Skip to main content

Hook Handlers

A handler is the part of a hook that does the work. It can run a command, call a URL, call an MCP tool, ask a model, or start a subagent. The type key picks which one. For example, {"type": "command", "command": "./check.sh"} runs a script.

Remove the entry, or use disableAllHooks, to turn a handler off.

Exampleโ€‹

An HTTP hook that posts every Stop event to a local service.

.claude/settings.json
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "http",
"url": "http://localhost:8080/claude-stop",
"headers": { "Authorization": "Bearer $HOOK_TOKEN" },
"allowedEnvVars": ["HOOK_TOKEN"],
"timeout": 5
}
]
}
]
}
}

Only names in allowedEnvVars are filled into headers. Other references become empty strings.

Handler Typesโ€‹

TypeStatusWhat it doesEvents it works on
commandDocumentedRuns a shell command or an executable. Input on stdin. Result by exit code, stdout, and stderr.All 33 events.
httpDocumentedSends the input as JSON in a POST to a URL. The result is the response body, and needs a 2xx status.31 events. Not SessionStart and not Setup.
mcp_toolDocumentedCalls a tool on a configured MCP server. The text result is read like stdout. A result with isError: true is a non-blocking error.33 events, but skipped on Setup and on SessionStart at launch.
promptDocumentedOne model call that returns ok.12 events, plus PermissionRequest.
๐Ÿงชย agentDocumentedA subagent that checks a condition. Up to 50 turns. Experimental, and the docs say it may change.12 events. Not PermissionRequest.
callbackUndocumentedA function that an SDK host or a mod registers.Events that run device hooks. It is not a config key.
scriptDiffersSome text names this type.2.1.304 rejects it with Unknown hook type "script". A script entry under PreToolUse also disables the whole settings file it sits in.

The 12 events of prompt and agent are PermissionDenied, PostToolBatch, PostToolUse, PostToolUseFailure, PreToolUse, Stop, SubagentStop, TaskCompleted, TaskCreated, TeammateIdle, UserPromptExpansion, and UserPromptSubmit. SessionStart and Setup accept command and mcp_tool only.

warning

A script hook never runs in 2.1.304. Worse, one script entry under PreToolUse turns off every hook in that settings file. Source: a probe of the program (see Probes).

Common Fieldsโ€‹

FieldStatusWhat it doesNotes
typeDocumentedPicks the handler kind.One of command, http, mcp_tool, prompt, agent.
ifDocumentedOne permission rule that filters the handler.Only tool events read it. See Configuration.
timeoutDocumentedSeconds before Claude Code cancels the hook.A positive number. Defaults are on Configuration.
statusMessageDocumentedSpinner text while the hook runs.A string.
onceDocumentedRemoves the hook after its first successful run.A failure, exit 2, or timeout keeps it. Honored only in skill frontmatter.

Command Fieldsโ€‹

FieldStatusWhat it doesNotes
commandDocumentedThe command string, or the program to run when args is set.Shell form uses sh -c, Git Bash, or PowerShell.
argsDocumentedAn argument list for exec form.No shell runs. Placeholders are replaced in command and in each element.
shellDocumentedbash or powershell.Ignored when args is set.
asyncDocumentedRuns in the background.timeout is not enforced. The hook cannot block. Output arrives on the next turn.
asyncRewakeDocumentedA background run that wakes the model on exit 2.stderr (or stdout if stderr is empty) becomes a system reminder. timeout still applies. Implies async.
onFailureDocumentedcontinue or block.Needs 2.1.295. See Configuration. Also works on http.
rewakeMessageUndocumentedA custom prefix for the system reminder of asyncRewake.An internal field.
rewakeSummaryUndocumentedA one-line summary shown to you for asyncRewake.An internal field. Default text is Stop hook feedback.
cloudUndocumenteddevice or skip for cloud sessions that this machine drives.An internal field. An unknown value reads as skip. Also works on http.

HTTP Fieldsโ€‹

FieldStatusWhat it doesNotes
urlDocumentedThe POST target.Must pass allowedHttpHookUrls when that setting exists.
headersDocumentedExtra request headers.$VAR and ${VAR} are replaced only for names in allowedEnvVars.
allowedEnvVarsDocumentedNames that may be replaced in headers.Other references become empty strings. httpHookAllowedEnvVars narrows the list.
onFailureDocumentedcontinue or block.A non-2xx status or a connection error counts as a failure.

MCP Tool Fieldsโ€‹

FieldStatusWhat it doesNotes
serverDocumentedThe name of a configured MCP server.Plugin servers use plugin:<plugin>:<server>.
toolDocumentedThe tool to call.A string.
inputDocumentedThe tool arguments.String values accept ${path} from the hook input, such as ${tool_input.file_path}.

On events that can block, Claude Code waits for a server that is still connecting. The wait lasts at most MCP_TIMEOUT and the hook timeout. On observer events, it does not wait.

Prompt and Agent Fieldsโ€‹

FieldStatusWhat it doesNotes
promptDocumentedThe text to evaluate.$ARGUMENTS is replaced by the input JSON. Without it, Claude Code appends the JSON.
modelDiffersThe model for the check.Applies to prompt and agent.
continueOnBlockDocumentedFeeds an ok: false reason to Claude and goes on.prompt only. Default false. Agent hooks always act as if true.
ok (model reply)Documentedtrue allows. false blocks.The effect of false per event is in the Response schema section of the Hooks Reference.
reason (model reply)DocumentedWhy the model blocked.Required when ok is false.
impossible (model reply)DocumentedThe condition can never be met.On Stop and SubagentStop the turn ends. Agents ignore it. prompt only.

Source: Hooks Reference and the program (handler schemas for command, prompt, mcp_tool, http, and agent). Not verified: the callback forwarding rules for cloud sessions.