Hook Events
Claude Code has 33 hook events. Each event fires at one point in a session, and each one gets its own input fields and accepts its own output fields. This page lists them in groups: tool, tool result, session, prompt and turn, agent and task, and other events. The fields that every event shares are on Input and Output.
Add or remove the event key in the hooks map to turn an event on or off.
Example
A SessionStart hook that adds your open tickets as context.
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [{ "type": "command", "command": ".claude/hooks/tickets.sh" }]
}
]
}
}
#!/bin/bash
# Plain stdout on SessionStart becomes context for Claude.
echo "Open tickets: $(gh issue list --limit 5 --json title -q '.[].title' | paste -sd ';' -)"
All Events
| Event | Group | Fires when | Matcher | Can block |
|---|---|---|---|---|
Pre | Tool | Before a tool runs. | Tool name | ✅ |
Permission | Tool | A permission prompt would show. | Tool name | ❌ (use a decision) |
Permission | Tool | Auto mode denies a call. | Tool name | ❌ |
Post | Tool result | A tool call succeeds. | Tool name | ❌ |
Post | Tool result | A tool call fails. | Tool name | ❌ |
Post | Tool result | All tool calls of a batch are done. | None | ✅ |
Session | Session | A session starts or resumes. | Start source | ❌ |
Setup | Session | --, or -- or -- with -. | CLI flag | ❌ |
Session | Session | A session ends. | End reason | ❌ |
Instructions | Session | A CLAUDE. or rules file loads. | Load reason | ❌ |
Config | Session | A settings or skill file changes. | Config source | ✅ |
Cwd | Session | A shell command changes the directory. | None | ❌ |
File | Session | A watched file changes on disk. | File names | ❌ |
Directory | Session | A directory is added with /. | Add source | ❌ |
User | Prompt | You submit a prompt. | None | ✅ |
User | Prompt | A typed command expands to a prompt. | Command name | ✅ |
Message | Prompt | Assistant text streams to the screen. | None | ❌ |
Notification | Prompt | Claude Code sends a notification. | Notification type | ❌ |
Stop | Prompt | The main agent finishes. | None | ✅ (keeps working) |
Stop | Prompt | The turn ends on an API error. | Error type | ❌ |
Subagent | Agent | A subagent starts or resumes. | Agent type | ❌ |
Subagent | Agent | A subagent finishes. | Agent type | ✅ (keeps working) |
Task | Agent | Task makes a task. | None | ✅ |
Task | Agent | A task is marked done. | None | ✅ |
Teammate | Agent | A teammate is about to go idle. | None | ✅ (keeps working) |
Pre | Other | Before a compaction. | Trigger | ✅ |
Post | Other | After a compaction. | Trigger | ❌ |
Pre | Other | Before a requested model switch. | Target model | ✅ |
Post | Other | After the model changes. | Target model | ❌ |
Elicitation | Other | An MCP server asks you for input. | Server name | ✅ (declines) |
Elicitation | Other | You answered an MCP question. | Server name | ✅ |
Worktree | Other | A worktree is needed. | None | ✅ (fails) |
Worktree | Other | A hook-made worktree is cleaned up. | None | ✅ (fails) |
Tool Events
These events fire before a tool runs, and when a permission is asked for or denied.
They are the main place to approve, change, or block a tool call.
MCP tools are named mcp__<server>__<tool>.
PreToolUse
Fires after Claude builds the tool input and before the tool runs.
It does not fire for @ file mentions.
Exit 2 blocks the call, and stderr is the reason.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
tool_ | Documented | Input | The tool name. Any tool except End. |
tool_ | Documented | Input | The tool arguments. The shape depends on the tool (see below). File paths are absolute. |
tool_ | Documented | Input | The tool call ID. |
permission | Documented | Output, in hook | allow, deny, ask, or defer. allow skips the prompt but not deny or ask rules. Order of strength: deny, then defer, then ask, then allow. defer works only in - with one tool call. |
permission | Documented | Output, in hook | The reason text. For ask it shows in the prompt. For deny it goes to Claude. Otherwise it goes to the debug log. |
updated | Documented | Output, in hook | Replaces the whole tool input. Rules and background checks use the new input. Needed with allow for Ask and Exit. Ignored with defer. |
additional | Documented | Output, in hook | Text placed next to the tool result. Ignored with defer. |
permission | Undocumented | Output, in hook | Words for a permission card. For the desktop host only. An object with title (200 characters), description (2000), and display (64). Ignored, with a debug line, if the text cannot be shown. |
Top-level decision and reason | Differs | Output | approve maps to allow, and block maps to deny. Use permission instead. |
ask label | Documented | Behavior | The prompt shows [settings], [plugin:, or [skill]. An ask also forces a prompt in auto mode. |
Tool Input Shapes
| Tool | Status | Keys in tool_input |
|---|---|---|
Bash | Documented | command, description, timeout (milliseconds), run_ |
Power | Documented | The same keys as Bash. Match with Bash|Power. |
Write | Documented | file_, content |
Edit | Documented | file_, old_, new_, replace_ |
Read | Documented | file_, offset, limit |
Glob | Documented | pattern, path |
Grep | Documented | pattern, path, glob, output_, -, multiline |
Web | Documented | url, prompt, offset (2.1.290) |
Web | Documented | query, allowed_, blocked_ |
Agent | Documented | prompt, description, subagent_, model |
Ask | Documented | questions, and answers (set only through updated) |
Exit | Documented | Claude Code adds plan and plan. The old allowed key is accepted and ignored. |
The docs name Workflow as a tool you can match, but give no input shape for it.
PermissionRequest
Fires when a permission prompt would show, or when a call that cannot prompt would be denied.
Exit 2 is not honored here. Deny with the decision object instead.
There is no event for a sandbox network request.
Handlers: command, http, mcp_tool, and prompt. An agent hook is skipped.
| Field | Status | Direction | What it does |
|---|---|---|---|
tool_, tool_ | Documented | Input | The same as in Pre. There is no tool_. |
permission_ | Documented | Input | Updates that Claude Code suggests. The same shape as updated. A dialog may show other options. |
decision. | Documented | Output, in hook | allow or deny. Deny and ask rules still apply. |
decision. | Documented | Output | New tool input. allow only. Checked again against deny and ask rules. |
decision. | Documented | Output | Permission updates to apply. allow only. |
decision. | Documented | Output | Why it was denied. deny only. Goes to Claude. |
decision. | Documented | Output | Stops Claude. deny only. |
Permission Update Entries
These entries are used in updatedPermissions and permission_suggestions.
| Entry | Status | What it does | Fields |
|---|---|---|---|
add, replace, remove | Documented | Change permission rules. | rules (each {tool), behavior (allow, deny, ask), destination |
set | Documented | Change the permission mode. | mode: default, auto, accept, dont, bypass, plan. bypass works only if bypass was on at launch. |
add, remove | Documented | Change working directories. | directories |
destination | Differs | Where Claude Code keeps the change. | session, local, project, user |
PermissionDenied
Fires only when auto mode denies a call, including a denial with no classifier verdict.
It does not fire for manual denials, PreToolUse blocks, or deny rules.
The exit code and stderr are ignored.
All five handler types are allowed, but output from prompt and agent is dropped.
| Field | Status | Direction | What it does |
|---|---|---|---|
tool_, tool_, tool_, mcp_ | Documented | Input | As in Pre. |
reason | Documented | Input | Why auto mode denied. A rule name in brackets, such as [Data Exfiltration]. |
retry | Documented | Output, in hook | true tells the model it may retry. The denial stands. Ignored for denials with no verdict. |
Tool Result Events
These events fire after a tool runs. PostToolUse and PostToolUseFailure match on tool name. PostToolBatch has no matcher.
All three accept the five handler types.
PostToolUse
Fires after a tool call succeeds.
Exit 2 shows stderr to Claude but does not undo the tool.
It does not see writes made by Bash or by outside processes. Use FileChanged for those.
| Field | Status | Direction | What it does |
|---|---|---|---|
tool_, tool_, tool_, mcp_ | Documented | Input | As in Pre. |
tool_ | Documented | Input | The structured tool output. The shape depends on the tool. |
duration_ | Documented | Input | Run time in milliseconds. Leaves out permission prompts and Pre hooks. Optional. |
decision, reason | Documented | Output | block adds the reason next to the result. Claude still sees the original output. |
additional | Documented | Output, in hook | Text next to the result. Not delivered for async hooks. |
updated | Documented | Output, in hook | Replaces what Claude sees. Must match the tool output shape. For built-in tools a bad shape is ignored. The tool already ran. |
updated | Documented | Output, in hook | The same, for MCP tools only. Prefer updated. |
classifier | Documented | Output, in hook | A note for the auto mode classifier. Needs 2.1.236. At most 2,000 characters for one call. Dropped for async hooks and read-only calls. Treated as unverified context. |
tool_ | Documented | Input | Files that a Bash run changed. Needs 2.1.269, a public beta, and the setting bash. Keys: changed (200), files (5), more, unavailable, skipped, shared. |
tool_ of Agent | Documented | Input | status (completed or async_), agent, content, resolved, models, total, total, total, usage, and output for a background launch. |
tool_ of Exit | Documented | Input | plan and file. |
Subagent tool | Documented | Matcher | The tool that carries a subagent report in auto mode. Match it to read tool_. Needs 2.1.271. |
PostToolUseFailure
Fires when a started tool fails, or an MCP tool returns an error.
It does not fire for unknown tools, schema errors, or permission denials.
Exit 2 shows stderr to Claude.
| Field | Status | Direction | What it does |
|---|---|---|---|
tool_, tool_, tool_, mcp_ | Documented | Input | As in Post. |
error | Documented | Input | What went wrong. The same text as the tool result. Bash and Power errors start with Exit code N. |
is_ | Documented | Input | true for an abort. Canceling a running tool does not fire this hook. |
duration_ | Documented | Input | Run time in milliseconds. Optional. |
additional | Documented | Output, in hook | Text next to the error. A top-level decision: also works. |
PostToolBatch
Fires once after all tool calls of a batch resolve, before the next model request.
Exit 2, decision: "block", or continue: false stops the loop.
| Field | Status | Direction | What it does |
|---|---|---|---|
tool_ | Documented | Input | One entry per call, with tool_, tool_, tool_, and tool_. |
tool_ | Documented | Input | What the model gets in the tool_. A serialized string or content blocks. It is not the Post object. |
additional | Documented | Output, in hook | Context for the next request. Sent once. |
Session Events
These events fire when a session starts or ends, and when its settings, files, or folders change.
SessionStart
Fires when a session starts or resumes.
Interactive starts run it in the background, but the first reply waits for it.
Exit 2 shows stderr to you only.
Handlers: command and mcp_tool (skipped at launch).
| Field | Status | Direction | What it does |
|---|---|---|---|
source | Documented | Input | How the session began: startup, resume, clear, compact, fork. This is the matcher. |
model | Documented | Input | The active model ID. Can be missing, for example after /. |
agent_ | Documented | Input | The agent name from --. Optional. |
session_ | Documented | Input | The custom title. Present only when one exists. |
seconds_, context_, prompt_, estimated_ | Documented | Input | The cost of a stale resume. Only for resume and fork with an earlier reply. Needs 2.1.251. |
additional | Documented | Output, in hook | Text before the first prompt. Plain stdout works too. |
initial | Documented | Output | The first user message. Only in -. From a plugin it works only if the plugin was installed before the start. |
session | Documented | Output | Sets the title. Works for startup, resume, fork. Same as /. |
watch | Documented | Output | Absolute paths for File to watch. |
reload | Documented | Output | Scans the skill and command folders again. Use it after a hook installs skills. |
Setup
Fires for --init-only, or for --init or --maintenance with -p. It does not fire on a normal start.
--init-only also runs SessionStart with startup.
Handler: command only.
| Field | Status | Direction | What it does |
|---|---|---|---|
Setup event | Gated | Event | See the flags above. |
trigger | Documented | Input | init or maintenance. It is also the matcher. |
additional | Differs | Output | Treat it as not delivered. Not verified in 2.. |
CLAUDE_ | Documented | Environment | Persists environment variables, as for Session. |
SessionEnd
Fires when a session ends.
The budget is 1.5 seconds for all hooks together. Exit 2 shows stderr to you. JSON is dropped.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
reason | Documented | Input | Why it ended: clear, resume, logout, prompt_, other. This is the matcher. |
InstructionsLoaded
Fires when CLAUDE.md or a .claude/rules/*.md file loads.
It runs async and has no decision. It does not fire for an AGENTS.md file read directly.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
file_ | Documented | Input | The absolute path of the file. |
memory_ | Documented | Input | User, Project, Local, or Managed. |
load_ | Documented | Input | session_, nested_, path_, include, compact. This is the matcher. |
globs, trigger_, parent_ | Documented | Input | Extra data for lazy and include loads. globs is only for path_. |
ConfigChange
Fires when a settings, managed policy, or skill file changes.
It does not fire for server-managed or MDM changes.
Exit 2 or decision: "block" stops the change, except for policy_settings.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
source | Documented | Input | user_, project_, local_, policy_, skills. This is the matcher. |
file_ | Documented | Input | The changed file. Optional. |
decision, reason | Documented | Output | block keeps the old settings. Nobody sees reason. system and continue are dropped. |
CwdChanged
Fires when a shell command in the main conversation changes the directory.
It has no matcher and cannot block.
CLAUDE_ENV_FILE is cleared at the next event.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
old_, new_ | Documented | Input | The two directories. |
watch | Documented | Output, in hook | Replaces the dynamic watch list. An empty array clears it. system shows as a short notice. continue is dropped. |
FileChanged
Fires when a watched file changes on disk.
A file watcher drives it, not tool calls.
The matcher names the files to watch, and Claude Code filters by base name.
It cannot block.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
file_ | Documented | Input | The absolute path. |
event | Documented | Input | change, add, or unlink. |
watch | Documented | Output, in hook | Replaces the dynamic watch list. The watcher starts only when something names a file. |
DirectoryAdded
Fires after /add-dir, or after the SDK register_repo_root request.
It runs in the background with a 600 second timeout.
It does not fire for --add-dir, /permissions, or a directory Claude Code already knows.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
directory | Documented | Input | The absolute path. |
source | Documented | Input | slash_ or register_. This is the matcher. system goes to Claude for slash_ and to the debug log otherwise. |
Prompt and Turn Events
These events fire around a turn: when you send a prompt, while text shows, when Claude Code sends a notification, and when Claude stops.
UserPromptSubmit
Fires when you submit a prompt, before Claude reads it.
It has no matcher. It also fires for scheduled tasks, background subagent reports, and messages from other sessions.
The default timeout is 30 seconds.
Exit 2 blocks the prompt. Plain stdout is added as context.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
prompt | Documented | Input | The text. A typed / arrives as typed, not expanded. Pasted text arrives expanded. |
source | Undocumented | Input | Who made the prompt: user, sdk, system, loop_, schedule_, poll_. May be missing. |
session_ | Documented | Input | The custom title, only when one is set. |
decision, reason | Documented | Output | block stops the prompt. You see reason. It is not added to context. |
additional | Documented | Output, in hook | Context placed next to the prompt. |
session | Documented | Output | Sets the session title. |
suppress | Documented | Output | Leaves the prompt text out of the block message. Otherwise the block message ends with Original prompt: and is written to the transcript. |
UserPromptExpansion
Fires when a typed command expands into a prompt.
The matcher is command_name.
It covers typing /skill, which skips PreToolUse.
Exit 2 blocks. Plain stdout is context.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
expansion_ | Documented | Input | slash_ or mcp_. |
command_, command_, prompt | Documented | Input | The command parts and the raw line. |
command_ | Documented | Input | Where the command came from, such as plugin. Optional. |
decision, reason | Documented | Output | block stops the expansion. |
additional, suppress | Documented | Output, in hook | As in User. |
MessageDisplay
Fires while assistant text streams, once for each batch of finished lines.
It has no matcher. The timeout is 10 seconds.
It only changes what you see. The transcript and Claude keep the original.
In -p mode it runs once with the full text.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
turn_, message_ | Documented | Input | UUIDs of the turn and the message. message_ is stable for the whole message. |
index, final | Documented | Input | The position of the batch. final is true on the last one. |
delta | Documented | Input | The new lines. Whole lines, except in the final batch. |
display | Documented | Output, in hook | Text shown in place of delta. If the hook fails, the original shows. system and continue are dropped. |
Notification
Fires when Claude Code sends a notification.
The matcher is the notification type.
It runs even if desktop notifications are off.
The exit code and stderr are ignored, but terminalSequence still works.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
message, title, notification_ | Documented | Input | The text, an optional title, and the type. |
permission_ | Documented | Type | A prompt waited about 6 seconds. |
idle_ | Documented | Type | The session was idle for about 60 seconds. Both depend on typing and running agents. |
auth_, elicitation_, elicitation_, elicitation_, elicitation_ | Documented | Type | Auth finished, and the steps of an MCP question. The two dialog types wait 6 seconds. |
agent_, agent_ | Documented | Type | Background session events in agent view. agent_ for a teammate setup question needs 2.1.248. |
quota_, quota_, quota_ | Documented | Type | Usage limit wait events. Need 2.1.234. |
auth_, computer_, computer_, plugin_, push_, worker_ | Undocumented | Type | Other values that the program passes as notification. plugin_ comes from the mod call $.. Whether each one reaches a hook is not verified. |
Stop
Fires when the main agent finishes. It does not fire on a user interrupt.
It has no matcher.
Exit 2 or decision: "block" keeps Claude working.
The cap is 8 continuations in a row, set by CLAUDE_CODE_STOP_HOOK_BLOCK_CAP.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
stop_ | Documented | Input | true when a stop hook already continued the turn. Check it to avoid loops. |
last_ | Documented | Input | The text of the final reply. Use it instead of the transcript. |
background_ | Documented | Input | Tasks still running. Each has id, type, status, description, and some of command, agent_, server, tool, name by type. Text is cut at 1000 characters. |
session_ | Documented | Input | Scheduled wakeups. Each has id, schedule, recurring, prompt. |
decision, reason | Documented | Output | block stops Claude from stopping. reason is required. It becomes the next instruction. |
additional | Documented | Output, in hook | Feedback that keeps the turn going. Labeled Stop hook feedback, not an error. |
StopFailure
Fires instead of Stop when the turn ends on an API error.
The matcher is error.
Output and the exit code are ignored, but terminalSequence works.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
error | Differs | Input | The error type. See the list on Configuration. |
error_ | Documented | Input | More detail. Optional. |
last_ | Documented | Input | The rendered API error text. It is not Claude's own words, unlike in Stop. |
Agent and Task Events
These events tell your hooks when a subagent, a task, or a teammate starts, stops, or goes idle. Teammates belong to agent teams. See Subagent Runtime.
SubagentStart
Fires when a subagent starts or resumes, and for each message of an in-process teammate.
The matcher is the agent type.
It cannot block. Exit 2 shows stderr in the subagent transcript only.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
agent_, agent_ | Documented | Input | The subagent ID and type. A plugin agent type is my-. Anchor the matcher with ^ and $. |
additional | Documented | Output, in hook | Context for the subagent before its first prompt. On a repeat run it is added only if the earlier copy is gone, to keep the cache. |
SubagentStop
Fires when a subagent finishes.
The matcher is the agent type.
Exit 2 or decision: "block" keeps it running, and reason is its next instruction.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
stop_, last_, background_, session_ | Documented | Input | As in Stop. The two arrays are scoped to the parent session. |
agent_, agent_ | Documented | Input | The subagent ID and type. agent_ can be empty for internal agents, such as prompt suggestions and /. A named matcher does not match an empty type. |
agent_ | Documented | Input | The subagent transcript, in a nested subagents/ folder. transcript_ is the main one. |
additional | Documented | Output, in hook | Non-error feedback that keeps the subagent running. Same loop guards as Stop. |
TaskCreated
Fires when TaskCreate makes a task.
It has no matcher. It does not fire in a session without the Task tools.
Exit 2 or decision: "block" deletes the task and gives the message to Claude.
continue: false is ignored.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
task_, task_ | Documented | Input | The task ID and title. |
task_, teammate_ | Documented | Input | Optional detail and the creator. May be absent. |
team_ | Documented | Input | The session team name. Deprecated, to be removed. |
agent_ | Documented | Input | The creating subagent or teammate. Needs 2.1.290. May be absent. |
TaskCompleted
Fires when a task is marked done, or when a teammate ends its turn with open tasks.
It has no matcher.
Exit 2 keeps the task open, and stderr goes to the model.
continue: false stops a teammate, and is ignored when TaskUpdate caused the event.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
task_, task_, task_, teammate_ | Documented | Input | As in Task. |
team_, agent_ | Documented | Input | The deprecated team name, and the acting agent. agent_ needs 2.1.290. |
TeammateIdle
Fires when an agent team teammate is about to go idle.
It has no matcher.
Exit 2 gives stderr to the teammate, and it keeps working. continue: false stops it.
Handlers: all five types.
| Field | Status | Direction | What it does |
|---|---|---|---|
teammate_, team_ | Documented | Input | The teammate and the deprecated team name. |
agent_ | Documented | Input | The in-process teammate. Needs 2.1.290. May be absent. |
Other Events
These events cover compaction, model switches, MCP questions, and worktrees.
None of them accepts prompt or agent handlers.
PreCompact and PostCompact
PreCompact fires before a compaction. PostCompact fires after it.
The matcher is trigger.
For PreCompact, exit 2 or decision: "block" blocks it.
Blocking a proactive auto compaction skips it. Blocking a recovery compaction shows the API error.
PostCompact has no decision. Exit 2 shows stderr to you.
Handlers: command, http, mcp_tool.
For the compaction process, see Context and Compaction.
| Field | Status | Event | What it does |
|---|---|---|---|
trigger | Documented | Both, input | manual or auto. auto includes idle compaction. |
custom_ | Documented | Pre, input | The text after /. null for auto or when empty. |
compact_ | Documented | Post, input | The summary that Claude Code made. |
PreModelSwitch and PostModelSwitch
Both need 2.1.251.
The matcher is the canonical name of to_model.
Handlers: command, http, mcp_tool.
For how a model is chosen, see Models.
PreModelSwitch fires before a requested switch: /model, the picker, /config, fast mode, or set_model.
It does not fire for automatic fallback or resume.
The timeout is 30 seconds, and a timeout blocks.
Exit 2 or decision: "block" cancels the switch.
PostModelSwitch fires after the model changes, also on fallback, opusplan, and resume.
It cannot block. It does not fire for a one-turn fallback chain.
Plain stdout is context. Exit 2 shows stderr as a notice.
| Field | Status | Direction | What it does |
|---|---|---|---|
from_, to_, requested_ | Documented | Input | The model IDs and the name you asked for. requested_ is null for the default. |
source | Documented | Input | command, picker, or sdk. Post adds auto and resume. |
context_, prompt_, cache_ | Documented | Input | The cost of sending the context again. cache_ is 5m or 1h. |
estimated_, pricing | Documented | Input | The estimate and its basis. pricing is configured, catalog, or default. |
permission, permission | Documented | Output, Pre | allow, deny, ask, and the reason. ask works only in interactive /, else it is a refusal. No defer, updated, or additional. Strength order: deny, ask, allow. |
additional | Documented | Output, Post | Text for the next request. If the hook is late by 5 seconds, it goes to the request after. |
Elicitation and ElicitationResult
An elicitation is a question that an MCP server asks you.
The matcher for both events is the server name.
Handlers: command, http, mcp_tool.
Elicitation fires when the server asks. A hook can answer, so no dialog shows. Exit 2 declines.
reason, systemMessage, and continue are dropped.
ElicitationResult fires after you answer, before the answer goes to the server. It also runs on decline and cancel.
| Field | Status | Direction | What it does |
|---|---|---|---|
mcp_, message | Documented | Elicitation, input | The server and the prompt text. |
mode, url, elicitation_, requested_ | Documented | Elicitation, input | form or url mode, the URL, the ID, and the form schema. Optional. |
action, content | Documented | Elicitation, output | accept, decline, cancel, and the form values. Read only on exit 0. A hook answer skips Elicitation hooks. A decline beats an accept. |
decision: | Documented | Elicitation, output | Declines. Works from 2.1.284. Beats action. |
action, content, mode, elicitation_ | Documented | Elicitation, input | Your answer. action is accept, decline, or cancel. |
action, content | Documented | Elicitation, output | Change or block the answer. content replaces the whole object. An output with no action is ignored. cancel still sends your values. |
WorktreeCreate and WorktreeRemove
WorktreeCreate replaces the default git worktree step.
It fires for --worktree, EnterWorktree, isolation: "worktree", workflows, background sessions, and remote control.
It has no matcher. Any non-zero exit fails it.
.worktreeinclude is not processed.
WorktreeRemove cleans up a worktree that a WorktreeCreate hook made.
It has no matcher. Exit 0 counts as removed. A non-zero exit fails the removal if the folder still exists.
Claude Code keeps a subagent worktree. JSON is dropped.
Handlers: command, http, mcp_tool.
| Field | Status | Direction | What it does |
|---|---|---|---|
name | Documented | Worktree, input | The slug of the new worktree, such as bold-. |
Path on stdout | Documented | Worktree, output | A command hook prints the path as its last non-empty line. ANSI codes are stripped. A relative path resolves against the hook folder. Absolute paths with . or .., and paths through a repo symlink, are refused. |
worktree | Documented | Worktree, output | An HTTP hook returns the path here. A command hook cannot return JSON, so it cannot use terminal. |
worktree_ | Documented | Worktree, input | The absolute path to remove. |
Related Pages
- Hooks: the overview.
- Configuration: matchers and timeouts.
- Input and Output: common fields, decisions, and exit codes.
- Subagent Runtime: subagents and teams.
Source: Hooks Reference, the HookInput types in the program type file, and the hook output schema in the program.
Not verified: any input shape for Workflow, Skill, and MCP tools beyond tool_input being unknown; the output schema of each built-in tool for updatedToolOutput (the docs give only Bash: stdout, stderr, interrupted, isImage).