Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create Cursor hooks. Use when you want to create a hook, write hooks.json, add hook scripts, or automate behavior around agent events.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 767% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-10 | ✗→✓ | ▲ Improved | -14% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 81% | 0% |
Create hooks when you want Cursor to run custom logic before or after agent events. Hooks are scripts or prompt-based checks that exchange JSON over stdin/stdout and can observe, block, modify, or follow up on behavior.
When the user asks for a hook, don't stop at describing the format. Gather the missing requirements, then create or update the hook files directly.
Before you write anything, determine:
Infer these from the conversation when possible. Only ask for the missing pieces.
.cursor/hooks.json and .cursor/hooks/*~/.cursor/hooks.json and ~/.cursor/hooks/*Path behavior matters:
.cursor/hooks/my-hook.sh~/.cursor/, so use paths like ./hooks/my-hook.sh or hooks/my-hook.shPrefer project hooks when the behavior should be shared with the repository and checked into version control.
Use the narrowest event that matches the user's goal.
sessionStart, sessionEnd: set up or audit a sessionpreToolUse, postToolUse, postToolUseFailure: work across all toolssubagentStart, subagentStop: control or continue Task/subagent workflowsbeforeShellExecution, afterShellExecution: gate or audit terminal commandsbeforeMCPExecution, afterMCPExecution: gate or audit MCP tool callsbeforeReadFile, afterFileEdit: control file reads or post-process editsbeforeSubmitPrompt: validate prompts before they are sentpreCompact: observe context compactionstop: handle agent completionafterAgentResponse, afterAgentThought: track agent output or reasoningbeforeTabFileRead: control file access for inline completionsafterTabFileEdit: post-process edits made by TabbeforeShellExecutionafterShellExecutionafterFileEditpreToolUsepostToolUsesubagentStartsubagentStopbeforeSubmitPromptbeforeMCPExecutionCreate a hooks.json file with schema version 1:
json{ "version": 1, "hooks": { "afterFileEdit": [ { "command": ".cursor/hooks/format.sh" } ] } }
Each hook definition can include:
command: shell command or script pathtype: "command" or "prompt" (defaults to "command")timeout: timeout in secondsmatcher: filter for when the hook runsfailClosed: block the action when the hook crashes, times out, or returns invalid JSONloop_limit: mainly for stop and subagentStop follow-up loopsUse matchers to avoid running the hook on every event.
preToolUse / postToolUse / postToolUseFailure: match on tool type such as Shell, Read, Write, Task, or MCP tools in MCP: ... formsubagentStart / subagentStop: match on subagent type such as generalPurpose, explore, or shellbeforeShellExecution / afterShellExecution: match on the full shell command stringbeforeReadFile: match on tool type such as Read or TabReadafterFileEdit: match on tool type such as Write or TabWritebeforeSubmitPrompt: matches the value UserPromptSubmitImportant matcher warning:
[[:space:]]; use JavaScript equivalents like \sCommand hooks are the default. They receive JSON on stdin and can return JSON on stdout.
json{ "version": 1, "hooks": { "beforeShellExecution": [ { "command": ".cursor/hooks/approve-network.sh", "matcher": "curl|wget|nc ", "failClosed": true } ] } }
bash#!/bin/bash input=$(cat) command=$(echo "$input" | jq -r '.command // empty') if [[ "$command" =~ curl|wget|nc ]]; then echo '{ "permission": "ask", "user_message": "This command may make a network request. Please review it before continuing.", "agent_message": "A hook flagged this shell command as a possible network call." }' exit 0 fi echo '{ "permission": "allow" }' exit 0
Important behavior:
0: success2: block the action, same as returning denyfailClosed: trueAlways make hook scripts executable after creating them.
Prompt hooks are useful when the policy is easier to describe than to script.
json{ "version": 1, "hooks": { "beforeShellExecution": [ { "type": "prompt", "prompt": "Does this command look safe to execute? Only allow read-only operations. Here is the hook input: $ARGUMENTS", "timeout": 10 } ] } }
Use prompt hooks for lightweight policy decisions. Prefer command hooks when the logic must be deterministic or when the user needs exact, auditable behavior.
Use the event's supported output fields only.
preToolUse: can return permission, user_message, agent_message, and updated_inputpostToolUse: can return additional_context; for MCP tools it can also return updated_mcp_tool_outputsubagentStart: can return permission and user_messagesubagentStop: can return followup_messagebeforeShellExecution / beforeMCPExecution: can return permission, user_message, and agent_messagehooks.json file$PATHOther measured skills in the registry, with their headline benchmark lift.