gunnar-cli
Gunnar's command-line tool, one of Gunnar's three products: gunnar (the server), gunnar-ui (the web console) and gunnar-cli. One program: git with encrypted (quantum-safe) repositories (gunnar-cli clone, push, crypt …) and the control plane of a Gunnar server (gunnar-cli control …).
Install
cargo install gunnar-cli
Or from any Gunnar site: the signed binary its own release build carries, with its sha256, signature and a one-line verify command; open /cli on the site (for example https://www.gunnar.rs/cli). The guide "Gunnar by hand" in the gunnar repository walks through a first server, a passkey, a push, an encrypted repository and a twin.
The default build is AIRGAP: it dials only the server (--at) and the remote a person names. The named extras, each off by default (the same names on all three products):
| feature | what it adds |
public-site |
nothing here (the public site is the console's) |
mcp |
nothing here (the MCP connector is the console's) |
engine-gix |
the gix storage engine, beside znippy, in a --features server build |
online |
gunnar-cli login <console>: the browser device flow over HTTPS |
federation |
online, and control mirror import --from github|codeberg|gitlab… (the other forges) |
full |
all of the above |
The old program names, and what they are now:
| was | is |
gunnar (the git client bin of this crate) |
gunnar-cli: every verb it had, and control. The name gunnar is the server's (cargo install gunnar) |
gunnar-solo |
cargo install gunnar-cli --features server: both halves in one program |
gunnar-service |
cargo install gunnar-cli --features systemd: the server as a systemd service |
gunnar-cli-metered |
still a bin of its own (--features metered): the estate front's tool on a metered estate |
Building with plain cargo
A lone clone of gunnar builds it, with nothing beside it: the root workspace resolves from crates.io (cargo xtask lone-clone proves it).
# the product: git, crypt and the control plane (the package's default)
cargo install --locked --path crates/gunnar-cli
# the git client alone (no control plane): the same program, fewer features
cargo build --release -p gunnar-cli --no-default-features --features client
# core gunnar-server: no UI, no shop, no monetize
cargo build --release -p gunnar-server
# server, client and control in one program
cargo install --locked --path crates/gunnar-cli --features server
The Build Thing cells (.nornir/build-variants.toml, crates/gunnar-recipe) run the same cargo builds from the same code: the gunnar-cli / gunnar-cli-musl cells are exactly -p gunnar-cli --bin gunnar-cli --no-default-features --features client,control (the package's default, named), and every gunnar-server* cell builds -p gunnar-server, with metered (monetize) only on the cells named for it. Guarded by crates/gunnar-recipe/tests/plain_cargo_cells.rs (the cells) and crates/gunnar-cli/tests/plain_cargo.rs (what the builds link: the client's crate ceiling, no server crate in the client, no monetize / UI / shop crate in core gunnar-server).
Size
The git client alone (--no-default-features --features client, release, x86_64 Linux glibc; it was the gunnar bin until 2026-10-30). Packages are distinct name version pairs in cargo tree -e normal --prefix none; the binary as cargo leaves it (strip = "debuginfo") and fully stripped (strip).
| packages | binary | stripped | |
before, 2026-10-12 (df17b29e) |
442 | 25 070 552 B | 19 820 304 B |
| after the cut, 2026-10-12 | 389 | 19 920 040 B | 15 924 376 B |
What the cut removed: nornir-git asked for gix with gix's default features (blame, merge, notes, mailmap, worktree-archive, revparse-regex, dirwalk …) and with the blocking-http-transport-reqwest-rust-tls transport — reqwest, hyper, h2, rustls, tokio-rustls, rustls-platform-verifier and their tails. The client reaches neither: every http(s):// remote is rewritten to SSH before a fetch (nornir_git::gitio::clone_or_fetch), and the client's git is SSH over russh. nornir-git now names exactly the gix features its code calls under porcelain, and carries the rest as the https and gix-defaults features, both in its default so its other consumers are unchanged; gunnar takes it with default-features = false.
What stays, and why: age (with ssh + armor: the key ring wrapped to members' SSH keys) brings its own i18n (fluent) and the older RustCrypto generation, so aes/cipher/sha2… appear twice beside russh's; hpke + x-wing are the quantum-safe members; russh brings aws-lc-rs (the one crypto backend) and the p256/p384/p521/rsa key types SSH servers present. The ceiling in tests/plain_cargo.rs is 395; raise it only with a new row here.
Part of Gunnar, a git server and git client. Source: https://www.gunnar.rs/repo/gunnar/gunnar.
License: AGPL-3.0-only, or a commercial licence granted jointly by Ignalina ApS and Vetra Automation AB (gunnar@gunnar.rs).