Hey Nix friends!
I’ve been working on learning the basics of Nix for awhile now, in particular focusing on flakes. One of the things that still eludes me is the different use cases for the main flake commands.
When would you use nix build
vs nix shell
vs nix develop
vs nix run
? What are the strengths and weaknesses of each?
So far, I feel like nix develop is the command I am most familiar with from setting up my development environment on a web app, but I’d really like to understand all of them better.
nix run nixpkgs#tree
(the command will have to live in$out/bin/
) (ormeta.mainProgram
, if that exists)--
or your flags will be interpreted bynix run
, not passed to the command. E.g.nix run nixpkgs#tree -- -a
nix shell nixpkgs#ffmpeg
. Tip: to enable multiple programs:nix shell nixpkgs#{ffmpeg,tree,imagemagick}
.$out/bin
, but has a different name? This is an odd one:nix shell nixpkgs#postgresql --command psql ...
(extra odd: you don’t need to use--
to separate program args from nix args.) (I understand the “why” behind this, but I hate it. The newnix
command was supposed to solve the counterintuitive UI problem, but here we are, back to square 1. 🤷♀️)nix build
, although if it’s available in a binary cache it will just fetch it from there:nix build nixpkgs#imagemagick
. Now you have it in your/nix/store
, and a symlink to that path in./result
./nix/store
. Combine two flags:nix build nixpkgs#imagemagick --print-out-paths --no-link
.$ nix run nixpkgs#tree -- $(nix build nixpkgs#imagemagick --print-out-paths --no-link)/bin
.open $(nix build nixpkgs#grandperspective --print-out-paths --no-link)/Applications/*
nix run
really is just syntactic sugar for$(nix build --no-link --print-out-paths )/bin/
(sort of)But my all time favourite is
nix develop
: it plops you in a build shell for a derivation. This means you can pretend you are the nix builder, locally. Including fetching the source!E.g., to build sbcl (the lisp compiler) locally, without installing anything else nor even downloading the source, just:
I think this is very neat.
(question: I only know to use patchPhase as a function and buildPhase as a var to eval because I know the derivation well, but there has to be a deterministic way to invoke this, no?)
Summary:
--print-build-logs
).