Follow Discord
Sweep 08 Oct 2026 · 18:53Z Build v2.1.295 516 read Stable v2.1.286 Latest v2.1.295 Next v2.1.295 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · claude-code

Hooks reference changedhooks

Nearest release: v2.1.295, published an hour before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Upstream edited this page at 8 Oct 2026 20:22 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 8 Oct 2026 20:37 UTC.

Upstream edited
Recorded here
Lines+185added
Lines−25removed
From line 878 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits92to this page, all time

#### Other ways to decline an elicitation #### Answer a form request from a script

The whole hunk

from line 878, old and new numbered
/
lines
from line 878
878878| `PostCompact` | No | Shows stderr to user only |
879879| `PreModelSwitch` | Yes | Blocks the model switch and shows stderr to the user |
880880| `PostModelSwitch` | No | Shows stderr to user only; the model already switched |
881| `Elicitation` | Yes | Denies the elicitation |
881| `Elicitation` | Yes | Declines the request, and no dialog appears |
882882| `ElicitationResult` | Yes | Blocks the response (action becomes decline) |
883883| `WorktreeCreate` | Yes | Any non-zero exit code causes worktree creation to fail |
884884| `WorktreeRemove` | Yes | Any non-zero exit code causes worktree removal to fail if the directory still exists afterward. See [WorktreeRemove](#worktreeremove) for what happens to the directory |
from line 1025
10251025| PermissionDenied | `hookSpecificOutput` | `retry: true` tells the model it may retry the denied tool call; Claude Code ignores it for [no-verdict denials](#permissiondenied-decision-control) |
10261026| WorktreeCreate | path return | Command hook prints path on stdout; HTTP hook returns `hookSpecificOutput.worktreePath`. Hook failure or missing path fails creation |
10271027| WorktreeRemove | Exit code | Any non-zero exit code makes the removal fail if the directory still exists afterward. JSON output is discarded |
1028| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values for accept) |
1029| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values override) |
1028| Elicitation, ElicitationResult | `hookSpecificOutput` or top-level `decision` | `action` (accept/decline/cancel), `content` (form field values). `decision: "block"` also [declines](#other-ways-to-decline-an-elicitation) |
10301029| MessageDisplay | `hookSpecificOutput` | `displayContent` replaces the displayed text on screen. Display-only: the transcript and what Claude sees keep the original |
10311030| SessionStart, SubagentStart, PostModelSwitch | Context only | `hookSpecificOutput.additionalContext` adds context for Claude. SessionStart also accepts [`initialUserMessage`, `watchPaths`, `sessionTitle`, and `reloadSkills`](#sessionstart-decision-control). No blocking or decision control |
10321031| Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged | None | No decision control. Used for side effects like logging or cleanup |
from line 3400
34013400 
34023401Runs when an MCP server requests user input mid-task. By default, Claude Code shows an interactive dialog for the user to respond. Hooks can intercept this request and respond programmatically, skipping the dialog entirely.
34033402 
3403For a complete hook with its settings entry and script, see [Answer a form request from a script](#answer-a-form-request-from-a-script).
3404 
34043405The matcher field matches against the MCP server name.
34053406 
34063407#### Elicitation input
from line 3445
34443445 
34453446#### Elicitation output
34463447 
3447To respond programmatically without showing the dialog, return a JSON object with `hookSpecificOutput`:
3448An Elicitation hook can answer the request for the user, decline or cancel it, or leave it to the dialog. To answer, decline, or cancel, exit 0 and print a `hookSpecificOutput` object with an `action`. The server gets your answer and no dialog appears. Each row of this table shows what to return for one outcome and what the MCP server receives:
34483449 
3450| To | Return | The server receives |
3451| :- | :- | :- |
3452| Answer for the user | `"action": "accept"`, with the form field values in `content` | `accept` with your `content` |
3453| Decline the request | `"action": "decline"` | `decline` |
3454| Cancel the request | `"action": "cancel"` | `cancel` |
3455| Leave the request to the user | No output, with exit code 0 | The user's answer from the [dialog](/docs/en/mcp#respond-to-mcp-elicitation-requests) |
3456 
3457This output answers the form-mode request shown under [Elicitation input](#elicitation-input). The keys in `content` are the property names from that request's `requested_schema`:
3458 
34493459```json theme={null}
34503460{
34513461 "hookSpecificOutput": {
from line 3468
34583468}
34593469```
34603470 
3461| Field | Values | Description |
3462| :- | :- | :- |
3463| `action` | `accept`, `decline`, `cancel` | Whether to accept, decline, or cancel the request |
3464| `content` | object | Form field values to submit. Only used when `action` is `accept` |
3471This output declines a request:
34653472 
3466Exit code 2 denies the elicitation. Claude Code doesn't show your stderr message anywhere.
3473```json theme={null}
3474{
3475 "hookSpecificOutput": {
3476 "hookEventName": "Elicitation",
3477 "action": "decline"
3478 }
3479}
3480```
34673481 
3468Claude Code acts on `hookSpecificOutput` from an Elicitation hook's JSON output and discards `systemMessage` and `continue`.
3482In the dialog, selecting **Decline** sends `decline` and pressing `Esc` sends `cancel`, so return the one you want the server to see.
34693483 
3484For a URL-mode request, a hook that returns `accept` skips the dialog, so the URL never opens.
3485 
3486Claude Code discards `reason`, `systemMessage`, and `continue` from an Elicitation hook's JSON output, whichever `action` you return.
3487 
3488#### Other ways to decline an elicitation
3489 
3490Your hook can also decline in these ways. The server receives the same `decline` as for `"action": "decline"`:
3491 
3492* **Exits with code 2**: Claude Code ignores a `hookSpecificOutput` printed by the same hook
3493* **Prints a top-level `"decision": "block"`**: the block overrides an `action` in the same output
3494 
3495When several hooks match the same request, a decline from one of them overrides an `accept` or `cancel` from another.
3496 
3497This script declines URL-mode requests and leaves form requests to the dialog:
3498 
3499```bash theme={null}
3500#!/bin/bash
3501if [ "$(jq -r '.mode')" = "url" ]; then
3502 exit 2
3503fi
3504```
3505 
3506Neither the user nor the server sees why your hook declined, because Claude Code doesn't show your stderr or your `reason`.
3507 
3508Claude Code ignored a top-level `decision` from `Elicitation` and `ElicitationResult` hooks from v2.1.105 until the fix in v2.1.284.
3509 
3510#### Answer a form request from a script
3511 
3512This example answers one recurring question for the user. An MCP server named `issue-tracker` asks for a project key in a form, and the hook fills in `DOCS`. The script accepts when `project_key` is the form's single field. For any other request it prints nothing, so the dialog appears.
3513 
3514<Tabs>
3515 <Tab title="macOS/Linux">
3516 Register a command hook for the event in your settings file, with the server name as the matcher:
3517 
3518 ```json theme={null}
3519 {
3520 "hooks": {
3521 "Elicitation": [
3522 {
3523 "matcher": "issue-tracker",
3524 "hooks": [
3525 {
3526 "type": "command",
3527 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/answer-project-key.sh",
3528 "args": []
3529 }
3530 ]
3531 }
3532 ]
3533 }
3534 }
3535 ```
3536 
3537 Save this script to `.claude/hooks/answer-project-key.sh` in your project and make it executable with `chmod +x`:
3538 
3539 ```bash theme={null}
3540 #!/bin/bash
3541 input=$(cat)
3542 fields=$(jq -c '.requested_schema.properties // {} | keys' <<<"$input")
3543 
3544 if [ "$fields" = '["project_key"]' ]; then
3545 jq -n '{hookSpecificOutput: {hookEventName: "Elicitation", action: "accept", content: {project_key: "DOCS"}}}'
3546 fi
3547 ```
3548 </Tab>
3549 
3550 <Tab title="Windows (PowerShell)">
3551 Register a command hook that runs the script through PowerShell, with the server name as the matcher:
3552 
3553 ```json theme={null}
3554 {
3555 "hooks": {
3556 "Elicitation": [
3557 {
3558 "matcher": "issue-tracker",
3559 "hooks": [
3560 {
3561 "type": "command",
3562 "command": "powershell.exe",
3563 "args": [
3564 "-NoProfile",
3565 "-ExecutionPolicy",
3566 "Bypass",
3567 "-File",
3568 "${CLAUDE_PROJECT_DIR}/.claude/hooks/answer-project-key.ps1"
3569 ]
3570 }
3571 ]
3572 }
3573 ]
3574 }
3575 }
3576 ```
3577 
3578 Save this script to `.claude/hooks/answer-project-key.ps1` in your project:
3579 
3580 ```powershell theme={null}
3581 $request = [Console]::In.ReadToEnd() | ConvertFrom-Json
3582 $fields = @($request.requested_schema.properties.PSObject.Properties.Name)
3583 
3584 if ($fields.Count -eq 1 -and $fields[0] -eq 'project_key') {
3585 @{
3586 hookSpecificOutput = @{
3587 hookEventName = "Elicitation"
3588 action = "accept"
3589 content = @{ project_key = "DOCS" }
3590 }
3591 } | ConvertTo-Json -Depth 3
3592 }
3593 ```
3594 </Tab>
3595</Tabs>
3596 
3597To confirm the hook works, start Claude Code with `claude --debug` and give Claude a task that makes the server ask for the project key. No dialog appears, and the [debug log](#debug-hooks) has a line that ends with `Elicitation resolved by hook: {"action":"accept","content":{"project_key":"DOCS"}}`.
3598 
34703599### ElicitationResult
34713600 
34723601Runs after a user responds to an MCP elicitation. Hooks can observe, modify, or block the response before it is sent back to the MCP server.
34733602 
3603When an [Elicitation](#elicitation) hook answers a request, Claude Code sends that answer to the server without running ElicitationResult hooks.
3604 
34743605The matcher field matches against the MCP server name.
34753606 
34763607#### ElicitationResult input
from line 3617
34863617 "mcp_server_name": "my-mcp-server",
34873618 "action": "accept",
34883619 "content": { "username": "alice" },
3489 "mode": "form",
3490 "elicitation_id": "elicit-123"
3620 "mode": "form"
34913621}
34923622```
34933623 
34943624#### ElicitationResult output
34953625 
3496To override the user's response, return a JSON object with `hookSpecificOutput`:
3626An ElicitationResult hook can let the user's response through, change its values, or block it. To change or block the response, exit 0 and print a `hookSpecificOutput` object with an `action`. Each row of this table shows what to return for one outcome and what the MCP server receives:
34973627 
3628| To | Return | The server receives |
3629| :- | :- | :- |
3630| Let the response through | No output, with exit code 0 | The user's response, unchanged |
3631| Change the submitted values | `"action": "accept"`, with the new values in `content` | `accept` with your `content` in place of the user's values |
3632| Block the response | `"action": "decline"` | `decline`, without the user's values |
3633| Cancel the request | `"action": "cancel"` | `cancel`, along with the values the user submitted. To withhold them, return `"decline"` |
3634 
3635This output changes the response shown under [ElicitationResult input](#elicitationresult-input), so the server receives `[email protected]` where the user submitted `alice`:
3636 
34983637```json theme={null}
34993638{
35003639 "hookSpecificOutput": {
35013640 "hookEventName": "ElicitationResult",
3502 "action": "decline",
3503 "content": {}
3641 "action": "accept",
3642 "content": {
3643 "username": "[email protected]"
3644 }
35043645 }
35053646}
35063647```
35073648 
3508| Field | Values | Description |
3509| :- | :- | :- |
3510| `action` | `accept`, `decline`, `cancel` | Overrides the user's action |
3511| `content` | object | Overrides form field values. Only meaningful when `action` is `accept` |
3649Your `content` replaces the user's whole `content` object, so include the fields you aren't changing. Return `action` along with it, because Claude Code ignores a `hookSpecificOutput` that has no `action`.
35123650 
3513Exit code 2 blocks the response, changing the effective action to `decline`. Claude Code doesn't show your stderr message anywhere.
3651ElicitationResult hooks also run when the user declines or cancels, and your `action` replaces theirs. Check that the input's `action` is `accept` before you return `accept`, or your hook turns a declined request into an accepted one. This script makes the same change when the user accepted, keeps the other fields, and prints nothing otherwise:
35143652 
3515Claude Code acts on `hookSpecificOutput` from an ElicitationResult hook's JSON output and discards `systemMessage` and `continue`.
3653```bash theme={null}
3654#!/bin/bash
3655input=$(cat)
3656 
3657if [ "$(jq -r '.action' <<<"$input")" = "accept" ]; then
3658 jq '{hookSpecificOutput: {hookEventName: "ElicitationResult", action: "accept", content: (.content + {username: (.content.username + "@example.com")})}}' <<<"$input"
3659fi
3660```
3661 
3662This output blocks the response:
3663 
3664```json theme={null}
3665{
3666 "hookSpecificOutput": {
3667 "hookEventName": "ElicitationResult",
3668 "action": "decline"
3669 }
3670}
3671```
3672 
3673Exit code 2 and a top-level `"decision": "block"` also block the response. [Other ways to decline an elicitation](#other-ways-to-decline-an-elicitation) covers which one takes effect when a hook combines them, what the user sees, and which versions ignored `decision`.
3674 
3675Claude Code discards `reason`, `systemMessage`, and `continue` from an ElicitationResult hook's JSON output, whichever `action` you return.
35163676 
35173677## Prompt-based hooks
35183678 
Feedback