Your AI agents work. Your secrets stay home.
Local-first, open-source credential vault that lets AI agents authenticate and use API keys without ever seeing the plaintext secret. Uses the "wisp token" pattern: agents receive opaque placeholders, a local proxy swaps them for real credentials at the network boundary.
# Install (once published)
brew install wispkey
# -- or --
cargo install wispkey
# Create your vault
wispkey init
# Import existing .env credentials
wispkey import .env
# Start the proxy
wispkey serveFour commands from zero to protected. The AI process never touches your real secrets.
[AI Agent] --> "Authorization: Bearer wk_openai_prod_a7x9m2k4"
|
[WispKey Proxy @ localhost:7700]
|
Decrypts real key, swaps it in
|
[OpenAI API] <-- "Authorization: Bearer sk-real-key..."
- You store credentials in an encrypted local vault (AES-256-GCM, Argon2id key derivation)
- WispKey generates wisp tokens (
wk_*) for each credential - AI agents use wisp tokens in their requests
- The proxy intercepts headers, body, and query parameters -- swaps wisp for real, forwards to the target API
- The agent never sees, stores, or can exfiltrate the real secret
- Encrypted local vault -- AES-256-GCM at rest, Argon2id master key derivation, SQLite backend, configurable session timeout (default 30 min)
- Wisp token proxy -- HTTP forward proxy + blind HTTPS CONNECT tunneling + HTTPS reverse proxy mode (
X-Target-Urlheader) on localhost:7700 - CLI -- Full credential lifecycle:
init,unlock,add,list,get,remove,rotate,import,status,log - MCP server -- Native integration with Cursor, Claude Code, Windsurf via stdio JSON-RPC
- .env importer -- One-command migration with auto-detection of OpenAI, GitHub, Slack, AWS, and bearer token patterns
- Projects -- Top-level credential isolation by team or engagement (
project create,use,current,list,delete) - Partitions -- Logical credential grouping within projects, with encrypted
.wkbundleexport/import (partition create,list,delete,assign,export,import)
- Policy engine -- TOML-defined rules with per-credential, per-host, per-path, per-method restrictions, deny rules, time windows, and sliding-window rate limiting
- Audit log -- Every credential use and denial logged with timestamp, target host/path, method, and status; queryable by credential and date range
- Host restrictions -- Glob-pattern allowlists per credential (e.g.
api.openai.com/*) - Cross-OS local file protection -- Vault directories and sensitive local files are owner-only on Linux/macOS and restricted with Windows ACLs on Windows
- Browser-based Clerk login --
wispkey cloud loginopens browser, localhost callback captures session token - Tier enforcement -- Personal (free, local-only), Cloud ($1.99/mo), Enterprise (contact)
- Environment fallback -- If a wisp token lookup fails, the proxy checks
WISPKEY_FALLBACK_{SLUG}env vars and records an auto-fix note to.wispkey/auto-fix-notes.json
WispKey stores arbitrary encrypted secret values, not only API keys from .env files. Use api_key as the generic opaque secret type for passwords, database URLs, SSH/private-key files, webhook secrets, OAuth tokens, service-account JSON, and anything else that should stay out of the agent process. The type mainly controls how the proxy injects or substitutes the value at request time.
| Type | CLI Flag | Injection |
|---|---|---|
| Bearer Token | --type bearer_token |
Authorization: Bearer <value> |
| API Key | --type api_key |
Header or body replacement |
| Basic Auth | --type basic_auth |
Authorization: Basic <base64> |
| Custom Header | --type custom_header --header-name X-Api-Key |
Named header |
| Query Param | --type query_param --param-name key |
URL query parameter |
Examples:
wispkey add "db-password" --type api_key --value "correct-horse-battery-staple" --tags "database"
wispkey add "db-url" --type api_key --value "postgres://user:pass@localhost/app" --tags "database"
wispkey add "ssh-private-key" --type api_key --value-file ~/.ssh/id_ed25519 --partition "ssh-keys"
wispkey add "service-account-json" --type api_key --value-file ./service-account.json --tags "gcp"
wispkey add "basic-auth-api" --type basic_auth --value "user:password" --hosts "api.example.com"Configure in Cursor, Claude Code, or any MCP-compatible tool:
{
"mcpServers": {
"wispkey": {
"command": "wispkey",
"args": ["mcp", "serve"],
"env": { "WISPKEY_PASSWORD": "your-master-password" }
}
}
}Available MCP tools:
wispkey_list-- List credentials (filter by tag, project)wispkey_get_token-- Get wisp token for a credentialwispkey_proxy_status-- Check vault/session/proxy statewispkey_project_list-- List all projects with partition counts
WispKey supports HTTPS in two ways:
CONNECT tunneling (standard forward proxy) -- the agent sets HTTP_PROXY=http://localhost:7700 and the proxy tunnels the TLS connection. CONNECT is a blind tunnel: the proxy cannot inspect or rewrite headers, bodies, or query strings inside the TLS stream. Use CONNECT only when the request does not need wisp token substitution.
Reverse proxy mode -- use X-Target-Url for explicit HTTPS targeting:
curl -x http://localhost:7700 \
-H "X-Target-Url: https://api.openai.com/v1/chat/completions" \
-H "Authorization: Bearer wk_openai_prod_a7x9m2k4" \
-d '{"model": "gpt-4", "messages": [...]}'Define credential access rules in ~/.wispkey/policies.toml:
[[policy]]
name = "restrict-production"
credential = "aws-prod"
allowed_methods = ["GET"]
denied_paths = ["/admin/**", "/delete/**"]
allowed_hosts = ["api.aws.com"]
rate_limit = "10/minute"
time_window = "09:00-17:00 America/New_York"Manage policies via CLI:
wispkey policy init # Create starter policies.toml
wispkey policy list # Show loaded policies
wispkey policy check # Validate policy fileCredentials are isolated by project. Each project contains partitions, which contain credentials.
Each project gets its own personal partition, so partition names are project-scoped.
wispkey project create "client-alpha" --description "Client Alpha credentials"
wispkey project use "client-alpha"
wispkey project current
wispkey project list
wispkey project export "client-alpha" --output client-alpha.wkbundle
wispkey project import client-alpha.wkbundle
wispkey list --all-projects
wispkey serve --all-projectsOverride per-terminal with export WISPKEY_PROJECT=client-alpha.
Export and import encrypted credential bundles for sharing or backup:
wispkey partition create "staging" --description "Staging API keys"
wispkey partition assign "my-credential" --partition "staging"
wispkey partition export "staging" --output staging.wkbundle
wispkey partition import staging.wkbundleExports are encrypted with a separate bundle passphrase, not the vault master password. The bundle file contains real secrets after decryption, so share the file and passphrase through different channels. New exports require a 12+ character bundle passphrase.
For non-interactive bundle operations, use WISPKEY_BUNDLE_PASSPHRASE or a protected passphrase file:
export WISPKEY_BUNDLE_PASSPHRASE='a-long-export-passphrase'
wispkey project export "client-alpha" --output client-alpha.wkbundle
wispkey project import client-alpha.wkbundle \
--bundle-passphrase-file ~/.wispkey/client-alpha.bundle-passphraseExport and import one encrypted credential for narrow sharing:
wispkey credential export "openai-key" --output openai-key.wkcred
wispkey credential import openai-key.wkcred --project client-alpha --partition personalSet WISPKEY_PASSWORD to skip interactive prompts:
export WISPKEY_PASSWORD='your-master-password'
wispkey init
wispkey unlock
wispkey add "key" --type api_key --value "secret"WISPKEY_PASSWORD only unlocks or initializes the vault. It is intentionally not used for encrypted bundle export/import; use WISPKEY_BUNDLE_PASSPHRASE or --bundle-passphrase-file for those commands.
src/
core/ # Vault engine (encrypt/decrypt, CRUD, wisp tokens, projects, partitions)
proxy/ # HTTP/HTTPS proxy (tokio + hyper, credential injection, policy eval, env fallback)
mcp/ # MCP server (stdio JSON-RPC transport)
cli/ # CLI interface (clap, 37 subcommands)
audit/ # Audit logging (SQLite, credential + time filtering)
migrate/ # .env file importer (auto-detection heuristics)
partition/ # Encrypted bundle export/import (.wkbundle)
secure_files.rs # Cross-platform owner-only local file protection
sharing/ # Project and single-credential encrypted share bundles
cloud/ # Cloud sync client (Clerk browser login, tier enforcement)
policy/ # Policy engine (TOML rules, rate limiting, time windows)
tests/
integration.rs # CLI integration tests
plugin/ # Cursor plugin (rules, skills, hooks, agents)
- Rust 1.94+ via rustup
- SQLite is bundled via
rusqlite-- no system install needed
git clone https://github.com/rankupgames/wispkey.git
cd wispkey
cargo build # Debug build
cargo build --release # Optimized release build
cargo test # Run all 86 tests (72 unit + 14 integration)
cargo clippy --all-targets --all-features -- -D warnings -W clippy::suspicious -W clippy::style -W clippy::perf -W clippy::complexity
cargo fmt --check # Format check
cargo audit # Dependency advisory check (install with: cargo install cargo-audit --version 0.22.1 --locked)rustup target add x86_64-unknown-linux-gnu
rustup target add aarch64-unknown-linux-gnu
rustup target add x86_64-pc-windows-msvc
rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin
cargo build --release --target aarch64-apple-darwin| Component | Crate | Purpose |
|---|---|---|
| Async runtime | tokio |
Concurrent proxy connections |
| HTTP proxy | hyper + hyper-rustls |
HTTP/HTTPS request interception and CONNECT tunneling |
| Encryption | ring + argon2 |
AES-256-GCM vault, Argon2id key derivation |
| Database | rusqlite (bundled) |
Zero-config credential store + audit log |
| CLI | clap |
Subcommand parsing with shell completions |
| Serialization | serde + serde_json + toml |
Config, policy, and MCP protocol |
| HTTP client | reqwest |
Cloud API calls (rustls-tls) |
| Logging | tracing |
Structured logging with env filter |
| Patterns | glob-match + regex |
Host restriction globs, wisp token scanning |
| Browser | open |
Clerk login flow (opens default browser) |
- WispKey Cloud (private) -- Cloudflare Worker API for encrypted cloud sync, billing, and team features
- WispKey Desktop -- Tauri + SvelteKit desktop companion app
The open-source CLI works fully offline -- no account needed. WispKey Cloud is an optional companion for encrypted sync and team workflows:
| Tier | Price | What you get |
|---|---|---|
| Personal | Free | Everything in this repo -- local vault, proxy, MCP, plugin |
| Cloud | $1.99/mo ($1.49/mo annual) | Encrypted sync, up to 10 cloud partitions, 100 MB storage |
| Enterprise | Contact us | Unlimited partitions, org management, SSO, dedicated support |
See CONTRIBUTING.md for development workflow and guidelines.
Apache-2.0 -- see LICENSE for details.