# Where is \`shell.nix\` documented? (or idiosyncrasies of Nix expressions used with shell-producing Nix commands)

**URL:** https://discourse.nixos.org/t/where-is-shell-nix-documented-or-idiosyncrasies-of-nix-expressions-used-with-shell-producing-nix-commands/22518
**Category:** Documentation
**Created:** [October 16, 2022, 1:14pm UTC](https://discourse.nixos.org/t/where-is-shell-nix-documented-or-idiosyncrasies-of-nix-expressions-used-with-shell-producing-nix-commands/22518 "2022-10-16T13:14:24Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![toraritte](https://discourse.nixos.org/user_avatar/discourse.nixos.org/toraritte/32/6777_2.png) [@toraritte](https://discourse.nixos.org/u/toraritte)
#### Post date: [October 16, 2022, 1:14pm UTC](https://discourse.nixos.org/t/where-is-shell-nix-documented-or-idiosyncrasies-of-nix-expressions-used-with-shell-producing-nix-commands/22518/1 "2022-10-16T13:14:24Z")

</div>

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`](https://nixos.org/manual/nix/stable/command-ref/nix-shell.html?search=shell.nix#:~:text=a%20derivation%20for%20development.-,If%20path%20is%20not%20given%2C%20nix%2Dshell%20defaults%20to%20shell.nix%20if%20it%20exists%2C%20and%20default.nix%20otherwise.,-If%20path%20starts%20with)).

What I’m alluding to are conventions such as

- When are `shellHook` instructions run: after `buildInputs` 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](https://releases.nixos.org/nix-dev/2015-December/019018.html) because the Nix language uses the same convention.
- defining shell / environment variables; for example, variables defined in `mkShell`’s `shellHook` (without `export`) become shell variables, and variables defined outside it become environment variables (i.e., they get exported implicitly) in the resulting shell.

> **Example:**
>
> ```nix
> { pkgs ? import <nixpkgs> {} }:
> 
> pkgs.mkShell {
> 
> shellHook = ''
> SHELL_VARIABLE=27
> '';
> 
> ENVIRONMENT_VARIABLE="the cake is a lie"
> }
> 
> ```
> 
> will produce
> 
> ```plaintext
> $ 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](https://nixos.org/manual/nixpkgs/stable/), on [nix.dev](https://nix.dev/tutorials/declarative-and-reproducible-developer-environments), in the [NixOS wiki](https://nixos.wiki/wiki/Development_environment_with_nix-shell), 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](https://nixos.org/manual/nixpkgs/stable/#python)’s `postShellHook`, `preShellHook`, `venvHook`.
