Introduction - nixos-cli
nixos-cli
is a robust, cohesive, drop-in replacement for NixOS tooling such as
nixos-rebuild
, among many other tools.
Why?
NixOS tooling today is fragmented across large, aging shell and Perl scripts that are difficult to maintain or extend. Prolific examples include:
These tools contain deep functionality, but much of it is hidden, hard to modify, or locked behind poor ergonomics.
nixos-cli
aims to modernize this experience by:
- Replacing and improving existing tooling
- Providing a consistent interface across all commands
- Making functionality more accessible and extensible
- Offering a clean, discoverable CLI experience for both users and developers
In summary, this tool has one goal: to create a modular NixOS CLI that mirrors
or enhances the functionality of all current NixOS tooling in nixpkgs
, adds on
to it if needed, and eventually come to replace it entirely.
Yes, this is already being done somewhat by switch-to-configuration-ng
and
nixos-rebuild-ng
. However, nixos-cli
strives to achieve further goals,
including (but not limited to the following)
- Enhanced usability (and looking nice! Who doesn't love eye candy?)
- Deeper integration with NixOS internals
- Creating a self-contained NixOS manager binary that includes routine scripts
such as
switch-to-configuration
activation functionality - Plugins for further NixOS tooling to be developed out-of-tree
Key Features
- Drop-in replacements for common NixOS tools (with better names!)
- An integrated NixOS option search UI
- An improved generation manager, with an additional UI (more fine-tuned than
nix-collect-garbage -d
)
Check out the overview page for more information about key features.
More features are planned; see the roadmap for more information.
Status
This tool is under active development, but is not yet stable.
Until a 1.0 release, the CLI interface and configuration may change without
notice.
Watch the Releases page for:
- Breaking changes
- Feature updates
- Bug fixes
Core contributors:
Contributions, testing, and bug reports/general feedback are highly encouraged, since there are few people working on this project actively.
Talk!
Join the Matrix room at #nixos-cli:matrix.org! It's open for chatting about NixOS in general, and for making it a better experience for all that involved.
Installation
nixos-cli
is split into two separate executables. This is very intentional for
a number of reasons.
- The majority of NixOS users use either flakes or legacy-style Nix, without mixing the two.
- While the majority of logic is shared between the two styles of configuration, the command-line interface should not be forced to deal with the differences, for the sake of clarity.
- If users want to mix styles, they should do so intentionally. This distinction is reflected in the CLI binaries themselves—not hidden in command behavior.
The flake-style configuration is the default. Nix flakes have been available for several years; although still technically experimental, they are widely adopted and considered stable in practice, particularly in forks like Lix. Legacy configurations are actively supported regardless of this status, though.
NixOS has quite a large ecosystem of tools, and can be quite the moving target
in terms of features, so nixos-unstable
and the current stable release are the
only actively supported releases.
Adding To Configuration
Use the following sections depending on whether or not your systems are configured with flakes or legacy-style configurations.
Available configuration settings for nixos-cli
are defined in the more
detailed settings section, and are specified in Nix
attribute set format here. Internally, they are converted to TOML.
Flakes
nixos-cli
is provided as a flake input. Add this and the exported NixOS module
to the system configuration.
{
inputs.nixos-cli.url = "github:nix-community/nixos-cli";
outputs = { nixpkgs, nixos-cli, ... }: {
nixosConfigurations.system-name = nixpkgs.lib.nixosSystem {
modules = [
nixos-cli.nixosModules.nixos-cli
# ...
];
};
};
}
Then, enable the module.
{ config, pkgs, ... }:
{
services.nixos-cli = {
enable = true;
config = {
# Whatever settings desired.
}
};
}
The default package is flake-enabled, so the services.nixos-cli.package
option
does not need to be specified.
Legacy
To use the NixOS module in legacy mode, import the default.nix
provided in
this repository. An example is provided below with builtins.fetchTarball
:
{ config, system, pkgs, ...}:
let
# In pure evaluation mode, always use a full Git commit hash instead of a branch name.
nixos-cli-url = "github:nix-community/nixos-cli/archive/GITREVORBRANCHDEADBEEFDEADBEEF0000.tar.gz"
nixos-cli = import "${builtins.fetchTarball nixos-cli-url}" {inherit pkgs;};
in {
imports = [
nixos-cli.module
];
services.nixos-cli = {
enable = true;
package = nixos-cli.nixosLegacy;
config = {
# Other configuration for nixos-cli
};
};
# ... rest of config
}
NOTE: Use the nixosLegacy
package. Specifying the services.nixos-cli.package
option is required for legacy configurations, due to the fact that the default
package is for flake configurations only. If there is a reliable way to detect
if a configuration is flake-enabled, please file an
issue so that
this requirement can be removed.
Cache
There is a Cachix cache available. Add the following to your NixOS configuration to avoid lengthy rebuilds and fetching extra build-time dependencies:
{
nix.settings = {
substituters = [ "https://watersucks.cachix.org" ];
trusted-public-keys = [
"watersucks.cachix.org-1:6gadPC5R8iLWQ3EUtfu3GFrVY7X6I4Fwz/ihW25Jbv8="
];
};
}
Or if using the Cachix CLI outside a NixOS environment:
$ cachix use watersucks
There are rare cases in which you want to automatically configure a cache when
using flakes, such as when installing NixOS configurations using this tool. The
following configuration in the flake.nix
can help with this:
{
nixConfig = {
extra-substituters = [ "https://watersucks.cachix.org" ];
extra-trusted-public-keys = [
"watersucks.cachix.org-1:6gadPC5R8iLWQ3EUtfu3GFrVY7X6I4Fwz/ihW25Jbv8="
];
};
inputs = {}; # Whatever you normally have here
outputs = inputs: {}; # Whatever you normally have here
}
⚠️ Beware, though: this is a relatively undocumented feature—use with caution.
Running Using Nix Shells
Sometimes, you may not want to add it to your configuration, and instead run
nixos-cli
on an ad-hoc basis.
This is the preferred way to use nixos-cli
when running nixos init
or
nixos install
on a live NixOS USB for installation.
Use nix develop
(flake-enabled package by default):
$ nix shell github:nix-community/nixos-cli
Alternative using legacy-style nix-shell
and the nixosLegacy
package:
$ nix-shell -E 'with import (fetchTarball "https://github.com/nix-community/nixos-cli/archive/refs/heads/main.tar.gz") {}; nixosLegacy'
Rebuild
After adding the next sections to your configuration, rebuild your configuration
once, and then the nixos
command should be available. Verify by running
nixos features
:
# Example output of `nixos features`
$ nixos features
nixos 0.13.0-dev
git rev: 53beba5f09042ab8361708a5e0196098d642ba5b
go version: go1.24.1
nix version: nix (Nix) 2.28.2
Compilation Options
-------------------
flake :: true
nixpkgs_version :: 24.11
Nice! nixos-cli
is now ready for usage.
Overview
NixOS Tooling Replacements
nixos-cli
has drop-in replacements for the following tools:
nixos-rebuild
→nixos apply
+nixos generation
nixos-enter
→nixos enter
nixos-generate-config
→nixos init
nixos-version
→nixos info
nixos-install
→nixos install
nixos-info
→nixos manual
nixos apply
+ nixos generation
nixos-rebuild
is primarily used to manage NixOS configurations, but has become
bloated and has some non-obvious behavior.
nixos-rebuild
commands are replaced entirely by a combination of the
nixos apply
and nixos generation
commands, with some better-looking logging,
showing diffs between generations, and interactive confirmation before applying
configurations.
Alternatives to builtin Nix tools are provided that can be switched through the settings if available; for example:
nix-output-monitor
for building configurationsnvd
for showing generation diffs
A list of analogues to nixos-rebuild
behavior:
# `nixos-rebuild switch`
$ nixos apply
# `nixos-rebuild switch`, without interactive confirmation
$ nixos apply -y
# `nixos-rebuild switch` on an arbitrary flake ref
$ nixos apply "github:water-sucks/nixed#CharlesWoodson"
# `nixos-rebuild test`
$ nixos apply --no-boot
# `nixos-rebuild vm[-with-bootloader]`
$ nixos apply --vm[-with-bootloader] --output ./vm
# `nixos-rebuild boot`
$ nixos apply --no-activate
# `nixos-rebuild list-generations`
$ nixos generation list
# Show diffs between two generation numbers on the local system
$ nixos generation diff 59 60
# Switch to an arbitrary generation number (and specialisation)
$ nixos generation switch 420 [--specialisation "wayland"]
# `nixos-rebuild switch --rollback`
$ nixos generation rollback
# Fine-tuned generation deletion; keep at least five generations, delete the rest
$ nixos generation delete --min 5 --all
Check the manual for more important information.
Setting the $NIXOS_CONFIG
variable allows for not specifying the --flake
flag at all, which is a huge improvement over nixos-rebuild
.
nixos generation list
by default is a TUI list with Vim-like bindings. To get
tabular, grep
-able output like the old behavior of nixos-rebuild
uses, use
-t
.
Default specialisations are managed through the nixos-cli
configuration.
In the future, setting build and target hosts for remote building/activation using SSH will be supported.
nixos-enter
nixos enter
behaves mostly the same as nixos-enter
, minus some extra logging
controls.
nixos-generate-config
-> nixos init
nixos init
can be used in the same way as nixos-generate-config
. Usually,
this is done through a NixOS live USB before installation. As such, refer to the
installation section for instructions on how to do that.
NOTE: The current configuration that is generated does not include
nixos-cli
setup, due to implementation complexity. If you believe this is
important enough, please file a feature request.
nixos-install
-> nixos install
nixos install
can also be used in the same way as the current nixos-install
script. Similar to nixos init
usage, this is likely to be done off a live USB,
rather than on a live system.
In the future, remote NixOS installations will be supported.
nixos features
This command describes the features that nixos-cli
was compiled with.
Use this when filing issues, in order to provide information about the environment for proper problem diagnosis.
Option UI
The option UI is a nice search for NixOS options that are available on a given system. These are computed on demand for the system, so all available options on that exact system are present.
This is a significant advantage over alternatives; since options are computed from the modules present in a given system, modules that don't have module documentation exposed can still have documentation through the option UI!
Cool, right?
Run nixos option -i
for the interactive search TUI.
Also, nixos option
will just print options and their evaluated values, without
dropping into a TUI.
However, there is one caveat: generating the option index is an intensive
operation; this can be precomputed on every configuration change using the
services.nixos-cli.prebuildOptionCache
if desired.
Environment Variables
The following environment variables influence nixos-cli
behavior:
-
NO_COLOR
:: disable output color (does not apply for TUIs) -
NIXOS_CLI_CONFIG
:: change thenixos-cli
settings location (default:/etc/nixos-cli/config.toml
) -
NIXOS_CONFIG
:: where the configuration to work with is storedThis can vary depending on if the CLI is flake-enabled. If the CLI is flake-enabled, then
$NIXOS_CONFIG
must point to a valid flake ref. Otherwise, it can point to a local Nix configuration file (i.e.configuration.nix
) or directory containing adefault.nix
.
Aliases
Aliases can be used to make shortcuts for nixos-cli
commands. Check the
settings section for an example.
A list of common aliases that people can configure:
nixos genlist
::nixos generation list
nixos switch
::nixos generation switch
nixos testcfg
::nixos apply --no-boot --no-activate
nixos build
::nixos apply --no-boot --no-activate --output ./result
NOTE: Currently, aliases to compose multiple CLI commands or to invoke shell commands are not supported. If this is important to you, please file a feature request.
Completion
Shell completion is provided through the default package. Descriptions for completion candidates are provided (requires newer Bash versions if applicable).
If desired, completion scripts can be obtained manually using
nixos completion <SHELL>
.
Supported shells:
bash
zsh
fish
If you want support for another shell, file an issue. However, this support is provided by Cobra, and as such, support will probably need to be implemented upstream before this is possible.
Settings
Settings are stored in /etc/nixos-cli/config.toml
, and are stored in
TOML
format.
If preferred, this can be overridden by an environment variable
NIXOS_CLI_CONFIG
at runtime. This is useful for testing configuration files.
Additionally, some configuration values can be overridden on the command-line
with the --config
flag.
Example invocation:
$ nixos --config apply.imply_impure_with_tag=false apply
The preferred way to create this settings file is through the provided Nix
module that generates the TOML using the services.nixos-cli.config
option.
Refer to the module documentation for other available options.
Available Settings
These are the available settings for nixos-cli
and their default values.
General
-
aliases
Defines alternative aliases for long commands to improve user ergonomics. Example:
[aliases]
genlist = ["generation", "list"]
switch = ["generation", "switch"]
rollback = ["generation", "rollback"]
Default: []
-
auto_rollback
Enables automatic rollback of a NixOS system profile when an activation command fails. This can be disabled when a reboot or some other circumstance is needed for successful activation
Default:
true
-
color
Turns on ANSI color sequences for decorated output in supported terminals.
Default:
true
-
config_location
Path to a Nix file or directory to look for user configuration in by default.
Default:
"/etc/nixos"
-
no_confirm
Disables prompts that ask for user confirmation, useful for automation.
Default:
false
-
root_command
Specifies which command to use for privilege escalation (e.g., sudo or doas).
Default:
"sudo"
-
use_nvd
Use the better-looking
nvd
diffing tool when comparing configurations instead ofnix store diff-closures
.Default:
false
apply
Settings for apply
command
-
apply.ignore_dirty_tree
Allows 'apply' to use Git commit messages even when the working directory is dirty.
Default:
false
-
apply.imply_impure_with_tag
Automatically appends '--impure' to the 'apply' command when using '--tag' in flake-based workflows.
Default:
false
-
apply.specialisation
Specifies which systemd specialisation to use when activating a configuration with 'apply'.
Default:
""
-
apply.use_git_commit_msg
When enabled, the last Git commit message will be used as the value for '--tag' automatically.
Default:
false
-
apply.use_nom
Enables nix-output-monitor to show more user-friendly build progress output for the 'apply' command.
Default:
false
enter
Settings for enter
command
-
enter.mount_resolv_conf
Ensures internet access by mounting the host's /etc/resolv.conf into the chroot environment.
Default:
true
init
Settings for init
command
-
init.desktop_config
Specifies the desktop environment configuration to inject during initialization.
Default:
""
-
init.extra_attrs
Default:
[]
-
init.extra_config
Default:
""
-
init.xserver_enabled
Controls whether X11-related services and packages are configured by default during init.
Default:
false
option
Settings for option
command
-
option.debounce_time
Controls how often search results are recomputed when typing in the options UI, in milliseconds.
Default:
25
-
option.min_score
Sets the cutoff score for showing results in fuzzy-matched option lookups.
Default:
1
-
option.prettify
If enabled, renders option documentation in a prettier Markdown format where applicable.
Default:
true
Module
These are the available NixOS module options for nixos-cli
. This is the
preferred way to configure things like settings, and to add the CLI itself to
the $PATH
.
services.nixos-cli.enable
unified NixOS tooling replacement for nixos-* utilities
Type: boolean
Default: false
Example: true
services.nixos-cli.package
Package to use for nixos-cli
Type: types.package
Default: self.packages.${pkgs.system}.nixos
services.nixos-cli.config
Configuration for nixos-cli, in TOML format
Type: tomlFormat.type
Default: {}
services.nixos-cli.generationTag
A description for this generation
Type: types.nullOr types.str
Default: lib.maybeEnv "NIXOS_GENERATION_TAG" null
Example: "Sign Git GPG commits by default"
services.nixos-cli.prebuildOptionCache
Prebuild JSON cache for nixos option
command
Type: types.bool
Default: config.documentation.nixos.enable
Generated with nix-options-doc
FAQ
Do you intend on making this an official NixOS application?
Yes! I will be writing an RFC to see if people are interested in this.
That's my ultimate goal, anyway.
What about nh
? Isn't that better since it supports more OSes?
nh
is a more popular application in this realm, perhaps because it looked
prettier due to the earlier nix-output-monitor
and nvd
integration, and is
significantly older than nixos-cli
.
However, I prefer to keep the focus on NixOS here, while nh
tries to be a
unified rebuild
+ switch
manager for multiple OSes. That's the difference.
nixos-cli
also has more features than nh
for NixOS-based machines, so that's
a plus.
What about home-manager
and nix-darwin
? Will you support those systems?
They are fundamentally separate projects with roughly similar surfaces, so no. I
am a heavy user of both projects, though, so I may write my own darwin
and
hm
CLIs that roughly mirror this.
Think about this:
home-manager
has to work in the user context, while NixOS works in the system one.nix-darwin
doesn't interact with boot scripts, while NixOS does.
Among a slew of other differences. The rebuild
+ switch
workflow may be the
same, but the options are different, and I'm lazy. So no.
Can the option search work with other sources?
It's theoretically possible, as long as the modules can be evaluated with
lib.evalModules
. As such, home-manager
, nix-darwin
, and even flake-parts
are possible to do!
However, this tends to significantly increase evaluation time, and will depend on the system to eval. I plan to break out the option search UI into a separate project that can be more generalized, and add it back to this one as a plugin of sorts.
More questions?
File an issue! Perhaps it's important enough to add to this FAQ as well.
Contributing
Contributions of all kinds are appreciated! The following are especially welcome.
Code Contribution
This is by far the best way to help!
nixos-cli
is quite a large tool with a very large scope and many moving parts,
so any efforts to ease the burden around implementation and maintenance is
greatly appreciated. Even so-called "drive-by" contributions or features are
also appreciated, as long as they do not result in excessive maintenance burden
later on.
Submit contributions through pull requests, or by emailing them personally to
varun@snare.dev
, if you do not want to use GitHub. Credit will be preserved.
Please make sure your code is up to standard by running:
gofmt
to format Go codegolangci-lint
to catch common issuesprettier
to format Markdown files
All available dependencies are provided in a Nix development shell.
If your changes modify the CLI or any core behavior, please also update the
relevant man
pages or documentation in doc/
. This includes changes to the
following things:
- CLI commands/options
- Settings
- NixOS module options
Bug Reports
Testing every feature edge-case is hard—especially before full releases.
If you're a brave soul, use the main branch instead of a release version, and file bug reports by opening a new issue with the Bug Report template. In the bug report, provide:
- A clear description of the problem
- IMPORTANT: What was expected vs. what actually happened
- Steps to reproduce the issue
- Your environment (run
nixos features
) - Any relevant logs, error messages, or images
Clear reports will assist in faster bug fixes!
Improving Documentation
Nix documentation is notoriously patchy — so help here is especially welcome.
As such, documentation quality is of utmost importance. nixos-cli
should be a
tool that is both easy to use and powerful in functionality; however, as
powerful as it can be, who cares if that power isn't discoverable?
Documentation lives in two places:
- Markdown files for this website, generated using
mdbook
- Manual pages (
man
pages), generated usingscdoc
Refer to the code contribution guidelines when submitting documentation improvements, or file an issue if the documentation issues are substantial.
Feature Suggestions
Have an idea for improving NixOS tooling here? Start a discussion or open an issue!
Discourse around how this can be done is always productive.
The vision is to make this a standard NixOS tool, so all ideas that align with that scope are welcome. If there’s a new command or sub-tool you’d like to see, open a GitHub issue or reach out on Matrix. However, try to keep it within scope of the NixOS project, though.
❌ Features like home-manager
or nix-darwin
integration will not be
considered as first-class features. Sorry in advance.
Community Conduct
All contributors must follow a friendly, respectful code of conduct.
The TL;DR? Don't be a dick.
Disagreement is fine, but harassment, rudeness, or discrimination are not tolerated in any spaces.
Roadmap
- ❌ Remote application of configurations
- ❌ Remote installation of NixOS configurations (a la
nixos-anywhere
) - ❌ Ability to remotely manage generations
- ❌ Smart container management (a la
nixos-container
) - ❌ Explicit ability to deploy systems from non-NixOS operating systems
- ❌ Drafting an RFC to make
nixos-cli
the default NixOS management tool
See the Issues section in the GitHub repository for a list of other issues and/or features to be implemented or make your own requests! All requests are welcome.