ScrubOpen Scrub

GUIDE · CLAUDE CODE, GEMINI CLI

Keep secrets and client data out of Claude Code prompts

Terminal agents make it easy to paste a log, a stack trace or a customer email straight into a prompt. A prompt hook can stop that before it leaves your machine, and a small filter can clean text you do want to send.

How secrets end up in prompts

In a terminal agent the prompt is often a paste: a failing request with its Authorization header, a .env line, a log that includes a customer's email, a support ticket you want a fix for. Everything in the prompt goes to the model provider. Rotating a leaked key takes minutes; explaining a leaked customer list does not.

Block it before it is sent: a prompt hook

Claude Code runs a UserPromptSubmit hook before each prompt is sent. A hook cannot rewrite the prompt, but it can stop it and tell you why. Scrub's command-line tool installs one:

brew install onurkat/scrub/scrub        # macOS; Linux/Windows: see the GitHub release
scrub hook install claude-code          # this project (.claude/settings.json)
scrub hook install claude-code --user   # all projects (~/.claude/settings.json)

It merges with your existing settings and hooks. When a prompt contains an email, phone number, IBAN, card number, ID number, API key, token or a term from your Scrub dictionary, Claude Code shows:

Scrub blocked this prompt: EMAIL: 1, SECRET: 1.
Scrub the text with Ctrl+Alt+S or scrub, then submit it again;
or prefix the prompt with #noscrub to send anyway.

Only category counts are shown, never the values. A clean prompt passes without any output. To remove the hook: scrub hook uninstall claude-code. For Gemini CLI: scrub hook install gemini.

Clean text you do want to send: the filter

scrub reads text on standard input and writes the scrubbed version, so it fits in a pipe:

pbpaste | scrub | claude -p "Why does this request fail?"
scrub app.log --keep | claude -p "Summarise the errors"
claude -p "Draft a reply" < ticket.txt | scrub restore --last

--keep stores the mapping locally (readable only by your user) so scrub restore --last, or Ctrl+Alt+R in the desktop app, can put the real values back into the answer.

Which keys are recognised

Stripe-style sk_live_/rk_ keys, OpenAI-style sk- keys, AWS access key IDs (AKIA…), GitHub personal tokens (ghp_…), Slack bot tokens (xoxb-…), Google API keys (AIza…), JSON Web Tokens and PEM private key blocks. Custom secrets such as internal hostnames or project names go in the dictionary.

What a prompt hook does not cover

The hook is a seatbelt for the moment you paste, not a substitute for keeping secrets out of the working tree.

Questions

Does the hook see my files or tool output?

No. It runs on the prompt you type (UserPromptSubmit). Files the agent reads later are not inspected by this hook; keep secrets out of the repository and use .gitignore and environment variables for keys.

Can I send a prompt anyway?

Yes. Start the prompt with #noscrub and the hook lets it through. The prefix is sent along with the prompt.

Does it work without the desktop app?

Yes. The hook and the scrub filter are part of the command-line tool, installed with Homebrew on macOS or from the GitHub release.