I work on a python project, and I have a flake to get the right environment for it: The python version I use, uv, and some dependencies I need to link against. The python venv itself I then manage with uv.
Looking around I see people suggesting to use nix develop (or what used to be shell.nix), and especially if you look at direnv and similar tools, they seem to use that same functionality, often suggesting a setup with a pkgs.mkShell.
But the documentation of nix develop clearly says that it drops you into an environment that is ready to build the derivation you referenced. That is not the environment you referenced, but just “on the way” to build that one. In that sense yes, it’s a “development environment”, if you are working on developing a nix package.
But in my case, and many others I’m sure, they just want the right environment to be able to work on their project. Then nix develop seems to be the wrong thing. Am I missing something?
I’m unsure because it looks like “everybody” is using that. But nix develop comes with so much baggage that you probably don’t want, like all the shell functions it adds for you to play around with the build phases. Again, this makes sense if you work on a nix package, but not in the case I describe.
In my case, don’t we want to use nix build and add ./result/bin to the path?
If you want to hack on your non-nix code and use the tooling that you’re used to using outside of nix, use nix develop. If you want to build it with nix and get the resultant benefits, use nix build + result/bin/whatever, or use nix shell to make it available on PATH, or use nix run to run your program directly.
The options you give make sense to me. If you go the nix develop way, people use nativeBuildInputs to get an environment. Then maybe that’s on purpose? I felt like that was a way to get around using the wrong tool (develop instead of build). Because instead you could have just gotten that environment to begin with.
I don’t want to reinvent things myself and direnv seems fixed to use a devShell … in your opinion, this is the way to go?
Ultimately I think any of the above options are fine, it just entirely depends on your workflow. There’s some overlap in usage and it’s not clearly distinguished in documentation.
Normally I would stick to the nix develop-type workflow while hacking on the code, because I usually want some additional tooling that isn’t necessarily used to build the package (e.g. some tooling that I’d use to init the project, maybe a language-specific formatter) - and yes, I use direnv which essentially forces that workflow, but it works for me.
Once the non-nix code is in good shape and I want to add it to a config or something, then I would write a proper package expression for it and then expose that.
You can add the nix-packaged version of the current project itself to the mkShell environment, if you like that way of working. If you do that, it prevents dumping stuff in $HOME, as all the dependencies and build results will come from the nix store instead. With direnv it would even result in instant rebuilds if you change the code. Though I personally don’t usually work this way.
I had a bad experience doing this and would like to suggest that nix-shell with shell.nix might be the better option for some people.
The background is that, off the shelf, nix develop (or nix-direnv + flake.nix) will copy all of your project files to /nix/store every time you enter the environment (unless nothing has changed). I had many gigs of data files and this got out of hand pretty quickly.
I understand that if you initialize a git repository, untracked files won’t be included in this process. Maybe that’s a good fit for some projects.
Anyway it was a gotcha for me and nix-shell just worked as expected for the postulated scenario (i.e. “hack on your non-nix code and use the tooling that you’re used to using outside of nix”).
That is, nix-shell added stuff to the store just once based on what I wrote in shell.nix and it pays no attention to the files in my project. In contrast, the purity mechanisms of the flake approach don’t seem to help here and you need to work to inhibit them.
You can use nix develop without flakes. Anyway I was answering their question as-is, they didn’t ask about nix-shell and it’s not so much better that it was worth me bringing it up.