secret-box Claude Code mod: hide secrets from Claude Code as it uses them
Claude Code uses an API key without seeing it: a masked box saves it to .env and tool output comes back redacted.
Permissions
- Reads filesCan read files and list directories on your machine ($.fs.read / list / stat / exists).
- Writes filesCan create or overwrite files on your machine ($.fs.write).
- Runs commandsCan run shell programs on your machine ($.process.run / spawn). Check the source for exactly which ones.
- Intercepts tool callsSees every tool call Claude makes (tool.call / tool.check) and could block or change it.
- Reads your promptsCan see what you type and the conversation transcript (prompt.* / session.append / session.messages).
- Changes the UIDraws into the Claude Code interface: bands, panes, status text, toasts (ui.render / $.ui.*).
- Adds commands/toolsRegisters new slash commands or tools that you or Claude can invoke ($.command.register / $.tool.register).
- tested with
- v2.1.307
- last tested
- requires
- Claude Code ≥ 2.1.287
- surfaces
- pane, above-prompt, toast, transcript
- source
- Ray Amjad (ray-amjad) (MIT)
Install inside Claude Code:
/plugin install secret-box --marketplace ray-amjad/claude-code-modsWhat does this mod do?
secret-box is a community mod by Ray Amjad (ray-amjad), published in his claude-code-mods repository. It aims to hide secrets from Claude Code without stopping Claude from using them. A key that reaches the conversation stays in the transcript, so the mod keeps it out in both directions.
- In. Claude calls a
request_secrettool with a variable name and a one-line reason. A masked box opens, you paste the key, and the mod writesNAME=valueto.env(or a file such as.env.local) and adds that file to.gitignoreif git does not already ignore it. Claude gets the name and a placeholder. - Use. A placeholder written in a
Bash,Write,Edit,MultiEditorNotebookEditcall turns into the real value as the tool runs. - Out. Tool results, prompts, attachments and subagent tasks are scanned. Vendor-shaped keys, high-entropy tokens, passwords on command lines and in connection strings, and every secret-named value in
.envcome back as placeholders. - Never committed.
git addof a.envfile and agit committhat would include one are refused.
Emails and public IP addresses are hidden only if you turn on the pii option.
Install
The install block above adds the author's marketplace and installs the plugin from it. Mods load only in a folder you have trusted, so accept the trust prompt first. To ask for the box, tell Claude billing.js needs the Stripe secret key, or use the secret box to ask me for STRIPE_SECRET_KEY.
$ install secret-box
Requires Claude Code ≥ 2.1.287
Installs from the author's own marketplace: ray-amjad/claude-code-mods
1.One line, inside Claude Code
/plugin install secret-box --marketplace ray-amjad/claude-code-modsPaste into a running session (v2.1.275+). Claude Code asks to add the marketplace first.
2.From your shell
claude plugin marketplace add ray-amjad/claude-code-mods claude plugin install secret-box@claude-code-modsThen run /reload-plugins in any session that is already open.
3.Try it without installing
git clone https://github.com/ray-amjad/claude-code-mods claude --plugin-dir ./claude-code-mods/plugins/secret-boxLoads the mod for one session only. Nothing is added to your settings.
How it works
hooks/hooks.json loads one module, register.jsx, which calls the redaction code in redact.ts and detect.ts and adds the box and the .env guard. The box waits for you in short sleep 0.3 processes, because a hook has a 10 second budget of its own time but time inside a mods API call is not counted. This is the commit guard, from register.jsx:
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
const why = await commitBlockReason($, String(e.command || ''))
return why ? { deny: `secret-box: ${why} A pushed key can't be taken back.` } : next(e)
}).catch(() => ({ deny: 'secret-box: the .env guard failed, so this call is blocked to be safe.' }))On every tool call, redact.ts swaps placeholders for real values (only in the tools listed in restoreTools), runs the tool, scans the result, and swaps keys it finds for placeholders. A Bash command that runs git commit, git tag or gh issue/gh pr gets no real values, so a commit message keeps the placeholder. The placeholder-to-value vault lives in memory and is not written to disk. Before a tool reads a .env file, a hook reads it too and hands each secret-named value to the vault, so even a plain word password is hidden.
Customize it
Open /plugin configure secret-box@claude-code-mods, or set pluginConfigs in your user settings. The options are:
secrets(on) andpii(off), withhideEmailsandredactPrivateIpsfor whatpiicovers.restoreInToolInputsandrestoreTools(defaultBash,Write,Edit,MultiEdit,NotebookEdit). The option text warns never to list a tool that sends input to a model or the network, such as Agent, WebFetch or WebSearch.notify,minEntropy(3.6),minLength(24) andcontextMinEntropy(3.0).- Allow and deny lists:
allow,allowEmails,allowPrefixes,allowUrlHostsanddenyPrefixes.
Permissions & safety
We read the manifest, hooks.json, register.jsx, redact.ts in full, and detect.ts lines 1 to 823 and 1585 to 1657. The middle of detect.ts is detector regular expressions and helper code that we searched for network, process, eval, dynamic import and globalThis use rather than reading line by line. We listed the PNG images and the example app without running them. There is no package.json, no install script, no dependency, no binary and no minified code. Findings:
- Network: none. No
fetch, sockets or$.httpanywhere. The URLs indetect.tsare patterns it matches (Slack and Discord webhooks). - Processes (
$.process.run):sleep 0.3while the box waits (on Windowsnode -eorping),git ls-files --error-unmatch,git check-ignore -q,git diff --cached --name-onlyandgit ls-files --modified --others --exclude-standard. All are argv arrays with no shell. - File writes: only the env file you approve in the box (a bare name matching
.envor.env.<name>, never a path) and the project's.gitignore. It refuses a file git tracks. Nothing under~/.claude, shell files or LaunchAgents. - File reads:
.envfiles named in a Bash, Read, Grep or Edit call, and.envin the working directory at session start. Values are kept in memory only. - Daemons and telemetry: none.
- Gating: it rewrites and can deny prompts, tool calls, attachments,
@mentions and subagent spawns. Its.catchhandlers fail closed, so a crash withholds a result or drops a prompt instead of passing raw text. It refuses@.env,git addof.env, and agit committhat would include one. - Real values go to tools: placeholders become real keys inside Bash, Write and Edit. A file Claude writes with a placeholder holds the real key. It refuses to put a value containing shell-active characters into a Bash command.
- Prompt injection: the
request_secretdescription tells Claude to use it instead of asking you to paste a secret. That is the stated purpose. No hidden Unicode found. - External requirements: none. It needs an interactive session and, for the dock, a terminal of at least 144 columns; otherwise it uses the band above the prompt (Ctrl+X, then Tab).
- License: MIT, with a LICENSE file in the repo root.
claude plugin validate passed with no manifest errors or warnings. It reported one non-blocking directory finding: no plugin icon. claude plugin test ran 46 tests across 3 files, and all passed.
- Reads files
- Can read files and list directories on your machine ($.fs.read / list / stat / exists).
- Writes files
- Can create or overwrite files on your machine ($.fs.write).
- Runs commands
- Can run shell programs on your machine ($.process.run / spawn). Check the source for exactly which ones.
- Intercepts tool calls
- Sees every tool call Claude makes (tool.call / tool.check) and could block or change it.
- Reads your prompts
- Can see what you type and the conversation transcript (prompt.* / session.append / session.messages).
- Changes the UI
- Draws into the Claude Code interface: bands, panes, status text, toasts (ui.render / $.ui.*).
- Adds commands/tools
- Registers new slash commands or tools that you or Claude can invoke ($.command.register / $.tool.register).
Compatibility & troubleshooting
The README's Limits section lists what to expect. In auto mode, Claude Code's classifier may block cat .env before secret-box sees it, though the placeholder still works. A .env value under 8 characters is hidden in .env reads but not everywhere else. Only the working directory's .env is learned at session start. Editing in the middle of the box with the arrow keys is not tracked. If the box does not appear, widen the terminal or press Ctrl+X, then Tab. Placeholders from an earlier session mean nothing in a new one.
To try it, copy the author's example folder to a scratch directory, run git init, and ask Claude to set up STRIPE_SECRET_KEY. Paste a fake key and then run cat .env to see the placeholder.
FAQ
- Does Claude ever see the key I paste into the box?
- Not through the box. You type into a field that draws only dots, the mod keeps the real text in memory, writes it to .env, and returns the variable name, the file and a placeholder like [REDACTED-SECRET-1a2b3c4d]. The author's README says a paste can show for one frame before it is redrawn as dots.
- Can Claude still leak the key if it wants to?
- Yes. The README says so plainly. With a placeholder Claude can run a command that transforms the key (base64, rev) or sends it somewhere, and the transformed output is not recognised. The mod stops keys landing in the transcript by accident; it is not a sandbox against a model trying to leak one.
- What happens if Claude runs git commit with .env staged?
- The Bash hook refuses it. It blocks git add of a .env file, and before any git commit it runs git diff --cached --name-only and denies the call if a .env file (other than .env.example, .sample, .template or .dist) is staged. If git cannot say what the commit includes, the commit is blocked too.
- Does it work in claude -p or SDK sessions?
- Redaction and the .env guard still run, but the request_secret tool is not registered, because there is nobody to type into the box.
- Which Claude Code versions does it need?
- It is built on function hooks. The author tested it with 2.1.296; we loaded it on 2.1.307, where the validator reported no errors or warnings in the manifest and all 46 of the author's tests passed.
# Related mods
FeaturedSecret Redactor
Swaps API keys, emails and public IPs for placeholders before Claude sees them, and restores them when a tool runs.
- toast
- Intercepts tool calls
- Reads your prompts
- Changes the UI
tested with v2.1.291
PII Guard
Replaces Taiwanese personal data with placeholders before Claude sees it and restores real values when Claude writes.
- none
- Reads files
- Runs commands
- Network
- Intercepts tool calls
- Reads your prompts
tested with v2.1.291
More in Safety guards, Tools you add to Claude.