about summary refs log tree commit diff
path: root/users/wpcarro/website/blog/posts/nix-shell-note.md
blob: da33c846ceaa3d66ae9df09a8f4e0c1eca52de2e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
## Background

I rarely use `nix-shell` for its originally intended purpose of "reproducing the
environment of a derivation for development". Instead, I often use it to put
some executable on my `PATH` for some ad hoc task.

What's `nix-shell`'s "intended purpose"? Let's ask The Man (`man nix-shell`):

> The command nix-shell will build the dependencies of the specified derivation,
> but not the derivation itself. It will then start an interactive shell in
> which all environment variables defined by the derivation path have been set
> to their corresponding values, and the script $stdenv/setup has been
> sourced. This is useful for reproducing the environment of a derivation for
> development.

Because I'm abusing `nix-shell` in this way, I'm liable to forget that
`nix-shell` puts `buildInputs` on `PATH` and *not* the derivation itself. But I
often only want the derivation!

## Solution

Pass the Nix expression to `nix-shell -p`:

```shell
λ nix-shell -p '(import /depot {}).tvix.eval'
```

## Explanation

This works because Nix forwards the arguments passed to `-p` (i.e. `--packages`)
and interpolates them into this expression here: [source][nix-src]

```nix
{ ... }@args:

with import <nixpkgs> args;

(pkgs.runCommandCC or pkgs.runCommand) "shell" {
  buildInputs = [
    # --packages go here
  ];
}
```

So really you can pass-in *any* valid Nix expression that produces a derivation
and `nix-shell` will put its outputs on your `PATH`.

Enjoy!

[nix-src]: https://sourcegraph.com/github.com/NixOS/nix@3ae9467d57188f9db41f85b0e5c41c0c9d141955/-/blob/src/nix-build/nix-build.cc?L266