How it works
Cloakroom checks what goes to the AI and swaps real values for placeholders.
In short
Every time the AI reads a file, runs a command or uses an add-on, Cloakroom checks what goes to the AI and swaps real values for placeholders. When the AI writes or runs something that holds a placeholder, Cloakroom puts the real value back on your machine. Commands that would send a secret off your machine, or move money, wait for your OK.
Claude Code reads a file or runs a tool
| "Nadia Petrov called about..." sk_live_51Hx9Q...
v
+--------------------------------------------+
| Cloakroom (on your machine) |
| rules + local model -> find the values |
| encrypted vault -> remember them |
+--------------------------------------------+
| "PII_PERSON_1 called about..." PII_SECRET_1
v
the model works with placeholders only
| Write reply.md: "Hi PII_PERSON_1,"
v
Cloakroom puts the real value back, locally
|
v
reply.md on your disk: "Hi Nadia Petrov,"
Hooks are small checks the agent runs before and after each action (a “tool call”). PII is personal data such as names, emails and addresses. MCP tools are add-ons that give the AI extra abilities, such as a browser. OCR reads text out of pictures.
The two modes
- Full (the default)
- Runs pattern rules and a local detection model (PII-Tracer). It catches keys, passwords, card numbers, government IDs, and also names, addresses and other personal details written as plain text.
- Rules
- Runs the pattern rules only. It still catches keys with a known shape (AWS, GitHub, Stripe, Slack, OpenAI, Google, JWTs, private keys), checksummed numbers (cards, IBANs, SSNs) and emails or names that sit next to obvious context, but it misses most free-text personal data. Use it when you can’t install the model, or when you only care about secrets.
Set the mode for everything in ~/.cloakroom/config.json, or for one shell with CLOAKROOM_MODE=rules, or for one command with --mode rules.
{ "mode": "rules" }
Backends (full mode only)
CLOAKROOM_BACKEND picks how the model runs. The default, auto, uses PyTorch when there’s a GPU (Apple Silicon or CUDA), otherwise the ONNX export if you’ve made one, otherwise PyTorch on the CPU.
cloakroom export-onnxwrites the CPU model under~/.cloakroom/onnx/. It needs PyTorch once and takes a few minutes (about 4 on a 2-core cloud machine).CLOAKROOM_ONNX=int8uses a smaller quantized export: a little faster, a few more false alarms.CLOAKROOM_BACKEND=torchoronnxforces one.
cloakroom doctor prints the backend in use and how long one check takes.
Each step
Hide
Hooks on every tool input and tool output run the detectors (a prompt with sensitive data is blocked instead, since prompts can’t be rewritten): pattern rules for secrets with known shapes, checksummed PII, context rules, and the PII-Tracer model for names, addresses and other free-text personal data. A value found once is masked everywhere it repeats.
Filter
A known-safe filter leaves harmless look-alikes alone, such as documented examples: published test cards and keys, sandbox IDs, reserved domains, bot and role mailboxes, loopback addresses, UUIDs and hashes, redaction markers, filler placeholders (AC000…, sk-...), standard numbers after RFC / ISO / ICAO / IEEE / PEP, and default dates (1970-01-01, 1900-01-01).
Pictures
PDFs become their text layer; scans, Read pictures and images in MCP tool results are read by local OCR (the ocr extra) and only the masked text goes to Claude. Without OCR they are held back.
Put back (restore)
Values go into the vault, an encrypted file kept per session (AES-GCM, key in the OS secure store). When Claude writes a file or runs a command with a placeholder, the real value is put back locally. The model never sees it.
Placeholders that can’t be guessed
A placeholder is PII_<KIND>_<n>_<tag>. A value comes back only when the tag checks out and the placeholder is in this session’s vault. Anything else in placeholder shape stays as text. Three refused guesses in one session show you one line.
Files Claude wrote stay masked
When real values are put back into a file, the hook records per file its path, its SHA-256, size and time, and per value the byte position, the value’s SHA-256, kind and placeholder. The log (~/.cloakroom/filelog.bin) is encrypted like the vault and holds no values: they are read back from the file when needed.
Encoded dumps and secrets
od, xxd, base64 and spaced-out output are turned back into text and checked; a hit withholds the output (it isn’t passed on). Each secret already in the session vault is also looked for in its encoded forms (base64, URL-encoded and JSON-escaped), and as an MD5, SHA-1 or SHA-256 hash, as hex, and reversed.
Sending-data hold
Before a shell command runs, Cloakroom checks whether it can send data off the machine. If it does and it holds a known secret, a key the rules recognise, or a literal token of 16+ characters in a credential header, the command is denied. To send it anyway, type cr: allow as your prompt (Claude never sees it), then ask Claude to run the same command again: it passes once, within 10 minutes.
Money-movement hold
Before any tool call runs, Cloakroom checks whether it would move money: a write to a listed payment endpoint, a payment CLI command, or an MCP tool whose name carries a money verb. Such a call is held with one line naming the endpoint or tool; cr: allow lets the same call run once.
Write-time and commit check
When a key or password would land in a file that is in a git repo and not git-ignored, the call is denied and Claude is told to put the value in .env. Before Claude runs git commit or git push, a key or password in what would be committed holds the command.
If the program is missing, nothing gets through
If the cloakroom command is missing, the plugin blocks prompts and denies tool calls instead of letting data through.
Other coding agents
Codex and Gemini CLI can’t swap a tool’s output for a masked copy, so Cloakroom blocks the original and the AI reads the masked text in the block message.
- Codex
cloakroom hook <event> --agent codexreads Codex’s hook input and turns the answer into Codex’s. Codex’s file edits (apply_patch) are restored and checked like Write.cloakroom install codexwrites the four hooks into~/.codex/hooks.json.- Gemini CLI
- Gemini CLI uses its own tool names with Claude Code’s argument names, so
--agent geminifirst renames the tool. Gemini lets a call through when a hook times out, so with the model not loaded yet the hook doesn’t wait: it checks with the rules in-process.cloakroom install geminiwrites these hooks as an extension of its own.
What it protects against, and what it doesn’t: Security model. Every detail: docs-HOW-IT-WORKS.md.