I'm trying to write a shell.nix
to have a stable environment for doing web development in a project. I'd like to use this so that I don't have to write nix-shell -p nodejs_22 --command "yarn dev"
. However, I don't see a way to specify this in the shell.nix
file.
Here's what I came up with:
{ pkgs ? import <nixpkgs> {} }:
let lib = import <nixpkgs/lib>;
in pkgs.mkShell {
packages = with pkgs; [
nodejs_22 yarn
];
shellHook = ''
export PATH="${pkgs.nodejs_22.out}/bin:$PATH"
yarn dev
'';
}
The problem here is that shellHook
is not really meant to do this. It's meant for initialization purposes. When I CTRL+C (SIGINT) on the node process, it drops me into bash, inside the nix shell. However, I want it to just exit entirely and go back to the shell before nix-shell
was run.
How can I specify the --command
argument inside the shell.nix
file? It it's not possible, it's kind of pointless to me since I could just create a shell script with the full nix-shell command instead.
Using trap - SIGINT
, trap "exit 130" INT
and variations (including using job control) did not help.
As you've discovered, nix-shell
isn't really meant for this. If you really insist on this way of running your dev command, then you need an exec
to replace the bash process running your shellHook
with yarn itself:
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [
pkgs.nodejs_22
pkgs.yarn
];
shellHook = "exec yarn dev";
}
This way, a Ctrl+C should not drop you into the shell inside nix-shell
but directly exit.