Nix-shell -p, but without opening new shell?

I find that I’m regularly caught in this pattern:

$ foo --with some arguments maybe
foo: command not found 
$ nix-shell -p foo
$ ↑
$ <some other command shows up>

I.e. I want to get foo available, but preferably without opening a new shell.

I know it’s possible to load the effect of nix-shell into an existing shell, because direnv can do it. But what is the easiest way? Is there a shell alias worth adding to my environment (or, preferably, to the default environment on a nix system) that amends the current shell with what’s necessary to make a nixpkgs package available?

If you’re using flakes you could probably do nix run nixpkgs#foo -- --with some args. That doesn’t amend the current shell though, but nix execs into foo, but perhaps that’s sufficient for your use-case.

I have this in my shell config:

nix-load() {
        local s=""
        for attr in "$@"; do
                s="$s nixpkgs#$attr"
        done
        paths="$(nix build --no-link --print-out-paths $s)"
        for p in $paths; do
                export PATH="$p/bin:$PATH"
        done
}

Example: nix-load ffmpeg adds ffmpeg to the current shell’s PATH.

Note that this is equivalent to nix shell, not nix-shell. This means it only adds things to PATH. It doesn’t run stdenv setup hooks like nix-shell -p does.

2 Likes

You can run eval $(nix print-dev-env), but it still overrides a bunch of shell things.

Thanks for all the suggestions. They seem to all aim at running a command, or adding it to the PATH, but sometimes nix-shell -p extend the environment in other ways, too.

I am thinking of what direnv’s use nix does - just ad-hoc, with the packages (or expressions, like ghc.withPackages) listed on the command line.

I guess I want

~ $ . <(direnv apply_dump <(nix-shell -p hello --run 'direnv dump'))
~ $ hello
Hallo, Welt!
1 Like