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.

To disable a handler, remove the entry or use disableAllHooks.

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
}
]
}
]
}
}

Claude Code fills only names in allowedEnvVars into headers. Other references become empty strings.

Handler Types​

TypeStatusWhat it doesEvents it works on
command
Documented: An official docs page names this item.
Runs a shell command or an executable. Input on stdin. Result by exit code, stdout, and stderr.All 33 events.
http
Documented: An official docs page names this item.
Sends 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_tool
Documented: An official docs page names this item.
Calls a tool on a configured MCP server. Claude Code reads the text result like stdout. A result with isError: true is a non-blocking error.33 events. Claude Code skips it on Setup, and on SessionStart when Claude Code starts.
prompt
Documented: An official docs page names this item.
One model call that returns ok.12 events, plus PermissionRequest.
agent
Documented: An official docs page names this item.
Experimental: The program or the official docs call this experimental or beta.
A subagent that checks a condition. Up to 50 turns. Experimental, and the docs say it may change.12 events. Not PermissionRequest.
callback
Undocumented: Only the program shows this item. It can change without notice.
A function that an SDK host or a mod registers.Events that run device hooks. It is not a config key.
script
Differs: The official docs and the program disagree. The row says how. Rejected in 2.1.305. Do not use.
Some text names this type.2.1.305 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.305. 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
type
Documented: An official docs page names this item.
Picks the handler kind.One of command, http, mcp_tool, prompt, agent.
if
Documented: An official docs page names this item.
One permission rule that filters the handler.Only tool events read it. See Configuration.
timeout
Documented: An official docs page names this item.
Seconds before Claude Code cancels the hook.A positive number. Defaults are on Configuration.
statusMessage
Documented: An official docs page names this item.
Spinner text while the hook runs.A string.
once
Documented: An official docs page names this item.
Removes the hook after its first successful run.A failure, exit 2, or timeout keeps it. Claude Code honors it only in skill frontmatter.

Command Fields​

FieldStatusWhat it doesNotes
command
Documented: An official docs page names this item.
The command string, or the program to run when you set args.Shell form uses sh -c, Git Bash, or PowerShell.
args
Documented: An official docs page names this item.
An argument list for exec form.No shell runs. Claude Code replaces placeholders in command and in each element.
shell
Documented: An official docs page names this item.
bash or powershell.Claude Code ignores it when you set args.
async
Documented: An official docs page names this item.
Runs in the background.Claude Code does not enforce timeout. The hook cannot block. Output arrives on the next turn.
asyncRewake
Documented: An official docs page names this item.
A 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.
onFailure
Documented: An official docs page names this item.
continue or block.Needs 2.1.295. See Configuration. Also works on http.
rewakeMessage
Undocumented: Only the program shows this item. It can change without notice.
A custom prefix for the system reminder of asyncRewake.An internal field.
rewakeSummary
Undocumented: Only the program shows this item. It can change without notice.
A one-line summary that Claude Code shows to you for asyncRewake.An internal field. Default text is Stop hook feedback.
cloud
Undocumented: Only the program shows this item. It can change without notice.
device 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
url
Documented: An official docs page names this item.
The POST target.Must pass allowedHttpHookUrls when that setting exists.
headers
Documented: An official docs page names this item.
Extra request headers.Claude Code replaces $VAR and ${VAR} only for names in allowedEnvVars.
allowedEnvVars
Documented: An official docs page names this item.
Names that Claude Code may replace in headers.Other references become empty strings. httpHookAllowedEnvVars narrows the list.
onFailure
Documented: An official docs page names this item.
continue or block.A non-2xx status or a connection error counts as a failure.

MCP Tool Fields​

FieldStatusWhat it doesNotes
server
Documented: An official docs page names this item.
The name of a configured MCP server.Plugin servers use plugin:<plugin>:<server>.
tool
Documented: An official docs page names this item.
The tool to call.A string.
input
Documented: An official docs page names this item.
The 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
prompt
Documented: An official docs page names this item.
The text to evaluate.Claude Code replaces $ARGUMENTS with the input JSON. Without it, Claude Code appends the JSON.
model
Differs: The official docs and the program disagree. The row says how. Docs: the default is the background model for both types. Program: the agent default is Haiku.
The model for the check.Applies to prompt and agent.
continueOnBlock
Documented: An official docs page names this item.
Feeds an ok: false reason to Claude. Then it continues.prompt only. Default false. Agent hooks always act as if true.
ok (model reply)
Documented: An official docs page names this item.
true allows. false blocks.The effect of false per event is in the Response schema section of the Hooks Reference.
reason (model reply)
Documented: An official docs page names this item.
Why the model blocked.Required when ok is false.
impossible (model reply)
Documented: An official docs page names this item.
The condition can never be met.On Stop and SubagentStop the turn ends. Agents ignore it. prompt only.

Prompt and Agent Concurrency​

Since 2.1.312, the program limits how many prompt and agent hooks run at the same time. The limits do not cover command, http, or mcp_tool hooks.

LimitStatusWhat it doesNotes
24 at a time
Documented: An official docs page names this item.
At most 24 prompt and agent hooks run at once.The program counts them per session host, not per agent. A hook over the limit waits for a free place.
12 overdue
Documented: An official docs page names this item.
At most 12 more run when they waited longer than the timeout of their event.These hooks use a second count of 12. It is separate from the first.
12 per event
Undocumented: Only the program shows this item. It can change without notice.
When one event starts several of these hooks, at most 12 start together.The program also uses this number to size the time budget of the event.

Source: the program (chunk-r5cyd28m.js, the model hooks and overdue model hooks counts). We did not trace that a subagent shares the session host of its parent.

Source: Hooks Reference and the program (handler schemas for command, prompt, mcp_tool, http, and agent). Cloud sessions forward only your own hooks of kind command and http from user settings, settings.local.json, or --settings. They never forward prompt, agent, or mcp_tool hooks, or plugin or managed hooks. A device client registers up to 128 hooks with a lease of 60 to 3600 seconds (600 by default). The cloud worker calls back with hook_callback. We read these rules in the program. We did not run them, because a cloud session needs a login (needs a cloud session, not run).