The Nix Package Manager in Practice
The Nix Package Manager in Practice
Nix the language is useless without Nix the tool. The boring default on Nix 2.35 is: nix shell for five minutes, nix profile only for personal CLIs that are not a project, and nix search against a 26.05 pin — not nix-env -iA.
Project compilers still belong in devShell / direnv. This chapter is the user profile and one-shot PATH.
Mental model
~/.nix-profile is a generation of symlinks into /nix/store. It is not /usr/bin. Adding jq does not delete the previous jq; rollback is another generation.
| Command | Lifetime |
|---|---|
nix shell nixpkgs#jq |
This process |
nix run nixpkgs#jq -- --version |
One command |
nix profile install nixpkgs#jq |
Until rollback/remove |
nix search nixpkgs jq |
Query |
Unqualified nixpkgs# follows your registry (often a moving flake). For desk work prefer a pinned flake:
nix shell github:NixOS/nixpkgs/nixos-26.05#jqor nix shell .#jq inside a repo.
Worked examples
Case 1: One-shot
nix shell github:NixOS/nixpkgs/nixos-26.05#cowsay --command cowsay "Desk system ready"Output:
____________________
< Desk system ready >
--------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Nothing new in nix profile list.
Case 2: nix run
nix run github:NixOS/nixpkgs/nixos-26.05#helloOutput:
Hello, world!
run builds (or substitutes) and executes the default app. Good for nix run .#desk-api.
Case 3: Profile install + list
nix profile install github:NixOS/nixpkgs/nixos-26.05#jq
nix profile list
which jq
readlink -f "$(which jq)"Output (shape):
Name: jq
Flake attribute: packages.x86_64-linux.jq
Store path: /nix/store/…-jq-…
readlink -f $(which jq) is a store path. On NixOS, prefer Home Manager home.packages over a growing profile if the user already has HM.
Case 4: Rollback
nix profile history
nix profile rollback
which jq || echo 'jq gone'If jq was the only package in that generation, it disappears from PATH. The store path remains until GC.
nix profile remove jq # if your 2.35 CLI uses names; else remove by index from `nix profile list`Case 5: Search against 26.05, not the registry drift
nix search github:NixOS/nixpkgs/nixos-26.05 jqOutput (shape):
* legacyPackages.x86_64-linux.jq
jq: Command-line JSON processor
First search can be slow (eval). After that, 26.05 is cached. nix search nixpkgs jq without a pin is whatever the flake registry says today.
Pin the user registry so unqualified nixpkgs# matches the desk:
nix registry pin nixpkgs github:NixOS/nixpkgs/nixos-26.05
nix registry listCI still uses the repo flake.lock, not your laptop registry. The pin only stops surprise nix shell nixpkgs#jq on a workstation.
nix profile upgrade --allOn Nix 2.35 this rebuilds profile packages against whatever they were installed from. Prefer deleting a profile package and using Home Manager / the project flake instead of living on upgrade --all. Compilers still do not belong here.
The trap
The trap is nix-env -iA nixpkgs.jq. Unpinned, fights flakes, surprising rollbacks. nix-env is legacy. nix profile or Home Manager.
The other trap is nix profile install of go, nodejs, rustc. The next repo wants another version. Put those in the project devShell.
A third trap: nix shell nixpkgs#jq with an unlocked registry while CI uses 26.05. Pin the URL or the repo flake.
The boring rule
nix shell/nix runfor trials. Pinnixos-26.05.nix profilefor personal CLIs (jq,ripgrep). Not for compilers.nix profile rollbackwhen an install was a mistake.- No
nix-env. - Project tools in the flake, not in the user profile.
Try this
nix shell github:NixOS/nixpkgs/nixos-26.05#fastfetch --command fastfetch(orhello).nix search github:NixOS/nixpkgs/nixos-26.05 postgresql | head.- Install
hellointo the profile, run it, rollback, confirmwhich hello. nix profile listand remove anything that is a compiler.