Claude Code · PreToolUse hook · Bash matcher · Free · Open Source

Stop Claude from installing
a package no human ever vetted.

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


A CRITICAL package never makes it past PreToolUse.

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 Code Bash tool → PreToolUse hook → permission decision
# 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.


One command. Edits .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.


Anonymous tier: 15/day. Free key: 200/day. Both real.

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

Get free API key →


Does the hook block legitimate installs?

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.

What gets sent to Commit?

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.

Does this work with Cursor too?

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.

What happens if Commit is down?

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.

How do I uninstall?

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.


One command. One hook. Real packages stay. CRITICAL ones don't.

npx proof-of-commitment hook --claude-code

Free API key — 200/day, no card →