Nix-run: run nix derivations without nix3 or flakes

I don’t use flakes or nix3-command, so it was always a bit uncomfortable to repeat the package name twice when writing nix-shell -p name --run “name args”, which also doesn’t support properly running derivations from remotes/local directories, since it would instead create a dev shell for the derivation.

The solution is to write a wrapper that uses nix-instantiate to extract meta.mainProgram and then nix-build to build the derivation, the output of which could afterwards be ran.

The important part here is to not use expressions since it breaks building remote tarballs, which is supported by nix-build by default (as in you can do nix-build "https://github.com/nixos/nixpkgs/archive/refs/heads/master.tar.gz" -A hello). To replicate lib.getExe, you also need to parse the derivation to get the bin output if it exists, and thanks to the @Gabriella439‘s nix-derivation library it is possible to do so.

Basically, anything that can be nix-build-t can be nix-run-ed, even if you don’t have a meta.mainProgram you can manually specify -B/--binary instead.

There’s also a special case for <nixpkgs>, so instead of writing nix-run "<nixpkgs>" -A something you can just write nix-run -p something

It’s in nixpkgs-unstable, just add it to your configuration.nix or use via nix-shell -p nix-run

The small disadvantage compared to nix run is the need to write -- before the program arguments since I wasn’t exactly able to imitate the nix argument parsing 1 to 1, but it is supported:

$ nix-run -p stress-ng -- \
        --cpu 12 \
        --vm 8 \
        --vm-bytes 240% \
        --timeout 5m \
        --page-in
22 Likes

nice, thanks!

i previously had a barebones version using fetchTree documented as an alternative to nix run, and now opened a PR to mention nix-run as well.

(nitpick: i kinda like tree references’ terser syntax better than https://github.com/nixos/nixpkgs/archive/refs/heads/master.tar.gz :see_no_evil_monkey:, while they also seem able to handle the remote fetches.)

ideally tho, i hope we could get a command like this built-in, so libraries would feel more comfortable documenting remote invocation using it.

1 Like

Fetch-tree is experimental AFAIK, so there isn’t much of an advantage to using it over just using nix3-command

right, my goal wasn’t so much to avoid any use of experimental features: i consider fetchTree boring enough that i wouldn’t mind dealing with it even if something changes in the future.

rather, with -f default.nix, for non-flake use i think the v3 cli offers only second-class UX without the built-in fetch-tree references, to a point where i’m not sure what value it adds when one can do without - i.e. when you need neither flakes’ evaluation caching, their outputs schema, nor dependency management using its inputs over alternatives.

2 Likes
nix-run -p bluetui                                                                    nix-shell-env 
error: unrecognised flag '--raw'
Try 'nix-instantiate --help' for more information.
readCreateProcess: nix-instantiate "<nixpkgs>" "--eval" "--raw" "-A" "bluetui.meta.mainProgram" "--read-write-mode" (exit 1): failed

Does this require a newer version of nixos? I’m on nixos 25.11 and got it from unstable.

1 Like

Not NixOS but CppNix 2.26 IIRC or Lix 2.94

2 Likes

Can this be used to run a custom command in a local default.nix, eg. by defining an attribute with writeScriptBin?

Yes, absolutely, nix-run uses local default.nix by default, same as nix-build

Nice. It would make it a bit cleaner in CI workflows if it was part of the nixos/nix container or an alternative one. Currently my strategy is to define a minimal shell just for CI and then call it with nix-shell -A … –run “…” in places where it doesn’t make sense to define a derivation for the output, eg using static site generators.