A faster, persistent implementation of direnv's use_nix and use_flake, to
replace the built-in one.
Prominent features:
- significantly faster after the first run by caching the
nix-shellenvironment - prevents garbage collection of build dependencies by symlinking the resulting
shell derivation in the user's
gcroots(Life is too short to lose your project's build cache if you are on a flight with no internet connection)
Compared to lorri, nix-direnv is simpler (and requires no external daemon). Additionally, lorri can sometimes re-evaluate the entirety of nixpkgs on every change (leading to perpetual high CPU load).
Requirements:
- bash 4.4
- nix 2.4 or newer
- direnv 2.21.3 or newer
Warning
We assume that direnv is installed properly because nix-direnv IS NOT a replacement for regular direnv (only some of its functionality).
Note
nix-direnv requires a modern Bash. MacOS ships with bash 3.2 from 2007. As a
work-around we suggest that macOS users install direnv via Nix or Homebrew.
There are different ways to install nix-direnv, pick your favourite:
Via home-manager (Recommended)
Note that while the home-manager integration is recommended, some use cases require the use of features only present in some versions of nix-direnv. It is much harder to control the version of nix-direnv installed with this method. If you require such specific control, please use another method of installing nix-direnv.
In $HOME/.config/home-manager/home.nix add
{
# ...other config, other config...
programs = {
direnv = {
enable = true;
enableBashIntegration = true; # see note on other shells below
nix-direnv.enable = true;
};
bash.enable = true; # see note on other shells below
};
}Check the current
Home Manager Options
for integration with shells other than Bash. Be sure to also allow
home-manager to manage your shell with programs.<your_shell>.enable = true.
Direnv's source_url
Put the following lines in your .envrc:
if ! has nix_direnv_version || ! nix_direnv_version 3.1.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.1.0/direnvrc" "sha256-yMJ2OVMzrFaDPn7q8nCBZFRYpL/f0RcHzhmw/i6btJM="
fiVia system configuration on NixOS
For NixOS 23.05+ all that's required is
{
programs.direnv.enable = true;
}other available options are:
{ pkgs, ... }: {
#set to default values
programs.direnv = {
package = pkgs.direnv;
silent = false;
loadInNixShell = true;
direnvrcExtra = "";
nix-direnv = {
enable = true;
package = pkgs.nix-direnv;
};
}With `nix profile`
As non-root user do the following:
nix profile install nixpkgs#nix-direnvThen add nix-direnv to $HOME/.config/direnv/direnvrc:
source $HOME/.nix-profile/share/nix-direnv/direnvrcFrom source
Clone the repository to some directory and then source the direnvrc from this
repository in your own ~/.config/direnv/direnvrc:
# put this in ~/.config/direnv/direnvrc
source $HOME/nix-direnv/direnvrcEither add shell.nix or a default.nix to the project directory:
# save this as shell.nix
{ pkgs ? import <nixpkgs> {}}:
pkgs.mkShell {
packages = [ pkgs.hello ];
}Then add the line use nix to your envrc:
echo "use nix" >> .envrc
direnv allowIf you haven't used direnv before, make sure to hook it into your shell first.
You may use a different file name than shell.nix or default.nix by passing
the file name in .envrc, e.g.:
echo "use nix foo.nix" >> .envrcnix-direnv also comes with an alternative use_flake implementation. The code
is tested and does work but the upstream flake api is not finalized, so we
cannot guarantee stability after a nix upgrade.
Like use_nix, our use_flake will prevent garbage collection of downloaded
packages, including flake inputs.
This repository ships with a
flake template.
which provides a basic flake with devShell integration and a basic .envrc.
To make use of this template, you may issue the following command:
nix flake new -t github:nix-community/nix-direnv <desired output path>echo "use flake" >> .envrc && direnv allowThe use flake line also takes an additional arbitrary flake parameter, so you
can point at external flakes as follows:
use flake ~/myflakes#projectUnder the covers, use_flake calls nix print-dev-env. The first argument to
the use_flake function is the flake expression to use, and all other arguments
are proxied along to the call to print-dev-env. You may make use of this fact
for some more arcane invocations.
For instance, if you have a flake that needs to be called impurely under some
conditions, you may wish to pass --impure to the print-dev-env invocation so
that the environment of the calling shell is passed in.
You can do that as follows:
echo "use flake . --impure" > .envrc
direnv allowLike use flake, use nix now uses nix print-dev-env. Due to historical
reasons, the argument parsing emulates nix shell.
This leads to some limitations in what we can reasonably parse.
Currently, all single-word arguments and some well-known double arguments will be interpreted or passed along.
By default, nix-direnv will reload a previously working devShell if it discovers
that a new version does not evaluate. This can be disabled by calling
nix_direnv_disallow_fallback in .envrc, like so:
nix_direnv_disallow_fallback
use nix # or use flakeTo avoid delays and time consuming rebuilds at unexpected times, you can use nix-direnv in the "manual reload" mode. nix-direnv will then tell you when the nix environment is no longer up to date. You can then decide yourself when you want to reload the nix environment.
To activate manual mode, use nix_direnv_manual_reload in your .envrc like
this:
nix_direnv_manual_reload
use nix # or use flakeTo reload your nix environment, use the nix-direnv-reload command:
nix-direnv-reload-p: Starts a list of packages to install; consumes all remaining arguments--include/-I: Add the following path to the list of lookup locations for<...>file names--attr/-A: Specify the output attribute to utilize
--command, --run, --exclude, --pure, -i, and --keep are explicitly
ignored.
All single word arguments (-j4, --impure etc) are passed to the underlying
nix invocation.
As a convenience, nix-direnv adds common files to direnv's watched file list
automatically.
The list of additionally tracked files is as follows:
-
for
use nix:~/.direnvrc~/.config/direnv/direnvrc.envrc,- A single nix file. In order of preference:
- The file argument to
use nix default.nixif it existsshell.nixif it exists
- The file argument to
-
for
use flake:~/.direnvrc~/.config/direnv/direnvrc.envrcflake.nixflake.lockdevshell.tomlif it exists
Users are free to use direnv's builtin watch_file function to track additional
files. watch_file must be invoked before either use flake or use nix to
take effect.
nix-direnv sets the following environment variables for user consumption. All other environment variables are either a product of the underlying nix invocation or are purely incidental and should not be relied upon.
NIX_DIRENV_DID_FALLBACK: Set when the current revision of your nix shell or flake's devShell are invalid and nix-direnv has loaded the last known working shell.
nix-direnv also respects the following environment variables for configuration.
NIX_DIRENV_FALLBACK_NIX: Can be set to a fallback Nix binary location, to be used when a compatible one isn't available inPATH. Defaults toconfig.nix.packageif installed via the NixOS module, otherwise needs to be set manually. Leave unset or empty to fail immediately when a Nix implementation can't be found onPATH.
- Changing where direnv stores its cache
- Quickly setting up direnv in a new nix project
- Disable the diff notice (requires direnv 2.34+): Note that this goes into direnv's TOML configuration!
- direnv-instant - A non-blocking daemon that makes direnv truly instant by running it asynchronously in the background. When combined with nix-direnv's caching, it provides immediate shell access while environment loading happens in the background, with automatic notifications when the environment is ready.
For commercial support, please contact Mic92 at joerg@thalheim.io or reach out to Numtide.