How can we pass argument to flake.nix?

$ nix build --arg cl true
error: '--arg' and '--argstr' are incompatible with flakes
Try 'nix --help' for more information.
$ nix build --argstr cl true
error: '--arg' and '--argstr' are incompatible with flakes
Try 'nix --help' for more information.

For example, how can we pass arguments to a flake.nix to change its build behaviour?

1 Like

Oh, I notice

Currently, flakes are evaluated in pure mode and have no function arguments (other than the computed set of flake dependencies), so it’s not possible to do things like:

Use builtins.currentSystem.
Access ~/.config/nixpkgs/{config.nix,overlays}.
Access command line arguments passed via --arg.

It cannot be done, right?

Some discussion can be seen in

1 Like

Yeah, I don’t think that nix is able to take arguments right now. Bat people have been (ab)using the system to encode arguments in the name of the package, like in mach-nix that allows a syntax like:

nix (build|shell) mach-nix#gen.(python|docker).package1.package2...

Depending on your use case it might be enough. So you could for instance create a package mypackage, a package mypackage.arg1.true, a package mypackage.arg1.false, a package mypackage.arg2.2 etc… and I guess this can be done automatically to avoid copy/pasting the expression (I’m sure that mach nix does not create exponentially many expressions manually).


Not what you are asking but in case helpful, a way I personally use to allow having options in my local flakes which is similar to having arguments, is to check for the existence of files. For example, I have expressions of the type:

let has_foo = builtins.pathExists ./config/foo;
in {
  imports = [] ++ (lib.optional has_foo ./foo.nix);

Then I use .gitignore to ignore the config directory. Because the files are ignored by git, to build this flake I have to run commands passing path:, like: sudo nixos-rebuild switch --flake path:$(pwd) or nix build path:$(pwd).

This allows also to read the file and compare it if more granular options are needed. It works because when running with path:$(pwd), the whole directory path is included in the flake, not only the files tracked by git.