
@vaultry/claude-secrets
Encrypted token store for Claude Code sessions and your shell/apps.
macOS Keychain backed · MCP server · CLI · .env placeholder expansion.
Stop pasting tokens into every new Claude session. Store them once, reference them everywhere — including commit-safe
.envfiles.
Quick install (one line)
curl -fsSL https://raw.githubusercontent.com/vaultry/claude-secrets/main/install.sh | bash
Or via npm:
npm install -g @vaultry/claude-secrets
claude-secrets-setup
claude mcp add claude-secrets --scope user -- claude-secrets-mcp
Three interfaces
| Interface | Who uses it | Policy-gated |
|---|---|---|
| MCP server | Claude Code sessions | Yes (per-project allowlist) |
CLI claude-secrets |
Your shell, apps, scripts | No (user has Keychain access) |
.env placeholders |
Any tool that reads .env | Via CLI |
Store secrets

Pipe from stdin (keeps the value out of shell history):
echo "ghp_xxxxx" | claude-secrets set GITHUB_TOKEN
op read "op://Private/Gitea/token" | claude-secrets set GITEA_TOKEN
claude-secrets set DB_PASSWORD # interactive — type, Ctrl-D
Encrypted with AES-256-GCM, master key stored in macOS Keychain (syncs between Macs via iCloud Keychain).
Commit-safe .env files

Replace real values with secret://NAME references. The .env file can now be committed to git safely — it contains only names, no credentials.
# .env
API_KEY=secret://GITHUB_TOKEN
DB_URL=postgres://app:secret://DB_PASSWORD@db.local/app
PORT=3000
Placeholder syntax: secret://NAME — URI-style, avoids bash parameter-expansion collisions. Names can contain A-Z, 0-9, _, ., -.
Expand placeholders

Resolve placeholders to real values at runtime:
eval "$(claude-secrets export)" # into current shell
claude-secrets export --format json > resolved.json
claude-secrets export --format dotenv > .env.resolved
claude-secrets export --file .env.staging # different file
claude-secrets export --on-missing empty # empty for missing refs
--on-missing |
Behavior |
|---|---|
throw (default) |
Exit 1 with list of missing names |
empty |
Placeholder becomes empty string |
keep |
Placeholder left literal (secret://NAME) |
Run a command with secrets

claude-secrets exec -- pnpm dev # inject then run
claude-secrets exec -- node build.js
claude-secrets exec --file .env.prod -- npm run deploy
Secrets live only in the child process — not in the parent shell's environment, history, or ps output.
package.json scripts work seamlessly:
{
"scripts": {
"dev": "claude-secrets exec -- ts-node src/index.ts",
"test": "claude-secrets exec --file .env.test -- vitest",
"deploy": "claude-secrets exec --file .env.prod -- node deploy.js"
}
}
MCP server (for Claude Code)
After registering with claude mcp add, Claude Code gets 6 tools under mcp__claude-secrets__*:
| Tool | Policy