v0.7.1 · macOS + Windows + Linux · MIT
a cross-platform secrets manager AI agents architecturally cannot leak from.
Stores keys in the macOS Keychain, Windows Credential Manager, or Linux Secret Service — with an encrypted-file fallback on headless servers. Ships with a Claude Code plugin that lets agents put secrets into your files without ever seeing the value. Free, open source, auto-updating install.
claude.ai/code
demo · 30 s · placeholder
the diff
the leak vs the fix
The leak isn't where the key is stored — it's where the agent can see it. Storage vaults like 1Password CLI / doppler / vault all make the value flow through the agent's context window the moment you ask for it. keys-keeper gives the agent a different verb.
.env directly. The transcript holds only the operation. The value lives in the macOS Keychain (Touch-ID protected) or Windows Credential Manager (DPAPI-bound) and in the file you wanted it in. Nowhere else.
the design
command surface, by design
The split is structural, not a convention. The shipped Claude skill markdown enumerates exactly which commands the agent may use. The one command that prints plaintext to stdout — keys reveal — refuses to run unless an explicit env-var is set, which the skill never sets and the agent has no path to set. The structural guard fires before any prose can override it.
keys add NAME --from-clipboard / --from-file / --stdin
keys list / info / audit
keys copy NAME
pbcopy; auto-clears in 30 s with SHA-256 check so it doesn't wipe unrelated content.keys inject NAME --file F --as ENV
ENV=value to the file. The CLI writes; the agent never sees.keys resolve PATH
__KEYS:name__ placeholders in-place. Works on .env.template, deploy scripts, anything text.keys ssh NAME
ssh -i <tempfile>, shreds the tempfile on exit.keys reveal NAME
KEYS_KEEPER_ALLOW_REVEAL=1 is in env. Most users never set it; agents have no path to set it. This is the structural guard that fires before any prose can override it.The shipped skill markdown tells Claude: "You MUST NOT runkeys reveal. You CAN usekeys copy / inject / resolve / ssh." The env-var gate makes that instruction structural. Even if the agent tried, the CLI itself refuses.
and a local admin
so you can browse 50+ keys without losing your mind
Run keys serve and a localhost-only admin opens at 127.0.0.1:7777. Token in the URL, stripped via history.replaceState, then a session cookie. No cloud, no account, no telemetry. Five screens, terminal-density.
/paste Bulk import
SOURCE
PREVIEW · 4 entries · 0 errors
top entries · last 7 d
daily activity · last 30 d
Settings
how it fits together
two-layer storage. one process. zero network.
Secrets live in your OS credential store — macOS Keychain (Touch-ID protected) or Windows Credential Manager (DPAPI-bound to your login). Metadata (names, tags, refs, audit log) lives in ~/.config/keys-keeper/ or %APPDATA%\keys-keeper\ as boring JSON you can back up or diff. The CLI mediates both. The admin is the same process exposing localhost HTTP.
install in 2 minutes
two lines in Claude Code. auto-updates.
The Claude Code plugin is the recommended path — adds the skill and a SessionStart hook that pulls new releases via claude plugin update automatically. The CLI itself installs via pipx. For Cursor, Aider, Codex CLI, or Cline — one keys init <target> emits the matching rule file.
Run these as two separate slash commands in Claude Code — paste step 1, press Enter, then paste step 2. (Claude Code runs one slash command at a time.)
/plugin marketplace add kyzdes/claude-skills
/plugin install keys-keeper@claude-skills
git clone https://github.com/kyzdes/keys-keeper-skill.git cd keys-keeper-skill pipx install .
// after pipx install, run inside your project: keys init cursor # .cursor/rules/keys-keeper.mdc keys init aider # CONVENTIONS.md (then `aider --read CONVENTIONS.md`) keys init codex # AGENTS.md (also read by Cursor / Amp / Jules) keys init cline # .clinerules/00-keys-keeper.md keys init generic # prints to stdout — pipe wherever your agent reads rules
requires Python 3.10+ on macOS, Windows, or Linux. On a headless Linux server set KEYS_KEEPER_MASTER_KEY for the encrypted-file backend.
brew install pipx && pipx ensurepath. Windows: python -m pip install --user pipx && python -m pipx ensurepath — one line, restart your shell.
roadmap
open source · accepting PRs
Owner is one developer with a day job. The list below is what's planned but not yet shipped — pull-request bingo welcome.
- MCP stdio server (
keys mcp) — typed-tool surface for any MCP-compatible client (Cursor / Cline / Codex have native MCP) - Touch-ID-gated reveal in admin with auto-wipe from DOM after 10 s
- CSV export from /audit (already CLI-only via
keys audit > file.csv) - Bulk-paste parser extension for ssh_key / server / domain (currently clean only for api_key)
- Light theme polish — CSS tokens exist; not all surfaces tested
- Cmd+K action palette beyond navigation — "copy openrouter" as a one-shot
PRs welcome. Start at github.com/kyzdes/keys-keeper-skill/issues — or just open one with the rough idea.
now shipping
what landed since v0.5.
Two things that used to be on this list moved off it. Both are end-to-end encrypted and stay true to the architecture — the server never sees a plaintext secret.
cloud sync
S3-compatible backup and sync across machines — AWS S3, Cloudflare R2, Backblaze B2, or self-hosted MinIO. End-to-end encrypted as one AES-256-GCM blob; the bucket only ever holds ciphertext. keys sync setup.
zero-knowledge web vault
Open your vault in a browser from a host you run yourself. The page decrypts in-memory in the browser; the server never sees plaintext. keys webvault serve (read-only v1).
honest limitations
what v0.7.1 is not.
If any of these is a dealbreaker, that's fine — none of them are theoretically hard, they're just not done yet. Tracking on the roadmap above.
headless Linux needs a master key
Desktop Linux uses the OS keyring via secret-tool. A headless server has no keyring daemon, so the encrypted-file backend needs KEYS_KEEPER_MASTER_KEY in the environment to unlock.
single user
No team / multi-user / sharing. This is a personal tool.
bulk paste = api_key
Other types via + New form in the admin for now.
caller_path is best-effort
From ps -o command=. Forensics-level, not court evidence.
threat model
what this defends against. and what it doesn't.
If you're considering keys-keeper, you should know the boundaries. Vague claims help no one — here's the explicit shape of the protection.
defends against
AI agents extracting plaintext into transcripts (the original motivation), accidental git add of .env files, plaintext clipboard residue past the auto-clear window, ad-hoc shell scripts that need a key without you retyping it.
does not defend against
A root-level adversary on your Mac, malware with full keychain access, screen-recording on a compromised host, or network attackers (the admin is localhost-only and never reachable from outside the loopback interface anyway).