Non-blocking direnv integration daemon with tmux support that provides instant shell prompts by running direnv asynchronously in the background.
  • Rust 79.5%
  • Nix 9.6%
  • Shell 9.1%
  • Nushell 1.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-21 22:22:27 -05:00
hooks mux: support Neovim-owned direnv sessions 2026-09-12 10:15:38 +10:00
scripts add script to record demo 2025-12-31 10:18:33 +00:00
src mux: distinguish load outcomes from RPC delivery 2026-09-12 10:31:16 +10:00
tests tests: keep tmux server alive 2026-09-21 13:35:03 -05:00
.envrc add pytest-xdist to the devshell 2025-10-09 10:39:01 +01:00
.gitignore chore: ignore .direnv 2025-10-12 17:26:27 +02:00
Cargo.lock mux: size herdr split like other multiplexers 2026-07-24 08:27:32 +02:00
Cargo.toml mux: size herdr split like other multiplexers 2026-07-24 08:27:32 +02:00
CONTRIBUTING.md docs: point users to Forgejo [skip ci] 2026-09-21 20:35:00 -05:00
default.nix chore: license under GPL-3.0 2026-09-21 19:31:43 -05:00
flake.lock Merge 04dba8e434 into gitea-mq/batch/507548 2026-09-10 07:08:18 +00:00
flake.nix flake: bump nixpkgs and drop x86_64-darwin 2026-07-12 12:11:16 +02:00
home.nix home: remove fish readOnly workaround 2026-07-12 13:23:20 +02:00
LICENSE chore: license under GPL-3.0 2026-09-21 19:31:43 -05:00
nixos.nix Make kitty launch args configurable 2026-04-28 14:36:37 +08:00
pyproject.toml add pytest-xdist to the devshell 2025-10-09 10:39:01 +01:00
README.md docs: host previews on Forgejo [skip ci] 2026-09-21 22:22:27 -05:00
treefmt.nix add ruff checks 2025-10-09 10:39:01 +01:00

direnv-instant

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 = "git+https://forge.barrettruth.com/barrettruth/direnv-instant.git";
}

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 git+https://forge.barrettruth.com/barrettruth/direnv-instant.git -- in the lines above.

From source

cargo build --release

Configuration

Module options under programs.direnv-instant:

Option Type Default Description
enable bool false Enable direnv-instant
package package built-in Package to use
enableBashIntegration bool true Install bash hook
enableZshIntegration bool true Install zsh hook
enableFishIntegration bool true Install fish hook
settings.use_cache bool true Apply cached env instantly on prompt
settings.mux_delay int 4 Seconds before opening a multiplexer pane
settings.kitty_launch_args listOf str ["--location" "vsplit" "--keep-focus" "--self"] Args passed to kitty launch
settings.debug_log string null Path to daemon debug log

Home Manager only:

Option Type Default Description
enableNushellIntegration bool true Install nushell hook
enableKittyIntegration bool config.programs.kitty.enable Configure 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

GPL-3.0