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 nix
itself 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
.envrc
can be several folders upstream; direnv still finds it automatically.- Once
direnv allow
is run, both terminal shells and Emacs buffers inherit the environment. - I didn’t need a
~/.direnvrc
file. All the setup works with just the project.envrc
and shell hook, that was a rabbit hole I mention now in case I left a few.direnvrc
files 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.