nobe4 / Posts / Poor Man's devenv: Now with Caching _

 |  264 words  |  Nix Tech

In Poor Man’s devenv, I wrote a small bash script called use. It finds project files, maps them to Nix packages, and opens a shell with:

exec nix-shell -p "${packages[@]}"

It worked, but every shell still paid the nix-shell setup cost. It was just slow enough for me to change it.

The new version caches the built environment.

One cache per package set ยถ

use sorts and deduplicates the package names, then hashes the result:

hash_input="$(printf '%s\n' "${shell_packages[@]}" | LC_ALL=C sort -u)"
package_key="$(printf '%s\n' "$hash_input" | md5sum)"

Order does not matter. use go jq and use jq go share the same cache.

The hash is only used as a file name. It is not used for security, so MD5 is enough.

Build once, reuse later ยถ

nix print-dev-env evaluates the mkShell expression and prints a bash script that recreates its build environment. Unlike nix develop, it does not start a shell. This makes its output easy to save and source later:

nix print-dev-env \
    --impure \
    --expr "with import <nixpkgs> {}; mkShell { packages = [ ${shell_packages[*]} ]; }" \
    --profile "$HOME/.local/state/use/${package_key}.profile" \
    > "$HOME/.local/state/use/${package_key}.bash"

Later runs source the saved environment and start the user’s shell:

. "$HOME/.local/state/use/${package_key}.bash"
exec "$SHELL" -i

Conclusion ยถ

This keeps use small and efficient:

See the full diff.