Skip to main content

Command Palette

Search for a command to run...

Get Started

Third Party Hooks

Cursor supports loading hooks from third-party tools, enabling compatibility with existing hook configurations from other AI coding assistants.

Claude Code Hooks

Cursor can load and execute hooks configured for Claude Code, allowing you to use the same hook scripts across both tools.

Requirements

To enable Claude Code hooks compatibility:

  1. Enable Third-party skills in Cursor Settings → Rules, Skills, Subagents → Include third-party Plugins, Skills, and other configs
  2. The feature must be enabled for your account

Configuration Locations

Claude Code hooks are loaded from these locations (in priority order):

LocationPathDescription
Project local.claude/settings.local.jsonProject-specific, gitignored overrides
Project.claude/settings.jsonProject-level hooks, checked into repo
User~/.claude/settings.jsonUser-level hooks, apply globally

Priority Order

When hooks are configured in multiple locations, they are merged in this priority order (highest to lowest):

  1. Enterprise hooks (managed deployment)
  2. Team hooks (dashboard-configured)
  3. Project hooks (.cursor/hooks.json)
  4. User hooks (~/.cursor/hooks.json)
  5. Claude project local (.claude/settings.local.json)
  6. Claude project (.claude/settings.json)
  7. Claude user (~/.claude/settings.json)

All matching hooks from every source run. When responses conflict, higher-priority sources take precedence during merge.

Enterprise-managed hooks and dashboard distribution require an Enterprise plan. Contact sales to learn more.

Claude Code Hook Format

Claude Code hooks use a similar but slightly different format. Cursor automatically maps Claude hook names to their Cursor equivalents.

Example Claude Code settings.json:

{  "hooks": {    "PreToolUse": [      {        "matcher": "Shell",        "hooks": [          {            "type": "command",            "command": "./hooks/validate-shell.sh"          }        ]      }    ],    "PostToolUse": [      {        "matcher": ".*",        "hooks": [          {            "type": "command",            "command": "./hooks/audit.sh"          }        ]      }    ]  }}

Response Format Compatibility

Cursor supports both Claude Code's nested hookSpecificOutput response format and the older flat response format. Hook scripts written for Claude Code will work in Cursor regardless of which format they use.

PreToolUse Response Formats

Nested format (Claude Code style):

{  "hookSpecificOutput": {    "hookEventName": "PreToolUse",    "permissionDecision": "deny",    "permissionDecisionReason": "Blocked by policy",    "updatedInput": { "command": "npm ci" }  }}

Flat format (Cursor native style):

{  "permission": "deny",  "user_message": "Blocked by policy",  "updated_input": { "command": "npm ci" }}

Both formats are equivalent. The nested permissionDecision maps to permission, permissionDecisionReason maps to user_message, and updatedInput maps to updated_input.

Stop / SubagentStop Response Formats

Nested format (Claude Code style):

{  "hookSpecificOutput": {    "decision": "block",    "reason": "Tasks incomplete, continue working"  }}

Flat format (Claude Code legacy style):

{  "decision": "block",  "reason": "Tasks incomplete, continue working"}

Cursor native format:

{  "followup_message": "Tasks incomplete, continue working"}

For Stop and SubagentStop hooks, a decision of "block" with a reason is treated as an automatic follow-up, equivalent to providing followup_message in the native Cursor format.

Hook Step Mapping

Claude Code hook names are automatically mapped to Cursor hook names:

Claude Code HookCursor Hook
PreToolUsepreToolUse
PostToolUsepostToolUse
UserPromptSubmitbeforeSubmitPrompt
Stopstop
SubagentStopsubagentStop
SessionStartsessionStart
SessionEndsessionEnd
PreCompactpreCompact

Exit Code Behavior

Both Cursor and Claude Code hooks support exit code 2 to block an action. This provides consistent behavior when sharing hooks between tools:

#!/bin/bash# Block dangerous commandsif [[ "$COMMAND" == *"rm -rf"* ]]; then  echo '{"permission": "deny", "user_message": "Destructive command blocked"}'  exit 2fiecho '{"permission": "allow"}'exit 0
  • Exit code 0: Hook succeeded, use the JSON output
  • Exit code 2: Block the action (equivalent to permission: "deny")
  • Other exit codes: Hook failed, action proceeds (fail-open)

Migration from Claude Code

If you have existing Claude Code hooks, you can:

  1. Keep using Claude Code config files: Enable third-party skills and your existing .claude/settings.json hooks will work automatically
  2. Migrate to Cursor format: Copy your hooks to .cursor/hooks.json using the Cursor format for full feature support

Cursor format equivalent:

{  "version": 1,  "hooks": {    "preToolUse": [      {        "command": "./hooks/validate-shell.sh",        "matcher": "Shell"      }    ],    "postToolUse": [      {        "command": "./hooks/audit.sh"      }    ]  }}

Supported Features

When using Claude Code hooks in Cursor, the following features are supported:

Claude Code EventCursor MappingSupported
PreToolUsepreToolUseYes
PostToolUsepostToolUseYes
StopstopYes
SubagentStopsubagentStopYes
SessionStartsessionStartYes
SessionEndsessionEndYes
PreCompactpreCompactYes
UserPromptSubmitbeforeSubmitPromptYes
Notification-No
PermissionRequest-No

Additional supported features:

FeatureSupported
Command-based hooks (type: "command")Yes
Prompt-based hooks (type: "prompt")Yes
Nested hookSpecificOutput responsesYes
Exit code 2 blockingYes
Tool matchers (regex patterns)Yes
Timeout configurationYes

Tool Name Mapping

Claude Code tool names are mapped to Cursor tool names:

Claude Code ToolCursor ToolSupported
BashShellYes
ReadReadYes
WriteWriteYes
EditWriteYes
GrepGrepYes
TaskTaskYes
Glob-No
WebFetch-No
WebSearch-No

Limitations

Some features are only available when using the native Cursor format:

  • subagentStart hook (Claude Code only has SubagentStop)
  • Loop limit configuration (loop_limit)
  • Team/Enterprise hook distribution via dashboard

Troubleshooting

Claude Code hooks not loading

  1. Verify "Third-party skills" is enabled in Cursor Settings
  2. Check that your .claude/settings.json file is valid JSON
  3. Cursor watches config files and reloads them automatically. If hooks still do not load, restart Cursor.

Hooks running but not blocking

  1. Ensure your hook script exits with code 2 to block actions
  2. Check the JSON output format matches the expected schema
  3. View the Hooks output channel in Cursor for error details

Different behavior between Cursor and Claude Code

Some behavior differences may exist due to different execution environments. Test your hooks in both tools to ensure compatibility.

Enterprise hook deployment

Use managed Enterprise hooks and team distribution from the dashboard.

Contact Sales