Why this matters
This is the daily-driver Nix. Need ripgrep on a machine for ten minutes, or want to try a CLI without polluting pacman: one command, no install, nothing left behind except cache. It replaces npx, pipx run, and docker run --rm for most one-off tool use.
Concept
Installables and the nixpkgs# syntax
Every new-style nix command takes an installable: <flake>#<attribute>. nixpkgs#hello means "the attribute hello in the flake named nixpkgs".
Where does the name nixpkgs come from? The flake registry, a lookup table from short names to URLs:
nix registry list | grep 'flake:nixpkgs 'global flake:nixpkgs https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.zstSo nixpkgs#hello is really https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.zst#hello. The registry has 46 global entries. You can add your own with nix registry add, or pin nixpkgs to a commit with nix registry pin. Both write to ~/.config/nix/registry.json.
The attribute path is resolved against the flake's outputs. For nixpkgs, hello is shorthand for legacyPackages.x86_64-linux.hello. You will see the long form in search results.
nix run: execute once
nix run nixpkgs#helloHello, world!Nix evaluates the attribute, downloads the closure from cache.nixos.org (or builds it), runs bin/hello, exits. Nothing is added to your PATH or profile. The closure stays in the store until GC.
Arguments go after --:
nix run nixpkgs#hello -- --greeting "hi dave"hi daveWhich binary runs? meta.mainProgram if set, otherwise a binary matching the package name.
nix shell: a temporary PATH
nix shell nixpkgs#ripgrepDrops you into a subshell where rg is on PATH. Your fish config, cwd and env are untouched. Type exit to leave. For a one-liner, use -c:
nix shell nixpkgs#ripgrep -c sh -c 'command -v rg'/nix/store/vli6118fdbngwy46j1w741ansmrzfszr-ripgrep-15.2.0/bin/rgThe binary lives in the store, not in /usr/bin. Several packages at once: nix shell nixpkgs#ripgrep nixpkgs#fd nixpkgs#jq.
nix shell is for using tools. nix develop (next lesson, Dev shells) is for building projects: it also sets up compilers, headers and environment variables.
nix search: finding names
nix search nixpkgs ripgrep* legacyPackages.x86_64-linux.bat-extras.batgrep (2024.08.24-unstable-2025-02-22)
Quickly search through and highlight files using ripgrep
* legacyPackages.x86_64-linux.grip-grab (0.6.7)
Fast, more lightweight ripgrep alternative for daily use cases
* legacyPackages.x86_64-linux.repgrep (0.17.1)
Interactive replacer for ripgrep that makes it easy to find and replace across files on the command line
* legacyPackages.x86_64-linux.ripgrep (15.2.0)
Utility that combines the usability of The Silver Searcher with the raw speed of grepThe search term is a regex matched against name and description. Anchor the end to cut noise: nix search nixpkgs 'ripgrep$'. Exclude with -e: nix search nixpkgs grep -e bat. Machine-readable: --json.
The first search evaluates all of nixpkgs and caches the result in ~/.cache/nix/. It takes a while. Later searches are fast.
For a name you already suspect, skip search and check directly:
nix eval nixpkgs#turso-cli.version"1.0.31"Where the files come from
Nothing is compiled on your machine for common packages. cache.nixos.org is a substituter: Nix asks it "do you have this store path?" and downloads the prebuilt closure. Your nix config show lists it as the only substituter. If a path is not in the cache, Nix builds it locally.
Try it
Run a tool you do not have, with arguments.
nix run nixpkgs#ripgrep -- --versionripgrep 15.2.0
features:+pcre2
simd(compile):+SSE2,-SSSE3,-AVX2
simd(runtime):+SSE2,+SSSE3,+AVX2
PCRE2 10.45 is available (JIT is available)Then look up the exact attribute for Biome and its version:
nix eval nixpkgs#biome.version"2.5.14"Exercise
Find the nixpkgs attribute for Node.js 22 (not 24), confirm its exact version, and run node --version through it without installing anything.
Solution
nix search nixpkgs 'nodejs_2' 2>/dev/null | grep '^\*'* legacyPackages.x86_64-linux.nodejs_22 (22.23.3)
* legacyPackages.x86_64-linux.nodejs_24 (24.21.0)
* legacyPackages.x86_64-linux.nodejs_26 (26.10.0)nix eval nixpkgs#nodejs_22.version
nix run nixpkgs#nodejs_22 -- --version"22.23.3"
v22.23.3Note ^nodejs_ finds nothing: the regex runs against the full attribute path legacyPackages.x86_64-linux.nodejs_22, so anchoring to the start fails.
nixpkgs#nodejs with no suffix is the current default, 24.21.0 at this nixpkgs revision. Pin the suffixed attribute in projects. The first nix run downloads the Node closure; on your line expect a minute or two.
Trap
fish and #. In fish, # starts a comment only at the start of a word, so nix run nixpkgs#hello is safe. But a space before it, nix run nixpkgs #hello, makes #hello a comment and the command silently becomes nix run nixpkgs. Keep flake#attr as one unbroken token.