devsafe lockbox
Store secrets in an encrypted binary file that AI tools, grep, cat, and ripgrep cannot read. Free to use, no account required.
Every command on this page works without an account, without a subscription, and without an internet connection. Your secrets never leave your machine.
Usage
$ devsafe lockbox <command> [options]
The lockbox is a single binary file (.devsafe-lockbox) encrypted with nonce-unique AEAD. Because it is a binary format, text-based tools like grep, cat, ripgrep, and AI coding assistants see only unreadable bytes. Your secrets stay invisible.
Use the --project <name> flag on any subcommand to scope operations to a named project or client namespace. Without it, lockbox uses the current directory's project context.
Core operations
lockbox import
Import secrets from a .env file into your lockbox. The original .env file is not modified or deleted (you should remove it yourself after confirming the import).
$ devsafe lockbox import .env ✓ imported 12 secrets into lockbox STRIPE_SECRET_KEY, DATABASE_URL, RESEND_API_KEY, ... +9 more ✓ encrypted with nonce-unique AEAD
If you have already run devsafe diagnose and it found exposed secrets, you can import those findings directly:
$ devsafe lockbox import --from-diagnosis ✓ imported 4 secrets found by diagnose
lockbox edit
Add, update, or delete secrets interactively. The lockbox is decrypted in memory, never written to disk as plaintext. Your terminal's secure input mode is used for entering values.
$ devsafe lockbox edit ? Action: (a)dd / (u)pdate / (d)elete / (q)uit: a ? Key name: OPENAI_API_KEY ? Value: ******** ✓ OPENAI_API_KEY added
lockbox run
Run any command with your lockbox secrets injected as environment variables. Secrets exist only in the child process's memory. They are not written to disk, shell history, or log files.
$ devsafe lockbox run npm start ✓ injected 12 secrets server listening on :3000
lockbox export
Export lockbox contents to stdout in .env format. Useful for migrating to another machine or sharing with a teammate through a secure channel. Pipe to a file if needed.
$ devsafe lockbox export | pbcopy # secrets are now in your clipboard
Only use this for migration. Do not pipe to a file that stays on disk. The entire point of lockbox is to avoid plaintext secrets on your filesystem.
lockbox list
Show all stored key names. Values are never displayed.
$ devsafe lockbox list STRIPE_SECRET_KEY DATABASE_URL RESEND_API_KEY OPENAI_API_KEY SUPABASE_SERVICE_ROLE_KEY ✓ 5 secrets stored
You can also use devsafe lockbox ls as a shorthand.
lockbox proof
Prove that the lockbox file is invisible to text tools and AI. This command runs grep, cat, ripgrep, strings, and other text extraction tools against your lockbox file and shows you what they find (nothing).
$ devsafe lockbox proof testing .devsafe-lockbox against 6 extraction tools... grep STRIPE_SECRET_KEY ✓ not found cat ✓ binary, unreadable rg STRIPE_SECRET_KEY ✓ not found strings ✓ no secret values hexdump (sample) ✓ no plaintext file type detection ✓ "data" (not text) ✓ lockbox is invisible to all text-based tools
Config file integration
lockbox inject
Replace {{LOCKBOX:KEY}} placeholders in any file with real values at runtime. The output goes to stdout, so your source file is never modified. Useful for config files, deployment scripts, or CI templates.
$ devsafe lockbox inject config.template.yaml > config.yaml ✓ replaced 3 references: DATABASE_URL, REDIS_URL, API_SECRET
lockbox template
Generate a .env.template file from your current lockbox. Each key becomes a {{LOCKBOX:KEY}} placeholder. Commit this template to version control so teammates know which secrets the project needs, without exposing any values.
$ devsafe lockbox template ✓ wrote .env.template with 5 placeholders $ cat .env.template STRIPE_SECRET_KEY={{LOCKBOX:STRIPE_SECRET_KEY}} DATABASE_URL={{LOCKBOX:DATABASE_URL}} RESEND_API_KEY={{LOCKBOX:RESEND_API_KEY}} ...
lockbox wrap-mcp
Rewrite an MCP (Model Context Protocol) config file so that hardcoded credentials are replaced with lockbox references. The original credentials are imported into your lockbox automatically.
$ devsafe lockbox wrap-mcp ~/.claude/claude_desktop_config.json ✓ found 3 credentials in MCP config ✓ imported GITHUB_TOKEN, SUPABASE_KEY, SLACK_WEBHOOK into lockbox ✓ rewrote config to use lockbox injection
After wrapping, your MCP config no longer contains plaintext secrets. When your AI tool reads the config, lockbox injects the real values at runtime.
Security tools
lockbox scan
Scan any file for leaked secret values. This checks the file's contents against every value stored in your lockbox. If any of your secrets appear in the file, lockbox reports them.
$ devsafe lockbox scan docker-compose.yml LEAKED: DATABASE_URL found on line 14 LEAKED: REDIS_URL found on line 22 2 secrets exposed in docker-compose.yml
lockbox scan-poison
Scan an MCP config file for tool poisoning. This looks for hidden directives, invisible Unicode characters, and prompt injection attempts that could trick an AI tool into leaking your secrets.
$ devsafe lockbox scan-poison claude_desktop_config.json ✓ no poisoning detected in 4 tool definitions
lockbox audit-permissions
Audit the permission claims in an MCP config. Flags tools that request more access than they need (reading your filesystem, executing shell commands, or accessing network resources without justification).
$ devsafe lockbox audit-permissions tool: filesystem-server WARN: requests read access to / (full filesystem) WARN: requests write access to ~/Documents tool: slack-mcp ✓ permissions are appropriate
lockbox gate
Check a command for destructive operations before running it. Useful as a safety net when AI tools suggest shell commands. Returns exit code 0 if safe, exit code 1 if the command looks destructive.
$ devsafe lockbox gate "rm -rf /" BLOCKED: recursive force-delete on root directory $ devsafe lockbox gate "git status" ✓ command is safe
lockbox filter
Pipe any output through the secret redaction filter. Any value that matches a secret in your lockbox is replaced with [REDACTED]. Useful for logging, CI output, or piping AI tool responses through before displaying them.
$ env | devsafe lockbox filter STRIPE_SECRET_KEY=[REDACTED] DATABASE_URL=[REDACTED] HOME=/Users/you PATH=/usr/local/bin:/usr/bin
AI tool integration
lockbox install-hooks
Install pre-execution hooks into Claude Code that block AI from reading your lockbox file, .env files, or any file containing secrets. The hooks run before every tool call the AI makes.
$ devsafe lockbox install-hooks ✓ installed PreToolUse hook: blocks Read of .env, .devsafe-lockbox ✓ installed PreToolUse hook: blocks Bash cat/grep on secret files ✓ hooks written to .claude/settings.json
lockbox remove-hooks
Remove all lockbox-related hooks from Claude Code.
$ devsafe lockbox remove-hooks ✓ removed 2 lockbox hooks from .claude/settings.json
lockbox install-agents
Generate an AGENTS.md file and agent instruction files that teach AI tools how to handle secrets properly. The instructions tell the AI to use devsafe lockbox run instead of reading .env files directly.
$ devsafe lockbox install-agents ✓ wrote AGENTS.md with secret-handling rules ✓ wrote .github/copilot-instructions.md ✓ wrote .cursor/rules/secrets.mdc
Team and client operations
lockbox grant
Create a time-limited, single-use grant for one secret. The grant expires after the time window you set, and can only be consumed once. Useful for sharing a single API key with a teammate or contractor without giving them access to your entire lockbox.
$ devsafe lockbox grant --key STAGING_DB_URL --ttl 1h ✓ grant created ID: grant_8f2a3c Expires: 1 hour from now Uses: 1 (single-use) Share this ID with the recipient.
lockbox use-grant
Consume a grant to retrieve the secret value. After one use, the grant is permanently invalidated.
$ devsafe lockbox use-grant grant_8f2a3c ✓ STAGING_DB_URL retrieved (grant consumed, now expired)
lockbox revoke
Remove all secrets for a specific project. Designed for client offboarding: when a project ends, wipe all credentials in one command.
$ devsafe lockbox revoke --project acme-corp This will delete 8 secrets for project "acme-corp". Continue? (y/N): y ✓ revoked 8 secrets for acme-corp
lockbox intake
Collect credentials from a client through an encrypted intake form. Generates a one-time link the client can use to submit their API keys, database URLs, and other secrets directly into your lockbox for that project.
$ devsafe lockbox intake --project acme-corp ✓ intake form created Send this link to your client: https://lockbox.devsafe.com/intake/f8a2c... Expires in 72 hours. Single use.
Global flags
| Flag | Description |
|---|---|
| --project <name> | Scope all operations to a named project or client namespace. Secrets from different projects are isolated from each other. |
| --lockbox <path> | Use a lockbox file at a custom path instead of the default .devsafe-lockbox in the current directory. |
| --json | Output results as JSON for scripting and CI integration. |
| --quiet | Suppress all output except errors. |
Common workflows
Import secrets, then run your app
The most common workflow. Move your .env secrets into lockbox, then use lockbox run instead of sourcing the .env file.
# Step 1: import your .env $ devsafe lockbox import .env ✓ imported 12 secrets into lockbox # Step 2: delete the plaintext .env (it's in lockbox now) $ rm .env # Step 3: run your app through lockbox $ devsafe lockbox run npm start ✓ injected 12 secrets server listening on :3000 # Step 4: prove it's invisible $ devsafe lockbox proof ✓ lockbox is invisible to all text-based tools
Protect your MCP config
If you use Claude Code, Cursor, or other AI tools with MCP servers, your config file probably contains hardcoded API keys. Wrap it in one command.
$ devsafe lockbox wrap-mcp ~/.claude/claude_desktop_config.json ✓ imported 3 credentials, rewrote config # verify the config no longer has plaintext keys $ devsafe lockbox scan ~/.claude/claude_desktop_config.json ✓ no leaked secrets found
Share a secret with a teammate
Create a time-limited grant. Send the grant ID over Slack, email, or any channel. The recipient consumes it once. No shared password managers, no plaintext in chat history.
# You (the sender) $ devsafe lockbox grant --key PROD_DATABASE_URL --ttl 30m ✓ grant_9d4f1a — expires in 30 minutes, single use # Teammate (the recipient) $ devsafe lockbox use-grant grant_9d4f1a ✓ PROD_DATABASE_URL retrieved
Scan for leaked secrets
Before committing, check that your config files do not contain any lockbox values in plaintext.
$ devsafe lockbox scan docker-compose.yml LEAKED: DATABASE_URL found on line 14 # fix it: use lockbox inject instead of hardcoding $ devsafe lockbox inject docker-compose.template.yml > docker-compose.yml ✓ replaced 2 references $ devsafe lockbox scan docker-compose.yml ✓ no leaked secrets found