nix-cli.md

Try Nix without installing

Before this, you'll want

  1. NixOS configuration
  2. Meet nixpkgs
The package manager14 min

Think about the last time you wanted to try some command line tool somebody recommended. You installed it. And then, in all likelihood, you never removed it again, because uninstalling things is a chore nobody has ever enjoyed doing.

That is not carelessness, it is just how package managers work. Before you can use a thing, you have to change your machine:

$ sudo apt install helloSetting up hello...

Nix can do something else entirely. It can lend you a package for exactly one command, or exactly one shell, and then take it back. It may fetch a store path along the way, but it does not add the program to a global package list and it does not leave a profile entry behind.

Enable the current command interface

One small thing to get out of the way first. The newer nix command and flakes are still officially gated behind an experimental flag. Most installers turn them on for you already, but if Nix ever complains, NixOS can keep the setting in the machine configuration:

GoalTurn on the newer command interface and flakes.

  • Include "nix-command" and "flakes"
configuration.nixNixOS moduleA NixOS module, checked against real NixOS options and evaluated by the NixOS module system.

And yes, “experimental” is exactly the sort of word that should make a beginner nervous. The interface really can still change. But this is what everybody uses every day, and starting with the old commands instead would only mean learning the same thing twice.

Read a package address

Every modern Nix command needs to know two things: where to get the software, and which piece of that source you actually want. So they all take the same shape, source#attribute.

$ nix shell nixpkgs#hello

Here nixpkgs is the source and hello is the package attribute, the same attribute you’d select from pkgs. The registry works out that nixpkgs means a nixpkgs snapshot, which is all you need for a quick experiment.

Borrow a package for one shell

Time to actually borrow something. nix shell opens a shell whose PATH includes the package you asked for, and changes nothing else about your system.

$ nix shell nixpkgs#hello$ helloHello, world!$ exit$ hellobash: hello: command not found

Then you leave, and it’s gone. The package may stay in the Nix store for next time, but your shell has stopped carrying the key to it.

GoalOpen a temporary shell containing ripgrep.

Which makes this the nicest way there is to try a tool out before deciding whether it deserves a place in your system, your home, or a particular project.

Run one program and leave

Sometimes even a shell is more than you wanted. nix run is smaller still: fetch the selected app, run it, and hand you back your terminal.

GoalRun hello once without staying inside a shell.

Use nix shell when you want tools around you. Use nix run when the program is the whole job.

Search instead of guessing

Both of those commands assume you already know the attribute to ask for. So what do you do when you don’t?

Humans say “a terminal multiplexer.” Nix needs an exact package attribute. So nix search takes the source, then as many words as you like, and matches them against every package’s name and description.

GoalSearch nixpkgs for a terminal multiplexer, describing it rather than naming it.

The attributes you were after are zellij and tmux. Search the descriptions first, then take the candidate for a spin in a temporary shell.

The program still lives in the store

Hold on, though. If nothing was installed, where is the program actually coming from?

Nix never copied it into /usr/bin. It put the package’s store path on PATH for the temporary environment and left everything else alone:

$ nix shell nixpkgs#hello$ which hello/nix/store/w2q5r...-hello-2.12.2/bin/hello

That prefix is derived from the package’s build inputs, which is why two different versions get two different paths and can sit side by side without ever overwriting each other.

Know when an address is not pinned

There is one catch to all this convenience, and it’s the one from the last lesson wearing a new hat. nixpkgs#hello asks the registry what nixpkgs means right now, and right now keeps changing.

PickChoose the address tied to one exact source revision.

Which does not mean you should start typing revisions by hand, because nobody sane works that way. It means the pinning has to live somewhere, and a flake lockfile is where it goes: written down once, in the repository, and remembered for you. I swear we will get back to this later :D

What to keep

  • Modern commands use source#attribute to identify what they should use.
  • nix shell lends tools to a temporary shell.
  • nix run runs one selected app and returns.
  • nix search nixpkgs words finds attributes from human descriptions.
  • Temporary environments change PATH, not /usr/bin or a global package list.

Useful links

NORMALCOURSE IN BETA