Advice for when to use nix run versus nix-shell?

I mostly use nix-shell to load temporary environments with packages I need for development. I also noticed nix run does similar things and the documentation reads similarly. That reminded me of Eelco’s NixOS 2017 Conference talk on Nix 1.12 where he described CLI interface improvements including nix run.
All this leads to my actual question(s):

  1. are they the same command? or intended to become the same one?
  2. if different, when do you use one over the other?
1 Like

nix run is a replacement for nix-shell -p, not for nix-shell in general.

nix run is a little easier to use for doing one-shot commands due to how it takes the command and arguments (as separate args to itself, whereas nix-shell -p requires you to cram them into a single argument). For example, with nix run:

> nix run nixpkgs.hello -c hello --greeting 'Hi everybody!'
Hi everybody!


> nix-shell -p hello --run "hello --greeting 'Hi everybody!'"
Hi everybody!

Though there are some more practical differences, like nix-shell -p evaluates the command with a shell whereas nix run apparently doesn’t (nix run nixpkgs.hello -c echo \$PATH just echoes $PATH whereas nix-shell -p hello --run 'echo $PATH' will print the environment variable). Also the two commands set up $PATH differently for some reason, e.g.

> nix run nixpkgs.hello -c env | grep '^PATH'
PATH=/nix/store/sshmh79fir83xlzq9pi7qydgmzm69xxb-hello-2.10/bin:<inherited path>
> nix-shell -p hello --run env | grep '^PATH'
PATH=/nix/store/9sjgkbxaq8sibpavaalkmm5scbgl60na-bash-interactive-4.4-p23/bin:/nix/store/qvagarl5ghs07v39zhszm5x9rn08k231-clang-wrapper-7.1.0/bin:/nix/store/i2nf6hslid0ak8fzgpj2m082sprihi92-clang-7.1.0/bin:/nix/store/6964byz5cbs03s8zckqn72i6zq12ipqv-coreutils-8.31/bin:/nix/store/nxw7kw4px494nxw0cz5f1zfw3rvm645s-cctools-binutils-darwin-wrapper/bin:/nix/store/2pj2hdfy8jqy41hbh5h6z7sqhmcpi7xy-cctools-binutils-darwin/bin:/nix/store/6964byz5cbs03s8zckqn72i6zq12ipqv-coreutils-8.31/bin:/nix/store/sshmh79fir83xlzq9pi7qydgmzm69xxb-hello-2.10/bin:/nix/store/6964byz5cbs03s8zckqn72i6zq12ipqv-coreutils-8.31/bin:/nix/store/zvb6vxqx5f3y89mgg4can85g5fwn8xjn-findutils-4.6.0/bin:/nix/store/fa4psi2mhr14kil59vbs5vx7b791x55x-diffutils-3.7/bin:/nix/store/1qkqjb02khxr13q8hhwicznz5zsvjvzv-gnused-4.7/bin:/nix/store/bzr287y1sy2qsrmywwkgxlkblz7vx61w-gnugrep-3.3/bin:/nix/store/4mjyhc65kdri28g59gpnjvimjkb44vpy-gawk-4.2.1/bin:/nix/store/c52xr0xha8m6752wr8s3h03ggjajwq5l-gnutar-1.32/bin:/nix/store/r1rvdsxgrmjpcf0k5fd9bsjg807m1grm-gzip-1.10/bin:/nix/store/aas637k5pwjp26mzm2la15n0dl11pl6j-bzip2-<inherited path>

Which is to say, nix-shell adds all of the dependencies to the path too, whereas nix run only adds the output package.