etwa-cli

Crates.ioetwa-cli
lib.rsetwa-cli
version0.1.0
created_at2026-01-25 12:57:35.955036+00
updated_at2026-01-25 12:57:35.955036+00
descriptionConvenience wrapper for Nix CLI to improve non-flake experience
homepage
repositoryhttps://codeberg.org/psentee/etwa
max_upload_size
id2068682
size37,192
(psentee)

documentation

README

etwa-cli

This project is a wrapper for nix CLI1 that makes working with non-flakes projects easier, or at least faster. It is a personal project with alpha quality. It works for me, might not work for you, no promises (yet) about keeping the interface stable. Also, this prototype doesn't even have unit tests yet.

The problem it solves is when you run nix build -f ./nilla.nix …, Lix runs in your local directory. Then, if something uses something like src = ./., it copies the entire thing to the Nix store. With .git/. With your personal config file and your editor's backup files. With Node's node_modules/ or Rust's target/. With whatever junk is in .direnv/. And so on, and so on. It takes time. It's also always impure, so there's risk that your code will break if another project tries to (purely) import it.

The etwa CLI does something similar to Nix flakes: it takes the -f/--file flag, and:

  • Finds root of the Git repository containing the provided path
  • Imports Git-tracked files in that repository, as they exist in your working tree---with all local modifications, including --intent-to-added files, processed with git-lfs and other filters (including git-crypt and such, beware!), should even include submodules)
  • Rewrites the -f entrypoint to point Nix at the clean, lightweight copy

Most of the time you should be able to type etwa instead of nix and it will do the same but faster and with pure evaluation.

Usage info

Below is what etwa --help shows. I'll try to keep this README up to date with reality, but please run --help yourself to double check.

Usage: etwa [ETWA_FLAGS] NIX_SUBCOMMAND NIX_ARGS...

Just run `etwa` like you're running `nix`. One
difference: no nix flags before the command. Flags
before the command are etwa's (see below).

ETWA FLAGS:

-h, --help
    Show this help text
-v, --verbose / -q, --quiet
    More/less logs (can be repeated for even more/less logs)
-N NIX, --nix NIX
    Overrides `nix` command invoked at the end. The
    `nix` command used for plumbing (`nix eval`) is
    not affected. For example, to build something with
    nix-output-monitor, run:
      etwa -N nom build -f ./nilla.nix ...
--import
    Don't run `nix`, only print imported root & entrypoint as JSON
--import-root, --import-entrypoint
    Don't run `nix`, only print imported root or entrypoint store path
-n, --dry-run
    Don't run `nix`, only print what would run

Usage with nix-output-monitor

You can use -N flag to override the final nix command (without affecting nix that runs as plumbing). For example, to use nix-output-monitor, run:

etwa -N nom build -f ./nilla.nix ...

Usage with nix-direnv

Nix-direnv is not immune to the "import everything and the kitchen sink to the Nix store" problem. Unfortunately it doesn't allow you to easily override path to nix (you can set NIX_DIRENV_FALLBACK_NIX but it will still prefer nix it finds on $PATH). The following .envrc snippet works (as of nix-direnv version 3.1.0) by overwriting nix-direnv's internal function:

if command -v etwa >/dev/null 2>&1 ; then
    echo "Found etwa-cli, overriding _nix"
    _nix () {
        etwa "$@"
    }
fi

Future steps

  • Clean up the prototype code and add some test cases
  • Add more convenience on top of what we have (injecting current system into installable attribute path? NixOS & home-manager support? Nilla conveniences? Configuration?)

Limitations

  • only UTF-8 paths are supported
  • no funny stuff with symlinks
  • no nix flags before subcommand

Temporary limitations (hopefully will be solved in future)

  • only git projects are supported

Footnotes

  1. Lix, to be specific. It probably works with cppnix but I don't care and won't check.

Commit count: 250

cargo fmt