direnv-instant

July 24, 2026 · View on GitHub

Non-blocking direnv shell integration. Runs direnv in a background daemon so your prompt comes back immediately instead of waiting for .envrc to finish.

Demo

What it does

The shell hook starts a daemon and returns right away. The daemon runs direnv, writes the resulting environment to a file, and signals the shell with SIGUSR1 when it's done. The shell trap then loads the new environment. On revisit, a cached environment from the previous run is applied instantly while the daemon revalidates in the background.

If direnv takes longer than 4 seconds (configurable), a tmux/zellij/wezterm/kitty/herdr split opens showing direnv's output so you can see what it's doing — and ctrl-c it if needed.

Supported shells: bash, zsh, fish, nushell. Supported multiplexers: tmux, zellij, wezterm, kitty (kitty needs the home-manager module), herdr.

If you use Nix, pair this with nix-direnv. It caches Nix environments and creates gcroots, which keeps direnv-instant's cached environment from being garbage collected out from under you.

Installation

direnv-instant replaces direnv's normal shell integration — don't use both. Remove any eval "$(direnv hook ...)" lines from your shell config first.

Home Manager

{
  inputs.direnv-instant.url = "github:Mic92/direnv-instant";
}

Pass inputs through extraSpecialArgs, then:

{ inputs, ... }:
{
  imports = [ inputs.direnv-instant.homeModules.direnv-instant ];
  programs.direnv-instant.enable = true;
}

NixOS

Same flake input. Pass inputs through specialArgs, then:

{ inputs, ... }:
{
  imports = [ inputs.direnv-instant.nixosModules.direnv-instant ];
  programs.direnv-instant.enable = true;
}

Manual shell setup

bash (~/.bashrc):

eval "$(direnv-instant hook bash)"

zsh (~/.zshrc):

eval "$(direnv-instant hook zsh)"

fish (~/.config/fish/config.fish):

direnv-instant hook fish | source

fish note: the nix direnv package ships share/fish/vendor_conf.d/direnv.fish, which fish auto-loads even though no hook line appears in your config. The direnv-instant hook unregisters those handlers, so the config.fish line above is enough.

nushell: there's no hook nu | source one-liner because nushell's source is parse-time only. The hook ships at share/direnv-instant/nushell.nu; the home-manager module sources it for you when programs.direnv-instant.enableNushellIntegration is enabled. Nushell also can't trap SIGUSR1, so the hook polls the env file on each prompt — new env shows up on the next prompt after direnv finishes.

For a quick test without installing, swap direnv-instant for nix run github:Mic92/direnv-instant -- in the lines above.

From source

cargo build --release

Configuration

Module options under programs.direnv-instant:

OptionTypeDefaultDescription
enableboolfalseEnable direnv-instant
packagepackagebuilt-inPackage to use
enableBashIntegrationbooltrueInstall bash hook
enableZshIntegrationbooltrueInstall zsh hook
enableFishIntegrationbooltrueInstall fish hook
settings.use_cachebooltrueApply cached env instantly on prompt
settings.mux_delayint4Seconds before opening a multiplexer pane
settings.kitty_launch_argslistOf str["--location" "vsplit" "--keep-focus" "--self"]Args passed to kitty launch
settings.debug_logstringnullPath to daemon debug log

Home Manager only:

OptionTypeDefaultDescription
enableNushellIntegrationbooltrueInstall nushell hook
enableKittyIntegrationboolconfig.programs.kitty.enableConfigure kitty remote control

Outside the modules, the same settings are read from environment variables: DIRENV_INSTANT_USE_CACHE, DIRENV_INSTANT_MUX_DELAY, DIRENV_INSTANT_KITTY_LAUNCH_ARGS (newline-separated), DIRENV_INSTANT_DEBUG_LOG.

How is this different from lorri?

Both run nix evaluation in the background. direnv-instant shows you what's happening: after a few seconds it opens a multiplexer pane with direnv's output instead of making you tail journal logs, and you can ctrl-c a stuck rebuild. It also works with any direnv .envrc, not just Nix shells.

License

MIT