Claude Code's Bash tool happily runs npm install,
pip install, cargo add, and go get — sometimes for
packages the model hallucinated. The Commit hook adds a PreToolUse entry that
intercepts each install, scores every package against the Commit Index, and replies
deny on CRITICAL — the agent never executes a sole-publisher + high-download
package without you noticing.
Works with Claude Code hooks · No account required to start · Anonymous tier: 15 audits/day
What happens when Claude runs npm install
Claude decides to install lodash. Before the Bash tool executes,
the hook reads Claude's stdin payload, calls Commit, and emits a
permissionDecision: "deny" in
hookSpecificOutput. Claude surfaces the reason in the agent dialog and
never runs the command.
# Claude suggests: $ npm install lodash # Hook receives stdin (PreToolUse payload): {"tool_name":"Bash","tool_input":{"command":"npm install lodash"}} # Hook writes stdout, Claude shows: 🔴 Commit blocked: lodash flagged CRITICAL 🔴 lodash (score 84) — CRITICAL: sole npm publisher + >10M/wk → https://getcommit.dev/audit?packages=lodash&ecosystem=npm
Same flow for pip install, cargo add, and go get.
HIGH packages return ask — Claude prompts. Other commands pass through —
the hook only acts on install verbs it recognizes.
Install · 30 seconds
.claude/settings.json in place.
Run the command in your project directory (per-project) or with --global
(all your Claude Code projects). The hook script is written to
~/.commit/cursor-hook.js (kept that name for backward compatibility — same script
serves both clients) and registered as a PreToolUse entry with the
Bash matcher.
# Per-project (recommended): writes .claude/settings.json next to your repo $ npx proof-of-commitment hook --claude-code # Or apply to every Claude Code project on this machine $ npx proof-of-commitment hook --claude-code --global # Install for BOTH Cursor and Claude Code in one shot $ npx proof-of-commitment hook # Remove later $ npx proof-of-commitment hook --uninstall
The hook merges into any existing settings.json — your other
PreToolUse, Write|Edit, SessionStart, and MCP
entries are preserved. No global npm install required.
Free API key · 200 audits/day · 30 seconds, no card
The hook works without an account — anonymous IP gets 15 audits/day. Long Claude Code sessions with many installs blow through that quickly. A free key lifts you to 200/day. Two ways to get one:
# In the terminal — saves to ~/.commit/config $ npx proof-of-commitment login # Or in the browser https://getcommit.dev/get-started?ref=claude-code-hook-429
FAQ
Only CRITICAL packages are denied — the precise profile that preceded ua-parser-js (Oct 2021),
event-stream (2018), and the Shai-Hulud burst (Sep 2025): sole publisher + very high downloads.
HIGH triggers Claude Code's ask dialog. Everything else passes silently. False
positives on healthy popular packages are rare by design — see the writing for the scoring rationale.
Only the package names and ecosystem (npm/pypi/cargo/golang) — parsed from the
tool_input.command field. Not your code, not your environment, not the rest
of the command. Source:
npm-package/index.js.
Yes. The same script auto-detects the client — Cursor's beforeShellExecution
stdin shape vs Claude Code's PreToolUse shape — and replies in the right format.
See Commit for Cursor for the Cursor-specific install command.
The hook has a 4-second timeout. On timeout or non-429 errors, it returns
allow by writing no stdout and exiting 0 — Claude proceeds normally. On 429
(rate limit), it surfaces the signup prompt and warns about unscored packages so you can
decide explicitly instead of silently allowing.
npx proof-of-commitment hook --uninstall — removes the Bash matcher entry
from .claude/settings.json and deletes ~/.commit/cursor-hook.js
if empty. Your other PreToolUse entries are untouched.
npx proof-of-commitment hook --claude-code