A personal vault for secrets (API keys, tokens, passwords, recovery codes, whatever) that's safe to keep in a public or private git repo synced to GitHub, because nothing sensitive is ever stored in cleartext.
Read SECRETS.md for how it works and the threat model. TL;DR:
- SOPS + age.
Values are encrypted; item names, notes, and dates stay cleartext so
git log/git diffare actually readable. - The encrypted vault (
secrets/vault.sops.yaml) is meant to be committed. The age private key that decrypts it is not — it lives only on your machine(s), never in git. - Every commit to the vault is a version.
scripts/secrets.py history/diff/rollbackwalk that history. - A pre-commit hook blocks the ways this could go wrong (staging a raw key file, staging a plaintext export, or accidentally committing the vault file with its encryption stripped off).
# one-time per clone
git config core.hooksPath .githooks
# first time ever
./scripts/secrets.py init # generates your age key, wires up .sops.yaml
# -> BACK UP THE PRINTED KEY PATH SOMEWHERE SAFE
./scripts/secrets.py set github_pat --notes "read:repo, created 2026-09-03"
./scripts/secrets.py get github_pat
./scripts/secrets.py list
./scripts/secrets.py rm github_pat
git add secrets/*.sops.yaml
git commit -m "add github_pat"
git pushEvery set/rm, once committed, is a version. To look at that history:
./scripts/secrets.py history github_pat # every value change, when, and why
./scripts/secrets.py diff <rev1> <rev2> # what changed vault-wide between two commits
./scripts/secrets.py rollback github_pat <rev> # restore an old value into the current vaultFull command reference: ./scripts/secrets.py -h, or -h on any subcommand.