Skip to content

Instantly share code, notes, and snippets.

Last active September 24, 2022 13:53
What would you like to do?
Nix UI

General notes

  • nix-channel and ~/.nix-defexpr are gone. We'll use $NIX_PATH (or user environment specific overrides configured via nix set-path) to look up packages. Since $NIX_PATH supports URLs nowadays, this removes the need for channels: you can just set $NIX_PATH to e.g. and stay up to date automatically.

  • By default, packages are selected by attribute name, rather than the name attribute. Thus nix install hello is basically equivalent to nix-env -iA hello. The attribute name is recorded in the user environment manifest and used in upgrades. Thus (at least by default) hello won't be upgraded to helloVariant.

    @vcunat suggested making this an arbitrary Nix expression rather than an attrpath, e.g. firefox.override { enableFoo = true; }. However, such an expression would not have a key in the user environment, unlike an attrpath. Better to require an explicit flag for this.

    TBD: How to deal with search path clashes. The idea is that nix install firefox will check the search path from left to right, looking for a firefox attribute. However, the user may want to have multiple versions of Nixpkgs in the search path, so we'll need some way to specify more precisely.

  • By default, we won't show build log output anymore. Instead there will be some progress indicator (e.g. 9/16 packages built, 1234/5678 KiB downloaded). If a build fails, Nix will print the last N lines of the build log, with a pointer to nix log to get the rest.

  • Terminology: should ditch either user environments or profiles.

  • All commands that provide output should have a --json flag.

  • Commands versus flags: A flag should not make a command do something completely different. So no more nix-instantiate --eval (since the --eval causes nix-instantiate to not instantiate anything). However, the opposite, nix eval --instantiate might be okay, since it causes instantiation in addition to evaluation.

  • TBD: Need some support for discovering / configuring "plugins" (i.e. the stuff currently enabled via wrapFirefox, texlive.combine etc.). One way would be to allow packages to declare user environment builder hooks to delay stuff like wrapper script generation until the user environment is (re)built. For example, the firefox package could declare a hook that iterates over the installed packages, looking for Firefox plugins, and then writes an appropriate wrapper script to $out/bin/firefox. As a bonus, this gets rid of the firefox / firefoxWrapper distinction.

Main commands

nix search

Searches for available packages. Replaces nix-env -qa.

  • To show all available packages:

      $ nix search
      hello                  1.12
      firefox                43.3
      firefox-esr            38.0.3
      perlPackages.DBDSQLite 1.2.3
  • To search by package name:

      $ nix search --name 'hel.*'
      hello           1.12
  • To search by attribute name:

      $ nix search firefox perlPackages
      firefox                43.3
      perlPackages.DBDSQLite 1.2.3
      perlPackages.XMLSimple 4.5.6
  • Other filters: --description, ...

TBD: nix search could have a cache.

nix install

Adds a package to the user environment. (Maybe this should be called nix add?)

  • Install the Hello package from Nixpkgs:

      $ nix install hello

    This will install the hello attribute from the package search path. Assuming that $NIX_PATH is nixpkgs=https://..., this is equivalent to `nix-env -iA nixpkgs.hello).

  • Install the Hello package, marking it as "declarative":

      $ nix install -d hello

    This gives it semantics similar to environment.systemPackages in NixOS: any subsequent operation on the user environment will rebuild hello (if necessary) from the then-current Nixpkgs. Without -d, the user installs some fixed store paths that are left unchanged by subsequent operations, unless they specifically target that package. For example:

      $ nix install -d hello
      ... time passes ...
      $ nix install firefox # <- this may rebuild hello
      ... time passes ...
      $ nix uninstall firefox # <- this may also rebuild hello

    while without -d, none of the operations on firefox will change hello.

    This is implemented by having the manifest.nix for the user environment track non-declarative packages by store path, e.g.

      { hello = {
          expr = builtins.storePath /nix/store/abcd1234-hello-1.2.3;

    while declarative entries look something like

      { hello = {
          expr = (import <nixpkgs> {}).hello;
  • Install the Hello package from a Nixpkgs git clone:

      $ nix install -f /path/to/nixpkgs hello
  • Install a store path:

      $ nix install /nix/store/abcd1234-hello-1.11

    TBD: Since user environments are keyed by attribute name, and we don't have an attribute name here, we have to fake one. We could just use the name part of the store path (i.e. hello), or assign a random name. There could be a --key flag to override the attribute name.

  • Copy a package from the default user environment on a remote machine and install it:

      $ nix install mandark:hello

    or from a specific user environment:

      $ nix install mandark:/nix/var/nix/profiles/test:hello
  • Copy a store path from a remote machine via SSH and install it:

      $ nix install mandark:/nix/store/abcd1234-hello-1.11

nix rebuild

Rebuilds the user environment, given the current package search path and the manifest, thus causing declarative packages (those installed with nix install -d) to be rebuilt if necessary.

This command is really equivalent to doing an empty nix install or nix uninstall - it doesn't change the manifest, it just rebuilds it, which in the case of declarative packages can cause a rebuild of those packages.

nix upgrade

Replaces nix-env -u. For each non-declarative user environment element, checks if a more recent package with the same attribute name is available.

nix list

Shows the packages installed in the user environment.

$ nix list
hello   1.10
firefox 43.0

nix status

Shows installed packages and compares them to available packages. Replaces nix-env -qc.

nix uninstall

Removes a package from the user environment.

$ nix uninstall hello

nix rollback

Exactly the same as nix-env --rollback.

nix use

Replaces nix-shell -p. It's a different verb from nix shell to denote that nix use gives you a shell containing a package, while nix shell gives you a shell containing the environment for building a package.

  • Start a shell containing the hello package from the package search path:
$ nix use hello
[subshell]$ hello

This should also have a way to run a command, but unlike nix-shell --command <foo>, the arguments should be positional to remove the need for quoting. E.g.

$ nix use hello -c hello --greeting bla

nix sandbox

Like nix-use, but runs the shell / command in a namespace where (for instance) it only has access to specific parts of the user's home directory.

nix set-path

Overrides $NIX_PATH for a specific user environment. E.g.

$ nix set-path nixpkgs=

will cause Nix to henceforth use the specified version of Nixpkgs for this particular user environment.

Nbp suggested calling this nix remote (analogous to git remote), however the local/remote terminology doesn't really apply here. A possibility might be nix source, e.g.

  • nix source add nixpkgs https://...
  • nix source add nixpkgs-14.12 https://...
  • nix source remove nixpkgs-14.12
  • nix source pin nixpkgs # put an infinite TTL on downloaded nixpkgs tarball, for nix-channel like behaviour

nix query-options

Shows per-package options. How exactly packages will declare these options is TBD. Example:

$ nix query-options emacs
x11  | true  | Whether to enable X11 GUI support
cups | false | Whether to enable CUPS printing support

Then at install time you can specify these options:

$ nix install emacs --pkg-option x11 true

or maybe

$ nix install emacs --disable x11 --enable cups

Maybe also a command to modify options:

$ nix modify emacs --enable x11

(This is equivalent to nix install, except that it uses previously recorded values for options that are not specified.)

Possibly we could have a --global flag for querying global options (like "enable Pulseaudio for all packages that support it").

nix history

Show the history (log) of changes to a user environment. Improved version of nix-env --list-generations. Should show the changes between user environment generations (e.g. firefox upgraded from 43.0 to 44.0).


Multiple operations that modify a user environment can be combined in an atomic transaction. For example,

$ nix uninstall chromium \; install firefox

Developer commands

nix build

Replaces nix-build, but with Nix expression lookup semantics consistent with the other commands. Thus:

$ nix build hello

builds the hello package from package search path, while

$ nix build -f release.nix tarball

builds the tarball attribute from the file release.nix.


$ nix-build /nix/store/abcd1234-hello-1.11

is equivalent to nix-store -r (i.e. it will fetch the specified path from the binary cache).

nix shell

  • Start a development shell based on ./default.nix or ./shell.nix:

      $ nix shell

    (Hm, do we want a special case like this?)

  • Start a development shell based on the firefox attribute in the package search path:

      $ nix shell firefox
  • Start a development shell based on the build.x86_64-linux attribute in release.nix:

      $ nix shell -f release.nix build.x86_64-linux

    (I.e. nix-shell release.nix -A build.x86_64-linux.)

  • Run a command inside the shell:

      $ nix shell -c make -C target -j10

    Unlike nix-shell --command, this uses positional arguments, removing the need to escape the command. Note: this complicates option processing a bit since the position of -c is significant (it should come after all package names).

nix edit

Opens the Nix expression of the specified package in an editor.

$ nix edit firefox

nix repl

May want to move this into Nix.

nix eval / parse

These replace nix-instantiate --eval and nix-instantiate --parse. E.g.

$ nix eval -E '1 + 2'

nix make-store-derivation

Replaces nix-instantiate with a more descriptive if somewhat verbose name.

nix log

  • Show the build log of the given store path:

      $ nix log $(type -p hello)
  • Show the build log of the given package from the package search path:

      $ nix log hello

nix fetch-url

Replaces nix-prefetch-url.

  • Fetch the URL denoted by hello.src and print its hash:

      $ nix fetch-url hello.src
  • Fetch the specified URL and print its hash:

      $ nix fetch-url

System administration commands

nix gc

Deletes old user environment generations and then deletes unreachable store paths. Equivalent to nix-collect-garbage -d.

Policy on how long to keep generations can be specified in nix.conf (i.e. flags like --delete-older-than can now be made sticky).

nix copy

Copies paths between Nix stores. In Nix 2.0, binary caches and remote systems are a kind of store.

  • Copy the closure of Firefox to a local binary cache:

      $ nix copy --to file:///tmp/my-cache -r $(type -p firefox)
  • Copy the closure of Firefox to a binary cache in S3:

      $ nix copy --to s3://nixos-cache -r $(type -p firefox)
  • Copy the closure of a path between to binary caches:

      $ nix copy --from --to file:///tmp/my-cache \
          -r /nix/store/lhs110bci7yz6a0p6bbha8kvja3sjyr6-util-linux-2.27.1
  • Copy to a remote machine via SSH:

      $ nix copy --to ssh:// -r $(type -p firefox)
  • Copy from a remote machine via SSH:

      $ nix copy --from ssh:// -r /nix/store/lhs110bci7yz6a0p6bbha8kvja3sjyr6-util-linux-2.27.1

Misc. store-level commands

nix path-info

Shows info about a store path (size, hash, registration time, signatures, ...).

  • E.g. -s shows the size of a path:

      $ nix path-info -s /run/current-system
      /nix/store/vrgjb5kh9gs2n3prpsap45syffjy5g5v-nixos-system-foo-16.03.git.8d4ef4dM  47528
  • -S shows the closure size:

      $ nix path-info -S /run/current-system
      /nix/store/vrgjb5kh9gs2n3prpsap45syffjy5g5v-nixos-system-foo-16.03.git.8d4ef4dM  3224565536
  • With -r, shows info about the closure of the path:

      $ nix path-info -r -s /run/current-system
      /nix/store/000csds2hcgwy2y8khm3cs4jjqpc92h5-libpaper-1.1.24   47856
      /nix/store/00sc3r8iln5yd3cxaixv63a6a04i31b2-nss-cacert-3.23  251384

    Or to show paths with the biggest closure in a closure:

      $ nix path-info -r -sS /run/current-system | sort -rnk3 | head
      /nix/store/vrgjb5kh9gs2n3prpsap45syffjy5g5v-nixos-system-foo-16.03.git.8d4ef4dM  47528 3224565536
      /nix/store/l88j4ksdz1d09lrz5zf0iwjg6jgb17ks-etc                                  32808 3089347976
      /nix/store/5zqifi40vh52wp2z1rvyx5nl8apk492j-system-units                         80608 2835439360
      /nix/store/rd58kxz7g6q8kv5s7w13w097clz0yv8s-unit-dbus.service                     1264 2780572336

nix substitutes

Shows available substitutes of a given store path.

nix add-to-store

Replaces nix-store --add.

nix verify

Replaces and extends nix-store --verify-paths and nix-store --verify. By default, checks whether paths have at least one valid signature and are not corrupted on disk.

  • Verify all paths in the NixOS system closure:

      $ nix verify -r /run/current-system
      path ‘/nix/store/xfz2ywkml4pf2yqg5wjvfijx1ds4x56l-firmware-linux-nonfree-2016-01-26’ is untrusted
      path ‘/nix/store/v6afsf2pz3xzszhygmyrdbdyv9wsvhaq-oxygen-icons-4.14.3’ is untrusted
      795 paths checked, 384 untrusted, 0 corrupted, 0 failed
  • The same, but obtain missing signatures from the specified substituter:

      $ nix verify -r /run/current-system -s
      path ‘/nix/store/w5yam5fymbxmar39lvrqwrr0xdgqjs20-firewall-reload’ is untrusted
      path ‘/nix/store/z953anwmv7ivdcaw3nff3n90jqf5smm3-vista-fonts-1’ is untrusted
      795 paths checked, 14 untrusted, 0 corrupted, 0 failed
  • Verify whether any path in the store has been corrupted (without checking sigs):

      $ nix verify --all --no-trust
  • Verify a binary cache:

      $ nix verify --all --store file:///tmp/my-cache

nix print-roots / print-dead / print-live

These replace nix-store --gc subcommands.

Misc. utility commands

nix hash-file

Replaces nix-hash --flat.

nix hash-path

Replaces nix-hash (without --flat).

nix to-base16 / to-base32

Replaces nix-hash --to-base32 / --to-base32.

nix nar

Replaces nix-store --dump.

nix unnar

Replaces nix-store --restore.

nix list-nar

New command to list the contents of a NAR file.

Copy link

@edolstra This looks really great!

One thing that I'd like to see better UI/UX for is this idiom:

$ nix-instantiate . --indirect --add-root $PWD/shell.drv
$ nix-shell $PWD/shell.drv

I've been tempted for a while to write a tool that would do all of that for me, while also creating a profile for easy rollback. (And maybe some way for keeping track of / rolling back the git revision of nixpkgs that I'm working with)

Unfortunately, I don't quite have enough bandwidth at the moment to think up a solid design...

Copy link

We need to provide a better version recognition of a pkg for nix update.

Copy link

globin commented Jan 20, 2016

@jagajaga I'm working on adding a version attribute to all derivations

Copy link

This looks great. There's some small things that Nix could do well to steal from Homebrew for OSX:

  • Rename nix status to nix info and have it be a comprehensive source of info about the package. brew info <blah> is my favourite part of homebrew. See what I get for brew info sqlite:
    • Show latest version in Nix path and latest available from substitutes, as well as all installed versions of a certain package and how much space they take up. I.E every installed version of GCC I have so I can see if mine is out of date or I have tons of them clogging my disk.
    • Show which installed version, if any, is linked into my current user profile, or even NixOS profile.
    • Link to the Nix expression where it is defined, preferably even a Github link
    • Which of the dependencies I have and what would need to be installed.
    • Description of the package and the list of options, maybe merge nix query-options into it. This is what brew does.
  • When a nix search doesn't find anything, and you aren't on unstable, then check if the package is in unstable and link to the derivation on Github. Even better, search for open pull requests to NixOS/Nixpkgs.

I also like the nix source command format, and agree about moving internal hackery commands under nix store <somecommand>

Copy link

It looks very nice! I specially like the build log output hidden by default and nix log.

A few suggestions:

  • It would be nice to have a way to use a previous channel generation with nix-install -d if for some reason some updates fails to build, as it happens sometimes on unstable (Source building with missing source file comes to mind).
  • The new UI is missing commands to list and switch generations for user, system and channels, adding them could be useful (current nix-env --list-generations, nix-env --switch-generation X with -p /nix/var/nix/profiles/system and -p /nix/var/nix/profiles/per-user/root/channels variants).
  • In the same idea, a command to tag a generation like nixos-rebuild -p does could be useful. Eg nix tag-generation "test", even better if it could work with user and channel generations and also allow to tag previous generations by passing the generation number.

Copy link

Why not call nix set-path just nix path, and have the add/remove sub commands as suggested by nbp? Maybe this could also allow for caching/rolling back paths, although it would have to interact with nix' handling of http paths in some way.

I also wish for a declarative way to handle paths on a project basis. I use my small tool nix-path ( for this now. It lets you have a file defining all paths your project uses, and then sets up NIX_PATH correctly. It is used as a wrapper around the other nix commands, like nix-path -f my-paths.nix nix-build .... It would be nice to have something similar supported out of the box by nix.

Copy link

@cstrahan perhaps your command could be nix shell persist or nix shell save or nix shell retain, but I'd rather it not look like a .drv file 😦

Copy link

I did a little writeup with my thoughts & proposals:

In that I address the problem of search path clashes @edolstra mentioned in the General section.

Copy link

@edolstra @Profpatsch can we move this discussion into a Nix issue? GitHub gists have no notifications and are generally harder to track.

Copy link

Copy link

this all sounds great.

Copy link

looks great

nix source over nix set-path
nix uninstall chromium + install firefox over nix uninstall chromium \; install firefox

I'm looking forward to this new interaction

Copy link

I'd prefer if version was a separate attribute, so we don't need to parse it for nix search output.

Copy link

spinus commented Jan 21, 2016

+1 for version attribute

what about keeping configuration as separate command, like git and few other tools:

nix config set KEY VAL

instead of mixing setting configuration with other commands
nix set-path
nix modify etc

Copy link

Can there be a function to show or link to the implementation/documentation for any particular Nixpkgs/lib function?

Copy link

Baughn commented Jan 23, 2016

One of my pet peeves is that garbage collection deletes the inputs used for the current system, which then have to be re-downloaded on next update. It's the reason I switched it back off.

I don't know if this is the right place to mention that, but since it seems like you're planning to do a lot of other changes... I thought I'd say it.

From what I can tell re. declarative vs. non-declarative packages, it sounds like declarative packages would be what users normally want, whereas non-declarative ones might be more useful for development or special circumstances. If that's the case, shouldn't -d be the default?

Copy link

Were the latest suggestions from NixOS/nix#779 factored in?

Copy link

Am I missing something or is there no command for rebuilding the system? nix rebuild is stated to rebuild the user environment! 😕

Copy link

Oh and just wanted to mention, channels currently is the only easy way of merging multiple different package sets together that allows one to just write nix-env -i 'channel_name.package, so I don't have to point to a particular package set using -f option. If we remove that and only allow NIX_PATH, how do we gain mergeable package sets? Do we just append every new package set folder_path/url to the NIX_PATH? But does this allow imperative kind of nix-channel style management of such package sets? (I guess it depends on what kind of balance of imperativeness and declarativeness we are heading to...)

Copy link

It might be nice to have something like the git-aliases somewhere, I keep forgetting the cheatsheet commands.

Copy link

Wanted: verbose versions (aliases) of the single-character flags (-d, -e, -p, ...). For example:

-d => --declarative

And then ENSURE that: the help messages, 'usage' output, online documentation, tutorials all use the verbose versions (i.e., make the verbose versions the default, and have the single-character versions be alternative, compact forms).

Copy link

bobvanderlinden commented Jun 3, 2016

@matthiasbeyer I was looking for the same thing. I do think it would be confusing to have that in nix as well, because it will make no sense when Nix is used on another distro. Maybe have a separate nixos command with nixos switch (as well as boot, etc). nixos-rebuild always came across to me as weird, because often it didn't rebuild much at all.

Copy link

@bobvanderlinden I guess it would be nice to simply have a new level in the hierarchy to have nix <command> for nix related stuff and nix os <command> for nixos related stuff.

This way we have the scoping, but only one command in the top-level. A non-nixos installation could simply yield Not on a NixOS system, cannot execute NixOS specific commands or something like that.

Copy link

avnik commented Jul 15, 2016

My two cents:

nix export/nix import looks more sane names then nar/unnar

Also would be nice to have well designed nixos command, to replace nixos-{install,rebuild) (as well as possible extendable in same way like git)

Copy link

ndowens commented Feb 22, 2017

I am glad for the changes. Looking forward to it. 👍 to all who worked on this :) Thanks for the work

Copy link

CMCDragonkai commented Mar 28, 2017

Some extra suggestions:

  1. Reverse search - an obvious way to find the package that contains a particular executable or resource, basically walking back the symlink. (I know this can be done atm, but easier if integrated into nix command line)
  2. Show the implementation of any nix function or module (it can be done somewhat via nix-repl if the nix-repl could show the path/line number.. etc)
  3. Nix expression impurity appears to include environment variables, filesystem files... etc, why not one-off commands? Not really a suggestion, just wanted a discussion on the impurity aspect of Nix expressions.
  4. Show the dependencies of a Nix package

Copy link

bennofs commented Apr 23, 2017

@edolstra you say that allowing an arbitrary expression in nix install would not allow us to construct a key for the manifest.nix. But, what do you think about the following solution:

  • instead of storing a key in the manifest.nix, store the expression that was used for the install
  • on each new install, check if any of the existing expressions evaluates to the same as the to-be-installed expression. If yes, replace it.

Copy link

jpotier commented Sep 12, 2017

TBD: nix search could have a cache.

We could reimplement this bash function:

nix-search () {
  local CACHE="$HOME/.cache/nq-cache"
  if ! (
    [ -e $CACHE ] && [ $(stat -c %Y $CACHE) -gt $(( $(date +%s) - 3600 )) ]
    echo "update cache" && nix-env -qa --json > "$CACHE"
  jq -r 'to_entries | .[] | .key + "|" + .value.meta.description' < "$CACHE" | {
  if [ $# -gt 0 ]
    grep -i "$*" | column -t -s "|" | grep --color=always -i "$*"
    column -t -s "|"

It relies on jq and has been working well for me for a year (I'm not the author of this)

Copy link

About tools like nix-shell (and eventually nix shell and nix use): can we get an option to just modify your environment in place instead of dropping you into a new shell? Currently nix-shell functionality can be frustrating to use because it always puts you in a bash shell, and if you try to specify another shell you risk having your environment clobbered when the shell is initialized. (Right now using Fish with nix-darwin means you can't use Fish directly with nix-shell --run. This can and should be fixed separately and I'll submit a PR for it soon, but keep reading.) There are other annoyances with completions being missing by default (not hard to work around, but annoying) and crazy/whacky prompts when using multiple/nested nix-shells.

Using the Nix integration of direnv, we get a really nice thing where the changes are imported directly into our current shell's environment, regardless of what shell we're using. That would be a great option to have built into Nix itself. Maybe we could even use direnv to achieve it.


Copy link

bobvanderlinden commented Mar 16, 2019

I would really love to see a way to generalize the usages of Nix on local-, user- and system-level. Currently to install packages on system level you need to:

  • open /etc/nixos/configuration.nix
  • look up systemPackages
  • add entry of package
  • close file
  • run nixos-rebuild switch

To install packages in for your local project you need to:

  • open shell.nix or default.nix
  • look up buildInputs
  • add entry of package
  • close file
  • rerun nix-shell

The gist above has nice UX, but only mentions alternatives for nix-env when it comes to installing/uninnstalling packages. It would be nice if we could do something like:

nix install --local hello
nix install --user hello
nix install --system hello

To make this work, a manifest.nix could exist in your home directory (~/.nixpkgs/manifest.nix), in your system (/etc/nixos/manifest.nix) or locally next to your shell.nix/default.nix.

The default could very well be --user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment