Secrets you decrypt locally, rotate from your shell, audit on the same wire.
A zero-knowledge config vault and a small Go CLI. The server stores ciphertext; your CLI does the rest.
$ go install github.com/adamori/granith/cmd/granith@latest
$ export GRANITH_SERVER=https://api.granith.dev
$ export GRANITH_TOKEN=grnth_kQ8…7P.4xVm…Yz
$ granith run -- node server.js
▸ fetched bundle · 3 secrets · 142 bytes · etag d4f1…
▸ decrypted in 11ms · running command
listening on :3000 The CLI fetched a ciphertext bundle, unwrapped the project key locally with the token, decrypted in process memory, and exec'd your command with the values as env vars. The server returned bytes; it never held a key that could read them.
$ curl -sI -H 'if-none-match: "d4f1…"' \
-H "authorization: bearer $GRANITH_TOKEN" \
https://api.granith.dev/api/v1/bundle
HTTP/2 304 One row per bundle fetch. No secret names, no values, no labels. Enough to spot a stolen token; not enough to leak which secret your process touches when.
{
"ts": "2026-05-15T09:42:11Z",
"actor_id": "tok_d8e2…",
"action": "bundle.fetch",
"ip": "203.0.113.42",
"user_agent": "granith-go/1.0.0"
} Open registration, free forever, single-user.
No invite, no card, no trial that runs out. Anyone can register and it stays free. Still single-user — one account, no teams, no shared vaults.
One limit: 1 MB of encrypted storage — roughly a thousand typical secrets. Need more? Tell me what you're building on Telegram @paneelmaja or at [email protected] and it's raised — free.