Nix shell IDE integration
Most projects involve some CLI tools which can be useful to integrate into the
IDE. For example, when using an interpreted language like Python, telling the
IDE where to find the python
executable means it should be able to find and
auto-complete language-specific
dependencies, detect
any syntax errors based on the exact interpreter version, and run the tests without
any extra setup. There’s just one snag: some IDEs require you to specify an absolute
path to the interpreter, and Nix store paths are hashed:
$ nix-shell --pure --run 'type -a python'
python is /nix/store/y027d3bvlaizbri04c1bzh28hqd6lj01-python3-3.11.7/bin/python
Now, we could absolutely point the IDE to this path, but that’s brittle: if anything changes in the Python derivation, this path will change, and the IDE will no longer be pointing at the right path. We might not even notice until the path is garbage collected from the Nix store.
Here’s the thing, though: Bash knows about python
because $PATH
contains
the Nix store path
(/nix/store/y027d3bvlaizbri04c1bzh28hqd6lj01-python3-3.11.7/bin
in the example
above), and we can use that knowledge to work around IDE deficiencies. If we use
the shell to create (or overwrite) a symbolic link to the python
executable
every time we activate the Nix shell, that link will always point to the
relevant file. We can do this in the shellHook
:
let
pkgs = import (builtins.fetchTarball {
name = "nixos-unstable-2024-06-05";
url = "https://github.com/nixos/nixpkgs/archive/57610d2f8f0937f39dbd72251e9614b1561942d8.tar.gz";
sha256 = "0k8az8vmfdk1n8xlza252sqk0hm1hfc7g67adin6jxqaab2s34n9";
}) { };
python = pkgs.python3.withPackages (pythonPackages: [ pythonPackages.pytest ]);
in
pkgs.mkShell {
packages = [
pkgs.bashInteractive
python
];
shellHook = ''
ln --force --no-target-directory --symbolic "${python}/bin/python" python
'';
}
Now, any time we re-enter this shell, it updates the python
symlink1, and we have a fixed absolute path to the “current”
Python interpreter! Just point to that file in your IDE, and it should detect
the rest. You probably also want to add /python
to your .gitignore
to make
sure it doesn’t get added to version control.
For reference, an example repository which uses this technique.
-
The symlink ends up in the directory where you run
nix-shell
. Since this is normally the root of the project, that’s what I assume in this article. ↩
No webmentions were found.