By “shell producing Nix commands”, I mean these commands
nix-shell
nix shell
nix develop
- (Are there other ways?)
I also understand that shell.nix
itself is not documented as it is just a convention when the provided Nix expression is saved in a file (e.g., to be used with nix-shell
).
What I’m alluding to are conventions such as
- When are
shellHook
instructions run: afterbuildInputs
are in scope or before? - To do shell string interpolation in the shell in
shellHook
, one has to use two single quotes to escape it because the Nix language uses the same convention. - defining shell / environment variables; for example, variables defined in
mkShell
’sshellHook
(withoutexport
) become shell variables, and variables defined outside it become environment variables (i.e., they get exported implicitly) in the resulting shell.
Example:
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
shellHook = ''
SHELL_VARIABLE=27
'';
ENVIRONMENT_VARIABLE="the cake is a lie"
}
will produce
$ nix-shell -E "{pkgs ? import <nixpkgs> {} }: pkgs.mkShell { shellHook = ''SHELL_VARIABLE=27''; ENVIRONMENT_VARIABLE=\"the cake is a lie\"; }"
[nix-shell:~]$ echo -e "SHELL_VARIABLE: "$SHELL_VARIABLE"\nENVIRONMENT_VARIABLE: "$ENVIRONMENT_VARIABLE
SHELL_VARIABLE: 27
ENVIRONMENT_VARIABLE: the cake is a lie
[nix-shell:~]$ bash
new-shell$ echo -e "SHELL_VARIABLE: "$SHELL_VARIABLE"\nENVIRONMENT_VARIABLE: "$ENVIRONMENT_VARIABLE
SHELL_VARIABLE:
ENVIRONMENT_VARIABLE: the cake is a lie
The above example is not a secret, one can figure it out from examples in the Nixpkgs manual, on nix.dev, in the NixOS wiki, etc., but this is never spelled out explicitly, so I wonder what other such Nix expression behaviours / features are there that I’m probably missing.
I also just realized while trying to find answers in the official docs that even individual packages can define their own Nix shell conventions. Case in point: Python’s postShellHook
, preShellHook
, venvHook
.