Claude Code — Hooks
- File format
- JSON
- Discovery path
-
.claude/settings.json - Syllago install method
- JSON merge
- Symlink support
- No
- Config file
-
.claude/settings.json - Handler types
-
command,http,prompt,agent
Hook events
| Canonical Event | Native Name | Category |
|---|---|---|
after_compact | PostCompact | Context |
after_tool_execute | PostToolUse | Tool |
agent_stop | Stop | Lifecycle |
before_compact | PreCompact | Context |
before_prompt | UserPromptSubmit | Lifecycle |
before_tool_execute | PreToolUse | Tool |
config_change | ConfigChange | Config |
elicitation | Elicitation | Interaction |
elicitation_result | ElicitationResult | Interaction |
error_occurred | ErrorOccurred | Lifecycle |
file_changed | FileChanged | Workspace |
instructions_loaded | InstructionsLoaded | Context |
notification | Notification | Output |
permission_request | PermissionRequest | Security |
session_end | SessionEnd | Lifecycle |
session_start | SessionStart | Lifecycle |
stop_failure | StopFailure | Lifecycle |
subagent_start | SubagentStart | Lifecycle |
subagent_stop | SubagentStop | Lifecycle |
task_completed | TaskCompleted | Lifecycle |
teammate_idle | TeammateIdle | Collaboration |
tool_use_failure | PostToolUseFailure | Tool |
worktree_create | WorktreeCreate | Workspace |
worktree_remove | WorktreeRemove | Workspace |
Features
How each feature converts to syllago's canonical format. See format conversion for what these statuses mean.
Fields
Native frontmatter or config fields this provider exposes. The first column is the provider's own field name; the canonical key column links to syllago's cross-provider equivalent.
| Provider field | Conversion | Canonical key | Summary |
|---|---|---|---|
matcher | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | — | Matcher field evaluated as: '*'/empty/omitted = match all; only letters/digits/_/| = exact string or |-separated list; any other chars = JavaScript regex. Per-event fields (tool_name, source, reason, notification_type) drive matching. if field uses permission-rule syntax for subcommand-level filtering (e.g., Bash(git *)). |
type | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | — | Hooks can be command (shell), http (POST), mcp_tool (call an MCP tool), prompt (LLM eval), or agent (subagent, experimental); prompt/agent restricted to a subset of events. |
async | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | Command hooks with async: true run in background; decisions ignored, systemMessage delivered on next turn. asyncRewake: true additionally wakes Claude when the background hook exits with code 2, delivering stderr (or stdout if stderr empty) as a system reminder. |
headers | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | HTTP hooks accept headers (additional request headers with $VAR or ${VAR} env var interpolation) and allowedEnvVars (list of env var names permitted for interpolation; variables not listed are replaced with empty strings). Non-2xx responses and connection failures are non-blocking errors. |
hooks | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | Hooks defined in skill/subagent frontmatter run only while the component is active; skills support a once: true handler flag (honored only in skill frontmatter, not in settings files or agent frontmatter); for subagents, Stop hooks are auto-converted to SubagentStop. |
server | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | mcp_tool hooks call a named tool on an already-connected MCP server; accepts server (server name), tool (tool name), and input (arguments with ${path} substitution from hook JSON input). Tool text output treated as command-hook stdout. Server must be already connected; SessionStart/Setup hooks may see 'not connected' on first run. |
updatedInput | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | PreToolUse hooks return updatedInput to replace tool params before execution; defer (CC v2.1.89+) exits Claude for external resume via -p. |
updatedMCPToolOutput | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | PostToolUse hooks for MCP tools return updatedMCPToolOutput to filter/transform/annotate tool results before Claude sees them. |
updatedPermissions | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | — | PermissionRequest hooks return updatedPermissions with addRules/replaceRules/removeRules/setMode/addDirectories entries scoped to session/local/project/user destinations. |
allowManagedHooksOnly | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | — | Enterprise policy setting allowManagedHooksOnly: true restricts hook execution to only managed (admin-deployed) hooks, blocking user and project hooks. Plugin hooks force-enabled in managed settings enabledPlugins are exempt. |
asyncRewake | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | — | Command hooks with asyncRewake: true wake Claude after completing background execution when exit code is 2, delivering stderr (or stdout if stderr empty) as a system reminder on the next turn. Implies async: true. |
disableAllHooks | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | — | Setting disableAllHooks: true in settings.json disables all hook execution for that scope; useful for debugging or locked-down environments. |
if | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | — | Handlers accept an if field using permission-rule syntax to gate execution on conditions. Only evaluated on tool events (PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied); hooks on other events with an if field never run. For Bash, matched against each subcommand after stripping leading VAR=value assignments. |
shell | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | — | Command hooks accept a shell field ('bash' default or 'powershell') to run the command via PowerShell on Windows. Does not require CLAUDE_CODE_USE_POWERSHELL_TOOL since hooks spawn PowerShell directly. |
Other features
Behaviors, conventions, and capabilities that aren't tied to a single named field — things like path-based activation, discovery rules, and lifecycle behavior.
| Feature | Conversion | Summary |
|---|---|---|
async_execution | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | hook_async_execution: async: true on command handlers runs hook in background without blocking; decisions ignored; systemMessage delivered on next turn; asyncRewake: true also wakes Claude on exit code 2 |
context_injection | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | Hooks return systemMessage field in JSON output to inject context into agent's active session |
| Decision Control via Exit Codes and JSON Output | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | Hooks decide via exit codes (0/2/other) or JSON fields (continue, stopReason, permissionDecision, decision, updatedInput, additionalContext). PermissionDenied event returns {retry: true} to allow model to retry the denied tool call. |
decision_control | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | block: exit code 2 or decision=block; allow: permissionDecision=allow in hookSpecificOutput; modify: updatedInput replaces tool input before execution; PermissionDenied event supports {retry: true} to allow model retry |
handler_types | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | Five types: command (shell), http (POST to URL), mcp_tool (MCP tool call), prompt (LLM evaluation), agent (subagent with tools, experimental); prompt/agent restricted to subset of events |
| Hook Event Set | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | 29 hook events spanning session, turn, and tool-call cadences: Setup, SessionStart, SessionEnd, InstructionsLoaded, UserPromptSubmit, UserPromptExpansion, PreToolUse, PermissionRequest, PermissionDenied, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, StopFailure, Notification, SubagentStart, SubagentStop, TaskCreated, TaskCompleted, TeammateIdle, ConfigChange, CwdChanged, FileChanged, WorktreeCreate, WorktreeRemove, PreCompact, PostCompact, Elicitation, ElicitationResult. Each event has a defined matcher field; UserPromptSubmit, PostToolBatch, Stop, TeammateIdle, TaskCreated, TaskCompleted, WorktreeCreate, WorktreeRemove, and CwdChanged do not support matchers. |
| Hook Scopes and Locations | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | Six hook scopes: user, project, local, managed policy, plugin, and component frontmatter; managed policy can lock down the others via allowManagedHooksOnly; plugin hooks force-enabled in managed settings are exempt from allowManagedHooksOnly. |
hook_scopes | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | Six scopes: user (~/.claude/settings.json), project (.claude/settings.json), local (.claude/settings.local.json), managed policy, plugin (hooks/hooks.json), component frontmatter (skill/agent) |
input_modification | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | hook_input_modification: PreToolUse returns updatedInput in hookSpecificOutput; entire input object replaced; compatible with all permissionDecision values except defer |
json_io_protocol | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | Command hooks receive event JSON on stdin; respond with JSON on stdout (exit 0); structured fields: continue, stopReason, suppressOutput, systemMessage, hookSpecificOutput |
matcher_patterns | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | hook_matcher_patterns: exact string, pipe-separated list, or JavaScript regex; matches on tool_name or event-specific fields; if field uses permission-rule syntax for per-subcommand filtering |
permission_control | Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → | hook_permission_update_entries: PermissionRequest hooks return updatedPermissions with addRules/replaceRules/removeRules/setMode entries |
| Elicitation and ElicitationResult Hooks | Conversion type: No canonical equivalent — appended as prose in a conversion notes block so nothing is silently lost. Learn more → | Elicitation/ElicitationResult hooks intercept MCP server input requests, returning accept/decline/cancel actions or modifying the response. Matchers filter by MCP server name. |
| Common Handler Fields (timeout, statusMessage, once) | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | All hook handler types accept: timeout (seconds before cancel; defaults 600 for command, 30 for prompt, 60 for agent), statusMessage (custom spinner message), and once (runs once per session then removed; honored only in skill frontmatter). |
| Persistent Environment Variable Propagation via CLAUDE_ENV_FILE | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | SessionStart/CwdChanged/FileChanged hooks can write export statements to $CLAUDE_ENV_FILE that persist across subsequent Bash commands. |
| WorktreeCreate Hook Replaces Default Git Behavior | Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → | WorktreeCreate hook fully replaces Claude Code's git worktree creation, returning the new worktree path; enables non-git VCS support. |
Sources
| Source |
|---|
| https://code.claude.com/docs/en/hooks.md |
| https://code.claude.com/docs/en/hooks-guide.md |
| hooks-example-hooks.json |
| settings-strict-example.json |
| settings-lax-example.json |