Developers
Protect every API key from your terminal, your code and your CI
One command protects a whole project. Your SDKs keep working without a single code change. AI coding agents can set up keys without ever seeing one, and CI stops keys from being committed.
Command line
Viewnpx vallkey initPython
Viewpip install vallkeyGitHub Actions
Viewuses: vallkeyhq/scan-action@v1Open source under the MIT license, with no dependencies. Node.js 18 or newer, Python 3.8 or newer.
The command line
From a .env file full of keys to ghost keys, in a minute
Sign in once from your browser. Then init finds the keys in your .env files, creates ghost keys with each provider's safe default rules, and writes them back. Your real keys are stored encrypted and leave the files.
- login
- Approve this computer in your browser, once. The tool gets its own API token, which you can revoke in Settings.
- init
- Find the API keys in your .env files, create a ghost key for each and write the ghost keys back.
- scan
- Look for API keys in your code and your whole git history. Keys are always masked. Exits with 1 for CI.
- keys
- List your ghost keys.
- kill <key id>
- Stop a ghost key everywhere, right away.
- mcp
- Run the MCP server for AI coding agents.
$ npx vallkey login Your code: BCDF-GHJK (approve it in your browser)✓ Signed in. $ npx vallkey initThese keys can become ghost keys: .env OPENAI_API_KEY OpenAI API key sk-proj-…(52 chars) .env STRIPE_SECRET_KEY Stripe secret key sk_live_…(40 chars) ✓ Swapped 2 keys for ghost keys.Next: • The official SDKs read OPENAI_BASE_URL, so no code change. • Stripe: start your app with node -r vallkey/auto $ npx vallkey scan --history✓ No API keys found in 312 files or in git history.Any SDK, no code changes
Your code stays exactly as it is
Load Vallkey's small helper once. Every request that carries a ghost key goes to Vallkey with the same path; every other request is left alone. No base URLs to set, in any library.
Node.js
$ npm install vallkey$ node -r vallkey/auto server.js # Or for next dev, vite and other tools:$ NODE_OPTIONS='-r vallkey/auto' npm run devPython
$ pip install vallkey$ VALLKEY_AUTO=1 python app.py # Or in code, anywhere:import vallkey.autoIt looks for a ghost key
It sends that request to Vallkey
It leaves the rest alone
For web pages and mobile apps
Call APIs from the browser, with nothing in it worth stealing
Your server makes a short-lived key for each signed-in user, and the page or app uses that one. It expires in minutes, can only do what its ghost key allows, and stops the moment you kill or rotate the ghost key.
- Only your server can make them: requests from a web page are refused
- Limits per user, including a daily AI budget, across all of a user's keys
- Block one person in a click, without touching anyone else
- List the websites allowed to use a key; pages elsewhere are refused
import { createSessionKey } from 'vallkey/session' // after your own sign-in checkconst { session_key } = await createSessionKey({ user: user.id })from vallkey.session import create_session_keysession_key = create_session_key(user=user.id)["session_key"]const openai = new OpenAI({ apiKey: session_key, baseURL: 'https://api.vallkey.com/v1', dangerouslyAllowBrowser: true,})For AI coding agents
Let your agent set up keys, without ever seeing one
The Vallkey MCP server works with Claude Code, Cursor, Windsurf and any other MCP client. To protect a key, the agent names the variable; the server on your computer reads the key, creates the ghost key and writes it back. Only the key id reaches the agent.
- Your MCP client asks you before each tool runs
- Files outside the project folder are refused
- Looser rules still wait for the safety delay
- Every action is in your audit log, marked as an agent's
$ npx vallkey login$ claude mcp add vallkey -- npx -y vallkey mcp{ "mcpServers": { "vallkey": { "command": "npx", "args": ["-y", "vallkey", "mcp"] } }}scan_projectFinds API keys in the project, masked.protect_env_keySwaps a key in a .env file for a ghost key.list_keys, get_keyLists keys and shows one key's rules and status.get_activityRecent requests, with the reason for each refused one.update_rulesChanges some rules. Looser ones still wait for the safety delay.kill_keyStops a key at once. Reviving it is left to a person.In CI
A committed key fails the build, on the right line
The GitHub Action scans every push and pull request. Each key it finds is marked on its line and listed in the run summary, always masked. Scan the whole history too, or only report without failing.
on: [push, pull_request]jobs: scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - uses: vallkeyhq/scan-action@v1On other CI systems: npx --yes vallkey scan
Stripe secret key found
Stripe secret key sk_live_…(40 chars). Treat it as leaked: create a new key at the provider, revoke this one, and keep keys out of the code.
Management API
Everything the dashboard does, by API
Create keys, change rules, read activity and kill keys from your own scripts. Each script gets its own API token, read only or admin, that you can revoke at any time.
1curl https://api.vallkey.com/_guard/v1/keys \2 -H "Authorization: Bearer $VALLKEY_TOKEN" \3 -H "Content-Type: application/json" \4 -d '{"provider": "openai", "real_key": "sk-...", "label": "Support bot",5 "rules": {"allowedModels": ["gpt-5-mini"], "dailyTokens": 2000000}}'Write-only real keys
Same errors as Stripe and OpenAI
Protect your keys before the next commit
Free plan, no card needed. npx vallkey init takes about a minute.