Integrating direnv

The last thing we'll add to improve our newly created development environment is integration with direnv. This utility provides a critical feature in improving the experience with Nix development shells. In short, direnv will automatically evaluate (once explicitly allowed on a per-file basis) any .envrc files found at the root of a directory (and by nature, all parent directories).

What these .envrc files do is dependent on their contents. They can be as basic or advanced as desired. In the case of Nix, one can use nix-direnv to automatically enter into a Nix development shell. This is so incredibly common across the Nix ecosystem that you'll almost always see .envrc files in Nix-infused repositories.

The std framework provides some additional magic on top of the standard direnv experience which will not only allow us to select which of our defined development shells we want to enter automatically but also apply file watchers to our definitions to automatically reload our environment when the files change. To accomplish this, we'll add the following to a .envrc file at the root of our repository:

#! /bin/sh
# This file is sourced by direnv when entering the directory. The content below
# is pulled from: https://divnix.github.io/std/guides/envrc.html

source "$(
    nix eval \
        --no-update-lock-file \
        --no-write-lock-file \
        --no-warn-dirty \
        --accept-flake-config \
        .#__std.direnv_lib 2>/dev/null
)"

# Here we can select which development environment is used by `direnv`. We only
# have one in this case, and we called it default.
# See: /nix/std-example/devshells.nix).
use std nix //example/devshells:default

With this, and direnv installed/configured, we can cd into our repository root and be automatically dropped into our newly minted development shell:

$ direnv allow
direnv: loading ~/code/nix/std-book-example/.envrc
direnv: using std nix //example/devshells:default
direnv: Watching: nix/example/devshells.nix

🔨 Welcome to example devshell 🔨

To autocomplete 'std' in bash, zsh, oil: source <(std _carapace)
More shells: https://rsteube.github.io/carapace/carapace/gen/hiddenSubcommand.html


[Testing]

  tests - run the unit tests

[general commands]

  menu  - prints this menu
  std   - A tui for projects that conform to Standard

direnv: export +DEVSHELL_DIR +NIXPKGS_PATH +PRJ_DATA_DIR +PRJ_ROOT ~PATH ~XDG_DATA_DIRS

As expected, std is available and we can even see our example tests command in the menu. Let's give it a try:

$ tests
Finished test [unoptimized + debuginfo] target(s) in 0.04s
     Running unittests src/main.rs (target/debug/deps/example-965805a32576c369)

running 1 test
test test_say_hello ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s