From Pexels cottonbro
Using direnv with Nix and Emacs
I wanted my Emacs to automatically pick up the Nix environment for each project, so I set up direnv to manage project-specific shells. I was finding it a pain cd into a project, running nix-shell and then starting emacs.
1. Install direnv
Let’s be completely honest here. I can’t quite remember whether sudo apt-get install direnv was important, or whether I installed it direnv using Nix. I think, after a lot of fighting, the important thing was that I have a binary (linked) file direnv in my .nix-profile/bin folder. So I don’t think I need the system (apt-get install) file.
nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs
nix-channel --update
nix-env -iA nixpkgs.direnv
Basically, I got in a lot of trouble doing this, got very confused and don’t fully understand what I was doing. I think one of my problems might have been that direnv wasn’t in my rix archive (because of course, I’m trying to use rix). I had to upgrade my nix installation before I got any of this to work as well; something I need to take more care of going forward. I do sudo apt-get update and sudo apt-get upgrade often enough but nixitself is outside that system. Because I was looking for nix-direnv (which doesn’t exist) it may be that I can get the package from rix. After some confusing investigations, I didn’t use nix-direnv; the official direnv package contains everything needed (in particular the binaries). I don’t know if I need a system-wide direnv which looks for a specific direnv.
I added the following to ~/.bashrc so that every time I cd into a folder, direnv automatically loads the environment:
Inside my project folder, I created a .envrc file:
use nix
Then I ran
direnv allow
Making it work in Emacs
I wanted Emacs to pick up the same Nix environment. Here’s how I set it up.
sing use-package in my .emacs:
(use-package direnv
:ensure t
:config
(direnv-mode)) ;; automatically enable direnv-mode
To make sure emacs can see the shell environment (I usually initialise from the Gui).
(use-package exec-path-from-shell
:ensure t
:config
(exec-path-from-shell-initialize))
Sometimes I needed to run
M-x direnv-update-environment
but I haven’t run that for a while.
Notes
.envrccan be several folders upstream; direnv still finds it automatically.- Once
direnv allowis run, both terminal shells and Emacs buffers inherit the environment. - I didn’t need a
~/.direnvrcfile. All the setup works with just the project.envrcand shell hook, that was a rabbit hole I mention now in case I left a few.direnvrcfiles lying around and wonder if they are important one day.
With this configuration, I now have a seamless workflow: I can open files anywhere in the project, and Emacs automatically uses the correct Nix environment.
Use the share button below if you liked it.
It makes me smile, when I see it.