nix-shell
doesn’t build the package itself. I haven’t looked into the details but AIUI it doesn’t run the phases for the derivation, though I think it makes them available as shell functions. mkShell
disables building by defining a single phase that always aborts. nix run
does build the derivation and makes it available to the shell. It’s like nix-shell -p
, which I would assume would abort on a mkShell
the same way nix run
does.
tl;dr nix run
is a “new interface”, part of nix 2.0. This new interface has no implementation for the feature from nix-shell that you are looking for.
nix run pkg1 pkg2
supersedes nix-shell -p pkg1 pkg2
, but nix-shell -A pkg
has no equivalent. The magic of nix-shell -A pkg
is that it goes trough all the dependencies of pkg
and starts a shell with these packages in the environment.
To reproduce that, you need to be able to extract all the dependencies of a package, which is done in nix-shell (around here and here) but has no equivalent in nix run
(here) because it has no extraction logic.
If you want to emulate nix-shell
with nix run
, you may consider using nix run $(nix-build $(nix-store -q --references $(nix-instantiate) | grep ".drv$" | grep -v bash))
which still uses the old interface to obtain the .drv (nix-instantiate
), to extract the dependencies (nix-store -q --references
) and to build these .drvs (nix-build
). The new nix build
interface does not print the outputs, and therefore cannot be used here. the others have no equivalent.
nix 2.0 interface is still a work in progress, you should stick with nix-shell to get a shell from a derivation seen as an “environment” for that shell.
Thanks for that explanation!
Is there the intention to implement something like nix shell
in nix 2.x or is the plan to keep nix-shell around?
That would be a question for @edolstra, but here is what seems likely to happen from my point of view, which may be very wrong.
nix-shell contains a lot of ad-hoc hacks to setup the environment, and this stuff does not really pertain to nix per se. So I guess there is little chance to see nix-shell ported as-is. More probably, the functionnality will see a large reactoring to move most of the custom hacks into nixpkgs and cleaner, well-defined interfaces.
This is a lot of work, and no-one seems too eager to start working on it as nix-shell
is still fully supported, maintained, and working as intended.
More than 10 months passed since the last reply here - are there any news regarding nix-shell in the new interface? Maybe there is some ticket on the topic?
Going to quote @lilyball’s reply verbatim from another thread because it is highly relevant:
BTW the “better option” here is
nix run
.nix-shell -p foo
sets up the environment as it would for buildingfoo
, so all offoo
's dependencies are in yourPATH
and all of the other environment vars are set too (I count 23 env vars containingNIX
), butnix run
produces an environment much more similar to what you’d get if you simply installed the package (e.g. it basically just prefixes yourPATH
with the appropriate directories from the specified package).That said,
nix-shell
replaces your normal shell initialization files andnix run
doesn’t, so depending on how your.bashrc
is set up you might override thePATH
. For example with my setup,echo $PATH
in anix run
shell starts the path with/usr/local/bin
before the nix-provided path value, because my current.bashrc
unconditionally prefixes my PATH (which I really should fix).
If I have a shell.nix
file, I can simply run
❯ nix-shell
these paths will be fetched (0.05 MiB download, 0.28 MiB unpacked):
/nix/store/qgbwdnk91rk26b5bkd6qv5r6c2v733kb-bash-interactive-4.4-p23-dev
copying path '/nix/store/qgbwdnk91rk26b5bkd6qv5r6c2v733kb-bash-interactive-4.4-p23-dev' from 'https://cache.nixos.org'...
[nix-shell:~/dev/research/julia/odecontrol]$
Can I do something similar with nix run
? I haven’t been able to make it work:
❯ nix run
error: opening file '/home/skainswo/dev/research/julia/odecontrol/default.nix': No such file or directory
nix
2.3 or 2.4pre?
For 2.3, no, run
does not read from a shell.nix
, as the content of a shell.nix
is not meant to be built. run
though builds and then gives the build result in the environment. nix-shell
and nix shell
(2.3) though do not build the mentioned derivations, but instead their buildinputs and give those into the environment.
2.4s run
works completely different from both, and require a flake with applications.
nix develop
is more similar to that usage, you can also use nix shell
, but nix shell
is more similar to nix-shell -p
What is the difference between nix shell
and nix develop
? From nix --help
for 2.4pre
:
nix develop - run a bash shell that provides the build environment of a derivation
nix shell - run a shell in which the specified packages are available
but I still can’t mentally differentiate between the two, unlike nix run
, which clearly has a different purpose now - to run nix apps.
nix develop
takes a single derivation, and gives you a shell to make it (all dependencies needed to build it will be exposed in the shell).
nix shell
, essentially adds packages to the current shell. (Technically forks the shell, and in the child shell will add the packages)
Example:
nix develop nixpkgs#ripgrep
→ You will have rust, pkg-config, and a few other packages added to your shell, but not ripgrep
nix shell nixpkgs#ripgrep
→ You will have access to ripgrep, and nothing else will be added.
not really the current shell.
I think a better definition would be:
nix shell
will start a new shell where all the packages you give it are available to use.
So nix develop
is analogous to nix-build
while nix shell
is analogous to nix-shell
.
But then there is also nix build
.
Maybe it’s futile to draw similarities between the old and the new commands, just take them for what they are.
@jayesh.bhoot I think a better breakdown would look like this:
use | old command | new command |
---|---|---|
start a new shell that has ripgrep available |
nix-shell -p ripgrep |
nix shell nixpkgs#ripgrep |
start a new shell that has the dependencies required for building ripgrep available (like gcc and rustc ) |
nix-shell -A ripgrep |
nix develop nixpkgs#ripgrep |
build ripgrep completely within Nix. Put the resulting binary in a result/ symlink |
nix-build -A ripgrep |
nix build nixpkgs#ripgrep |
run an application defined in a flake | nothing similar? | nix run nixpkgs#ripgrep |
A couple things to keep in mind:
-
nix build
,nix develop
, andnix run
have special support for flakes. For instance, if there is aflake.nix
in the current directory, then:-
nix build
with no arguments will try to build theoutputs.defaultPackage
. -
nix develop
with no arguments will load the shell defined inoutputs.devShell
. -
nix run
with no arugments will run the command defined inoutputs.defaultApp
.
-
-
You might be able to make the argument that
nix run
is similar tonix-shell -p ripgrep --run 'ripgrep'
, but this is somewhat of a stretch. -
nix shell
may be renamed: Rename 'nix shell' · Issue #4715 · NixOS/nix · GitHub
Thank you. This, combined with Flakes - NixOS Wiki, give us a lot of clarity.
The most authoritative page on the nix
command seems to be Nix command - NixOS Wiki. You should consider putting your response there.
While the wiki does have a lot of good info, I’d recommend you make sure to read through all the man pages for nix
. By now I think these pages have a lot more info on the new-style Nix commands:
https://nixos.org/manual/nix/unstable/command-ref/experimental-commands.html
Previously it was nix-shell -p pkg --run "some command"
nix run
is for running applications defined in flakes. But flakes allow you to run arbitrary applications, not just binaries from a given derivation.
I think nix-shell -p pkg --run "some command"
is closer to nix shell nixpkgs#pkg --comand "some command"
.
Fair, I don’t think there was a way to just run a given binary in the old cli. Or it would be hideous like $(NIX_PATH=remote.domain.org/toplevel.tar.gz nix build -A pkg)/bin/<command> ...
, but at that point, you’re just scripting instead of using a cli.
This is the best response in the thread imho, however I am still left more confused than I was before from this discussion (I saw it in an email digest and was curious).
I think the problem is that a lot of the responses in the thread presume what you’re trying to do and provide responses in that context. Eg that it provides the “build environment” for the current package - what if the current package is mkShell and I’m just trying to set up an environment?
Do I use nix-shell, nix run, nix develop, or nix shell? I think it’s nix shell, but some of the responses in this thread make me think maybe I want nix develop. Right now I’m using nix-shell.
And without this comment I have no context for the man page comment that “ run a shell in which the specified packages are available”, specifically where the “specified packages” come from. (packages, buildInputs, nativeBuildInputs, etc).
I didn’t dig into the man page documentation deeply and probably never will, unless my life revolves around building things with nix. But if it’s just one tool that I’m using, I’m going to learn what I need to in order to accomplish the tasks that I have. I simply don’t have the time to read dozens of pages about functionality that I may never use.