What is the best dev workflow around nix-shell?

My setup is usually like this:

shell.nix:

{ nixpkgs ? import (fetchGit {
  url = https://github.com/NixOS/nixpkgs-channels;
  ref = "nixpkgs-unstable";
}) {} }:
with nixpkgs;
mkShell {
  buildInputs = [ ... ];
  SOME_ENV_VAR = "foo";
  shellHook = ''
    # usually link in a nix-built vendor directory or other housekeeping
  '';
}

for the already mentioned direnv, my super sophisticated .envrc:

use nix
# optionally also some env vars, if they're supposed to be secret, otherwise they go into `shell.nix`.

My editor of choice is spacemacs, and I’m using emacs-direnv to automatically load my nix-shell for each buffer so all dependencies are found.

For caching the nix-shell I’m using the persistent cached shell variant of use nix, but that’s pretty optional, just speeds things up a lot.

Depending on who I’m working with, I might try to keep all other nix things in a nix/ directory in the project, but I think having a shell.nix and default.nix at top-level is just good practice and easier to work with. So in the subdir go things like a common pinned nixpkgs version, dockertools, overlays, gemset.nix, etc…

To be honest I’m still experimenting with what I find the most comfortable project layout to work with, but after a few years this has been pretty much the standard I build on.

6 Likes