Skip to lesson
Exit
Block a risky command with a hook1 / 2

2 min lesson

Block one force-push before execution

Build one beforeShellExecution guard and prove its deny, allow and failure paths.

Step 1 of 2

Add beforeShellExecution to .cursor/hooks.json and run block-protected-push.mjs from the project root. Parse the command from JSON stdin. Deny a force-push to main with clear user and Agent messages, and allow other Git commands. Set failClosed to true. Run parser tests for flag order, main refspecs and safe neighboring commands. In a disposable repository, make a matched hook exit with an error and confirm that Cursor blocks the command. Restore the real guard, then test the denied force-push and an allowed feature-branch push locally. Repeat the deny in a cloud agent and keep remote branch protection enabled.

Hooks stop the shell before it runs

0:26 · narrated
Read this demo as text
  1. Ask the agent to run rm -rf on a temp directory. A Rule might say please don't. That is not enough.
  2. Rejected before the shell ran. The deny-rm hook fired. Change that gate in Cursor Settings, Hooks — not by hoping the model remembers.
Watch once: beforeShellExecution denies rm -rf in-product — a Rule steers, a hook enforces.

Practice next: Now do the module workflow: place a deterministic deny on beforeShellExecution and test both the blocked and allowed paths.

Simulated Cursor 3.12 (macOS, light) — beta educational reconstruction, not the real product.