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:
- Enable Third-party skills in Cursor Settings → Rules, Skills, Subagents → Include third-party Plugins, Skills, and other configs
- The feature must be enabled for your account
Configuration Locations
Claude Code hooks are loaded from these locations (in priority order):
| Location | Path | Description |
|---|---|---|
| Project local | .claude/settings.local.json | Project-specific, gitignored overrides |
| Project | .claude/settings.json | Project-level hooks, checked into repo |
| User | ~/.claude/settings.json | User-level hooks, apply globally |
Priority Order
When hooks are configured in multiple locations, they are merged in this priority order (highest to lowest):
- Enterprise hooks (managed deployment)
- Team hooks (dashboard-configured)
- Project hooks (
.cursor/hooks.json) - User hooks (
~/.cursor/hooks.json) - Claude project local (
.claude/settings.local.json) - Claude project (
.claude/settings.json) - 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 Hook | Cursor Hook |
|---|---|
PreToolUse | preToolUse |
PostToolUse | postToolUse |
UserPromptSubmit | beforeSubmitPrompt |
Stop | stop |
SubagentStop | subagentStop |
SessionStart | sessionStart |
SessionEnd | sessionEnd |
PreCompact | preCompact |
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:
- Keep using Claude Code config files: Enable third-party skills and your existing
.claude/settings.jsonhooks will work automatically - Migrate to Cursor format: Copy your hooks to
.cursor/hooks.jsonusing 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 Event | Cursor Mapping | Supported |
|---|---|---|
PreToolUse | preToolUse | Yes |
PostToolUse | postToolUse | Yes |
Stop | stop | Yes |
SubagentStop | subagentStop | Yes |
SessionStart | sessionStart | Yes |
SessionEnd | sessionEnd | Yes |
PreCompact | preCompact | Yes |
UserPromptSubmit | beforeSubmitPrompt | Yes |
Notification | - | No |
PermissionRequest | - | No |
Additional supported features:
| Feature | Supported |
|---|---|
Command-based hooks (type: "command") | Yes |
Prompt-based hooks (type: "prompt") | Yes |
Nested hookSpecificOutput responses | Yes |
| Exit code 2 blocking | Yes |
| Tool matchers (regex patterns) | Yes |
| Timeout configuration | Yes |
Tool Name Mapping
Claude Code tool names are mapped to Cursor tool names:
| Claude Code Tool | Cursor Tool | Supported |
|---|---|---|
Bash | Shell | Yes |
Read | Read | Yes |
Write | Write | Yes |
Edit | Write | Yes |
Grep | Grep | Yes |
Task | Task | Yes |
Glob | - | No |
WebFetch | - | No |
WebSearch | - | No |
Limitations
Some features are only available when using the native Cursor format:
subagentStarthook (Claude Code only hasSubagentStop)- Loop limit configuration (
loop_limit) - Team/Enterprise hook distribution via dashboard
Troubleshooting
Claude Code hooks not loading
- Verify "Third-party skills" is enabled in Cursor Settings
- Check that your
.claude/settings.jsonfile is valid JSON - Cursor watches config files and reloads them automatically. If hooks still do not load, restart Cursor.
Hooks running but not blocking
- Ensure your hook script exits with code
2to block actions - Check the JSON output format matches the expected schema
- 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.