docs
token-hunt v0.1.0
Python 3.10+ · zero cloud, zero telemetry · fail-closed ·source on GitHub
01 Install
pip install token-hunt# standalone cliclaude plugin install token-hunt@JordanNewell# the six-hook guardThe plugin is the only step most people need — it wires all six hooks into Claude Code. The pip package is the engine underneath and the standalone CLI; the plugin drives it. Cursor and Aider work today via the CLI peer (manual wiring); first-class plugin integrations ship in v0.2.
02 The six hooks
Every point a secret can enter the transcript has a hook on it. BLOCK hooks stop the tool call before it runs. WARN hooks can't un-ring the bell — the paste or output is already in the transcript — so they banner the agent and log the finding for rotation.
| hook | what it sees | action on leak |
|---|---|---|
UserPromptSubmit | your paste | WARN |
PreToolUse:Bash | command about to run | BLOCK |
PostToolUse:Bash | command output | WARN + log |
PostToolUse:Read | file contents | WARN + log |
PreToolUse:Edit/Write | new file content | BLOCK |
PostToolUse:Edit/Write | echo | WARN + log |
Fail-closed: if the scanner itself crashes inside a hook, the tool call isBLOCKED with a bypass hint — never silently allowed.
03 CLI
$ token-hunt scan <path>
Scan a file or directory. Findings print with rule, line, and a rotate URL.
--stdin— read text from stdin instead of a file--context <point>— pretend to run at this hook (default UserPromptSubmit)--format text|json— output format (default text)--no-log— don't write the finding to rotations.log
$ token-hunt list
List open leaks from rotations.log, newest first.
--all— include closed leaks too
$ token-hunt close <id>
Mark a leak closed after you rotated the key. Overdue finds stay flagged past 72h.
--note <text>— rotation note, e.g. "rotated at console.anthropic.com"
$ token-hunt watch <dir>
Watch a directory live — e.g. your agent transcript dir — and scan every file change.
--context <point>— hook to attribute findings to (default PostToolUse:Read)--exit-after <n>— exit after n seconds instead of running forever
token-hunt watch ~/.claude/projects/token-hunt listtoken-hunt close 1 --note "rotated at console.anthropic.com"04 Bash escape-hatch detection
Bash evaluates secrets into emitted text with no literal in sight — no regex scanner can see the value because it never appears. token-hunt ships a runtime detector for this class in the PreToolUse:Bash hook:
BLOCKED
echo ${ANTHROPIC_API_KEY:+SET}
${ANTHROPIC_API_KEY:-UNSET}both branches run — the value leaks
BLOCKED
echo $GITHUB_TOKENdirect echo of a secret var
ALLOWED
[ -n "$ANTHROPIC_API_KEY" ] \
&& echo SETstatus check — no value emitted
A variable counts as secret-bearing when its name ends in _KEY,_TOKEN, _SECRET, _PASSWORD, _PAT and friends, or starts with a known provider prefix (ANTHROPIC_,OPENAI_, GITHUB_…). Non-secret vars echo freely.
05 Configuration
Pattern layers
Later layers extend earlier ones — your local rules add to the builtin 48, never replace them.
- 1
builtin.toml— ships with the package — 48 rules - 2
~/.token-hunt/patterns.local.toml— machine-local, gitignored - 3
./.token-hunt/patterns.local.toml— repo-local, gitignored
Allowlist
Test fixtures and known fakes go in ~/.token-hunt/allowlist.toml by SHA-256 fingerprint (first 16 chars of the value), or path-based, so findings never re-fire:
fingerprints = [
"a1b2c3d4e5f60718...", # fake fixture, tests/
]Environment
TOKEN_HUNT_DISABLE=1Per-repo opt-out. Disables every hook. For repos you trust and nothing else.TOKEN_HUNT_ALLOW=1One-shot bypass of the BLOCK hooks only (Bash, Edit/Write). The WARN hooks always fire — they block nothing, so there is nothing to bypass. Use sparingly.06 Rules & providers
48 rules cover 51 providers in three tiers:
- Shape-verified (35 rules) — dedicated regexes matched against documented key formats: Z.ai, Anthropic, OpenAI, GitHub, GitLab, Figma, PyPI, npm, Linear, Stripe, Slack, OpenRouter, Groq, Together, Fireworks, Mistral, xAI, Perplexity, Hugging Face, Cerebras, Replicate, Vercel AI Gateway, NVIDIA NIM, Chutes, Requesty, Novita, Upstage, Baseten, Baidu Qianfan, fal.ai, DashScope, Moonshot Kimi, Cohere, Scaleway.
- Keyword-gated opaque (11 rules) — providers with no public key format (SambaNova, Nebius, AI21, OVHcloud, FriendliAI, GMI Cloud, Crusoe, Featherless, DeepInfra, Inference.net, BytePlus). The provider name must appear in the text and a 32+-char token must be present. Low precision by design — you get attribution and the rotate URL, not shape confidence. No guessed regexes.
- Generic fallbacks (2 rules) — bare
sk-+ 32 chars (DeepSeek, StepFun, SiliconFlow, Poe, Qwen) and JWTs (MiniMax).
Extend or override anything with a local pattern layer (§05). Every finding carries its rule id, so you always know which rule fired.