Windsurf IDE Hook · pre_run_command · Free · Open Source

Block bad installs in Windsurf
before they touch the filesystem.

Windsurf's Cascade agent runs npm install, pip install, cargo add, and go get — often suggesting packages it has never seen before. Commit's hook intercepts each install command via Windsurf's pre_run_command hook, scores every package against the Commit Index, and denies CRITICAL packages (sole publisher + high downloads — the attack profile of ua-parser-js, event-stream, Shai-Hulud) before they hit disk.

Works with Windsurf's Cascade hooks · No account required to start · Anonymous tier: 15 audits/day


A CRITICAL package never reaches the package manager.

Windsurf's Cascade agent decides to install lodash. Before the command runs, the hook calls Commit, gets a score, and exits with code 2 (Windsurf's deny signal). Cascade surfaces the reason in the chat — the install never runs.

Windsurf Cascade → Commit hook → permission decision
# Cascade suggests:
$ npm install lodash

# Commit hook intercepts. Windsurf shows:

🔴 Commit blocked: lodash flagged CRITICAL

  🔴 lodash (score 84) — CRITICAL: sole npm publisher + >10M/wk

→ https://getcommit.dev/audit?packages=lodash&ecosystem=npm

The same flow runs on pip install, cargo add, and go get. HIGH packages are blocked with a warning message. Everything else passes through silently.


One command. Edits .windsurf/hooks.json in place.

Run the command in your project directory (per-project) or with --global (all your projects). The hook script is registered as a pre_run_command entry in .windsurf/hooks.json.

# Per-project (recommended): writes .windsurf/hooks.json next to your repo
$ npx proof-of-commitment hook --windsurf

# Or apply to every Windsurf project on this machine
$ npx proof-of-commitment hook --windsurf --global

# Install for all three IDEs at once (Cursor + Claude Code + Windsurf)
$ npx proof-of-commitment hook

# Remove later
$ npx proof-of-commitment hook --uninstall

The hook merges into any existing hooks.json — your other pre_run_command 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. CI runners and dev containers share egress IPs, so the counter ticks faster than you'd think. A free key lifts you to 200/day.

# In the terminal — saves to ~/.commit/config
$ npx proof-of-commitment login

# Or in the browser
https://getcommit.dev/get-started?ref=windsurf-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 packages are blocked with a warning. 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 shell command. Not your code, not your environment, not the rest of the command. Source: npm-package/index.js.

Does this work with Cursor and Claude Code too?

Yes. The same script auto-detects the client from stdin shape and replies in the right format. Run poc hook (no flags) to install for all three IDEs at once. See Commit for Cursor and Commit for Claude Code for client-specific guides.

How does Windsurf's hook differ from Cursor's?

Windsurf uses exit code 2 to deny and stderr for the user message, while Cursor uses a JSON response body. The hook auto-detects the client and handles this automatically — you install once and it works regardless of which IDE triggers the command.

What happens if Commit is down?

The hook has a 4-second timeout. On timeout or non-429 errors, it exits 0 (allow) — the install proceeds. 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 entry from .windsurf/hooks.json. Your other hooks are untouched.


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

npx proof-of-commitment hook --windsurf

Free API key — 200/day, no card →