Y|sndr - One too many shell


Excellent and timely post, that’s exactly what I’ve been researching lately! One thing I still wish I understand is how nix develop and direnv actually work under the hood. Here are some specific questions I have:

  • What is “environment where the package is built” in the first place? I think it needs special PATH, and also something for pgk-config to work. What about dynamic libraries, do I need a special LD_PRELOAD? What other extra bits comprise the actual environment?

  • How exactly shellHooks run? What the do, how they typically look like?

  • The specific problem I have is that I need an ad-hoc dev environment for a non-nix project I am working on. And I want to create that dev environment in my shell (fish with my configs), rather than spawning a devShell. I managed to do that using devShell and .envrc by copy-pasting stuff from then internet, but I don’t understand how that works under the hood. That is, I can’t recreate the environment I want manually.

  • And a semi-related question – for that dev environment case, I do want to use flakes because I do want the env to be pinned down with lock. However, I don’t want to commit flake.nix / flake.lock to the repository, as the project is not nix-based, and the fact that I use nix to get system packages is my private business. So, I want to add flakes to .git/info/exclude. And that goes again flake’s expectation that everything is in a git repo. Any practical tips here?

It is basically an environment that has all inputs of the derivation and the hooks have been run.

IIRC nix develop does run them, though not direnv, though the latter exposes it as vars, such that you could do eval "${shellHook}" in your .envrc.

They set up the environment as necessary, be it providing additional environment variables that need to be created programmatically or be it creating some folders or sideeffecty stuff.

Some even start programs like databases or docker containers, though I’m not a friend of that.

Use path:$(pwd) then. You won’t get eval cache this way, and nix will behave as if you were doing a git add . before every nix command.

I was in a similar situation. I made a second git repository with the flake.nix, flake.lock, and .envrc in it, and added the repo with the actual source as a git submodule. Because it was a subdirectory in the repository containing the .envrc, direnv still kicked in when I cd’d to the submodule.