cvault
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@cvaultrun the migrations with the database credentials"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π cvault
A local, encrypted, multi-tenant password manager for Claude Code. Claude can use your credentials (run commands, write .env files, call APIs) without the values ever entering the chat, and you get a fast terminal UI to browse, copy and edit them.
tenant (client / workspace)
ββ environment (optional) develop Β· staging Β· prod β¦
ββ project β linked to a directory on disk
ββ service (postgres, stripe, admin-panel, β¦)
ββ item secret Β· credential (multi-field) Β· file
ββ role + default ("log in as admin")
ββ versions v1, v2, β¦ (never deleted)
path: tenant/env/project/service/key e.g. rezilens/staging/digrc-api/admin-panel/systemadminFor Claude (MCP server)
Uses secrets without seeing them: output is scrubbed to
***Sealed mode: you type or receive values in a native macOS dialog or on the clipboard
Knows the current project's credentials at session start (hook)
Picks the right credential by role, or falls back to the default
For you (CLI + interactive UI)
cvault: arrow-key explorer with tables, search, copy, editEvery change is a new version; roll back any time
Archive instead of delete, restorable at any level
Full audit log of every access
Contents
Concepts: refs & environments Β· roles & defaults Β· versioning Β· archive Β· export & import Β· directory linking
Related MCP server: SecureCode
Quick start
git clone <this repo> ~/mcp/vault-mcp && cd ~/mcp/vault-mcp
npm install && npm run build
npm link # puts `cvault` on your PATH
# 1. store a random master password in the macOS Keychain and create the vault
security add-generic-password -a "$USER" -s vault-mcp -w "$(openssl rand -base64 33)"
export VAULT_MASTER_PASSWORD_CMD='security find-generic-password -s vault-mcp -w' # add to ~/.zshrc
cvault init
# 2. register the MCP server with Claude Code (user scope = every project)
claude mcp add cvault -s user \
-e VAULT_MASTER_PASSWORD_CMD='security find-generic-password -s vault-mcp -w' \
-- "$(which node)" ~/mcp/vault-mcp/dist/index.js
# 3. (recommended) SessionStart hook, so Claude knows each project's credentials
# add to ~/.claude/settings.json β hooks.SessionStart:
# { "hooks": [{ "type": "command", "timeout": 10,
# "command": "node ~/mcp/vault-mcp/dist/cli.js hook session-start" }] }
# 4. add your first project, linked to its directory
cvault project add acme/api --bind ~/work/acme-api
cvault set-cred acme/staging/api/admin-panel/superadmin -u root --role admin --default # password prompted, hiddenThe vault lives in
~/.vault-mcp/(override withVAULT_HOME). The master password never leaves the Keychain.
How Claude uses it
Start Claude inside a linked directory and the session hook tells it which items exist (names only, never values):
CVAULT: this working directory is bound to vault project "acme/api"
Available items (names only, no values):
- admin-panel/superadmin (credential; role: admin; DEFAULT; fields: username, password, url)
- admin-panel/auditor (credential; role: viewer; fields: username, password)
- stripe/api_key (secret; "Stripe live key")Then just ask:
You say | Claude does | Claude sees |
"run the migrations with the DB creds" |
| command output with |
"create the .env for this project" |
| the list of keys written |
"list Stripe customers" |
| the response, scrubbed |
"log into the admin panel as viewer" | picks | nothing secret |
"log into the staging panel" (no credential stored yet) | automatically calls |
|
"save the OpenAI key sealed" |
|
|
"give me the DB password sealed" |
|
|
Interactive explorer
Run cvault with no arguments (or cvault ui). cvault --help lists the scriptable commands.
cvault 5 items in 1 project Β· ~/.vault-mcp
home βΊ acme βΊ api
ββββββββββββββββββββββββββββββββββββββββββββββββ Esc back/cancel Β· Ctrl+C quit ββ
? Pick an item
SERVICE β KEY β TYPE β ROLE β DEFAULT β FIELDS / FILE β VER β DESCRIPTION
βββββββββββββΌβββββββββββββΌβββββββββββββΌβββββββββΌββββββββββΌββββββββββββββββββββββββββΌββββββΌββββββββββββββββ
β― admin-panel β auditor β credential β viewer β - β username, password β v1 β Read-only
admin-panel β superadmin β credential β admin β yes β username, password, url β v2 β Full access
ssh β deploy-key β file β - β - β deploy.pem (412 B) β v1 β CI deploy key
stripe β api_key β secret β - β - β - β v3 β Stripe live key
ββ Actions ββββββββββββββββββββββ
+ New itemβ¦
Servicesβ¦Navigate: opens at the project linked to your current directory; search across all items by ref, role or description.
Copy any secret or credential field. The clipboard auto-clears after 30s, even if you've already quit.
Export: an encrypted bundle,
.envor JSON for a project or the whole vault.View all fields, version history and the audit log as tables.
Edit values and fields, add or remove fields, replace files. Each change saves a new version.
Labels: role, default and description, without creating a new version.
Manage: create tenants, projects, services and items; link directories; toggle Claude reveal; archive and restore; roll back; export a project or the whole vault.
Keys:
ββmove Β·βselect Β·Escback / cancel the current action Β·Ctrl+Cquit.Responsive: tables drop low-priority columns on narrow terminals.
CLI reference
Command | What it does |
| interactive explorer |
| create the vault |
| tables of projects, services and all items (scope: |
| create a project, optionally linked to a directory |
| link or unlink a directory (optionally with a default environment) |
| allow Claude to read plaintext ( |
| create or update a service, and restrict where its secrets may be sent |
| rename a service or move it into or out of an environment |
| unlock a credential locked after a 401 or a blocked use |
| allow Claude to store values it received in chat (off by default) |
| store a secret (hidden prompt) |
| store a credential (password prompted, hidden) |
| encrypt a file into the vault |
| print a value (credentials as a table) |
| set labels, no new version |
| history and roll back |
| archive or restore a tenant, project, service or item |
| bulk-import a |
| export a tenant, project, service or everything (details) |
| restore an encrypted bundle (existing items get a new version) |
| preview what the session hook injects |
| access log |
| maintenance |
MCP tools
Group | Tools |
Browse (no values) |
|
Use (values hidden) |
|
Sealed (you β vault) |
|
Manage |
|
Versions & archive |
|
Reveal (opt-in) |
|
Concepts
Refs & environments
tenant/[env/]project/service/key[@version][#field]
Form | Example |
with environment (5 levels) |
|
without environment (4 levels) |
|
inside a linked directory |
|
The environment is optional. The same service name can exist once per environment (
staging/admin-panel,develop/admin-panel), each with its own items, versions and allowed hosts.A directory link can carry a default environment:
cvault project bind acme/api --env staging. Thenadmin-panel/rootmeans staging.Listing and export scopes accept
acme/staging(everything in staging),acme/staging/apioracme/api(all environments).cvault service-move acme/api/staging-panel acme/staging/api/panelmoves an existing service into an environment (items, versions and hosts move with it).Credentials default to the
passwordfield.
Missing credentials
When a task needs a login that isn't in the vault, the session hook, server instructions and "not found" errors all point Claude at request_credential. It opens native dialogs:
Path: pre-filled with Claude's suggestion and editable. Paths are corrected automatically, with no second dialog. Project and environment typed in the wrong order (
rezilens/digrc-api-service/develop/admin-panel/systemadmin) becomerezilens/develop/digrc-api-service/admin-panel/systemadmin; extra levels fold into the service name; messy characters are cleaned. It only asks again when the intent can't be worked out.Fields: username (visible), password (hidden), plus any extra fields Claude asks for. Masked fields (password, token, secret, key, pin, otp) are asked twice, and a mismatch asks again, so a typo can't be saved silently. For an existing item, leaving a field empty keeps its current value, and a new version is saved.
If a login is rejected, Claude is told to stop after one attempt (accounts often lock after a few), never to try another environment's credential, and to offer request_credential on the same path to re-enter it.
Claude only receives the resulting ref.
Enforced rules (code, not instructions)
The server enforces these itself, so Claude can't skip them:
Rule | How it's enforced |
Missing secret β ask the user | Before |
Allowed hosts per service |
|
Lock after a rejected login | An HTTP 401 from |
Use budget | After 5 uses of a password/token field within 10 minutes (any tool, including clipboard fills), a dialog asks Allow / Block. Allow gives 30 more minutes; Block locks the credential. Usernames don't count. |
No values through chat |
|
Roles & defaults
Give credentials a role (admin, viewer, tester, β¦) and mark one per service as the default. "Log in as viewer" picks the viewer item; with no role named, Claude uses the default and only asks when neither applies.
Versioning
Every write creates version N+1. Old versions stay encrypted (and old files are kept as <uid>.vN.bin). @N reads any version; rollback copies an old version forward as a new version, so history is never rewritten.
Archive, never delete
Archive a tenant, project, service or single item. It's hidden and unusable but fully restorable. Archiving a tenant hides everything under it.
Export & import
Format | Encrypted? | Contents | Typical use |
| β passphrase β scrypt β AES-256-GCM | every item incl. files, roles, defaults, descriptions | backups, moving to another machine, handing a project to a teammate |
| β plaintext |
| seeding a |
| β plaintext | nested | scripts and other tools |
cvault export acme/api # β cvault-acme-api.cvault (asks for a passphrase)
cvault import-bundle cvault-acme-api.cvault # on the other machine
cvault import-bundle backup.cvault --into acme-staging/api # remap tenant/project
cvault export acme/api/stripe -f env --yes --stdout # STRIPE keys as KEY=value.env names are built from the path below the export scope: exporting a project gives STRIPE_API_KEY and ADMIN_PANEL_SUPERADMIN_PASSWORD, while exporting one service gives API_KEY and SUPERADMIN_PASSWORD. Name clashes are an error, never a silent overwrite. Plaintext exports need confirmation (--yes in scripts), are written with mode 600, and are refused inside a git repo unless the file is gitignored. For scripts, set the bundle passphrase with CVAULT_BUNDLE_PASSPHRASE. Export is deliberately not an MCP tool, so Claude can't dump the vault. In the explorer: Export⦠on the home page and on each project page.
Directory linking
cvault project bind links a directory (and its subdirectories; the most specific link wins) to a project. This drives short refs, the explorer's start page and the SessionStart hook.
Security model
Crypto: master password β scrypt (N=2ΒΉβ·) β key-encryption key, which wraps a random 256-bit data key. Every value and file is encrypted with AES-256-GCM, with the item's UUID as additional authenticated data. Metadata (names, roles, bindings) is stored unencrypted, so the session hook needs no password.
Master password comes from the macOS Keychain via
VAULT_MASTER_PASSWORD_CMD, and is removed from the server's environment at startup so child processes never inherit it.Claude never sees values by default. Injected secrets are scrubbed (raw, base64 and URL-encoded) from command and HTTP output.
reveal_secretis off per project, and only the CLI can turn it on.Sealed mode: values travel through native macOS dialogs or the clipboard, never through tool arguments or results. They're passed to
osascriptvia env, not argv.Guardrails:
.envand file writes into a git repo are refused unless the file is gitignored, and files are written with mode 0600.Audit log of every use, reveal, copy and edit. It never records values.
Limit: scrubbing keeps secrets out of the conversation and transcripts. It is not a sandbox, so a command can still misuse an injected secret on purpose. Review commands that come from untrusted content.
Development
npm run build # tsc β dist/
npm test # vitest (crypto, versioning, archive, roles, export/import, injection, scrubbing)
npx @modelcontextprotocol/inspector node dist/index.jssrc/
index.ts MCP server (tools, sealed mode, reveal gate)
cli.ts cvault CLI + SessionStart hook
ui.ts interactive explorer
store.ts vault: hierarchy, versioned items, archive, roles, audit
crypto.ts scrypt + AES-256-GCM
inject.ts run / .env / file / http injection + scrubbing
sealed.ts macOS dialogs + clipboard with auto-clear
export.ts encrypted bundles, .env / JSON export, bundle import
enforce.ts server-side rules: auto-prompt, allowed hosts, use budget, 401 lock
policy.ts host matching / extraction, budget constants
table.ts table rendering
db.ts SQLite schema + migrationsLicense
MIT Β© 2026 shahroz Dhillon
This server cannot be deployed
Maintenance
Related MCP Connectors
Secrets for developers and agentsβsecure context and workflows without exposing secret values.
Encrypted secret store and rotation for autonomous agent credentials
Encrypted store for API keys and database URLs your code needs. Use them without reading them.
- FullmaktOAuthai.fullmakt
Credential broker for AI agents: scoped, revocable API access with policy enforcement and audit.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA secure secrets management server that enables LLMs to execute CLI commands using injected credentials while protecting sensitive data through output redaction and user-approved session permissions. It features an encrypted vault, secret capture from command outputs, and a macOS menu bar app for native notifications and dialogs.MIT
- AlicenseAqualityDmaintenanceSecrets vault for Claude Code. Encrypt API keys, tokens and passwords with AES-256. Full audit logs, MCP access rules, and zero-knowledge mode. Secrets never appear in chat.1753 npm1MIT
- AlicenseAqualityAmaintenanceA cross-platform secrets manager that stores named credential sets in the system keychain and injects them as environment variables, enabling secure secret management for AI coding assistants and CLI tools.5MIT
- FlicenseNot gradedqualityBmaintenanceEnables agents to securely use credentials for GitHub, Cloudflare, OpenAI, Stripe, and xAI without ever reading the secret values, including credential health, rotation, and audit features.-