Content-addressed
Every payload is named by its SHA-256. Pull re-hashes on arrival; a mismatch is exit code 3, not a warning you scroll past.
anvil pushes a file under a name and version, writes a signed manifest next to it, and later verifies that what it hands back is byte-for-byte what you pushed. The client and the server are the same executable; anvil serve is the registry. That is the whole idea.
$ anvil push io.byteanvil.gateway@2.4.1 ./build/gateway --channel release pushed io.byteanvil.gateway@2.4.1 sha256:9f2c4e71b0a8c35d… 18446120 bytes signed with key 7c1d9a (trusted since 2026-02-11) $ anvil verify io.byteanvil.gateway@2.4.1 digest ok · signature ok · key trusted → exit 0
Every payload is named by its SHA-256. Pull re-hashes on arrival; a mismatch is exit code 3, not a warning you scroll past.
Each artifact carries an Ed25519 detached signature over the canonical manifest.json. Trust is a list of key ids you maintain; an untrusted key is exit 4.
dev, staging, release - a fixed set. Promotion copies metadata, never the payload, so a promoted build keeps its original digest.
Policies are per-channel. Run anvil prune --dry-run or the simulator on this site before anything is deleted.
There is no installer and no package to register. Drop the binary on PATH, point it at a store directory, and start the registry on port 8711:
curl -O https://byteanvil.info/anvil && chmod +x anvil # or: make ./anvil serve --store /srv/artifacts --listen :8711
Build from source if you prefer - it needs a C11 compiler and make, nothing else. The install page lists the exit you should see and the two environment variables worth setting.