I work on a lot of projects, on many computers. Trying to keep all the software I need on all of them (and on a consistent version) has proved to be a challenging task. Sure virtualenvs or docker containers solve this partially, when you expect some cli tool to be there and it's not, that can really break your flow.
Devenv
Meet devenv.
Fast, Declarative, Reproducible, and Composable Developer Environments using Nix
Not only does this solve my problem, it also feeds my recent obsession with Nix :D
Devenv can be set up a couple of ways, but I immediately jumped into flakes as I've been writing a lot of flakes for my NixOS configuration.
Here is the flake.nix
boilerplate to use devenv. Simply copy this into the root of your project and start adding configuration:
Configuration
So what can you configure then?
Languages
Enabling the python interpreter and installing poetry for dependency management.
Packages
Installing packages from nixpkgs, like ffmpeg and python linting/formatting tools.
Scripts / Aliases
You can even write custom shell scripts to be added to the environment. This is useful to avoid typing out long commands you use often (poetry...).
This way I can easily run main.py foo
by just typing run foo
.
Pre-commit hooks
Take away the pain of managing pre-commit hooks and let nix do it for you. This option has one pretty big flaw though: It overwrites your manually written .pre-commit-config.yml
with a symlink to the nix store. This means you will not be able to use hooks written by your non-enlightened (not using nix) coworkers, nor share this one with them. The files will be in conflict. You have been warned.
For personal projects it's nice though.
Here I am adding isort
, black
and ruff
as pre-commit hooks for my project, and adding extra args for ruff to ignore E501
(line too long) errors.
Note that these tools do not have to be installed separately as packages to use them in pre-commit hook. I am just doing it so I can run them manually.
Bringing it together
Here is my current flake.nix
for Miso Bot
Usage
Now that we have this environment configured in flake.nix
, how do we use it?
Simply run:
The building of the nix packages will take some time but eventually you will be dropped in a bash shell containing the environment you specified. If you're a zsh (or some other shell) user like me, you might be wondering; Do I really have to use bash now? Don't worry. There is a fix for that:
Now you have the same shell but it's using zsh and keeps all your zsh config/aliases. Speaking of aliases, I have made this alias to greatly simplify the change into a devshell:
Allowing me to simply write "dev" once I'm in my project folder.
It is possible to use
direnv
and.envrc
to change into the devshell automatically, but I tried that and did not like it. I don't always need the devshell if I'm simply browsing files and it's easy enough to do manually.
Caching
If you are using nix garbage collection, then the devshell derivations are deleted by the nix garbage collector. This can be annoying, as you will have to rebuild your environment all the time. To remedy this, add this to your nix configuration: