Non-interactive nix-shell - Stack Overflow

admin2025-04-18  4

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.

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.

Share Improve this question asked Jan 29 at 10:38 Simao Gomes VianaSimao Gomes Viana 6747 silver badges16 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 1

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.

The solution is to add exit 0 at the end of your shellHook, but I went ahead and made some other improvements as well:

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
  buildInputs = [
    pkgs.nodejs_22 pkgs.yarn
  ];

  shellHook = ''
    set -e
    yarn dev
    exit 0
  '';
}

Disclaimer: I'm not familiar with Node.js and Yarn, and there might be a better way to set up a Node.js environment in Nix.

转载请注明原文地址:http://www.anycun.com/QandA/1744972058a90229.html