476| `async` | 否 | 如果为 `true`,在后台运行而不阻止。请参阅 [在后台运行 hooks](#run-hooks-in-the-background) |476| `async` | 否 | 如果为 `true`,在后台运行而不阻止。请参阅 [在后台运行 hooks](#run-hooks-in-the-background) |
477| `asyncRewake` | 否 | 如果为 `true`,在后台运行并在退出代码 2 时唤醒 Claude。hook 的 stderr 或 stdout(如果 stderr 为空)显示给 Claude 作为 [系统提醒](/docs/zh-CN/glossary#system-reminder),以便它可以对长时间运行的后台失败做出反应 |477| `asyncRewake` | 否 | 如果为 `true`,在后台运行并在退出代码 2 时唤醒 Claude。hook 的 stderr 或 stdout(如果 stderr 为空)显示给 Claude 作为 [系统提醒](/docs/zh-CN/glossary#system-reminder),以便它可以对长时间运行的后台失败做出反应 |
478| `shell` | 否 | 用于此 hook 的 shell。接受 `"bash"` 或 `"powershell"`。默认为 `"bash"`,或在未安装 Git Bash 时在 Windows 上默认为 `"powershell"`。设置 `"powershell"` 在 Windows 上通过 PowerShell 运行命令。不需要 `CLAUDE_CODE_USE_POWERSHELL_TOOL`,因为 hooks 直接生成 PowerShell。设置 `args` 时被忽略 |478| `shell` | 否 | 用于此 hook 的 shell。接受 `"bash"` 或 `"powershell"`。默认为 `"bash"`,或在未安装 Git Bash 时在 Windows 上默认为 `"powershell"`。设置 `"powershell"` 在 Windows 上通过 PowerShell 运行命令。不需要 `CLAUDE_CODE_USE_POWERSHELL_TOOL`,因为 hooks 直接生成 PowerShell。设置 `args` 时被忽略 |
479| `onFailure` | 否 | hook 失败时对该操作的处理方式:`"continue"`(默认值)或 `"block"`。请参阅 [在 hook 失败时阻止操作](#block-the-action-when-a-hook-fails)。需要 Claude Code v2.1.295 或更高版本 |
479 480
480<a id="exec-form-and-shell-form" />481<a id="exec-form-and-shell-form" />
481 482
533| `url` | 是 | 发送 POST 请求的 URL |534| `url` | 是 | 发送 POST 请求的 URL |
534| `headers` | 否 | 其他 HTTP 标头作为键值对。值支持使用 `$VAR_NAME` 或 `${VAR_NAME}` 语法的环境变量插值。仅解析 `allowedEnvVars` 中列出的变量 |535| `headers` | 否 | 其他 HTTP 标头作为键值对。值支持使用 `$VAR_NAME` 或 `${VAR_NAME}` 语法的环境变量插值。仅解析 `allowedEnvVars` 中列出的变量 |
535| `allowedEnvVars` | 否 | 可能被插值到标头值中的环境变量名称列表。对未列出变量的引用被替换为空字符串。任何环境变量插值都需要 |536| `allowedEnvVars` | 否 | 可能被插值到标头值中的环境变量名称列表。对未列出变量的引用被替换为空字符串。任何环境变量插值都需要 |
537| `onFailure` | 否 | hook 失败时对该操作的处理方式:`"continue"`(默认值)或 `"block"`。请参阅 [在 hook 失败时阻止操作](#block-the-action-when-a-hook-fails)。需要 Claude Code v2.1.295 或更高版本 |
536 538
537Claude Code 将 hook 的 [JSON 输入](#hook-input-and-output) 作为 POST 请求体发送,`Content-Type: application/json`。响应体使用与命令 hooks 相同的 [JSON 输出格式](#json-output)。539Claude Code 将 hook 的 [JSON 输入](#hook-input-and-output) 作为 POST 请求体发送,`Content-Type: application/json`。响应体使用与命令 hooks 相同的 [JSON 输出格式](#json-output)。
538 540
821 退出码输出823 退出码输出
822</h3>824</h3>
823 825
824来自 hook 命令的退出码告诉 Claude Code 该操作是否应继续、被阻止或被忽略。退出码不单独起作用。Claude Code 从 stdout 读取 [JSON 输出字段](#json-output),无论退出码是什么(不仅仅是 0),对于使用标准决策模型的事件,通过 schema 验证的解析对象与退出码一起生效。退出 2 的阻止是 JSON 无法覆盖的唯一结果。826hook 的退出码告诉 Claude Code 是否继续执行触发该 hook 的操作,例如工具调用或提示词。运行结束时有以下三种结果之一:
825 827
826两个表负责说明每个事件的例外:[每个事件的退出码 2 行为](#exit-code-2-behavior-per-event)说明退出码对每个事件的作用,[决策控制](#decision-control)说明每个事件接受哪些决策字段。通用字段如 `systemMessage` 在大多数事件中工作,并在 [JSON 输出](#json-output)表中列出。828* **成功**:hook 以 0 退出。Claude Code 应用 hook 打印的任何 [JSON 输出](#json-output)字段,除非这些字段阻止或拒绝该操作,否则操作继续进行。
829* **阻止错误**:hook 以 2 退出。在[可以阻止的事件](#exit-code-2-behavior-per-event)上,Claude Code 停止该操作。
830* **非阻止错误**:hook 以任何其他代码退出,或以其他方式失败,例如无法启动或打印无效 JSON。操作继续进行,在 `PreToolUse` 等事件上,您会在会话记录中看到 `<hook name> hook error` 通知。如果希望失败的 hook 阻止操作,请设置 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。
831
832hook 打印到 stdout 的内容可能会改变结果。例如,如果 `PreToolUse` hook 以 1 退出但打印了通过验证的 JSON,则该运行是成功的,由 JSON 字段决定后续行为。要确定 hook 在 `PreToolUse` 等事件上的结果,请将其打印到 stdout 的内容与第一列匹配,并将其退出码与表头匹配:
833
834| Stdout | 退出 0 | 退出 2 | 任何其他退出码 |
835| :- | :- | :- | :- |
836| 通过 [schema 验证](#json-output)的 JSON 对象 | 成功。字段生效 | 阻止错误。Claude Code 仍读取字段,但它们无法覆盖阻止 | 成功。Claude Code 忽略退出码,仅由字段决定。设置 [`onFailure: "block"`](#block-the-action-when-a-hook-fails) 时,这算作失败 |
837| [无法解析](#exit-code-0)或未通过 schema 验证的 JSON | 非阻止错误。通知带有解析或验证消息 | 阻止错误。您的 stderr 作为原因 | 非阻止错误。通知带有解析或验证消息 |
838| [纯文本](#exit-code-0)或无输出 | 成功 | 阻止错误。您的 stderr 作为原因 | 非阻止错误。通知带有您的 stderr 的第一行 |
839
840某些事件有自己的规则:
841
842* **`WorktreeCreate`**:任何非零退出码都会使 worktree 创建失败,无论您的 JSON 说什么。
843* **`WorktreeRemove`**:任何非零退出码会在目录之后仍然存在时使 worktree 移除失败。
844* **`Stop`、`SubagentStop`、`TaskCompleted` 以及插件的 `UserPromptSubmit` hook**:当 hook 以 2 退出、stdout 上无内容且其 stderr 表明某个文件缺失(例如 `No such file or directory`)时,Claude Code 将该运行视为非阻止错误。
845* **`Elicitation` 和 `ElicitationResult`**:Claude Code 在 hook 以 0 退出时应用您的 `hookSpecificOutput`,在任何其他退出码上忽略它。
846* **丢弃 hook 输出的事件,如 `StopFailure`**:Claude Code 在任何退出码上都忽略您的 JSON,但 `terminalSequence` 等副作用字段除外,它们仍会触发。
847
848要查看退出码 2 对您的事件有何作用,请参阅[每个事件的退出码 2 行为](#exit-code-2-behavior-per-event)。要查看它接受哪些决策字段,请参阅[决策控制](#decision-control)。
827 849
828<h4 id="exit-code-0">850<h4 id="exit-code-0">
829 退出码 0851 退出码 0
835 857
836Claude Code 是否将您的 stdout 读取为 [JSON 输出](#json-output)或纯文本取决于它如何开始和结束,忽略周围的空白:858Claude Code 是否将您的 stdout 读取为 [JSON 输出](#json-output)或纯文本取决于它如何开始和结束,忽略周围的空白:
837 859
838* **以 `{` 开始并以 `}` 结束**:Claude Code 将其解析为 JSON。当输出是两行或更多行,每行本身都解析为 JSON,且没有行是设置字段的 [JSON 输出](#json-output)对象时,Claude Code 将整个输出视为纯文本。当其中一行确实设置了字段时,整个输出是解析失败,如下所述。860* **以 `{` 开始并以 `}` 结束**:Claude Code 将其解析为 JSON。当输出是两行或更多行,每行本身都解析为 JSON,且没有行是设置字段的 [JSON 输出](#json-output)对象时,Claude Code 将整个输出视为纯文本。当其中一行确实设置了字段时,整个输出是解析失败。
839* **以 `{` 开始但不以 `}` 结束**:Claude Code 将其视为纯文本。861* **以 `{` 开始但不以 `}` 结束**:Claude Code 将其视为纯文本。
840* **以其他任何内容开始**:Claude Code 将其视为纯文本,即使它是 JSON 数组或带引号的 JSON 字符串也是如此。862* **以其他任何内容开始**:Claude Code 将其视为纯文本,即使它是 JSON 数组或带引号的 JSON 字符串也是如此。
841 863
842对于使用标准决策模型的事件,退出 0 且解析对象未通过 schema 验证是非阻止错误:操作继续,会话记录显示 `<hook name> hook error` 通知,带有验证消息。在除 2 以外的任何退出码上都会发生相同情况,而[退出 2 仍然阻止](#exit-code-2)。864当 Claude Code 尝试将您的 stdout 解析为 JSON 但无法解析,或解析后的对象未通过 [schema 验证](#json-output)时,该运行是[非阻止错误](#exit-code-output)。`<hook name> hook error` 通知带有解析或验证消息。在添加纯文本 stdout 作为上下文的事件上,Claude Code 不会添加它未能解析的 stdout。
843
844对于使用标准决策模型的事件,当 Claude Code 尝试将您的 stdout 解析为 JSON 且无法解析时,它在除 2 外的每个退出码上报告非阻止错误。会话记录显示 `<hook name> hook error` 通知,带有解析消息。在添加纯文本 stdout 作为上下文的事件上,Claude Code 不添加文本。在 v2.1.248 之前,Claude Code 将该 stdout 视为纯文本。
845 865
846来自退出 0 的 hook 的 stderr 仅进入调试日志,从不进入会话记录,Claude 从不看到它。要自己读取它,请启用[调试日志](#debug-hooks)。要从 `PostToolUse` 或 `PostToolUseFailure` hook 向 Claude 显示警告,请改为退出 2,以便 [Claude 看到 stderr](#exit-code-2-behavior-per-event),即使工具已经运行。866Claude 从不看到以 0 退出的 hook 的 stderr。要在 `PreToolUse` 等事件上自己读取它,请启用[调试日志](#debug-hooks)。要从 `PostToolUse` 或 `PostToolUseFailure` hook 向 Claude 显示警告,请改为退出 2,以便 [Claude 看到 stderr](#exit-code-2-behavior-per-event),即使工具已经运行。
847 867
848<h4 id="exit-code-2">868<h4 id="exit-code-2">
849 退出码 2869 退出码 2
850</h4>870</h4>
851 871
852退出 2 表示阻止错误。在[可以阻止的事件](#exit-code-2-behavior-per-event)上,无论您是否打印 JSON,退出 2 都会阻止:即使 JSON `permissionDecision` 为 `"allow"` 也无法覆盖它。Claude Code 仍然读取 stdout 上的任何有效 [JSON 输出](#json-output)。在 `Elicitation` 和 `ElicitationResult` 上,退出 2 的 hook 的 `hookSpecificOutput` 被忽略。872以代码 2 退出以阻止操作。在[可以阻止的事件](#exit-code-2-behavior-per-event)上,Claude Code 会停止该操作:例如,`PreToolUse` hook 会阻止工具调用,`UserPromptSubmit` hook 会拒绝提示词。
853 873
854阻止消息是您的 JSON 阻止决策中的原因(如果它做出了阻止决策),否则是您的 stderr 文本。阻止的作用因事件而异:`PreToolUse` 阻止工具调用,`UserPromptSubmit` 拒绝提示词,等等。[每个事件的退出码 2 行为](#exit-code-2-behavior-per-event)列出每个事件的效果,每个事件的部分说明消息去向。874随阻止一起提供的消息是 hook 的 stderr。如果 hook 还打印了做出阻止决策的 JSON,Claude Code 会改用该决策的原因。
855 875
856退出 2 的 hook 同时打印未通过 [JSON 输出](#json-output) schema 验证的 JSON 时仍然阻止:Claude Code 使用 stderr 作为阻止原因,并在调试日志中记录验证失败。在 v2.1.214 之前,Claude Code 将该组合视为非阻止错误,操作继续。876即使 hook 打印了 JSON,退出 2 也会阻止:
877
878* **通过 schema 验证的 JSON**:Claude Code 仍读取 [JSON 输出](#json-output)字段,但它们无法覆盖阻止。即使 `permissionDecision` 为 `"allow"`,也不会放行操作。在 `Elicitation` 和 `ElicitationResult` 上,以 2 退出的 hook 的 `hookSpecificOutput` 被忽略。
879* **未通过 schema 验证的 JSON**:hook 仍然阻止。Claude Code 使用您的 stderr 作为阻止原因,并在调试日志中记录验证失败。
857 880
858此脚本通过退出 2 阻止 `rm` 命令,并将所有其他命令留给正常权限流程:881此脚本通过退出 2 阻止 `rm` 命令,并将所有其他命令留给正常权限流程:
859 882
871exit 0 # No decision: the normal permission flow applies894exit 0 # No decision: the normal permission flow applies
872```895```
873 896
897将此脚本注册为 `Bash` 上的 `PreToolUse` hook 后,以 `rm` 开头的命令会被阻止,Claude 会收到 hook 的 stderr 作为工具的错误,前缀为事件名称、工具名称和 hook 的命令:
898
899```text theme={null}
900PreToolUse:Bash hook error: [${CLAUDE_PROJECT_DIR}/.claude/hooks/no-rm.sh]: Blocked: rm commands are not allowed
901```
902
874<h4 id="other-exit-codes">903<h4 id="other-exit-codes">
875 其他退出码904 其他退出码
876</h4>905</h4>
877 906
878对于大多数 hook 事件,任何其他退出码本身不会阻止。发生什么取决于您的 stdout:907当 hook 以 0 或 2 以外的代码退出,并且向 stdout 打印纯文本或不打印任何内容时,该运行是[非阻止错误](#exit-code-output)。您会在会话记录中看到 `<hook name> hook error` 通知,带有 `Failed with non-blocking status code:` 和 hook stderr 的第一行。例如,当 `Bash` 上的 `PreToolUse` hook 向 stderr 打印 `something broke` 并以 1 退出时,`PreToolUse:Bash hook error` 通知带有以下行:
879 908
880* 使用通过 schema 验证的解析对象时,对于使用标准决策模型的事件,Claude Code 忽略退出码,仅由 JSON 决定结果:909```text theme={null}
881 * 事件支持的每个字段都会生效,包括 `permissionDecision`、`additionalContext`、`updatedInput` 和 `systemMessage`,hook 不被报告为错误。910Failed with non-blocking status code: something broke
882 * [决策控制](#decision-control)列出每个事件的决策字段;通用字段如 `systemMessage` 遵循 [JSON 输出](#json-output)表。911```
883* 使用未通过 schema 验证的解析对象时,对于使用标准决策模型的事件,它与[退出 0 时](#exit-code-0)相同,是非阻止错误:操作继续,`<hook name> hook error` 通知带有验证消息。
884* 使用 Claude Code [尝试解析为 JSON](#exit-code-0) 但无法解析的 stdout 时,对于使用标准决策模型的事件,Claude Code 报告与退出 0 时相同的非阻止错误。操作继续,通知带有解析消息。
885* 使用 Claude Code [视为纯文本](#exit-code-0)的 stdout,或使用空 stdout 时,对于大多数 hook 事件是非阻止错误:操作继续,会话记录显示 `<hook name> hook error` 通知,后跟 stderr 的第一行,前缀为 `Failed with non-blocking status code:`。要捕获完整 stderr,请启用[调试日志](#debug-hooks)。
886 912
887标准决策模型之外的事件在[每个事件表](#exit-code-2-behavior-per-event)中保留自己的行:`WorktreeCreate` 在任何非零退出时都会使创建失败,无论您的 JSON 说什么;完全丢弃 hook 输出的事件(如 `StopFailure`)在每个退出码上都忽略您的 JSON,但 `terminalSequence` 等副作用字段除外,它们仍会触发。913要捕获完整的 stderr 而不仅是第一行,请启用[调试日志](#debug-hooks)。
888 914
889无法启动的 hook 也归入相同的非阻止类别。当脚本路径不存在或不可执行时,shell 以某个代码(如 127)退出,您会看到相同的通知,带有解释器的消息,例如 `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`。对于大多数 hook 事件,操作继续。当您设置策略 hook 时,请在其第一次运行时留意此通知:`settings.json` 中拼写错误的路径会使该关卡被悄无声息地禁用。915无法启动的 hook 也是非阻止错误。在 shell 形式下,当脚本路径不存在或不可执行时,shell 以某个代码(如 127)退出,通知带有解释器的消息,例如 `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`。当您设置策略 hook 时,请在其第一次运行时留意此通知,因为 `settings.json` 中拼写错误的路径意味着该 hook 从不运行。要改为阻止操作,请设置 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。
890 916
891<Warning>917<Warning>
892 对于大多数 hook 事件,退出码 2 是唯一仅凭退出码即可阻止的退出码。如果 stdout 上没有有效 JSON,Claude Code 将退出码 1 视为非阻止错误并继续操作,即使 1 是传统的 Unix 失败代码。如果您的 hook 旨在强制执行策略,请使用 `exit 2`。worktree 事件不同:来自 `WorktreeCreate` 的任何非零退出码都会中止 worktree 创建,来自 `WorktreeRemove` 的任何非零退出码会在目录之后仍然存在时使 worktree 移除失败。918 如果 stdout 上没有有效 JSON,Claude Code 将退出码 1 视为非阻止错误,即使 1 是传统的 Unix 失败代码。如果您的 hook 旨在强制执行策略,请使用 `exit 2`。
893</Warning>919</Warning>
894 920
895<h4 id="timeouts">921<h4 id="timeouts">
900 926
901在 [`PreModelSwitch`](#premodelswitch) 上,因超时被取消的 hook 会阻止模型切换。在 `PreToolUse` 上,两类 hook 的行为不同:927在 [`PreModelSwitch`](#premodelswitch) 上,因超时被取消的 hook 会阻止模型切换。在 `PreToolUse` 上,两类 hook 的行为不同:
902 928
903* 超时的 `command`、`http` 或 `mcp_tool` hook 不阻止工具调用。调用通过正常[权限流程](/docs/zh-CN/permissions)继续,因此不要指望停滞的 hook 充当关卡。929* 超时的 `command`、`http` 或 `mcp_tool` hook 不阻止工具调用。调用通过正常[权限流程](/docs/zh-CN/permissions)继续,因此不要指望停滞的 hook 充当关卡。要在 `command` 或 `http` hook 超时时阻止调用,请设置 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。
904* 超过其超时时间的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) 会[阻止工具调用](#pretooluse)。930* 超过其超时时间的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) 会[阻止工具调用](#pretooluse)。
905 931
932<h4 id="block-the-action-when-a-hook-fails">
933 hook 失败时阻止操作
934</h4>
935
936在大多数事件上,当 hook 失败或超时时,Claude Code 仍会执行该操作,因此路径错误或脚本崩溃的策略 hook 会放行一切。要改为阻止操作,请在 `command` 或 `http` hook 上设置 `"onFailure": "block"`。默认值为 `"continue"`。需要 Claude Code v2.1.295 或更高版本。
937
938`.claude/settings.json` 中的这个 `PreToolUse` hook 会在每个 Bash 命令之前运行一个项目脚本,如果脚本失败则阻止该命令:
939
940```json theme={null}
941{
942 "hooks": {
943 "PreToolUse": [
944 {
945 "matcher": "Bash",
946 "hooks": [
947 {
948 "type": "command",
949 "command": "node",
950 "args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js"],
951 "onFailure": "block"
952 }
953 ]
954 }
955 ]
956 }
957}
958```
959
960要测试它,请让 `check-command.js` 保持缺失状态,并让 Claude 运行一个 Bash 命令,例如 `ls`。Claude Code 会阻止该调用,错误中包含 `failed; blocking because onFailure is "block"`,后跟 node 自身的错误输出(此处截取为一行):
961
962```text theme={null}
963PreToolUse:Bash hook error: [node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js]: failed; blocking because onFailure is "block"
964Error: Cannot find module '/path/to/project/.claude/hooks/check-command.js'
965```
966
967超时后,消息显示 `timed out` 而不是 `failed`。如果未设置 `onFailure`,同样缺失的脚本是非阻止错误,`ls` 会运行。
968
969以下每种情况都算作失败:
970
971* **无法启动**:命令 hook 无法启动,例如因为脚本或可执行文件不存在
972* **0 或 2 以外的退出码**:对于命令 hook,即使它打印了允许操作的 JSON(如 `permissionDecision: "allow"`),也算作失败。要返回 JSON 决策,请以 0 退出
973* **HTTP 错误**:HTTP hook 的连接失败,或响应状态不是 2xx
974* **超时**:hook 达到其 [`timeout`](#common-fields)
975* **无效输出**:JSON 输出[无法解析](#exit-code-0)或未通过 [schema 验证](#json-output)。对于 HTTP hook,既不为空也不是 JSON 对象的 2xx 响应体也算。命令 hook 的纯文本 stdout 不算失败
976
977设置 `"block"` 后,失败的效果与[该事件上退出码 2 的效果](#exit-code-2-behavior-per-event)相同,但 `PermissionRequest` 除外,在该事件上它会拒绝请求。例如,`PreToolUse` 失败会阻止工具调用,`UserPromptSubmit` 失败会阻止提示词。
978
979该字段对以下 hook 无效:
980
981* **`Stop`、`SubagentStop`、`TaskCompleted` 和 `TeammateIdle` hook**:这些事件上的退出码 2 会让 Claude 回去继续工作,而 Claude 无法修复无法运行的 hook
982* **后台命令 hook**:设置了 [`async` 或 `asyncRewake`](#run-hooks-in-the-background) 的命令 hook
983
906<h4 id="exit-code-2-behavior-per-event">984<h4 id="exit-code-2-behavior-per-event">
907 每个事件的退出码 2 行为985 每个事件的退出码 2 行为
908</h4>986</h4>
960* **连接失败**:非阻止错误,执行继续1038* **连接失败**:非阻止错误,执行继续
961* **超时**:hook 被取消,如[超时](#timeouts)下所述1039* **超时**:hook 被取消,如[超时](#timeouts)下所述
962 1040
963与命令 hook 不同,HTTP hook 无法仅通过状态码发出阻止错误信号。要阻止工具调用或拒绝权限,请返回 2xx 响应,其 JSON 响应体包含相应的决策字段。1041HTTP hook 无法仅通过状态码发出阻止错误信号:非 2xx 状态或连接失败是[非阻止错误](#exit-code-output)。要阻止工具调用或拒绝权限,请返回 2xx 响应,其 JSON 响应体包含相应的决策字段。要在请求失败或返回非 2xx 状态时阻止操作,请设置 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。
964 1042
965<h3 id="json-output">1043<h3 id="json-output">
966 JSON 输出1044 JSON 输出
1237 SessionStart 决策控制1315 SessionStart 决策控制
1238</h4>1316</h4>
1239 1317
1240Claude Code 会将其[视为纯文本](#exit-code-0)的 stdout 添加到 Claude 的上下文中。除所有 hook 都可用的 [JSON 输出字段](#json-output)外,您还可以返回以下事件专属字段:1318SessionStart hook 可以为 Claude 添加上下文、提供第一条用户消息、设置会话标题、监视文件以及重新加载 skill。除所有 hook 都可用的 [JSON 输出字段](#json-output)外,为每项功能返回相应字段:
1241 1319
1242| 字段 | 描述 |1320| 字段 | 描述 |
1243| :- | :- |1321| :- | :- |
1244| `additionalContext` | 在对话开始时、第一个提示词之前添加到 Claude 上下文中的字符串。关于文本的传递方式以及应放入的内容,请参阅[为 Claude 添加上下文](#add-context-for-claude) |1322| `additionalContext` | 在对话开始时、第一个提示词之前添加到 Claude 上下文中的字符串。关于文本的传递方式以及应放入的内容,请参阅[为 Claude 添加上下文](#add-context-for-claude) |
1245| `initialUserMessage` | 用作会话第一条用户消息的字符串。适用于使用 `-p` 标志的[非交互模式](/docs/zh-CN/headless),此时即使未提供提示词,它也会成为第一个轮次。如果提供了提示词,该提示词将作为下一个轮次跟随其后。与附加到现有轮次的 `additionalContext` 不同,此字段会创建轮次 |1323| `initialUserMessage` | 在使用 `-p` 标志的[非交互模式](/docs/zh-CN/headless)下,用作会话第一条用户消息的字符串。即使您未传入提示词,它也会成为第一轮。您传入的提示词会作为下一轮紧随其后 |
1246| `sessionTitle` | 设置会话标题,效果与 `/rename` 相同。可用于根据启动文件夹、git 分支或 worktree 名称自动命名会话。当 `source` 为 `"startup"`、`"resume"` 或 `"fork"` 时生效;在 `"clear"` 和 `"compact"` 时被忽略 |1324| `sessionTitle` | 设置会话标题,效果与 `/rename` 相同。在 `source` 为 `"startup"`、`"resume"` 或 `"fork"` 时生效 |
1247| `watchPaths` | 在此会话期间监视 [FileChanged](#filechanged) 事件的绝对路径数组 |1325| `watchPaths` | 在此会话期间监视 [FileChanged](#filechanged) 事件的绝对路径数组 |
1248| `reloadSkills` | 布尔值。为 `true` 时,Claude Code 会在 SessionStart hook 完成后重新扫描 [skill](/docs/zh-CN/skills) 和命令目录,使 hook 安装的 skill 在同一会话中(从第一个提示词开始)即可使用 |1326| `reloadSkills` | 布尔值。为 `true` 时,Claude Code 会在 SessionStart hook 完成后重新扫描 [skill](/docs/zh-CN/skills) 和命令目录。请参阅[重新加载 hook 安装的 skill](#reload-skills-that-a-hook-installs) |
1327
1328以下输出添加上下文并为会话命名:
1249 1329
1250```json theme={null}1330```json theme={null}
1251{1331{
1257}1337}
1258```1338```
1259 1339
1260由于对于此事件,纯 stdout 已经会传达给 Claude,因此仅加载上下文的 hook 可以直接打印到 stdout,而无需构建 JSON。当您需要将上下文与 `sessionTitle` 等其他字段结合使用时,请使用 JSON 形式。1340仅添加上下文的 hook 可以直接打印内容而无需构建 JSON,因为 Claude Code 会将 SessionStart hook 的[纯文本 stdout](#exit-code-0) 添加到 Claude 的上下文中。
1341
1342如果您的插件的 SessionStart hook 提供 `initialUserMessage` 或 `sessionTitle`,请在会话开始前安装该插件。对于在 SessionStart hook 运行之后才完成安装的插件,Claude Code 会忽略这两个字段。
1343
1344<h4 id="reload-skills-that-a-hook-installs">
1345 重新加载 hook 安装的 skill
1346</h4>
1347
1348要使 SessionStart hook 安装的 skill 在同一会话中可用,请返回 `reloadSkills`。skill 发现通常在 SessionStart hook 完成之前运行,因此如果不这样做,hook 写入 `~/.claude/skills/` 或 `.claude/skills/` 的文件在第一个提示词运行时可能缺失。
1261 1349
1262当 SessionStart hook 安装或更新 skill 时,请使用 `reloadSkills`。skill 发现通常在 SessionStart hook 完成之前运行,因此 hook 写入 `~/.claude/skills/` 或 `.claude/skills/` 的文件否则只会在下一个会话中出现。此示例同步一个共享的 skill 仓库并请求重新扫描:1350此示例同步共享的 skill 仓库并请求重新扫描:
1263 1351
1264```bash theme={null}1352```bash theme={null}
1265#!/bin/bash1353#!/bin/bash
1270echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1358echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
1271```1359```
1272 1360
1273仓库 URL 只是一个占位符;请将其替换为您自己的 skill 仓库。使用占位符时,clone 会失败并向 stderr 打印一条 `fatal:` 消息。以 0 退出的 SessionStart hook 的 stderr 仅供参考,因此 `reloadSkills` 请求仍然有效。1361仓库 URL 是占位符。请将其替换为您自己的 skill 仓库。
1274 1362
1275<h4 id="persist-environment-variables">1363<h4 id="persist-environment-variables">
1276 持久化环境变量1364 持久化环境变量
1419 1507
1420对于 `command`、`http` 和 `mcp_tool` 类型,`UserPromptSubmit` hook 的默认超时时间为 30 秒,短于这些类型在大多数其他事件上 600 秒的默认值。由于此 hook 在每个提示词之前运行,并且在完成前会阻塞模型处理,卡住的 hook 会使会话停滞。如果您的 hook 需要更多时间,请在 hook 条目中设置 `timeout` 字段。1508对于 `command`、`http` 和 `mcp_tool` 类型,`UserPromptSubmit` hook 的默认超时时间为 30 秒,短于这些类型在大多数其他事件上 600 秒的默认值。由于此 hook 在每个提示词之前运行,并且在完成前会阻塞模型处理,卡住的 hook 会使会话停滞。如果您的 hook 需要更多时间,请在 hook 条目中设置 `timeout` 字段。
1421 1509
1422除了使用 [`async: true`](#run-hooks-in-the-background) 运行的 command hook 外,达到超时的 `UserPromptSubmit` command、HTTP 或 MCP 工具 hook 会被取消,其输出(包括任何 `additionalContext`)会被丢弃。提示词仍会传达给 Claude,只是不带该上下文。会话记录中会显示一条通知,指明该 hook、触发的超时时间,以及输出已被丢弃。1510除了使用 [`async: true`](#run-hooks-in-the-background) 运行的 command hook 之外,达到超时的 `UserPromptSubmit` command、HTTP 或 MCP 工具 hook 都会被取消,其输出(包括任何 `additionalContext`)会被丢弃。提示词仍会在没有该上下文的情况下传达给 Claude。若要改为阻止该提示词,请在 command 或 HTTP hook 上设置 [`onFailure: "block"`](#block-the-action-when-a-hook-fails)。会话记录中会显示一条通知,指明该 hook、触发的超时以及输出已被丢弃。
1423 1511
1424`UserPromptSubmit` 上的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) 达到超时时,会阻止该提示词,并显示一条指明该 hook 和超时时间的消息,因为此处的回调可能充当不能失败放行的策略关卡。会话会继续。在 v2.1.208 之前,该事件上的回调超时会以执行错误结束该轮次。1512`UserPromptSubmit` 上的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) 达到超时时,会阻止该提示词,并显示一条指明该 hook 和超时时间的消息,因为此处的回调可能充当不能失败放行的策略关卡。会话会继续。在 v2.1.208 之前,该事件上的回调超时会以执行错误结束该轮次。
1425 1513
1860| :- | :- | :- | :- |1948| :- | :- | :- | :- |
1861| `url` | string | `"https://example.com/api"` | 要获取内容的 URL |1949| `url` | string | `"https://example.com/api"` | 要获取内容的 URL |
1862| `prompt` | string | `"Extract the API endpoints"` | 对获取到的内容运行的提示词 |1950| `prompt` | string | `"Extract the API endpoints"` | 对获取到的内容运行的提示词 |
1951| `offset` | number | `100000` | 可选,从页面开头跳过的字符数。Claude 会设置它以继续读取较长的页面。需要 Claude Code v2.1.290 或更高版本 |
1863 1952
1864<h5 id="websearch">1953<h5 id="websearch">
1865 WebSearch1954 WebSearch
2112| `message` | 仅用于 `"deny"`:告诉 Claude 权限被拒绝的原因 |2201| `message` | 仅用于 `"deny"`:告诉 Claude 权限被拒绝的原因 |
2113| `interrupt` | 仅用于 `"deny"`:如果为 `true`,则停止 Claude |2202| `interrupt` | 仅用于 `"deny"`:如果为 `true`,则停止 Claude |
2114 2203
2115以 2 退出但不带 `decision` 对象的 hook 不会改变权限流程,其 stderr 会被丢弃。只有 `decision` 对象才能授予或拒绝请求。2204以退出码 2 退出但未提供 `decision` 对象的 hook 不会改变权限流程,其 stderr 会被丢弃。要授予或拒绝请求,请返回 `decision` 对象。
2116 2205
2117```json theme={null}2206```json theme={null}
2118{2207{
2678 TaskCreated 决策控制2767 TaskCreated 决策控制
2679</h4>2768</h4>
2680 2769
2681TaskCreated hook 可以通过两种方式阻止创建。无论哪种方式,Claude Code 都会删除该任务,并将您的消息作为工具错误返回给 Claude。Claude Code 会忽略此事件中的 `continue: false`,Claude 会继续工作。2770TaskCreated hook 可以通过退出码 2 或 JSON 决策来阻止创建。无论哪种方式,Claude Code 都会删除该任务,并将您的消息作为工具的错误返回给 Claude。Claude Code 会忽略来自此事件的 `continue: false`,Claude 会继续工作。
2682 2771
2683* **退出码 2**:Claude Code 将 stderr 文本作为消息返回。2772* **退出码 2**:Claude Code 将 stderr 文本作为消息返回。
2684* **JSON `{"decision": "block", "reason": "..."}`**:Claude Code 将 `reason` 作为消息返回。2773* **JSON `{"decision": "block", "reason": "..."}`**:Claude Code 将 `reason` 作为消息返回。
3560 3649
3561无论决策如何,Claude Code 都会向用户显示您的 hook 返回的任何 `systemMessage`,因此用于报告成本的 hook 可以返回 `{"systemMessage": "..."}` 并以 0 退出。3650无论决策如何,Claude Code 都会向用户显示您的 hook 返回的任何 `systemMessage`,因此用于报告成本的 hook 可以返回 `{"systemMessage": "..."}` 并以 0 退出。
3562 3651
3563未在超时时间内响应的 PreModelSwitch hook 会阻止切换。相比之下,在 [PreToolUse](#timeouts) 上,超时的命令 hook 会让工具调用继续进行。此事件的默认超时时间为 30 秒。`PreModelSwitch` 仅运行 `command`、`http` 和 `mcp_tool` hook,因此 `prompt` 和 `agent` 的默认值不适用。3652在超时之前未响应的 PreModelSwitch hook 会阻止切换。关于超时对其他事件的影响,请参阅[超时](#timeouts)。此事件的默认超时时间为 30 秒。`PreModelSwitch` 仅运行 `command`、`http` 和 `mcp_tool` hook,因此 `prompt` 和 `agent` 的默认值不适用。
3564 3653
3565以 0 或 2 以外的代码退出且未打印 JSON 决策的 hook 不会阻止切换:Claude Code 会显示其 stderr 并应用切换,如[其他退出码](#other-exit-codes)中所述。3654以 0 或 2 以外的代码退出且未打印 JSON 决策的 hook 属于非阻塞错误,如[其他退出码](#other-exit-codes)中所述。
3566 3655
3567<h3 id="postmodelswitch">3656<h3 id="postmodelswitch">
3568 PostModelSwitch3657 PostModelSwitch
4278异步 hooks 与同步 hooks 相比有额外的约束:4367异步 hooks 与同步 hooks 相比有额外的约束:
4279 4368
4280* Hook 输出在下一个对话轮次传递。如果会话空闲,响应等待直到下一个用户交互。例外:退出代码为 2 的 `asyncRewake` hook 即使在会话空闲时也会立即唤醒 Claude。4369* Hook 输出在下一个对话轮次传递。如果会话空闲,响应等待直到下一个用户交互。例外:退出代码为 2 的 `asyncRewake` hook 即使在会话空闲时也会立即唤醒 Claude。
4281* 每次执行创建一个单独的后台进程。同一异步 hook 的多个触发之间没有去重。4370* 每次执行创建一个单独的后台进程。
4282 4371
4283<h2 id="security-considerations">4372<h2 id="security-considerations">
4284 安全考虑4373 安全考虑