SpyBara
Go Premium

Documentation 2026-09-18 23:58 UTC to 2026-09-19 23:57 UTC

11 files changed +1,549 −665. View all changes and history on the product overview
2026
Fri 25 23:58 Thu 24 22:57 Wed 23 23:57 Tue 22 23:59 Mon 21 22:59 Sun 20 23:59 Sat 19 23:57 Fri 18 23:58 Tue 15 23:58 Mon 14 22:58 Sun 13 21:00 Sat 12 03:02 Thu 10 23:00 Wed 9 22:58 Tue 8 20:00 Tue 1 21:02
Details

126 126 

127请参阅 [每个机制存储策略的位置](/docs/zh-CN/managed-settings#where-each-mechanism-stores-the-policy) 了解文件路径,以及 [客户端托管设置](/docs/zh-CN/claude-apps-gateway-config#client-side-managed-settings) 了解 Claude Desktop `bootstrapUrl` 等效项。127请参阅 [每个机制存储策略的位置](/docs/zh-CN/managed-settings#where-each-mechanism-stores-the-policy) 了解文件路径,以及 [客户端托管设置](/docs/zh-CN/claude-apps-gateway-config#client-side-managed-settings) 了解 Claude Desktop `bootstrapUrl` 等效项。

128 128 

129<h3 id="large-rollouts">

130 大规模推出

131</h3>

132 

133登录按客户端 IP 地址进行速率限制,默认值适合小团队。每个地址每 10 分钟获得 30 次登录开始和 10 次代码提交。向数千名开发者的推出可能在第一个早上达到这些限制,原因有两个:

134 

135* **网关看不到您的负载均衡器后面。** 没有 [`listen.trusted_proxies`](/docs/zh-CN/claude-apps-gateway-config#listen),每个开发者似乎都来自负载均衡器的地址并共享一个限制。首先设置它。网关在第一次忽略 `X-Forwarded-For` 标头时会记录警告。

136* **许多开发者共享几个 NAT 或 VPN 出口地址。** 即使 `trusted_proxies` 正确,他们也共享这些地址的限制。提高 [`rate_limits`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 以适应。

137 

138要调整 `max`,将开发者数除以他们共享的出口地址数。估计在一个 `window_seconds` 周期内有多少人登录,默认为 10 分钟。然后将其加倍以覆盖重试和同时登录 Claude Code 和 Claude Desktop 的开发者。

139 

140例如,10,000 名开发者在 4 个出口地址后面在一小时内均匀登录。这是每个地址 2,500 名开发者,每 10 分钟约 420 名,您将其加倍并四舍五入到 1,000。下面的示例将两个限制都设置为 1,000:

141 

142```yaml theme={null}

143rate_limits:

144 device_authorization: { max: 1000, window_seconds: 600 }

145 device_verify: { max: 1000, window_seconds: 600 }

146```

147 

148`device_verify` 是阻止某人猜测另一个开发者登录代码的原因,因此仅在您的估计需要的范围内提高它。即使在这些限制下,代码也是来自 20 字符字母表的 8 个字符,并在 10 分钟后过期,因此猜测仍然不切实际;请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。

149 

150当您的 IdP 发出刷新令牌时,Claude Code 会无声地续订会话,因此您可以在推出后将限制放回。没有刷新令牌,开发者每 [`session.ttl_hours`](/docs/zh-CN/claude-apps-gateway-config#session) 再次登录。为该稳定速率调整两个限制的大小,并保持它们提高。

151 

152当达到限制时,Claude Code v2.1.274 或更高版本显示 `The gateway is limiting sign-in attempts right now`。v2.1.274 或更高版本的网关在验证页面上显示 `Too many attempts came from your network address`,并提供要检查的设置。它还写入一条 `sign-in refused` 日志行,命名要更改的设置。

153 

129<h2 id="operations">154<h2 id="operations">

130 运维155 运维

131</h2>156</h2>


160 185 

161`/.well-known/oauth-authorization-server` 处的 OAuth 发现文档也仅在配置加载、OIDC 发现、上游客户端构造和 Postgres 迁移全部成功后才返回 `200`,因此它也充当端到端启动检查。186`/.well-known/oauth-authorization-server` 处的 OAuth 发现文档也仅在配置加载、OIDC 发现、上游客户端构造和 Postgres 迁移全部成功后才返回 `200`,因此它也充当端到端启动检查。

162 187 

188<h3 id="concurrent-upstream-requests">

189 并发上游请求

190</h3>

191 

192默认情况下,每个网关副本最多同时向上游发送 256 个请求。流式响应在流结束前计入限制。

193 

194当副本达到限制时到达的请求在网关内等待一个空闲槽位。开发者看到一个响应缓慢启动或似乎挂起。在 `provider: anthropic` 上游上,等待时间超过 [`timeouts.upstream_ttfb_ms`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 的请求放弃该上游,当没有后续上游提供它时以 502 失败。

195 

196包含 `upstream requests:` 的启动日志行显示生效的限制。当副本的打开请求数超过限制时,它也最多每分钟记录一次包含 `client requests are open` 的警告。

197 

198要同时提供更多请求,您有两个选项:

199 

200* 添加副本。

201* 提高每个副本上的限制。在网关容器上设置 `BUN_CONFIG_MAX_HTTP_REQUESTS` 环境变量为 1 到 65535 之间的整数,然后重启容器。

202 

203副本以约限制除以请求保持打开的平均秒数的请求速率填充其限制。例如,如果请求平均保持打开 10 秒,默认限制为 256 的副本以约每秒 26 个请求的速率填充它。

204 

205如果您在 CPU 上自动扩展,限制处的副本排队请求而不触发扩展,因此将目标设置在副本在记录 `client requests are open` 警告时显示的 CPU 级别以下。

206 

207<Warning>

208 每个打开的请求在网关进程中持有内存,同时它流式传输,同时它等待一个槽位。如果您将限制保持在 256,过载副本上的内存仍然增长,因为等待请求保持其请求体。根据峰值时打开的请求数调整容器的内存,当您更改限制时观察内存。耗尽内存的副本被杀死并丢弃它持有的每个流。

209</Warning>

210 

163<h3 id="outage-behavior">211<h3 id="outage-behavior">

164 中断行为212 中断行为

165</h3>213</h3>


207 升级255 升级

208</h3>256</h3>

209 257 

210副本是无状态的,因此滚动重启在任何时间都是安全的。网关在启动时运行架构迁移,这意味着部署新二进制文件会自动迁移数据库。并发副本在 Postgres 咨询锁上序列化,因此只有一个应用每个迁移。258副本是无状态的,因此滚动重启不会丢失任何网关状态。网关在启动时运行架构迁移,这意味着部署新二进制文件会自动迁移数据库。并发副本在 Postgres 咨询锁上序列化,因此只有一个应用每个迁移。

259 

260当您的编排器使用 `SIGTERM` 停止副本时,如在滚动重启或缩减中,网关停止接受新连接,让已在途中的请求和流完成后再退出。它最多等待 25 秒,称为排空窗口,然后关闭仍然打开的任何东西。`SIGINT`(如终端中的 Ctrl+C)启动相同的排空,排空期间的第二个信号关闭打开的请求并立即退出。排空需要网关 v2.1.274 或更高版本。

261 

262长生成可以流式传输数分钟。在 Kubernetes 和 Amazon ECS 上,将这两个一起提高以给这些流更多时间:

263 

264* **排空窗口**:在网关容器上设置 `CLAUDE_GATEWAY_DRAIN_TIMEOUT_MS` 环境变量为正整数毫秒数,如 `120000`。网关忽略任何其他形式的值,如 `120s`,并保持 25 秒的默认值

265* **您的编排器的宽限期**:Kubernetes 上的 `terminationGracePeriodSeconds`,或 Amazon ECS 上的 `stopTimeout`

266 

267宽限期在两个平台上默认为 30 秒。将其保持至少比排空窗口长 5 秒,否则编排器在排空完成前杀死网关。在 Kubernetes 上,也添加任何 `preStop` 钩子的持续时间,因为宽限期在钩子运行之前而不是网关接收 `SIGTERM` 时开始计数。

268 

269您的平台也可能限制排空可以运行多长时间:

270 

271* **Amazon ECS on Fargate**:`stopTimeout` 最多允许 120 秒

272* **Cloud Run**:在 `SIGTERM` 后 10 秒停止实例,因此打开的流在那里最多获得 10 秒,无论排空窗口是什么

273 

274当排空窗口结束时仍有请求打开,网关记录一个包含 `drain window over after` 的警告,计数它切断的请求,并命名两个要提高的设置。

211 275 

212迁移是仅追加的,因此回滚到知道较少迁移的先前二进制文件是安全的;它忽略额外的行。回滚也重新验证 YAML 针对较旧二进制文件的架构,因此采用由较新版本引入的密钥的配置在较旧版本上启动失败。在回滚前移除新密钥。276迁移是仅追加的,因此回滚到知道较少迁移的先前二进制文件是安全的;它忽略额外的行。回滚也重新验证 YAML 针对较旧二进制文件的架构,因此采用由较新版本引入的密钥的配置在较旧版本上启动失败。在回滚前移除新密钥。

213 277 


239 303 

240* 开发者持有短期 JWT 而不是原始上游密钥。CLI 到网关的腿使用 RFC 8628 设备授权,网关与 IdP 的授权代码交换在默认配置中运行 PKCE,因此拦截的 IdP 授权代码是无用的。304* 开发者持有短期 JWT 而不是原始上游密钥。CLI 到网关的腿使用 RFC 8628 设备授权,网关与 IdP 的授权代码交换在默认配置中运行 PKCE,因此拦截的 IdP 授权代码是无用的。

241* 设备验证页面强制执行同源 POST 和每个 RFC 8628 §5.1 的每 IP 速率限制。请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。305* 设备验证页面强制执行同源 POST 和每个 RFC 8628 §5.1 的每 IP 速率限制。请参阅 [用户代码暴力破解抵抗](#user-code-brute-force-resistance)。

242* 出站请求通过服务器端请求伪造 (SSRF) 防护,解析 DNS,阻止链接本地和云元数据地址加上默认的本地环回,并将连接固定到解析的 IP,因此操作员影响的 URL(如 IdP 和 OTLP 目的地)无法重定向到云元数据端点。RFC 1918 私有范围被故意允许,因为 IdP 和 OTLP 收集器通常存在于私有 IP 上。仅当网关必须合法到达的某些内容存在于本地环回时(例如本地开发 IdP 或 `localhost` 上的 sidecar OTLP 收集器),在网关的环境中设置 `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`。该变量为每个操作员配置的 URL 放宽本地环回块,也跳过启动时警告,该警告检查 pod 是否可以到达云元数据端点,因此更倾向于为收集器提供其自己的内部地址。306* 网关对您的 IdP、您的 OTLP 收集器和 `provider: anthropic` 上游的请求通过服务器端请求伪造 (SSRF) 防护,解析 DNS,阻止链接本地和云元数据地址加上默认的本地环回,并将连接固定到解析的 IP,因此操作员影响的 URL 无法重定向到云元数据端点。RFC 1918 私有范围被故意允许,因为 IdP 和 OTLP 收集器通常存在于私有 IP 上。对于其他提供商,网关在加载配置时拒绝命名这些地址或元数据主机名之一的 `base_url`,然后提供商的 SDK 连接而不进行 DNS 检查。

307 

308 如果您打开 [仅代理出口](/docs/zh-CN/claude-apps-gateway-config#proxy-only-egress),该地址检查会移到您的转发代理:网关交付主机名,代理的允许列表必须拒绝这些目的地。

309 

310 仅当网关必须合法到达的某些内容存在于本地环回时(例如本地开发 IdP 或 `localhost` 上的 sidecar OTLP 收集器),在网关的环境中设置 `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1`。该变量为每个操作员配置的 URL 放宽本地环回块,也跳过启动时警告,该警告检查 pod 是否可以到达云元数据端点,因此更倾向于为收集器提供其自己的内部地址。

243 311 

244如果您添加自己的出口控制,网关必须在使用实例元数据凭证(如工作负载身份)时到达元数据服务器。312如果您添加自己的出口控制,网关必须在使用实例元数据凭证(如工作负载身份)时到达元数据服务器。

245 313 


254 322 

255开发者在 `/device` 验证页面中输入的 `user_code` 是从 20 字符字母表中抽取的 8 个字符,产生 20⁸ 或约 2.56×10¹⁰ 个组合,在 10 分钟后过期。323开发者在 `/device` 验证页面中输入的 `user_code` 是从 20 字符字母表中抽取的 8 个字符,产生 20⁸ 或约 2.56×10¹⁰ 个组合,在 10 分钟后过期。

256 324 

257网关在设备授权端点上应用按 IP 速率限制,可通过 [`rate_limits`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 配置。如果许多开发者从单个共享公司 NAT 地址登录,提高限制。限制仅适用于登录流,不适用于推理。325网关在设备授权端点上应用按 IP 速率限制,可通过 [`rate_limits`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) 配置。如果许多开发者从单个共享公司 NAT 地址登录,提高限制。[大规模推出](#large-rollouts) 显示如何调整它们的大小。限制仅适用于登录流,不适用于推理。

258 326 

259<h3 id="compliance-posture">327<h3 id="compliance-posture">

260 合规性态势328 合规性态势


291| 启动显示 `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | 已安装的 Claude Code 版本早于 gateway 支持 | 让开发者更新 Claude Code 到包含 Cloud gateway 支持的版本 |359| 启动显示 `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | 已安装的 Claude Code 版本早于 gateway 支持 | 让开发者更新 Claude Code 到包含 Cloud gateway 支持的版本 |

292| 启动退出,显示 `Administrator policy requires a Cloud gateway sign-in on this machine` | 开发者的环境设置了 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`,其设置配置了 [`apiKeyHelper`](/docs/zh-CN/settings-reference#apikeyhelper),或来自早期 Claude Console 登录的 API 密钥仍然保存 | 让开发者清除每个适用的项:取消设置变量、删除 `apiKeyHelper` 条目,或运行 `claude auth logout` 删除保存的密钥。然后让他们启动 `claude` 并使用 `/login` 登录。另请参阅[管理员策略需要 Cloud gateway 登录](/docs/zh-CN/errors#administrator-policy-requires-a-cloud-gateway-sign-in)。 |360| 启动退出,显示 `Administrator policy requires a Cloud gateway sign-in on this machine` | 开发者的环境设置了 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`,其设置配置了 [`apiKeyHelper`](/docs/zh-CN/settings-reference#apikeyhelper),或来自早期 Claude Console 登录的 API 密钥仍然保存 | 让开发者清除每个适用的项:取消设置变量、删除 `apiKeyHelper` 条目,或运行 `claude auth logout` 删除保存的密钥。然后让他们启动 `claude` 并使用 `/login` 登录。另请参阅[管理员策略需要 Cloud gateway 登录](/docs/zh-CN/errors#administrator-policy-requires-a-cloud-gateway-sign-in)。 |

293| 启动或 `/login` 在托管设置加载时返回 403 后报告 `Claude Code may not be enabled for your organization` | gateway 或其前面的某个组件用 403 响应了 `/managed/settings` 请求。gateway 自身的设置路由从不返回 403。状态来自 [`access_control`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) IP 检查或 gateway 前面的代理或 WAF。审计日志将 IP 检查拒绝记录为 `access.denied` 并说明原因。开发者保持登录状态。 | 检查审计日志中失败时的 `access.denied`,修复 `access_control` 列表或前端,然后让开发者再次启动 `claude` |361| 启动或 `/login` 在托管设置加载时返回 403 后报告 `Claude Code may not be enabled for your organization` | gateway 或其前面的某个组件用 403 响应了 `/managed/settings` 请求。gateway 自身的设置路由从不返回 403。状态来自 [`access_control`](/docs/zh-CN/claude-apps-gateway-config#http-tuning) IP 检查或 gateway 前面的代理或 WAF。审计日志将 IP 检查拒绝记录为 `access.denied` 并说明原因。开发者保持登录状态。 | 检查审计日志中失败时的 `access.denied`,修复 `access_control` 列表或前端,然后让开发者再次启动 `claude` |

362| CLI `/login`:`The gateway is limiting sign-in attempts right now`,或在较旧版本上 `Request failed with status code 429`。`/device` 页面可能向尚未尝试过的开发者显示 `Too many attempts` | 达到了每 IP 登录速率限制。要么 `listen.trusted_proxies` 不覆盖负载均衡器,所以每个开发者共享其地址,要么许多开发者共享一个 NAT 或 VPN 出口地址。具有 `result: rate_limited` 的审计事件显示相同的一个或几个 `client_ip` 值。 | 首先将 `listen.trusted_proxies` 设置为负载均衡器的源范围,然后如果开发者仍然共享地址,提高 `rate_limits`。请参阅[大规模推出](#large-rollouts)。 |

294| CLI `/login`:`Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | gateway 主机名解析为至少一个公网 IP 地址。Claude Code 检查每个解析的地址,要求每个都是私网。常见原因是双栈名称,其中一个族解析为公网地址,包括 AWS 内部双栈负载均衡器,它们返回公网范围的 AAAA 地址。 | 让 gateway 名称在开发者机器上仅解析为私网地址。对于双栈名称,删除公网范围的记录或提供单独的仅内部 DNS 名称。请参阅[私网先决条件](/docs/zh-CN/claude-apps-gateway#prerequisites)。如果地址是你的组织拥有并在内部使用的公网空间,请[声明该块](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)。 |363| CLI `/login`:`Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | gateway 主机名解析为至少一个公网 IP 地址。Claude Code 检查每个解析的地址,要求每个都是私网。常见原因是双栈名称,其中一个族解析为公网地址,包括 AWS 内部双栈负载均衡器,它们返回公网范围的 AAAA 地址。 | 让 gateway 名称在开发者机器上仅解析为私网地址。对于双栈名称,删除公网范围的记录或提供单独的仅内部 DNS 名称。请参阅[私网先决条件](/docs/zh-CN/claude-apps-gateway#prerequisites)。如果地址是你的组织拥有并在内部使用的公网空间,请[声明该块](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own)。 |

295| CLI `/login`:`Gateway login would go through proxy <proxy>, which is not on a private network` | `HTTPS_PROXY` 或 `HTTP_PROXY` 适用于 gateway 主机,且代理的主机名解析为公网地址。主机名仅解析为私网地址的代理是允许的,不会触发此错误 | 在开发者的机器上将 gateway 主机添加到 `NO_PROXY`,以便连接是直接的,或使用主机名解析为私网地址的代理。消息会命名要添加的确切 `NO_PROXY` 条目 |364| CLI `/login`:`Gateway login would go through proxy <proxy>, which is not on a private network` | `HTTPS_PROXY` 或 `HTTP_PROXY` 适用于 gateway 主机,且代理的主机名解析为公网地址。主机名仅解析为私网地址的代理是允许的,不会触发此错误 | 在开发者的机器上将 gateway 主机添加到 `NO_PROXY`,以便连接是直接的,或使用主机名解析为私网地址的代理。消息会命名要添加的确切 `NO_PROXY` 条目 |

296| CLI `/login`:`Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it` | gateway 在 [`gatewayInternalNetworks`](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) 中声明的块上,开发者的机器从该块外的地址到达它:VPN 地址池、容器或 WSL2 NAT 段,或不是你的网络 | 让开发者从你的网络上的主机 OS 运行 `/login`。如果显示的地址也是你的组织自己的公网空间,将 gateway 的条目替换为覆盖两者的块,最多 `/8`;第二个重叠条目会被拒绝 |365| CLI `/login`:`Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it` | gateway 在 [`gatewayInternalNetworks`](/docs/zh-CN/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) 中声明的块上,开发者的机器从该块外的地址到达它:VPN 地址池、容器或 WSL2 NAT 段,或不是你的网络 | 让开发者从你的网络上的主机 OS 运行 `/login`。如果显示的地址也是你的组织自己的公网空间,将 gateway 的条目替换为覆盖两者的块,最多 `/8`;第二个重叠条目会被拒绝 |


301| CLI `/login`:`Could not resolve gateway host <host>` | 机器无法解析 gateway 的内部 DNS 名称,通常是因为它不在公司网络上 | 让开发者连接到你的网络或 VPN,然后重试 `/login` |370| CLI `/login`:`Could not resolve gateway host <host>` | 机器无法解析 gateway 的内部 DNS 名称,通常是因为它不在公司网络上 | 让开发者连接到你的网络或 VPN,然后重试 `/login` |

302| 启动退出,显示配置验证错误,命名 `store.postgres_url` | 未配置 Postgres;gateway 需要 Postgres | 设置 `store.postgres_url`。对于本地开发,使用一次性容器:`docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`。 |371| 启动退出,显示配置验证错误,命名 `store.postgres_url` | 未配置 Postgres;gateway 需要 Postgres | 设置 `store.postgres_url`。对于本地开发,使用一次性容器:`docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`。 |

303| 启动退出:`requires the native binary` | 在 Node 下运行而不是本地二进制 | 使用[独立安装方法](/docs/zh-CN/setup)之一安装 Claude Code |372| 启动退出:`requires the native binary` | 在 Node 下运行而不是本地二进制 | 使用[独立安装方法](/docs/zh-CN/setup)之一安装 Claude Code |

304| 启动退出,在 `config.load` 后显示 OIDC 发现错误 | `oidc.issuer` 无法访问,或 TLS 链不受信任 | 检查发行者是否可从 pod 访问并提供 `/.well-known/openid-configuration`。为私有 PKI 设置 `ca_cert_pem`。如果 pod 仅通过前向代理到达 IdP,设置 [`oidc.use_proxy: true`](/docs/zh-CN/claude-apps-gateway-config#idp-requests-through-a-forward-proxy);在 v2.1.227 之前的版本上,改为给 pod 一条到 IdP 每个端点的直接路由。 |373| 启动退出,在 `config.load` 后显示 OIDC 发现错误 | `oidc.issuer` 无法访问,或 TLS 链不受信任 | 检查发行者是否可从 pod 访问并提供 `/.well-known/openid-configuration`。为私有 PKI 设置 `ca_cert_pem`。如果 pod 仅通过前向代理到达 IdP,设置 [`oidc.use_proxy: true`](/docs/zh-CN/claude-apps-gateway-config#idp-requests-through-a-forward-proxy);在 v2.1.227 之前的版本上,改为给 pod 一条到 IdP 每个端点的直接路由。如果 pod 也无法解析 IdP 的主机名,或代理拒绝 `CONNECT` 到 IP 地址,请参阅[仅代理出口](/docs/zh-CN/claude-apps-gateway-config#proxy-only-egress),这需要 v2.1.277 或更高版本。 |

305| 启动退出,显示 Postgres 权限错误 | 数据库角色在其模式上缺少 DDL 权限 | 授予角色对 gateway 模式的 `CREATE` 权限,以便它可以在启动时创建和修改其表 |374| 启动退出,显示 Postgres 权限错误 | 数据库角色在其模式上缺少 DDL 权限 | 授予角色对 gateway 模式的 `CREATE` 权限,以便它可以在启动时创建和修改其表 |

375| 日志:`could not connect to Postgres at boot, attempt 1 of 3` | 当 gateway 启动时数据库无法访问,例如在网络仍在启动的冷实例上 | 如果 gateway 随后完成启动,无需采取任何措施。当数据库无法访问时,gateway 在退出前尝试连接三次,间隔两秒。如果它以 `could not connect to Postgres` 退出,检查 `store.postgres_url` 和到数据库的网络路径。如果尝试超时而不是被拒绝,提高 [`store.connect_timeout_seconds`](/docs/zh-CN/claude-apps-gateway-config#store) 以给每个尝试更长的时间。 |

306| `/oauth/callback` 显示"Sign-in could not be completed" | 电子邮件域被拒绝、id\_token 验证失败,或 `email_verified` 显式为 `false`,gateway 总是拒绝且无覆盖 | 检查 `allowed_email_domains` 和 IdP 是否返回已验证的 `email` 声明。对于 `email_verified: false`,修复 IdP 端验证。如果你的 IdP 在不同的声明名称下发出电子邮件,设置 `oidc.email_claim`。 |376| `/oauth/callback` 显示"Sign-in could not be completed" | 电子邮件域被拒绝、id\_token 验证失败,或 `email_verified` 显式为 `false`,gateway 总是拒绝且无覆盖 | 检查 `allowed_email_domains` 和 IdP 是否返回已验证的 `email` 声明。对于 `email_verified: false`,修复 IdP 端验证。如果你的 IdP 在不同的声明名称下发出电子邮件,设置 `oidc.email_claim`。 |

307| 日志:`token exchange failed request_id=<id>: id_token missing email claim` | IdP 默认不在 id\_token 中包含 `email`。此拒绝仅在设置 `allowed_email_domains` 时触发;没有它,缺少的电子邮件会创建没有电子邮件的会话 | 配置 IdP 在 id\_token 中发出 `email`。Okta:将 `email` 添加到自定义授权服务器的 ID 令牌声明。Entra:在应用注册上添加 `email` 作为可选声明。PingFederate:启用发出 `email` 的 OpenID Connect 策略。如果 IdP 从 userinfo 端点提供 `email` 但不会在 id\_token 中包含它,例如 Okta 组织授权服务器,设置 `oidc.userinfo_fallback: true`。 |377| 日志:`token exchange failed request_id=<id>: id_token missing email claim` | IdP 默认不在 id\_token 中包含 `email`。此拒绝仅在设置 `allowed_email_domains` 时触发;没有它,缺少的电子邮件会创建没有电子邮件的会话 | 配置 IdP 在 id\_token 中发出 `email`。Okta:将 `email` 添加到自定义授权服务器的 ID 令牌声明。Entra:在应用注册上添加 `email` 作为可选声明。PingFederate:启用发出 `email` 的 OpenID Connect 策略。如果 IdP 从 userinfo 端点提供 `email` 但不会在 id\_token 中包含它,例如 Okta 组织授权服务器,设置 `oidc.userinfo_fallback: true`。 |

308| 日志:`refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …)`,开发者每 `session.ttl_hours` 看到 `Cloud gateway session expired` | IdP 接受了刷新令牌但没有随之返回 id\_token,所以 gateway 询问了 IdP 的 userinfo 端点以获取用户的声明。IdP 在那里拒绝了刷新的访问令牌。gateway 回答 `temporarily_unavailable`,所以 Claude Code 保留刷新令牌但无法续订会话。v2.1.260 之前的 gateway 版本记录相同的行但没有 `(at …)` 详情。 | 设置 [`oidc.scope_on_refresh: true`](/docs/zh-CN/claude-apps-gateway-config#oidc),在 gateway v2.1.260 或更高版本中可用,以便刷新请求再次请求 `openid`。某些 IdP(如 Okta)仅在被要求时在刷新时返回 id\_token。在 PingFederate 上,改为在 **Applications > OAuth > OpenID Connect Policy Management** 下启用 **Return ID Token On Refresh Grant**。该密钥不会改变 PingFederate 的行为。对于仍然省略它的其他 IdP,检查 userinfo 端点是否接受由刷新发出的访问令牌。作为临时措施,提高 [`session.ttl_hours`](/docs/zh-CN/claude-apps-gateway-config#session)。请参阅[身份提供者设置](#identity-provider-setup)了解取消配置权衡。 |378| 日志:`refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …)`,开发者每 `session.ttl_hours` 看到 `Cloud gateway session expired` | IdP 接受了刷新令牌但没有随之返回 id\_token,所以 gateway 询问了 IdP 的 userinfo 端点以获取用户的声明。IdP 在那里拒绝了刷新的访问令牌。gateway 回答 `temporarily_unavailable`,所以 Claude Code 保留刷新令牌但无法续订会话。v2.1.260 之前的 gateway 版本记录相同的行但没有 `(at …)` 详情。 | 设置 [`oidc.scope_on_refresh: true`](/docs/zh-CN/claude-apps-gateway-config#oidc),在 gateway v2.1.260 或更高版本中可用,以便刷新请求再次请求 `openid`。某些 IdP(如 Okta)仅在被要求时在刷新时返回 id\_token。在 PingFederate 上,改为在 **Applications > OAuth > OpenID Connect Policy Management** 下启用 **Return ID Token On Refresh Grant**。该密钥不会改变 PingFederate 的行为。对于仍然省略它的其他 IdP,检查 userinfo 端点是否接受由刷新发出的访问令牌。作为临时措施,提高 [`session.ttl_hours`](/docs/zh-CN/claude-apps-gateway-config#session)。请参阅[身份提供者设置](#identity-provider-setup)了解取消配置权衡。 |

309| 每个 Amazon Bedrock 请求都返回 502;日志显示 `Could not load credentials from any providers` | 在 EC2 上,IMDSv2 的默认跳数限制为 1,阻止了来自容器内的实例元数据请求。启动和 `/readyz` 仍然通过,因为 AWS SDK 在第一个请求时解析实例凭证,而不是在客户端构造时 | 使用 `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2` 提高跳数限制,或在启动模板中设置它。更改适用于实例上的每个容器。在可用的地方优先使用 ECS 任务角色,它们从 ECS 容器凭证端点读取凭证并完全避免更改,或在专用 gateway 实例上应用更改以限制暴露。 |379| 每个 Amazon Bedrock 请求都返回 502;日志显示 `Could not load credentials from any providers` | 在 EC2 上,IMDSv2 的默认跳数限制为 1,阻止了来自容器内的实例元数据请求。启动和 `/readyz` 仍然通过,因为 AWS SDK 在第一个请求时解析实例凭证,而不是在客户端构造时 | 使用 `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2` 提高跳数限制,或在启动模板中设置它。更改适用于实例上的每个容器。在可用的地方优先使用 ECS 任务角色,它们从 ECS 容器凭证端点读取凭证并完全避免更改,或在专用 gateway 实例上应用更改以限制暴露。 |

380| 在峰值负载下,响应开始缓慢或似乎挂起,或在上游健康时失败,显示 502 `all upstreams failed` | 副本打开的请求比它一次发送到上游的请求多,所以额外的请求在 gateway 内等待。在 `provider: anthropic` 上游上,等待时间超过 `timeouts.upstream_ttfb_ms` 的请求放弃该上游,当没有后续上游提供服务时会产生 502。日志显示包含 `client requests are open` 的警告。 | 添加副本,或提高每个副本上的限制。请参阅[并发上游请求](#concurrent-upstream-requests)。 |

310| IdP 错误:unknown or unsupported scope | IdP 拒绝它不识别的作用域 | 将 `oidc.scopes` 设置为你的 IdP 接受的确切列表;它必须包含 `openid`。默认值为 `openid profile email offline_access`。 |381| IdP 错误:unknown or unsupported scope | IdP 拒绝它不识别的作用域 | 将 `oidc.scopes` 设置为你的 IdP 接受的确切列表;它必须包含 `openid`。默认值为 `openid profile email offline_access`。 |

311| 设置 `oidc.scopes` 后会话不会静默续订 | `offline_access` 从覆盖中删除了 | 如果你的 IdP 支持,添加 `offline_access` 回来。没有刷新令牌,开发者每 `session.ttl_hours` 重新运行浏览器登录。 |382| 设置 `oidc.scopes` 后会话不会静默续订 | `offline_access` 从覆盖中删除了 | 如果你的 IdP 支持,添加 `offline_access` 回来。没有刷新令牌,开发者每 `session.ttl_hours` 重新运行浏览器登录。 |

312| 浏览器显示"This request came from another site and was blocked" | 跨站点表单 POST,作为 CSRF 保护被阻止。对于嵌入或代理的页面是预期的 | 直接打开验证链接 |383| 浏览器显示"This request came from another site and was blocked" | 跨站点表单 POST,作为 CSRF 保护被阻止。对于嵌入或代理的页面是预期的 | 直接打开验证链接 |

Details

504| Bedrock 请求返回 `403 AccessDeniedException` | 账户未提交 Anthropic 的一次性用例表单,启动自动 AWS Marketplace 订阅的账户首次调用尚未完成,或任务角色的策略缺少推理配置文件或基础模型 ARN | 从 Bedrock 控制台的模型目录提交用例表单;如果刚刚提交或这是账户的首次调用,请在几分钟后重试。在两个 ARN 系列上授予 `bedrock:InvokeModel` 和 `bedrock:InvokeModelWithResponseStream`。 |504| Bedrock 请求返回 `403 AccessDeniedException` | 账户未提交 Anthropic 的一次性用例表单,启动自动 AWS Marketplace 订阅的账户首次调用尚未完成,或任务角色的策略缺少推理配置文件或基础模型 ARN | 从 Bedrock 控制台的模型目录提交用例表单;如果刚刚提交或这是账户的首次调用,请在几分钟后重试。在两个 ARN 系列上授予 `bedrock:InvokeModel` 和 `bedrock:InvokeModelWithResponseStream`。 |

505| Bedrock 返回 `ValidationException` 说按需吞吐量不受支持 | 自定义 `models:` 条目映射到区域仅通过推理配置文件提供的裸基础模型 ID | 改为将模型映射到其跨区域推理配置文件 ID (`us.anthropic.*`);内置目录已经这样做了 |505| Bedrock 返回 `ValidationException` 说按需吞吐量不受支持 | 自定义 `models:` 条目映射到区域仅通过推理配置文件提供的裸基础模型 ID | 改为将模型映射到其跨区域推理配置文件 ID (`us.anthropic.*`);内置目录已经这样做了 |

506| ECS 任务在 gateway 记录任何内容之前以 `ResourceInitializationError` 停止 | 执行角色无法读取 Secrets Manager 机密,或私有子网没有到 Secrets Manager 或 ECR 的路径 | 在三个 `gateway-` 机密的 ARN 上向执行角色授予 `secretsmanager:GetSecretValue`,并通过 NAT 网关提供出站,或者没有一个,Secrets Manager、ECR 和 CloudWatch Logs 的接口端点,`awslogs` 驱动程序在同一阶段需要,加上 S3 网关端点 |506| ECS 任务在 gateway 记录任何内容之前以 `ResourceInitializationError` 停止 | 执行角色无法读取 Secrets Manager 机密,或私有子网没有到 Secrets Manager 或 ECR 的路径 | 在三个 `gateway-` 机密的 ARN 上向执行角色授予 `secretsmanager:GetSecretValue`,并通过 NAT 网关提供出站,或者没有一个,Secrets Manager、ECR 和 CloudWatch Logs 的接口端点,`awslogs` 驱动程序在同一阶段需要,加上 S3 网关端点 |

507| Gateway 启动退出,出现 Postgres 连接超时错误 | 数据库安全组不允许 gateway 的安全组在 5432 上,或服务在数据库的 VPC 之外运行;存储在 5 秒后停止等待 | 在数据库的安全组上允许来自 gateway 安全组的 5432,并在与 DB 子网组相同的 VPC 中运行服务 |507| Gateway 启动退出,出现 Postgres 连接超时错误 | 数据库安全组不允许 gateway 的安全组在 5432 上,或服务在数据库的 VPC 之外运行 | 在数据库的安全组上允许来自 gateway 安全组的 5432,并在与 DB 子网组相同的 VPC 中运行服务 |

508| Gateway 启动退出,出现 Postgres TLS 证书验证错误 | 连接字符串设置 `sslmode=verify-full` 但镜像不信任 RDS CA 包:包未复制到镜像中,或 `NODE_EXTRA_CA_CERTS` 不指向它 | 添加构建步骤的两个 Dockerfile 行,复制包并设置 `NODE_EXTRA_CA_CERTS`,然后重建、在新标签下推送并重新部署 |508| Gateway 启动退出,出现 Postgres TLS 证书验证错误 | 连接字符串设置 `sslmode=verify-full` 但镜像不信任 RDS CA 包:包未复制到镜像中,或 `NODE_EXTRA_CA_CERTS` 不指向它 | 添加构建步骤的两个 Dockerfile 行,复制包并设置 `NODE_EXTRA_CA_CERTS`,然后重建、在新标签下推送并重新部署 |

509| 流式响应在安静期间中途下降 | v2.1.229 之前的 gateway 在 Bedrock 或 Claude Platform on AWS 上游上在上游安静时不发送任何内容,例如在没有流式输出的扩展思考期间。ALB 在默认情况下 60 秒无数据后关闭连接,因此它在该间隙处切断流。v2.1.229 及更高版本的 gateway 在该超时内保持安静流:在这些上游上,gateway 在大约 15 秒无流数据后发出 SSE `ping` 事件,在 Anthropic API 上游上它中继 API 自己的 ping | 将 gateway 更新到 v2.1.229 或更高版本,或通过 `modify-load-balancer-attributes` 或 EKS 上的 `load-balancer-attributes` Ingress 注解将 `idle_timeout.timeout_seconds` 属性设置为 `3600` |509| 流式响应在安静期间中途下降 | v2.1.229 之前的 gateway 在 Bedrock 或 Claude Platform on AWS 上游上在上游安静时不发送任何内容,例如在没有流式输出的扩展思考期间。ALB 在默认情况下 60 秒无数据后关闭连接,因此它在该间隙处切断流。v2.1.229 及更高版本的 gateway 在该超时内保持安静流:在这些上游上,gateway 在大约 15 秒无流数据后发出 SSE `ping` 事件,在 Anthropic API 上游上它中继 API 自己的 ping | 将 gateway 更新到 v2.1.229 或更高版本,或通过 `modify-load-balancer-attributes` 或 EKS 上的 `load-balancer-attributes` Ingress 注解将 `idle_timeout.timeout_seconds` 属性设置为 `3600` |

510 510 

Details

318| Cloud Run 在到达容器前返回 `403 Forbidden` | 调用者 IAM 检查仍然启用 | 使用 `--no-invoker-iam-check` 部署,或使用 `--allow-unauthenticated` 授予 `allUsers` `run.invoker` 角色 |318| Cloud Run 在到达容器前返回 `403 Forbidden` | 调用者 IAM 检查仍然启用 | 使用 `--no-invoker-iam-check` 部署,或使用 `--allow-unauthenticated` 授予 `allUsers` `run.invoker` 角色 |

319| `--no-invoker-iam-check` 被拒绝,显示 `invoker_iam_disabled is not currently available` | 被 `constraints/run.managed.requireInvokerIam` 阻止 | 使用 `--allow-unauthenticated`。如果通过 `constraints/iam.allowedPolicyMemberDomains` 的域受限共享也阻止了它,请使用 GKE 路径,它在网络层公开网关,无需 `allUsers` 绑定。 |319| `--no-invoker-iam-check` 被拒绝,显示 `invoker_iam_disabled is not currently available` | 被 `constraints/run.managed.requireInvokerIam` 阻止 | 使用 `--allow-unauthenticated`。如果通过 `constraints/iam.allowedPolicyMemberDomains` 的域受限共享也阻止了它,请使用 GKE 路径,它在网络层公开网关,无需 `allUsers` 绑定。 |

320| 部署时 `Container manifest type … must support amd64/linux` | 镜像在非 amd64 主机上构建,或 buildx 发出了 OCI 镜像索引 | 使用 `--platform=linux/amd64 --provenance=false` 构建 |320| 部署时 `Container manifest type … must support amd64/linux` | 镜像在非 amd64 主机上构建,或 buildx 发出了 OCI 镜像索引 | 使用 `--platform=linux/amd64 --provenance=false` 构建 |

321| 网关启动在 Cloud Run 上以 Postgres 连接超时错误退出 | 服务未附加到 VPC,或 Cloud SQL 在该 VPC 上没有私有 IP;存储在 5 秒后停止等待 | 使用 `--network` 和 `--subnet` 部署以进行直接 VPC 出口,并使用 `--no-assign-ip` 和 `--network` 指向同一 VPC 创建 Cloud SQL 实例 |321| 网关启动在 Cloud Run 上以 Postgres 连接超时错误退出 | 服务未附加到 VPC,或 Cloud SQL 在该 VPC 上没有私有 IP | 使用 `--network` 和 `--subnet` 部署以进行直接 VPC 出口,并使用 `--no-assign-ip` 和 `--network` 指向同一 VPC 创建 Cloud SQL 实例 |

322| Google Cloud 的 Agent Platform 请求返回 `403 PERMISSION_DENIED` | 运行时未使用 `claude-gateway` 服务账户,或模型未在 Model Garden 中为项目启用 | 在 Cloud Run 上设置 `--service-account` 或在 GKE 上绑定 Workload Identity,并在 Model Garden 中为目标区域启用每个 Claude 模型 |322| Google Cloud 的 Agent Platform 请求返回 `403 PERMISSION_DENIED` | 运行时未使用 `claude-gateway` 服务账户,或模型未在 Model Garden 中为项目启用 | 在 Cloud Run 上设置 `--service-account` 或在 GKE 上绑定 Workload Identity,并在 Model Garden 中为目标区域启用每个 Claude 模型 |

323| 流式响应在固定持续时间后切断 | 前端请求超时:GKE Ingress 后面的负载均衡器后端服务默认为 30 秒,Cloud Run 默认为 300 秒 | 在 GKE 上附加具有提高的 `timeoutSec` 的 BackendConfig,或在 Cloud Run 上使用 `--timeout=3600` 部署 |323| 流式响应在固定持续时间后切断 | 前端请求超时:GKE Ingress 后面的负载均衡器后端服务默认为 30 秒,Cloud Run 默认为 300 秒 | 在 GKE 上附加具有提高的 `timeoutSec` 的 BackendConfig,或在 Cloud Run 上使用 `--timeout=3600` 部署 |

324 324 

Details

164 归档环境164 归档环境

165</h3>165</h3>

166 166 

167要归档环境,请打开它进行编辑并选择**Archive**。你不能删除环境,只能归档它。167要归档你自己的环境之一,请打开它进行编辑并选择**Archive**。所有者从管理设置中的**Cloud environments**页面归档[共享环境](#organization-shared-environments)。你不能删除环境,只能归档它。

168 168 

169归档影响新会话,不影响运行中的会话:169归档影响新会话,不影响运行中的会话:

170 170 


177 组织共享环境177 组织共享环境

178</h3>178</h3>

179 179 

180在Team和Enterprise计划上,所有者可以创建与组织的每个成员共享的云环境。同一角色管理**Cloud environments**管理页面上的其他所有内容,包括[自托管环境](/docs/zh-CN/self-hosted-environments);管理员角色无法打开该页面。可以打开它的完整角色列表是[管理服务器管理的设置](/docs/zh-CN/server-managed-settings#access-control)的角色列表。共享环境出现在每个成员的环境选择器中,与他们的个人环境并排,所以团队可以标准化一个配置,而不是每个成员重新创建它。180在Team和Enterprise计划上,所有者可以创建与组织的每个成员共享的云环境。同一角色管理**Cloud environments**管理页面上的其他所有内容,包括[自托管环境](/docs/zh-CN/self-hosted-environments);管理员角色无法打开该页面。可以打开它的完整角色列表是[管理服务器管理的设置](/docs/zh-CN/server-managed-settings#access-control)的角色列表。

181 181 

182从[admin settings](https://claude.ai/admin-settings)中的**Cloud environments**页面创建、编辑和归档共享环境。共享环境也可以从[claude.ai/code](https://claude.ai/code)的[环境选择器](#configure-your-environment)打开:所有者可以在那里编辑它。其他成员以只读方式看到它。每个共享环境都有一个名称、一个[网络访问级别](#access-levels)、`.env`格式的[环境变量](#set-environment-variables)和一个[setup script](#setup-scripts)。所有者在[claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code)单独选择组织的[默认环境](#the-default-environment)。182共享环境出现在每个成员的[环境选择器](#configure-your-environment)中,在**Organization**标题下,位于成员自己的环境之后(在**Personal**下),所以团队可以标准化一个配置,而不是每个成员重新创建它。在那里选择共享环境的设置图标会为每个成员(包括所有者)打开其配置的只读摘要。

183 

184所有者通过以下两种方式之一使环境对组织可用:

185 

186* **创建共享环境**:使用[admin settings](https://claude.ai/admin-settings)中的**Cloud environments**页面,这也是所有者编辑和归档共享环境的地方。每个都有一个名称、一个[网络访问级别](#access-levels)、`.env`格式的[环境变量](#set-environment-variables)和一个[setup script](#setup-scripts)。

187* **共享个人环境**:在环境选择器中打开你自己的环境之一进行编辑,然后从**Who can use it**行共享它。环境保持其ID,所以已经使用它的会话和routine不受影响,每个成员都可以看到它并在其中启动会话。

188 

189所有者在[claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code)单独选择组织的[默认环境](#the-default-environment)。

183 190 

184每个成员在共享环境中的会话都读取其变量,所以不要在其中包含秘密。[API凭证](#add-api-credentials)给予会话一个它们无法读取的密钥,在Team或Enterprise计划上还不可用。191每个成员在共享环境中的会话都读取其变量,所以不要在其中包含秘密。[API凭证](#add-api-credentials)给予会话一个它们无法读取的密钥,在Team或Enterprise计划上还不可用。

185 192 


198 205 

199每个环境都设置一个网络访问级别,控制其会话可以进行的出站连接。默认级别 **Trusted** 允许包注册表和其他[允许列表中的域](#default-allowed-domains);**Custom** 采用您自己的域列表。206每个环境都设置一个网络访问级别,控制其会话可以进行的出站连接。默认级别 **Trusted** 允许包注册表和其他[允许列表中的域](#default-allowed-domains);**Custom** 采用您自己的域列表。

200 207 

201要更改环境的网络访问,[打开它进行编辑](#configure-your-environment)并在对话框中使用 **Network access** 选择器。打开选择器的云图标出现在[Default 环境](#the-default-environment)下列出的应用界面上,以及[例程编辑器](/docs/zh-CN/routines#environments-and-network-access)中;个人环境在您的 claude.ai 账户设置中没有单独的页面。208要更改环境的网络访问,[打开它进行编辑](#configure-your-environment)并在对话框中使用 **Network access** 选择器。[共享环境](#organization-shared-environments)在那里以只读方式打开,因此 Owner 改为从[管理设置](https://claude.ai/admin-settings)中的 **Cloud environments** 页面更改其网络访问。打开选择器的云图标出现在[Default 环境](#the-default-environment)下列出的应用界面上,以及[例程编辑器](/docs/zh-CN/routines#environments-and-network-access)中;个人环境在您的 claude.ai 账户设置中没有单独的页面。

202 209 

203<Note>210<Note>

204 您在会话或例程上启用的 MCP 连接器无需将其主机添加到 **Allowed domains**,因为连接器流量通过 Anthropic 的服务器而不是会话的网络传输。这依赖于[安全性和隔离](/docs/zh-CN/claude-code-on-the-web#security-and-isolation)下提到的同一条通往 Anthropic 的通道。关闭任何您不需要的连接器,以限制 Claude 可以访问的工具。211 您在会话或例程上启用的 MCP 连接器无需将其主机添加到 **Allowed domains**,因为连接器流量通过 Anthropic 的服务器而不是会话的网络传输。这依赖于[安全性和隔离](/docs/zh-CN/claude-code-on-the-web#security-and-isolation)下提到的同一条通往 Anthropic 的通道。关闭任何您不需要的连接器,以限制 Claude 可以访问的工具。


208 访问级别215 访问级别

209</h3>216</h3>

210 217 

211[环境对话框](#configure-your-environment)中的 **Network access** 字段采用以下四个级别之一:218**Network access** 字段在[环境对话框](#configure-your-environment)中采用以下四个级别之一:

212 219 

213| 级别 | 出站连接 |220| 级别 | 出站连接 |

214| :---------- | :------------------------------------------------------ |221| :---------- | :------------------------------------------------------ |

hooks.md +1399 −634

Details

10 有关包含示例的快速入门指南,请参阅[使用 hooks 自动化工作流](/docs/zh-CN/hooks-guide)。10 有关包含示例的快速入门指南,请参阅[使用 hooks 自动化工作流](/docs/zh-CN/hooks-guide)。

11</Tip>11</Tip>

12 12 

13Hooks 是用户定义的 shell 命令、HTTP 端点或 LLM 提示,在 Claude Code 生命周期中的特定点自动执行。使用此参考查找事件架构、配置选项、JSON 输入/输出格式以及异步 hooks、HTTP hooks 和 MCP 工具 hooks 等高级功能。如果您是第一次设置 hooks,请改为从[指南](/docs/zh-CN/hooks-guide)开始。13Hooks 是用户定义的 shell 命令、HTTP 端点、MCP 工具调用、LLM 提示或子代理,在 Claude Code 生命周期中的特定点自动执行。Claude Code 在其运行的任何地方都会触发相同的 hook 事件:终端中的会话、IDE 扩展、[桌面应用](/docs/zh-CN/desktop-quickstart)和[云会话](/docs/zh-CN/claude-code-on-the-web)。使用此参考查找事件架构、配置选项、JSON 输入/输出格式以及异步 hooks、HTTP hooks 和 MCP 工具 hooks 等高级功能。

14 14 

15<h2 id="hook-lifecycle">15<h2 id="hook-lifecycle">

16 Hook 生命周期16 Hook 生命周期

17</h2>17</h2>

18 18 

19Hooks 在 Claude Code 会话期间的特定点触发。当事件触发且匹配器匹配时,Claude Code 会将关于该事件的 JSON 上下文传递给您的 hook 处理程序。对于命令 hooks,输入通过 stdin 到达。对于 HTTP hooks,它作为 POST 请求体到达。您的处理程序随后可以检查输入、采取行动并可选地返回决定。19Claude Code 在会话期间的特定点运行 hooks。当事件触发且匹配器匹配时,Claude Code 会将关于该事件的 JSON 上下文传递给您的 hook 处理程序。对于命令 hooks,输入通过 stdin 到达。对于 HTTP hooks,它作为 POST 请求体到达。您的处理程序随后可以检查输入、采取行动并可选地返回决定。

20 20 

21事件分为三种频率:21事件分为三种频率:

22 22 

23* 每个会话一次:`SessionStart` 和 `SessionEnd`23* 每个会话一次:`SessionStart` 和 `SessionEnd`

24* 每轮一次:`UserPromptSubmit`、`Stop` 和 `StopFailure`24* 每轮一次:`UserPromptSubmit`、`Stop` 和 `StopFailure`

25* 代理循环内的每个工具调用:`PreToolUse` 和 `PostToolUse`25* 代理循环内的每个工具调用:`PreToolUse` 和 `PostToolUse`,除了 [`EndConversation`](/docs/zh-CN/tools-reference#endconversation-tool-behavior) 调用,它们跳过两者

26 26 

27<div style={{maxWidth: "500px", margin: "0 auto"}}>27<div style={{maxWidth: "500px", margin: "0 auto"}}>

28 <Frame>28 <Frame>

29 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" alt="Hook 生命周期图,显示可选的 Setup 流入 SessionStart,然后是每轮循环,包含 UserPromptSubmit、用于 slash commands 的 UserPromptExpansion、嵌套的代理循环(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)和 Stop 或 StopFailure,然后是 TeammateIdle、PreCompact、PostCompact 和 SessionEnd,Elicitation 和 ElicitationResult 嵌套在 MCP 工具执行内,PermissionDenied 作为 PermissionRequest 的副分支用于自动模式拒绝,WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged 和 FileChanged 作为独立异步事件,MessageDisplay 作为仅显示事件,在助手消息文本流式传输时运行" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />29 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" className="dark:hidden" alt="Hook 生命周期图,显示可选的 Setup 流入 SessionStart,然后是每轮循环,包含 UserPromptSubmit、用于 slash commands 的 UserPromptExpansion、嵌套的代理循环(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)和 Stop 或 StopFailure,然后是 TeammateIdle、PreCompact、PostCompact 和 SessionEnd,Elicitation 和 ElicitationResult 嵌套在 MCP 工具执行内,PermissionDenied 作为 PermissionRequest 的副分支用于自动模式拒绝,WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged、FileChanged 和 DirectoryAdded 作为独立异步事件,PreModelSwitch 作为独立顺序事件,在请求的模型切换之前运行,PostModelSwitch 作为独立异步事件,在会话的模型更改后运行,MessageDisplay 作为仅显示事件,在助手消息文本流式传输时运行" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />

30 

31 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle-dark.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=c9b3d88487335f58cce0b52e2f9e7531" className="hidden dark:block" alt="Hook 生命周期图,显示可选的 Setup 流入 SessionStart,然后是每轮循环,包含 UserPromptSubmit、用于 slash commands 的 UserPromptExpansion、嵌套的代理循环(PreToolUse、PermissionRequest、PostToolUse、PostToolUseFailure、PostToolBatch、SubagentStart/Stop、TaskCreated、TaskCompleted)和 Stop 或 StopFailure,然后是 TeammateIdle、PreCompact、PostCompact 和 SessionEnd,Elicitation 和 ElicitationResult 嵌套在 MCP 工具执行内,PermissionDenied 作为 PermissionRequest 的副分支用于自动模式拒绝,WorktreeCreate、WorktreeRemove、Notification、ConfigChange、InstructionsLoaded、CwdChanged、FileChanged 和 DirectoryAdded 作为独立异步事件,PreModelSwitch 作为独立顺序事件,在请求的模型切换之前运行,PostModelSwitch 作为独立异步事件,在会话的模型更改后运行,MessageDisplay 作为仅显示事件,在助手消息文本流式传输时运行" width="520" height="1336" data-path="images/hooks-lifecycle-dark.svg" />

30 </Frame>32 </Frame>

31</div>33</div>

32 34 

33下表总结了每个事件何时触发。[Hook 事件](#hook-events)部分记录了每个事件的完整输入架构和决定控制选项。35下表总结了每个事件何时触发。[Hook 事件](#hook-events)部分记录了每个事件的完整输入架构和决定控制选项。

34 36 

35| Event | When it fires |37| 事件 | 触发时机 |

36| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |38| :-------------------- | :--------------------------------------------------------------------------------------------------------------------- |

37| `SessionStart` | When a session begins or resumes |39| `SessionStart` | 当会话开始或恢复时 |

38| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |40| `Setup` | 当你使用 `--init-only` 启动 Claude Code,或在 `-p` 模式下使用 `--init` 或 `--maintenance` 时。用于 CI 或脚本中的一次性准备 |

39| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |41| `UserPromptSubmit` | 当你提交提示词时,在 Claude 处理之前 |

40| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |42| `UserPromptExpansion` | 当用户输入的命令扩展为提示词时,在到达 Claude 之前。可以阻止扩展 |

41| `PreToolUse` | Before a tool call executes. Can block it |43| `PreToolUse` | 在工具调用执行之前。可以阻止它 |

42| `PermissionRequest` | When a tool call needs a permission decision |44| `PermissionRequest` | 当工具调用需要权限决策时 |

43| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |45| `PermissionDenied` | 当自动模式拒绝工具调用时,包括没有分类器判决的拒绝。使用 JSON `hookSpecificOutput.retry: true` 来告诉模型它可以重试被拒绝的工具调用。Claude Code 在分类器未产生判决时忽略 `retry` |

44| `PostToolUse` | After a tool call succeeds |46| `PostToolUse` | 在工具调用成功后 |

45| `PostToolUseFailure` | After a tool call fails |47| `PostToolUseFailure` | 在工具调用失败后 |

46| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |48| `PostToolBatch` | 在一整批并行工具调用解决后,在下一次模型调用之前 |

47| `Notification` | When Claude Code sends a notification |49| `Notification` | 当 Claude Code 发送通知时 |

48| `MessageDisplay` | While assistant message text is displayed |50| `MessageDisplay` | 当助手消息文本正在显示时 |

49| `SubagentStart` | When a subagent is spawned |51| `SubagentStart` | 当子代理被生成时 |

50| `SubagentStop` | When a subagent finishes |52| `SubagentStop` | 当子代理完成时 |

51| `TaskCreated` | When a task is being created via `TaskCreate` |53| `TaskCreated` | 当通过 `TaskCreate` 创建任务时 |

52| `TaskCompleted` | When a task is being marked as completed |54| `TaskCompleted` | 当任务被标记为已完成时 |

53| `Stop` | When Claude finishes responding |55| `Stop` | 当 Claude 完成响应时 |

54| `StopFailure` | When the turn ends due to an API error |56| `StopFailure` | 当轮次因 API 错误而结束时 |

55| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |57| `TeammateIdle` | 当[代理团队](/docs/zh-CN/agent-teams)队友即将空闲时 |

56| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |58| `InstructionsLoaded` | 当 CLAUDE.md 或 `.claude/rules/*.md` 文件被加载到上下文中时。在会话开始时和文件在会话期间被延迟加载时触发 |

57| `ConfigChange` | When a configuration file changes during a session |59| `ConfigChange` | 当配置文件在会话期间更改时 |

58| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |60| `CwdChanged` | 当工作目录更改时,例如当 Claude 执行 `cd` 命令时。对于使用 direnv 等工具的反应式环境管理很有用 |

59| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |61| `DirectoryAdded` | 当工作目录在会话中期通过 `/add-dir` 或 SDK `register_repo_root` 控制请求添加时 |

60| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |62| `FileChanged` | 当监视的文件在磁盘上更改时。`matcher` 字段指定要监视的文件名 |

61| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |63| `WorktreeCreate` | 当通过 `--worktree`、`isolation: "worktree"` 创建工作树时,或用于后台会话。替换默认的 git 行为 |

62| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |64| `WorktreeRemove` | 当在会话退出时、子代理完成时或删除后台会话时移除工作树 |

63| `PreCompact` | Before context compaction |65| `PreCompact` | 在上下文压缩之前 |

64| `PostCompact` | After context compaction completes |66| `PostCompact` | 在上下文压缩完成后 |

65| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |67| `PreModelSwitch` | 在 Claude Code 应用你或客户端请求的模型切换之前。可以阻止切换 |

66| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |68| `PostModelSwitch` | 在会话的模型更改后,包括 Claude Code 自己进行的更改,例如在你恢复会话时恢复模型 |

67| `Elicitation` | When an MCP server requests user input during a tool call |69| `Elicitation` | 当 MCP 服务器在工具调用期间请求用户输入时 |

68| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |70| `ElicitationResult` | 在用户响应 MCP 引出后,在响应发送回服务器之前 |

69| `SessionEnd` | When a session terminates |71| `SessionEnd` | 当会话终止时 |

70 72 

71<h3 id="how-a-hook-resolves">73<h3 id="how-a-hook-resolves">

72 Hook 如何解析74 Hook 如何解析

73</h3>75</h3>

74 76 

75要了解这些部分如何组合在一起,请考虑这个 `PreToolUse` hook,它阻止破坏性 shell 命令。`matcher` 缩小到 Bash 工具调用,`if` 条件进一步缩小到匹配 `rm *` 的 Bash 子命令,因此 `block-rm.sh` 仅在两个过滤器都匹配时生成:77要了解事件、匹配器和处理程序如何组合在一起,请考虑这个 `PreToolUse` hook,它阻止破坏性 shell 命令。

76 78 

77```json theme={null}79<Tabs>

78{80 <Tab title="macOS/Linux">

81 `matcher` 缩小到 Bash 工具调用,`if` 条件进一步缩小到匹配 `rm *` 的 Bash 子命令,因此 `block-rm.sh` 仅在两个过滤器都匹配时生成:

82 

83 ```json theme={null}

84 {

79 "hooks": {85 "hooks": {

80 "PreToolUse": [86 "PreToolUse": [

81 {87 {


91 }97 }

92 ]98 ]

93 }99 }

94}100 }

95```101 ```

96 102 

97该脚本从 stdin 读取 JSON 输入,提取命令,如果包含 `rm -rf`,则返回 `permissionDecision` 为 `"deny"`:103 该脚本从 stdin 读取 JSON 输入,提取命令,如果包含 `rm -rf`,则返回 `permissionDecision` 为 `"deny"`。将其保存到项目中的 `.claude/hooks/block-rm.sh`,并使用 `chmod +x .claude/hooks/block-rm.sh` 使其可执行,以便 Claude Code 可以运行它:

98 104 

99```bash theme={null}105 ```bash theme={null}

100#!/bin/bash106 #!/bin/bash

101# .claude/hooks/block-rm.sh107 # .claude/hooks/block-rm.sh

102COMMAND=$(jq -r '.tool_input.command')108 COMMAND=$(jq -r '.tool_input.command')

103 109 

104if echo "$COMMAND" | grep -q 'rm -rf'; then110 if echo "$COMMAND" | grep -q 'rm -rf'; then

105 jq -n '{111 jq -n '{

106 hookSpecificOutput: {112 hookSpecificOutput: {

107 hookEventName: "PreToolUse",113 hookEventName: "PreToolUse",


109 permissionDecisionReason: "Destructive command blocked by hook"115 permissionDecisionReason: "Destructive command blocked by hook"

110 }116 }

111 }'117 }'

112else118 else

113 exit 0 # no decision; normal permission flow applies119 exit 0 # no decision; normal permission flow applies

114fi120 fi

115```121 ```

122 

123 此脚本与本页面上解析 JSON 输入的其他 Bash 示例一样,使用 `jq`,因此在尝试它们之前,请安装 `jq` 并确保它在您的 `PATH` 上。

124 </Tab>

125 

126 <Tab title="Windows (PowerShell)">

127 匹配器 `Bash|PowerShell` 涵盖 [PowerShell 工具](#powershell)以及 Bash。单个 `if` 规则仅匹配一个工具的调用,因此每个工具都有自己的处理程序:第一个缩小到匹配 `rm *` 的 Bash 子命令,第二个缩小到匹配 `Remove-Item *` 的 PowerShell 命令。两者都通过 `powershell.exe` 运行相同的脚本:

128 

129 ```json theme={null}

130 {

131 "hooks": {

132 "PreToolUse": [

133 {

134 "matcher": "Bash|PowerShell",

135 "hooks": [

136 {

137 "type": "command",

138 "if": "Bash(rm *)",

139 "command": "powershell.exe",

140 "args": [

141 "-NoProfile",

142 "-ExecutionPolicy",

143 "Bypass",

144 "-File",

145 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"

146 ]

147 },

148 {

149 "type": "command",

150 "if": "PowerShell(Remove-Item *)",

151 "command": "powershell.exe",

152 "args": [

153 "-NoProfile",

154 "-ExecutionPolicy",

155 "Bypass",

156 "-File",

157 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"

158 ]

159 }

160 ]

161 }

162 ]

163 }

164 }

165 ```

166 

167 `-NoProfile` 标志跳过加载您的 PowerShell 配置文件,以便 hook 快速启动,`-ExecutionPolicy Bypass` 让 PowerShell 运行本地脚本文件。

116 168 

117现在假设 Claude Code 决定运行 `Bash "rm -rf /tmp/build"`。以下是发生的情况:169 该脚本从 stdin 读取 JSON 输入,提取命令,如果包含 `rm -rf` 或 `Remove-Item` 后跟 `-Recurse`,则返回 `permissionDecision` 为 `"deny"`。将其保存到项目中的 `.claude/hooks/block-rm.ps1`:

170 

171 ```powershell theme={null}

172 # .claude/hooks/block-rm.ps1

173 $callInput = [Console]::In.ReadToEnd() | ConvertFrom-Json

174 $command = $callInput.tool_input.command

175 

176 if ($command -match 'rm -rf|Remove-Item.*-Recurse') {

177 @{

178 hookSpecificOutput = @{

179 hookEventName = "PreToolUse"

180 permissionDecision = "deny"

181 permissionDecisionReason = "Destructive command blocked by hook"

182 }

183 } | ConvertTo-Json

184 } else {

185 exit 0 # no decision; normal permission flow applies

186 }

187 ```

188 </Tab>

189</Tabs>

190 

191现在假设 Claude Code 决定针对 macOS/Linux 配置运行 `Bash "rm -rf /tmp/build"`。以下是发生的情况:

118 192 

119<Frame>193<Frame>

120 <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" alt="Hook 解析流程图:PreToolUse 触发,匹配器检查 Bash 匹配,然后 if 条件检查 Bash(rm *) 匹配。如果两者都匹配,hook 命令运行并返回 permissionDecision deny,因此工具调用被阻止,Claude Code 继续。如果任一检查未能匹配,hook 被跳过,工具调用被允许继续。" width="930" height="270" data-path="images/hook-resolution.svg" />194 <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" className="dark:hidden" alt="Hook 解析流程图:PreToolUse 触发,匹配器检查 Bash 匹配,然后 if 条件检查 Bash(rm *) 匹配。如果两者都匹配,hook 命令运行并返回 permissionDecision deny,因此工具调用被阻止,Claude Code 继续。如果任一检查未能匹配,hook 被跳过,工具调用被允许继续。" width="930" height="270" data-path="images/hook-resolution.svg" />

195 

196 <img src="https://mintcdn.com/claude-code/_xqph1dUOslCOwsj/images/hook-resolution-dark.svg?fit=max&auto=format&n=_xqph1dUOslCOwsj&q=85&s=e80af91f8507cee6bd51ac3c2dd92f63" className="hidden dark:block" alt="Hook 解析流程图:PreToolUse 触发,匹配器检查 Bash 匹配,然后 if 条件检查 Bash(rm *) 匹配。如果两者都匹配,hook 命令运行并返回 permissionDecision deny,因此工具调用被阻止,Claude Code 继续。如果任一检查未能匹配,hook 被跳过,工具调用被允许继续。" width="930" height="270" data-path="images/hook-resolution-dark.svg" />

121</Frame>197</Frame>

122 198 

123<Steps>199<Steps>


183您定义 hook 的位置决定了其范围:259您定义 hook 的位置决定了其范围:

184 260 

185| 位置 | 范围 | 可共享 |261| 位置 | 范围 | 可共享 |

186| :---------------------------------------------------------- | :----- | :----------------------------- |262| :------------------------------------------ | :--------------------------------------------------------------------- | :---------------------------------- |

187| `~/.claude/settings.json` | 您的所有项目 | 否,本地于您的计算机 |263| `~/.claude/settings.json` | 您的所有项目 | 否,本地于您的计算机 |

188| `.claude/settings.json` | 单个项目 | 是,可以提交到仓库 |264| `.claude/settings.json` | 单个项目 | 是,可以提交到仓库 |

189| `.claude/settings.local.json` | 单个项目 | 否,gitignored 当 Claude Code 创建时 |265| `.claude/settings.local.json` | 单个项目 | 否,gitignored 当 Claude Code 保存设置到其中时 |

190| 托管策略设置 | 组织范围 | 是,管理员控制 |266| 托管策略设置 | 组织范围 | 是,管理员控制 |

191| [Plugin](/docs/zh-CN/plugins) `hooks/hooks.json` | 启用插件时 | 是,与插件捆绑 |267| [Plugin](/docs/zh-CN/plugins) `hooks/hooks.json` | 启用插件时 | 是,与插件捆绑 |

192| [Skill](/docs/zh-CN/skills) 或[代理](/docs/zh-CN/sub-agents) frontmatter | 组件活跃时 | 是,在组件文件中定义 |268| [Skill](/docs/zh-CN/skills) frontmatter | 调用 skill 后的会话其余部分。请参阅[Skills 和代理中的 Hooks](#hooks-in-skills-and-agents) | 是,在 skill 文件中定义 |

269| [Subagent](/docs/zh-CN/sub-agents) frontmatter | 该 subagent 运行时 | 是,在 subagent 文件中定义 |

270 

271[Cloud sessions](/docs/zh-CN/claude-code-on-the-web)不读取您的本地 `~/.claude/settings.json`;那里的 hooks 来自仓库,意味着其 `.claude/settings.json` 在具有一个仓库的会话中以及它在任何会话中声明的插件,以及来自您组织的服务器管理的设置。在[自托管环境](/docs/zh-CN/self-hosted-environments-configuration#permissions-and-tool-approval)中,Claude Code 也运行操作员从运行程序主机的 `~/.claude/` 中播种的 hooks,并且当该文件在[Claude Code 应用的托管源](/docs/zh-CN/managed-settings#how-claude-code-combines-managed-sources)中时,它运行运行程序镜像的托管设置文件中的 hooks,默认情况下仅当服务器管理的设置和 MDM 交付的 Claude Code 策略都不提供托管层时。有关哪些文件到达云会话,请参阅[您的设置中携带的内容](/docs/zh-CN/cloud-environments#what-carries-over-from-your-setup)。

193 272 

194有关设置文件解析的详细信息,请参阅[设置](/docs/zh-CN/settings)。企业管理员可以使用 `allowManagedHooksOnly` 来阻止用户、项目和插件 hooks。在托管设置 `enabledPlugins` 中强制启用的插件中的 Hooks 是豁免的,因此管理员可以通过组织市场分发经过审查的 hooks。请参阅[Hook 配置](/docs/zh-CN/settings#hook-configuration)。273有关设置文件解析的详细信息,请参阅[设置](/docs/zh-CN/settings)。

274 

275来自设置文件、托管策略设置和插件的 Hooks 也在[subagents](/docs/zh-CN/sub-agents)内运行。当 subagent 调用工具时,工具事件(如 `PreToolUse` 和 `PostToolUse`)触发与主对话中配置的相同 hooks,输入携带 `agent_id` 和 `agent_type`[通用输入字段](#common-input-fields),用于标识 subagent。

276 

277企业管理员可以使用 `allowManagedHooksOnly` 来限制哪些 hooks 运行:

278 

279* 您的用户、项目、本地和插件 hooks 被阻止。托管设置 `enabledPlugins` 中强制启用的插件中的 Hooks 是豁免的

280* Claude Code 也将您的[`statusLine`](/docs/zh-CN/statusline)、[`fileSuggestion`](/docs/zh-CN/settings-reference#filesuggestion)和[`subagentStatusLine`](/docs/zh-CN/statusline#subagent-status-lines)设置缩小到托管设置

281* Claude Code 也禁用具有[`command` 源](/docs/zh-CN/plugin-marketplaces#command-sources)的插件,包括托管设置 `enabledPlugins` 中强制启用的插件,除非[`disableCommandPluginSources`](/docs/zh-CN/settings-reference#disablecommandpluginsources)明确设置为 `false`。`command` 源需要 Claude Code v2.1.229 或更高版本

282* Claude Code 也阻止市场[`headersHelper` 命令](/docs/zh-CN/plugin-marketplaces#authenticate-archive-downloads),除非[`disableCommandPluginSources`](/docs/zh-CN/settings-reference#disablecommandpluginsources)明确设置为 `false`,除了托管设置本身声明的市场

283 

284请参阅[在 `allowManagedHooksOnly` 下运行的内容](/docs/zh-CN/settings-reference#what-runs-under-allowmanagedhooksonly)。

285 

286Hook 条目在设置级别之间合并而不是相互替换:用户、项目和本地设置添加它们自己的 hooks 而不移除托管的,[`disableAllHooks`](#disable-or-remove-hooks)设置无法从托管设置外部禁用托管 hooks。

287 

288[HTTP hook 允许列表](/docs/zh-CN/settings-reference#hook-and-skill-settings)适用于来自每个源的 hooks,包括托管策略设置:

289 

290* `allowedHttpHookUrls`:在任何设置级别定义时,Claude Code 仅在其 URL 与合并的允许列表匹配时运行 HTTP hook 处理程序

291* `httpHookAllowedEnvVars`:定义时,Claude Code 仅将该列表上的环境变量插值到 hook 标头中

195 292 

196<h3 id="matcher-patterns">293<h3 id="matcher-patterns">

197 匹配器模式294 匹配器模式


218每个事件类型在不同的字段上匹配:315每个事件类型在不同的字段上匹配:

219 316 

220| 事件 | 匹配器过滤的内容 | 示例匹配器值 |317| 事件 | 匹配器过滤的内容 | 示例匹配器值 |

221| :---------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |318| :---------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

222| `PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest`、`PermissionDenied` | 工具名称 | `Bash`、`Edit\|Write`、`mcp__.*` |319| `PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest`、`PermissionDenied` | 工具名称 | `Bash`、`Edit\|Write`、`mcp__.*` |

223| `SessionStart` | 会话如何启动 | `startup`、`resume`、`clear`、`compact` |320| `SessionStart` | 会话如何启动 | `startup`、`resume`、`clear`、`compact`、`fork` |

224| `Setup` | 哪个 CLI 标志触发了设置 | `init`、`maintenance` |321| `Setup` | 哪个 CLI 标志触发了设置 | `init`、`maintenance` |

225| `SessionEnd` | 会话为何结束 | `clear`、`resume`、`logout`、`prompt_input_exit`、`bypass_permissions_disabled`、`other` |322| `SessionEnd` | 会话为何结束 | `clear`、`resume`、`logout`、`prompt_input_exit`、`other` |

226| `Notification` | 通知类型 | `permission_prompt`、`idle_prompt`、`auth_success`、`elicitation_dialog`、`elicitation_complete`、`elicitation_response`、`agent_needs_input`、`agent_completed` |323| `Notification` | 通知类型 | `permission_prompt`、`idle_prompt`、`auth_success`、`elicitation_dialog`、`elicitation_url_dialog`、`elicitation_complete`、`elicitation_response`、`agent_needs_input`、`agent_completed`、`quota_auto_resume_fired`、`quota_auto_resume_stale`、`quota_auto_resume_disabled` |

227| `SubagentStart` | 代理类型 | `general-purpose`、`Explore`、`Plan`、自定义代理名称或插件范围的名称如 `^my-plugin:reviewer$` |324| `SubagentStart` | 代理类型 | `general-purpose`、`Explore`、`Plan`、自定义代理名称或插件范围的名称如 `^my-plugin:reviewer$` |

228| `PreCompact`、`PostCompact` | 触发压缩的原因 | `manual`、`auto` |325| `PreCompact`、`PostCompact` | 触发压缩的原因 | `manual`、`auto` |

326| `PreModelSwitch`、`PostModelSwitch` | 会话切换到的模型的规范名称,如[PreModelSwitch](#premodelswitch)下所述 | `claude-opus-5`、`claude-opus-4-6\|claude-opus-5`、`.*opus.*` |

229| `SubagentStop` | 代理类型 | 与 `SubagentStart` 相同的值 |327| `SubagentStop` | 代理类型 | 与 `SubagentStart` 相同的值 |

230| `ConfigChange` | 配置源 | `user_settings`、`project_settings`、`local_settings`、`policy_settings`、`skills` |328| `ConfigChange` | 配置源 | `user_settings`、`project_settings`、`local_settings`、`policy_settings`、`skills` |

231| `CwdChanged` | 不支持匹配器 | 总是在每次目录更改时触发 |329| `CwdChanged` | 不支持匹配器 | 总是在每次出现时触发 |

330| `DirectoryAdded` | 目录如何被添加 | `slash_command`、`register_repo_root` |

232| `FileChanged` | 文字文件名以监视(请参阅 [FileChanged](#filechanged)) | `.envrc\|.env` |331| `FileChanged` | 文字文件名以监视(请参阅 [FileChanged](#filechanged)) | `.envrc\|.env` |

233| `StopFailure` | 错误类型 | `rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens`、`unknown` |332| `StopFailure` | 错误类型 | `rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`account_on_hold`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens`、`cloud_credential_error`、`unknown` |

234| `InstructionsLoaded` | 加载原因 | `session_start`、`nested_traversal`、`path_glob_match`、`include`、`compact` |333| `InstructionsLoaded` | 加载原因 | `session_start`、`nested_traversal`、`path_glob_match`、`include`、`compact` |

235| `UserPromptExpansion` | 命令名称 | 您的 skill 或命令名称 |334| `UserPromptExpansion` | 命令名称 | 您的 skill 或命令名称 |

236| `Elicitation` | MCP 服务器名称 | 您配置的 MCP 服务器名称 |335| `Elicitation` | MCP 服务器名称 | 您配置的 MCP 服务器名称 |

237| `ElicitationResult` | MCP 服务器名称 | 与 `Elicitation` 相同的值 |336| `ElicitationResult` | MCP 服务器名称 | 与 `Elicitation` 相同的值 |

238| `UserPromptSubmit`、`PostToolBatch`、`Stop`、`TeammateIdle`、`TaskCreated`、`TaskCompleted`、`WorktreeCreate`、`WorktreeRemove`、`MessageDisplay` | 不支持匹配器 | 总是在每次出现时触发 |337| `UserPromptSubmit`、`PostToolBatch`、`Stop`、`TeammateIdle`、`TaskCreated`、`TaskCompleted`、`WorktreeCreate`、`WorktreeRemove`、`MessageDisplay` | 不支持匹配器 | 总是在每次出现时触发 |

239 338 

240匹配器针对 Claude Code 在 stdin 上发送给您的 hook 的[JSON 输入](#hook-input-and-output)中的字段运行。对于工具事件,该字段是 `tool_name`。每个[hook 事件](#hook-events)部分列出了完整的匹配器值集和该事件的输入架构。339在 `cloud_credential_error` 上匹配 `StopFailure` 需要 Claude Code v2.1.267 或更高版本,这是第一个在该值下报告凭证加载失败而不是 `server_error` 或 `unknown` 的版本。

340 

341对于大多数事件,Claude Code 针对它在 stdin 上发送给您的 hook 的[JSON 输入](#hook-input-and-output)中的字段评估匹配器。对于工具事件,该字段是 `tool_name`。对于 `PreModelSwitch` 和 `PostModelSwitch`,Claude Code 针对它从 `to_model` 派生的规范名称评估匹配器,如[PreModelSwitch](#premodelswitch)下所述。每个[hook 事件](#hook-events)部分列出了完整的匹配器值集和该事件的输入架构。

241 342 

242此示例仅在 Claude 写入或编辑文件时运行 linting 脚本:343此示例仅在 Claude 写入或编辑文件时运行 linting 脚本:

243 344 


259}360}

260```361```

261 362 

262`UserPromptSubmit`、`PostToolBatch`、`Stop`、`TeammateIdle`、`TaskCreated`、`TaskCompleted`、`WorktreeCreate`、`WorktreeRemove`、`MessageDisplay` 和 `CwdChanged` 不支持匹配器,总是在每次出现时触发。如果您向这些事件添加 `matcher` 字段,它会被静默忽略。363如果您向不支持匹配器的事件添加 `matcher` 字段,它会被静默忽略。

263 364 

264对于工具事件,您可以通过在单个 hook 处理程序上设置[`if` 字段](#common-fields)来更狭隘地过滤。`if` 使用[权限规则语法](/docs/zh-CN/permissions)来匹配工具名称和参数,因此 `"Bash(git *)"` 仅在任何 Bash 输入的子命令与 `git *` 匹配时运行,`"Edit(*.ts)"` 仅对 TypeScript 文件运行。365对于工具事件,您可以通过在单个 hook 处理程序上设置[`if` 字段](#common-fields)来更狭隘地过滤。`if` 使用[权限规则语法](/docs/zh-CN/permissions)来匹配工具名称和参数,因此 `"Bash(git *)"` 仅在任何 Bash 输入的子命令与 `git *` 匹配时运行,`"Edit(*.ts)"` 仅对 TypeScript 文件运行。

265 366 


323* **[命令 hooks](#command-hook-fields)**(`type: "command"`):运行 shell 命令。您的脚本在 stdin 上接收事件的[JSON 输入](#hook-input-and-output),并通过退出代码和 stdout 传回结果。424* **[命令 hooks](#command-hook-fields)**(`type: "command"`):运行 shell 命令。您的脚本在 stdin 上接收事件的[JSON 输入](#hook-input-and-output),并通过退出代码和 stdout 传回结果。

324* **[HTTP hooks](#http-hook-fields)**(`type: "http"`):将事件的 JSON 输入作为 HTTP POST 请求发送到 URL。端点通过使用与命令 hooks 相同的[JSON 输出格式](#json-output)的响应体传回结果。425* **[HTTP hooks](#http-hook-fields)**(`type: "http"`):将事件的 JSON 输入作为 HTTP POST 请求发送到 URL。端点通过使用与命令 hooks 相同的[JSON 输出格式](#json-output)的响应体传回结果。

325* **[MCP 工具 hooks](#mcp-tool-hook-fields)**(`type: "mcp_tool"`):在已连接的[MCP 服务器](/docs/zh-CN/mcp)上调用工具。工具的文本输出被视为命令 hook stdout。426* **[MCP 工具 hooks](#mcp-tool-hook-fields)**(`type: "mcp_tool"`):在已连接的[MCP 服务器](/docs/zh-CN/mcp)上调用工具。工具的文本输出被视为命令 hook stdout。

326* **[提示 hooks](#prompt-and-agent-hook-fields)**(`type: "prompt"`):向 Claude 模型发送提示以进行单轮评估。模型返回 yes/no 决定作为 JSON。请参阅[基于提示的 hooks](#prompt-based-hooks)。427* **[提示 hooks](#prompt-and-agent-hook-fields)**(`type: "prompt"`):向 Claude 模型发送提示以进行单轮评估。模型返回其决定作为 JSON。请参阅[基于提示的 hooks](#prompt-based-hooks)。

327* **[代理 hooks](#prompt-and-agent-hook-fields)**(`type: "agent"`):生成一个可以使用 Read、Grep 和 Glob 等工具来验证条件的 subagent,然后返回决定。代理 hooks 是实验性的,可能会改变。请参阅[基于代理的 hooks](#agent-based-hooks)。428* **[代理 hooks](#prompt-and-agent-hook-fields)**(`type: "agent"`):生成一个可以使用 Read、Grep 和 Glob 等工具来验证条件的 subagent,然后返回决定。代理 hooks 是实验性的,可能会改变。请参阅[基于代理的 hooks](#agent-based-hooks)。

328 429 

329所有匹配的 hooks 并行运行,相同的处理程序会自动去重。命令 hooks 按命令字符串和 `args` 去重,HTTP hooks 按 URL 去重。430所有匹配的 hooks 并行运行。如果您在多个设置文件中定义相同的处理程序,它运行一次。插件或 skill 的相同处理程序副本保持分离。

330 431 

331处理程序在当前目录中运行,使用 Claude Code 的环境。在远程 web 环境中,`$CLAUDE_CODE_REMOTE` 环境变量设置为 `"true"`,在本地 CLI 中未设置。从 v2.1.199 开始,[`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/zh-CN/env-vars)设置为[远程控制](/docs/zh-CN/remote-control)会话 ID,而本地会话具有活跃的远程控制连接。432处理程序在当前目录中运行,使用 Claude Code 的环境。如果当前目录不再存在,例如另一个 shell 在会话中途删除的 worktree 或临时目录,Claude Code 从以下第一个仍然存在的目录运行命令 hooks:会话启动的目录、项目根目录、您的主目录或系统临时目录。Claude Code 在[调试日志](#debug-hooks)中记录一条警告,命名回退目录。

433 

434`$CLAUDE_CODE_REMOTE` 环境变量在远程 web 环境中为 `"true"`,在本地 CLI 中未设置。Claude Code v2.1.199 及更高版本在本地会话具有活跃的远程控制连接时将[`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/zh-CN/env-vars)设置为[远程控制](/docs/zh-CN/remote-control)会话 ID。

332 435 

333<h4 id="common-fields">436<h4 id="common-fields">

334 通用字段437 通用字段


337这些字段适用于所有 hook 类型:440这些字段适用于所有 hook 类型:

338 441 

339| 字段 | 必需 | 描述 |442| 字段 | 必需 | 描述 |

340| :-------------- | :- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |443| :-------------- | :- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

341| `type` | 是 | `"command"`、`"http"`、`"mcp_tool"`、`"prompt"` 或 `"agent"` |444| `type` | 是 | `"command"`、`"http"`、`"mcp_tool"`、`"prompt"` 或 `"agent"` |

342| `if` | 否 | 权限规则语法以过滤此 hook 何时运行,例如 `"Bash(git *)"` 或 `"Edit(*.ts)"`。hook 命令仅在工具调用与模式匹配时运行。请参阅下面的[Bash 匹配表](#bash-if-matching)了解 Bash 模式如何针对子命令、`$()`和反引号进行评估。仅在工具事件上评估:`PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest` 和 `PermissionDenied`。在其他事件上,设置了 `if` 的 hook 永远不会运行。使用与[权限规则](/docs/zh-CN/permissions)相同的语法 |445| `if` | 否 | 权限规则语法以过滤此 hook 何时运行,例如 `"Bash(git *)"` 或 `"Edit(*.ts)"`。hook 命令仅在工具调用与模式匹配时运行。请参阅下面的[Bash 匹配表](#bash-if-matching)了解 Bash 模式如何针对子命令、`$()` 和反引号进行评估。仅在工具事件上评估:`PreToolUse`、`PostToolUse`、`PostToolUseFailure`、`PermissionRequest` 和 `PermissionDenied`。在其他事件上,设置了 `if` 的 hook 永远不会运行。使用与[权限规则](/docs/zh-CN/permissions)相同的语法 |

343| `timeout` | 否 | 取消前的秒数。默认值:`command`、`http` 和 `mcp_tool` 为 600;`prompt` 为 30;`agent` 为 60。[`UserPromptSubmit`](#userpromptsubmit) 将 `command`、`http` 和 `mcp_tool` 的默认值降低到 30,[`MessageDisplay`](#messagedisplay) 将其降低到 10 |446| `timeout` | 否 | 取消前的秒数。Claude Code 不在您使用 [`async: true`](#run-hooks-in-the-background)运行的命令 hook 上强制执行它。默认值:`command`、`http` 和 `mcp_tool` 为 600;`prompt` 为 30;`agent` 为 60。Claude Code 在[`UserPromptSubmit`](#userpromptsubmit)、[`PreModelSwitch`](#premodelswitch)和[`PostModelSwitch`](#postmodelswitch)上将 `command`、`http` 和 `mcp_tool` 的默认值降低到 30,在[`MessageDisplay`](#messagedisplay)上降低到 10。[`SessionEnd`](#sessionend) hooks 共享 1.5 秒的预算;如果您的设置设置了更长的每个 hook `timeout`,Claude Code 会提高预算以匹配,最多 60 秒 |

344| `statusMessage` | 否 | hook 运行时显示的自定义加载程序消息 |447| `statusMessage` | 否 | hook 运行时显示的自定义加载程序消息 |

345| `once` | 否 | 如果为 `true`,每个会话仅运行一次,然后被移除。仅在[skill frontmatter](#hooks-in-skills-and-agents)中声明的 hooks 中受尊重;在设置文件和代理 frontmatter 中被忽略 |448| `once` | 否 | 如果为 `true`,Claude Code 在其第一次成功运行后移除 hook。失败、以退出代码 2 阻止或超时的运行会将 hook 保留在原位,因此它在下一个匹配事件上再次运行。仅在[skill frontmatter](#hooks-in-skills-and-agents)中声明的 hooks 中受尊重;在设置文件和代理 frontmatter 中被忽略 |

346 449 

347`if` 字段恰好包含一个权限规则。没有 `&&`、`||` 或列表语法来组合规则;要应用多个条件,请为每个条件定义一个单独的 hook 处理程序。450`if` 字段恰好包含一个权限规则。没有 `&&`、`||` 或列表语法来组合规则;要应用多个条件,请为每个条件定义一个单独的 hook 处理程序。

348 451 

452在文件工具的 `if` 条件中,单段目录模式如 `"Edit(src/**)"` 仅匹配工作目录中的 `src` 目录及其下的文件。要匹配任何深度的名为 `src` 的目录,请写 `"Edit(**/src/**)"`。在 v2.1.214 之前,`"Edit(src/**)"` 匹配工作目录下任何深度的名为 `src` 的目录。

453 

349<span id="bash-if-matching" />对于 Bash 模式,您的 hook 命令是否运行取决于模式的形状和 Claude 调用的 Bash 命令。前导 `VAR=value` 赋值在匹配前被剥离。454<span id="bash-if-matching" />对于 Bash 模式,您的 hook 命令是否运行取决于模式的形状和 Claude 调用的 Bash 命令。前导 `VAR=value` 赋值在匹配前被剥离。

350 455 

351| `if` 模式 | Bash 命令 | Hook 运行? | 原因 |456| `if` 模式 | Bash 命令 | Hook 运行? | 原因 |

352| :----------------- | :--------------------- | :------- | :-------------------------------------- |457| :----------------- | :-------------------------- | :------- | :----------------------------------------- |

353| `Bash(git *)` | `FOO=bar git push` | 是 | 前导赋值被剥离;`git push` 匹配 |458| `Bash(git *)` | `FOO=bar git push` | 是 | 前导赋值被剥离;`git push` 匹配 |

354| `Bash(git *)` | `npm test && git push` | 是 | 每个子命令都被检查;`git push` 匹配 |459| `Bash(git *)` | `npm test && git push` | 是 | 每个子命令都被检查;`git push` 匹配 |

355| `Bash(rm *)` | `echo $(rm -rf /)` | 是 | `$()` 和反引号内的命令被检查;`rm -rf /` 匹配 |460| `Bash(rm *)` | `echo $(rm -rf /)` | 是 | `$()` 和反引号内的命令被检查;`rm -rf /` 匹配 |

356| `Bash(rm *)` | `echo $(date)` | 否 | 没有子命令匹配 `rm *` |461| `Bash(rm *)` | `echo $(date)` | 否 | 没有子命令匹配 `rm *` |

462| `Bash(cat *)` | `echo before $(date) after` | 否 | 替换可以位于任何参数位置,因此检查完整命令和 `date`;都不匹配 `cat *` |

463| `Bash(git *)` | `$TOOL git push` | 是 | Claude Code 无法判断命令名称展开为什么,因此它运行 hook |

357| `Bash(git push *)` | `echo $(date)` | 是 | 指定超过命令名称的模式在 `$()`、反引号或 `$VAR` 上运行 hook |464| `Bash(git push *)` | `echo $(date)` | 是 | 指定超过命令名称的模式在 `$()`、反引号或 `$VAR` 上运行 hook |

358 465 

359过滤器也会失败开放,当 Bash 命令无法解析时无论如何运行您的 hook。因为 `if` 过滤器是尽力而为的,使用[权限系统](/docs/zh-CN/permissions)而不是 hook 来强制执行硬允许或拒绝。466当 Claude Code 无法确定 Bash 输入运行哪些命令时,它无论如何都会运行您的 hook。因为 `if` 过滤器是尽力而为的,使用[权限系统](/docs/zh-CN/permissions)而不是 hook 来强制执行硬允许或拒绝。

360 467 

361<h4 id="command-hook-fields">468<h4 id="command-hook-fields">

362 命令 hook 字段469 命令 hook 字段


369| `command` | 是 | 要执行的 shell 命令。与 `args` 一起,要直接生成的可执行文件。请参阅[Exec 形式和 shell 形式](#exec-form-and-shell-form) |476| `command` | 是 | 要执行的 shell 命令。与 `args` 一起,要直接生成的可执行文件。请参阅[Exec 形式和 shell 形式](#exec-form-and-shell-form) |

370| `args` | 否 | 参数列表。存在时,`command` 被解析为可执行文件并直接使用 `args` 作为参数向量生成,不涉及 shell。请参阅[Exec 形式和 shell 形式](#exec-form-and-shell-form) |477| `args` | 否 | 参数列表。存在时,`command` 被解析为可执行文件并直接使用 `args` 作为参数向量生成,不涉及 shell。请参阅[Exec 形式和 shell 形式](#exec-form-and-shell-form) |

371| `async` | 否 | 如果为 `true`,在后台运行而不阻止。请参阅[在后台运行 hooks](#run-hooks-in-the-background) |478| `async` | 否 | 如果为 `true`,在后台运行而不阻止。请参阅[在后台运行 hooks](#run-hooks-in-the-background) |

372| `asyncRewake` | 否 | 如果为 `true`,在后台运行并在退出代码 2 时唤醒 Claude。暗示 `async`。Hook 的 stderr,或 stdout(如果 stderr 为空),作为系统提醒显示给 Claude,以便它可以对长时间运行的后台失败做出反应 |479| `asyncRewake` | 否 | 如果为 `true`,在后台运行并在退出代码 2 时唤醒 Claude。hook 的 stderr,或 stdout(如果 stderr 为空),作为系统提醒显示给 Claude,以便它可以对长时间运行的后台失败做出反应 |

373| `shell` | 否 | 用于此 hook 的 shell。接受 `"bash"` 或 `"powershell"`。默认为 `"bash"`,或在未安装 Git Bash 时在 Windows 上默认为 `"powershell"`。设置 `"powershell"` 在 Windows 上通过 PowerShell 运行命令。不需要 `CLAUDE_CODE_USE_POWERSHELL_TOOL`,因为 hooks 直接生成 PowerShell。设置 `args` 时被忽略 |480| `shell` | 否 | 用于此 hook 的 shell。接受 `"bash"` 或 `"powershell"`。默认为 `"bash"`,或在未安装 Git Bash 时在 Windows 上默认为 `"powershell"`。设置 `"powershell"` 在 Windows 上通过 PowerShell 运行命令。不需要 `CLAUDE_CODE_USE_POWERSHELL_TOOL`,因为 hooks 直接生成 PowerShell。设置 `args` 时被忽略 |

374 481 

375<a id="exec-form-and-shell-form" />482<a id="exec-form-and-shell-form" />


431 538 

432Claude Code 使用 `Content-Type: application/json` 将 hook 的[JSON 输入](#hook-input-and-output)作为 POST 请求体发送。响应体使用与命令 hooks 相同的[JSON 输出格式](#json-output)。539Claude Code 使用 `Content-Type: application/json` 将 hook 的[JSON 输入](#hook-input-and-output)作为 POST 请求体发送。响应体使用与命令 hooks 相同的[JSON 输出格式](#json-output)。

433 540 

434错误处理与命令 hooks 不同:非 2xx 响应、连接失败和超时都会产生非阻止错误,允许执行继续。要阻止工具调用或拒绝权限,返回 2xx 响应,其 JSON 体包含 `decision: "block"` 或 `hookSpecificOutput` 与 `permissionDecision: "deny"`。541错误处理与命令 hooks 不同;请参阅[HTTP 响应处理](#http-response-handling)。

435 542 

436此示例将 `PreToolUse` 事件发送到本地验证服务,使用来自 `MY_TOKEN` 环境变量的令牌进行身份验证:543此示例将 `PreToolUse` 事件发送到本地验证服务,使用来自 `MY_TOKEN` 环境变量的令牌进行身份验证:

437 544 


470| `tool` | 是 | 该服务器上要调用的工具的名称 |577| `tool` | 是 | 该服务器上要调用的工具的名称 |

471| `input` | 否 | 传递给工具的参数。字符串值支持从 hook 的[JSON 输入](#hook-input-and-output)进行 `${path}` 替换,例如 `"${tool_input.file_path}"` |578| `input` | 否 | 传递给工具的参数。字符串值支持从 hook 的[JSON 输入](#hook-input-and-output)进行 `${path}` 替换,例如 `"${tool_input.file_path}"` |

472 579 

473工具的文本内容被视为命令 hook stdout:如果它解析为有效的[JSON 输出](#json-output),则作为决定进行处理,否则显示为纯文本。如果命名的服务器未连接,或工具返回 `isError: true`,hook 会产生非阻止错误,执行继续。580Claude Code 读取工具的文本内容的方式与读取命令 hook stdout 相同,遵循[退出代码 0 下的解析规则](#exit-code-0)。如果命名的服务器未连接,或工具返回 `isError: true`,hook 会产生非阻止错误,执行继续。

474 

475MCP 工具 hooks 在 Claude Code 连接到您的 MCP 服务器后在每个 hook 事件上可用。`SessionStart` 和 `Setup` 通常在服务器完成连接之前触发,因此这些事件上的 hooks 应该期望在首次运行时出现"未连接"错误。

476 581 

477此示例在每个 `Write` 或 `Edit` 后在 `my_server` MCP 服务器上调用 `security_scan` 工具,传递编辑文件的路径:582此示例在每个 `Write` 或 `Edit` 后在 `my_server` MCP 服务器上调用 `security_scan` 工具,传递编辑文件的路径:

478 583 


496}601}

497```602```

498 603 

604`mcp_tool` hook 仅在 Claude Code 使会话的 MCP 服务器对 hooks 可用后才能在每个 hook 事件上运行。`SessionStart` 和 `Setup` 可能在该点之前触发:

605 

606* **在启动时**:`SessionStart` 在服务器可用之前触发,包括当您使用 `--continue` 或 `--resume` 启动时。Claude Code 跳过事件的 `mcp_tool` hooks 而不调用它们的工具,[调试日志](#debug-hooks)记录 `mcp_tool hooks are not available for the 'SessionStart' hook event (no MCP client context)`。

607* **稍后在运行的会话中**:在 `/clear` 或压缩后,`SessionStart` 再次触发,服务器已可用,其 `mcp_tool` hooks 运行。

608* **在 `Setup` 上**:`Setup` 总是在服务器可用之前触发,因此 Claude Code 每次都跳过其 `mcp_tool` hooks 并记录相同的消息,命名 `Setup`。

609 

610例如,此配置从没有匹配器的 `SessionStart` hook 在 `my_server` MCP 服务器上调用 `load_context` 工具,因此它适用于每个 `SessionStart` 源:

611 

612```json theme={null}

613{

614 "hooks": {

615 "SessionStart": [

616 {

617 "hooks": [

618 {

619 "type": "mcp_tool",

620 "server": "my_server",

621 "tool": "load_context"

622 }

623 ]

624 }

625 ]

626 }

627}

628```

629 

630当您运行 `claude` 时,Claude Code 跳过此 hook,永远不调用 `load_context`,并将 `no MCP client context` 消息写入调试日志。在该同一会话中运行 `/clear`,hook 运行并调用 `load_context`。`type: "command"` hook 在 `SessionStart` 上运行,因此对会话从其第一个转向需要的任何东西使用一个。

631 

499<h4 id="prompt-and-agent-hook-fields">632<h4 id="prompt-and-agent-hook-fields">

500 提示和代理 hook 字段633 提示和代理 hook 字段

501</h4>634</h4>


513 646 

514使用这些占位符按项目或插件根目录引用 hook 脚本,无论 hook 运行时的工作目录如何:647使用这些占位符按项目或插件根目录引用 hook 脚本,无论 hook 运行时的工作目录如何:

515 648 

516* `${CLAUDE_PROJECT_DIR}`:项目根目录。Claude Code 也在[stdio MCP 服务器](/docs/zh-CN/mcp#option-3-add-a-local-stdio-server)和插件 LSP 服务器的环境中设置此变量。649* `${CLAUDE_PROJECT_DIR}`:项目根目录,会话启动的位置。Claude Code 也在[stdio MCP 服务器](/docs/zh-CN/mcp#option-3-add-a-local-stdio-server)和插件 LSP 服务器的环境中设置此变量。

517* `${CLAUDE_PLUGIN_ROOT}`:插件的安装目录,用于与[插件](/docs/zh-CN/plugins)捆绑的脚本。在每次插件更新时更改。650* `${CLAUDE_PLUGIN_ROOT}`:插件的安装目录,用于与[插件](/docs/zh-CN/plugins)捆绑的脚本。请参阅[插件环境变量](/docs/zh-CN/plugins-reference#environment-variables)了解路径在更新中的行为。

518* `${CLAUDE_PLUGIN_DATA}`:插件的[持久数据目录](/docs/zh-CN/plugins-reference#persistent-data-directory),用于应该在插件更新后保留的依赖项和状态。651* `${CLAUDE_PLUGIN_DATA}`:插件的[持久数据目录](/docs/zh-CN/plugins-reference#persistent-data-directory),用于应该在插件更新后保留的依赖项和状态。

519 652 

520对于任何引用路径占位符的 hook,优先使用[exec 形式](#exec-form-and-shell-form)。Exec 形式将每个 `args` 元素作为一个参数传递,不带 shell 标记化,因此包含空格或特殊字符的路径不需要引号。在 shell 形式中,用双引号包装每个占位符。653<Note>

654 **Worktrees 是不同的。** 如果 Claude 在会话期间进入[worktree](/docs/zh-CN/worktrees),Claude Code 保持 `${CLAUDE_PROJECT_DIR}` 在其原位,并以不同的方式将 worktree 路径传递给您的 hooks:

655 

656 * **`${CLAUDE_PROJECT_DIR}` 保持不变**:它仍然指向会话启动的项目根目录,因此像 `${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh` 这样的命令仍然在主检出中运行脚本。

657 * **`cwd` 跟随 Claude**:hook 的[输入 JSON](#common-input-fields)中的 `cwd` 字段在 Claude 进入 worktree 后是 worktree 根目录,在 Claude 运行 `cd` 后是新目录。当 hook 需要知道 Claude 正在哪个目录中工作时读取它。

658</Note>

659 

660对于任何引用路径占位符的 hook,优先使用[exec 形式](#exec-form-and-shell-form)。在 shell 形式中,用双引号包装每个占位符。

521 661 

522<Tabs>662<Tabs>

523 <Tab title="项目脚本">663 <Tab title="项目脚本">


577 Skills 和代理中的 Hooks717 Skills 和代理中的 Hooks

578</h3>718</h3>

579 719 

580除了设置文件和插件外,hooks 还可以使用 frontmatter 直接在[skills](/docs/zh-CN/skills)和[subagents](/docs/zh-CN/sub-agents)中定义。这些 hooks 的范围限于组件的生命周期,仅在该组件活跃时运行。720除了设置文件和插件外,hooks 还可以使用 frontmatter 直接在[skills](/docs/zh-CN/skills)和[subagents](/docs/zh-CN/sub-agents)中定义,使用与基于设置的 hooks 相同的配置格式。Claude Code 保持它们注册多长时间取决于组件:

581 

582支持所有 hook 事件。对于 subagents,`Stop` hooks 会自动转换为 `SubagentStop`,因为这是 subagent 完成时触发的事件。

583 721 

584Hooks 使用与基于设置的 hooks 相同的配置格式,但范围限于组件的生命周期,并在其完成时清理。722* **Subagent hooks**:Claude Code 仅在该 subagent 运行时运行它们,并在其完成时移除它们。Claude Code 在此处将 `Stop` hook 转换为 `SubagentStop`,这是 subagent 完成时触发的事件。

723* **Skill hooks**:Claude Code 在您或 Claude 调用 skill 时注册它们,并在会话的其余部分保持运行它们,在 skill 自己的转向之后的转向上也是如此。要让 Claude Code 在第一次成功运行后移除 hook,请在其上设置[`once: true`](#common-fields)。

585 724 

586此 skill 定义了一个 `PreToolUse` hook,在每个 `Bash` 命令之前运行安全验证脚本:725此 skill 定义了一个 `PreToolUse` hook,在每个 `Bash` 命令之前运行安全验证脚本:

587 726 


598---737---

599```738```

600 739 

601代理在其 YAML frontmatter 中使用相同的格式。740Subagents 在其 YAML frontmatter 中使用相同的格式。

741 

742项目 skill 中的 Frontmatter hooks 遵循与设置文件中的 hooks 相同的[工作区信任规则](#workspace-trust)。Claude Code 在您或 Claude 调用 skill 时注册它们,包括在您未信任的文件夹中的 `-p` 运行。

743 

744项目 subagent 中的 Frontmatter hooks 仅在您接受 agent 文件来自的文件夹的[工作区信任对话](/docs/zh-CN/permissions#project-allow-rules-and-workspace-trust)后运行。`-p` 会话不计为接受它。[在您信任文件夹之前运行的内容](/docs/zh-CN/permissions#what-runs-before-you-trust-a-folder)将此与设置文件规则进行比较,subagents 页面列出[哪些范围是豁免的](/docs/zh-CN/sub-agents#hooks-in-subagent-frontmatter)。在 v2.1.218 之前,这些 hooks 可以从您未信任的文件夹运行。

602 745 

603<h3 id="the-/hooks-menu">746<h3 id="the-/hooks-menu">

604 `/hooks` 菜单747 `/hooks` 菜单


608 751 

609菜单显示所有五种 hook 类型:`command`、`prompt`、`agent`、`http` 和 `mcp_tool`。每个 hook 都标有 `[type]` 前缀和指示其定义位置的源:752菜单显示所有五种 hook 类型:`command`、`prompt`、`agent`、`http` 和 `mcp_tool`。每个 hook 都标有 `[type]` 前缀和指示其定义位置的源:

610 753 

611* `User`:来自 `~/.claude/settings.json`754* `User Settings`:来自 `~/.claude/settings.json`

612* `Project`:来自 `.claude/settings.json`755* `Project Settings`:来自 `.claude/settings.json`

613* `Local`:来自 `.claude/settings.local.json`756* `Local Settings`:来自 `.claude/settings.local.json`

614* `Plugin`:来自插件的 `hooks/hooks.json`757* `Plugin Hooks`:来自插件的 `hooks/hooks.json`

615* `Session`:在当前会话中在内存中注册758* `Session Hooks`:在当前会话中在内存中注册

616* `Built-in`:由 Claude Code 内部注册

617 759 

618选择 hook 会打开详细视图,显示其事件、匹配器、类型、源文件以及完整的命令、提示或 URL。菜单是只读的:要添加、修改或移除 hooks,请直接编辑设置 JSON 或要求 Claude 进行更改。760选择 hook 会打开详细视图,显示其事件、匹配器、类型、源文件以及完整的命令、提示或 URL。菜单是只读的:要添加、修改或移除 hooks,请直接编辑设置 JSON 或要求 Claude 进行更改。

619 761 


623 765 

624要移除 hook,请从设置 JSON 文件中删除其条目。766要移除 hook,请从设置 JSON 文件中删除其条目。

625 767 

626要临时禁用所有 hooks 而不移除它们,请在设置文件中设置 `"disableAllHooks": true`。没有办法在保持 hook 在配置中的同时禁用单个 hook。768要临时禁用所有 hooks 而不移除它们,请在设置文件中设置 `"disableAllHooks": true`。Claude Code 读取[设置优先级](/docs/zh-CN/settings#settings-precedence)应用后留下的值,因此项目的 `.claude/settings.json` 中的 `"disableAllHooks": false` 覆盖您的用户设置中的 `true`。要关闭一次运行,无论项目的设置说什么,请传递 `--settings '{"disableAllHooks": true}'`,这优先于项目和本地设置。没有办法在保持 hook 在配置中的同时禁用单个 hook。

627 769 

628`disableAllHooks` 设置遵守托管设置层次结构。如果管理员通过托管策略设置配置了 hooks,则在用户、项目或本地设置中设置的 `disableAllHooks` 无法禁用这些托管 hooks。仅在托管设置级别设置的 `disableAllHooks` 可以禁用托管 hooks。770`disableAllHooks` 设置遵守托管设置层次结构。如果管理员通过托管策略设置配置了 hooks,则在用户、项目或本地设置中设置的 `disableAllHooks` 无法禁用这些托管 hooks。仅在托管设置级别设置的 `disableAllHooks` 可以禁用托管 hooks。对于每个级别的完整范围,请参阅[`disableAllHooks`](/docs/zh-CN/settings-reference#disableallhooks)。

629 771 

630对设置文件中 hooks 的直接编辑通常由文件监视程序自动拾取。772对设置文件中 hooks 的直接编辑通常由文件监视程序自动拾取。

631 773 


633 Hook 输入和输出775 Hook 输入和输出

634</h2>776</h2>

635 777 

636命令 hooks 通过 stdin 接收 JSON 数据,并通过退出代码、stdout 和 stderr 传回结果。HTTP hooks 接收相同的 JSON 作为 POST 请求体,并通过 HTTP 响应体传回结果。本部分涵盖所有事件通用的字段和行为。每个事件在[Hook 事件](#hook-events)下的部分包括其特定的输入架构和决定控制选项。778命令 hook 通过 stdin 接收 JSON 数据,并通过退出代码、stdout 和 stderr 传达结果。HTTP hook 接收与 POST 请求体相同的 JSON,并通过 HTTP 响应体传达结果。本节涵盖所有事件通用的字段和行为。[Hook 事件](#hook-events)下的每个事件部分包括其特定的输入架构和决策控制选项。

779 

780在 macOS 和 Linux 上,命令 hook 在没有控制终端的自己的会话中运行。hook 进程和任何子进程无法打开 `/dev/tty` 或直接向 Claude Code 界面发送转义序列。Windows 没有 `/dev/tty`。

637 781 

638从 v2.1.139 开始,在 macOS 和 Linux 上,命令 hooks 在没有控制终端的自己的会话中运行。hook 进程和任何子进程无法打开 `/dev/tty` 或直接向 Claude Code 界面发送转义序列。Windows 没有 `/dev/tty`。要在任何平台上向用户显示消息,请在 JSON 输出中返回[`systemMessage`](#json-output)。要触发桌面通知、设置窗口标题或响铃,请改为返回[`terminalSequence`](#emit-terminal-notifications)。782要在任何平台上向用户显示消息,请在 JSON 输出中返回 [`systemMessage`](#json-output)。某些事件会丢弃它或将其传递到其他地方,每个[事件部分](#hook-events)都会说明这一点。要触发桌面通知、设置窗口标题或响铃,请改为返回 [`terminalSequence`](#emit-terminal-notifications)。

639 783 

640<h3 id="common-input-fields">784<h3 id="common-input-fields">

641 通用输入字段785 通用输入字段

642</h3>786</h3>

643 787 

644Hook 事件接收这些字段作为 JSON,除了每个[hook 事件](#hook-events)部分中记录的事件特定字段。对于命令 hooks,此 JSON 通过 stdin 到达。对于 HTTP hooks,它作为 POST 请求体到达。788Hook 事件接收这些字段作为 JSON,除了每个 [hook 事件](#hook-events)部分中记录的事件特定字段。对于命令 hook,此 JSON 通过 stdin 到达。对于 HTTP hook,它作为 POST 请求体到达。

645 789 

646| 字段 | 描述 |790| 字段 | 描述 |

647| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |791| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

648| `session_id` | 当前会话标识符 |792| `session_id` | 当前会话标识符 |

649| `prompt_id` | UUID 标识当前正在处理的用户提示。与 OpenTelemetry 事件上的[`prompt.id` 属性](/docs/zh-CN/monitoring-usage#event-correlation-attributes)匹配,因此您可以将 hook 输出与单个提示的遥测关联起来。在第一个用户输入之前不存在。需要 Claude Code v2.1.196 或更高版本 |793| `prompt_id` | 标识当前正在处理的用户提示的 UUID。与 [OpenTelemetry 事件上的 `prompt.id` 属性](/docs/zh-CN/monitoring-usage#event-correlation-attributes)匹配,因此您可以将 hook 输出与单个提示的遥测关联起来。在第一个用户输入之前不存在。需要 Claude Code v2.1.196 或更高版本 |

650| `transcript_path` | 对话 JSON 的路径。成绩单文件异步写入,可能滞后于内存中的对话,因此当 hook 触发时,它可能还不包括当前轮次的最新消息。需要当前轮次最后助手文本的 hooks 应该在[Stop](#stop) 和 [SubagentStop](#subagentstop) 上使用 `last_assistant_message`,而不是读取成绩单 |794| `transcript_path` | 对话 JSON 的路径。转录文件异步写入,可能滞后于内存中的对话,因此当 hook 触发时,它可能还不包括当前轮次的最新消息。需要当前轮次最终助手文本的 hook 应在 [Stop](#stop) 和 [SubagentStop](#subagentstop) 上使用 `last_assistant_message`,而不是读取转录 |

651| `cwd` | 调用 hook 时的当前工作目录 |795| `cwd` | 调用 hook 时的当前工作目录 |

652| `permission_mode` | 当前[权限模式](/docs/zh-CN/permissions#permission-modes):`"default"`、`"plan"`、`"acceptEdits"`、`"auto"`、`"dontAsk"` 或 `"bypassPermissions"`。标记为**手动**的模式作为 `"default"` 到达,永远不会作为 `"manual"` 到达,因此匹配 `"default"` 的脚本继续工作。并非所有事件都接收此字段。检查每个[hook 事件](#hook-events)部分中的 JSON 示例 |796| `scratchpad_dir` | 会话的 scratchpad 目录的路径,Claude 在其中保存临时工作文件。当会话没有 scratchpad 或 temp 目录不可用时不存在。需要 Claude Code v2.1.257 或更高版本 |

653| `effort` | 对象,其中 `level` 字段保存该轮次的活跃[努力级别](/docs/zh-CN/model-config#adjust-effort-level):`"low"`、`"medium"`、`"high"`、`"xhigh"` 或 `"max"`。如果请求的模型努力级别超过当前模型支持的级别,这是模型实际使用的降级级别。Ultracode 不是一个不同的级别,报告为 `"xhigh"`。该对象与[状态行](/docs/zh-CN/statusline#available-data) `effort` 字段匹配。存在于在工具使用上下文中触发的事件中,例如 `PreToolUse`、`PostToolUse`、`Stop` 和 `SubagentStop`,当当前模型支持努力参数时。该级别也可作为 `$CLAUDE_EFFORT` 环境变量提供给 hook 命令和 Bash 工具。 |797| `permission_mode` | 当前[权限模式](/docs/zh-CN/permissions#permission-modes):`"default"`、`"plan"`、`"acceptEdits"`、`"auto"`、`"dontAsk"` 或 `"bypassPermissions"`。标记为**手动**的模式作为 `"default"` 到达,从不作为 `"manual"`,因此匹配 `"default"` 的脚本继续工作。并非所有事件都接收此字段。检查每个 [hook 事件](#hook-events)部分中的 JSON 示例 |

654| `hook_event_name` | 触发的事件名称 |798| `effort` | 对象,其 `level` 字段保存 hook 运行时生效的[工作量级别](/docs/zh-CN/model-config#adjust-effort-level):`"low"`、`"medium"`、`"high"`、`"xhigh"` 或 `"max"`。如果您设置了活跃模型不支持的级别,`level` 会报告 Claude Code 运行的级别;[调整工作量级别](/docs/zh-CN/model-config#adjust-effort-level)说明它如何选择该级别。Ultracode 不是一个不同的级别,报告为 `"xhigh"`。该对象与[状态行](/docs/zh-CN/statusline#available-data) `effort` 字段匹配。对于在工具使用上下文中触发的事件(如 `PreToolUse`、`PostToolUse`、`Stop` 和 `SubagentStop`),当当前模型支持工作量参数时存在。该级别也可作为 `$CLAUDE_EFFORT` 环境变量供 hook 命令和 Bash 工具使用。 |

799| `hook_event_name` | 触发的事件的名称 |

655 800 

656使用 `--agent` 运行或在 subagent 内部时,包括两个额外字段:801使用 `--agent` 运行或在 subagent 内部时,包括两个额外字段:

657 802 

658| 字段 | 描述 |803| 字段 | 描述 |

659| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |804| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

660| `agent_id` | Subagent 的唯一标识符。仅当 hook 在 subagent 调用内触发时存在。使用此来区分 subagent hook 调用和主线程调用。 |805| `agent_id` | subagent 的唯一标识符。仅当 hook 在 subagent 调用内触发时存在。使用此来区分 subagent hook 调用和主线程调用。 |

661| `agent_type` | 代理名称(例如,`"Explore"` 或 `"security-reviewer"`)。当会话使用 `--agent` 或 hook 在 subagent 内触发时存在。对于 subagents,subagent 的类型优先于会话的 `--agent` 值。对于[自定义 subagents](/docs/zh-CN/sub-agents),这是代理 frontmatter 中的 `name` 字段,而不是文件名。对于由[插件](/docs/zh-CN/plugins)提供的 subagents,这是插件范围的标识符,例如 `my-plugin:reviewer`,而不是裸 frontmatter 名称。请参阅[SubagentStart](#subagentstart)了解如何针对插件范围的名称编写匹配器。 |806| `agent_type` | Agent 名称(例如,`"Explore"` 或 `"security-reviewer"`)。当会话使用 `--agent` 或 hook 在 subagent 内触发时存在。对于 subagent,subagent 的类型优先于会话的 `--agent` 值。请参阅 [SubagentStart](#subagentstart) 了解自定义和插件 subagent 报告的值以及如何针对插件范围的名称编写匹配器。 |

807 

808只有 [`SessionStart`](#sessionstart) hook 可以接收 `model` 字段,Claude Code 并不总是包括它。[`PreModelSwitch`](#premodelswitch) 和 [`PostModelSwitch`](#postmodelswitch) hook 改为接收 `from_model` 和 `to_model`,因此使用 PostModelSwitch hook 来跟踪模型在会话期间的变化。

809 

810没有 `$CLAUDE_MODEL` 环境变量。如果您在 shell 中设置了 hook,可以读取 `$ANTHROPIC_MODEL`,但该值在您使用 `/model` 在会话期间切换模型时不会改变。

662 811 

663仅[`SessionStart`](#sessionstart) hooks 可以接收 `model` 字段,且不保证存在。没有 `$CLAUDE_MODEL` 环境变量。Hook 进程继承父环境,因此如果您在 shell 中设置了 `$ANTHROPIC_MODEL`,它可以读取该值,但当您在会话期间使用 `/model` 切换模型时,该值不会改变。一组变量不被继承:Claude Code [从它生成的每个子进程中删除 `OTEL_*` 导出器变量](/docs/zh-CN/monitoring-usage#administrator-configuration),包括 hooks。812hook 进程继承父环境,除了 Claude Code [从它生成的每个子进程中删除](/docs/zh-CN/monitoring-usage#administrator-configuration)的 `OTEL_*` 导出器变量,以及当 [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](/docs/zh-CN/env-vars#variables) 设置为 `1` 时它剥离的变量。

664 813 

665例如,Bash 命令的 `PreToolUse` hook 在 stdin 上接收:814例如,Bash 命令的 `PreToolUse` hook 在 stdin 上接收以下内容:

666 815 

667```json theme={null}816```json theme={null}

668{817{


670 "prompt_id": "550e8400-e29b-41d4-a716-446655440000",819 "prompt_id": "550e8400-e29b-41d4-a716-446655440000",

671 "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",820 "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",

672 "cwd": "/home/user/my-project",821 "cwd": "/home/user/my-project",

822 "scratchpad_dir": "/tmp/claude-1000/-home-user-my-project/abc123/scratchpad",

673 "permission_mode": "default",823 "permission_mode": "default",

674 "hook_event_name": "PreToolUse",824 "hook_event_name": "PreToolUse",

675 "tool_name": "Bash",825 "tool_name": "Bash",

676 "tool_input": {826 "tool_input": {

677 "command": "npm test"827 "command": "npm test",

678 }828 "description": "Run test suite",

829 "timeout": 120000,

830 "run_in_background": false

831 },

832 "tool_use_id": "toolu_01ABC123..."

679}833}

680```834```

681 835 

682`tool_name` 和 `tool_input` 字段是事件特定的。每个[hook 事件](#hook-events)部分记录了该事件的额外字段。836`tool_name`、`tool_input` 和 `tool_use_id` 字段是事件特定的。每个 [hook 事件](#hook-events)部分记录该事件的额外字段。

683 837 

684<h3 id="exit-code-output">838<h3 id="exit-code-output">

685 退出代码输出839 退出代码输出

686</h3>840</h3>

687 841 

688您的 hook 命令的退出代码告诉 Claude Code 操作是否应该继续、被阻止或被忽略。842来自 hook 命令的退出代码告诉 Claude Code 该操作是否应继续、被阻止或被忽略。退出代码不单独起作用。Claude Code 从 stdout 读取[JSON 输出字段](#json-output),无论退出代码是什么,对于使用标准决策模型的事件,通过架构验证的解析对象与代码一起生效。退出 2 的阻止是 JSON 无法覆盖的唯一结果。

689 843 

690**退出 0** 表示成功。Claude Code 解析 stdout 以获取[JSON 输出字段](#json-output)。JSON 输出仅在退出 0 时处理。对于大多数事件,stdout 被写入调试日志,但不显示在成绩单中。例外是 `UserPromptSubmit`、`UserPromptExpansion` 和 `SessionStart`,其中 stdout 作为 Claude 可以看到和作用的上下文添加。844两个表拥有每个事件的例外:[每个事件的退出代码 2 行为](#exit-code-2-behavior-per-event)说明退出代码对每个事件的作用,[决策控制](#decision-control)说明每个事件接受哪些决策字段。通用字段如 `systemMessage` 在大多数事件中工作,并在 [JSON 输出](#json-output)表中列出。

691 845 

692**退出 2** 表示阻止错误。Claude Code 忽略 stdout 和其中的任何 JSON。相反,stderr 文本被反馈给 Claude 作为错误消息。效果取决于事件:`PreToolUse` 阻止工具调用,`UserPromptSubmit` 拒绝提示,等等。有关完整列表,请参阅[每个事件的退出代码 2 行为](#exit-code-2-behavior-per-event)。846<h4 id="exit-code-0">

847 退出代码 0

848</h4>

849 

850退出 0 表示成功,是您打印 JSON 进行结构化控制时的预期退出代码。

851 

852对于大多数事件,Claude Code 将 stdout 写入调试日志,不在转录中显示。例外是 `UserPromptSubmit`、`UserPromptExpansion`、`SessionStart` 和 `PostModelSwitch`,其中 Claude Code 添加纯文本 stdout 作为 Claude 可以看到和作用的上下文。

853 

854Claude Code 是否将您的 stdout 读取为 [JSON 输出](#json-output)或纯文本取决于它如何开始和结束,忽略周围的空格:

693 855 

694**任何其他退出代码** 是大多数 hook 事件的非阻止错误。成绩单显示 `<hook name> hook error` 通知,然后是 stderr 的第一行,因此您可以在不使用 `--debug` 的情况下识别原因。执行继续,完整的 stderr 被写入调试日志。856* **以 `{` 开始并以 `}` 结束**:Claude Code 将其解析为 JSON。当输出是两行或更多行,每行本身都解析为 JSON,且没有行是设置字段的 [JSON 输出](#json-output)对象时,Claude Code 将整个输出视为纯文本。当其中一行确实设置了字段时,整个输出是解析失败,如下所述。

857* **以 `{` 开始但不以 `}` 结束**:Claude Code 将其视为纯文本。

858* **以其他任何内容开始**:Claude Code 将其视为纯文本、JSON 数组或包含的引用 JSON 字符串。

695 859 

696例如,一个 hook 命令脚本,阻止危险的 Bash 命令:860对于使用标准决策模型的事件,退出 0 且解析对象未通过架构验证是非阻止错误:操作继续,转录显示 `<hook name> hook error` 通知,带有验证消息。在任何退出代码(除 2 外)上都会发生相同情况,而[退出 2 仍然阻止](#exit-code-2)。

861 

862对于使用标准决策模型的事件,当 Claude Code 尝试将您的 stdout 解析为 JSON 且无法解析时,它在除 2 外的每个退出代码上报告非阻止错误。转录显示 `<hook name> hook error` 通知,带有解析消息。在添加纯文本 stdout 作为上下文的事件上,Claude Code 不添加文本。在 v2.1.248 之前,Claude Code 将该 stdout 视为纯文本。

863 

864来自退出 0 的 hook 的 Stderr 仅进入调试日志,从不进入转录,Claude 从不看到它。要自己读取它,请启用[调试日志](#debug-hooks)。要从 `PostToolUse` 或 `PostToolUseFailure` hook 向 Claude 显示警告,请改为退出 2,以便[Claude 看到 stderr](#exit-code-2-behavior-per-event),即使工具已经运行。

865 

866<h4 id="exit-code-2">

867 退出代码 2

868</h4>

869 

870退出 2 表示阻止错误。在[可以阻止的事件](#exit-code-2-behavior-per-event)上,退出 2 无论您是否打印 JSON 都会阻止:即使 JSON `permissionDecision` 为 `"allow"` 也无法覆盖它。Claude Code 仍然读取 stdout 上的任何有效 [JSON 输出](#json-output)。在 `Elicitation` 和 `ElicitationResult` 上,退出 2 hook 的 `hookSpecificOutput` 被忽略。

871 

872阻止消息是您的 JSON 的阻止决策的原因(当它做出一个时),否则是您的 stderr 文本。阻止做什么因事件而异:`PreToolUse` 阻止工具调用,`UserPromptSubmit` 拒绝提示,等等。[每个事件的退出代码 2 行为](#exit-code-2-behavior-per-event)列出每个事件的效果,每个事件的部分说明消息去向。

873 

874退出 2 的 hook 同时打印 JSON 且未通过 [JSON 输出](#json-output)架构验证仍然阻止:Claude Code 使用 stderr 作为阻止原因,并在调试日志中记录验证失败。在 v2.1.214 之前,Claude Code 将该组合视为非阻止错误,操作继续。

875 

876此脚本通过退出 2 阻止 `rm` 命令,并将所有其他命令留给正常权限流:

697 877 

698```bash theme={null}878```bash theme={null}

699#!/bin/bash879#!/bin/bash

700# 从 stdin 读取 JSON 输入,检查命令880# Reads JSON input from stdin, checks the command

701command=$(jq -r '.tool_input.command' < /dev/stdin)881input=$(cat)

882command=$(jq -r '.tool_input.command' <<<"$input")

702 883 

703if [[ "$command" == rm* ]]; then884if [[ "$command" == rm* ]]; then

704 echo "Blocked: rm commands are not allowed" >&2885 echo "Blocked: rm commands are not allowed" >&2

705 exit 2 # 阻止错误:工具调用被阻止886 exit 2 # Blocking error: tool call is prevented

706fi887fi

707 888 

708exit 0 # 无决定:正常权限流程适用889exit 0 # No decision: the normal permission flow applies

709```890```

710 891 

892<h4 id="other-exit-codes">

893 其他退出代码

894</h4>

895 

896任何其他退出代码对于大多数 hook 事件本身不会阻止。发生什么取决于您的 stdout:

897 

898* 使用通过架构验证的解析对象,对于使用标准决策模型的事件,Claude Code 忽略退出代码,JSON 单独决定结果:

899 * 事件支持的每个字段都被接受,包括 `permissionDecision`、`additionalContext`、`updatedInput` 和 `systemMessage`,hook 不被报告为错误。

900 * [决策控制](#decision-control)列出每个事件的决策字段;通用字段如 `systemMessage` 遵循 [JSON 输出](#json-output)表。

901* 使用未通过架构验证的解析对象,对于使用标准决策模型的事件,它与[退出 0 上](#exit-code-0)相同的非阻止错误:操作继续,`<hook name> hook error` 通知带有验证消息。

902* 使用 Claude Code [尝试解析为 JSON](#exit-code-0)且无法解析的 stdout,Claude Code 报告与退出 0 上相同的非阻止错误,用于使用标准决策模型的事件。操作继续,通知带有解析消息。

903* 使用 Claude Code [视为纯文本](#exit-code-0)的 stdout,或使用空 stdout,对于大多数 hook 事件是非阻止错误:操作继续,转录显示 `<hook name> hook error` 通知,后跟 stderr 的第一行,前缀为 `Failed with non-blocking status code:`。要捕获完整 stderr,请启用[调试日志](#debug-hooks)。

904 

905标准决策模型之外的事件在[每个事件表](#exit-code-2-behavior-per-event)中保持自己的行:`WorktreeCreate` 在任何非零退出时失败创建,无论您的 JSON 说什么,事件丢弃 hook 输出(如 `StopFailure`)在每个退出代码上忽略您的 JSON,除了副作用字段如 `terminalSequence`,它仍然触发。

906 

907无法启动的 hook 落入相同的非阻止桶。当脚本路径不存在或不可执行时,shell 以代码(如 127)退出,您看到相同的通知,带有解释器的消息,例如 `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`。对于大多数 hook 事件,操作继续。当您设置策略 hook 时,在其第一次运行时观察此通知:`settings.json` 中的拼写错误的路径使门无声地禁用。

908 

711<Warning>909<Warning>

712 对于大多数 hook 事件,仅退出代码 2 阻止操作。Claude Code 将退出代码 1 视为非阻止错误并继续操作,尽管 1 是传统的 Unix 失败代码。如果您的 hook 旨在强制执行策略,请使用 `exit 2`。例外是 `WorktreeCreate`,其中任何非零退出代码都会中止 worktree 创建。910 对于大多数 hook 事件,退出代码 2 是唯一通过代码单独阻止的退出代码。没有 stdout 上的有效 JSON,Claude Code 将退出代码 1 视为非阻止错误并继续操作,即使 1 是传统的 Unix 失败代码。如果您的 hook 旨在强制执行策略,请使用 `exit 2`。worktree 事件不同:来自 `WorktreeCreate` 的任何非零退出代码中止 worktree 创建,来自 `WorktreeRemove` 的任何非零退出代码使 worktree 移除失败(如果目录仍然存在)。

713</Warning>911</Warning>

714 912 

913<h4 id="timeouts">

914 超时

915</h4>

916 

917除了您使用 [`async: true`](#run-hooks-in-the-background) 运行的命令 hook,Claude Code 取消达到其 [`timeout`](#common-fields) 的 `command`、`http` 或 `mcp_tool` hook,丢弃 hook 的输出,因此在大多数事件上超时的 hook 不呈现决策。

918 

919在 [`PreModelSwitch`](#premodelswitch) 上,在其超时处取消的 hook 阻止模型切换。在 `PreToolUse` 上,两个 hook 系列不同:

920 

921* 超时的 `command`、`http` 或 `mcp_tool` hook 不阻止工具调用。调用通过正常[权限流](/docs/zh-CN/permissions)继续,因此不要指望停滞的 hook 充当门。

922* 超过其超时的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) [阻止工具调用](#pretooluse)。

923 

715<h4 id="exit-code-2-behavior-per-event">924<h4 id="exit-code-2-behavior-per-event">

716 每个事件的退出代码 2 行为925 每个事件的退出代码 2 行为

717</h4>926</h4>

718 927 

719退出代码 2 是 hook 发出"停止,不要这样做"的方式。效果取决于事件,因为某些事件代表可以被阻止的操作(如尚未发生的工具调用),而其他事件代表已经发生或无法防止的事情。928退出代码 2 是 hook 发出"停止,不要这样做"信号的方式。效果取决于事件,因为某些事件代表可以被阻止的操作(如尚未发生的工具调用),而其他事件代表已经发生或无法防止的事情。

720 929 

721| Hook 事件 | 可以阻止? | 退出 2 时发生的情况 |930| Hook 事件 | 可以阻止? | 退出 2 时发生什么 |

722| :-------------------- | :---- | :------------------------------------------------------------------------- |931| :-------------------- | :---- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |

723| `PreToolUse` | 是 | 阻止工具调用 |932| `PreToolUse` | 是 | 阻止工具调用 |

724| `PermissionRequest` | 是 | 拒绝权限 |933| `PermissionRequest` | 否 | 此事件不接受退出代码 2,权限流程保持不变。改为通过 [`decision` 对象](#permissionrequest-decision-control)拒绝 |

725| `UserPromptSubmit` | 是 | 阻止提示处理并从上下文中删除提示 |934| `UserPromptSubmit` | 是 | 阻止提示处理并删除提示 |

726| `UserPromptExpansion` | 是 | 阻止扩展 |935| `UserPromptExpansion` | 是 | 阻止扩展 |

727| `Stop` | 是 | 防止 Claude 停止,继续对话 |936| `Stop` | 是 | 防止 Claude 停止,继续对话 |

728| `SubagentStop` | 是 | 防止 subagent 停止 |937| `SubagentStop` | 是 | 防止 subagent 停止 |

729| `TeammateIdle` | 是 | 防止队友空闲(队友继续工作) |938| `TeammateIdle` | 是 | 防止队友空闲,因此它继续工作 |

730| `TaskCreated` | 是 | 回滚任务创建 |939| `TaskCreated` | 是 | 回滚任务创建 |

731| `TaskCompleted` | 是 | 防止任务被标记为已完成 |940| `TaskCompleted` | 是 | 防止任务被标记为已完成 |

732| `ConfigChange` | 是 | 阻止配置更改生效(除了 `policy_settings`) |941| `ConfigChange` | 是 | 阻止配置更改生效(除 `policy_settings` 外) |

733| `StopFailure` | 否 | 输出和退出代码被忽略 |942| `StopFailure` | 否 | 输出和退出代码被忽略,除 `terminalSequence` 外 |

734| `PostToolUse` | 否 | 向 Claude 显示 stderr(工具已运行) |943| `PostToolUse` | 否 | 向 Claude 显示 stderr;工具已经运行 |

735| `PostToolUseFailure` | 否 | 向 Claude 显示 stderr(工具已失败) |944| `PostToolUseFailure` | 否 | 向 Claude 显示 stderr;工具已经失败 |

736| `PostToolBatch` | 是 | 在下一个模型调用之前停止代理循环 |945| `PostToolBatch` | 是 | 在下一个模型调用之前停止代理循环 |

737| `PermissionDenied` | 否 | 退出代码和 stderr 被忽略(拒绝已发生)。使用 JSON `hookSpecificOutput.retry: true` 告诉模型它可能重试 |946| `PermissionDenied` | 否 | 退出代码和 stderr 被忽略,因为拒绝已经发生。使用 JSON `hookSpecificOutput.retry: true` 告诉模型它可能重试;Claude Code 对[无判决拒绝](#permissiondenied-decision-control)忽略 `retry: true` |

738| `Notification` | 否 | 仅向用户显示 stderr |947| `Notification` | 否 | 退出代码和 stderr 被忽略 |

739| `SubagentStart` | 否 | 仅向用户显示 stderr |948| `SubagentStart` | 否 | 仅向用户显示 stderr |

740| `SessionStart` | 否 | 仅向用户显示 stderr |949| `SessionStart` | 否 | 仅向用户显示 stderr |

741| `Setup` | 否 | 仅向用户显示 stderr |950| `Setup` | 否 | 退出代码和 stderr 被忽略 |

742| `SessionEnd` | 否 | 仅向用户显示 stderr |951| `SessionEnd` | 否 | 仅向用户显示 stderr |

743| `CwdChanged` | 否 | 仅向用户显示 stderr |952| `CwdChanged` | 否 | 仅向用户显示 stderr |

953| `DirectoryAdded` | 否 | Stderr 进入调试日志;目录已经添加 |

744| `FileChanged` | 否 | 仅向用户显示 stderr |954| `FileChanged` | 否 | 仅向用户显示 stderr |

745| `PreCompact` | 是 | 阻止压缩 |955| `PreCompact` | 是 | 阻止压缩 |

746| `PostCompact` | 否 | 仅向用户显示 stderr |956| `PostCompact` | 否 | 仅向用户显示 stderr |

747| `Elicitation` | 是 | 拒绝 elicitation |957| `PreModelSwitch` | 是 | 阻止模型切换并向用户显示 stderr |

748| `ElicitationResult` | 是 | 阻止响应(操作变为 decline) |958| `PostModelSwitch` | 否 | 仅向用户显示 stderr;模型已经切换 |

749| `WorktreeCreate` | 是 | 任何非零退出代码都会导致 worktree 创建失败 |959| `Elicitation` | 是 | 拒绝引出 |

750| `WorktreeRemove` | 否 | 失败仅在调试模式下记录 |960| `ElicitationResult` | 是 | 阻止响应(操作变为拒绝) |

961| `WorktreeCreate` | 是 | 任何非零退出代码导致 worktree 创建失败 |

962| `WorktreeRemove` | 是 | 任何非零退出代码导致 worktree 移除失败(如果目录仍然存在)。请参阅 [WorktreeRemove](#worktreeremove) 了解目录发生什么 |

751| `InstructionsLoaded` | 否 | 退出代码被忽略 |963| `InstructionsLoaded` | 否 | 退出代码被忽略 |

752| `MessageDisplay` | 否 | 显示原始文本 |964| `MessageDisplay` | 否 | 显示原始文本 |

753 965 

754对于 `SessionStart`、`Setup` 和 `SubagentStart`,退出代码 2 stderr 在成绩单中呈现为 `<hook name> hook error` 通知,与[非阻止错误](#exit-code-output)的方式相同。Claude 看不到它,会话或 subagent 继续进行。对于 `SubagentStart`,通知出现在 subagent 自己的成绩单中,而不是在父对话中。966对于 `SessionStart`、`SubagentStart` 和 `PostModelSwitch`,Claude Code 在转录中呈现退出代码 2 stderr 作为 `<hook name> hook error` 通知,与呈现[非阻止错误](#exit-code-output)的方式相同。Claude 看不到它,会话或 subagent 继续。对于 `SubagentStart`,通知出现在 subagent 自己的转录中,而不是在父对话中。

755 

756从 Claude Code v2.1.199 开始,`SessionStart`、`Setup` 和 `SubagentStart` 在成绩单中显示退出代码 2 stderr。早期版本仅将其写入调试日志。

757 967 

758<h3 id="http-response-handling">968<h3 id="http-response-handling">

759 HTTP 响应处理969 HTTP 响应处理

760</h3>970</h3>

761 971 

762HTTP hooks 使用 HTTP 状态代码和响应体而不是退出代码和 stdout:972HTTP hook 使用 HTTP 状态代码和响应体而不是退出代码和 stdout。下面的结果适用于大多数事件;在[每个事件表](#exit-code-2-behavior-per-event)中有自己的失败合约的事件(如 `WorktreeCreate`)将该合约应用于失败的 HTTP hook:

763 973 

764* **2xx 带空体**:成功,等同于退出代码 0 且无输出974* **2xx 且空体**:成功,等同于退出代码 0 且无输出

765* **2xx 带纯文本体**:成功,文本作为上下文添加975* **2xx 且 JSON 对象体**:使用与命令 hook 相同的 [JSON 输出](#json-output)架构解析。未通过架构验证的体是非阻止错误

766* **2xx 带 JSON 体**:成功,使用与命令 hooks 相同的[JSON 输出](#json-output)架构解析976* **2xx 且任何其他体,如纯文本**:非阻止错误,处理方式与非 2xx 状态相同。Claude Code 不将文本添加到 Claude 的上下文

767* **非 2xx 状态**:非阻止错误,执行继续977* **非 2xx 状态**:非阻止错误,执行继续

768* **连接失败或超时**:非阻止错误,执行继续978* **连接失败**:非阻止错误,执行继续

979* **超时**:hook 被取消,如 [Timeouts](#timeouts) 下所述

769 980 

770与命令 hooks 不同,HTTP hooks 无法仅通过状态代码发出阻止错误信号。要阻止工具调用或拒绝权限,返回 2xx 响应,其 JSON 体包含适当的决定字段。981与命令 hook 不同,HTTP hook 无法仅通过状态代码发出阻止错误信号。要阻止工具调用或拒绝权限,返回 2xx 响应,其 JSON 体包含适当的决策字段。

771 982 

772<h3 id="json-output">983<h3 id="json-output">

773 JSON 输出984 JSON 输出

774</h3>985</h3>

775 986 

776退出代码让您允许或阻止,但 JSON 输出提供更细粒度的控制。与其使用代码 2 退出来阻止,不如退出 0 并将 JSON 对象打印到 stdout。Claude Code 从该 JSON 读取特定字段以控制行为,包括[决定控制](#decision-control)以阻止、允许或升级给用户。987退出代码只让您阻止或保持沉默,但 JSON 输出给您更细粒度的控制。与其退出代码 2 来阻止,不如退出 0 并将 JSON 对象打印到 stdout。Claude Code 从该 JSON 读取特定字段来控制行为,包括[决策控制](#decision-control)来阻止、允许或升级给用户。

777 988 

778<Note>989<Note>

779 您必须为每个 hook 选择一种方法,而不是两种:要么单独使用退出代码进行信号传递,要么退出 0 并打印 JSON 以进行结构化控制。Claude Code 仅在退出 0 时处理 JSON。如果您退出 2,任何 JSON 都会被忽略。990 每个 hook 选择一种方法:要么单独使用退出代码进行信号,要么退出 0 并打印 JSON 进行结构化控制。如果您混合它们,退出 2 保持其[阻止效果](#exit-code-2-behavior-per-event),Claude Code 仍然读取 JSON 字段,除了 [Exit code 2](#exit-code-2) 下注明的一个引出例外。

780</Note>991</Note>

781 992 

782您的 hook 的 stdout 必须仅包含 JSON 对象。如果您的 shell 配置文件在启动时打印文本,它可能会干扰 JSON 解析。请参阅故障排除指南中的[JSON 验证失败](/docs/zh-CN/hooks-guide#json-validation-failed)。993您的 hook 的 stdout 必须仅包含 JSON 对象。如果您的 shell 配置文件在启动时打印文本,它可能会干扰 JSON 解析。请参阅故障排除指南中的 [Hook JSON 无效](/docs/zh-CN/hooks-guide#hook-json-has-no-effect)。

783 994 

784Hook 输出字符串,包括 `additionalContext`、`systemMessage` 和纯 stdout,上限为 10,000 个字符。超过此限制的输出被保存到文件并替换为预览和文件路径,与大型工具结果的处理方式相同。995hook 的 `additionalContext`、`systemMessage` 和 `initialUserMessage` 字符串,以及其纯 stdout,限制为 10,000 个字符:

996 

997* **范围**:Claude Code 单独测量每个字符串,即使多个 hook 为同一事件运行。对于 JSON 输出,每个字段单独测量;纯 stdout 整体测量。

998* **超过限制**:Claude Code 将输出保存到会话目录中的文件,并用文件路径和最多前 2,000 个字符的预览替换它。大型有效 Bash 结果的处理方式相同,在 [Output limits](/docs/zh-CN/tools-reference#output-limits) 下描述。与该 Bash 上限不同,此上限没有设置或环境变量来提高它。

999* **读取文件**:Claude Code 不要求 Claude 读取文件,因此将 Claude 必须始终看到的任何内容保持在上限内。

785 1000 

786JSON 对象支持三种字段:1001JSON 对象支持三种字段:

787 1002 

788* **通用字段**,如 `continue`,在所有事件中工作。这些列在下表中。1003* **通用字段**如 `continue` 在下表中列出。每个事件都接受它们,但某些事件丢弃它们或将 `systemMessage` 传递到转录以外的地方。每个事件的部分说明这一点。`terminalSequence` 也在这些事件上工作,除了 [Emit terminal notifications](#emit-terminal-notifications) 下列出的例外。

789* **顶级 `decision` 和 `reason`** 由某些事件用于阻止或提供反馈。1004* **顶级 `decision` 和 `reason`** 由某些事件用来阻止或提供反馈。

790* **`hookSpecificOutput`** 是一个嵌套对象,用于需要更丰富控制的事件。它需要一个设置为事件名称的 `hookEventName` 字段。1005* **`hookSpecificOutput`** 是需要更丰富控制的事件的嵌套对象。它需要一个 `hookEventName` 字段设置为事件名称。

791 1006 

792| 字段 | 默认 | 描述 |1007| 字段 | 默认 | 描述 |

793| :----------------- | :------ | :----------------------------------------------------------------------------------------------------------------------------------------- |1008| :----------------- | :------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

794| `continue` | `true` | 如果为 `false`,Claude 在 hook 运行后完全停止处理。优先于任何事件特定的决定字段 |1009| `continue` | `true` | 如果 `false`,Claude 在 hook 运行后完全停止处理。优先于任何事件特定的决策字段 |

795| `stopReason` | 无 | 当 `continue` 为 `false` 时向用户显示的消息。不向 Claude 显示 |1010| `stopReason` | 无 | 当 `continue` 为 `false` 时向用户显示的消息。它保留在对话中,因此如果对话继续,Claude 会看到它 |

796| `suppressOutput` | `false` | 如果为 `true`,从成绩单中隐藏 hook 的 stdout。Stdout 仍然出现在调试日志中 |1011| `suppressOutput` | `false` | 无效果:Claude Code 接受字段但不作用。成功的 hook 的 stdout 从不在转录中显示,并在调试日志中记录 |

797| `systemMessage` | 无 | 向用户显示的警告消息 |1012| `systemMessage` | 无 | 向用户显示的警告消息。在 [Agent SDK](/docs/zh-CN/agent-sdk/overview) 和 [`--output-format stream-json`](/docs/zh-CN/headless) 输出中,它可以作为 [`SDKInformationalMessage`](/docs/zh-CN/agent-sdk/typescript#sdkinformationalmessage) 到达 |

798| `terminalSequence` | 无 | Claude Code 代表您发出的终端转义序列,例如桌面通知、窗口标题或响铃。限制为 OSC `0`/`1`/`2`/`9`/`99`/`777` 和 BEL。如果值包含允许列表之外的任何内容,该字段将被忽略。使用此而不是写入 `/dev/tty`,这对 hooks 不可用 |1013| `terminalSequence` | 无 | Claude Code 代表您发出的终端转义序列,如桌面通知、窗口标题或响铃。限制为 OSC `0`/`1`/`2`/`9`/`99`/`777` 和 BEL。如果值包含允许列表外的任何内容,字段被忽略。使用此而不是写入 `/dev/tty`,这对 hook 不可用 |

799 1014 

800要无论事件类型如何都完全停止 Claude:1015要完全停止 Claude:

801 1016 

802```json theme={null}1017```json theme={null}

803{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }1018{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }

804```1019```

805 1020 

1021对于 `PreToolUse` 和 `PostToolUse` hook,停止适用,即使工具调用失败或在 Claude 仍在流式传输响应时完成。

1022 

806<h4 id="emit-terminal-notifications">1023<h4 id="emit-terminal-notifications">

807 发出终端通知1024 发出终端通知

808</h4>1025</h4>

809 1026 

810`terminalSequence` 字段需要 Claude Code v2.1.141 或更高版本。1027Hook 运行时没有控制终端,因此直接写入转义序列到 `/dev/tty` 失败。改为在 `terminalSequence` 字段中返回转义序列,Claude Code 通过其自己的终端写入路径代表您发出它。这是无竞争的,在 tmux 和 GNU screen 内工作,并在 Windows 上工作,其中没有 `/dev/tty`。

811 

812Hooks 运行时没有控制终端,因此直接向 `/dev/tty` 写入转义序列会失败。相反,在 `terminalSequence` 字段中返回转义序列,Claude Code 通过其自己的终端写入路径为您发出它。这是无竞争的,在 tmux 和 GNU screen 内工作,并在 Windows 上工作,其中没有 `/dev/tty`。

813 1028 

814该字段接受一个或多个允许列表转义序列的字符串:1029该字段接受一个或多个允许列表转义序列的字符串:

815 1030 


819* OSC `777`:urxvt、Ghostty 和 Warp 通知1034* OSC `777`:urxvt、Ghostty 和 Warp 通知

820* 裸 BEL1035* 裸 BEL

821 1036 

822序列可以用 BEL 或 ST 终止。允许列表之外的任何内容,包括 CSI 光标和颜色序列、OSC 调色板序列、OSC 8 超链接、OSC 52 剪贴板写入和 OSC 1337,都会被拒绝,该字段将被忽略。1037序列可以用 BEL 或 ST 终止。允许列表外的任何内容,包括 CSI 光标和颜色序列、OSC 调色板序列、OSC 8 超链接、OSC 52 剪贴板写入和 OSC 1337,被拒绝,字段被忽略。

1038 

1039Claude Code 在处理您的 hook 输出时写入序列本身,因此字段在丢弃 `systemMessage` 和 `continue` 的事件上工作,如 `Notification` 和 `StopFailure`。它有两个限制:

1040 

1041* Claude Code 仅在交互式会话中写入序列,仅当其界面在屏幕上时。在使用 `-p` 标志的非交互式模式和 Agent SDK 中,它忽略字段。

1042* `WorktreeCreate` 命令 hook 无法返回 JSON,因为 Claude Code 将其 stdout 读取为 worktree 路径。HTTP `WorktreeCreate` hook 返回 JSON 并可以包括字段。

823 1043 

824下面的示例从 `Notification` hook 触发桌面通知。转义序列使用 `printf` 八进制转义构建,因此控制字节永远不会出现在 shell 命令行上,`jq -n --arg` 构建 JSON 输出,因此通知消息中的引号、反斜杠和换行符被正确转义:1044下面的示例从 `Notification` hook 触发桌面通知。转义序列用 `printf` 八进制转义构建,因此控制字节从不出现在 shell 命令行上,`jq -n --arg` 构建 JSON 输出,因此通知消息中的引号、反斜杠和换行符被正确转义:

825 1045 

826```bash theme={null}1046```bash theme={null}

827#!/bin/bash1047#!/bin/bash

828# Notification hook:当 Claude Code 需要注意时 ping 桌面。1048# Notification hook: ping the desktop when Claude Code needs attention.

829input=$(cat)1049input=$(cat)

830title="Claude Code'1050title="Claude Code"

831body=$(jq -r '.message // 'Needs your attention"' <<<"$input")1051body=$(jq -r '.message // "Needs your attention"' <<<"$input")

832seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")1052seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")

833jq -nc --arg seq "$seq" '{terminalSequence: $seq}'1053jq -nc --arg seq "$seq" '{terminalSequence: $seq}'

834```1054```

835 1055 

836`{ "terminalSequence": "..." }` 形状从任何 shell 或语言都相同。在 Windows 上,在 PowerShell 或脚本中构建转义字符串并发出相同的 JSON 对象。1056`{ "terminalSequence": "..." }` 形状从任何 shell 或语言都相同。

837 

838<Note>

839 `terminalSequence` 是之前直接向 `/dev/tty` 写入转义序列的 hooks 的受支持替代品。允许列表限制为无法移动光标或改变颜色的序列,因此 hook 永远无法破坏屏幕上的提示。

840</Note>

841 1057 

842<h4 id="add-context-for-claude">1058<h4 id="add-context-for-claude">

843 为 Claude 添加上下文1059 为 Claude 添加上下文

844</h4>1060</h4>

845 1061 

846`additionalContext` 字段将来自您的 hook 的字符串传递到 Claude 的上下文窗口中。Claude Code 将字符串包装在系统提醒中,并将其插入到 hook 触发的对话点。Claude 在下一个模型请求时读取提醒,但它不会在界面中显示为聊天消息。1062`additionalContext` 字段将字符串从您的 hook 传递到 Claude 的上下文窗口。Claude Code 将字符串包装在系统提醒中,并在 hook 触发的点将其插入对话。Claude 在下一个模型请求时读取提醒,但它不作为聊天消息出现在界面中。

847 1063 

848在 `hookSpecificOutput` 中返回 `additionalContext` 以及事件名称:1064在 `hookSpecificOutput` 中返回 `additionalContext` 以及事件名称:

849 1065 


858 1074 

859提醒出现的位置取决于事件:1075提醒出现的位置取决于事件:

860 1076 

861* [SessionStart](#sessionstart)、[Setup](#setup) 和 [SubagentStart](#subagentstart):在对话开始,在第一个提示之前1077* [SessionStart](#sessionstart) 和 [SubagentStart](#subagentstart):在对话开始,在第一个提示之前

862* [UserPromptSubmit](#userpromptsubmit) 和 [UserPromptExpansion](#userpromptexpansion):与提交的提示一起1078* [UserPromptSubmit](#userpromptsubmit) 和 [UserPromptExpansion](#userpromptexpansion):与提交的提示一起

863* [PreToolUse](#pretooluse)、[PostToolUse](#posttooluse)、[PostToolUseFailure](#posttoolusefailure) 和 [PostToolBatch](#posttoolbatch):在工具结果旁边1079* [PreToolUse](#pretooluse)、[PostToolUse](#posttooluse)、[PostToolUseFailure](#posttoolusefailure) 和 [PostToolBatch](#posttoolbatch):在工具结果旁边

864* [Stop](#stop) 和 [SubagentStop](#subagentstop):在轮次末尾。对话继续,以便 Claude 可以对反馈采取行动。请参阅[Stop 决定控制](#stop-decision-control)1080* [Stop](#stop) 和 [SubagentStop](#subagentstop):在轮次末尾。对话继续,因此 Claude 可以对反馈采取行动。请参阅 [Stop decision control](#stop-decision-control)

1081* [PostModelSwitch](#postmodelswitch):与切换后的下一个请求一起。请参阅 [PostModelSwitch decision control](#postmodelswitch-decision-control) 了解时间

1082 

1083当多个 hook 为同一事件返回 `additionalContext` 时,Claude 接收所有值。

865 1084 

866当多个 hooks 为同一事件返回 `additionalContext` 时,Claude 接收所有值。如果值超过 10,000 个字符,Claude Code 将完整文本写入会话目录中的文件,并将 Claude 传递文件路径以及简短预览。1085如果值超过 10,000 个字符,Claude Code 将文本写入会话目录中的文件,并改为传递 Claude 文件路径,带有最多前 2,000 个字符的预览。Claude 可以读取文件,但 Claude Code 不要求它。

867 1086 

868使用 `additionalContext` 来获取 Claude 应该了解的有关您的环境当前状态或刚刚运行的操作的信息:1087使用 `additionalContext` 获取 Claude 应该知道的关于您的环境当前状态或刚刚运行的操作的信息:

869 1088 

870* **环境状态**:当前分支、部署目标或活跃的功能标志1089* **环境状态**:当前分支、部署目标或活跃功能标志

871* **条件项目规则**:哪个测试命令适用于刚刚编辑的文件,哪些目录在此 worktree 中是只读的1090* **条件项目规则**:哪个测试命令适用于刚编辑的文件,哪些目录在此 worktree 中是只读的

872* **外部数据**:分配给您的开放问题、最近的 CI 结果、从内部服务获取的内容1091* **外部数据**:分配给您的开放问题、最近的 CI 结果、从内部服务获取的内容

873 1092 

874对于永不改变的说明,更倾向于[CLAUDE.md](/docs/zh-CN/memory)。它加载时无需运行脚本,是静态项目约定的标准位置。1093对于从不改变的说明,更喜欢 [CLAUDE.md](/docs/zh-CN/memory)。它加载而不运行脚本,是静态项目约定的标准位置。

875 1094 

876将文本写成事实陈述而不是命令式系统指令。措辞如"部署目标是生产"或"此 repo 使用 `bun test`"读作项目信息。框架为带外系统命令的文本可能会触发 Claude 的提示注入防御,这会导致 Claude 将文本呈现给您,而不是将其视为上下文。1095将文本写成事实陈述而不是命令式系统说明。措辞如"部署目标是生产"或"此 repo 使用 `bun test`"读作项目信息。框架为带外系统命令的文本可以触发 Claude 的提示注入防御,这导致 Claude 向您显示文本而不是将其视为上下文。

877 1096 

878一旦注入,文本就会保存在会话成绩单中。对于 `PostToolUse` 或 `UserPromptSubmit` 等中期事件,使用 `--continue` 或 `--resume` 恢复会重放保存的文本,而不是为过去的轮次重新运行 hook,因此时间戳或提交 SHA 等值在恢复时变得陈旧。`SessionStart` hooks 在使用 `source` 设置为 `"resume"` 的 `--resume` 恢复时再次运行,因此它们可以刷新其上下文。1097Claude Code 在会话转录中保存注入的文本。对于 `PostToolUse` 或 `UserPromptSubmit` 等中期会话事件,当您使用 `--continue` 或 `--resume` 恢复时,Claude Code 重放保存的文本而不是为过去的轮次重新运行 hook,因此时间戳或提交 SHA 等值变得陈旧。`SessionStart` hook 在使用 `source` 设置为 `"resume"` 或 `"fork"`(如果您添加了 `--fork-session`)恢复时再次运行,因此它们可以刷新其上下文。

879 1098 

880<h4 id="decision-control">1099<h4 id="decision-control">

881 决定控制1100 决策控制

882</h4>1101</h4>

883 1102 

884并非每个事件都支持通过 JSON 阻止或控制行为。支持的事件各自使用不同的字段集来表达该决定。在编写 hook 之前,使用此表作为快速参考:1103并非每个事件都支持通过 JSON 阻止或控制行为。支持的事件各自使用不同的字段集来表达该决策。在编写 hook 之前,使用此表作为快速参考:

885 1104 

886| 事件 | 决定模式 | 关键字段 |1105| 事件 | 决策模式 | 关键字段 |

887| :-------------------------------------------------------------------------------------------------------------------------- | :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1106| :-------------------------------------------------------------------------------------------------------------------------- | :---------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

888| UserPromptSubmit、UserPromptExpansion、PostToolUse、PostToolUseFailure、PostToolBatch、Stop、SubagentStop、ConfigChange、PreCompact | 顶级 `decision` | `decision: "block"`、`reason`。Stop 和 SubagentStop 也接受 `hookSpecificOutput.additionalContext` 用于[继续对话的非错误反馈](#stop-decision-control) |1107| UserPromptSubmit、UserPromptExpansion、PostToolUse、PostToolUseFailure、PostToolBatch、Stop、SubagentStop、ConfigChange、PreCompact | 顶级 `decision` | `decision: "block"`、`reason`。Stop 和 SubagentStop 也接受 `hookSpecificOutput.additionalContext` 用于[继续对话的非错误反馈](#stop-decision-control) |

889| TeammateIdle、TaskCreated、TaskCompleted | 退出代码或 `continue: false` | 退出代码 2 使用 stderr 反馈阻止操作。JSON `{"continue": false, "stopReason": "..."}` 也会完全停止队友,匹配 `Stop` hook 行为 |1108| TeammateIdle、TaskCompleted | 退出代码或 `continue: false` | 退出代码 2 用 stderr 反馈阻止操作。JSON `{"continue": false, "stopReason": "..."}` 也完全停止队友,匹配 `Stop` hook 行为;[TaskCompleted 在 `TaskUpdate` 工具触发事件时忽略它](#taskcompleted-decision-control) |

1109| TaskCreated | 退出代码或顶级 `decision` | 退出代码 2 或 `decision: "block"` [取消任务](#taskcreated-decision-control)并将消息返回给 Claude。`continue: false` 被忽略 |

890| PreToolUse | `hookSpecificOutput` | `permissionDecision`(allow/deny/ask/defer)、`permissionDecisionReason` |1110| PreToolUse | `hookSpecificOutput` | `permissionDecision`(allow/deny/ask/defer)、`permissionDecisionReason` |

1111| PreModelSwitch | `hookSpecificOutput` 或顶级 `decision` | `permissionDecision`(allow/deny/ask)、`permissionDecisionReason`。`decision: "block"` 也[取消切换](#premodelswitch-decision-control) |

891| PermissionRequest | `hookSpecificOutput` | `decision.behavior`(allow/deny) |1112| PermissionRequest | `hookSpecificOutput` | `decision.behavior`(allow/deny) |

892| PermissionDenied | `hookSpecificOutput` | `retry: true` 告诉模型它可能重试被拒绝的工具调用 |1113| PermissionDenied | `hookSpecificOutput` | `retry: true` 告诉模型它可能重试被拒绝的工具调用;Claude Code 对[无判决拒绝](#permissiondenied-decision-control)忽略它 |

893| WorktreeCreate | 路径返回 | 命令 hook 在 stdout 上打印路径;HTTP hook 通过 `hookSpecificOutput.worktreePath` 返回。Hook 失败或缺少路径会导致创建失败 |1114| WorktreeCreate | 路径返回 | 命令 hook 在 stdout 上打印路径;HTTP hook 返回 `hookSpecificOutput.worktreePath`。Hook 失败或缺少路径失败创建 |

894| Elicitation | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(form 字段值用于 accept) |1115| WorktreeRemove | 退出代码 | 任何非零退出代码使移除失败(如果目录仍然存在)。JSON 输出被丢弃 |

895| ElicitationResult | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(form 字段值覆盖) |1116| Elicitation | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(接受的表单字段值) |

896| MessageDisplay | `hookSpecificOutput` | `displayContent` 替换屏幕上显示的文本。仅显示:成绩单和 Claude 看到的内容保持原始 |1117| ElicitationResult | `hookSpecificOutput` | `action`(accept/decline/cancel)、`content`(表单字段值覆盖) |

897| SessionStart、Setup、SubagentStart | 仅上下文 | `hookSpecificOutput.additionalContext` 为 Claude 添加上下文。SessionStart 也接受[`initialUserMessage`、`watchPaths`、`sessionTitle` 和 `reloadSkills`](#sessionstart-decision-control)。无阻止或决定控制 |1118| MessageDisplay | `hookSpecificOutput` | `displayContent` 替换屏幕上显示的文本。仅显示:转录和 Claude 看到的保持原始 |

898| WorktreeRemove、Notification、SessionEnd、PostCompact、InstructionsLoaded、StopFailure、CwdChanged、FileChanged | 无 | 无决定控制。用于日志记录或清理等副作用 |1119| SessionStart、SubagentStart、PostModelSwitch | 仅上下文 | `hookSpecificOutput.additionalContext` 为 Claude 添加上下文。SessionStart 也接受 [`initialUserMessage`、`watchPaths`、`sessionTitle` 和 `reloadSkills`](#sessionstart-decision-control)。无阻止或决策控制 |

899 1120| Setup、Notification、SessionEnd、PostCompact、InstructionsLoaded、StopFailure、CwdChanged、DirectoryAdded、FileChanged | 无 | 无决策控制。用于日志或清理等副作用 |

900一些事件也可以重写内容而不仅仅允许或阻止它:1121 

901 1122少数事件也可以重写内容而不仅仅允许或阻止它:

902* `PreToolUse`:`updatedInput` 直接在 `hookSpecificOutput` 下替换工具的参数,然后它运行。请参阅[PreToolUse 决定控制](#pretooluse-decision-control)1123 

903* `PermissionRequest`:`updatedInput` 在 `decision` 对象内。请参阅[PermissionRequest 决定控制](#permissionrequest-decision-control)1124* `PreToolUse`:`updatedInput` 直接在 `hookSpecificOutput` 下替换工具的参数,然后它运行。请参阅 [PreToolUse decision control](#pretooluse-decision-control)

904* `PostToolUse`:`updatedToolOutput` 替换工具的结果。请参阅[PostToolUse 决定控制](#posttooluse-decision-control)1125* `PermissionRequest`:`updatedInput` 在 `decision` 对象内。请参阅 [PermissionRequest decision control](#permissionrequest-decision-control)

905* `UserPromptSubmit`:无法替换提示;仅在其旁边注入 `additionalContext`1126* `PostToolUse`:`updatedToolOutput` 替换工具的结果。请参阅 [PostToolUse decision control](#posttooluse-decision-control)

1127* `UserPromptSubmit`:无法替换提示;它仅在其旁边注入 `additionalContext`

906 1128 

907对于编辑或转换用例,在 `PreToolUse` 处拦截出站工具输入,在 `PostToolUse` 处拦截入站工具结果。1129对于编辑或转换用例,在 `PreToolUse` 处拦截出站工具输入,在 `PostToolUse` 处拦截入站工具结果。

908 1130 

909以下是每种模式的实际示例:1131以下是每种模式的实际示例:

910 1132 

911<Tabs>1133<Tabs>

912 <Tab title="顶级决定">1134 <Tab title="顶级 decision">

913 由 `UserPromptSubmit`、`UserPromptExpansion`、`PostToolUse`、`PostToolUseFailure`、`PostToolBatch`、`Stop`、`SubagentStop`、`ConfigChange` 和 `PreCompact` 使用。唯一的值是 `"block"`。要允许操作继续,从您的 JSON 中省略 `decision`,或退出 0 而不带任何 JSON:1135 `decision` 的唯一值是 `"block"`。要允许操作继续,从您的 JSON 中省略 `decision`,或退出 0 而不带任何 JSON:

914 1136 

915 ```json theme={null}1137 ```json theme={null}

916 {1138 {


921 </Tab>1143 </Tab>

922 1144 

923 <Tab title="PreToolUse">1145 <Tab title="PreToolUse">

924 使用 `hookSpecificOutput` 以获得更丰富的控制:允许、拒绝或升级给用户。您还可以在运行前修改工具输入或为 Claude 注入额外上下文。有关完整的选项集,请参阅[PreToolUse 决定控制](#pretooluse-decision-control)。1146 使用 `hookSpecificOutput` 进行更丰富的控制:允许、拒绝或升级给用户。您也可以在运行前修改工具输入或为 Claude 注入额外上下文。请参阅 [PreToolUse decision control](#pretooluse-decision-control) 了解完整的选项集。

925 1147 

926 ```json theme={null}1148 ```json theme={null}

927 {1149 {


935 </Tab>1157 </Tab>

936 1158 

937 <Tab title="PermissionRequest">1159 <Tab title="PermissionRequest">

938 使用 `hookSpecificOutput` 代表用户允许或拒绝权限请求。允许时,您还可以修改工具的输入或应用权限规则,以便用户不会再次被提示。有关完整的选项集,请参阅[PermissionRequest 决定控制](#permissionrequest-decision-control)。1160 使用 `hookSpecificOutput` 代表用户允许或拒绝权限请求。允许时,您也可以修改工具的输入或应用权限规则,以便用户不会再次被提示。请参阅 [PermissionRequest decision control](#permissionrequest-decision-control) 了解完整的选项集。

939 1161 

940 ```json theme={null}1162 ```json theme={null}

941 {1163 {


953 </Tab>1175 </Tab>

954</Tabs>1176</Tabs>

955 1177 

956有关扩展示例,包括 Bash 命令验证、提示过滤和自动批准脚本,请参阅指南中的[您可以自动化的内容](/docs/zh-CN/hooks-guide#what-you-can-automate)以及[Bash 命令验证器参考实现](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py)。1178有关扩展示例,包括 Bash 命令验证、提示过滤和自动批准脚本,请参阅指南中的 [What you can automate](/docs/zh-CN/hooks-guide#what-you-can-automate) 和 [Bash command validator reference implementation](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py)。

957 1179 

958<h2 id="hook-events">1180<h2 id="hook-events">

959 Hook 事件1181 Hook 事件

960</h2>1182</h2>

961 1183 

962每个事件对应于 Claude Code 生命周期中 hooks 可以运行的一个点。下面的部分按照生命周期排序:从会话设置通过代理循环到会话结束。每个部分描述事件何时触发、它支持的匹配器、它接收的 JSON 输入以及如何通过输出控制行为。1184每个事件对应于 Claude Code 生命周期中的一个点,hooks 可以在该点运行。下面的部分按照生命周期顺序排列:从会话设置到 agentic 循环再到会话结束。每个部分描述事件何时触发、它支持的匹配器、它接收的 JSON 输入,以及如何通过输出控制行为。

963 1185 

964<h3 id="sessionstart">1186<h3 id="sessionstart">

965 SessionStart1187 SessionStart

966</h3>1188</h3>

967 1189 

968在 Claude Code 启动新会话或恢复现有会话时运行。用于加载开发上下文,如现有问题或代码库的最近更改,或设置环境变量。对于不需要脚本的静态上下文,请改用[CLAUDE.md](/docs/zh-CN/memory)。1190在 Claude Code 启动新会话或恢复现有会话时运行。对于加载开发上下文(如现有问题或代码库的最近更改)或设置环境变量很有用。对于不需要脚本的静态上下文,请改用 [CLAUDE.md](/docs/zh-CN/memory)。

969 1191 

970SessionStart 在每个会话上运行,因此保持这些 hooks 快速。仅支持 `type: "command"` 和 `type: "mcp_tool"` hooks。1192SessionStart 在每个会话上运行,因此请保持这些 hooks 快速。仅支持 `type: "command"` 和 `type: "mcp_tool"` hooks。有关 `mcp_tool` hooks 何时运行,请参阅 [MCP tool hook 字段](#mcp-tool-hook-fields)。

971 1193 

972匹配器值对应于会话的启动方式:1194匹配器值对应于会话的启动方式:

973 1195 

974| 匹配器 | 何时触发 |1196| 匹配器 | 何时触发 |

975| :-------- | :---------------------------------- |1197| :-------- | :------------------------------------------------------------------------------- |

976| `startup` | 新会话 |1198| `startup` | 新会话 |

977| `resume` | `--resume`、`--continue` 或 `/resume` |1199| `resume` | `--resume`、`--continue` 或 `/resume` |

978| `clear` | `/clear` |1200| `clear` | `/clear` |

979| `compact` | 自动或手动压缩 |1201| `compact` | 自动或手动压缩 |

1202| `fork` | 从现有会话分叉的新会话:`--fork-session` 与 `--resume` 或 `--continue`、`/fork` 后台副本或 `/branch` |

1203 

1204在 v2.1.214 之前,分叉的会话报告源为 `"resume"`。

1205 

1206当您启动交互式会话、使用 `--continue` 或 `--resume` 在启动时恢复对话、或运行 `/clear` 时,SessionStart hooks 在后台运行。您可以立即输入,恢复的对话出现时无需等待 hooks。Claude 的第一个响应仍然等待 hooks 完成,因此它们的上下文到达 Claude。

1207 

1208当您在会话内使用 `/resume` 切换对话时,切换等待 hooks 完成。如果您在后台 hooks 仍在运行时运行 `/clear` 或切换到另一个对话,它们返回的任何内容都不适用于会话。

1209 

1210在启动时也适用相同的等待,包括恢复的会话:您在 SessionStart hooks 仍在运行时发送的提示不会到达 Claude,直到它们完成。

1211 

1212在任一等待期间,按 `Esc` 将提示返回到输入中而不发送它。hooks 继续运行。

980 1213 

981<h4 id="sessionstart-input">1214<h4 id="sessionstart-input">

982 SessionStart 输入1215 SessionStart 输入

983</h4>1216</h4>

984 1217 

985除了[通用输入字段](#common-input-fields)外,SessionStart hooks 还接收 `source` 和可选的 `model`、`agent_type` 和 `session_title`:1218除了 [常见输入字段](#common-input-fields) 外,SessionStart hooks 还接收 `source` 和可选的 `model`、`agent_type` 和 `session_title`:

986 1219 

987| 字段 | 描述 |1220| 字段 | 描述 |

988| :-------------- | :---------------------------------------------------------------------------------------------------- |1221| :-------------- | :------------------------------------------------------------------------------------------------------ |

989| `source` | 会话如何启动:新会话为 `"startup"`,恢复会话为 `"resume"`,`/clear` 后为 `"clear"`,压缩后为 `"compact"` |1222| `source` | 会话如何启动:新会话为 `"startup"`、恢复的会话为 `"resume"`、`/clear` 后为 `"clear"`、压缩后为 `"compact"`、或从现有会话分叉的新会话为 `"fork"` |

990| `model` | 活跃模型标识符。它可以被省略,例如在 `/clear` 后或当会话通过对话恢复恢复时,因此在读取字段前检查它 |1223| `model` | 活跃的模型标识符。例如在 `/clear` 后或通过对话恢复恢复会话时可能被省略,因此在读取前检查该字段 |

991| `agent_type` | 代理名称,当您使用 `claude --agent <name>` 启动 Claude Code 时存在 |1224| `agent_type` | agent 名称,当您使用 `claude --agent <name>` 启动 Claude Code 时出现 |

992| `session_title` | 当前会话标题(如果已设置),例如通过 `--name` 或 `/rename`。发出 `sessionTitle` 的 hook 可以先检查 `session_title` 以避免覆盖用户显式设置的标题 |1225| `session_title` | 当前会话标题(如果已设置),例如通过 `--name` 或 `/rename`。发出 `sessionTitle` 的 hook 可以先检查 `session_title` 以避免覆盖用户明确设置的标题 |

1226 

1227当 `source` 为 `"resume"` 或 `"fork"` 且成绩单包含至少一个来自 Claude 的响应时,SessionStart hooks 也会接收下面的四个字段。您的 hook 可以使用它们来报告在第一个请求之前恢复陈旧对话的成本,例如在 [`systemMessage`](#json-output) 中。这些字段需要 Claude Code v2.1.251 或更高版本。

1228 

1229| 字段 | 描述 |

1230| :---------------------------- | :--------------------------------------------------------------------------------------------- |

1231| `seconds_since_last_response` | 自恢复成绩单中最后一个响应以来的挂钟秒数 |

1232| `context_tokens` | 恢复会话的第一个请求作为其提示重新发送的令牌 |

1233| `prompt_cache_likely_expired` | 当最后一个响应早于会话的 [prompt cache 生命周期](/docs/zh-CN/prompt-caching#cache-lifetime) 或更晚的压缩替换了缓存的对话时为 `true` |

1234| `estimated_cache_write_usd` | 将 `context_tokens` 写入会话模型的 prompt cache 的估计成本(美元),不包括响应 |

1235 

1236此示例显示了在最后一个响应后 90 分钟恢复的会话的输入:

993 1237 

994```json theme={null}1238```json theme={null}

995{1239{


997 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",1241 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

998 "cwd": "/Users/...",1242 "cwd": "/Users/...",

999 "hook_event_name": "SessionStart",1243 "hook_event_name": "SessionStart",

1000 "source": "startup",1244 "source": "resume",

1001 "model": "claude-sonnet-5"1245 "model": "claude-opus-5",

1246 "seconds_since_last_response": 5400,

1247 "context_tokens": 182340,

1248 "prompt_cache_likely_expired": true,

1249 "estimated_cache_write_usd": 1.1396

1002}1250}

1003```1251```

1004 1252 

1005<h4 id="sessionstart-decision-control">1253<h4 id="sessionstart-decision-control">

1006 SessionStart 决定控制1254 SessionStart 决策控制

1007</h4>1255</h4>

1008 1256 

1009您的 hook 脚本打印到 stdout 的任何文本都作为 Claude 的上下文添加。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您还可以返回这些事件特定字段:1257Claude Code 将它 [视为纯文本](#exit-code-0) 的 stdout 添加到 Claude 的上下文中。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您还可以返回这些事件特定的字段:

1010 1258 

1011| 字段 | 描述 |1259| 字段 | 描述 |

1012| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |1260| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |

1013| `additionalContext` | 添加到 Claude 上下文开始处的字符串,在第一个提示之前。请参阅[为 Claude 添加上下文](#add-context-for-claude)了解文本如何传递、放入什么内容以及恢复的会话如何处理过去的值 |1261| `additionalContext` | 在对话开始时添加到 Claude 上下文的字符串,在第一个提示之前。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1014| `initialUserMessage` | 用作会话第一个用户消息的字符串。适用于[非交互模式](/docs/zh-CN/headless)(`-p`),其中即使未提供提示,它也成为第一个轮次。如果提供了提示,它作为下一个轮次跟随。与 `additionalContext` 不同,后者附加到现有轮次,这创建轮次 |1262| `initialUserMessage` | 用作会话第一个用户消息的字符串。适用于 [非交互模式](/docs/zh-CN/headless),带有 `-p` 标志,即使未提供提示,它也成为第一个回合。如果提供了提示,它作为下一个回合跟随。与 `additionalContext` 不同,后者附加到现有回合,这会创建回合 |

1015| `sessionTitle` | 设置会话标题,与 `/rename` 的效果相同。使用此根据启动文件夹、git 分支或 worktree 名称自动命名会话。仅在 `source` 为 `"startup"` 或 `"resume"` 时适用;在 `"clear"` 和 `"compact"` 上被忽略 |1263| `sessionTitle` | 设置会话标题,与 `/rename` 效果相同。用于从启动文件夹、git 分支或 worktree 名称自动命名会话。当 `source` 为 `"startup"`、`"resume"` 或 `"fork"` 时适用;在 `"clear"` 和 `"compact"` 上被忽略 |

1016| `watchPaths` | 绝对路径数组,用于在此会话期间监视[FileChanged](#filechanged)事件 |1264| `watchPaths` | 绝对路径数组,用于在此会话期间监视 [FileChanged](#filechanged) 事件 |

1017| `reloadSkills` | 布尔值。当为 `true` 时,Claude Code 在 SessionStart hooks 完成后重新扫描[skill](/docs/zh-CN/skills)和命令目录,因此 hook 安装的 skills 在同一会话中可用,从第一个提示开始 |1265| `reloadSkills` | 布尔值。当为 `true` 时,Claude Code 在 SessionStart hooks 完成后重新扫描 [skill](/docs/zh-CN/skills) 和命令目录,因此 hook 安装的 skills 在同一会话中可用,从第一个提示开始 |

1018 1266 

1019```json theme={null}1267```json theme={null}

1020{1268{


1026}1274}

1027```1275```

1028 1276 

1029由于纯 stdout 已经为此事件到达 Claude,仅加载上下文的 hook 可以直接打印到 stdout 而无需构建 JSON。当您需要将上下文与其他字段(如 `suppressOutput` 或 `sessionTitle`)结合时,使用 JSON 形式。1277由于纯 stdout 已经为此事件到达 Claude,仅加载上下文的 hook 可以直接打印到 stdout 而无需构建 JSON。当您需要将上下文与其他字段(如 `sessionTitle`)结合时,使用 JSON 形式。

1030 1278 

1031当 SessionStart hook 安装或更新 skills 时使用 `reloadSkills`。Skill 发现通常在 SessionStart hooks 完成之前运行,因此 hook 写入 `~/.claude/skills/` 或 `.claude/skills/` 的文件否则只会在下一个会话中出现。此示例同步共享 skills 仓库并请求重新扫描:1279当 SessionStart hook 安装或更新 skills 时使用 `reloadSkills`。Skill 发现通常在 SessionStart hooks 完成之前运行,因此 hook 写入 `~/.claude/skills/` 或 `.claude/skills/` 的文件否则只会在下一个会话中出现。此示例同步共享 skills 存储库并请求重新扫描:

1032 1280 

1033```bash theme={null}1281```bash theme={null}

1034#!/bin/bash1282#!/bin/bash


1039echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1287echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'

1040```1288```

1041 1289 

1290存储库 URL 是占位符;将其替换为您自己的 skills 存储库。使用占位符,克隆失败并打印 `fatal:` 消息到 stderr。来自以 0 退出的 SessionStart hook 的 Stderr 仅供参考,因此 `reloadSkills` 请求仍然适用。

1291 

1042<h4 id="persist-environment-variables">1292<h4 id="persist-environment-variables">

1043 持久化环境变量1293 持久化环境变量

1044</h4>1294</h4>

1045 1295 

1046SessionStart hooks 可以访问 `CLAUDE_ENV_FILE` 环境变量,该变量提供一个文件路径,您可以在其中为后续 Bash 命令持久化环境变量。1296SessionStart hooks 可以访问 `CLAUDE_ENV_FILE` 环境变量,它提供一个文件路径,您可以在其中为后续 Bash 命令持久化环境变量。

1047 1297 

1048要设置单个环境变量,请将 `export` 语句写入 `CLAUDE_ENV_FILE`。使用追加(`>>`)来保留由其他 hooks 设置的变量:1298要设置单个环境变量,请将 `export` 语句写入 `CLAUDE_ENV_FILE`。使用追加 (`>>`) 来保留由其他 hooks 设置的变量:

1049 1299 

1050```bash theme={null}1300```bash theme={null}

1051#!/bin/bash1301#!/bin/bash


1066 1316 

1067ENV_BEFORE=$(export -p | sort)1317ENV_BEFORE=$(export -p | sort)

1068 1318 

1069# 运行修改环境的设置命令1319# Run your setup commands that modify the environment

1070source ~/.nvm/nvm.sh1320source ~/.nvm/nvm.sh

1071nvm use 201321nvm use 20

1072 1322 


1078exit 01328exit 0

1079```1329```

1080 1330 

1081写入此文件的任何变量都将在会话期间 Claude Code 执行的所有后续 Bash 命令中可用。

1082 

1083<Note>1331<Note>

1084 `CLAUDE_ENV_FILE` 可用于 SessionStart、[Setup](#setup)、[CwdChanged](#cwdchanged) 和 [FileChanged](#filechanged) hooks。其他 hook 类型无法访问此变量。1332 `CLAUDE_ENV_FILE` 可用于 SessionStart、[Setup](#setup)、[CwdChanged](#cwdchanged) 和 [FileChanged](#filechanged) hooks。其他 hook 类型无法访问此变量。

1085</Note>1333</Note>


1088 Setup1336 Setup

1089</h3>1337</h3>

1090 1338 

1091仅当您使用 `--init-only` 启动 Claude Code,或在[非交互模式](/docs/zh-CN/headless)中使用 `-p` 标志与 `--init` 或 `--maintenance` 结合时触发。它不在正常启动时触发。使用它进行一次性依赖安装或您从 CI 或脚本显式触发的计划清理,与正常会话启动分开。对于每个会话的初始化,请改用[SessionStart](#sessionstart)。1339仅当您使用 `--init-only` 启动 Claude Code,或在 [非交互模式](/docs/zh-CN/headless) 中使用 `--init` 或 `--maintenance` 与 `-p` 标志时触发。它不会在正常启动时触发。用于一次性依赖安装或您从 CI 或脚本显式触发的计划清理,与正常会话启动分开。对于每个会话的初始化,请改用 [SessionStart](#sessionstart)。

1092 1340 

1093匹配器值对应于触发 hook 的 CLI 标志:1341匹配器值对应于触发 hook 的 CLI 标志:

1094 1342 


1097| `init` | `claude --init-only` 或 `claude -p --init` |1345| `init` | `claude --init-only` 或 `claude -p --init` |

1098| `maintenance` | `claude -p --maintenance` |1346| `maintenance` | `claude -p --maintenance` |

1099 1347 

1100`--init-only` 运行 Setup hooks 和 SessionStart hooks(带 `startup` 匹配器),然后退出而不启动对话。`--init` 和 `--maintenance` 仅在与 `-p` 结合时触发 Setup hooks;在交互式会话中,这两个标志目前不触发 Setup hooks。1348当您运行 `claude --init-only` 时,Claude Code 运行 Setup hooks 和带有 `startup` 匹配器的 `SessionStart` hooks,然后退出而不启动对话。

1349 

1350当您使用 `-p` 启动或继续对话时,您还需要提供提示,作为参数或通过 stdin 管道传输。当 `SessionStart` hook 提供 [`initialUserMessage`](#sessionstart-decision-control) 或当您使用 [延迟工具调用](#defer-a-tool-call-for-later) 恢复会话时,您可以跳过提示。

1351 

1352成功时,`--init-only` 不向终端打印任何内容。要确认 hooks 运行,请使用 `claude --debug-file <path> --init-only` 启动,将 `<path>` 替换为日志文件位置,并检查日志中的 Setup 和 SessionStart hook 条目。

1101 1353 

1102因为 Setup 不在每次启动时触发,需要安装依赖的插件不能仅依赖 Setup。实际的模式是在首次使用时检查依赖,如果缺失则安装,例如测试 `${CLAUDE_PLUGIN_DATA}/node_modules` 的 hook 或 skill,如果不存在则运行 `npm install`。请参阅[持久数据目录](/docs/zh-CN/plugins-reference#persistent-data-directory)了解在何处存储已安装的依赖。1354由于 Setup 不会在每次启动时触发,需要安装依赖的插件不能仅依赖 Setup。实际的模式是在首次使用时检查依赖,如果缺失则安装,例如测试 `${CLAUDE_PLUGIN_DATA}/node_modules` 的 hook 或 skill,如果不存在则运行 `npm install`。有关存储已安装依赖的位置,请参阅 [持久数据目录](/docs/zh-CN/plugins-reference#persistent-data-directory)。如果您通过市场分发插件,您可能不需要此模式:Claude Code [在缓存插件时自动安装符合条件的 Node.js 包依赖](/docs/zh-CN/plugins-reference#node-js-package-dependencies)。

1103 1355 

1104<h4 id="setup-input">1356<h4 id="setup-input">

1105 Setup 输入1357 Setup 输入

1106</h4>1358</h4>

1107 1359 

1108除了[通用输入字段](#common-input-fields)外,Setup hooks 还接收一个 `trigger` 字段,设置为 `"init"` 或 `"maintenance"`:1360除了 [常见输入字段](#common-input-fields) 外,Setup hooks 接收设置为 `"init"` 或 `"maintenance"` 的 `trigger` 字段:

1109 1361 

1110```json theme={null}1362```json theme={null}

1111{1363{


1118```1370```

1119 1371 

1120<h4 id="setup-decision-control">1372<h4 id="setup-decision-control">

1121 Setup 决定控制1373 Setup 决策控制

1122</h4>1374</h4>

1123 1375 

1124Setup hooks 无法阻止。任何非零退出代码(包括 2)都会向用户显示 stderr 作为 `<hook name> hook error` 通知,执行继续。在[非交互模式](/docs/zh-CN/headless)中,hook 输出仅在您使用 `--verbose` 启动时出现。1376Setup hooks 无法阻止;执行在任何退出代码上继续。在每个退出代码上,Claude Code 丢弃 Setup hook 的 [JSON 输出字段](#json-output),如 `systemMessage`、`continue` 和 `hookSpecificOutput.additionalContext`。使用 `-p` 时,Setup hook 的 stdout、stderr 和退出代码仅在您使用 `--output-format stream-json --verbose` 启动时作为 [`hook_response` 事件](/docs/zh-CN/headless#read-session-metadata) 出现在运行的输出中。

1125 

1126要将信息传入 Claude 的上下文,在 JSON 输出中返回 `additionalContext`;纯 stdout 仅写入调试日志。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您还可以返回这些事件特定字段:

1127 

1128| 字段 | 描述 |

1129| :------------------ | :-------------------------------- |

1130| `additionalContext` | 添加到 Claude 上下文的字符串。多个 hooks 的值被连接 |

1131 

1132```json theme={null}

1133{

1134 "hookSpecificOutput": {

1135 "hookEventName": "Setup",

1136 "additionalContext": "Dependencies installed: node_modules, .venv"

1137 }

1138}

1139```

1140 1377 

1141Setup hooks 可以访问 `CLAUDE_ENV_FILE`。写入该文件的变量持久化到会话的后续 Bash 命令中,就像在[SessionStart hooks](#persist-environment-variables)中一样。仅支持 `type: "command"` 和 `type: "mcp_tool"` hooks。1378Setup hooks 可以访问 `CLAUDE_ENV_FILE`。写入该文件的变量持久化到会话的后续 Bash 命令中,就像在 [SessionStart hooks](#persist-environment-variables) 中一样。仅 `type: "command"` hooks 在 `Setup` 上运行。`type: "mcp_tool"` hook 在 `Setup` 上总是被跳过,如 [MCP tool hook 字段](#mcp-tool-hook-fields) 下所述。

1142 1379 

1143<h3 id="instructionsloaded">1380<h3 id="instructionsloaded">

1144 InstructionsLoaded1381 InstructionsLoaded

1145</h3>1382</h3>

1146 1383 

1147当 `CLAUDE.md` 或 `.claude/rules/*.md` 文件加载到上下文中时触发。此事件在会话启动时为急切加载的文件触发,稍后当文件被懒加载时再次触发,例如当 Claude 访问包含嵌套 `CLAUDE.md` 的子目录或条件规则与 `paths:` frontmatter 匹配时。该 hook 不支持阻止或决定控制。它异步运行以用于可观测性目的。1384在加载 `CLAUDE.md` 或 `.claude/rules/*.md` 文件到上下文时触发。此事件在会话启动时对于急切加载的文件触发,稍后当文件被懒加载时再次触发,例如当 Claude 访问包含嵌套 `CLAUDE.md` 的子目录或当带有 `paths:` frontmatter 的条件规则匹配时。hook 不支持阻止或决策控制。它异步运行用于可观测性目的。

1148 1385 

1149匹配器针对 `load_reason` 运行。例如,使用 `"matcher": "session_start"` 仅对会话启动时加载的文件触发,或使用 `"matcher": "path_glob_match|nested_traversal"` 仅对懒加载触发。1386当 Claude [直接通过 **Project instructions** 设置读取 `AGENTS.md`](/docs/zh-CN/memory#agents-md) 时,此事件不触发。当 `CLAUDE.md` 导入您的 `AGENTS.md` 时它确实触发,`load_reason` 设置为 `include`(与任何其他导入文件一样),以及当 `CLAUDE.md` 是它的符号链接时,作为正常的 `CLAUDE.md` 加载。

1387 

1388匹配器针对 `load_reason` 运行。例如,使用 `"matcher": "session_start"` 仅对会话启动时加载的文件触发,或 `"matcher": "path_glob_match|nested_traversal"` 仅对懒加载触发。

1150 1389 

1151<h4 id="instructionsloaded-input">1390<h4 id="instructionsloaded-input">

1152 InstructionsLoaded 输入1391 InstructionsLoaded 输入

1153</h4>1392</h4>

1154 1393 

1155除了[通用输入字段](#common-input-fields)外,InstructionsLoaded hooks 还接收这些字段:1394除了 [常见输入字段](#common-input-fields) 外,InstructionsLoaded hooks 接收这些字段:

1156 1395 

1157| 字段 | 描述 |1396| 字段 | 描述 |

1158| :------------------ | :--------------------------------------------------------------------------------------------------------------------------- |1397| :------------------ | :-------------------------------------------------------------------------------------------------------------------------- |

1159| `file_path` | 加载的指令文件的绝对路径 |1398| `file_path` | 加载的指令文件的绝对路径 |

1160| `memory_type` | 文件的范围:`"User"`、`"Project"`、`"Local"` 或 `"Managed"` |1399| `memory_type` | 文件的范围:`"User"`、`"Project"`、`"Local"` 或 `"Managed"` |

1161| `load_reason` | 文件被加载的原因:`"session_start"`、`"nested_traversal"`、`"path_glob_match"`、`"include"` 或 `"compact"`。`"compact"` 值在压缩事件后重新加载指令文件时触发 |1400| `load_reason` | 文件加载的原因:`"session_start"`、`"nested_traversal"`、`"path_glob_match"`、`"include"` 或 `"compact"`。`"compact"` 值在压缩事件后重新加载指令文件时触发 |

1162| `globs` | 文件 `paths:` frontmatter 中的路径 glob 模式(如果有)。仅对 `path_glob_match` 加载存在 |1401| `globs` | 文件 `paths:` frontmatter 中的路径 glob 模式(如果有)。仅对 `path_glob_match` 加载出现 |

1163| `trigger_file_path` | 触发此加载的文件的路径,用于懒加载 |1402| `trigger_file_path` | 触发此加载的文件的路径,用于懒加载 |

1164| `parent_file_path` | 包含此文件的父指令文件的路径,用于 `include` 加载 |1403| `parent_file_path` | 包含此文件的父指令文件的路径,用于 `include` 加载 |

1165 1404 


1176```1415```

1177 1416 

1178<h4 id="instructionsloaded-decision-control">1417<h4 id="instructionsloaded-decision-control">

1179 InstructionsLoaded 决定控制1418 InstructionsLoaded 决策控制

1180</h4>1419</h4>

1181 1420 

1182InstructionsLoaded hooks 没有决定控制。它们无法阻止或修改指令加载。使用此事件进行审计日志记录、合规性跟踪或可观测性。1421InstructionsLoaded hooks 没有决策控制。它们无法阻止或修改指令加载。Claude Code 丢弃它们的 [JSON 输出字段](#json-output),如 `systemMessage` 和 `continue`。使用此事件进行审计日志、合规性跟踪或可观测性。

1183 1422 

1184<h3 id="userpromptsubmit">1423<h3 id="userpromptsubmit">

1185 UserPromptSubmit1424 UserPromptSubmit

1186</h3>1425</h3>

1187 1426 

1188在用户提交提示时运行,在 Claude 处理之前。这允许您根据提示/对话添加额外上下文、验证提示或阻止某些类型的提示。1427在用户提交提示时运行,在 Claude 处理它之前。这允许您根据提示/对话添加额外上下文、验证提示或阻止某些类型的提示。

1189 1428 

1190`UserPromptSubmit` hooks 对 `command`、`http` 和 `mcp_tool` 类型的默认超时为 30 秒,比这些类型在其他事件上的 600 秒默认值更短。因为此 hook 在每个提示之前运行并阻止模型处理直到完成,卡住的 hook 会停滞会话。如果您的 hook 需要更多时间,在 hook 条目中设置 `timeout` 字段。1429`UserPromptSubmit` hooks 对 `command`、`http` 和 `mcp_tool` 类型的默认超时为 30 秒,比大多数其他事件的 600 秒默认值更短。因为此 hook 在每个提示之前运行并阻止模型处理直到它完成,卡住的 hook 会停滞会话。如果您的 hook 需要更多时间,请在 hook 条目中设置 `timeout` 字段。

1191 1430 

1192达到超时的 `UserPromptSubmit` hook 被取消,其输出(包括任何 `additionalContext`)被丢弃。提示仍然到达 Claude,但没有该上下文。从 v2.1.196 开始,成绩单显示一个通知,命名 hook、触发的超时以及输出被丢弃。早期版本取消 hook 而不显示通知。1431除了您使用 [`async: true`](#run-hooks-in-the-background) 运行的命令 hook 外,达到其超时的 `UserPromptSubmit` 命令、HTTP 或 MCP tool hook 被取消,其输出(包括任何 `additionalContext`)被丢弃。提示仍然到达 Claude 而没有该上下文。成绩单显示一个通知,命名 hook、触发的超时以及输出被丢弃。

1193 1432 

1194在 `UserPromptSubmit` 上达到超时的[Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks)会用命名 hook 和超时的消息阻止提示,因为那里的回调可能充当必须不失败打开的策略门。会话继续。在 v2.1.208 之前,该事件上的回调超时以执行错误结束轮次。1433在 `UserPromptSubmit` 上达到其超时的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) 用命名 hook 和超时的消息阻止提示,因为那里的回调可以充当不能失败打开的策略门。会话继续。在 v2.1.208 之前,该事件上的回调超时以执行错误结束回合。

1195 1434 

1196<h4 id="userpromptsubmit-input">1435<h4 id="userpromptsubmit-input">

1197 UserPromptSubmit 输入1436 UserPromptSubmit 输入

1198</h4>1437</h4>

1199 1438 

1200除了[通用输入字段](#common-input-fields)外,UserPromptSubmit hooks 还接收包含用户提交的文本的 `prompt` 字段。1439除了 [常见输入字段](#common-input-fields) 外,UserPromptSubmit hooks 接收包含用户提交的文本的 `prompt` 字段。

1201 1440 

1202```json theme={null}1441```json theme={null}

1203{1442{


1211```1450```

1212 1451 

1213<h4 id="userpromptsubmit-decision-control">1452<h4 id="userpromptsubmit-decision-control">

1214 UserPromptSubmit 决定控制1453 UserPromptSubmit 决策控制

1215</h4>1454</h4>

1216 1455 

1217`UserPromptSubmit` hooks 可以控制用户提示是否被处理并添加上下文。所有[JSON 输出字段](#json-output)都可用。1456`UserPromptSubmit` hooks 可以控制是否处理用户提示并添加上下文。所有 [JSON 输出字段](#json-output) 都可用。

1218 1457 

1219有两种方法可以在退出代码 0 时向对话添加上下文:1458有两种方式在退出代码 0 上向对话添加上下文:

1220 1459 

1221* **纯文本 stdout**:写入 stdout 的任何非 JSON 文本都作为上下文添加1460* **纯文本 stdout**:Claude Code 将它 [视为纯文本](#exit-code-0) 的 stdout 添加到 Claude 的上下文

1222* **带 `additionalContext` 的 JSON**:使用下面的 JSON 格式以获得更多控制。`additionalContext` 字段作为上下文添加1461* **带有 `additionalContext` 的 JSON**:使用下面的 JSON 格式以获得更多控制。`additionalContext` 字段作为上下文添加

1223 1462 

1224纯 stdout 在成绩单中显示为 hook 输出。`additionalContext` 值作为系统提醒注入,Claude 读取而不显示成绩单条目。1463两个通道都不产生可见的成绩单条目。纯 stdout 和 `additionalContext` 值各自作为以 hook 名称开头的系统提醒注入;Claude 读取两者。要确认传递,请检查 [调试日志](#debug-hooks)。

1225 1464 

1226要阻止提示,返回一个 JSON 对象,其中 `decision` 设置为 `"block"`:1465要阻止提示,返回一个 JSON 对象,其中 `decision` 设置为 `"block"`:

1227 1466 

1228| 字段 | 描述 |1467| 字段 | 描述 |

1229| :----------------------- | :----------------------------------------------------------------------- |1468| :----------------------- | :----------------------------------------------------------------------------------------- |

1230| `decision` | `"block"` 防止提示被处理并从上下文中删除。省略以允许提示继续 |1469| `decision` | `"block"` 防止提示被处理并从上下文中删除它。省略以允许提示继续 |

1231| `reason` | 当 `decision` 为 `"block"` 时向用户显示。不添加到上下文 |1470| `reason` | 当 `decision` 为 `"block"` 时显示给用户。不添加到上下文 |

1232| `additionalContext` | 添加到 Claude 上下文的字符串,与提交的提示一起。请参阅[为 Claude 添加上下文](#add-context-for-claude) |1471| `additionalContext` | 与提交的提示一起添加到 Claude 上下文的字符串。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1233| `sessionTitle` | 设置会话标题。使用此根据提示内容自动命名会话 |1472| `sessionTitle` | 设置会话标题。用于根据提示内容自动命名会话 |

1234| `suppressOriginalPrompt` | 如果 `true` 当 `decision` 为 `"block"` 时,从向用户显示的阻止消息中省略原始提示文本 |1473| `suppressOriginalPrompt` | 如果在 `decision` 为 `"block"` 时为 `true`,则从显示给用户的阻止消息中省略原始提示文本 |

1474 

1475通过退出 2 阻止的 hook 路由方式与 `reason` 相同:阻止消息向用户显示 stderr 文本,它不添加到上下文。

1235 1476 

1236```json theme={null}1477```json theme={null}

1237{1478{


1249 UserPromptExpansion1490 UserPromptExpansion

1250</h3>1491</h3>

1251 1492 

1252当用户输入的斜杠命令在到达 Claude 之前展开为提示时运行。使用此来阻止特定命令的直接调用、为特定 skill 注入上下文或记录用户调用哪些命令。例如,匹配 `deploy` 的 hook 可以阻止 `/deploy`,除非存在批准文件,或匹配审查 skill 的 hook 可以将团队的审查清单附加为 `additionalContext`。1493当用户输入的命令在到达 Claude 之前扩展为提示时运行。使用此来阻止特定命令的直接调用、为特定 skill 注入上下文或记录用户调用哪些命令。例如,匹配 `deploy` 的 hook 可以阻止 `/deploy`,除非存在批准文件,或匹配审查 skill 的 hook 可以将团队的审查清单附加为 `additionalContext`。

1253 1494 

1254此事件涵盖 `PreToolUse` 不涵盖的路径:匹配 `Skill` 工具的 `PreToolUse` hook 仅在 Claude 调用工具时触发,但直接输入 `/skillname` 绕过 `PreToolUse`。`UserPromptExpansion` 在该直接路径上触发。1495此事件涵盖 `PreToolUse` 不涵盖的路径:匹配 `Skill` 工具的 `PreToolUse` hook 仅在 Claude 调用工具时触发,但直接输入 `/skillname` 绕过 `PreToolUse`。`UserPromptExpansion` 在该直接路径上触发。

1255 1496 

1256在 `command_name` 上匹配。留空匹配器以对每个提示类型斜杠命令触发。1497匹配 `command_name`。将匹配器留空以对每个提示类型命令触发。

1257 1498 

1258<h4 id="userpromptexpansion-input">1499<h4 id="userpromptexpansion-input">

1259 UserPromptExpansion 输入1500 UserPromptExpansion 输入

1260</h4>1501</h4>

1261 1502 

1262除了[通用输入字段](#common-input-fields)外,UserPromptExpansion hooks 还接收 `expansion_type`、`command_name`、`command_args`、`command_source` 和原始 `prompt` 字符串。`expansion_type` 字段对于 skill 和自定义命令为 `slash_command`,或对于 MCP 服务器提示为 `mcp_prompt`。1503除了 [常见输入字段](#common-input-fields) 外,UserPromptExpansion hooks 接收 `expansion_type`、`command_name`、`command_args`、`command_source` 和原始 `prompt` 字符串。`expansion_type` 字段对于 skill 和自定义命令为 `slash_command`,或对于 MCP 服务器提示为 `mcp_prompt`。

1263 1504 

1264```json theme={null}1505```json theme={null}

1265{1506{


1277```1518```

1278 1519 

1279<h4 id="userpromptexpansion-decision-control">1520<h4 id="userpromptexpansion-decision-control">

1280 UserPromptExpansion 决定控制1521 UserPromptExpansion 决策控制

1281</h4>1522</h4>

1282 1523 

1283`UserPromptExpansion` hooks 可以阻止展开或添加上下文。所有[JSON 输出字段](#json-output)都可用。1524`UserPromptExpansion` hooks 可以阻止扩展或添加上下文。所有 [JSON 输出字段](#json-output) 都可用。

1284 1525 

1285| 字段 | 描述 |1526| 字段 | 描述 |

1286| :------------------ | :----------------------------------------------------------------------- |1527| :------------------ | :----------------------------------------------------------------------------------------- |

1287| `decision` | `"block"` 防止斜杠命令展开。省略以允许它继续 |1528| `decision` | `"block"` 防止命令扩展。省略以允许它继续 |

1288| `reason` | 当 `decision` 为 `"block"` 时向用户显示 |1529| `reason` | 当 `decision` 为 `"block"` 时显示给用户 |

1289| `additionalContext` | 添加到 Claude 上下文的字符串,与展开的提示一起。请参阅[为 Claude 添加上下文](#add-context-for-claude) |1530| `additionalContext` | 与扩展的提示一起添加到 Claude 上下文的字符串。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1531 

1532通过退出 2 阻止的 hook 路由方式与 `reason` 相同:阻止消息向用户显示 stderr 文本。

1290 1533 

1291```json theme={null}1534```json theme={null}

1292{1535{


1303 MessageDisplay1546 MessageDisplay

1304</h3>1547</h3>

1305 1548 

1306在助手消息流向屏幕时运行。Claude Code 分批显示消息:每次一批新完成的行准备好渲染时,hook 运行一次,包含这些行,Claude Code 在其位置渲染 hook 的替换文本。长消息产生多个调用;短消息可能只产生一个。1549在助手消息流向屏幕时运行。Claude Code 分批显示消息:每次一批新完成的行准备好渲染时,hook 运行一次,这些行,Claude Code 用 hook 的替换文本渲染它们的位置。长消息产生多个调用;短消息可能只产生一个。

1307 1550 

1308使用 MessageDisplay 来:1551使用 MessageDisplay 来:

1309 1552 

1310* 剥离 markdown 以获得最小显示1553* 为最小显示剥离 markdown

1311* 转换 Agent SDK 应用向其用户显示的文本1554* 转换 Agent SDK 应用程序向其用户显示的文本

1312* 从 Claude 的响应中编辑 API 密钥或内部主机名1555* 从 Claude 的响应中编辑 API 密钥或内部主机名

1313 1556 

1314Claude Code 保持每个批次直到您的 hook 返回,因此保持 hook 快速。如果 hook 失败或超时,Claude Code 显示原始文本。此事件的默认超时为 10 秒;如果您的 hook 需要更多时间,在 hook 条目中设置 `timeout` 字段。1557Claude Code 保持每个批次直到您的 hook 返回,因此保持 hook 快速。如果 hook 失败或超时,Claude Code 显示原始文本。此事件的默认超时为 10 秒;如果您的 hook 需要更多时间,请在 hook 条目中设置 `timeout` 字段。

1315 1558 

1316MessageDisplay 仅用于显示:替换文本仅改变屏幕上呈现的内容。成绩单和 Claude 看到的内容保持原始文本,因此 Claude 永远看不到替换,详细模式显示原始内容。Hook 仅接收助手消息文本,因此工具结果和您输入的文本呈现不变。1559MessageDisplay 仅用于显示:替换文本仅更改屏幕上呈现的内容。成绩单和 Claude 看到的内容保持原始文本,因此 Claude 永远看不到替换,详细模式显示原始。hook 仅接收助手消息文本,因此工具结果和您输入的文本呈现不变。

1317 1560 

1318MessageDisplay 不支持匹配器,对每个流向文本的助手消息触发;没有文本的消息(如仅工具调用响应)不触发它。1561MessageDisplay 不支持匹配器,对每个流式传输文本的助手消息触发;没有文本的消息(如仅工具调用响应)不触发它。

1319 1562 

1320在非交互式运行中,包括 Agent SDK 查询和 `claude -p`,MessageDisplay 每个助手消息运行一次,而不是每批行运行一次。单个调用在消息完成后到达,并携带完整消息文本:`index` 为 `0`,`final` 为 `true`,`delta` 保存整个消息。为每个消息收集 `delta` 文本的 hook 在两种模式中接收相同的总文本。1563在非交互式运行中,包括 Agent SDK 查询和 `claude -p`,MessageDisplay 每个助手消息运行一次而不是每批行一次。单个调用在消息完成后到达并携带完整消息文本:`index` 为 `0`,`final` 为 `true`,`delta` 保持整个消息。为每个消息收集 `delta` 文本的 hook 在两种模式中接收相同的总文本。

1321 1564 

1322<h4 id="messagedisplay-input">1565<h4 id="messagedisplay-input">

1323 MessageDisplay 输入1566 MessageDisplay 输入

1324</h4>1567</h4>

1325 1568 

1326除了[通用输入字段](#common-input-fields)外,MessageDisplay hooks 还接收轮次和消息的标识符、此调用在消息中的位置以及 `delta` 中的新文本。批次边界取决于文本如何流动,因此使用 `index` 和 `final` 来跟踪通过消息的进度,而不是期望行以特定方式分组。1569除了 [常见输入字段](#common-input-fields) 外,MessageDisplay hooks 接收回合和消息的标识符、此调用在消息中的位置以及 `delta` 中的新文本。批次边界取决于文本流的方式,因此使用 `index` 和 `final` 来跟踪通过消息的进度,而不是期望行以特定方式分组。

1327 1570 

1328| 字段 | 描述 |1571| 字段 | 描述 |

1329| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |1572| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |

1330| `turn_id` | 当前轮次的 UUID |1573| `turn_id` | 当前回合的 UUID |

1331| `message_id` | 正在显示的助手消息的 UUID。在同一消息的每个批次中稳定。这不是 API `msg_…` id,因此无法与成绩单消息 ids 关联 |1574| `message_id` | 正在显示的助手消息的 UUID。在同一消息的每个批次中稳定。这不是 API `msg_…` id,因此无法与成绩单消息 id 关联 |

1332| `index` | 此批次在消息中的零基索引 |1575| `index` | 此批次在消息中的零基索引 |

1333| `final` | 在消息的最后一个批次上为 `true`。每个消息恰好有一个最终批次 |1576| `final` | 在消息的最后一个批次上为 `true`。每个消息恰好有一个最终批次 |

1334| `delta` | 自上一个批次以来新完成的行,包括终止换行符。始终是完整行,除了最终批次可能在行中间结束。在交互式运行中,当消息以换行符结束时最终批次的 delta 为空,因此将 `final` 而不是非空 delta 视为消息结束信号。在 Agent SDK 和 `claude -p` 运行中,单个调用携带整个消息 |1577| `delta` | 自上一个批次以来新完成的行,包括终止换行符。始终是完整行,除了最终批次可能在行中间结束。在交互式运行中,当消息以换行符结束时最终批次的 delta 为空,因此将 `final` 而不是非空 delta 视为消息结束信号。在 Agent SDK 和 `claude -p` 运行中,单个调用携带整个消息 |


1351 MessageDisplay 输出1594 MessageDisplay 输出

1352</h4>1595</h4>

1353 1596 

1354除了所有 hooks 可用的[JSON 输出字段](#json-output)外,MessageDisplay hooks 可以返回 `displayContent` 来替换屏幕上的 delta:1597除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,MessageDisplay hooks 可以返回 `displayContent` 来替换屏幕上的 delta:

1355 1598 

1356| 字段 | 描述 |1599| 字段 | 描述 |

1357| :--------------- | :----------------------- |1600| :--------------- | :--------------------- |

1358| `displayContent` | 代替 delta 显示的文本。省略以显示原始内容 |1601| `displayContent` | 显示代替 delta 的文本。省略以显示原始 |

1359 1602 

1360MessageDisplay hooks 没有决定控制。它们无法阻止消息或改变成绩单中存储或发送给 Claude 的内容。1603MessageDisplay hooks 没有决策控制。它们无法阻止消息或更改成绩单中存储或发送给 Claude 的内容。Claude Code 作用于它们的 JSON 输出中的 `displayContent` 并丢弃 `systemMessage` 和 `continue`。

1361 1604 

1362此示例从 Claude 的响应中剥离 markdown 格式以获得纯文本显示。脚本从 stdin 读取每个批次,从 `delta` 中移除粗体标记和内联代码反引号,并将结果作为 `displayContent` 返回。1605此示例从 Claude 的响应中剥离 markdown 格式以获得纯文本显示。脚本从 stdin 读取每个批次,从 `delta` 中删除粗体标记和内联代码反引号,并将结果作为 `displayContent` 返回。

1363 1606 

1364<Tabs>1607<Tabs>

1365 <Tab title="macOS/Linux">1608 <Tab title="macOS/Linux">


1383 }1626 }

1384 ```1627 ```

1385 1628 

1386 将此脚本保存到您的项目中的 `.claude/hooks/plain-display.sh` 并使用 `chmod +x` 使其可执行:1629 将此脚本保存到项目中的 `.claude/hooks/plain-display.sh` 并使用 `chmod +x` 使其可执行:

1387 1630 

1388 ```bash theme={null}1631 ```bash theme={null}

1389 #!/bin/bash1632 #!/bin/bash

1390 jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'1633 jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'

1391 ```1634 ```

1392 

1393 脚本需要 `jq` 在您的 `PATH` 上。

1394 </Tab>1635 </Tab>

1395 1636 

1396 <Tab title="Windows (PowerShell)">1637 <Tab title="Windows (PowerShell)">


1422 1663 

1423 `-NoProfile` 标志跳过加载您的 PowerShell 配置文件,以便 hook 快速启动,`-ExecutionPolicy Bypass` 让 PowerShell 运行本地脚本文件。1664 `-NoProfile` 标志跳过加载您的 PowerShell 配置文件,以便 hook 快速启动,`-ExecutionPolicy Bypass` 让 PowerShell 运行本地脚本文件。

1424 1665 

1425 将此脚本保存到您的项目中的 `.claude/hooks/plain-display.ps1`:1666 将此脚本保存到项目中的 `.claude/hooks/plain-display.ps1`:

1426 1667 

1427 ```powershell theme={null}1668 ```powershell theme={null}

1428 $batch = [Console]::In.ReadToEnd() | ConvertFrom-Json1669 $batch = [Console]::In.ReadToEnd() | ConvertFrom-Json


1437 </Tab>1678 </Tab>

1438</Tabs>1679</Tabs>

1439 1680 

1440没有 markdown 的批次通过不变。如果脚本失败,例如因为 `jq` 缺失,Claude Code 显示原始文本并仅在[调试输出](#debug-hooks)中注意失败,而不是在会话中。1681没有 markdown 的批次通过不变。如果脚本失败,例如因为 `jq` 缺失,Claude Code 显示原始文本并仅在 [调试输出](#debug-hooks) 中注意失败,而不是在会话中。

1441 1682 

1442<h3 id="pretooluse">1683<h3 id="pretooluse">

1443 PreToolUse1684 PreToolUse

1444</h3>1685</h3>

1445 1686 

1446在 Claude 创建工具参数后和处理工具调用之前运行。在工具名称上匹配:`Bash`、`Edit`、`Write`、`Read`、`Glob`、`Grep`、`Agent`、`WebFetch`、`WebSearch`、`AskUserQuestion`、`ExitPlanMode` 和任何[MCP 工具名称](#match-mcp-tools)。1687在 Claude 创建工具参数之后和处理工具调用之前运行。匹配除 `EndConversation` 外的任何工具名称:内置工具如 `Bash`、`PowerShell`、`Edit`、`Write`、`Read`、`Glob`、`Grep`、`Agent`、`Workflow`、`WebFetch`、`WebSearch`、`AskUserQuestion` 和 `ExitPlanMode`,以及任何 [MCP 工具名称](#match-mcp-tools)。

1688 

1689要在特定文件在磁盘上更改时运行 hook,无论什么写入它,请使用 [FileChanged](#filechanged) 而不是按名称匹配文件编辑工具。与 PreToolUse 不同,Claude Code 在更改后运行 FileChanged hooks,它们没有决策控制,因此无法阻止写入。

1447 1690 

1448<Warning>1691<Warning>

1449 PreToolUse 仅在 Claude 调用工具时运行。您[在提示中使用 `@` 引用的文件](/docs/zh-CN/common-workflows#reference-files-and-directories)被添加而不进行任何工具调用:Claude Code 在构建提示时插入其内容,因此没有 PreToolUse hook 对它们触发,包括匹配 `Read` 的 hooks。要阻止特定路径的 `@` 引用,请改用[`Read` 拒绝规则](/docs/zh-CN/permissions#read-and-edit)。1692 PreToolUse 仅在 Claude 调用工具时运行。您 [在提示中使用 `@` 引用的文件](/docs/zh-CN/common-workflows#reference-files-and-directories) 添加时没有任何工具调用:Claude Code 在构建提示时插入它们的内容,因此没有 PreToolUse hook 为它们触发,包括匹配 `Read` 的 hooks。要阻止特定路径的 `@` 引用,请改用 [`Read` 拒绝规则](/docs/zh-CN/permissions#read-and-edit)。

1693 

1694 PreToolUse 也不为 [`EndConversation`](/docs/zh-CN/tools-reference#endconversation-tool-behavior) 触发。

1450</Warning>1695</Warning>

1451 1696 

1452使用[PreToolUse 决定控制](#pretooluse-decision-control)来允许、拒绝、询问或延迟工具调用。1697使用 [PreToolUse 决策控制](#pretooluse-decision-control) 来允许、拒绝、询问或延迟工具调用。

1698 

1699在 `PreToolUse` 上超过其超时的 [Agent SDK 回调 hook](/docs/zh-CN/agent-sdk/hooks) 阻止工具调用,Claude 接收命名超时的错误结果。另一个 hook 返回的显式拒绝仍然优先。

1453 1700 

1454<h4 id="pretooluse-input">1701<h4 id="pretooluse-input">

1455 PreToolUse 输入1702 PreToolUse 输入

1456</h4>1703</h4>

1457 1704 

1458除了[通用输入字段](#common-input-fields)外,PreToolUse hooks 还接收 `tool_name`、`tool_input` 和 `tool_use_id`。`tool_input` 字段取决于工具:1705除了 [常见输入字段](#common-input-fields) 外,PreToolUse hooks 接收 `tool_name`、`tool_input` 和 `tool_use_id`。

1706 

1707对于 [MCP 工具](#match-mcp-tools),输入还携带 `mcp_server`,一个包含服务器 `name` 和 `source` 的对象,说明服务器定义来自何处。`source` 值包括 `plugin`、`sdk` 和配置范围如 `user` 和 `project`。[Agent SDK 参考中的 `McpServerProvenance`](/docs/zh-CN/agent-sdk/typescript#mcpserverprovenance) 列出了所有内容并说明如何处理您不认识的内容。基于 `source` 而不是 `name` 或 `mcp__<server>__` 工具名称前缀做出信任决定。`mcp_server` 字段需要 Claude Code v2.1.274 或更高版本。

1708 

1709对于文件工具 `Write`、`Edit` 和 `Read`,`tool_input.file_path` 始终是绝对的:

1710 

1711* Claude Code 在 hooks 运行之前扩展 `~` 和相对路径,因此匹配路径的 hook 无法通过 `~` 或相同路径的相对拼写绕过

1712* 在 Windows 上,路径到达时带有反斜杠分隔符,即使您的 hook 在 Git Bash 下运行,其中 `$PWD` 看起来像 `/c/project`

1713* 使用正斜杠编写的比较(如 `/src/` 检查)永远不会匹配反斜杠路径,工具调用继续进行,就像 hook 没有什么要阻止的一样

1714* 在比较前规范化分隔符:Bash 中的 `FILE_PATH="${FILE_PATH//\\//}"` 或 Python 中的 `file_path.replace("\\", "/")`,然后匹配路径段如 `/src/` 而不是用 `^` 锚定,因为路径是绝对的

1715 

1716Windows 上的 `Write` 调用传递:

1717 

1718```json theme={null}

1719{

1720 "hook_event_name": "PreToolUse",

1721 "tool_name": "Write",

1722 "tool_input": {

1723 "file_path": "C:\\project\\src\\index.ts",

1724 "content": "..."

1725 },

1726 ...

1727}

1728```

1729 

1730`tool_input` 字段取决于工具:

1731 

1732<a id="bash" />

1459 1733 

1460<h5 id="bash">1734<h5 id="bash">

1461 Bash1735 Bash


1464执行 shell 命令。1738执行 shell 命令。

1465 1739 

1466| 字段 | 类型 | 示例 | 描述 |1740| 字段 | 类型 | 示例 | 描述 |

1467| :------------------ | :------ | :----------------- | :------------------------------------------------------------------------- |1741| :------------------ | :------ | :----------------- | :--------------------------------------------------------------------------- |

1468| `command` | string | `"npm test"` | 要执行的 shell 命令 |1742| `command` | string | `"npm test"` | 要执行的 shell 命令 |

1469| `description` | string | `"Run test suite"` | 命令执行操作的可选描述 |1743| `description` | string | `"Run test suite"` | 命令执行操作的可选描述 |

1470| `timeout` | number | `120000` | 可选超时(毫秒)。高于[最大值](/docs/zh-CN/tools-reference#bash-tool-behavior)的值被减少到最大值而不是被拒绝 |1744| `timeout` | number | `120000` | 可选超时(毫秒)。高于 [最大值](/docs/zh-CN/tools-reference#bash-tool-behavior) 的值被减少到最大值而不是被拒绝 |

1471| `run_in_background` | boolean | `false` | 是否在后台运行命令 |1745| `run_in_background` | boolean | `false` | 是否在后台运行命令 |

1472 1746 

1747当 Bash 命令更改 Git 存储库中的文件时,Claude Code 可以记录更改的内容。当 [`bashEditDiffEnabled`](/docs/zh-CN/settings-reference#basheditdiffenabled) 设置打开记录时,它在每个权限模式中记录;该设置的条目说明哪些文件可以设置它。否则它仅在自动模式和 `bypassPermissions` 模式中记录,仅当 Claude Code 指导 Claude 通过 Bash 编辑文件时。设置 `bashEditDiffEnabled` 为 `false` 以关闭记录。后台命令和只读命令不携带 diff。

1748 

1749您的 [PostToolUse hook](#posttooluse) 然后在 `tool_response.bashEditDiff` 中接收更改的文件。列表涵盖命令运行时在存储库下更改的内容。Git 忽略的文件和子模块中的文件不被列出。需要 Claude Code v2.1.269 或更高版本。

1750 

1751<Note>

1752 列表是尽力而为的,处于公开测试版。Claude Code 可能会错过更改、包含另一个进程同时更改的文件,或在其大小限制处停止。字段形状可能会改变。使用列表查找要审查的内容,而不是强制执行策略。

1753</Note>

1754 

1755`changedFiles` 和 `files` 列出命令更改的内容;其余字段说明该列表的完整性和可靠性。

1756 

1757| 字段 | 类型 | 示例 | 描述 |

1758| :------------- | :------ | :------------------------------------------------------ | :----------------------------------------------------------------------- |

1759| `changedFiles` | array | `["/path/to/src/app.ts"]` | 命令更改的文件的绝对路径,最多 200 个。每当 `files` 保持 diff 或 `moreFiles` 高于零时出现 |

1760| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | 最多 5 个更改文件的 diffs,用于显示。对于命令添加或删除的文件,`created` 或 `deleted` 为 `true` |

1761| `moreFiles` | number | `2` | 在 `files` 中没有 diff 的更改文件的计数 |

1762| `unavailable` | boolean | `true` | 当 diff 不完整或无法获取时设置 |

1763| `skipped` | boolean | `true` | 对于移动工作树的 Git 命令设置,如 `git checkout` 或 `git stash`,因此 Claude Code 不获取 diff |

1764| `shared` | boolean | `true` | 当另一个 Bash 工具调用(如子 agent 的)同时在同一存储库中运行时设置,因此某些列出的更改可能是该命令的 |

1765 

1766<a id="powershell" />

1767 

1768<h5 id="powershell">

1769 PowerShell

1770</h5>

1771 

1772执行 PowerShell 命令。有关按平台的可用性,请参阅 [PowerShell 工具](/docs/zh-CN/tools-reference#powershell-tool)。

1773 

1774字段与 Bash 工具匹配,命令字符串在 `command` 中:

1775 

1776| 字段 | 类型 | 示例 | 描述 |

1777| :------------------ | :------ | :------------------------- | :----------------- |

1778| `command` | string | `"Get-ChildItem -Recurse"` | 要执行的 PowerShell 命令 |

1779| `description` | string | `"List files recursively"` | 命令执行操作的可选描述 |

1780| `timeout` | number | `120000` | 可选超时(毫秒) |

1781| `run_in_background` | boolean | `false` | 是否在后台运行命令 |

1782 

1783在检查 shell 命令的 hooks 中匹配 `Bash|PowerShell`,以便它们涵盖两个工具:

1784 

1785* 在 Windows 上,无论 PowerShell 工具在何处启用,Claude 都将 PowerShell 视为主 shell 并通过它路由 shell 命令。

1786* 在没有 Git Bash 的 Windows 上,工具自动启用,Claude Code 根本不注册 Bash 工具。

1787* 仅匹配 `Bash` 的 hook 永远不会在那里触发。

1788 

1473<h5 id="write">1789<h5 id="write">

1474 Write1790 Write

1475</h5>1791</h5>


1503| 字段 | 类型 | 示例 | 描述 |1819| 字段 | 类型 | 示例 | 描述 |

1504| :---------- | :----- | :-------------------- | :---------- |1820| :---------- | :----- | :-------------------- | :---------- |

1505| `file_path` | string | `"/path/to/file.txt"` | 要读取的文件的绝对路径 |1821| `file_path` | string | `"/path/to/file.txt"` | 要读取的文件的绝对路径 |

1506| `offset` | number | `10` | 可选的开始读取的行号 |1822| `offset` | number | `10` | 可选行号以开始读取 |

1507| `limit` | number | `50` | 可选的要读取的行数 |1823| `limit` | number | `50` | 可选要读取的行数 |

1508 1824 

1509<h5 id="glob">1825<h5 id="glob">

1510 Glob1826 Glob


1513查找与 glob 模式匹配的文件。1829查找与 glob 模式匹配的文件。

1514 1830 

1515| 字段 | 类型 | 示例 | 描述 |1831| 字段 | 类型 | 示例 | 描述 |

1516| :-------- | :----- | :--------------- | :---------------- |1832| :-------- | :----- | :--------------- | :----------------- |

1517| `pattern` | string | `"**/*.ts"` | 要匹配文件的 Glob 模式 |1833| `pattern` | string | `"**/*.ts"` | 要匹配文件的 glob 模式 |

1518| `path` | string | `"/path/to/dir"` | 可选的搜索目录。默认为当前工作目录 |1834| `path` | string | `"/path/to/dir"` | 可选要搜索的目录。默认为当前工作目录 |

1519 1835 

1520<h5 id="grep">1836<h5 id="grep">

1521 Grep1837 Grep


1526| 字段 | 类型 | 示例 | 描述 |1842| 字段 | 类型 | 示例 | 描述 |

1527| :------------ | :------ | :--------------- | :------------------------------------------------------------------------ |1843| :------------ | :------ | :--------------- | :------------------------------------------------------------------------ |

1528| `pattern` | string | `"TODO.*fix"` | 要搜索的正则表达式模式 |1844| `pattern` | string | `"TODO.*fix"` | 要搜索的正则表达式模式 |

1529| `path` | string | `"/path/to/dir"` | 可选的要搜索的文件或目录 |1845| `path` | string | `"/path/to/dir"` | 可选要搜索的文件或目录 |

1530| `glob` | string | `"*.ts"` | 可选的 glob 模式以过滤文件 |1846| `glob` | string | `"*.ts"` | 可选 glob 模式以过滤文件 |

1531| `output_mode` | string | `"content"` | `"content"`、`"files_with_matches"` 或 `"count"`。默认为 `"files_with_matches"` |1847| `output_mode` | string | `"content"` | `"content"`、`"files_with_matches"` 或 `"count"`。默认为 `"files_with_matches"` |

1532| `-i` | boolean | `true` | 不区分大小写的搜索 |1848| `-i` | boolean | `true` | 不区分大小写的搜索 |

1533| `multiline` | boolean | `false` | 启用多行匹配 |1849| `multiline` | boolean | `false` | 启用多行匹配 |


1536 WebFetch1852 WebFetch

1537</h5>1853</h5>

1538 1854 

1539获取和处理 web 内容。1855获取和处理网络内容。

1540 1856 

1541| 字段 | 类型 | 示例 | 描述 |1857| 字段 | 类型 | 示例 | 描述 |

1542| :------- | :----- | :---------------------------- | :----------- |1858| :------- | :----- | :---------------------------- | :----------- |

1543| `url` | string | `"https://example.com/api"` | 要获取内容的 URL |1859| `url` | string | `"https://example.com/api"` | 要从中获取内容的 URL |

1544| `prompt` | string | `"Extract the API endpoints"` | 在获取的内容上运行的提示 |1860| `prompt` | string | `"Extract the API endpoints"` | 在获取的内容上运行的提示 |

1545 1861 

1546<h5 id="websearch">1862<h5 id="websearch">


1559 Agent1875 Agent

1560</h5>1876</h5>

1561 1877 

1562生成一个[subagent](/docs/zh-CN/sub-agents)。1878生成 [子 agent](/docs/zh-CN/sub-agents)。

1563 1879 

1564| 字段 | 类型 | 示例 | 描述 |1880| 字段 | 类型 | 示例 | 描述 |

1565| :-------------- | :----- | :------------------------- | :------------ |1881| :-------------- | :----- | :------------------------- | :-------------- |

1566| `prompt` | string | `"Find all API endpoints"` | 代理要执行的任务 |1882| `prompt` | string | `"Find all API endpoints"` | agent 要执行的任务 |

1567| `description` | string | `"Find API endpoints"` | 任务的简短描述 |1883| `description` | string | `"Find API endpoints"` | 任务的简短描述 |

1568| `subagent_type` | string | `"Explore"` | 要使用的专门代理的类型 |1884| `subagent_type` | string | `"Explore"` | 要使用的专门 agent 类型 |

1569| `model` | string | `"sonnet"` | 可选的模型别名以覆盖默认值 |1885| `model` | string | `"sonnet"` | 可选模型别名以覆盖默认值 |

1570 1886 

1571在 `PostToolUse` 中,已完成的 Agent 调用的 `tool_response` 携带 subagent 的最终文本以及使用遥测。读取这些字段以从 hook 记录每个 subagent 的成本:1887当前台 Agent 调用完成时,您的 [PostToolUse hook](#posttooluse) 在 `tool_response` 中接收子 agent 的结果和运行遥测。读取这些字段以检查运行;对于跨子 agent 的令牌和成本汇总,使用 [令牌和成本计数器](/docs/zh-CN/monitoring-usage#token-counter) 过滤到 `query_source` `"subagent"`,因为 `totalTokens` 和 `usage` 仅涵盖最终请求:

1572 1888 

1573| 字段 | 类型 | 示例 | 描述 |1889| 字段 | 类型 | 示例 | 描述 |

1574| :------------------ | :----- | :---------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- |1890| :------------------ | :----- | :---------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- |

1575| `status` | string | `"completed"` | 前台 subagents 为 `"completed"`,后台 subagents 为 `"async_launched"`。从 v2.1.198 开始,subagents 默认在后台运行,因此省略的 `run_in_background` 也产生 `"async_launched"` |1891| `status` | string | `"completed"` | 前台子 agent 为 `"completed"`,后台子 agent 为 `"async_launched"`。从 v2.1.198 起,子 agent 默认在后台运行,因此省略的 `run_in_background` 也产生 `"async_launched"` |

1576| `agentId` | string | `"a4d2c8f1e0b3a297"` | subagent 运行的标识符 |1892| `agentId` | string | `"a4d2c8f1e0b3a297"` | 子 agent 运行的标识符 |

1577| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | subagent 的最终文本块 |1893| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | 子 agent 的最终文本块,或对于其报告通过 `SubagentHandback` 的子 agent,关于该交接的简短说明代替 |

1578| `resolvedModel` | string | `"claude-sonnet-4-5"` | subagent 运行的模型,可能与请求的模型不同。需要 Claude Code v2.1.174 或更高版本 |1894| `resolvedModel` | string | `"claude-sonnet-4-5"` | 子 agent 启动的模型,可能与请求的模型不同 |

1579| `totalTokens` | number | `12450` | 在 subagent 轮次中计费的总令牌数 |1895| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | 按顺序使用的模型,连续重复折叠;仅在模型在运行中交换时设置。需要 Claude Code v2.1.212 或更高版本 |

1580| `totalDurationMs` | number | `48211` | subagent 运行的挂钟时间 |1896| `totalTokens` | number | `12450` | 子 agent 最终 API 请求的令牌计数:输入、输出和缓存令牌合并。这不是整个运行的总计 |

1581| `totalToolUseCount` | number | `7` | subagent 进行的工具调用计数 |1897| `totalDurationMs` | number | `48211` | 子 agent 运行的挂钟持续时间 |

1582| `usage` | object | `{"input_tokens": 8320, ...}` | 按类型的令牌分解:`input_tokens`、`output_tokens`、`cache_creation_input_tokens`、`cache_read_input_tokens` |1898| `totalToolUseCount` | number | `7` | 子 agent 进行的工具调用计数 |

1899| `usage` | object | `{"input_tokens": 8320, ...}` | 最终 API 请求的每类型令牌分解:`input_tokens`、`output_tokens`、`cache_creation_input_tokens`、`cache_read_input_tokens` |

1583 1900 

1584对于后台 subagents,工具在启动 subagent 后立即返回,因此 `tool_response` 不携带使用字段。它具有 `status: "async_launched"`、`agentId`、`description`、`prompt`、`outputFile` 和 `resolvedModel`。1901在 Claude Code v2.1.271 或更高版本上,使用 [`SubagentHandback`](/docs/zh-CN/tools-reference) 工具运行的子 agent(Claude Code 在 [自动模式](/docs/zh-CN/permission-modes#eliminate-prompts-with-auto-mode) 中提供)通过该工具而不是作为文本返回其报告。其 `completed` 结果的 `content` 字段然后携带关于该交接的简短说明而不是报告本身。要读取报告,匹配 `PreToolUse` 或 `PostToolUse` hook 在 `SubagentHandback` 上并读取 `tool_input.message`。

1585 1902 

1586`resolvedModel` 字段命名 subagent 实际运行的模型,可能与 `tool_input` 中的 `model` 值不同。它需要 Claude Code v2.1.174 或更高版本。1903对于后台子 agent,工具在任务移到后台时返回,因此 `tool_response` 不携带使用字段:后台启动立即返回,前台任务在运行中被 Claude Code 后台化时返回。它有 `status: "async_launched"`、`agentId`、`description`、`prompt`、`outputFile` 和 `resolvedModel`。

1904 

1905在 `completed` 响应上,`resolvedModel` 命名子 agent 启动的模型,可能与 `tool_input` 中的 `model` 值不同,如 `availableModels` 或其他覆盖适用时。在 `async_launched` 响应上,`resolvedModel` 命名 agent 移到后台时使用的模型,因此在后台化之前发生的交换反映在那里。`modelsUsed` 和后台化时间 `resolvedModel` 行为需要 Claude Code v2.1.212 或更高版本。

1587 1906 

1588<a id="askuserquestion" />1907<a id="askuserquestion" />

1589 1908 


1595 1914 

1596| 字段 | 类型 | 示例 | 描述 |1915| 字段 | 类型 | 示例 | 描述 |

1597| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- |1916| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------- |

1598| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | 要呈现的问题,每个都有 `question` 字符串、短 `header`、`options` 数组和可选的 `multiSelect` 标志 |1917| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | 要呈现的问题,每个都有 `question` 字符串、简短 `header`、`options` 数组和可选 `multiSelect` 标志 |

1599| `answers` | object | `{"Which framework?": "React"}` | 可选。将问题文本映射到选定的选项标签。多选答案用逗号连接标签。Claude 不设置此字段;通过 `updatedInput` 提供它以以编程方式回答 |1918| `answers` | object | `{"Which framework?": "React"}` | 可选。将问题文本映射到选定的选项标签。多选答案用逗号连接标签。Claude 不设置此字段;通过 `updatedInput` 提供它以以编程方式回答 |

1600 1919 

1601<h5 id="exitplanmode">1920<h5 id="exitplanmode">

1602 ExitPlanMode1921 ExitPlanMode

1603</h5>1922</h5>

1604 1923 

1605呈现一个计划并要求用户在 Claude 离开[Plan Mode](/docs/zh-CN/permission-modes#analyze-before-you-edit-with-plan-mode)之前批准它。Claude 在调用工具之前将计划写入磁盘上的文件,因此来自模型的字面 `tool_input` 通常为空。Claude Code 在将输入传递给 hooks 之前注入计划内容和文件路径。1924呈现计划并要求用户在 Claude 离开 [plan mode](/docs/zh-CN/permission-modes#analyze-before-you-edit-with-plan-mode) 之前批准它。Claude 在调用工具之前将计划写入磁盘上的文件,因此来自模型的字面 `tool_input` 通常为空。Claude Code 在将输入传递给 hooks 之前注入计划内容和文件路径。

1606 1925 

1607| 字段 | 类型 | 示例 | 描述 |1926| 字段 | 类型 | 示例 | 描述 |

1608| :--------------- | :----- | :------------------------------------------ | :---------------------------------------------------------------- |1927| :--------------- | :----- | :------------------------------------------ | :----------------------------------------------------------------- |

1609| `plan` | string | `"## Refactor auth\n1. Extract..."` | Markdown 中的计划内容。从磁盘上的计划文件注入 |1928| `plan` | string | `"## Refactor auth\n1. Extract..."` | Markdown 中的计划内容。从磁盘上的计划文件注入 |

1610| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | 计划文件的路径。注入 |1929| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | 计划文件的路径。注入 |

1611| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | 已弃用。Claude Code 接受该字段但忽略它。在 v2.1.205 之前,它携带 Claude 请求实现计划的基于提示的权限 |1930| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | 已弃用。Claude Code 接受该字段但忽略它。在 v2.1.205 之前,它携带 Claude 请求以实现计划的基于提示的权限 |

1612 1931 

1613在 `PostToolUse` 中,`tool_response` 是一个对象,具有 `plan` 和 `filePath` 字段,保存批准的计划,加上内部状态标志。读取 `tool_response.plan` 以获取计划内容,而不是从磁盘重新读取文件。1932在 `PostToolUse` 中,`tool_response` 是一个包含 `plan` 和 `filePath` 字段的对象,保持批准的计划,加上内部状态标志。读取 `tool_response.plan` 以获取计划内容,而不是从磁盘重新读取文件。

1614 1933 

1615<h4 id="pretooluse-decision-control">1934<h4 id="pretooluse-decision-control">

1616 PreToolUse 决定控制1935 PreToolUse 决策控制

1617</h4>1936</h4>

1618 1937 

1619`PreToolUse` hooks 可以控制工具调用是否继续。与使用顶级 `decision` 字段的其他 hooks 不同,PreToolUse 在 `hookSpecificOutput` 对象内返回其决定。这给了它更丰富的控制:四个结果(允许、拒绝、询问或延迟)加上在执行前修改工具输入的能力。1938`PreToolUse` hooks 可以控制工具调用是否继续。与使用顶级 `decision` 字段的其他 hooks 不同,PreToolUse 在 `hookSpecificOutput` 对象内返回其决策。这给了它更丰富的控制:四个结果(允许、拒绝、询问或延迟)加上在执行前修改工具输入的能力。

1620 1939 

1621| 字段 | 描述 |1940| 字段 | 描述 |

1622| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1941| :------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

1623| `permissionDecision` | `"allow"` 绕过权限提示,除了[需要用户交互的工具](#pretooluse-decision-control)和连接器工具[您的组织设置为 `ask`](/docs/zh-CN/mcp#organization-controls-on-connector-tools)。`"deny"` 防止工具调用。`"ask"` 提示用户确认。`"defer"` 优雅地退出,以便工具稍后可以恢复。[拒绝和询问规则](/docs/zh-CN/permissions#manage-permissions)在 hook 返回什么时仍然被评估 |1942| `permissionDecision` | `"allow"` 跳过权限提示,除了 [任何模式自动批准的操作](/docs/zh-CN/permission-modes#actions-no-mode-auto-approves) 和对于 `AskUserQuestion` 和 `ExitPlanMode`,需要 [`updatedInput` 与其配对](#allow-with-updatedinput)。`"deny"` 防止工具调用。`"ask"` 提示用户确认。`"defer"` 优雅地退出以便工具稍后可以恢复。[拒绝和询问规则](/docs/zh-CN/permissions#manage-permissions) 仍然被评估,无论 hook 返回什么 |

1624| `permissionDecisionReason` | 对于 `"allow"` 和 `"ask"`,向用户显示但不向 Claude 显示。对于 `"deny"`,向 Claude 显示。对于 `"defer"`,被忽略 |1943| `permissionDecisionReason` | 对于 `"allow"` 和 `"ask"`,显示给用户但不显示给 Claude。对于 `"deny"`,显示给 Claude。对于 `"defer"`,被忽略 |

1625| `updatedInput` | 在执行前修改工具的输入参数。替换整个输入对象,因此包括未修改的字段以及修改后的字段。与 `"allow"` 结合以自动批准,或与 `"ask"` 结合以向用户显示修改后的输入。对于 `"defer"`,被忽略 |1944| `updatedInput` | 在执行前修改工具的输入参数。替换整个输入对象,因此在修改的输入旁边包含未更改的字段。Claude Code 根据您的 hook 返回的输入而不是 Claude 发送的输入评估权限规则和 Bash 命令的 [自动后台资格](/docs/zh-CN/tools-reference#background-commands)。与 `"allow"` 结合以自动批准,或与 `"ask"` 结合以向用户显示修改的输入。对于 `"defer"`,被忽略 |

1626| `additionalContext` | 在工具执行前添加到 Claude 上下文的字符串。对于 `"defer"`,被忽略。请参阅[为 Claude 添加上下文](#add-context-for-claude) |1945| `additionalContext` | 与工具结果一起添加到 Claude 上下文的字符串。当 `permissionDecision` 为 `"defer"` 时被忽略。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1946 

1947当多个 PreToolUse hooks 返回不同的决策时,优先级为 `deny` > `defer` > `ask` > `allow`。

1627 1948 

1628当多个 PreToolUse hooks 返回不同的决定时,优先级是 `deny` > `defer` > `ask` > `allow`。1949通过退出 2 阻止的 hook 路由方式与 `"deny"` 相同:Claude 看到 stderr 消息作为拒绝原因。

1629 1950 

1630当 hook 返回 `"ask"` 时,向用户显示的权限提示包括一个标签,标识 hook 来自何处:例如,`[User]`、`[Project]`、`[Plugin]` 或 `[Local]`。这帮助用户了解哪个配置源正在请求确认。1951当 hook 返回 `"ask"` 时,显示给用户的权限提示包括一个标签,标识 hook 来自何处:`[settings]` 对于来自任何设置文件或 agent frontmatter 的 hook,`[plugin:<name>]` 对于插件的 hook,或 `[skill]` 对于来自 skill frontmatter 的 hook。这帮助用户理解哪个配置源请求确认。

1952 

1953hook 的 `"ask"` 也在 [自动模式](/docs/zh-CN/permission-modes#eliminate-prompts-with-auto-mode) 中强制权限提示:分类器仍然可以拒绝工具调用,但它无法静默批准调用。在 v2.1.211 之前,分类器可以批准在 [沙箱](/docs/zh-CN/sandboxing) 外运行的 Bash 命令而不显示 hook 请求的提示;分类器仍然对该命令应用了自己的安全规则,hook `"deny"` 总是被尊重。

1631 1954 

1632```json theme={null}1955```json theme={null}

1633{1956{


1643}1966}

1644```1967```

1645 1968 

1646`AskUserQuestion` 和 `ExitPlanMode` 需要用户交互,通常在[非交互模式](/docs/zh-CN/headless)中使用 `-p` 标志时阻止。返回 `permissionDecision: "allow"` 以及 `updatedInput` 满足该要求:hook 从 stdin 读取工具的输入,通过您自己的 UI 收集答案,并在 `updatedInput` 中返回它,以便工具运行而不提示。仅返回 `"allow"` 对这些工具不足够。对于 `AskUserQuestion`,回显原始 `questions` 数组并添加一个[`answers`](#askuserquestion)对象,将每个问题的文本映射到选定的答案。1969<span id="allow-with-updatedinput" />

1647 1970 

1648连接器工具[您的组织设置为 `ask`](/docs/zh-CN/mcp#organization-controls-on-connector-tools)即使 hook 返回 `"allow"` 也会提示。1971在 [非交互模式](/docs/zh-CN/headless) 中使用 `-p` 标志,Claude Code 仅在运行有 [权限主机](/docs/zh-CN/headless#turn-off-permission-prompts-in-unattended-runs) 来接收提示时提供 `AskUserQuestion` 和 `ExitPlanMode`,如 Agent SDK `canUseTool` 回调。这些工具需要用户交互。返回 `permissionDecision: "allow"` 与 `updatedInput` 一起满足该要求:hook 从 stdin 读取工具的输入,通过您自己的 UI 收集答案,并在 `updatedInput` 中返回它,以便工具运行而不提示。仅返回 `"allow"` 对这些工具不充分。对于 `AskUserQuestion`,回显原始 `questions` 数组并添加一个 [`answers`](#askuserquestion) 对象,将每个问题的文本映射到选定的答案。

1649 1972 

1650从 v2.1.199 开始,一个 MCP 工具,其服务器用 [`_meta["anthropic/requiresUserInteraction"]`](/docs/zh-CN/mcp#require-approval-for-a-specific-tool) 标记它,更严格:hook 不能用 `"allow"` 跳过其批准提示,无论是否有 `updatedInput`,因为 Claude Code 无法确认 hook 收集了工具需要的交互。1973从 v2.1.199 起,其服务器用 [`_meta["anthropic/requiresUserInteraction"]`](/docs/zh-CN/mcp#require-approval-for-a-specific-tool) 标记的 MCP 工具更严格:hook 无法用 `"allow"` 跳过其批准提示,无论是否有 `updatedInput`,因为 Claude Code 无法确认 hook 收集了工具需要的交互。

1651 1974 

1652<Note>1975<Note>

1653 PreToolUse 之前使用顶级 `decision` 和 `reason` 字段,但这些对此事件已弃用。改用 `hookSpecificOutput.permissionDecision` 和 `hookSpecificOutput.permissionDecisionReason`。已弃用的值 `"approve"` 和 `"block"` 映射到 `"allow"` 和 `"deny"`。PostToolUse 和 Stop 等其他事件继续使用顶级 `decision` 和 `reason` 作为其当前格式。1976 PreToolUse 之前使用顶级 `decision` 和 `reason` 字段,但这些对此事件已弃用。改用 `hookSpecificOutput.permissionDecision` 和 `hookSpecificOutput.permissionDecisionReason`。已弃用的值 `"approve"` 和 `"block"` 映射到 `"allow"` 和 `"deny"` 分别。PostToolUse 和 Stop 等其他事件继续使用顶级 `decision` 和 `reason` 作为其当前格式。

1654</Note>1977</Note>

1655 1978 

1656<h4 id="defer-a-tool-call-for-later">1979<h4 id="defer-a-tool-call-for-later">

1657 延迟工具调用以供稍后使用1980 延迟工具调用以供稍后使用

1658</h4>1981</h4>

1659 1982 

1660`"defer"` 用于运行 `claude -p` 作为子进程并读取其 JSON 输出的集成,例如 Agent SDK 应用或构建在 Claude Code 之上的自定义 UI。它让该调用进程在工具调用处暂停 Claude,通过其自己的界面收集输入,并从中断处恢复。Claude Code 仅在[非交互模式](/docs/zh-CN/headless)中使用 `-p` 标志时遵守此值。在交互式会话中,它记录警告并忽略 hook 结果。1983`"defer"` 用于运行 `claude -p` 作为子进程并读取其 JSON 输出的集成,如 Agent SDK 应用或构建在 Claude Code 之上的自定义 UI。它让该调用进程在工具调用处暂停 Claude,通过其自己的界面收集输入,并从中断处恢复。Claude Code 仅在 [非交互模式](/docs/zh-CN/headless) 中使用 `-p` 标志时尊重此值。在交互式会话中,它记录警告并忽略 hook 结果。

1661 1984 

1662`AskUserQuestion` 工具是典型情况:Claude 想要询问用户一些事情,但没有终端来回答。往返工作如下:1985`AskUserQuestion` 工具是典型情况:Claude 想问用户什么,但没有终端来回答。`-p` 运行仅在有 [权限主机](/docs/zh-CN/headless#turn-off-permission-prompts-in-unattended-runs) 时提供 `AskUserQuestion`,如您使用 `--permission-prompt-tool` 传递的 MCP 工具,因此使用一个启动运行。往返工作如下:

1663 1986 

16641. Claude 调用 `AskUserQuestion`。`PreToolUse` hook 触发。19871. Claude 调用 `AskUserQuestion`。`PreToolUse` hook 触发。

16652. Hook 返回 `permissionDecision: "defer"`。工具不执行。进程以 `stop_reason: "tool_deferred"` 退出,待处理的工具调用保留在成绩单中。19882. hook 返回 `permissionDecision: "defer"`。工具不执行。进程以 `stop_reason: "tool_deferred"` 退出,待处理的工具调用保留在成绩单中。

16663. 调用进程从 SDK 结果读取 `deferred_tool_use`,在其自己的 UI 中显示问题,并等待答案。19893. 调用进程从 SDK 结果读取 `deferred_tool_use`,在其自己的 UI 中呈现问题,并等待答案。

16674. 调用进程运行 `claude -p --resume <session-id>`。相同的工具调用再次触发 `PreToolUse`。19904. 调用进程运行 `claude -p --resume <session-id>`,带有相同的权限主机。相同的工具调用再次触发 `PreToolUse`。

16685. Hook 返回 `permissionDecision: "allow"` 和 `updatedInput` 中的答案。工具执行,Claude 继续。19915. hook 返回 `permissionDecision: "allow"`,答案在 `updatedInput` 中。工具执行,Claude 继续。

1669 1992 

1670`deferred_tool_use` 字段携带工具的 `id`、`name` 和 `input`。`input` 是 Claude 为工具调用生成的参数,在执行前捕获:1993`deferred_tool_use` 字段携带工具的 `id`、`name` 和 `input`。`input` 是 Claude 为工具调用生成的参数,在执行前捕获:

1671 1994 


1683}2006}

1684```2007```

1685 2008 

1686没有超时或重试限制。会话保留在磁盘上,直到您恢复它,受到 [`cleanupPeriodDays`](/docs/zh-CN/settings#available-settings) 保留扫描的约束,该扫描默认在 30 天后删除会话文件。如果恢复时答案还没有准备好,hook 可以再次返回 `"defer"`,进程以相同的方式退出。调用进程控制何时通过最终返回 `"allow"` 或 `"deny"` 从 hook 中断循环。2009没有超时或重试限制。会话保留在磁盘上直到您恢复它,受 [`cleanupPeriodDays`](/docs/zh-CN/settings-reference#cleanupperioddays) 保留扫描的约束,默认情况下在 30 天后删除会话文件,遵循 [保留扫描规则](/docs/zh-CN/claude-directory#cleaned-up-automatically)。如果答案在您恢复时还没有准备好,hook 可以再次返回 `"defer"`,进程以相同的方式退出。调用进程通过最终从 hook 返回 `"allow"` 或 `"deny"` 来控制何时打破循环。

1687 2010 

1688`"defer"` 仅在 Claude 在轮次中进行单个工具调用时有效。如果 Claude 一次进行多个工具调用,`"defer"` 被忽略并显示警告,工具通过正常权限流程进行。约束存在是因为恢复只能重新运行一个工具:没有办法延迟一个调用而不留下其他调用未解决。2011`"defer"` 仅在 Claude 在回合中进行单个工具调用时有效。如果 Claude 一次进行多个工具调用,`"defer"` 被忽略并显示警告,工具通过正常权限流程进行。约束存在是因为恢复只能重新运行一个工具:没有办法延迟批次中的一个调用而不留下其他未解决的。

1689 2012 

1690如果恢复时延迟的工具不再可用,进程以 `stop_reason: "tool_deferred_unavailable"` 和 `is_error: true` 退出,在 hook 触发之前。这发生在为恢复的会话未连接提供工具的 MCP 服务器时。`deferred_tool_use` 有效负载仍然包括,以便您可以识别哪个工具丢失。2013如果恢复时延迟的工具不再可用,进程以 `stop_reason: "tool_deferred_unavailable"` 和 `is_error: true` 退出,hook 触发前。这发生在为恢复的会话未连接提供工具的 MCP 服务器时。`deferred_tool_use` 有效负载仍然包含,以便您可以识别哪个工具丢失。

1691 2014 

1692<Note>2015<Note>

1693 `--resume` 恢复工具被延迟时活跃的权限模式,因此您不需要再次传递 `--permission-mode`。例外是 `plan` 和 `bypassPermissions`,它们永远不会被携带。在恢复时显式传递 `--permission-mode` 会覆盖恢复的值。2016 要在 plan mode 中恢复延迟会话,请与 `--resume` 一起传递 [`--permission-prompt-tool`](/docs/zh-CN/cli-reference#cli-flags),以便 Claude Code 可以呈现计划以供批准。没有它,Claude Code 不会恢复 plan mode。需要 Claude Code v2.1.246 或更高版本。

2017 

2018 当您使用 `-p` 恢复时,Claude Code 不会恢复任何其他存储的权限模式。它启动运行在新 `claude -p` 运行会启动的权限模式中,因此如果延迟会话使用了一个,请再次传递 `--permission-mode` 或 `--dangerously-skip-permissions`。当您使用 `claude --resume <session-id>` 恢复而不使用 `-p` 时,Claude Code 恢复存储的权限模式,除了 [恢复时的权限模式](/docs/zh-CN/sessions#permission-mode-on-resume) 中列出的例外。

1694</Note>2019</Note>

1695 2020 

1696<h3 id="permissionrequest">2021<h3 id="permissionrequest">

1697 PermissionRequest2022 PermissionRequest

1698</h3>2023</h3>

1699 2024 

1700在向用户显示权限对话框时运行。使用[PermissionRequest 决定控制](#permissionrequest-decision-control)代表用户允许或拒绝。2025在 Claude Code 即将要求您许可使用工具时运行。在无法显示提示的会话中,如 [非交互模式](/docs/zh-CN/headless) 中的后台子 agent,Claude Code 仍然运行这些 hooks,如果没有 hook 返回决策,它拒绝工具调用。

2026使用 [PermissionRequest 决策控制](#permissionrequest-decision-control) 代表用户允许或拒绝。

1701 2027 

1702在工具名称上匹配,与 PreToolUse 相同的值。2028当您需要在 Claude 要求许可使用工具时立即获得信号时使用此事件。Claude Code 仅在提示等待约六秒后运行 [Notification](#notification) hook,其中 `permission_prompt` 类型。

2029 

2030Claude Code 不为沙箱命令的 [网络请求](/docs/zh-CN/sandboxing#network-isolation) 运行 PermissionRequest hooks。要获得该提示的信号,请使用 `permission_prompt` 通知类型。

2031 

2032匹配工具名称,与 PreToolUse 相同的值。

1703 2033 

1704<h4 id="permissionrequest-input">2034<h4 id="permissionrequest-input">

1705 PermissionRequest 输入2035 PermissionRequest 输入

1706</h4>2036</h4>

1707 2037 

1708PermissionRequest hooks 接收 `tool_name` 和 `tool_input` 字段,如 PreToolUse hooks,但没有 `tool_use_id`。可选的 `permission_suggestions` 数组包含用户通常在权限对话框中看到的"总是允许"选项。区别在于 hook 何时触发:PermissionRequest hooks 在权限对话框即将显示给用户时运行,而 PreToolUse hooks 在工具执行前运行,无论权限状态如何。2038PermissionRequest hooks 接收 `tool_name` 和 `tool_input` 字段,如 PreToolUse hooks,但没有 `tool_use_id`。对于 MCP 工具,它们也接收 [`mcp_server`](#pretooluse-input) 对象。可选的 `permission_suggestions` 数组包含 Claude Code 为此请求建议的 [权限更新](#permission-update-entries),如添加允许规则或更改权限模式。

2039 

2040`permission_suggestions` 数组不是您看到的选项的精确列表,因为每个权限对话构建自己的选项。某些对话(如文件编辑的对话)根本不读取数组,并从请求本身派生其选项。读取它的对话仍然可以保留一个选项,其建议保留在数组中,例如当 [`allowManagedPermissionRulesOnly`](/docs/zh-CN/settings-reference#allowmanagedpermissionrulesonly) 隐藏规则保存选项时。它也可以提供没有建议条目的选项,如 [**Yes, and switch to auto mode**](/docs/zh-CN/permission-modes#switch-permission-modes),它直接更改权限模式而不是通过权限更新。

2041 

2042PreToolUse hooks 在每个工具调用之前运行,无论它是否需要权限。PermissionRequest hooks 仅在 Claude Code 即将要求您许可时运行,或当它否则会自动拒绝无法提示的调用时。两个事件都不为 [`EndConversation`](/docs/zh-CN/tools-reference#endconversation-tool-behavior) 触发。

1709 2043 

1710```json theme={null}2044```json theme={null}

1711{2045{


1731```2065```

1732 2066 

1733<h4 id="permissionrequest-decision-control">2067<h4 id="permissionrequest-decision-control">

1734 PermissionRequest 决定控制2068 PermissionRequest 决策控制

1735</h4>2069</h4>

1736 2070 

1737`PermissionRequest` hooks 可以允许或拒绝权限请求。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您的 hook 脚本可以返回一个 `decision` 对象,其中包含这些事件特定字段:2071`PermissionRequest` hooks 可以允许或拒绝权限请求。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您的 hook 脚本可以返回一个 `decision` 对象,其中包含这些事件特定的字段:

1738 2072 

1739| 字段 | 描述 |2073| 字段 | 描述 |

1740| :------------------- | :------------------------------------------------------------------------------------------------------------------ |2074| :------------------- | :------------------------------------------------------------------------------------------------------------------- |

1741| `behavior` | `"allow"` 授予权限,`"deny"` 拒绝它。[拒绝和询问规则](/docs/zh-CN/permissions#manage-permissions)仍然被评估,所以返回 `"allow"` 的 hook 不会覆盖匹配的拒绝规则 |2075| `behavior` | `"allow"` 授予权限,`"deny"` 拒绝它。[拒绝和询问规则](/docs/zh-CN/permissions#manage-permissions) 仍然被评估,因此返回 `"allow"` 的 hook 不会覆盖匹配的拒绝规则 |

1742| `updatedInput` | 仅对 `"allow"`:在执行前修改工具的输入参数。替换整个输入对象,因此包括未修改的字段以及修改后的字段。修改后的输入会重新针对拒绝和询问规则进行评估 |2076| `updatedInput` | 仅对 `"allow"`:在执行前修改工具的输入参数。替换整个输入对象,因此在修改的输入旁边包含未更改的字段。修改的输入针对拒绝和询问规则重新评估 |

1743| `updatedPermissions` | 仅对 `"allow"`:应用权限规则更新的[权限更新条目](#permission-update-entries)数组,例如添加允许规则或更改会话权限模式 |2077| `updatedPermissions` | 仅对 `"allow"`:[权限更新条目](#permission-update-entries) 数组以应用,如添加允许规则或更改会话权限模式 |

1744| `message` | 仅对 `"deny"`:告诉 Claude 为什么权限被拒绝 |2078| `message` | 仅对 `"deny"`:告诉 Claude 为什么权限被拒绝 |

1745| `interrupt` | 仅对 `"deny"`:如果为 `true`,停止 Claude |2079| `interrupt` | 仅对 `"deny"`:如果 `true`,停止 Claude |

2080 

2081不带 `decision` 对象退出 2 的 hook 保持权限流程不变,其 stderr 被丢弃。仅 `decision` 对象可以授予或拒绝请求。

1746 2082 

1747```json theme={null}2083```json theme={null}

1748{2084{


1762 权限更新条目2098 权限更新条目

1763</h4>2099</h4>

1764 2100 

1765`updatedPermissions` 输出字段和[`permission_suggestions` 输入字段](#permissionrequest-input)都使用相同的条目对象数组。每个条目都有一个 `type` 来确定其其他字段,以及一个 `destination` 来控制更改的写入位置。2101`updatedPermissions` 输出字段和 [`permission_suggestions` 输入字段](#permissionrequest-input) 都使用相同的条目对象数组。每个条目有一个 `type` 来确定其他字段,以及一个 `destination` 来控制更改写入的位置。

1766 2102 

1767| `type` | 字段 | 效果 |2103| `type` | 字段 | 效果 |

1768| :------------------ | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |2104| :------------------ | :------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- |

1769| `addRules` | `rules`、`behavior`、`destination` | 添加权限规则。`rules` 是 `{toolName, ruleContent?}` 对象的数组。省略 `ruleContent` 以匹配整个工具。`behavior` 是 `"allow"`、`"deny"` 或 `"ask"` |2105| `addRules` | `rules`、`behavior`、`destination` | 添加权限规则。`rules` 是 `{toolName, ruleContent?}` 对象的数组。省略 `ruleContent` 以匹配整个工具。`behavior` 是 `"allow"`、`"deny"` 或 `"ask"` |

1770| `replaceRules` | `rules`、`behavior`、`destination` | 用提供的 `rules` 替换 `destination` 处给定 `behavior` 的所有规则 |2106| `replaceRules` | `rules`、`behavior`、`destination` | 用提供的 `rules` 替换 `destination` 处给定 `behavior` 的所有规则 |

1771| `removeRules` | `rules`、`behavior`、`destination` | 移除给定 `behavior` 的匹配规则 |2107| `removeRules` | `rules`、`behavior`、`destination` | 删除给定 `behavior` 的匹配规则 |

1772| `setMode` | `mode`、`destination` | 更改权限模式。有效模式为 `default`、`auto`、`acceptEdits`、`dontAsk`、`bypassPermissions`、`plan` 和 `manual` 作为 `default` 的别名。`manual` 别名需要 Claude Code v2.1.200 或更高版本 |2108| `setMode` | `mode`、`destination` | 更改权限模式。有效模式为 `default`、`auto`、`acceptEdits`、`dontAsk`、`bypassPermissions`、`plan` 和 `manual` 作为 `default` 的别名。`manual` 别名需要 Claude Code v2.1.200 或更高版本 |

1773| `addDirectories` | `directories`、`destination` | 添加工作目录。`directories` 是路径字符串的数组 |2109| `addDirectories` | `directories`、`destination` | 添加工作目录。`directories` 是路径字符串的数组 |

1774| `removeDirectories` | `directories`、`destination` | 移除工作目录 |2110| `removeDirectories` | `directories`、`destination` | 删除工作目录 |

1775 2111 

1776<Note>2112<Note>

1777 `setMode` 与 `bypassPermissions` 仅在会话已启动时生效,绕过模式已可用:`--dangerously-skip-permissions`、`--permission-mode bypassPermissions`、`--allow-dangerously-skip-permissions` 或设置中的 `permissions.defaultMode: "bypassPermissions"`,且模式未被 [`permissions.disableBypassPermissionsMode`](/docs/zh-CN/permissions#managed-settings) 禁用。否则更新是无操作。`bypassPermissions` 无论 `destination` 如何都永远不会作为 `defaultMode` 持久化。2113 `setMode` 与 `bypassPermissions` 仅在您已经使用 bypass mode 启动会话时生效:`--dangerously-skip-permissions`、`--permission-mode bypassPermissions`、`--allow-dangerously-skip-permissions` 或 [用户、`--settings` 或托管设置](/docs/zh-CN/settings-reference#permissions-defaultmode) 中的 `permissions.defaultMode: "bypassPermissions"`。否则更新是无操作。当 [`permissions.disableBypassPermissionsMode`](/docs/zh-CN/permissions#managed-settings) 禁用模式或会话在 [受限模式](/docs/zh-CN/cli-reference#cli-flags) 中启动时,更新也是无操作。

2114 

2115 `bypassPermissions` 永远不会作为 `defaultMode` 持久化,无论 `destination` 如何。

1778</Note>2116</Note>

1779 2117 

1780每个条目上的 `destination` 字段确定更改是保留在内存中还是持久化到设置文件。2118每个条目上的 `destination` 字段确定更改是保留在内存中还是持久化到设置文件。


1786| `projectSettings` | `.claude/settings.json` |2124| `projectSettings` | `.claude/settings.json` |

1787| `userSettings` | `~/.claude/settings.json` |2125| `userSettings` | `~/.claude/settings.json` |

1788 2126 

1789Hook 可以回显它接收的 `permission_suggestions` 之一作为其自己的 `updatedPermissions` 输出,这等同于用户在对话框中选择该"总是允许"选项。2127hook 可以回显它接收的 `permission_suggestions` 之一作为其自己的 `updatedPermissions` 输出。

1790 2128 

1791<h3 id="posttooluse">2129<h3 id="posttooluse">

1792 PostToolUse2130 PostToolUse


1794 2132 

1795在工具成功完成后立即运行。2133在工具成功完成后立即运行。

1796 2134 

1797在工具名称上匹配,与 PreToolUse 相同的值。2135匹配工具名称,与 PreToolUse 相同的值。

2136 

2137当工具名称不是正确的过滤器时更广泛地匹配:

2138 

2139* 要在任何工具成功完成后运行 hook,省略 `matcher` 或将其设置为 `"*"`。您的 hook 然后可以自己发现更改了什么,例如通过运行 `git status --porcelain`,它也列出 `git diff` 错过的未跟踪文件。对于失败的工具调用,在 [PostToolUseFailure](#posttoolusefailure) 下添加相同的 hook。

2140* 要在特定文件更改时运行 hook,无论什么写入它,请使用 [FileChanged](#filechanged)。当 `Bash` 命令或 Claude Code 外的进程重写同一文件时,Claude Code 不运行匹配 `Edit|Write` 的 `PostToolUse` hook。

1798 2141 

1799<h4 id="posttooluse-input">2142<h4 id="posttooluse-input">

1800 PostToolUse 输入2143 PostToolUse 输入

1801</h4>2144</h4>

1802 2145 

1803`PostToolUse` hooks 在工具已经成功执行后触发。输入包括 `tool_input`(发送给工具的参数)和 `tool_response`(它返回的结果)。两者的确切架构取决于工具。2146`PostToolUse` hooks 在工具已经成功执行后触发。输入包括 `tool_input`(发送给工具的参数)和 `tool_response`(它返回的结果)。两者的确切模式取决于工具。文件工具 `tool_input` 路径以与 [PreToolUse](#pretooluse-input) 相同的格式到达:始终绝对,带有平台的本机分隔符,因此 Windows 上的反斜杠。对于 MCP 工具,输入也携带 [`mcp_server`](#pretooluse-input) 对象。

1804 2147 

1805```json theme={null}2148```json theme={null}

1806{2149{


1816 },2159 },

1817 "tool_response": {2160 "tool_response": {

1818 "filePath": "/path/to/file.txt",2161 "filePath": "/path/to/file.txt",

1819 "success": true2162 "type": "create"

1820 },2163 },

1821 "tool_use_id": "toolu_01ABC123...",2164 "tool_use_id": "toolu_01ABC123...",

1822 "duration_ms": 122165 "duration_ms": 12


1828| `duration_ms` | 可选。工具执行时间(毫秒)。不包括权限提示和 PreToolUse hooks 中花费的时间 |2171| `duration_ms` | 可选。工具执行时间(毫秒)。不包括权限提示和 PreToolUse hooks 中花费的时间 |

1829 2172 

1830<h4 id="posttooluse-decision-control">2173<h4 id="posttooluse-decision-control">

1831 PostToolUse 决定控制2174 PostToolUse 决策控制

1832</h4>2175</h4>

1833 2176 

1834`PostToolUse` hooks 可以在工具执行后向 Claude 提供反馈。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您的 hook 脚本可以返回这些事件特定字段:2177`PostToolUse` hooks 可以在工具执行后提供反馈给 Claude。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您的 hook 脚本可以返回这些事件特定的字段:

1835 2178 

1836| 字段 | 描述 |2179| 字段 | 描述 |

1837| :--------------------- | :------------------------------------------------------------------------- |2180| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |

1838| `decision` | `"block"` 用 `reason` 提示 Claude。Claude 仍然看到原始输出;要替换它,使用 `updatedToolOutput` |2181| `decision` | `"block"` 在工具结果旁边添加 `reason`。Claude 仍然看到原始输出;要替换它,请使用 `updatedToolOutput` |

1839| `reason` | 当 `decision` 为 `"block"` 时向 Claude 显示的解释 |2182| `reason` | 当 `decision` 为 `"block"` 时显示给 Claude 的解释 |

1840| `additionalContext` | 添加到 Claude 上下文的字符串,与工具结果一起。请参阅[为 Claude 添加上下文](#add-context-for-claude) |2183| `additionalContext` | 与工具结果一起添加到 Claude 上下文的字符串。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1841| `updatedToolOutput` | 用提供的值替换工具的输出,然后将其发送给 Claude。该值必须与工具的输出形状匹配 |2184| `classifierContext` | 关于此调用结果的简短说明,用于 [自动模式](/docs/zh-CN/permission-modes#eliminate-prompts-with-auto-mode) 分类器而不是 Claude。有关详细信息,请参阅 [为自动模式分类器注释结果](#annotate-a-result-for-the-auto-mode-classifier)。需要 Claude Code v2.1.236 或更高版本 |

1842| `updatedMCPToolOutput` | 仅对[MCP 工具](#match-mcp-tools)替换输出。优先使用 `updatedToolOutput`,它适用于所有工具 |2185| `updatedToolOutput` | 在将工具的输出发送给 Claude 之前用提供的值替换它。该值必须与工具的输出形状匹配 |

2186| `updatedMCPToolOutput` | 仅替换 [MCP 工具](#match-mcp-tools) 的输出。优先使用 `updatedToolOutput`,它适用于所有工具 |

1843 2187 

1844下面的示例替换 `Bash` 调用的输出。替换值与 `Bash` 工具的输出形状匹配:2188下面的示例替换 `Bash` 调用的输出。替换值与 `Bash` 工具的输出形状匹配:

1845 2189 


1859```2203```

1860 2204 

1861<Warning>2205<Warning>

1862 `updatedToolOutput` 仅改变 Claude 看到的内容。工具已经在 hook 触发时运行,所以任何写入的文件、执行的命令或发送的网络请求都已生效。遥测,如 OpenTelemetry 工具跨度和分析事件,也在 hook 运行前捕获原始输出。要在运行前防止或修改工具调用,请改用[PreToolUse](#pretooluse) hook。2206 `updatedToolOutput` 仅更改 Claude 看到的内容。工具已经在 hook 触发时运行,因此任何写入的文件、执行的命令或发送的网络请求已经生效。遥测如 OpenTelemetry 工具跨度和分析事件也在 hook 运行之前捕获原始输出。要在运行前防止或修改工具调用,请改用 [PreToolUse](#pretooluse) hook。

2207 

2208 替换值必须与工具的输出形状匹配。内置工具返回结构化对象而不是纯字符串。例如,`Bash` 返回一个带有 `stdout`、`stderr`、`interrupted` 和 `isImage` 字段的对象。对于内置工具,不与工具的输出模式匹配的值被忽略,使用原始输出。MCP 工具输出通过而不进行模式验证。剥离 Claude 需要的错误详情可能导致它基于错误的假设继续。

2209</Warning>

2210 

2211<h4 id="annotate-a-result-for-the-auto-mode-classifier">

2212 为自动模式分类器注释结果

2213</h4>

2214 

2215返回 `classifierContext` 以向 [自动模式](/docs/zh-CN/permission-modes#eliminate-prompts-with-auto-mode) 分类器发送关于工具调用结果的简短说明,而不是向 Claude。分类器 [永远不会接收工具结果本身](/docs/zh-CN/permission-modes#how-the-classifier-evaluates-actions),因此此字段是告诉它在审查后续操作之前关于调用返回的内容的支持方式。该字段需要 Claude Code v2.1.236 或更高版本。

2216 

2217下面的示例告诉分类器查询的输出来自何处:

2218 

2219```json theme={null}

2220{

2221 "hookSpecificOutput": {

2222 "hookEventName": "PostToolUse",

2223 "classifierContext": "This query ran against the staging database, not production."

2224 }

2225}

2226```

2227 

2228分类器给予说明的权重取决于您配置 hook 的位置:

2229 

2230* **在 Claude Code 中配置的 Hooks**:对于来自设置文件、插件、skills 和 agent frontmatter 的 hooks,分类器将说明视为未验证的、应用提供的上下文。说明永远不会建立用户意图,如果它声称您批准或请求了什么,分类器会根据您在对话中的自己的消息检查该声明

2231* **进程内 Agent SDK 回调**:当应用嵌入 Claude Code 将 hook 注册为 [TypeScript SDK 回调](/docs/zh-CN/agent-sdk/hooks) 并在实时会话期间返回说明时,分类器可能会将用户声明中继的说明视为用户意图。这样的声明可以满足分类器会接受来自您发送的消息的同意要求,但它永远不会解除您自己的消息也无法解除的阻止。会话恢复后,Claude Code 将恢复的说明视为未验证的上下文。当来自两个组的 hooks 注释同一调用时,分类器将组合说明视为未验证

2232 

2233Claude Code 在传递说明时应用这些限制:

1863 2234 

1864 替换值必须与工具的输出形状匹配。内置工具返回结构化对象而不是纯字符串。例如,`Bash` 返回一个具有 `stdout`、`stderr`、`interrupted` 和 `isImage` 字段的对象。对于内置工具,不与工具的输出架构匹配的值被忽略,使用原始输出。MCP 工具输出通过而不进行架构验证。剥离 Claude 需要的错误详细信息可能导致它基于错误的假设继续。2235* **长度**:Claude Code 将一个工具调用的说明上限为 2,000 个字符,并截断其余部分。上限在响应该调用的每个 hook 中共享

2236* **仅同步响应**:Claude Code 忽略 [在后台运行](#run-hooks-in-the-background) 的 hook 响应中的字段,因为该响应在 Claude Code 记录工具结果后到达

2237* **分类器不记录的调用**:分类器的成绩单省略只读查找如文件读取和搜索。Claude Code 丢弃附加到其中一个调用的说明

2238* **与重写的交互**:当说明描述您用 `updatedToolOutput` 替换的输出时,在同一 hook 响应中返回两个字段。如果该重写被拒绝或另一个 hook 的重写替换它,Claude Code 丢弃说明。Claude Code 传递您返回的说明而不重写,即使另一个 hook 重写输出

2239 

2240<Warning>

2241 分类器读取您放在 `classifierContext` 中的内容作为来自托管会话的应用的信息,因此不要将不受信任的工具输出或第三方文本复制到其中。将说明保持为关于此一个调用的简短断言,如关于其来源的事实或关于它的用户声明;不要使用该字段传递不相关的消息或事件流。

1865</Warning>2242</Warning>

1866 2243 

1867<h3 id="posttoolusefailure">2244<h3 id="posttoolusefailure">

1868 PostToolUseFailure2245 PostToolUseFailure

1869</h3>2246</h3>

1870 2247 

1871当工具执行失败时运行:工具抛出错误,或 MCP 工具返回错误结果。使用此来记录失败、发送警报或向 Claude 提供纠正反馈。2248在启动执行的工具失败时运行:工具抛出错误,或 MCP 工具返回错误结果。使用此来记录失败、发送警报或向 Claude 提供纠正反馈。

1872 2249 

1873在工具名称上匹配,与 PreToolUse 相同的值。2250匹配工具名称,与 PreToolUse 相同的值。

1874 2251 

1875<Note>2252<Note>

1876 此事件不对工具调用在执行前被拒绝时触发:未知工具名称、输入失败架构或工具特定验证,或权限拒绝。验证拒绝作为 `tool_use_error` 结果返回,在 hooks 运行之前发生,因此它们既不触发 `PreToolUse` 也不触发此事件。权限拒绝触发 `PreToolUse` 但不触发此事件;请参阅[PermissionDenied](#permissiondenied)。2253 此事件不为执行前被拒绝的工具调用触发:未知工具名称、失败模式或工具特定验证的输入,或权限拒绝。验证拒绝作为 `tool_use_error` 结果返回,发生在 hooks 运行之前,因此它们既不触发 `PreToolUse` 也不触发此事件。权限拒绝触发 `PreToolUse` 但不触发此事件;请参阅 [PermissionDenied](#permissiondenied)。

1877</Note>2254</Note>

1878 2255 

1879<h4 id="posttoolusefailure-input">2256<h4 id="posttoolusefailure-input">

1880 PostToolUseFailure 输入2257 PostToolUseFailure 输入

1881</h4>2258</h4>

1882 2259 

1883PostToolUseFailure hooks 接收与 PostToolUse 相同的 `tool_name` 和 `tool_input` 字段,以及作为顶级字段的错误信息:2260PostToolUseFailure hooks 接收与 PostToolUse 相同的 `tool_name` 和 `tool_input` 字段,以及错误信息作为顶级字段。对于 MCP 工具,它们也接收 [`mcp_server`](#pretooluse-input) 对象。例如,失败的 `npm test` 命令可能传递:

1884 2261 

1885```json theme={null}2262```json theme={null}

1886{2263{


1895 "description": "Run test suite"2272 "description": "Run test suite"

1896 },2273 },

1897 "tool_use_id": "toolu_01ABC123...",2274 "tool_use_id": "toolu_01ABC123...",

1898 "error": "Command exited with non-zero status code 1",2275 "error": "Exit code 1\nError: Cannot find module 'express'",

1899 "is_interrupt": false,2276 "is_interrupt": false,

1900 "duration_ms": 41872277 "duration_ms": 4187

1901}2278}

1902```2279```

1903 2280 

1904| 字段 | 描述 |2281| 字段 | 描述 |

1905| :------------- | :--------------------------------------------- |2282| :------------- | :------------------------------------------------------------------------ |

1906| `error` | 描述出错原因的字符串 |2283| `error` | 描述出错内容的字符串。格式取决于失败的工具 |

1907| `is_interrupt` | 可选的布尔值,指示失败是否由用户中断引起 |2284| `is_interrupt` | 可选布尔值。当失败作为中止而不是工具报告的错误到达 Claude Code 时为 True。取消运行的工具不触发此 hook;工具结果携带中断消息 |

1908| `duration_ms` | 可选。工具执行时间(毫秒)。不包括权限提示和 PreToolUse hooks 中花费的时间 |2285| `duration_ms` | 可选。工具执行时间(毫秒)。不包括权限提示和 PreToolUse hooks 中花费的时间 |

1909 2286 

2287`error` 字符串通常与 Claude 接收的失败工具结果相同的文本。其格式因工具和失败而异。在 `tool_name`、`is_interrupt` 和第一行 `Exit code N` 上键入您的 hook;将字符串的其余部分视为显示文本,而不是稳定格式。

2288 

2289* 对于 Bash 和 PowerShell,运行并退出的命令产生第一行 `Exit code N`,然后是命令产生的任何输出作为一个块,stdout 和 stderr 交错

2290* 有效负载也可能携带裸失败消息,没有退出代码行,当 Claude Code 无法启动 shell 进程本身时

2291* Claude Code 中间截断长字符串,围绕 `... [N characters truncated] ...` 标记,并可以插入自己的行,如 `Command timed out after 2m 0s`

2292 

1910<h4 id="posttoolusefailure-decision-control">2293<h4 id="posttoolusefailure-decision-control">

1911 PostToolUseFailure 决定控制2294 PostToolUseFailure 决策控制

1912</h4>2295</h4>

1913 2296 

1914`PostToolUseFailure` hooks 可以在工具失败后向 Claude 提供上下文。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您的 hook 脚本可以返回这些事件特定字段:2297`PostToolUseFailure` hooks 可以在工具失败后向 Claude 提供上下文。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您的 hook 脚本可以返回这些事件特定的字段:

1915 2298 

1916| 字段 | 描述 |2299| 字段 | 描述 |

1917| :------------------ | :-------------------------------------------------------------------- |2300| :------------------ | :-------------------------------------------------------------------------------------- |

1918| `additionalContext` | 添加到 Claude 上下文的字符串,与错误一起。请参阅[为 Claude 添加上下文](#add-context-for-claude) |2301| `additionalContext` | 与错误一起添加到 Claude 上下文的字符串。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1919 2302 

1920```json theme={null}2303```json theme={null}

1921{2304{


1930 PostToolBatch2313 PostToolBatch

1931</h3>2314</h3>

1932 2315 

1933在批次中的每个工具调用都已解决后运行一次,在 Claude Code 向模型发送下一个请求之前。`PostToolUse` 每个工具触发一次,这意味着当 Claude 进行并行工具调用时它并发触发。`PostToolBatch` 恰好触发一次,包含完整批次,因此它是注入取决于运行的工具集而不是任何单个工具的上下文的正确位置。此事件没有匹配器。2316在批次中的每个工具调用都已解决后运行一次,在 Claude Code 向模型发送下一个请求之前。`PostToolUse` 每个工具运行一次,这意味着当 Claude 进行并行工具调用时它并发运行。`PostToolBatch` 恰好运行一次,带有完整批次,因此它是注入取决于运行的工具集而不是任何单个工具的上下文的正确位置。此事件没有匹配器。

1934 2317 

1935<h4 id="posttoolbatch-input">2318<h4 id="posttoolbatch-input">

1936 PostToolBatch 输入2319 PostToolBatch 输入

1937</h4>2320</h4>

1938 2321 

1939除了[通用输入字段](#common-input-fields)外,PostToolBatch hooks 还接收 `tool_calls`,一个描述批次中每个工具调用的数组:2322除了 [常见输入字段](#common-input-fields) 外,PostToolBatch hooks 接收 `tool_calls`,一个描述批次中每个工具调用的数组:

1940 2323 

1941```json theme={null}2324```json theme={null}

1942{2325{


1962}2345}

1963```2346```

1964 2347 

1965`tool_response` 包含与模型在相应 `tool_result` 块中接收的内容相同的内容。该值是序列化的字符串或内容块数组,完全如工具发出的那样。对于 `Read`,这意味着行号前缀的文本而不是原始文件内容。响应可能很大,因此仅解析您需要的字段。2348`tool_response` 包含模型在相应 `tool_result` 块中接收的相同内容。该值是序列化的字符串或内容块数组,完全如工具发出的一样。对于 `Read`,这意味着行号前缀的文本而不是原始文件内容。响应可能很大,因此仅解析您需要的字段。

1966 2349 

1967<Note>2350<Note>

1968 `tool_response` 形状与 `PostToolUse` 的不同。`PostToolUse` 传递工具的结构化 `Output` 对象,例如 `{filePath: "...", success: true}` 对于 `Write`;`PostToolBatch` 传递序列化的 `tool_result` 内容模型看到的。2351 `tool_response` 形状与 `PostToolUse` 的不同。`PostToolUse` 传递工具的结构化 `Output` 对象,如 `Write` 的 `{filePath: "...", type: "create"}`;`PostToolBatch` 传递模型看到的序列化 `tool_result` 内容。

1969</Note>2352</Note>

1970 2353 

1971<h4 id="posttoolbatch-decision-control">2354<h4 id="posttoolbatch-decision-control">

1972 PostToolBatch 决定控制2355 PostToolBatch 决策控制

1973</h4>2356</h4>

1974 2357 

1975`PostToolBatch` hooks 可以为 Claude 注入上下文。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您的 hook 脚本可以返回这些事件特定字段:2358`PostToolBatch` hooks 可以为 Claude 注入上下文。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您的 hook 脚本可以返回这些事件特定的字段:

1976 2359 

1977| 字段 | 描述 |2360| 字段 | 描述 |

1978| :------------------ | :------------------------------------------------------------------------------------------- |2361| :------------------ | :------------------------------------------------------------------------------------------------ |

1979| `additionalContext` | 在下一个模型调用之前注入的上下文字符串。请参阅[为 Claude 添加上下文](#add-context-for-claude)了解传递详情、放入什么内容以及恢复的会话如何处理过去的值 |2362| `additionalContext` | 在下一个模型调用之前注入一次的上下文字符串。有关传递详情、放入其中的内容以及恢复的会话如何处理过去的值,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

1980 2363 

1981```json theme={null}2364```json theme={null}

1982{2365{


1987}2370}

1988```2371```

1989 2372 

1990返回 `decision: "block"` 或 `continue: false` 在下一个模型调用之前停止代理循环。2373返回 `decision: "block"` 或 `continue: false` 在下一个模型调用之前停止 agentic 循环。阻止消息来自 JSON `reason` 或 `stopReason`,或来自退出 2 时的 stderr。您在成绩单中看到它作为警告,它保留在对话中,因此 Claude 在对话继续时看到它。

1991 2374 

1992<h3 id="permissiondenied">2375<h3 id="permissiondenied">

1993 PermissionDenied2376 PermissionDenied

1994</h3>2377</h3>

1995 2378 

1996当[自动模式](/docs/zh-CN/permission-modes#eliminate-prompts-with-auto-mode)分类器拒绝工具调用时运行。此 hook 仅在自动模式中触发:当您手动拒绝权限对话框、`PreToolUse` hook 阻止调用或 `deny` 规则匹配时,它不运行。使用它来记录分类器拒绝、调整配置或告诉模型它可能重试工具调用。2379在 [自动模式](/docs/zh-CN/permission-modes#eliminate-prompts-with-auto-mode) 拒绝工具调用时运行,包括当它拒绝而没有分类器判决时,因为 [与自动模式分开的安全检查拒绝了分类器自己的请求](/docs/zh-CN/errors#auto-mode-cannot-determine-the-safety-of-an-action) 或其响应没有解析。此 hook 仅在自动模式中触发:当您手动拒绝权限对话、`PreToolUse` hook 阻止调用或 `deny` 规则匹配时不运行。使用它来记录拒绝、调整配置或告诉模型它可能重试工具调用。

1997 2380 

1998在工具名称上匹配,与 PreToolUse 相同的值。2381匹配工具名称,与 PreToolUse 相同的值。

1999 2382 

2000<h4 id="permissiondenied-input">2383<h4 id="permissiondenied-input">

2001 PermissionDenied 输入2384 PermissionDenied 输入

2002</h4>2385</h4>

2003 2386 

2004除了[通用输入字段](#common-input-fields)外,PermissionDenied hooks 还接收 `tool_name`、`tool_input`、`tool_use_id` 和 `reason`。2387除了 [常见输入字段](#common-input-fields) 外,PermissionDenied hooks 接收 `tool_name`、`tool_input`、`tool_use_id` 和 `reason`。对于 MCP 工具,它们也接收 [`mcp_server`](#pretooluse-input) 对象。

2005 2388 

2006```json theme={null}2389```json theme={null}

2007{2390{


2016 "description": "Clean build directory"2399 "description": "Clean build directory"

2017 },2400 },

2018 "tool_use_id": "toolu_01ABC123...",2401 "tool_use_id": "toolu_01ABC123...",

2019 "reason": "Auto mode denied: command targets a path outside the project"2402 "reason": "[Irreversible Local Destruction]"

2020}2403}

2021```2404```

2022 2405 

2023| 字段 | 描述 |2406| 字段 | 描述 |

2024| :------- | :----------------- |2407| :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

2025| `reason` | 分类器解释为什么工具调用被拒绝的原因 |2408| `reason` | 拒绝原因。对于分类器判决,在大多数会话中它命名方括号中的匹配规则,如 `[Data Exfiltration]`;有关其他形式,请参阅 [审查拒绝](/docs/zh-CN/auto-mode-config#review-denials)。对于 [无判决拒绝](#permissiondenied-decision-control),它以 `Auto mode could not evaluate this action and is blocking it for safety` 开头。对于因分类器模型不可用而拒绝,它是固定文本 `Classifier unavailable` |

2026 2409 

2027<h4 id="permissiondenied-decision-control">2410<h4 id="permissiondenied-decision-control">

2028 PermissionDenied 决定控制2411 PermissionDenied 决策控制

2029</h4>2412</h4>

2030 2413 

2031PermissionDenied hooks 可以告诉模型它可能重试被拒绝的工具调用。返回一个 JSON 对象,其中 `hookSpecificOutput.retry` 设置为 `true`:2414PermissionDenied hooks 可以告诉模型它可能重试被拒绝的工具调用。返回一个 JSON 对象,其中 `hookSpecificOutput.retry` 设置为 `true`:


2039}2422}

2040```2423```

2041 2424 

2042当 `retry` 为 `true` 时,Claude Code 向对话添加一条消息,告诉模型它可能重试工具调用。拒绝本身不被反转。如果您的 hook 不返回 JSON,或返回 `retry: false`,拒绝成立,模型接收原始拒绝消息。2425当 `retry` 为 `true` 时,Claude Code 向对话添加一条消息,告诉模型它可能重试工具调用。Claude Code 不反转拒绝本身。如果您的 hook 不返回 JSON,或返回 `retry: false`,拒绝成立,模型接收原始拒绝消息。

2426 

2427当分类器对操作产生 [无判决](/docs/zh-CN/errors#auto-mode-cannot-determine-the-safety-of-an-action) 时,Claude Code 忽略 `retry: true`:其响应没有解析,或与自动模式分开的安全检查拒绝了分类器自己的请求。对于这些拒绝,Claude Code 已经在拒绝消息中告诉模型是否稍后重试或继续。

2043 2428 

2044<h3 id="notification">2429<h3 id="notification">

2045 Notification2430 Notification

2046</h3>2431</h3>

2047 2432 

2048在 Claude Code 发送通知时运行。在通知类型上匹配。省略匹配器以为所有通知类型运行 hooks。2433在 Claude Code 发送通知时运行。匹配通知类型。省略匹配器以对所有通知类型运行 hooks。

2434 

2435您即使在关闭桌面通知时也接收这些 hook 事件:`preferredNotifChannel` 设置,包括 `notifications_disabled`,仅更改您如何被警告,而不是您的 hook 是否运行。

2049 2436 

2050| 匹配器 | 何时触发 |2437| 匹配器 | 何时触发 |

2051| :--------------------- | :------------------------------------------------ |2438| :--------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

2052| `permission_prompt` | Claude 需要您批准工具使用 |2439| `permission_prompt` | Claude 需要您批准工具使用或沙箱命令的 [网络请求](/docs/zh-CN/sandboxing#network-isolation),提示已等待约六秒 |

2053| `idle_prompt` | Claude 完成并等待您的下一个提示 |2440| `idle_prompt` | Claude 约 60 秒前完成响应,您自那以后没有输入 |

2054| `auth_success` | 身份验证完成 |2441| `auth_success` | 身份验证完成 |

2055| `elicitation_dialog` | MCP 服务器打开引出表单 |2442| `elicitation_dialog` | MCP 服务器打开引出表单,您约六秒没有输入 |

2056| `elicitation_complete` | MCP 引出表单被提交或关闭 |2443| `elicitation_url_dialog` | MCP 服务器要求您打开浏览器 URL,您约六秒没有输入 |

2444| `elicitation_complete` | MCP 服务器报告 [URL 模式引出](#elicitation-input) 完成 |

2057| `elicitation_response` | MCP 引出响应被发送回服务器 |2445| `elicitation_response` | MCP 引出响应被发送回服务器 |

2058| `agent_needs_input` | 后台会话开始等待您的输入。仅在[代理视图](/docs/zh-CN/agent-view)在终端中打开时触发 |2446| `agent_needs_input` | 后台会话在 [agent view](/docs/zh-CN/agent-view) 在终端中打开时开始等待您的输入,或当前会话询问您 [agent team](/docs/zh-CN/agent-teams) 队友的终端设置问题,您约六秒没有输入 |

2059| `agent_completed` | 后台会话完成或失败。仅在[代理视图](/docs/zh-CN/agent-view)在终端中打开时触发 |2447| `agent_completed` | 后台会话完成或失败。仅在 [agent view](/docs/zh-CN/agent-view) 在终端中打开时触发 |

2448| `quota_auto_resume_fired` | Claude Code 在 claude.ai 使用限制暂停您的任务后继续它:在重置时,或更早当您在 Claude Code 中做的事情,如添加使用额度、升级您的计划或切换模型,使使用再次可用时,带有 [模型设置异常](/docs/zh-CN/interactive-mode#wait-for-a-usage-limit-to-reset) |

2449| `quota_auto_resume_stale` | claude.ai 使用限制在您的计算机睡眠超过约 30 分钟时重置。Claude Code 等待您按 `Enter` 而不是继续。在更短的睡眠后它继续并改为触发 `quota_auto_resume_fired` |

2450| `quota_auto_resume_disabled` | Claude Code 结束其对 claude.ai 使用限制的等待而不继续您的任务:[`autoContinueAtUsageLimit`](/docs/zh-CN/settings-reference#autocontinueatusagelimit) 关闭或重置在 Claude Code 自己启动的等待期间移动超过 24 小时,继续的任务继续命中限制,或继续在到达模型之前被阻止。当您按 `Esc` 或 `Ctrl+C` 或选择 **Don't continue automatically** 时不触发 |

2060 2451 

2061`agent_needs_input` 和 `agent_completed` 类型需要 Claude Code v2.1.198 或更高版本。2452`agent_needs_input` 和 `agent_completed` 类型需要 Claude Code v2.1.198 或更高版本。

2062 2453 

2454`quota_auto_resume_fired`、`quota_auto_resume_stale` 和 `quota_auto_resume_disabled` 类型需要 Claude Code v2.1.234 或更高版本。

2455 

2456在终端会话中,沙箱命令的网络请求的 `permission_prompt` 需要 Claude Code v2.1.246 或更高版本。

2457 

2458队友的终端设置问题的 `agent_needs_input` 需要 Claude Code v2.1.248 或更高版本。

2459 

2460<Note>

2461 `permission_prompt`、`idle_prompt`、`elicitation_dialog` 和 `elicitation_url_dialog` 类型与桌面通知共享其时序,因此在终端会话中您仅在您似乎远离终端时看到它们:

2462 

2463 * 期望 `permission_prompt` 一旦您约六秒没有输入。计时器在权限提示出现时启动,每次按键推迟它。要在 Claude 要求许可使用工具时立即运行 hook,请改用 [PermissionRequest](#permissionrequest)。

2464 * 期望 `idle_prompt` 约 60 秒后 Claude 完成响应,仅当您自那以后没有输入时。Claude Code 在等待 claude.ai 使用限制重置时不发送 `idle_prompt`。当等待自己结束时,其中一个 `quota_auto_resume_*` 类型触发。

2465 * 期望 `elicitation_dialog` 用于引出表单,或 `elicitation_url_dialog` 用于浏览器 URL 请求,一旦您约六秒没有输入。两者共享与 `permission_prompt` 相同的六秒门:计时器在对话出现时启动,每次按键推迟它。

2466 

2467 在另一个对话在屏幕上时到达的权限请求或引出保持相同的六秒门,从请求到达时计时。其通知可以在请求仍然等待时到达,同时打开的对话仍然在屏幕上。

2468</Note>

2469 

2470Claude Code 在会话中以不同方式计时 `permission_prompt`,其中它向 Agent SDK 的 [`canUseTool` 回调](/docs/zh-CN/agent-sdk/user-input) 发送权限请求,这是 Claude Desktop 和 VS Code 扩展如何托管 Claude Code 的方式:

2471 

2472* 期望 `permission_prompt` 约六秒后 Claude 要求许可。Claude Code 在您输入时不推迟它。

2473* 如果您或 [PermissionRequest](#permissionrequest) hook 更早回答,Claude Code 不运行 `permission_prompt`。

2474* 设置 [`CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS`](/docs/zh-CN/env-vars) 为 `1` 以在这些会话中关闭 `permission_prompt`。

2475 

2476在 v2.1.233 之前,`permission_prompt` 在这些会话中不触发。

2477 

2063使用单独的匹配器根据通知类型运行不同的处理程序。此配置在 Claude 需要权限批准时触发权限特定的警报脚本,在 Claude 空闲时触发不同的通知:2478使用单独的匹配器根据通知类型运行不同的处理程序。此配置在 Claude 需要权限批准时触发权限特定的警报脚本,在 Claude 空闲时触发不同的通知:

2064 2479 

2065```json theme={null}2480```json theme={null}


2093 Notification 输入2508 Notification 输入

2094</h4>2509</h4>

2095 2510 

2096除了[通用输入字段](#common-input-fields)外,Notification hooks 还接收 `message` 和通知文本、可选的 `title` 和 `notification_type` 指示哪个类型触发。2511除了 [常见输入字段](#common-input-fields) 外,Notification hooks 接收 `message` 与通知文本、可选 `title` 和 `notification_type` 指示哪个类型触发。

2097 2512 

2098```json theme={null}2513```json theme={null}

2099{2514{


2107}2522}

2108```2523```

2109 2524 

2110Notification hooks 无法阻止或修改通知。它们用于副作用,例如将通知转发到外部服务。[通用 JSON 输出字段](#json-output)如 `systemMessage` 适用。2525Notification hooks 无法阻止或修改通知。Claude Code 丢弃它们的 `systemMessage` 和 `continue` 字段,但仍然发出 [`terminalSequence`](#emit-terminal-notifications),这是桌面通知示例所依赖的。Notification hooks 用于副作用,如将通知转发到外部服务。

2111 2526 

2112<h3 id="subagentstart">2527<h3 id="subagentstart">

2113 SubagentStart2528 SubagentStart

2114</h3>2529</h3>

2115 2530 

2116当通过 Agent 工具生成 Claude Code subagent 时运行。支持匹配器以按代理类型名称过滤。对于内置代理,这是代理名称,如 `general-purpose`、`Explore` 或 `Plan`。对于[自定义 subagents](/docs/zh-CN/sub-agents),这是代理 frontmatter 中的 `name` 字段,而不是文件名。2531在 Claude 使用 Agent 工具生成子 agent 时运行,当 Claude [恢复子 agent](/docs/zh-CN/sub-agents#resume-subagents) 时,以及每次进程内 [agent team](/docs/zh-CN/agent-teams) 队友处理新消息时。支持匹配器以按 agent 类型名称过滤。对于内置 agent,这是 agent 名称如 `general-purpose`、`Explore` 或 `Plan`。对于 [自定义子 agent](/docs/zh-CN/sub-agents),这是 agent 的 frontmatter 中的 `name` 字段,而不是文件名。

2117 2532 

2118对于由[插件](/docs/zh-CN/plugins)提供的 subagents,代理类型是插件范围的标识符,例如 `my-plugin:reviewer`,而不是裸 frontmatter 名称。冒号将插件范围的名称放在正则表达式路径上,因此使用 `^` 和 `$` 锚定匹配器以进行精确匹配:`^my-plugin:reviewer$`。2533对于由 [插件](/docs/zh-CN/plugins) 提供的子 agent,agent 类型是插件范围的标识符如 `my-plugin:reviewer`,而不是裸 frontmatter 名称。冒号将插件范围的名称放在正则表达式路径上,因此用 `^` 和 `$` 锚定匹配器以获得精确匹配:`^my-plugin:reviewer$`。

2119 2534 

2120<h4 id="subagentstart-input">2535<h4 id="subagentstart-input">

2121 SubagentStart 输入2536 SubagentStart 输入

2122</h4>2537</h4>

2123 2538 

2124除了[通用输入字段](#common-input-fields)外,SubagentStart hooks 还接收 `agent_id` 和 subagent 的唯一标识符以及 `agent_type` 和代理名称(匹配器过滤的值)。2539除了 [常见输入字段](#common-input-fields) 外,SubagentStart hooks 接收 `agent_id` 与子 agent 的唯一标识符和 `agent_type` 与匹配器过滤的 agent 名称。

2125 2540 

2126```json theme={null}2541```json theme={null}

2127{2542{


2134}2549}

2135```2550```

2136 2551 

2137SubagentStart hooks 无法阻止 subagent 创建,但它们可以向 subagent 注入上下文。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您可以返回:2552SubagentStart hooks 无法阻止子 agent 创建,但它们可以向子 agent 注入上下文。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您可以返回:

2138 2553 

2139| 字段 | 描述 |2554| 字段 | 描述 |

2140| :------------------ | :----------------------------------------------------------------------------- |2555| :------------------ | :--------------------------------------------------------------------------------------------------------- |

2141| `additionalContext` | 添加到 subagent 上下文开始处的字符串,在其第一个提示之前。请参阅[为 Claude 添加上下文](#add-context-for-claude) |2556| `additionalContext` | 在子 agent 对话开始时添加到子 agent 上下文的字符串,在其第一个提示之前。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

2142 2557 

2143```json theme={null}2558```json theme={null}

2144{2559{


2149}2564}

2150```2565```

2151 2566 

2567当 hook 再次为同一子 agent 运行时,Claude Code 仅在子 agent 的上下文还不包含来自早期运行的副本时注入返回的上下文。在启动时注入的副本保留在位置,保持子 agent 的 [prompt cache](/docs/zh-CN/prompt-caching#subagents-and-the-cache) 完整。在 [自动压缩](/docs/zh-CN/sub-agents#auto-compaction) 丢弃该副本后,Claude Code 再次注入下一个运行的上下文。

2568 

2152<h3 id="subagentstop">2569<h3 id="subagentstop">

2153 SubagentStop2570 SubagentStop

2154</h3>2571</h3>

2155 2572 

2156当 Claude Code subagent 完成响应时运行。在代理类型上匹配,与 SubagentStart 相同的值。2573在 Claude Code 子 agent 完成响应时运行。匹配 agent 类型,与 SubagentStart 相同的值。

2157 2574 

2158<h4 id="subagentstop-input">2575<h4 id="subagentstop-input">

2159 SubagentStop 输入2576 SubagentStop 输入

2160</h4>2577</h4>

2161 2578 

2162除了[通用输入字段](#common-input-fields)外,SubagentStop hooks 还接收 `stop_hook_active`、`agent_id`、`agent_type`、`agent_transcript_path` 和 `last_assistant_message`。`agent_type` 字段是用于匹配器过滤的值。`transcript_path` 是主会话的成绩单,而 `agent_transcript_path` 是 subagent 自己的成绩单,存储在嵌套的 `subagents/` 文件夹中。`last_assistant_message` 字段包含 subagent 最终响应的文本内容,因此 hooks 可以访问它而无需解析成绩单文件。2579除了 [常见输入字段](#common-input-fields) 外,SubagentStop hooks 接收 `stop_hook_active`、`agent_id`、`agent_type`、`agent_transcript_path` 和 `last_assistant_message`。`agent_type` 字段是用于匹配器过滤的值。`transcript_path` 是主会话的成绩单,而 `agent_transcript_path` 是子 agent 自己的成绩单,存储在嵌套 `subagents/` 文件夹中。`last_assistant_message` 字段包含子 agent 最终响应的文本内容,因此 hooks 可以访问它而无需解析成绩单文件。

2580 

2581在 Claude Code v2.1.271 或更高版本上,使用 [`SubagentHandback`](/docs/zh-CN/tools-reference) 工具运行的子 agent 在停止之前通过该工具传递其报告。`last_assistant_message` 字段然后保持子 agent 的结束文本(如果有),这不是传递的报告。报告是该调用的 `message` 输入,`PreToolUse` 或 `PostToolUse` hook 匹配 `SubagentHandback` 接收为 `tool_input.message`。

2163 2582 

2164SubagentStop hooks 还接收 [Stop input](#stop-input) 中描述的 `background_tasks` 和 `session_crons` 数组,在 Claude Code v2.1.145 或更高版本中可用。两个数组都限定于父会话,而不是 subagent。2583SubagentStop hooks 也接收 [Stop 输入](#stop-input) 下描述的 `background_tasks` 和 `session_crons` 数组。两个数组都限定于父会话,而不是子 agent。

2165 2584 

2166```json theme={null}2585```json theme={null}

2167{2586{


2180}2599}

2181```2600```

2182 2601 

2183SubagentStop hooks 使用与[Stop hooks](#stop-decision-control)相同的决定控制格式,包括 `hookSpecificOutput.additionalContext` 和 `hookEventName` 设置为 `"SubagentStop"`,用于非错误反馈以保持 subagent 运行。返回 `decision: "block"` 和 `reason` 保持 subagent 运行并将 `reason` 作为其下一个指令传递给 subagent。要在 subagent 返回后向父会话注入上下文,请改用 `Agent` 工具上的[`PostToolUse`](#posttooluse) hook。2602SubagentStop hooks 使用与 [Stop hooks](#stop-decision-control) 相同的决策控制格式,包括 `hookSpecificOutput.additionalContext`,其中 `hookEventName` 设置为 `"SubagentStop"`,用于保持子 agent 运行的非错误反馈。返回 `decision: "block"` 与 `reason` 保持子 agent 运行并将 `reason` 作为其下一个指令传递给子 agent。通过退出 2 阻止的 hook 以相同方式传递其 stderr 消息。要在子 agent 返回后向父会话注入上下文,请改用 `Agent` 工具上的 [`PostToolUse`](#posttooluse) hook。

2184 2603 

2185<h3 id="taskcreated">2604<h3 id="taskcreated">

2186 TaskCreated2605 TaskCreated

2187</h3>2606</h3>

2188 2607 

2189当通过 `TaskCreate` 工具创建任务时运行。使用此来强制执行命名约定、要求任务描述或防止创建某些任务。2608在通过 `TaskCreate` 工具创建任务时运行。使用此来强制命名约定、要求任务描述或防止某些任务被创建。在 [没有 Task 工具的会话](/docs/zh-CN/tools-reference#task-tool-availability) 中,此事件不触发。

2190 2609 

2191当 `TaskCreated` hook 以代码 2 退出时,任务不被创建,stderr 消息作为反馈反馈给模型。要完全停止队友而不是重新运行它,返回 JSON `{"continue": false, "stopReason": "..."}` 。TaskCreated hooks 不支持匹配器,在每次出现时触发。2610TaskCreated hooks 不支持匹配器,对每个出现触发。

2192 2611 

2193<h4 id="taskcreated-input">2612<h4 id="taskcreated-input">

2194 TaskCreated 输入2613 TaskCreated 输入

2195</h4>2614</h4>

2196 2615 

2197除了[通用输入字段](#common-input-fields)外,TaskCreated hooks 还接收 `task_id`、`task_subject` 和可选的 `task_description`、`teammate_name` 和 `team_name`。2616除了 [常见输入字段](#common-input-fields) 外,TaskCreated hooks 接收 `task_id`、`task_subject` 和可选的 `task_description`、`teammate_name` 和 `team_name`。

2198 2617 

2199```json theme={null}2618```json theme={null}

2200{2619{

2201 "session_id": "abc123",2620 "session_id": "abc123",

2202 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",2621 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2203 "cwd": "/Users/...",2622 "cwd": "/Users/...",

2204 "permission_mode": "default",

2205 "hook_event_name": "TaskCreated",2623 "hook_event_name": "TaskCreated",

2206 "task_id": "task-001",2624 "task_id": "task-001",

2207 "task_subject": "Implement user authentication",2625 "task_subject": "Implement user authentication",


2213 2631 

2214| 字段 | 描述 |2632| 字段 | 描述 |

2215| :----------------- | :---------------------- |2633| :----------------- | :---------------------- |

2216| `task_id` | 被创建的任务的标识符 |2634| `task_id` | 正在创建的任务的标识符 |

2217| `task_subject` | 任务的标题 |2635| `task_subject` | 任务的标题 |

2218| `task_description` | 任务的详细描述。可能不存在 |2636| `task_description` | 任务的详细描述。可能不存在 |

2219| `teammate_name` | 创建任务的队友的名称。可能不存在 |2637| `teammate_name` | 创建任务的队友的名称。可能不存在 |

2220| `team_name` | 已弃用。会话派生的团队名称;将在未来版本中删除 |2638| `team_name` | 已弃用。会话派生的团队名称;将在未来版本中删除 |

2221 2639 

2222<h4 id="taskcreated-decision-control">2640<h4 id="taskcreated-decision-control">

2223 TaskCreated 决定控制2641 TaskCreated 决策控制

2224</h4>2642</h4>

2225 2643 

2226TaskCreated hooks 支持两种方式来控制任务创建:2644TaskCreated hook 可以通过两种方式阻止创建。任一方式,Claude Code 删除任务并将您的消息作为工具的错误返回给 Claude。Claude Code 忽略此事件的 `continue: false`,Claude 继续工作。

2227 2645 

2228* **退出代码 2**:任务不被创建,stderr 消息作为反馈反馈给模型。2646* **退出代码 2**:Claude Code 将 stderr 文本作为消息返回。

2229* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止队友,匹配 `Stop` hook 行为。`stopReason` 向用户显示。2647* **JSON `{"decision": "block", "reason": "..."}`**:Claude Code 将 `reason` 作为消息返回。

2230 2648 

2231此示例阻止主题不遵循所需格式的任务:2649此示例阻止主题不遵循所需格式的任务:

2232 2650 


2247 TaskCompleted2665 TaskCompleted

2248</h3>2666</h3>

2249 2667 

2250当任务被标记为已完成时运行。这在两种情况下触发:当任何代理通过 TaskUpdate 工具显式标记任务为已完成时,或当[代理团队](/docs/zh-CN/agent-teams)队友完成其轮次且有进行中的任务时。使用此来强制执行完成标准,如通过测试或 lint 检查,然后任务才能关闭。2668在任务被标记为完成时运行。这在两种情况下触发:当任何 agent 通过 TaskUpdate 工具显式标记任务为完成时,或当 [agent team](/docs/zh-CN/agent-teams) 队友完成其回合时有进行中的任务。使用此来强制完成标准,如通过测试或 lint 检查,然后任务才能关闭。

2251 2669 

2252当 `TaskCompleted` hook 以代码 2 退出时,任务不被标记为已完成,stderr 消息作为反馈反馈给模型。要完全停止队友而不是重新运行它,返回 JSON `{"continue": false, "stopReason": "..."}` 。TaskCompleted hooks 不支持匹配器,在每次出现时触发。2670TaskCompleted hooks 不支持匹配器,对每个出现触发。

2253 2671 

2254<h4 id="taskcompleted-input">2672<h4 id="taskcompleted-input">

2255 TaskCompleted 输入2673 TaskCompleted 输入

2256</h4>2674</h4>

2257 2675 

2258除了[通用输入字段](#common-input-fields)外,TaskCompleted hooks 还接收 `task_id`、`task_subject` 和可选的 `task_description`、`teammate_name` 和 `team_name`。2676除了 [常见输入字段](#common-input-fields) 外,TaskCompleted hooks 接收 `task_id`、`task_subject` 和可选的 `task_description`、`teammate_name` 和 `team_name`。

2259 2677 

2260```json theme={null}2678```json theme={null}

2261{2679{


2274 2692 

2275| 字段 | 描述 |2693| 字段 | 描述 |

2276| :----------------- | :---------------------- |2694| :----------------- | :---------------------- |

2277| `task_id` | 被完成的任务的标识符 |2695| `task_id` | 正在完成的任务的标识符 |

2278| `task_subject` | 任务的标题 |2696| `task_subject` | 任务的标题 |

2279| `task_description` | 任务的详细描述。可能不存在 |2697| `task_description` | 任务的详细描述。可能不存在 |

2280| `teammate_name` | 完成任务的队友的名称。可能不存在 |2698| `teammate_name` | 完成任务的队友的名称。可能不存在 |

2281| `team_name` | 已弃用。会话派生的团队名称;将在未来版本中删除 |2699| `team_name` | 已弃用。会话派生的团队名称;将在未来版本中删除 |

2282 2700 

2283<h4 id="taskcompleted-decision-control">2701<h4 id="taskcompleted-decision-control">

2284 TaskCompleted 决定控制2702 TaskCompleted 决策控制

2285</h4>2703</h4>

2286 2704 

2287TaskCompleted hooks 支持两种方式来控制任务完成:2705TaskCompleted hooks 支持两种方式来控制任务完成:

2288 2706 

2289* **退出代码 2**:任务不被标记为已完成,stderr 消息作为反馈反馈给模型。2707* **退出代码 2**:任务未被标记为完成,stderr 消息被反馈给模型作为反馈。

2290* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止队友,匹配 `Stop` hook 行为。`stopReason` 向用户显示。2708* **JSON `{"continue": false, "stopReason": "..."}`**:当队友完成其回合触发事件时,完全停止队友,匹配 `Stop` hook 行为。`stopReason` 显示给用户。当 `TaskUpdate` 工具触发事件时,Claude Code 忽略 `continue: false`;退出代码 2 仍然阻止完成。

2291 2709 

2292此示例运行测试并在失败时阻止任务完成:2710此示例运行测试并在它们失败时阻止任务完成:

2293 2711 

2294```bash theme={null}2712```bash theme={null}

2295#!/bin/bash2713#!/bin/bash

2296INPUT=$(cat)2714INPUT=$(cat)

2297TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')2715TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')

2298 2716 

2299# 运行测试套件2717# Run the test suite

2300if ! npm test 2>&1; then2718if ! npm test 2>&1; then

2301 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&22719 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&2

2302 exit 22720 exit 2


2309 Stop2727 Stop

2310</h3>2728</h3>

2311 2729 

2312在主 Claude Code 代理完成响应时运行。如果停止是由于用户中断,则不运行。API 错误触发[StopFailure](#stopfailure)。2730在主 Claude Code agent 完成响应时运行。如果停止由于用户中断而发生,则不运行。API 错误触发 [StopFailure](#stopfailure)。

2313 2731 

2314<Tip>2732<Tip>

2315 [`/goal`](/docs/zh-CN/goal)命令是会话范围的基于提示的 Stop hook 的内置快捷方式。当您想要 Claude 继续工作直到条件成立而不编写 hook 配置时使用它。2733 [`/goal`](/docs/zh-CN/goal) 命令是会话范围的基于提示的 Stop hook 的内置快捷方式。当您想让 Claude 继续朝着条件工作而不编写 hook 配置时使用它。

2316</Tip>2734</Tip>

2317 2735 

2318<h4 id="stop-input">2736<h4 id="stop-input">

2319 Stop 输入2737 Stop 输入

2320</h4>2738</h4>

2321 2739 

2322除了[通用输入字段](#common-input-fields)外,Stop hooks 还接收 `stop_hook_active`、`last_assistant_message`、`background_tasks` 和 `session_crons`。`stop_hook_active` 字段在 Claude Code 已经作为 stop hook 的结果继续时为 `true`。检查此值或处理成绩单以防止 Claude Code 无限运行。Claude Code 在 8 次连续阻止后覆盖 hook 并结束轮次。2740除了 [常见输入字段](#common-input-fields) 外,Stop hooks 接收 `stop_hook_active`、`last_assistant_message`、`background_tasks` 和 `session_crons`。`stop_hook_active` 字段在 Claude Code 已经作为 stop hook 的结果继续时为 `true`。检查此值或处理成绩单以避免在永远不会解决的条件上阻止。Claude Code 在 8 个连续阻止后覆盖 hook 并结束回合。

2323 2741 

2324`last_assistant_message` 字段包含 Claude 最终响应的文本内容,因此 hooks 可以访问它而无需解析成绩单文件。2742`last_assistant_message` 字段包含 Claude 最终响应的文本内容,因此 hooks 可以访问它而无需解析成绩单文件。对于作用于刚完成的回合的 hooks,如朗读或通知 hooks,使用此字段而不是读取 `transcript_path`:成绩单文件不保证在所有版本的 Stop 时间包含最终消息。

2325 2743 

2326`background_tasks` 和 `session_crons` 数组在 Claude Code v2.1.145 或更高版本中可用,让 hooks 区分"会话完成"和"会话暂停等待后台工作唤醒它"。当任务注册表可达时两个数组都存在,当没有任何内容在进行中或计划时为空。2744`background_tasks` 和 `session_crons` 数组让 hooks 区分"会话完成"与"会话暂停等待后台工作唤醒它"。当任务注册表可达时两个数组都出现,当没有任何东西在飞行或计划时为空。

2327 2745 

2328`background_tasks` 中的每个条目描述一个进行中的任务,并使用这些字段:2746`background_tasks` 中的每个条目描述一个进行中的任务,并使用这些字段:

2329 2747 

2330| 字段 | 描述 |2748| 字段 | 描述 |

2331| :------------ | :----------------------------------------------------------------------------------------------------------------------------------------- |2749| :------------ | :---------------------------------------------------------------------------------------------------------------------------------------- |

2332| `id` | 任务标识符 |2750| `id` | 任务标识符 |

2333| `type` | 友好的任务类型标签,如 `shell`、`subagent`、`monitor`、`workflow`、`teammate`、`cloud session` 或 `MCP task`。每个标签标识哪个 Claude Code 功能创建了任务。对于无法识别的类型回退到原始判别式 |2751| `type` | 友好的任务类型标签如 `shell`、`subagent`、`monitor`、`workflow`、`teammate`、`cloud session` 或 `MCP task`。每个标签标识哪个 Claude Code 功能创建了任务。对于无法识别的类型回退到原始判别式 |

2334| `status` | 当前任务状态 |2752| `status` | 当前任务状态 |

2335| `description` | 自由文本描述,上限为 1000 个字符,当被剪切时在字符串中有 `… [+N chars]` 标记 |2753| `description` | 自由文本描述,上限为 1000 个字符,当被剪切时在字符串中有 `… [+N chars]` 标记 |

2336| `command` | Shell 命令行,上限为 1000 个字符。仅对 `shell` 任务存在 |2754| `command` | Shell 命令行,上限为 1000 个字符。仅对 `shell` 任务出现 |

2337| `agent_type` | Subagent 类型名称。仅对 `subagent` 任务存在 |2755| `agent_type` | 子 agent 类型名称。仅对 `subagent` 任务出现 |

2338| `server` | MCP 服务器名称。仅对 `monitor` 和 `MCP task` 任务存在 |2756| `server` | MCP 服务器名称。仅对 `monitor` 和 `MCP task` 任务出现 |

2339| `tool` | MCP 工具名称。仅对 `monitor` 和 `MCP task` 任务存在 |2757| `tool` | MCP 工具名称。仅对 `monitor` 和 `MCP task` 任务出现 |

2340| `name` | 工作流名称。仅对 `workflow` 任务存在 |2758| `name` | Workflow 名称。仅对 `workflow` 任务出现 |

2341 2759 

2342`session_crons` 中的每个条目描述一个会话范围的计划唤醒,来自 `CronCreate`、`ScheduleWakeup` 和 `/loop`:2760`session_crons` 中的每个条目描述一个会话范围的计划唤醒,来自 `CronCreate`、`ScheduleWakeup` 和 `/loop`:

2343 2761 

2344| 字段 | 描述 |2762| 字段 | 描述 |

2345| :---------- | :--------------------------------------------------- |2763| :---------- | :---------------------------------------------------- |

2346| `id` | Cron 任务标识符 |2764| `id` | Cron 任务标识符 |

2347| `schedule` | Cron 表达式,例如 `0 9 * * 1-5` |2765| `schedule` | Cron 表达式,例如 `0 9 * * 1-5` |

2348| `recurring` | `false` 用于一次性唤醒,其计划编码单个触发时间,`true` 用于在每次匹配时重新触发的任务 |2766| `recurring` | 对于一次性唤醒(其计划编码单个触发时间)为 `false`,对于在每个匹配上重新触发的任务为 `true` |

2349| `prompt` | 当 cron 触发时提交的提示,上限为 1000 个字符,具有相同的 `… [+N chars]` 标记 |2767| `prompt` | 当 cron 触发时提交的提示,上限为 1000 个字符,带有相同的 `… [+N chars]` 标记 |

2350 2768 

2351此示例显示一个 Stop 输入,其中有一个进行中的 shell 任务和一个循环 cron:2769此示例显示了一个 Stop 输入,带有一个进行中的 shell 任务和一个循环 cron:

2352 2770 

2353```json theme={null}2771```json theme={null}

2354{2772{


2380```2798```

2381 2799 

2382<h4 id="stop-decision-control">2800<h4 id="stop-decision-control">

2383 Stop 决定控制2801 Stop 决策控制

2384</h4>2802</h4>

2385 2803 

2386`Stop` 和 `SubagentStop` hooks 可以控制 Claude 是否继续。除了所有 hooks 可用的[JSON 输出字段](#json-output)外,您的 hook 脚本可以返回这些事件特定字段:2804`Stop` 和 `SubagentStop` hooks 可以控制 Claude 是否继续。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您的 hook 脚本可以返回这些事件特定的字段:

2387 2805 

2388| 字段 | 描述 |2806| 字段 | 描述 |

2389| :------------------------------------- | :------------------------------------------------------------------------------------------- |2807| :------------------------------------- | :---------------------------------------------------------------------------------------- |

2390| `decision` | `"block"` 防止 Claude 停止。省略以允许 Claude 停止 |2808| `decision` | `"block"` 防止 Claude 停止。省略以允许 Claude 停止 |

2391| `reason` | 当 `decision` 为 `"block"` 时必需。告诉 Claude 为什么它应该继续 |2809| `reason` | 当 `decision` 为 `"block"` 时需要。告诉 Claude 为什么它应该继续 |

2392| `hookSpecificOutput.additionalContext` | 非错误反馈给 Claude。对话继续,以便 Claude 可以对其采取行动,但与 `decision: "block"` 不同,它在成绩单中显示为 hook 反馈而不是 hook 错误 |2810| `hookSpecificOutput.additionalContext` | Claude 的非错误反馈。对话继续以便 Claude 可以作用于它,但与 `decision: "block"` 不同,它在成绩单中显示为 hook 反馈而不是 hook 错误 |

2811 

2812通过退出 2 阻止的 hook 路由方式与 `reason` 相同:Claude 接收 stderr 消息作为为什么它应该继续的解释。

2393 2813 

2394```json theme={null}2814```json theme={null}

2395{2815{


2398}2818}

2399```2819```

2400 2820 

2401当 hook 按设计工作并给予 Claude 指导时使用 `additionalContext`,例如"在完成前运行测试套件"。它通过与 `decision: "block"` 相同的循环保护保持对话进行,即 `stop_hook_active` 输入和 8 次连续继续上限,但成绩单将其标记为 `Stop hook feedback`,不显示 hook 错误通知:2821当 hook 按设计工作并给 Claude 指导时使用 `additionalContext`,如"在完成前运行测试套件"。它通过与 `decision: "block"` 相同的循环保护保持对话进行,即 `stop_hook_active` 输入和 8 个连续继续上限,但成绩单将其标记为 `Stop hook feedback`,不显示 hook 错误通知:

2402 2822 

2403```json theme={null}2823```json theme={null}

2404{2824{


2413 StopFailure2833 StopFailure

2414</h3>2834</h3>

2415 2835 

2416当轮次因 API 错误而结束时运行,而不是[Stop](#stop)。输出和退出代码被忽略。使用此来记录失败、发送警报或在 Claude 因速率限制、身份验证问题或其他 API 错误而无法完成响应时采取恢复操作。2836在回合由于 API 错误而结束时运行,而不是 [Stop](#stop)。Claude Code 忽略 hook 的输出和退出代码,除了 [`terminalSequence`](#emit-terminal-notifications)。使用此来记录失败、发送警报或在 Claude 由于速率限制、身份验证问题或其他 API 错误无法完成响应时采取恢复操作。

2417 2837 

2418<h4 id="stopfailure-input">2838<h4 id="stopfailure-input">

2419 StopFailure 输入2839 StopFailure 输入

2420</h4>2840</h4>

2421 2841 

2422除了[通用输入字段](#common-input-fields)外,StopFailure hooks 还接收 `error`、可选的 `error_details` 和可选的 `last_assistant_message`。`error` 字段标识错误类型,用于匹配器过滤。2842除了 [常见输入字段](#common-input-fields) 外,StopFailure hooks 接收 `error`、可选的 `error_details` 和可选的 `last_assistant_message`。`error` 字段标识错误类型,用于匹配器过滤。

2423 2843 

2424| 字段 | 描述 |2844| 字段 | 描述 |

2425| :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2845| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

2426| `error` | 错误类型:`rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens` 或 `unknown` |2846| `error` | 错误类型:`rate_limit`、`overloaded`、`authentication_failed`、`oauth_org_not_allowed`、`account_on_hold`、`billing_error`、`invalid_request`、`model_not_found`、`server_error`、`max_output_tokens`、`cloud_credential_error` 或 `unknown` |

2427| `error_details` | 关于错误的额外详细信息(如果可用) |2847| `error_details` | 关于错误的其他详情,当可用时 |

2428| `last_assistant_message` | 在对话中显示的呈现错误文本。与 `Stop` 和 `SubagentStop` 不同,其中此字段包含 Claude 的对话输出,对于 `StopFailure` 它包含 API 错误字符串本身,例如 `"API Error: Rate limit reached"` |2848| `last_assistant_message` | 在对话中显示的呈现错误文本。与 `Stop` 和 `SubagentStop` 不同,其中此字段保持 Claude 的对话输出,对于 `StopFailure` 它包含 API 错误字符串本身,如 `"API Error: Rate limit reached"` |

2429 2849 

2430```json theme={null}2850```json theme={null}

2431{2851{


2439}2859}

2440```2860```

2441 2861 

2442StopFailure hooks 没有决定控制。它们仅为通知和日志记录目的运行。2862StopFailure hooks 没有决策控制。它们仅用于通知和日志记录目的运行。

2443 2863 

2444<h3 id="teammateidle">2864<h3 id="teammateidle">

2445 TeammateIdle2865 TeammateIdle

2446</h3>2866</h3>

2447 2867 

2448当[代理团队](/docs/zh-CN/agent-teams)队友在完成其轮次后即将空闲时运行。使用此来强制执行质量门,如要求通过 lint 检查或验证输出文件存在。2868在 [agent team](/docs/zh-CN/agent-teams) 队友完成其回合后即将空闲时运行。使用此来强制质量门,如在队友停止工作之前要求通过 lint 检查或验证输出文件存在。

2449 2869 

2450当 `TeammateIdle` hook 以代码 2 退出时,队友接收 stderr 消息作为反馈并继续工作而不是空闲。要完全停止队友而不是重新运行它,返回 JSON `{"continue": false, "stopReason": "..."}` 。TeammateIdle hooks 不支持匹配器,在每次出现时触发。2870TeammateIdle hooks 不支持匹配器,对每个出现触发。

2451 2871 

2452<h4 id="teammateidle-input">2872<h4 id="teammateidle-input">

2453 TeammateIdle 输入2873 TeammateIdle 输入

2454</h4>2874</h4>

2455 2875 

2456除了[通用输入字段](#common-input-fields)外,TeammateIdle hooks 还接收 `teammate_name` 和 `team_name`。2876除了 [常见输入字段](#common-input-fields) 外,TeammateIdle hooks 接收 `teammate_name` 和 `team_name`。

2457 2877 

2458```json theme={null}2878```json theme={null}

2459{2879{


2473| `team_name` | 已弃用。会话派生的团队名称;将在未来版本中删除 |2893| `team_name` | 已弃用。会话派生的团队名称;将在未来版本中删除 |

2474 2894 

2475<h4 id="teammateidle-decision-control">2895<h4 id="teammateidle-decision-control">

2476 TeammateIdle 决定控制2896 TeammateIdle 决策控制

2477</h4>2897</h4>

2478 2898 

2479TeammateIdle hooks 支持两种方式来控制队友行为:2899TeammateIdle hooks 支持两种方式来控制队友行为:

2480 2900 

2481* **退出代码 2**:队友接收 stderr 消息作为反馈并继续工作而不是空闲。2901* **退出代码 2**:队友接收 stderr 消息作为反馈并继续工作而不是空闲。

2482* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止队友,匹配 `Stop` hook 行为。`stopReason` 向用户显示。2902* **JSON `{"continue": false, "stopReason": "..."}`**:完全停止队友,匹配 `Stop` hook 行为。`stopReason` 显示给用户。

2483 2903 

2484此示例检查构建工件是否存在,然后允许队友空闲:2904此示例检查构建工件存在,然后允许队友空闲:

2485 2905 

2486```bash theme={null}2906```bash theme={null}

2487#!/bin/bash2907#!/bin/bash


2498 ConfigChange2918 ConfigChange

2499</h3>2919</h3>

2500 2920 

2501当会话期间配置文件更改时运行。使用此来审计设置更改、强制执行安全策略或阻止对配置文件的未授权修改。2921在会话期间配置文件更改时运行。使用此来审计设置更改、强制安全策略或阻止对配置文件的未授权修改。

2502 2922 

2503ConfigChange hooks 对设置文件、托管策略设置和 skill 文件的更改触发。输入中的 `source` 字段告诉您哪种类型的配置更改,可选的 `file_path` 字段提供更改文件的路径。2923Claude Code 在设置文件、托管策略文件或 skill 文件更改时运行 ConfigChange hooks。对于托管策略,它仅在 `managed-settings.json` 或 `managed-settings.d/` 中的文件更改时运行。它应用 [服务器托管设置](/docs/zh-CN/server-managed-settings) 和对 macOS 托管首选项或 Windows 注册表策略的更改而不运行它们。在带有 [`wslInheritsWindowsSettings`](/docs/zh-CN/settings-reference#wslinheritswindowssettings) 的 WSL 上,它也在其策略轮询上应用更改的 Windows 端托管设置文件而不运行它们。

2504 2924 

2505匹配器在配置源上过滤:2925匹配器过滤配置源:

2506 2926 

2507| 匹配器 | 何时触发 |2927| 匹配器 | 何时触发 |

2508| :----------------- | :------------------------------- |2928| :----------------- | :----------------------------------------------------- |

2509| `user_settings` | `~/.claude/settings.json` 更改 |2929| `user_settings` | `~/.claude/settings.json` 更改 |

2510| `project_settings` | `.claude/settings.json` 更改 |2930| `project_settings` | `.claude/settings.json` 更改 |

2511| `local_settings` | `.claude/settings.local.json` 更改 |2931| `local_settings` | `.claude/settings.local.json` 更改 |

2512| `policy_settings` | 托管策略设置更改 |2932| `policy_settings` | `managed-settings.json` 或 `managed-settings.d/` 中的文件更改 |

2513| `skills` | `.claude/skills/` 中的 skill 文件更改 |2933| `skills` | `.claude/skills/` 中的 skill 文件更改 |

2514 2934 

2515此示例记录所有配置更改以进行安全审计:2935此示例记录所有配置更改以进行安全审计:


2536 ConfigChange 输入2956 ConfigChange 输入

2537</h4>2957</h4>

2538 2958 

2539除了[通用输入字段](#common-input-fields)外,ConfigChange hooks 还接收 `source` 和可选的 `file_path`。`source` 字段指示哪种配置类型更改,`file_path` 提供被修改的特定文件的路径。2959除了 [常见输入字段](#common-input-fields) 外,ConfigChange hooks 接收 `source` 和可选的 `file_path`。`source` 字段指示哪个配置类型更改,`file_path` 提供修改的特定文件的路径。

2540 2960 

2541```json theme={null}2961```json theme={null}

2542{2962{


2550```2970```

2551 2971 

2552<h4 id="configchange-decision-control">2972<h4 id="configchange-decision-control">

2553 ConfigChange 决定控制2973 ConfigChange 决策控制

2554</h4>2974</h4>

2555 2975 

2556ConfigChange hooks 可以阻止配置更改生效。使用退出代码 2 或 JSON `decision` 来防止更改。被阻止时,新设置不应用于运行中的会话。2976ConfigChange hooks 可以阻止配置更改生效。使用退出代码 2 或 JSON `decision` 来防止更改。当被阻止时,新设置不应用于运行的会话。

2557 2977 

2558| 字段 | 描述 |2978| 字段 | 描述 |

2559| :--------- | :--------------------------------- |2979| :--------- | :-------------------------- |

2560| `decision` | `"block"` 防止配置更改被应用。省略以允许更改 |2980| `decision` | `"block"` 防止配置更改被应用。省略以允许更改 |

2561| `reason` | 当 `decision` 为 `"block"` 时向用户显示的解释 |2981| `reason` | 被接受但永远不显示 |

2562 2982 

2563```json theme={null}2983```json theme={null}

2564{2984{


2567}2987}

2568```2988```

2569 2989 

2570`policy_settings` 更改无法被阻止。Hooks 仍然对 `policy_settings` 源触发,因此您可以使用它们进行审计日志记录,但任何阻止决定都被忽略。这确保企业管理的设置始终生效。2990`policy_settings` 更改无法被阻止。当机器上的托管设置文件更改时,hooks 仍然为 `policy_settings` 源触发,因此您可以使用它们来记录这些编辑,但任何阻止决策都被忽略。这确保企业托管设置始终生效。当 [服务器托管设置](/docs/zh-CN/server-managed-settings) 到达或刷新时,Claude Code 不运行 `ConfigChange` hooks。

2991 

2992Claude Code 作用于 ConfigChange hook 的 JSON 输出中的阻止决策,并丢弃 `systemMessage` 和 `continue`。被阻止的更改不向您或 Claude 显示任何消息,无论您是用 `reason` 还是退出 2 时的 stderr 阻止。Claude Code 仅向调试日志写入一行。

2571 2993 

2572<h3 id="cwdchanged">2994<h3 id="cwdchanged">

2573 CwdChanged2995 CwdChanged

2574</h3>2996</h3>

2575 2997 

2576当会话期间工作目录更改时运行,例如当 Claude 执行 `cd` 命令时。使用此来对目录更改做出反应:重新加载环境变量、激活项目特定的工具链或自动运行设置脚本。与[FileChanged](#filechanged)配对,用于[direnv](https://direnv.net/)等管理每个目录环境的工具。2998在主对话中的 shell 命令更改工作目录时运行,例如当 Claude 执行 `cd` 命令时。使用此来对目录更改做出反应:重新加载环境变量、激活项目特定的工具链或自动运行设置脚本。与 [FileChanged](#filechanged) 配对,用于像 [direnv](https://direnv.net/) 这样管理每个目录环境的工具。

2577 2999 

2578CwdChanged hooks 可以访问 `CLAUDE_ENV_FILE`。写入该文件的变量持久化到会话的后续 Bash 命令中,就像在[SessionStart hooks](#persist-environment-variables)中一样。3000CwdChanged hooks 可以访问 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。写入该文件的变量持久化到后续 Bash 命令,直到下一个 CwdChanged 事件,当 Claude Code 清除它们时。

2579 3001 

2580CwdChanged 不支持匹配器,在每次目录更改时触发。3002CwdChanged 不支持匹配器,对每个出现触发。

2581 3003 

2582<h4 id="cwdchanged-input">3004<h4 id="cwdchanged-input">

2583 CwdChanged 输入3005 CwdChanged 输入

2584</h4>3006</h4>

2585 3007 

2586除了[通用输入字段](#common-input-fields)外,CwdChanged hooks 还接收 `old_cwd` 和 `new_cwd`。3008除了 [常见输入字段](#common-input-fields) 外,CwdChanged hooks 接收 `old_cwd` 和 `new_cwd`。

2587 3009 

2588```json theme={null}3010```json theme={null}

2589{3011{


2600 CwdChanged 输出3022 CwdChanged 输出

2601</h4>3023</h4>

2602 3024 

2603除了所有 hooks 可用的[JSON 输出字段](#json-output)外,CwdChanged hooks 还可以返回 `watchPaths` 来动态设置[FileChanged](#filechanged)监视的文件路径:3025除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,CwdChanged hooks 可以返回 `watchPaths` 来动态设置 [FileChanged](#filechanged) 监视的文件路径:

2604 3026 

2605| 字段 | 描述 |3027| 字段 | 描述 |

2606| :----------- | :-------------------------------------------------------------------- |3028| :----------- | :--------------------------------------------------------- |

2607| `watchPaths` | 绝对路径的数组。替换当前动态监视列表。来自您的 `matcher` 配置的路径始终被监视。返回空数组会清除动态列表,这在进入新目录时很典型 |3029| `watchPaths` | 绝对路径数组。替换当前动态监视列表。来自您 `matcher` 配置的路径始终被监视。进入新目录时返回空数组是典型的 |

2608 3030 

2609CwdChanged hooks 没有决定控制。它们无法阻止目录更改。3031CwdChanged hooks 没有决策控制。它们无法阻止目录更改。

3032 

3033Claude Code 从它们的 JSON 输出读取 `watchPaths` 和 `systemMessage`,并丢弃 `continue`。在交互式会话中,它显示 `systemMessage` 作为简短的终端通知。消息不到达 SDK 消息流。

3034 

3035<h3 id="directoryadded">

3036 DirectoryAdded

3037</h3>

3038 

3039在您使用 `/add-dir` 命令在会话中添加工作目录后运行,或在 SDK 客户端使用 `register_repo_root` 控制请求添加一个后运行。使用此来准备新添加的存储库,例如安装其依赖。

3040 

3041Claude Code 在以下情况下不触发此事件:

3042 

3043* 您使用 `--add-dir` 启动标志传递目录;[SessionStart](#sessionstart) 涵盖这些目录

3044* 您在 `/permissions` Workspace 标签上添加目录

3045* 您添加已经是工作目录或在其中的目录

3046 

3047Claude Code 在刷新沙箱和权限状态后触发 DirectoryAdded,因此沙箱工具已经在您的 hook 运行时看到新目录。Hook 命令本身运行未沙箱化。

3048 

3049Claude Code 不等待 hook:添加立即完成,hook 在后台以 600 秒默认超时运行。

3050 

3051匹配器过滤目录添加的方式:

3052 

3053| 匹配器 | 何时触发 |

3054| :------------------- | :-------------------------------------- |

3055| `slash_command` | 您使用 `/add-dir` 添加目录 |

3056| `register_repo_root` | SDK 客户端使用 `register_repo_root` 控制请求添加目录 |

3057 

3058<h4 id="directoryadded-input">

3059 DirectoryAdded 输入

3060</h4>

3061 

3062除了 [常见输入字段](#common-input-fields) 外,DirectoryAdded hooks 接收 `directory` 和 `source`。

3063 

3064| 字段 | 描述 |

3065| :---------- | :----------------------------------------------------------------------- |

3066| `directory` | 添加的目录的绝对路径 |

3067| `source` | 目录如何添加,`/add-dir` 为 `"slash_command"` 或 SDK 控制请求为 `"register_repo_root"` |

3068 

3069```json theme={null}

3070{

3071 "session_id": "abc123",

3072 "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",

3073 "cwd": "/Users/my-project",

3074 "hook_event_name": "DirectoryAdded",

3075 "directory": "/Users/my-other-repo",

3076 "source": "slash_command"

3077}

3078```

3079 

3080DirectoryAdded hooks 没有决策控制。它们无法阻止添加,这在 hook 运行时已经完成。Claude Code 从它们的 JSON 输出丢弃 `continue` 字段,并根据源以不同方式呈现其余部分:

3081 

3082* `slash_command`:Claude Code 将 hook 的 `systemMessage` 作为对话的下一个回合的上下文传递给 Claude,而不是向您显示它。失败 hooks 的计数出现在成绩单中。完整失败输出进入调试日志

3083* `register_repo_root`:Claude Code 仅将 `systemMessage` 输出和失败输出写入调试日志

2610 3084 

2611<h3 id="filechanged">3085<h3 id="filechanged">

2612 FileChanged3086 FileChanged

2613</h3>3087</h3>

2614 3088 

2615当监视的文件在磁盘上更改时运行。用于在项目配置文件修改时重新加载环境变量。3089在监视的文件在磁盘上更改时运行。Claude Code 使用文件系统监视器检测更改,而不是通过检查工具调用,因此它运行 hook,无论什么更改了文件:`Edit` 或 `Write` 工具调用、Claude 使用 `Bash` 运行的脚本或 Claude Code 外的进程。常见用途是在项目配置文件更改时重新加载环境变量。

2616 3090 

2617此事件的 `matcher` 有两个作用:3091此事件的 `matcher` 有两个角色:

2618 3092 

2619* **构建监视列表**:值在 `|` 上分割,每个段注册为工作目录中的文字文件名,因此 `".envrc|.env"` 监视恰好这两个文件。正则表达式模式在这里不有用:像 `^\.env` 这样的值会监视一个字面上名为 `^\.env` 的文件。3093* **构建监视列表**:值在 `|` 上分割,每个段注册为工作目录中的字面文件名,因此 `".envrc|.env"` 恰好监视这两个文件。正则表达式模式在这里不有用:像 `^\.env` 这样的值会监视字面名为 `^\.env` 的文件。

2620* **过滤哪些 hooks 运行**:当监视的文件更改时,相同的值使用标准[匹配器规则](#matcher-patterns)针对更改文件的基名过滤哪些 hook 组运行。3094* **过滤哪些 hooks 运行**:当监视的文件更改时,相同的值使用标准 [匹配器规则](#matcher-patterns) 针对更改文件的基名过滤哪些 hook 组运行。

2621 3095 

2622FileChanged hooks 可以访问 `CLAUDE_ENV_FILE`。写入该文件的变量持久化到会话的后续 Bash 命令中,就像在[SessionStart hooks](#persist-environment-variables)中一样。3096此示例在任何更改后规范化 `data.csv` 中的行结尾,包括 `Bash` 命令或外部脚本重写文件:

3097 

3098```json theme={null}

3099{

3100 "hooks": {

3101 "FileChanged": [

3102 {

3103 "matcher": "data.csv",

3104 "hooks": [

3105 {

3106 "type": "command",

3107 "command": "/path/to/normalize-line-endings.sh"

3108 }

3109 ]

3110 }

3111 ]

3112 }

3113}

3114```

3115 

3116hook 从 [JSON 输入](#filechanged-input) 的 `file_path` 字段读取更改文件的绝对路径,在 stdin 上。其 `grep` 守卫测试与 `perl` 删除的相同内容,行末的 CR,因此规范化后的运行退出而不触及文件。更松散的守卫循环永远,因为 `perl -i` 重写文件即使它替换了什么都没有,Claude Code 在每次重写后运行 hook。保存此脚本到 `/path/to/normalize-line-endings.sh` 并使其可执行:

3117 

3118```bash theme={null}

3119#!/bin/bash

3120FILE=$(jq -r .file_path)

3121if grep -q $'\r$' "$FILE"; then

3122 perl -pi -e 's/\r$//' "$FILE"

3123fi

3124```

3125 

3126要确认 hook 工作,要求 Claude 使用 Bash 命令向 `data.csv` 追加 CRLF 行。Claude Code 运行 hook,文件最终以 LF 结尾。

3127 

3128要监视您无法提前命名的文件,从 hook 返回 [`watchPaths`](#filechanged-output) 来动态更新监视列表。Claude Code 仅在某些东西命名要监视的文件时启动监视器,因此使用至少命名一个文件的 FileChanged 组为列表播种,或使用 [SessionStart](#sessionstart-decision-control) 或 [CwdChanged](#cwdchanged) hook 返回 `watchPaths`。匹配器仍然过滤当监视的文件更改时哪些 hook 组运行,因此给处理动态路径的组一个省略的匹配器,它匹配每个监视的文件并不向监视列表添加任何内容。`"*"` 匹配器也匹配每个文件,但 Claude Code 像任何其他值一样在监视列表中注册它,作为字面名为 `*` 的文件。

3129 

3130FileChanged hooks 可以访问 [`CLAUDE_ENV_FILE`](#persist-environment-variables)。写入该文件的变量持久化到后续 Bash 命令,直到下一个 [CwdChanged](#cwdchanged) 事件,当 Claude Code 清除它们时。

2623 3131 

2624<h4 id="filechanged-input">3132<h4 id="filechanged-input">

2625 FileChanged 输入3133 FileChanged 输入

2626</h4>3134</h4>

2627 3135 

2628除了[通用输入字段](#common-input-fields)外,FileChanged hooks 还接收 `file_path` 和 `event`。3136除了 [常见输入字段](#common-input-fields) 外,FileChanged hooks 接收 `file_path` 和 `event`。

2629 3137 

2630| 字段 | 描述 |3138| 字段 | 描述 |

2631| :---------- | :----------------------------------------------------- |3139| :---------- | :------------------------------------------------------- |

2632| `file_path` | 更改文件的绝对路径 |3140| `file_path` | 更改的文件的绝对路径 |

2633| `event` | 发生了什么:`"change"`(文件修改)、`"add"`(文件创建)或 `"unlink"`(文件删除) |3141| `event` | 发生了什么:修改文件为 `"change"`、创建的文件为 `"add"` 或删除的文件为 `"unlink"` |

2634 3142 

2635```json theme={null}3143```json theme={null}

2636{3144{


2647 FileChanged 输出3155 FileChanged 输出

2648</h4>3156</h4>

2649 3157 

2650除了所有 hooks 可用的[JSON 输出字段](#json-output)外,FileChanged hooks 还可以返回 `watchPaths` 来动态更新监视的文件路径:3158除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,FileChanged hooks 可以返回 `watchPaths` 来动态更新监视的文件路径:

2651 3159 

2652| 字段 | 描述 |3160| 字段 | 描述 |

2653| :----------- | :----------------------------------------------------------------------------- |3161| :----------- | :-------------------------------------------------------------------------- |

2654| `watchPaths` | 绝对路径的数组。替换当前动态监视列表。来自您的 `matcher` 配置的路径始终被监视。当您的 hook 脚本根据更改的文件发现要监视的其他文件时使用此项 |3162| `watchPaths` | 绝对路径数组。替换当前动态监视列表。来自您 `matcher` 配置的路径始终被监视。当您的 hook 脚本根据更改的文件发现要监视的其他文件时使用此 |

3163 

3164FileChanged hooks 没有决策控制。它们无法阻止文件更改发生。

2655 3165 

2656FileChanged hooks 没有决定控制。它们无法阻止文件更改的发生。3166Claude Code 从它们的 JSON 输出读取 `watchPaths` 和 `systemMessage`,并丢弃 `continue`。在交互式会话中,它显示 `systemMessage` 作为简短的终端通知。消息不到达 SDK 消息流。

2657 3167 

2658<h3 id="worktreecreate">3168<h3 id="worktreecreate">

2659 WorktreeCreate3169 WorktreeCreate

2660</h3>3170</h3>

2661 3171 

2662当您运行 `claude --worktree` 或[subagent 使用 `isolation: "worktree"`](/docs/zh-CN/sub-agents#choose-the-subagent-scope)时运行。默认情况下,Claude Code 使用 `git worktree` 创建隔离的工作副本。配置 WorktreeCreate hook 替换该默认 git 行为,让您使用不同的版本控制系统,如 SVN、Perforce 或 Mercurial。3172在创建 worktree 时运行,无论是从 `claude --worktree`、从 [使用 `isolation: "worktree"` 的子 agent](/docs/zh-CN/sub-agents#choose-the-subagent-scope),还是对于 Claude Code 在其自己的 worktree 中隔离的 [后台会话](/docs/zh-CN/agent-view#how-file-edits-are-isolated)。默认情况下,Claude Code 使用 `git worktree` 创建隔离的工作副本。配置 WorktreeCreate hook 替换该默认 git 行为,让您使用不同的版本控制系统,如 SVN、Perforce 或 Mercurial。

2663 3173 

2664因为 hook 完全替换默认行为,[`.worktreeinclude`](/docs/zh-CN/worktrees#copy-gitignored-files-into-worktrees)不被处理。如果您需要将本地配置文件(如 `.env`)复制到新 worktree,请在您的 hook 脚本内执行。3174因为 hook 完全替换默认行为,[`.worktreeinclude`](/docs/zh-CN/worktrees#copy-gitignored-files-into-worktrees) 不被处理。如果您需要将本地配置文件如 `.env` 复制到新 worktree,请在您的 hook 脚本内执行。

2665 3175 

2666Hook 必须返回创建的 worktree 目录的绝对路径。Claude Code 使用此路径作为隔离会话的工作目录。请参阅[WorktreeCreate 输出](#worktreecreate-output)了解每个 hook 类型如何返回路径。3176hook 必须返回创建的 worktree 目录的路径。Claude Code 使用此路径作为隔离会话的工作目录。有关每个 hook 类型如何返回路径,请参阅 [WorktreeCreate 输出](#worktreecreate-output)。

2667 3177 

2668此示例创建 SVN 工作副本并打印路径供 Claude Code 使用。用您自己的替换仓库 URL:3178Claude Code 作用于 hook 的成功和返回的路径,并丢弃 `systemMessage` 和 `continue`。

3179 

3180此示例创建 SVN 工作副本并打印路径供 Claude Code 使用。将存储库 URL 替换为您自己的:

2669 3181 

2670```json theme={null}3182```json theme={null}

2671{3183{


2684}3196}

2685```3197```

2686 3198 

2687Hook 从 stdin 上的 JSON 输入读取 worktree `name`,将新副本检出到新目录,并打印目录路径。最后一行的 `echo` 是 Claude Code 读取的 worktree 路径。将任何其他输出重定向到 stderr,以便它不会干扰路径。3199hook 从 stdin 上的 JSON 输入读取 worktree `name`,检出一个新副本到新目录,并打印目录路径。最后一行的 `echo` 是 Claude Code 读取为 worktree 路径的内容。将任何其他输出重定向到 stderr,以便它不干扰路径。

2688 3200 

2689<h4 id="worktreecreate-input">3201<h4 id="worktreecreate-input">

2690 WorktreeCreate 输入3202 WorktreeCreate 输入

2691</h4>3203</h4>

2692 3204 

2693除了[通用输入字段](#common-input-fields)外,WorktreeCreate hooks 还接收 `name` 字段。这是新 worktree 的 slug 标识符,由用户指定或自动生成,例如 `bold-oak-a3f2`。3205除了 [常见输入字段](#common-input-fields) 外,WorktreeCreate hooks 接收 `name` 字段。这是新 worktree 的 slug 标识符,由用户指定或自动生成,例如 `bold-oak-a3f2`。

2694 3206 

2695```json theme={null}3207```json theme={null}

2696{3208{


2706 WorktreeCreate 输出3218 WorktreeCreate 输出

2707</h4>3219</h4>

2708 3220 

2709WorktreeCreate hooks 不使用标准的允许/阻止决定模型。相反,hook 的成功或失败决定结果。Hook 必须返回创建的 worktree 目录的绝对路径:3221WorktreeCreate hooks 不使用标准允许/阻止决策模型。相反,hook 的成功或失败确定结果。hook 必须返回创建的 worktree 目录的路径:

3222 

3223* **命令 hooks** (`type: "command"`):将路径打印为 stdout 的最后一个非空行。Claude Code 在读取该行之前剥离 ANSI 转义代码,因此在您的 `echo` 之前打印的 shell 启动横幅被忽略。将任何其他 hook 输出重定向到 stderr。

3224* **HTTP hooks** (`type: "http"`):在响应体中返回 `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }`。

2710 3225 

2711* **命令 hooks**(`type: "command"`):在 stdout 上打印路径作为最后一个非空行。Claude Code 在读取该行之前剥离 ANSI 转义代码,因此在您的 `echo` 之前打印的 shell 启动横幅被忽略。将任何其他 hook 输出重定向到 stderr。3226如果 hook 失败或产生无路径,worktree 创建失败并出现错误。

2712* **HTTP hooks**(`type: "http"`):在响应体中返回 `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }`。

2713 3227 

2714如果 hook 失败或不产生路径,worktree 创建失败并出现错误。3228Claude Code 根据 hook 运行的目录解析相对路径,折叠其中的任何 `.` 或 `..` 段。如果结果路径不是 Claude Code 可以进入的目录,会话打印命名路径的错误并以代码 1 退出。

2715 3229 

2716Claude Code 根据 hook 运行的目录解析相对路径。如果生成的路径不是 Claude Code 可以进入的目录,会话打印一个错误,命名路径并以代码 1 退出。在 v2.1.205 之前,相对路径或磁盘上不存在的路径会在启动时使会话崩溃,使用 `-p` 时会停滞约 30 秒,然后以代码 0 退出。3230Claude Code 拒绝包含 `.` 或 `..` 段的绝对路径,以及通过存储库根下的符号链接的任何路径,因为提交到存储库的符号链接可能会将 worktree 重定向到其外。错误命名被拒绝的组件。返回不通过存储库内符号链接的规范化路径。在 v2.1.216 之前,worktree 创建遵循 hook 的路径而不进行此筛选。

2717 3231 

2718<h3 id="worktreeremove">3232<h3 id="worktreeremove">

2719 WorktreeRemove3233 WorktreeRemove

2720</h3>3234</h3>

2721 3235 

2722当 worktree 被移除时运行,要么当您退出 `--worktree` 会话并选择移除它时,要么当具有 `isolation: "worktree"` 的 subagent 完成时。这是[WorktreeCreate](#worktreecreate)的清理对应物。3236在删除 worktree 时运行。这是 [WorktreeCreate](#worktreecreate) 的清理对应物。事件在以下情况下触发:

2723 3237 

2724对于基于 git 的 worktrees,Claude Code 使用 `git worktree remove` 自动处理清理。如果您为非 git 版本控制系统配置了 WorktreeCreate hook,将其与 WorktreeRemove hook 配对以处理清理。没有它,worktree 目录留在磁盘上。3238* 您退出 `--worktree` 会话并选择删除它

3239* 带有 `isolation: "worktree"` 的子 agent 完成

3240* 您删除 [后台会话](/docs/zh-CN/agent-view#what-deleting-a-session-removes),其 worktree hook 创建

2725 3241 

2726Claude Code 将 WorktreeCreate 返回的路径作为 `worktree_path` 在 hook 输入中传递。此示例读取该路径并移除目录:3242对于基于 git 的 worktrees,Claude Code 使用 `git worktree remove` 自动处理清理。如果您为非 git 版本控制系统配置了 WorktreeCreate hook,将其与 WorktreeRemove hook 配对来处理清理。没有它,worktree 目录留在磁盘上。

3243 

3244Claude Code 丢弃 WorktreeRemove hook 的 [JSON 输出字段](#json-output),如 `systemMessage` 和 `continue`。

3245 

3246对于后台会话删除,Claude Code 在运行 hook 之前验证存储的 worktree 路径,并拒绝是符号链接或通过存储库根下的符号链接的路径。hook 仅对仍包含文件的 worktree 运行,当您在 [agent view](/docs/zh-CN/agent-view#what-deleting-a-session-removes) 中确认删除时;对于这样的 worktree,[`claude rm`](/docs/zh-CN/agent-view#manage-sessions-from-the-shell) 保持会话和 worktree。在 v2.1.216 之前,hook 在存储的路径上运行而不进行这些检查。

3247 

3248Claude Code 将 WorktreeCreate 返回的路径作为 `worktree_path` 在 hook 输入中传递。此示例读取该路径并删除目录:

2727 3249 

2728```json theme={null}3250```json theme={null}

2729{3251{


2746 WorktreeRemove 输入3268 WorktreeRemove 输入

2747</h4>3269</h4>

2748 3270 

2749除了[通用输入字段](#common-input-fields)外,WorktreeRemove hooks 还接收 `worktree_path` 字段,这是被移除的 worktree 的绝对路径。3271除了 [常见输入字段](#common-input-fields) 外,WorktreeRemove hooks 接收 `worktree_path` 字段,这是被删除的 worktree 的绝对路径。

2750 3272 

2751```json theme={null}3273```json theme={null}

2752{3274{


2758}3280}

2759```3281```

2760 3282 

2761WorktreeRemove hooks 没有决定控制。它们无法阻止 worktree 移除,但可以执行清理任务,如移除版本控制状态或存档更改。Hook 失败仅在调试模式下记录。3283WorktreeRemove hook 的退出代码决定结果。当 hook 以非零退出且 `worktree_path` 处的目录之后仍然存在时,删除失败:

3284 

3285* worktree 保留在磁盘上,hook 的命令和 stderr 进入 [调试日志](#debug-hooks)。

3286* 如果您删除后台会话,会话也保留。[agent view](/docs/zh-CN/agent-view#what-deleting-a-session-removes) 中的拒绝消息报告 hook 如何结束,如 `exited 1`,引用其 stderr 的开头,并说删除会话再次是否无论如何删除目录。

2762 3287 

2763<h3 id="precompact">3288<h3 id="precompact">

2764 PreCompact3289 PreCompact


2766 3291 

2767在 Claude Code 即将运行压缩操作之前运行。3292在 Claude Code 即将运行压缩操作之前运行。

2768 3293 

2769匹配器值指示压缩是手动还是自动触发:3294匹配器值指示压缩是手动触发还是自动触发:

2770 3295 

2771| 匹配器 | 何时触发 |3296| 匹配器 | 何时触发 |

2772| :------- | :----------- |3297| :------- | :-------------------------------------------------------------------- |

2773| `manual` | `/compact` |3298| `manual` | `/compact` |

2774| `auto` | 当上下文窗口满时自动压缩 |3299| `auto` | 当对话到达 [自动压缩窗口](/docs/zh-CN/model-config#set-the-auto-compact-window) 时自动压缩 |

2775 3300 

2776退出代码 2 以阻止压缩。对于手动 `/compact`,stderr 消息向用户显示。您也可以通过返回带有 `"decision": "block"` 的 JSON 来阻止。3301以代码 2 退出以阻止压缩。对于手动 `/compact`,stderr 消息显示给用户。您也可以通过返回 JSON 与 `"decision": "block"` 来阻止。

2777 3302 

2778阻止自动压缩有不同的效果,取决于何时触发。如果压缩在上下文限制之前主动触发,Claude Code 跳过它,对话继续未压缩。如果压缩被触发以从已由 API 返回的上下文限制错误恢复,底层错误浮出并且当前请求失败。3303阻止自动压缩根据何时触发有不同的效果。如果压缩在上下文限制之前主动触发,Claude Code 跳过它,对话继续未压缩。如果压缩被触发以从 API 已经返回的上下文限制错误恢复,底层错误浮出,当前请求失败。

3304 

3305Claude Code 丢弃 PreCompact hook 的 `systemMessage` 和 `continue` 字段。

2779 3306 

2780<h4 id="precompact-input">3307<h4 id="precompact-input">

2781 PreCompact 输入3308 PreCompact 输入

2782</h4>3309</h4>

2783 3310 

2784除了[通用输入字段](#common-input-fields)外,PreCompact hooks 还接收 `trigger` 和 `custom_instructions`。对于 `manual`,`custom_instructions` 包含用户传入 `/compact` 的内容。对于 `auto`,`custom_instructions` 为空。3311除了 [常见输入字段](#common-input-fields) 外,PreCompact hooks 接收 `trigger` 和 `custom_instructions`。对于 `manual`,`custom_instructions` 包含用户传递到 `/compact` 的内容,当他们传递什么都没有时为 `null`。对于 `auto`,`custom_instructions` 为 `null`。

2785 3312 

2786```json theme={null}3313```json theme={null}

2787{3314{


2790 "cwd": "/Users/...",3317 "cwd": "/Users/...",

2791 "hook_event_name": "PreCompact",3318 "hook_event_name": "PreCompact",

2792 "trigger": "manual",3319 "trigger": "manual",

2793 "custom_instructions": ""3320 "custom_instructions": null

2794}3321}

2795```3322```

2796 3323 


2798 PostCompact3325 PostCompact

2799</h3>3326</h3>

2800 3327 

2801在 Claude Code 完成压缩操作后运行。使用此事件对新的压缩状态做出反应,例如记录生成的摘要或更新外部状态。3328在 Claude Code 完成压缩操作后运行。使用此事件对新压缩状态做出反应,例如记录生成的摘要或更新外部状态。Claude Code 丢弃 PostCompact hook 的 `systemMessage` 和 `continue` 字段。

2802 3329 

2803与 `PreCompact` 相同的匹配器值适用:3330与 `PreCompact` 相同的匹配器值适用:

2804 3331 

2805| 匹配器 | 何时触发 |3332| 匹配器 | 何时触发 |

2806| :------- | :------------- |3333| :------- | :--------------------------------------------------------------------- |

2807| `manual` | 在 `/compact` 后 |3334| `manual` | 在 `/compact` 后 |

2808| `auto` | 在上下文窗口满时自动压缩后 |3335| `auto` | 在自动压缩后,当对话到达 [自动压缩窗口](/docs/zh-CN/model-config#set-the-auto-compact-window) |

2809 3336 

2810<h4 id="postcompact-input">3337<h4 id="postcompact-input">

2811 PostCompact 输入3338 PostCompact 输入

2812</h4>3339</h4>

2813 3340 

2814除了[通用输入字段](#common-input-fields)外,PostCompact hooks 还接收 `trigger` 和 `compact_summary`。`compact_summary` 字段包含压缩操作生成的对话摘要。3341除了 [常见输入字段](#common-input-fields) 外,PostCompact hooks 接收 `trigger` 和 `compact_summary`。`compact_summary` 字段包含压缩操作生成的对话摘要。

2815 3342 

2816```json theme={null}3343```json theme={null}

2817{3344{


2824}3351}

2825```3352```

2826 3353 

2827PostCompact hooks 没有决定控制。它们无法影响压缩结果,但可以执行后续任务。3354PostCompact hooks 没有决策控制。它们无法影响压缩结果,但可以执行后续任务。

3355 

3356<h3 id="premodelswitch">

3357 PreModelSwitch

3358</h3>

3359 

3360在 Claude Code 应用您或客户端请求的模型切换之前运行。使用它来阻止切换、要求确认或在切换发生之前显示它将花费什么。

3361 

3362PreModelSwitch 需要 Claude Code v2.1.251 或更高版本。Claude Code 为这些请求运行它:

3363 

3364* `/model <name>` 和 `/model` 选择器

3365* `Option+P` 或 `Alt+P` 模型选择器

3366* `/config` 中的 Model 设置

3367* 当那改变会话的模型时打开 [快速模式](/docs/zh-CN/fast-mode)

3368* 来自 [Agent SDK](/docs/zh-CN/agent-sdk/typescript#query-object) 主机或 [Remote Control](/docs/zh-CN/remote-control) 的 `set_model` 请求,或 `apply_flag_settings` 请求中的模型更改

3369 

3370Claude Code 不为它自己进行的切换运行 PreModelSwitch hooks,如 [自动模型回退](/docs/zh-CN/model-config#automatic-model-fallback) 或恢复会话时恢复模型。这些更改仅到达 [PostModelSwitch](#postmodelswitch)。

3371 

3372Claude Code 将匹配器与会话切换到的模型的规范名称进行比较,忽略任何 `[1m]` 后缀。别名如 `opus`、日期模型 ID 和提供商特定 ID 如 Amazon Bedrock 模型 ID 都匹配它们解析到的一个规范名称,因此 `claude-opus-5` 涵盖 Opus 5 的每个拼写。

3373 

3374当 Claude Code 无法确定目标的规范名称时,例如仅您的 [LLM 网关](/docs/zh-CN/llm-gateway) 知道的自定义模型 ID,它运行每个 PreModelSwitch hook,无论匹配器如何。阻止的 hook 应该从其输入检查 `to_model` 而不是仅依赖匹配器。

3375 

3376将匹配器写为精确名称、`|` 分隔列表如 `claude-opus-4-6|claude-opus-5` 或正则表达式如 `.*opus.*`。此示例使用精确名称匹配器,也从 hook 输入检查 `to_model`,因此它拒绝切换到 Opus 4.6,通过以代码 2 退出,并让任何其他目标通过:

3377 

3378<Tabs>

3379 <Tab title="macOS/Linux">

3380 命令使用 `jq` 检查 `to_model`:

3381 

3382 ```json theme={null}

3383 {

3384 "hooks": {

3385 "PreModelSwitch": [

3386 {

3387 "matcher": "claude-opus-4-6",

3388 "hooks": [

3389 {

3390 "type": "command",

3391 "command": "jq -e '.to_model | test(\"opus-4-6\")' > /dev/null && { echo 'Opus 4.6 is retired for this project. Use a newer model.' >&2; exit 2; }; exit 0"

3392 }

3393 ]

3394 }

3395 ]

3396 }

3397 }

3398 ```

3399 </Tab>

3400 

3401 <Tab title="Windows (PowerShell)">

3402 注册一个通过 PowerShell 运行脚本的命令 hook:

3403 

3404 ```json theme={null}

3405 {

3406 "hooks": {

3407 "PreModelSwitch": [

3408 {

3409 "matcher": "claude-opus-4-6",

3410 "hooks": [

3411 {

3412 "type": "command",

3413 "command": "powershell.exe",

3414 "args": [

3415 "-NoProfile",

3416 "-ExecutionPolicy",

3417 "Bypass",

3418 "-File",

3419 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-opus-46.ps1"

3420 ]

3421 }

3422 ]

3423 }

3424 ]

3425 }

3426 }

3427 ```

3428 

3429 将此脚本保存到项目中的 `.claude/hooks/block-opus-46.ps1`:

3430 

3431 ```powershell theme={null}

3432 $hookInput = [Console]::In.ReadToEnd() | ConvertFrom-Json

3433 if ($hookInput.to_model -match 'opus-4-6') {

3434 [Console]::Error.WriteLine('Opus 4.6 is retired for this project. Use a newer model.')

3435 exit 2

3436 }

3437 exit 0

3438 ```

3439 </Tab>

3440</Tabs>

3441 

3442要确认 hook 工作,从运行不同模型的会话运行 `/model claude-opus-4-6`。Claude Code 保持当前模型并报告 PreModelSwitch hook 阻止了切换,您的消息作为原因。

3443 

3444<h4 id="premodelswitch-input">

3445 PreModelSwitch 输入

3446</h4>

3447 

3448除了 [常见输入字段](#common-input-fields) 外,PreModelSwitch hooks 接收此表中的字段。最后五个描述重新发送对话到新模型的成本,因此 hook 可以在切换发生之前显示该数字。

3449 

3450| 字段 | 类型 | 描述 |

3451| :-------------------------- | :--------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

3452| `from_model` | string | 切换改变的模型 ID |

3453| `to_model` | string | 切换改变到的模型 ID。匹配器与此模型的规范名称进行比较 |

3454| `requested_model` | string or `null` | 请求命名的模型:别名如 `opus`、完整模型 ID 或当请求是默认模型时 `null` |

3455| `source` | string | 请求来自何处:`"command"` 对于 `/model <name>`、`/config` 中的 Model 设置或打开快速模式;`"picker"` 对于模型选择器;`"sdk"` 对于 `set_model` 请求,或来自 Agent SDK 主机或 Remote Control 的 `apply_flag_settings` 请求中的模型更改 |

3456| `context_tokens` | number | 下一个请求重新发送作为其提示的令牌:主对话中最后响应的输入、缓存读取、缓存创建和输出令牌,合并。第一个响应前为 `0` |

3457| `prompt_cache_warm` | boolean | 当前模型的 prompt cache 是否可能仍然温暖,意味着切换放弃它 |

3458| `cache_ttl` | string | [Prompt cache 生命周期](/docs/zh-CN/prompt-caching#cache-lifetime) Claude Code 为此会话请求:`"5m"` 或 `"1h"` |

3459| `estimated_cache_write_usd` | number | 将 `context_tokens` 写入 `to_model` 上的 prompt cache 的估计成本(美元),以 `cache_ttl` 速率,不包括下一个响应。服务器可能不需要重新缓存整个上下文,因此将其视为估计 |

3460| `pricing` | string | Claude Code 如何定价 `estimated_cache_write_usd`:当您的组织配置了自己的速率时为 `"configured"`,列表价格为 `"catalog"`,或当 `to_model` 没有已知价格且 Claude Code 假设默认速率时为 `"default"` |

3461 

3462此示例显示了在运行 Sonnet 5 的会话中 `/model opus` 的输入:

3463 

3464```json theme={null}

3465{

3466 "session_id": "abc123",

3467 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

3468 "cwd": "/Users/...",

3469 "hook_event_name": "PreModelSwitch",

3470 "from_model": "claude-sonnet-5",

3471 "to_model": "claude-opus-5",

3472 "requested_model": "opus",

3473 "source": "command",

3474 "context_tokens": 182340,

3475 "prompt_cache_warm": true,

3476 "cache_ttl": "5m",

3477 "estimated_cache_write_usd": 1.1396,

3478 "pricing": "catalog"

3479}

3480```

3481 

3482<h4 id="premodelswitch-decision-control">

3483 PreModelSwitch 决策控制

3484</h4>

3485 

3486`PreModelSwitch` hooks 可以取消切换、要求用户确认或让它继续。退出代码 2 或顶级 `decision: "block"` 取消切换。

3487 

3488为了更精细的控制,在 `hookSpecificOutput` 对象中返回 `permissionDecision` 和 `permissionDecisionReason`,如 [PreToolUse](#pretooluse-decision-control)。`PreModelSwitch` 接受 `"allow"`、`"deny"` 和 `"ask"`。它不接受 `"defer"`、`updatedInput` 或 `additionalContext`。下表描述两个字段:

3489 

3490| 字段 | 描述 |

3491| :------------------------- | :--------------------------------------------------------------------------------------------------------------------------- |

3492| `permissionDecision` | `"allow"` 继续并跳过 [当 prompt cache 温暖时 Claude Code 显示的确认](/docs/zh-CN/prompt-caching#switching-models)。`"deny"` 取消切换。`"ask"` 提示用户确认它 |

3493| `permissionDecisionReason` | 对于 `"deny"`,显示给用户作为切换被阻止的原因,或作为 `set_model` 请求的错误返回。对于 `"ask"`,显示在确认提示中。对于 `"allow"` 被忽略 |

3494 

3495仅交互式会话中的 `/model` 可以显示 `"ask"` 提示。在每个其他表面,包括带 `-p` 标志的非交互模式、`/config` 和 `set_model` 请求,Claude Code 将 `"ask"` 视为拒绝。

3496 

3497此示例要求用户确认并引用来自 `context_tokens` 的令牌计数:

3498 

3499```json theme={null}

3500{

3501 "hookSpecificOutput": {

3502 "hookEventName": "PreModelSwitch",

3503 "permissionDecision": "ask",

3504 "permissionDecisionReason": "Switching now re-sends about 180k tokens to the new model. Continue?"

3505 }

3506}

3507```

3508 

3509当多个 PreModelSwitch hooks 返回不同的决策时,优先级为 `deny` > `ask` > `allow`。

3510 

3511Claude Code 显示用户您的 hook 返回的任何 `systemMessage`,无论决策如何,因此成本报告 hook 可以返回 `{"systemMessage": "..."}` 并退出 0。

3512 

3513在其超时之前不响应的 PreModelSwitch hook 阻止切换。在 [PreToolUse](#timeouts) 上,相比之下,超时的命令 hook 让工具调用继续。此事件的默认超时为 30 秒。`PreModelSwitch` 仅运行 `command`、`http` 和 `mcp_tool` hooks,因此 `prompt` 和 `agent` 默认不适用。

3514 

3515以 0 或 2 以外的代码退出且不打印 JSON 决策的 hook 不阻止:Claude Code 显示其 stderr 并应用切换,如 [其他退出代码](#other-exit-codes) 下所述。

3516 

3517<h3 id="postmodelswitch">

3518 PostModelSwitch

3519</h3>

3520 

3521在会话的模型更改后运行。使用它来给 Claude 模型特定的指导,而不编辑每个 CLAUDE.md。

3522 

3523PostModelSwitch 需要 Claude Code v2.1.251 或更高版本。它无法阻止,因为模型已经更改。Claude Code 在任何这些更改后运行 PostModelSwitch hooks:

3524 

3525* 您或客户端请求的切换

3526* [自动模型回退](/docs/zh-CN/model-config#automatic-model-fallback),改变会话的模型

3527* 设置如 [`opusplan`](/docs/zh-CN/model-config#opusplan-model-setting) 进入或离开 plan mode

3528* Claude Code 恢复会话时恢复模型

3529 

3530Claude Code 不为来自 [回退模型链](/docs/zh-CN/model-config#fallback-model-chains) 的模型运行 PostModelSwitch hooks,因为该替换持续一个回合并保持会话的模型不变。

3531 

3532匹配器遵循与 [PreModelSwitch](#premodelswitch) 相同的规则:Claude Code 将其与会话切换到的模型的规范名称进行比较。

3533 

3534此示例在会话的模型更改为任何 Opus 模型时添加指导:

3535 

3536```json theme={null}

3537{

3538 "hooks": {

3539 "PostModelSwitch": [

3540 {

3541 "matcher": ".*opus.*",

3542 "hooks": [

3543 {

3544 "type": "command",

3545 "command": "echo 'On Opus, delegate implementation work to subagents and keep this conversation for planning and review.'"

3546 }

3547 ]

3548 }

3549 ]

3550 }

3551}

3552```

3553 

3554要确认 hook 工作,从运行不同模型的会话切换到 Opus 模型,例如从 Sonnet 会话运行 `/model opus`,然后询问 Claude 它对当前模型有什么指导。

3555 

3556<h4 id="postmodelswitch-input">

3557 PostModelSwitch 输入

3558</h4>

3559 

3560PostModelSwitch hooks 接收与 [PreModelSwitch](#premodelswitch-input) 相同的字段,其中 `hook_event_name` 设置为 `"PostModelSwitch"` 和两个更多 `source` 值:`"auto"` 对于自动回退或 Claude Code 自己进行的其他更改,以及 `"resume"` 对于恢复会话时恢复的模型。

3561 

3562当 `source` 为 `"auto"` 时,`requested_model` 为 `null`。当 `source` 为 `"resume"` 时,它是 Claude Code 恢复的保存模型设置。

3563 

3564<h4 id="postmodelswitch-decision-control">

3565 PostModelSwitch 决策控制

3566</h4>

3567 

3568Claude Code 获取您的 hook 在退出 0 时的 [纯文本 stdout](#exit-code-0),或来自 JSON 输出的 `additionalContext`,并在切换后的下一个请求中将其传递给 Claude。除了所有 hooks 可用的 [JSON 输出字段](#json-output) 外,您可以返回:

3569 

3570| 字段 | 描述 |

3571| :------------------ | :----------------------------------------------------------------------------------------- |

3572| `additionalContext` | 与下一个请求一起添加到 Claude 上下文的字符串。有关文本如何传递以及放入其中的内容,请参阅 [为 Claude 添加上下文](#add-context-for-claude) |

3573 

3574如果 hook 在您发送下一个提示后五秒内未完成,Claude Code 发送该请求而不输出,并将其附加到以下请求。如果模型在下一个请求之前更改多次,Claude Code 仅传递最后一个切换目标模型的输出。

2828 3575 

2829<h3 id="sessionend">3576<h3 id="sessionend">

2830 SessionEnd3577 SessionEnd

2831</h3>3578</h3>

2832 3579 

2833当 Claude Code 会话结束时运行。用于清理任务、记录会话统计或保存会话状态。支持匹配器以按退出原因过滤。3580在 Claude Code 会话结束时运行。对于清理任务、记录会话统计或保存会话状态很有用。支持匹配器以按退出原因过滤。

2834 3581 

2835hook 输入中的 `reason` 字段指示会话为何结束:3582`reason` 字段在 hook 输入中指示会话为什么结束:

2836 3583 

2837| 原因 | 描述 |3584| 原因 | 描述 |

2838| :---------------------------- | :------------------- |3585| :---------------------------- | :------------------------------------------------------- |

2839| `clear` | 会话使用 `/clear` 命令清除 |3586| `clear` | 使用 `/clear` 命令清除会话 |

2840| `resume` | 通过交互式 `/resume` 切换会话 |3587| `resume` | 通过交互式 `/resume` 切换会话 |

2841| `logout` | 用户登出 |3588| `logout` | 用户登出 |

2842| `prompt_input_exit` | 用户在提示输入可见时退出 |3589| `prompt_input_exit` | 用户在提示输入可见时退出 |

2843| `bypass_permissions_disabled` | 绕过权限模式被禁用 |

2844| `other` | 其他退出原因 |3590| `other` | 其他退出原因 |

3591| `bypass_permissions_disabled` | 在 v2.1.234 中删除;Claude Code 不发送它。从您的 `SessionEnd` 匹配器中删除它 |

2845 3592 

2846<h4 id="sessionend-input">3593<h4 id="sessionend-input">

2847 SessionEnd 输入3594 SessionEnd 输入

2848</h4>3595</h4>

2849 3596 

2850除了[通用输入字段](#common-input-fields)外,SessionEnd hooks 还接收 `reason` 字段,指示会话为何结束。有关所有值,请参阅上面的原因表。3597除了 [常见输入字段](#common-input-fields) 外,SessionEnd hooks 接收指示会话为什么结束的 `reason` 字段。有关所有值,请参阅上面的 [原因表](#sessionend)。

2851 3598 

2852```json theme={null}3599```json theme={null}

2853{3600{


2859}3606}

2860```3607```

2861 3608 

2862SessionEnd hooks 没有决定控制。它们无法阻止会话终止,但可以执行清理任务。3609SessionEnd hooks 没有决策控制。它们无法阻止会话终止,但可以执行清理任务。Claude Code 丢弃它们的 [JSON 输出字段](#json-output),如 `systemMessage`。

3610 

3611SessionEnd hooks 的默认超时为 1.5 秒。当您退出、运行 `/clear` 或使用交互式 `/resume` 切换会话时它适用。您可以通过两种方式给 hook 更多时间:

2863 3612 

2864SessionEnd hooks 的默认超时为 1.5 秒。这适用于会话退出、`/clear` 和通过交互式 `/resume` 切换会话。如果 hook 需要更多时间,在 hook 配置中设置 `timeout`。总体预算自动提高到配置的最高每个 hook 超时,最多 60 秒。在插件提供的 hooks 上设置的超时不会提高预算。要显式覆盖预算,请在毫秒中设置 `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` 环境变量。3613* **每个 hook `timeout`**:在该 hook 的配置中设置 `timeout`。整体预算自动上升以匹配您的设置文件中最高的每个 hook `timeout`,最多 60 秒。如果您以这种方式提高预算,没有自己的 `timeout` 的 hook 仍然保持默认值。在插件提供的 hooks 上设置的超时不提高预算。

3614* **`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`**:设置此环境变量(毫秒)以显式覆盖预算。您设置的值也成为每个没有自己的 `timeout` 的 hook 的超时。

3615 

3616此示例将预算设置为 5 秒:

2865 3617 

2866```bash theme={null}3618```bash theme={null}

2867CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude3619CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude

2868```3620```

2869 3621 

3622在 v2.1.268 之前,`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` 仅提高整体预算,没有自己的 `timeout` 的 hook 在 1.5 秒后仍然被取消。

3623 

2870<h3 id="elicitation">3624<h3 id="elicitation">

2871 Elicitation3625 Elicitation

2872</h3>3626</h3>

2873 3627 

2874当 MCP 服务器在任务中途请求用户输入时运行。默认情况下,Claude Code 显示交互式对话供用户响应。Hooks 可以拦截此请求并以编程方式响应,完全跳过对话。3628在 MCP 服务器请求用户输入中任务时运行。默认情况下,Claude Code 显示交互式对话供用户响应。Hooks 可以拦截此请求并以编程方式响应,完全跳过对话。

2875 3629 

2876匹配器字段与 MCP 服务器名称匹配。3630匹配器字段匹配 MCP 服务器名称。

2877 3631 

2878<h4 id="elicitation-input">3632<h4 id="elicitation-input">

2879 Elicitation 输入3633 Elicitation 输入

2880</h4>3634</h4>

2881 3635 

2882除了[通用输入字段](#common-input-fields)外,Elicitation hooks 还接收 `mcp_server_name`、`message` 和可选的 `mode`、`url`、`elicitation_id` 和 `requested_schema` 字段。3636除了 [常见输入字段](#common-input-fields) 外,Elicitation hooks 接收 `mcp_server_name`、`message` 和可选的 `mode`、`url`、`elicitation_id` 和 `requested_schema` 字段。

2883 3637 

2884对于 form 模式 elicitation(最常见的情况):3638对于表单模式引出,最常见的情况:

2885 3639 

2886```json theme={null}3640```json theme={null}

2887{3641{

2888 "session_id": "abc123",3642 "session_id": "abc123",

2889 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3643 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2890 "cwd": "/Users/...",3644 "cwd": "/Users/...",

2891 "permission_mode": "default",

2892 "hook_event_name": "Elicitation",3645 "hook_event_name": "Elicitation",

2893 "mcp_server_name": "my-mcp-server",3646 "mcp_server_name": "my-mcp-server",

2894 "message": "Please provide your credentials",3647 "message": "Please provide your credentials",


2902}3655}

2903```3656```

2904 3657 

2905对于 URL 模式 elicitation(基于浏览器的身份验证):3658对于 URL 模式引出,用于基于浏览器的身份验证:

2906 3659 

2907```json theme={null}3660```json theme={null}

2908{3661{

2909 "session_id": "abc123",3662 "session_id": "abc123",

2910 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3663 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2911 "cwd": "/Users/...",3664 "cwd": "/Users/...",

2912 "permission_mode": "default",

2913 "hook_event_name": "Elicitation",3665 "hook_event_name": "Elicitation",

2914 "mcp_server_name": "my-mcp-server",3666 "mcp_server_name": "my-mcp-server",

2915 "message": "Please authenticate",3667 "message": "Please authenticate",


2922 Elicitation 输出3674 Elicitation 输出

2923</h4>3675</h4>

2924 3676 

2925要以编程方式响应而不显示对话,返回带有 `hookSpecificOutput` 的 JSON 对象:3677要以编程方式响应而不显示对话,返回一个带有 `hookSpecificOutput` 的 JSON 对象:

2926 3678 

2927```json theme={null}3679```json theme={null}

2928{3680{


2937```3689```

2938 3690 

2939| 字段 | 值 | 描述 |3691| 字段 | 值 | 描述 |

2940| :-------- | :-------------------------- | :--------------------------------------- |3692| :-------- | :-------------------------- | :----------------------------------- |

2941| `action` | `accept`、`decline`、`cancel` | 是否接受、拒绝或取消请求 |3693| `action` | `accept`、`decline`、`cancel` | 是否接受、拒绝或取消请求 |

2942| `content` | object | 要提交的 form 字段值。仅在 `action` 为 `accept` 时使用 |3694| `content` | object | 要提交的表单字段值。仅在 `action` 为 `accept` 时使用 |

3695 

3696退出代码 2 拒绝引出。Claude Code 不在任何地方显示您的 stderr 消息。

2943 3697 

2944退出代码 2 拒绝 elicitation 并向用户显示 stderr。3698Claude Code 作用于 Elicitation hook 的 JSON 输出中的 `hookSpecificOutput`,并丢弃 `systemMessage` 和 `continue`。

2945 3699 

2946<h3 id="elicitationresult">3700<h3 id="elicitationresult">

2947 ElicitationResult3701 ElicitationResult

2948</h3>3702</h3>

2949 3703 

2950在用户响应 MCP elicitation 后运行。Hooks 可以观察、修改或阻止响应,然后将其发送回 MCP 服务器。3704在用户响应 MCP 引出后运行。Hooks 可以观察、修改或阻止响应,然后将其发送回 MCP 服务器。

2951 3705 

2952匹配器字段与 MCP 服务器名称匹配。3706匹配器字段匹配 MCP 服务器名称。

2953 3707 

2954<h4 id="elicitationresult-input">3708<h4 id="elicitationresult-input">

2955 ElicitationResult 输入3709 ElicitationResult 输入

2956</h4>3710</h4>

2957 3711 

2958除了[通用输入字段](#common-input-fields)外,ElicitationResult hooks 还接收 `mcp_server_name`、`action` 和可选的 `mode`、`elicitation_id` 和 `content` 字段。3712除了 [常见输入字段](#common-input-fields) 外,ElicitationResult hooks 接收 `mcp_server_name`、`action` 和可选的 `mode`、`elicitation_id` 和 `content` 字段。

2959 3713 

2960```json theme={null}3714```json theme={null}

2961{3715{

2962 "session_id": "abc123",3716 "session_id": "abc123",

2963 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3717 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",

2964 "cwd": "/Users/...",3718 "cwd": "/Users/...",

2965 "permission_mode": "default",

2966 "hook_event_name": "ElicitationResult",3719 "hook_event_name": "ElicitationResult",

2967 "mcp_server_name": "my-mcp-server",3720 "mcp_server_name": "my-mcp-server",

2968 "action": "accept",3721 "action": "accept",


2976 ElicitationResult 输出3729 ElicitationResult 输出

2977</h4>3730</h4>

2978 3731 

2979要覆盖用户的响应,返回带有 `hookSpecificOutput` 的 JSON 对象:3732要覆盖用户的响应,返回一个带有 `hookSpecificOutput` 的 JSON 对象:

2980 3733 

2981```json theme={null}3734```json theme={null}

2982{3735{


2989```3742```

2990 3743 

2991| 字段 | 值 | 描述 |3744| 字段 | 值 | 描述 |

2992| :-------- | :-------------------------- | :-------------------------------------- |3745| :-------- | :-------------------------- | :---------------------------------- |

2993| `action` | `accept`、`decline`、`cancel` | 覆盖用户的操作 |3746| `action` | `accept`、`decline`、`cancel` | 覆盖用户的操作 |

2994| `content` | object | 覆盖 form 字段值。仅在 `action` 为 `accept` 时有意义 |3747| `content` | object | 覆盖表单字段值。仅在 `action` 为 `accept` 时有意义 |

3748 

3749退出代码 2 阻止响应,将有效操作更改为 `decline`。Claude Code 不在任何地方显示您的 stderr 消息。

2995 3750 

2996退出代码 2 阻止响应,将有效操作更改为 `decline`。3751Claude Code 作用于 ElicitationResult hook 的 JSON 输出中的 `hookSpecificOutput`,并丢弃 `systemMessage` 和 `continue`。

2997 3752 

2998<h2 id="prompt-based-hooks">3753<h2 id="prompt-based-hooks">

2999 基于提示的 hooks3754 基于提示的 hooks


3021 3776 

3022* `ConfigChange`3777* `ConfigChange`

3023* `CwdChanged`3778* `CwdChanged`

3779* `DirectoryAdded`

3024* `Elicitation`3780* `Elicitation`

3025* `ElicitationResult`3781* `ElicitationResult`

3026* `FileChanged`3782* `FileChanged`

3027* `InstructionsLoaded`3783* `InstructionsLoaded`

3784* `MessageDisplay`

3028* `Notification`3785* `Notification`

3029* `PostCompact`3786* `PostCompact`

3787* `PostModelSwitch`

3030* `PreCompact`3788* `PreCompact`

3789* `PreModelSwitch`

3031* `SessionEnd`3790* `SessionEnd`

3032* `StopFailure`3791* `StopFailure`

3033* `SubagentStart`3792* `SubagentStart`

3034* `WorktreeCreate`3793* `WorktreeCreate`

3035* `WorktreeRemove`3794* `WorktreeRemove`

3036 3795 

3037`SessionStart` 和 `Setup` 支持 `command` 和 `mcp_tool` hooks。它们不支持 `http`、`prompt` 或 `agent` hooks。3796`SessionStart` 和 `Setup` 支持 `command` 和 `mcp_tool` hooks,[MCP tool hook 字段](#mcp-tool-hook-fields)描述了它们的 `mcp_tool` hooks 何时运行。它们不支持 `http`、`prompt` 或 `agent` hooks。

3038 3797 

3039<h3 id="how-prompt-based-hooks-work">3798<h3 id="how-prompt-based-hooks-work">

3040 基于提示的 hooks 如何工作3799 基于提示的 hooks 如何工作


3050 提示 hook 配置3809 提示 hook 配置

3051</h3>3810</h3>

3052 3811 

3053将 `type` 设置为 `"prompt"` 并提供 `prompt` 字符串而不是 `command`。使用 `$ARGUMENTS` 占位符将 hook 的 JSON 输入数据注入到您的提示文本中。Claude Code 将组合的提示和输入发送到快速 Claude 模型,该模型返回 JSON 决定。3812将 `type` 设置为 `"prompt"` 并提供 `prompt` 字符串而不是 `command`。使用 `$ARGUMENTS` 占位符将 hook 的 JSON 输入数据注入到您的提示文本中。

3054 3813 

3055此 `Stop` hook 要求 LLM 在允许 Claude 完成之前评估是否应该停止:3814此 `Stop` hook 要求 LLM 在允许 Claude 完成之前评估是否应该停止:

3056 3815 


3072```3831```

3073 3832 

3074| 字段 | 必需 | 描述 |3833| 字段 | 必需 | 描述 |

3075| :---------------- | :- | :-------------------------------------------------------------------------------------------------------------------------------------------- |3834| :---------------- | :- | :----------------------------------------------------------------------------------------------------- |

3076| `type` | 是 | 必须是 `"prompt"` |3835| `type` | 是 | 必须是 `"prompt"` |

3077| `prompt` | 是 | 要发送给 LLM 的提示文本。使用 `$ARGUMENTS` 作为 hook 输入 JSON 的占位符。如果 `$ARGUMENTS` 不存在,输入 JSON 被追加到提示 |3836| `prompt` | 是 | 要发送给 LLM 的提示文本。使用 `$ARGUMENTS` 作为 hook 输入 JSON 的占位符。如果 `$ARGUMENTS` 不存在,输入 JSON 被追加到提示 |

3078| `model` | 否 | 用于评估的模型。默认为快速模型 |3837| `model` | 否 | 用于评估的模型。默认为快速模型 |

3079| `timeout` | 否 | 超时(秒)。默认值:30 |3838| `timeout` | 否 | 超时(秒)。默认值:30 |

3080| `continueOnBlock` | 否 | 当提示返回 `ok: false` 时,将原因反馈给 Claude 并继续转轮而不是停止。默认值:`false`。在生成的 `decision: "block"` 上实现为 `continue: true`。有关每个事件的行为,请参阅[响应架构](#response-schema) |3839| `continueOnBlock` | 否 | 在适用的事件上,`true` 将 `ok: false` 原因反馈给 Claude 并继续而不是结束转轮。默认值:`false`。有关每个事件的行为,请参阅[响应架构](#response-schema) |

3081 3840 

3082<h3 id="response-schema">3841<h3 id="response-schema">

3083 响应架构3842 响应架构


3088```json theme={null}3847```json theme={null}

3089{3848{

3090 "ok": true | false,3849 "ok": true | false,

3091 "reason": "Explanation for the decision"3850 "reason": "Explanation for the decision",

3851 "impossible": true | false

3092}3852}

3093```3853```

3094 3854 

3095| 字段 | 描述 |3855| 字段 | 描述 |

3096| :------- | :---------------------------------------------------- |3856| :----------- | :-------------------------------------------------------------------------------------------------------------- |

3097| `ok` | `true` 允许。`false` 产生 `decision: "block"`。请参阅下面的每个事件行为 |3857| `ok` | `true` 允许。对于 `false`,请参阅下面的每个事件行为 |

3098| `reason` | 当 `ok` 为 `false` 时必需。用作阻止原因 |3858| `reason` | 当 `ok` 为 `false` 时必需 |

3859| `impossible` | 可选。当模型判断条件永远无法满足时,模型使用 `ok: false` 返回它。在 `Stop` 和 `SubagentStop` 上,Claude Code 随后让转轮结束而不是反馈原因。代理 hooks 和其他事件忽略它 |

3099 3860 

3100`ok: false` 时发生的情况取决于事件:3861`ok: false` 时发生的情况取决于事件:

3101 3862 

3102* `Stop` 和 `SubagentStop`:原因被反馈给 Claude 作为其下一条指令,转轮继续3863* `Stop` 和 `SubagentStop`:原因被反馈给 Claude 作为其下一条指令,转轮继续,除非响应也设置 `impossible: true`,在这种情况下 Claude Code 允许停止,转轮结束

3103* `PreToolUse`:工具调用被拒绝,原因作为工具错误返回给 Claude,等同于命令 hook 的 `permissionDecision: "deny"`3864* `PreToolUse`:工具调用被拒绝;默认情况下转轮结束,拒绝原因在聊天中显示为警告行。设置 `continueOnBlock: true` 以改为将原因返回给 Claude 作为工具错误,以便它可以调整并继续,等同于命令 hook 的 `permissionDecision: "deny"`。在 v2.1.210 之前,拒绝原因被返回给 Claude 作为工具错误,转轮继续

3104* `PostToolUse`:默认情况下转轮结束,原因在聊天中显示为警告行。设置 `continueOnBlock: true` 以将原因反馈给 Claude 并继续转轮3865* `PostToolUse`:默认情况下转轮结束,原因在聊天中显示为警告行。设置 `continueOnBlock: true` 以将原因反馈给 Claude 并继续转轮

3105* `PostToolBatch`、`UserPromptSubmit` 和 `UserPromptExpansion`:转轮结束,原因显示为警告行。这些事件在 `decision: "block"` 上结束转轮,无论 `continue` 如何3866* `PostToolBatch`、`UserPromptSubmit` 和 `UserPromptExpansion`:转轮结束,原因显示为警告行。这些事件在 `decision: "block"` 上结束转轮,无论 `continue` 如何

3106* `PostToolUseFailure`、`TaskCreated` 和 `TaskCompleted`:原因作为工具错误返回给 Claude,类似于 `PreToolUse`3867* `PostToolUseFailure` 和 `TaskCreated`:原因作为工具错误返回给 Claude,转轮继续,无论 `continueOnBlock` 如何

3868* `TaskCompleted`:当任务在转轮期间被标记为完成时触发时,原因作为工具错误返回给 Claude,转轮继续,无论 `continueOnBlock` 如何。当它因队友停止而触发时,它的行为类似于 `TeammateIdle` 并默认停止队友

3107* `TeammateIdle`:默认情况下队友停止,原因显示为警告行。设置 `continueOnBlock: true` 以将原因反馈给队友并保持其继续工作3869* `TeammateIdle`:默认情况下队友停止,原因显示为警告行。设置 `continueOnBlock: true` 以将原因反馈给队友并保持其继续工作

3108* `PermissionRequest`:`ok: false` 无效。要从 hook 拒绝批准,请使用[命令 hook](#command-hook-fields),返回 `hookSpecificOutput.decision.behavior: "deny"`3870* `PermissionRequest`:`ok: false` 无效。要从 hook 拒绝批准,请使用[命令 hook](#command-hook-fields),返回 `hookSpecificOutput.decision.behavior: "deny"`

3109* `PermissionDenied`:`ok: false` 无效,因为拒绝已经发生。此事件读取的唯一输出是 `hookSpecificOutput.retry`,提示和代理 hooks 无法设置 — 它们在此事件上运行,但其输出被丢弃。使用[命令 hook](#command-hook-fields)返回 `retry`3871* `PermissionDenied`:`ok: false` 无效,因为拒绝已经发生。此事件读取的唯一输出是 `hookSpecificOutput.retry`,提示和代理 hooks 无法设置。它们在此事件上运行,但其输出被丢弃。使用[命令 hook](#command-hook-fields)返回 `retry`

3110 3872 

3111如果您需要对任何事件进行更精细的控制,请使用[命令 hook](#command-hook-fields),其中包含[决定控制](#decision-control)中描述的每个事件字段。3873如果您需要对任何事件进行更精细的控制,请使用[命令 hook](#command-hook-fields),其中包含[决定控制](#decision-control)中描述的每个事件字段。

3112 3874 


3114 检查多个条件后再停止3876 检查多个条件后再停止

3115</h3>3877</h3>

3116 3878 

3117此 `Stop` hook 使用详细提示检查三个条件,然后允许 Claude 停止。`SubagentStop` hooks 使用相同的格式来评估[子代理](/docs/zh-CN/sub-agents)是否应该停止。如果 `"ok"` 为 `false`,Claude 继续工作,提供的原因作为其下一条指令:3879此 `Stop` hook 使用详细提示检查三个条件,然后允许 Claude 停止。`SubagentStop` hooks 使用相同的格式来评估[子代理](/docs/zh-CN/sub-agents)是否应该停止。如果模型因条件尚未满足而返回 `"ok": false`,Claude 继续工作,提供的原因作为其下一条指令:

3118 3880 

3119```json theme={null}3881```json theme={null}

3120{3882{


31531. Claude Code 生成一个 subagent,带有您的提示和 hook 的 JSON 输入39151. Claude Code 生成一个 subagent,带有您的提示和 hook 的 JSON 输入

31542. Subagent 可以使用 Read、Grep 和 Glob 等工具进行调查39162. Subagent 可以使用 Read、Grep 和 Glob 等工具进行调查

31553. 在最多 50 轮后,subagent 返回结构化的 `{ "ok": true/false }` 决定39173. 在最多 50 轮后,subagent 返回结构化的 `{ "ok": true/false }` 决定

31564. Claude Code 以与提示 hook 相同的方式处理决定39184. Claude Code 允许该操作(如果 `ok` 是 `true`)。如果 `ok` 是 `false`,Claude Code 处理阻止的方式与提示 hook 在该事件上具有 `continueOnBlock: true` 的方式相同,如[响应架构](#response-schema)下所列

3157 3919 

3158代理 hooks 在验证需要检查实际文件或测试输出时很有用,而不仅仅是评估 hook 输入数据。3920代理 hooks 在验证需要检查实际文件或测试输出时很有用,而不仅仅是单独评估 hook 输入数据。

3159 3921 

3160<h3 id="agent-hook-configuration">3922<h3 id="agent-hook-configuration">

3161 代理 hook 配置3923 代理 hook 配置

3162</h3>3924</h3>

3163 3925 

3164将 `type` 设置为 `"agent"` 并提供 `prompt` 字符串。配置字段与[提示 hooks](#prompt-hook-configuration)相同,但超时更长:3926将 `type` 设置为 `"agent"` 并提供 `prompt` 字符串,使用 `$ARGUMENTS` 作为 hook 输入 JSON 的占位符。配置字段与[提示 hooks](#prompt-hook-configuration)相同,除了代理 hooks 具有更长的默认超时时间 60 秒,并且没有 `continueOnBlock` 字段。

3165 

3166| 字段 | 必需 | 描述 |

3167| :-------- | :- | :----------------------------------------------- |

3168| `type` | 是 | 必须是 `"agent"` |

3169| `prompt` | 是 | 描述要验证的内容的提示。使用 `$ARGUMENTS` 作为 hook 输入 JSON 的占位符 |

3170| `model` | 否 | 要使用的模型。默认为快速模型 |

3171| `timeout` | 否 | 超时(秒)。默认值:60 |

3172 3927 

3173响应架构与提示 hooks 相同:`{ "ok": true }` 允许或 `{ "ok": false, "reason": "..." }` 阻止。3928响应架构是 `{ "ok": true }` 允许或 `{ "ok": false, "reason": "..." }` 阻止。在 `ok: false` 时,Claude Code 处理代理 hook 的方式与处理同一事件上具有 `continueOnBlock: true` 的[提示 hook](#response-schema) 的方式相同;代理 hooks 没有 `continueOnBlock` 字段,并且不支持提示 hook 的 `impossible` 字段。

3174 3929 

3175此 `Stop` hook 验证所有单元测试通过,然后允许 Claude 完成:3930此 `Stop` hook 验证所有单元测试通过,然后允许 Claude 完成:

3176 3931 


3204 3959 

3205将 `"async": true` 添加到命令 hook 的配置以在后台运行它而不阻止 Claude。此字段仅在 `type: "command"` hooks 上可用。3960将 `"async": true` 添加到命令 hook 的配置以在后台运行它而不阻止 Claude。此字段仅在 `type: "command"` hooks 上可用。

3206 3961 

3207此 hook 在每个 `Write` 工具调用后运行测试脚本。Claude 立即继续工作,同时 `run-tests.sh` 执行最多 120 秒。脚本完成时,其输出在下一个对话轮次上传递:3962此 hook 在每个 `Write` 工具调用后运行测试脚本。Claude 立即继续工作,同时 `run-tests.sh` 执行。脚本完成时,其输出在下一个对话轮次上传递:

3208 3963 

3209```json theme={null}3964```json theme={null}

3210{3965{


3216 {3971 {

3217 "type": "command",3972 "type": "command",

3218 "command": "/path/to/run-tests.sh",3973 "command": "/path/to/run-tests.sh",

3219 "async": true,3974 "async": true

3220 "timeout": 120

3221 }3975 }

3222 ]3976 ]

3223 }3977 }


3226}3980}

3227```3981```

3228 3982 

3229`timeout` 字段设置后台进程的最大时间(秒)。如果未指定,异步 hooks 使用与同步 hooks 相同的 10 分钟默认值。3983一旦异步 hook 在后台运行,Claude Code 不会对其强制执行 `timeout`。Claude Code 仍然对使用 `asyncRewake` 运行的 hook 强制执行 `timeout`。

3984 

3985Claude Code 仅在会话运行时传递异步 hook 的结果:

3986 

3987* 在[非交互模式](/docs/zh-CN/headless)中使用 `-p` 标志,Claude Code 在拆卸时杀死任何仍在运行的异步 hook,并以 `cancelled` 结果完成它

3988* 如果你的 hook 的工作必须超越 `claude -p` 会话,从它启动一个完全分离的进程

3230 3989 

3231<h3 id="how-async-hooks-execute">3990<h3 id="how-async-hooks-execute">

3232 异步 Hooks 如何执行3991 异步 Hooks 如何执行


3234 3993 

3235当异步 hook 触发时,Claude Code 启动 hook 进程并立即继续,不等待其完成。Hook 通过 stdin 接收与同步 hook 相同的 JSON 输入。3994当异步 hook 触发时,Claude Code 启动 hook 进程并立即继续,不等待其完成。Hook 通过 stdin 接收与同步 hook 相同的 JSON 输入。

3236 3995 

3237后台进程退出后,如果 hook 产生了带有 `additionalContext` 字段的 JSON 响应,该内容在下一个对话轮次作为上下文传递给 Claude。`systemMessage` 字段显示给你,而不是 Claude。3996后台进程退出后,Claude Code 从 hook 的 JSON 响应中传递 `additionalContext` 和 `systemMessage` 字段给 Claude 在下一个对话轮次。与同步 hook 的 `systemMessage` 不同,这两个字段都不会显示给你。

3238 3997 

3239Claude Code 根据与同步 hooks 相同的[输出架构](#json-output)验证 JSON 响应,并删除任何值类型错误的字段,例如不是字符串的 `systemMessage`,而不是传递它。使用 `--debug` 运行以查看命名每个删除字段的警告。在 v2.1.202 之前,来自异步 hook 的格式错误的 JSON 输出可能会导致会话崩溃,并且每次恢复会话时崩溃都会重复发生。3998Claude Code 根据与同步 hooks 相同的[输出架构](#json-output)验证 JSON 响应,并删除任何值类型错误的字段,例如不是字符串的 `systemMessage`,而不是传递它。使用 `--debug` 运行以查看命名每个删除字段的警告。在 v2.1.202 之前,来自异步 hook 的格式错误的 JSON 输出可能会导致会话崩溃,并且每次恢复会话时崩溃都会重复发生。

3240 3999 


3284 "type": "command",4043 "type": "command",

3285 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",4044 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",

3286 "args": [],4045 "args": [],

3287 "async": true,4046 "async": true

3288 "timeout": 300

3289 }4047 }

3290 ]4048 ]

3291 }4049 }


3298 限制4056 限制

3299</h3>4057</h3>

3300 4058 

3301异步 hooks 与同步 hooks 相比有几个限制:4059异步 hooks 与同步 hooks 相比有额外的约束:

3302 4060 

3303* 仅 `type: "command"` hooks 支持 `async`。基于提示的 hooks 无法异步运行。4061* Hook 输出在下一个对话轮次传递。如果会话空闲,响应等待直到下一个用户交互。例外:退出代码为 2 的 `asyncRewake` hook 即使在会话空闲时也会立即唤醒 Claude。

3304* 异步 hooks 无法阻止工具调用或返回决定。到 hook 完成时,触发操作已经进行。

3305* Hook 输出在下一个对话轮次传递。如果会话空闲,响应等待直到下一个用户交互。例外:`asyncRewake` hook 在退出代码 2 时立即唤醒 Claude,即使会话空闲。

3306* 每次执行创建一个单独的后台进程。同一异步 hook 的多个触发之间没有去重。4062* 每次执行创建一个单独的后台进程。同一异步 hook 的多个触发之间没有去重。

3307 4063 

3308<h2 id="security-considerations">4064<h2 id="security-considerations">


3313 免责声明4069 免责声明

3314</h3>4070</h3>

3315 4071 

3316命令 hooks 使用您的系统用户的完整权限运行。

3317 

3318<Warning>4072<Warning>

3319 命令 hooks 使用您的完整用户权限执行 shell 命令。它们可以修改、删除或访问您的用户帐户可以访问的任何文件。在将任何 hook 命令添加到您的配置之前,请审查并测试它们。4073 命令 hooks 使用您的完整用户权限执行 shell 命令。它们可以修改、删除或访问您的用户帐户可以访问的任何文件。在将任何 hook 命令添加到您的配置之前,请审查并测试它们。

3320</Warning>4074</Warning>

3321 4075 

4076<h3 id="workspace-trust">

4077 工作区信任

4078</h3>

4079 

4080Claude Code 在运行来自设置文件的任何 hook 之前会检查工作区信任。什么被视为受信任取决于会话类型:

4081 

4082* **交互式会话**:Claude Code 会保留来自每个设置文件的 hooks,包括您自己的 `~/.claude/settings.json`,直到您为该文件夹接受[工作区信任对话框](/docs/zh-CN/permissions#project-allow-rules-and-workspace-trust),或为其信任扩展到的父目录接受

4083* **`-p` 或 SDK 会话**:Claude Code 从不显示对话框,并将该文件夹视为受信任的,因此在您从未信任过的文件夹中运行存储库的 `.claude/settings.json` 中提交的 hooks

4084 

4085在您对存储库进行脚本化 `claude -p` 之前,如果您没有编写该存储库,请审查其 `.claude/` 设置文件,使用 [`--bare`](/docs/zh-CN/headless#start-faster-with-bare-mode) 开始,或[为该运行关闭 hooks](#disable-or-remove-hooks),使用 `--settings '{"disableAllHooks": true}'`。项目子代理中的 Frontmatter hooks 遵循比设置文件 hooks 更严格的规则。[在您信任文件夹之前运行的内容](/docs/zh-CN/permissions#what-runs-before-you-trust-a-folder)按会话类型列出每种存储库内容。

4086 

3322<h3 id="security-best-practices">4087<h3 id="security-best-practices">

3323 安全最佳实践4088 安全最佳实践

3324</h3>4089</h3>


3335 Windows PowerShell 工具4100 Windows PowerShell 工具

3336</h2>4101</h2>

3337 4102 

3338在 Windows 上,您可以通过在命令 hook 上设置 `"shell": "powershell"` 在 PowerShell 中运行单个 hooks。Hooks 直接生成 PowerShell,因此这适用于是否设置了 `CLAUDE_CODE_USE_POWERSHELL_TOOL`。Claude Code 自动检测 `pwsh.exe`(PowerShell 7 及更高版本的可执行文件),并回退到 `powershell.exe`(Windows PowerShell 5.1)。4103在 Windows 上,您可以通过在命令 hook 上设置 `"shell": "powershell"` 在 PowerShell 中运行单个 hooks。Claude Code 自动检测 `pwsh.exe`(PowerShell 7 及更高版本的可执行文件),并回退到 `powershell.exe`(Windows PowerShell 5.1)。

3339 4104 

3340```json theme={null}4105```json theme={null}

3341{4106{


3376 调试 hooks4141 调试 hooks

3377</h2>4142</h2>

3378 4143 

3379Hook 执行详细信息,包括哪些 hooks 匹配、它们的退出代码和完整 stdout 和 stderr,被写入调试日志文件。使用 `claude --debug-file <path>` 启动 Claude Code 以将日志写入已知位置,或运行 `claude --debug` 并在 `~/.claude/debug/<session-id>.txt` 读取日志。`--debug` 标志不打印到终端。4144Hook 执行详细信息被写入调试日志文件。使用 `claude --debug-file <path>` 启动 Claude Code 以将日志写入已知位置,或运行 `claude --debug` 并在 `~/.claude/debug/<session-id>.txt` 读取日志。`--debug` 标志不打印到终端。

4145 

4146例如,在 `Write` 上的 `PostToolUse` hook,其命令打印 `hook-ran` 会产生如下条目:

3380 4147 

3381```text theme={null}4148```text theme={null}

3382[DEBUG] Executing hooks for PostToolUse:Write41492026-07-19T02:03:24.382Z [DEBUG] Hook output does not start with {, treating as plain text

3383[DEBUG] Found 1 hook commands to execute41502026-07-19T02:03:24.382Z [DEBUG] "Hook PostToolUse:Write (PostToolUse) success:\nhook-ran"

3384[DEBUG] Executing hook command: <Your command> with timeout 600000ms

3385[DEBUG] Hook command completed with status 0: <Your stdout>

3386```4151```

3387 4152 

3388对于更细粒度的 hook 匹配详细信息,设置 `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` 以查看额外的日志行,例如 hook 匹配器计数和查询匹配。4153对于更细粒度的 hook 匹配详细信息,设置 `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` 以查看额外的日志行,例如 hook 匹配器计数和查询匹配。

Details

42* 需要用户交互的工具:内置 `AskUserQuestion` 工具和标记为 [`requiresUserInteraction`](/docs/zh-CN/mcp#require-approval-for-a-specific-tool) 的 MCP 工具42* 需要用户交互的工具:内置 `AskUserQuestion` 工具和标记为 [`requiresUserInteraction`](/docs/zh-CN/mcp#require-approval-for-a-specific-tool) 的 MCP 工具

43* `rm` 和 `rmdir` 移除针对 [关键路径](#critical-paths),没有允许规则或 `PreToolUse` hook `"allow"` 批准43* `rm` 和 `rmdir` 移除针对 [关键路径](#critical-paths),没有允许规则或 `PreToolUse` hook `"allow"` 批准

44* [跨会话消息传递保护措施](#skip-all-checks-with-bypasspermissions-mode)44* [跨会话消息传递保护措施](#skip-all-checks-with-bypasspermissions-mode)

45* 在 [`permissions.blockReadsOutsideWorkingDirectories`](/docs/zh-CN/settings-reference#permissions-blockreadsoutsideworkingdirectories) 打开时在工作目录外读取:识别的文件读取 Bash 命令和任何需要批准才能在沙箱外运行的 [未沙箱化重试](/docs/zh-CN/sandboxing#the-unsandboxed-retry-escape-hatch),即使在 auto 模式和 `bypassPermissions` 模式下也会提示。需要 Claude Code v2.1.257 或更高版本45* 在 [`permissions.blockReadsOutsideWorkingDirectories`](/docs/zh-CN/settings-reference#permissions-blockreadsoutsideworkingdirectories) 打开时在工作目录外读取:识别的文件读取 Bash 命令和任何需要批准才能在沙箱外运行的 [未沙箱化重试](/docs/zh-CN/sandboxing#the-unsandboxed-retry-escape-hatch),即使在 auto 模式和 `bypassPermissions` 模式下也会提示。需要 Claude Code v2.1.257 或更高版本。

46 

47 shell 解析器无法追踪的命令,例如更改目录多次或运行子 shell 的命令,即使在未命名任何外部路径时也会以相同方式提示。当命令在 [沙箱](/docs/zh-CN/sandboxing) 中运行且沙箱强制执行该块时,此提示不适用。

46 48 

47<h2 id="common-setups">49<h2 id="common-setups">

48 常见设置50 常见设置


59| 在 CI 中使用精确允许列表运行 | `claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"` | 无,超出您的 CI 运行器提供的 | [网络上的 Claude Code](/docs/zh-CN/claude-code-on-the-web) 忽略设置文件中的 `dontAsk` |61| 在 CI 中使用精确允许列表运行 | `claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"` | 无,超出您的 CI 运行器提供的 | [网络上的 Claude Code](/docs/zh-CN/claude-code-on-the-web) 忽略设置文件中的 `dontAsk` |

60| 在容器内完全无人值守运行 | `claude -p "<prompt>" --dangerously-skip-permissions` | 必需:容器、虚拟机或[沙箱运行时](/docs/zh-CN/sandbox-environments#sandbox-runtime);在 Linux 和 macOS 上,以[非 root 用户](#skip-all-checks-with-bypasspermissions-mode)身份运行 | 网络上的 Claude Code 忽略设置文件中的此模式。在此 `-p` 运行中,[仍会提示的少数调用](#skip-all-checks-with-bypasspermissions-mode)被拒绝 |62| 在容器内完全无人值守运行 | `claude -p "<prompt>" --dangerously-skip-permissions` | 必需:容器、虚拟机或[沙箱运行时](/docs/zh-CN/sandbox-environments#sandbox-runtime);在 Linux 和 macOS 上,以[非 root 用户](#skip-all-checks-with-bypasspermissions-mode)身份运行 | 网络上的 Claude Code 忽略设置文件中的此模式。在此 `-p` 运行中,[仍会提示的少数调用](#skip-all-checks-with-bypasspermissions-mode)被拒绝 |

61 63 

62Bash 沙箱和自动模式独立工作并结合,除了在 plan 模式下,其中[自动允许不会扩大批准](/docs/zh-CN/sandboxing#sandbox-modes)。有关完整交互,请参阅[沙箱化如何与权限和权限模式相关](/docs/zh-CN/sandboxing#how-sandboxing-relates-to-permissions-and-permission-modes)和[隔离如何与权限模式相关](/docs/zh-CN/sandbox-environments#how-isolation-relates-to-permission-modes)。64Bash 沙箱和自动模式独立工作并结合,除了在[沙箱模式](/docs/zh-CN/sandboxing#sandbox-modes)下列出的例外。有关完整交互,请参阅[沙箱化如何与权限和权限模式相关](/docs/zh-CN/sandboxing#how-sandboxing-relates-to-permissions-and-permission-modes)和[隔离如何与权限模式相关](/docs/zh-CN/sandbox-environments#how-isolation-relates-to-permission-modes)。

63 65 

64<h2 id="which-mode-a-session-starts-in">66<h2 id="which-mode-a-session-starts-in">

65 会话在哪个模式下启动67 会话在哪个模式下启动


326 328 

327在 v2.1.158 到 v2.1.206 中,这些提供商上的自动模式处于关闭状态,直到您设置 `CLAUDE_CODE_ENABLE_AUTO_MODE=1`,并且 Claude Code 在这些提供商上忽略 `defaultMode: "auto"`,除非也设置了该变量。该变量仍然被接受以保持兼容性,从 v2.1.207 开始无效。329在 v2.1.158 到 v2.1.206 中,这些提供商上的自动模式处于关闭状态,直到您设置 `CLAUDE_CODE_ENABLE_AUTO_MODE=1`,并且 Claude Code 在这些提供商上忽略 `defaultMode: "auto"`,除非也设置了该变量。该变量仍然被接受以保持兼容性,从 v2.1.207 开始无效。

328 330 

331<h3 id="server-side-classifier-review">

332 服务器端分类器审查

333</h3>

334 

335在 Enterprise 计划和使用 Claude API 的账户上,在 [AWS 上的 Claude Platform](/docs/zh-CN/claude-platform-on-aws)、Amazon Bedrock、Google Cloud 的 Agent Platform 和 Microsoft Foundry 上,以及每当您将 `ANTHROPIC_BASE_URL` 指向[LLM 网关或代理](/docs/zh-CN/llm-gateway)时,自动模式下的 Claude Code 会要求服务器审查[转到分类器的操作](#how-the-classifier-evaluates-actions)作为会话模型请求的一部分。服务器审查它们的地方,其判决决定这些操作。它不审查的地方,通常是因为网关或代理干扰了流量,或因为平台、区域或凭证还没有服务器端检查,Claude Code 会回退到自己的分类器请求,一旦该回退在会话的其余部分保持,它会在这些请求被计费的账户上显示[关于分类器请求费用的通知](/docs/zh-CN/auto-mode-classifier-billing)。要跳过询问服务器并始终使用 Claude Code 自己的分类器请求,请设置 [`CLAUDE_CODE_AUTO_MODE_SERVER=0`](/docs/zh-CN/env-vars)。该变量在直接连接到 Anthropic API 时不被读取。如果您设置 `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1` 并保持 `CLAUDE_CODE_AUTO_MODE_SERVER` 未设置,Claude Code 也会停止询问服务器。

336 

337默认询问服务器需要 Claude Code v2.1.278 或更高版本。

338 

329<h3 id="what-the-classifier-blocks-by-default">339<h3 id="what-the-classifier-blocks-by-default">

330 分类器默认阻止的内容340 分类器默认阻止的内容

331</h3>341</h3>


419* 向您在 [`environment`](/docs/zh-CN/auto-mode-config#define-trusted-infrastructure) 中列出的受信任域、存储桶和服务发送数据。这仅涵盖数据流,不涵盖同一基础设施上的破坏性或凭证操作429* 向您在 [`environment`](/docs/zh-CN/auto-mode-config#define-trusted-infrastructure) 中列出的受信任域、存储桶和服务发送数据。这仅涵盖数据流,不涵盖同一基础设施上的破坏性或凭证操作

420* [Chrome 中的 Claude](/docs/zh-CN/chrome)导航到受信任的内部域、localhost 或您命名的 URL430* [Chrome 中的 Claude](/docs/zh-CN/chrome)导航到受信任的内部域、localhost 或您命名的 URL

421 431 

422沙箱网络访问请求通过分类器路由,而不是默认允许。从 v2.1.198 开始,分类器重用其对网络主机和端口的判决,而不是在每次连接时重新运行:432沙箱网络访问请求通过分类器路由,而不是默认允许。Claude 命名命令需要的主机,分类器与命令一起审查它们,批准的列表仅为该一个命令打开这些主机。[每个命令允许的域](/docs/zh-CN/sandboxing#per-command-allowed-domains-in-auto-mode)涵盖列表可以和不能打开什么以及当命令到达未列出的主机时会发生什么。

423 

424* 允许被重用直到新内容进入对话,此时该主机再次被检查

425* Claude Code v2.1.234 及更高版本重用由对话超出分类器上下文窗口引起的拒绝,直到新内容进入对话或直到[压缩](/docs/zh-CN/costs#reduce-token-usage)缩小分类器读取的内容。Claude Code 然后再次检查主机

426* 分类器通过评估请求达到的拒绝在交互式 CLI 中持续一个回合。在[非交互模式](/docs/zh-CN/headless)和 Agent SDK 会话中,Claude Code 为其余运行重用该拒绝,因为这些会话没有回合边界

427* 更改您的权限模式或规则会删除所有缓存的判决

428 433 

429运行 `claude auto-mode defaults` 以将完整规则列表打印为 JSON。如果常规操作被阻止,管理员可以通过 `autoMode.environment` 设置添加受信任的仓库、存储桶和服务:请参阅[配置自动模式](/docs/zh-CN/auto-mode-config)。434运行 `claude auto-mode defaults` 以将完整规则列表打印为 JSON。如果常规操作被阻止,管理员可以通过 `autoMode.environment` 设置添加受信任的仓库、存储桶和服务:请参阅[配置自动模式](/docs/zh-CN/auto-mode-config)。

430 435 


471 <Accordion title="分类器如何评估操作">476 <Accordion title="分类器如何评估操作">

472 每个操作都经过固定的决策顺序。第一个匹配的步骤获胜:477 每个操作都经过固定的决策顺序。第一个匹配的步骤获胜:

473 478 

474 1. 与您的[允许、询问或拒绝规则](/docs/zh-CN/permissions#manage-permissions)匹配的操作立即解决。写入[受保护路径](#protected-paths)的操作即使允许规则匹配也会路由到分类器,Claude Code v2.1.218 及更高版本中针对[关键路径](#critical-paths)的 `rm` 和 `rmdir` 删除也是如此。标记为 [`requiresUserInteraction`](/docs/zh-CN/mcp#require-approval-for-a-specific-tool) 的 MCP 工具即使允许规则匹配也会直接提示您,您的组织在会话中设置为 `ask` 的[连接器工具](/docs/zh-CN/mcp#organization-controls-on-connector-tools)也是如此,其中该设置到达 Claude Code。与命令内容匹配的询问规则,例如 `Bash(git push *)`,回退到权限提示479 1. 与您的[允许、询问或拒绝规则](/docs/zh-CN/permissions#manage-permissions)匹配的操作立即解决,但有以下例外:

480 * 写入[受保护路径](#protected-paths)的操作即使允许规则匹配也会路由到分类器,Claude Code v2.1.218 及更高版本中针对[关键路径](#critical-paths)的 `rm` 和 `rmdir` 删除也是如此

481 * 标记为 [`requiresUserInteraction`](/docs/zh-CN/mcp#require-approval-for-a-specific-tool) 的 MCP 工具即使允许规则匹配也会直接提示您,您的组织在会话中设置为 `ask` 的[连接器工具](/docs/zh-CN/mcp#organization-controls-on-connector-tools)也是如此,其中该设置到达 Claude Code

482 * 携带[每个命令允许的域](/docs/zh-CN/sandboxing#per-command-allowed-domains-in-auto-mode)的 shell 命令也会路由到分类器,即使允许规则匹配,因为规则批准命令,而不是其主机

483 * 与命令内容匹配的询问规则,例如 `Bash(git push *)`,回退到权限提示

475 2. 只读操作和工作目录中的文件编辑被自动批准,除了写入[受保护路径](#protected-paths)和[工作目录外的第一次读取](#first-read-outside-the-working-directories),这会提示您484 2. 只读操作和工作目录中的文件编辑被自动批准,除了写入[受保护路径](#protected-paths)和[工作目录外的第一次读取](#first-read-outside-the-working-directories),这会提示您

476 3. 其他所有内容都转到分类器。在步骤 1 中直接提示您的连接器工具和` requiresUserInteraction` MCP 工具永远不会到达分类器,因此组织要求的批准或同意步骤都不会被自动批准485 3. 其他所有内容都转到分类器。在步骤 1 中直接提示您的连接器工具和` requiresUserInteraction` MCP 工具永远不会到达分类器,因此组织要求的批准或同意步骤都不会被自动批准

477 4. 如果分类器阻止,Claude 接收原因并尝试替代方案。在大多数会话中,原因名称分类器匹配的规则,例如 `[Data Exfiltration]`,而不是给出书面解释;请参阅[审查拒绝](/docs/zh-CN/auto-mode-config#review-denials)486 4. 如果分类器阻止,Claude 接收原因并尝试替代方案。在大多数会话中,原因名称分类器匹配的规则,例如 `[Data Exfiltration]`,而不是给出书面解释;请参阅[审查拒绝](/docs/zh-CN/auto-mode-config#review-denials)


488 497 

489 Claude Code 还在会丢弃未提交工作的命令之前运行 `git status`,例如 `git reset --hard` 或 `rm -rf`,并向分类器显示是否存在暂存、修改或未跟踪的工作。Claude Code 在该检查中报告未跟踪的文件,即使仓库的 git 配置设置了 `status.showUntrackedFiles=no`。498 Claude Code 还在会丢弃未提交工作的命令之前运行 `git status`,例如 `git reset --hard` 或 `rm -rf`,并向分类器显示是否存在暂存、修改或未跟踪的工作。Claude Code 在该检查中报告未跟踪的文件,即使仓库的 git 配置设置了 `status.showUntrackedFiles=no`。

490 499 

491 分类器看到用户消息、除了只读查找(如文件读取和搜索)之外的工具调用,以及您的 CLAUDE.md 内容。工具结果被剥离,因此文件或网页中的恶意内容无法直接操纵它。您可以使用 [PostToolUse hook 的 `classifierContext` 字段](/docs/zh-CN/hooks#annotate-a-result-for-the-auto-mode-classifier)注释调用的结果,分类器将其读取为应用程序提供的上下文。500 分类器看到用户消息、除了只读查找(如文件读取和搜索)之外的工具调用,以及您的 CLAUDE.md 内容。工具结果被剥离,因此文件或网页中的恶意内容无法直接操纵它。您可以使用 [PostToolUse hook 的 `classifierContext` 字段](/docs/zh-CN/hooks#annotate-a-result-for-the-auto-mode-classifier)注释调用的结果,分类器将其读取为应用程序提供的上下文。该字段需要 Claude Code v2.1.236 或更高版本。

492 501 

493 单独的服务器端探针扫描传入的工具结果并在 Claude 读取之前标记可疑内容。有关这些层如何协同工作的更多信息,请参阅[自动模式公告](https://claude.com/blog/auto-mode)和[工程深度潜水](https://www.anthropic.com/engineering/claude-code-auto-mode)。502 单独的服务器端探针扫描传入的工具结果并在 Claude 读取之前标记可疑内容。有关这些层如何协同工作的更多信息,请参阅[自动模式公告](https://claude.com/blog/auto-mode)和[工程深度潜水](https://www.anthropic.com/engineering/claude-code-auto-mode)。

494 </Accordion>503 </Accordion>


498 507 

499 1. 在子代理启动之前,委托的任务描述被评估,因此危险看起来的任务在生成时被阻止。508 1. 在子代理启动之前,委托的任务描述被评估,因此危险看起来的任务在生成时被阻止。

500 2. 当子代理运行时,其每个操作都通过分类器,使用与父会话相同的规则,子代理 frontmatter 中的任何 `permissionMode` 都被忽略。509 2. 当子代理运行时,其每个操作都通过分类器,使用与父会话相同的规则,子代理 frontmatter 中的任何 `permissionMode` 都被忽略。

501 3. 当子代理完成时,分类器审查其完整的操作历史;如果该返回检查标记了一个问题,安全警告被添加到子代理的结果前面。当单独的 API 安全检查拒绝审查请求本身时,Claude Code 仍然返回子代理的结果,前面加上警告,说工作未审查,应被视为不受信任。510 3. 当子代理完成时,分类器审查其工作和最终报告,然后父会话读取报告。当分类器标记子代理的工作或报告时,或单独的 API 安全检查拒绝审查时,报告仍然被交付,前面加上安全警告。当分类器不可用于审查时,报告到达时带有说明在对其采取行动之前验证子代理工作的说明。

502 511 

503 步骤 1 需要 Claude Code v2.1.178 或更高版本。较早的版本在步骤 2 和 3 应用分类器,但在子代理启动之前没有评估任务描述。512 步骤 1 需要 Claude Code v2.1.178 或更高版本。较早的版本在步骤 2 和 3 应用分类器,但在子代理启动之前没有评估任务描述。

504 </Accordion>513 </Accordion>


508 517 

509 会话的第一个自动模式请求验证 Sonnet 5 默认值:如果请求成功,Sonnet 5 保持会话的分类器模型,如果它因模型不可用而失败,会话改为使用回退。在该验证解决后,分类器的模型在会话中不会改变。518 会话的第一个自动模式请求验证 Sonnet 5 默认值:如果请求成功,Sonnet 5 保持会话的分类器模型,如果它因模型不可用而失败,会话改为使用回退。在该验证解决后,分类器的模型在会话中不会改变。

510 519 

511 在 Enterprise 计划和使用 Claude API、[AWS 上的 Claude Platform](/docs/zh-CN/claude-platform-on-aws)、Amazon Bedrock、Google Cloud 的 Agent Platform 或 Microsoft Foundry 的账户上,分类器调用计入您的令牌使用。每次检查发送记录的一部分加上待处理操作,在执行前添加往返。在受保护路径外的读取和工作目录编辑跳过分类器,因此开销主要来自 shell 命令和网络操作。520 在 Enterprise 计划和使用 Claude API、[AWS 上的 Claude Platform](/docs/zh-CN/claude-platform-on-aws)、Amazon Bedrock、Google Cloud 的 Agent Platform 或 Microsoft Foundry 的账户上,分类器调用计入您的令牌使用。每次检查发送记录的一部分加上待处理操作,在执行前添加往返。在受保护路径外的读取和工作目录编辑跳过分类器,因此开销主要来自 shell 命令和网络操作。服务器审查操作的地方,没有单独的分类器调用要计数;请参阅[服务器端分类器审查](#server-side-classifier-review)。

512 521 

513 分类器重用沙箱网络判决用于主机和端口,因此重复连接到同一主机不会各自添加检查。[分类器默认阻止的内容](#what-the-classifier-blocks-by-default)描述允许和拒绝持续多长时间。522 沙箱网络访问不添加每个连接分类器请求。分类器与命令一起判断[命令命名的主机](/docs/zh-CN/sandboxing#per-command-allowed-domains-in-auto-mode)在一次审查中,Claude Code 检查每个连接对照批准的列表而不再次调用分类器。

514 </Accordion>523 </Accordion>

515</AccordionGroup>524</AccordionGroup>

516 525 


651 660 

652Claude Code 也将直接在 shell 变量下的 glob 或尾部斜杠视为关键路径移除,如 `rm -rf "$DIR"/*`,因为当变量为空时命令变成从文件系统根目录的移除。661Claude Code 也将直接在 shell 变量下的 glob 或尾部斜杠视为关键路径移除,如 `rm -rf "$DIR"/*`,因为当变量为空时命令变成从文件系统根目录的移除。

653 662 

654使用 `$(...)` 或反引号隐藏命令替换中的移除,或使用 `<(...)` 的进程替换,不会跳过检查。Claude Code 找到关键路径移除,无论它位于替换内部(如 `echo "$(rm -rf ~)"`),还是位于同一命令中的其他地方。663使用 `(...)` 中的子 shell、`{ ...; }` 中的大括号组、`$(...)` 或反引号中的命令替换,或 `<(...)` 中的进程替换隐藏移除,不会跳过检查。Claude Code 找到关键路径移除,无论它位于嵌套形式内部(如 `(rm -rf ~)` 或 `echo "$(rm -rf ~)"`),还是位于同一命令中的其他地方。

655 664 

656<h3 id="remove-item-in-powershell">665<h3 id="remove-item-in-powershell">

657 PowerShell 中的 Remove-Item666 PowerShell 中的 Remove-Item

routines.md +18 −3

Details

52 52 

53创建表单设置例程的提示、存储库、环境、connectors 和触发器。53创建表单设置例程的提示、存储库、环境、connectors 和触发器。

54 54 

55Routines 作为完整的 Claude Code 云会话自主运行:没有权限模式选择器,运行期间也没有批准提示。会话可以运行 shell 命令、使用 [skills](/docs/zh-CN/skills) 提交到克隆的存储库,并调用您包含的任何 connectors。例程可以到达的内容由您选择的存储库、[environment](/docs/zh-CN/cloud-environments) 的网络访问和变量以及您包含的 connectors 决定。将每个范围限制在例程实际需要的范围内。55Routines 作为完整的 Claude Code 云会话自主运行:没有权限模式选择器,会话运行 shell 命令、使用 [skills](/docs/zh-CN/skills) 提交到克隆的存储库,并调用您包含的任何 connectors,所有这些都无需停止以获得批准,除了某些 [artifact](/docs/zh-CN/artifacts) 操作。

56 

57例程可以到达的内容由您选择的存储库、[environment](/docs/zh-CN/cloud-environments) 的网络访问和变量以及您包含的 connectors 决定。将每个范围限制在例程实际需要的范围内。

58 

59当例程的计划或 **Run now** 启动运行时,Claude 仅在以下所有条件都成立时才会重新发布现有 artifact,无需询问:

60 

61* 您可以编辑 artifact,它属于您自己的组织

62* artifact 不是公开共享的,也不是与特定人员或您的组织共享的,最新版本被选为查看者看到的版本

63* 发布仅包含页面,没有支持文件或任何其他添加的内容,并且不会强制覆盖较新版本

64* 页面不包含超出页面范围的授权,例如 [connector calls](/docs/zh-CN/artifacts#pull-live-data-with-mcp-connectors)

65 

66在所有其他情况下,包括发布新 artifact,Claude 会先询问。当例程的工作是保持页面最新时,请给它一个您已经发布的 artifact。

56 67 

57Routines 属于您的个人 claude.ai 账户。它们不与队友共享,并且计入您账户的每日运行配额。例程通过您连接的 GitHub 身份或 connectors 所做的任何事情都显示为您:提交和拉取请求携带您的 GitHub 用户,Slack 消息、Linear 票证或其他 connector 操作使用您为这些服务链接的账户。68Routines 属于您的个人 claude.ai 账户。它们不与队友共享,并且计入您账户的每日运行配额。例程通过您连接的 GitHub 身份或 connectors 所做的任何事情都显示为您:提交和拉取请求携带您的 GitHub 用户,Slack 消息、Linear 票证或其他 connector 操作使用您为这些服务链接的账户。

58 69 


349 360 

350Routines 需要 GitHub 访问权限来克隆存储库。当您使用 `/schedule` 从 CLI 创建例程时,Claude 检查您的账户是否具有您运行它的存储库的 GitHub 访问权限,如果没有,会添加一个设置说明,说明如何授予它。有关授予访问权限的两种方式,请参阅 [GitHub authentication options](/docs/zh-CN/claude-code-on-the-web#github-authentication-options)。361Routines 需要 GitHub 访问权限来克隆存储库。当您使用 `/schedule` 从 CLI 创建例程时,Claude 检查您的账户是否具有您运行它的存储库的 GitHub 访问权限,如果没有,会添加一个设置说明,说明如何授予它。有关授予访问权限的两种方式,请参阅 [GitHub authentication options](/docs/zh-CN/claude-code-on-the-web#github-authentication-options)。

351 362 

363如果您的 GitHub 连接在运行到期时缺失或已过期,例程将跳过运行,最多 72 小时。在该时间窗口内重新连接 GitHub,例程将自动恢复。72 小时后仍未连接,例程将关闭,您需要在重新连接 GitHub 后将其打开。

364 

352您添加的每个存储库在每次运行时都会被克隆。Claude 从存储库的默认分支开始,除非您的提示另有指定。365您添加的每个存储库在每次运行时都会被克隆。Claude 从存储库的默认分支开始,除非您的提示另有指定。

353 366 

354Claude 将其工作推送到以 `claude/` 为前缀的分支,这些分支始终被接受。当您的提示指示 Claude 推送到另一个分支时,Claude Code 会先检查推送,如果以下任何情况为真,则拒绝它:367Claude 将其工作推送到以 `claude/` 为前缀的分支,这些分支始终被接受。当您的提示指示 Claude 推送到另一个分支时,Claude Code 会先检查推送,如果以下任何情况为真,则拒绝它:


377 390 

378**Default** 环境使用 **Trusted** 网络访问,它仅允许 [默认允许列表](/docs/zh-CN/cloud-environments#default-allowed-domains) 通过会话的网络。对该路径之外的主机的请求失败,返回 `403` 和 `x-deny-reason: host_not_allowed`。MCP connector 流量通过 Anthropic 的服务器路由,而不是该路径,因此您添加到例程的 connectors 无需将其主机添加到 **Allowed domains** 即可工作。删除您在 [Connectors](#connectors) 下不需要的任何 connectors。391**Default** 环境使用 **Trusted** 网络访问,它仅允许 [默认允许列表](/docs/zh-CN/cloud-environments#default-allowed-domains) 通过会话的网络。对该路径之外的主机的请求失败,返回 `403` 和 `x-deny-reason: host_not_allowed`。MCP connector 流量通过 Anthropic 的服务器路由,而不是该路径,因此您添加到例程的 connectors 无需将其主机添加到 **Allowed domains** 即可工作。删除您在 [Connectors](#connectors) 下不需要的任何 connectors。

379 392 

380要允许其他域:393要允许其他域上的一个您自己的环境,请按照以下步骤操作。[organization-shared environment](/docs/zh-CN/cloud-environments#organization-shared-environments) 在此处打开为只读,因此所有者从 [admin settings](https://claude.ai/admin-settings) 中的 **Cloud environments** 页面更改其网络访问。

381 394 

382<Steps>395<Steps>

383 <Step title="打开例程进行编辑">396 <Step title="打开例程进行编辑">


413 426 

414一次性运行不计入每日 routine 运行上限。它们像任何其他会话一样消耗您的常规订阅使用量。427一次性运行不计入每日 routine 运行上限。它们像任何其他会话一样消耗您的常规订阅使用量。

415 428 

429当您的订阅暂停时,您的 routines 会被暂停并且不会运行。一旦您的订阅再次激活,请将它们重新打开。

430 

416<h2 id="troubleshooting">431<h2 id="troubleshooting">

417 故障排除432 故障排除

418</h2>433</h2>


427 442 

428* 您使用 Console API 密钥、[Anthropic 配置文件或联合凭证](/docs/zh-CN/authentication#anthropic-profiles-and-federation-credentials)或云提供商(如 Amazon Bedrock、Google Cloud 的 Agent Platform 或 Microsoft Foundry)进行身份验证。`/schedule` 需要 claude.ai 订阅登录。使用 Console API 密钥或配置文件时,如果启用了功能标志获取,提交 `/schedule` 会显示 `/schedule is available with Claude for Enterprise — ask your admin about migrating from API-key access`。使用云提供商登录时,您仍然会看到 `Unknown command: /schedule`。如果在您的 shell 中设置了 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`,或在 `settings.json` 中设置了 `apiKeyHelper`,请先删除它,因为这些会优先于 claude.ai 登录。配置文件或联合凭证也会优先,所以也要关闭它443* 您使用 Console API 密钥、[Anthropic 配置文件或联合凭证](/docs/zh-CN/authentication#anthropic-profiles-and-federation-credentials)或云提供商(如 Amazon Bedrock、Google Cloud 的 Agent Platform 或 Microsoft Foundry)进行身份验证。`/schedule` 需要 claude.ai 订阅登录。使用 Console API 密钥或配置文件时,如果启用了功能标志获取,提交 `/schedule` 会显示 `/schedule is available with Claude for Enterprise — ask your admin about migrating from API-key access`。使用云提供商登录时,您仍然会看到 `Unknown command: /schedule`。如果在您的 shell 中设置了 `ANTHROPIC_API_KEY` 或 `ANTHROPIC_AUTH_TOKEN`,或在 `settings.json` 中设置了 `apiKeyHelper`,请先删除它,因为这些会优先于 claude.ai 登录。配置文件或联合凭证也会优先,所以也要关闭它

429* 您完全登出,没有 API 密钥或其他凭证。如果启用了功能标志获取,提交 `/schedule` 会显示 `/schedule requires a claude.ai subscription. Run /login to sign in with your claude.ai account.` 在 v2.1.268 之前,登出的会话显示与 Console API 密钥相同的 Claude for Enterprise 消息444* 您完全登出,没有 API 密钥或其他凭证。如果启用了功能标志获取,提交 `/schedule` 会显示 `/schedule requires a claude.ai subscription. Run /login to sign in with your claude.ai account.` 在 v2.1.268 之前,登出的会话显示与 Console API 密钥相同的 Claude for Enterprise 消息

430* 您在云会话中。改为从 [web UI](https://claude.ai/code/routines) 管理例程445* 您在云会话中,提交 `/schedule` 会回答该命令在该环境中不可用。改为从 [web UI](https://claude.ai/code/routines) 管理例程

431* 您的组织的策略禁用了 [cloud sessions](/docs/zh-CN/claude-code-on-the-web),例程需要这些。在这种情况下,提交 `/schedule` 会回答 [`Cloud sessions are disabled by your organization's policy`](/docs/zh-CN/errors#cloud-sessions-are-disabled-by-your-organizations-policy)。在 v2.1.268 之前,它返回 `Unknown command: /schedule`446* 您的组织的策略禁用了 [cloud sessions](/docs/zh-CN/claude-code-on-the-web),例程需要这些。在这种情况下,提交 `/schedule` 会回答 [`Cloud sessions are disabled by your organization's policy`](/docs/zh-CN/errors#cloud-sessions-are-disabled-by-your-organizations-policy)。在 v2.1.268 之前,它返回 `Unknown command: /schedule`

432* Owner 为您的 Team 或 Enterprise 组织[关闭了例程](#routines-are-disabled-by-your-organizations-policy)。在 v2.1.227 之前,命令在这种情况下仍然出现,当 Claude 尝试创建或运行例程时,claude.ai 会拒绝该例程447* Owner 为您的 Team 或 Enterprise 组织[关闭了例程](#routines-are-disabled-by-your-organizations-policy)。在 v2.1.227 之前,命令在这种情况下仍然出现,当 Claude 尝试创建或运行例程时,claude.ai 会拒绝该例程

433 448 

Details

168* 运行器设置 `GCM_INTERACTIVE=never`,所以 Git Credential Manager 不打开登录对话框。168* 运行器设置 `GCM_INTERACTIVE=never`,所以 Git Credential Manager 不打开登录对话框。

169* 运行器清除 `core.askPass`,所以如果您使用 askpass 助手,改为通过 `GIT_ASKPASS` 环境变量设置它。169* 运行器清除 `core.askPass`,所以如果您使用 askpass 助手,改为通过 `GIT_ASKPASS` 环境变量设置它。

170 170 

171如果您的 git 主机拒绝凭证,或您没有配置凭证,运行器重试几次然后失败存储库准备。运行器不会将这些设置传递到会话的环境中。171如果您的 git 主机拒绝凭证,或您没有配置凭证,运行器重试几次然后失败存储库准备(当存储库是会话推送结果的存储库时)。对于会话仅从中读取的存储库,[故障排除](#troubleshooting)涵盖运行器何时改为跳过它。运行器不会将这些设置传递到会话的环境中。

172 172 

173如果检出目录由与运行器进程不同的 uid 拥有,git 拒绝对其进行操作;添加 `safe.directory`:173如果检出目录由与运行器进程不同的 uid 拥有,git 拒绝对其进行操作;添加 `safe.directory`:

174 174 


531* **会话无法通过身份验证出口代理到达网络**:当您使用 [`--proxy-authorization-command` 或 `--proxy-authorization-file`](#authenticate-to-an-egress-proxy) 设置的源失败、在 30 秒后超时或产生空值时,运行器以 `502 Bad Gateway` 应答该连接并记录原因。运行器在该日志中编辑命令的 stderr,并且永远不会记录标头值。使用 `--proxy-authorization-command` 时,在主机上自己运行该命令以确认它在 stdout 上打印整个标头值。如果运行器改为在启动时退出,显示 `could not start the proxy-authorization listener`,则它无法打开其环回监听器。531* **会话无法通过身份验证出口代理到达网络**:当您使用 [`--proxy-authorization-command` 或 `--proxy-authorization-file`](#authenticate-to-an-egress-proxy) 设置的源失败、在 30 秒后超时或产生空值时,运行器以 `502 Bad Gateway` 应答该连接并记录原因。运行器在该日志中编辑命令的 stderr,并且永远不会记录标头值。使用 `--proxy-authorization-command` 时,在主机上自己运行该命令以确认它在 stdout 上打印整个标头值。如果运行器改为在启动时退出,显示 `could not start the proxy-authorization listener`,则它无法打开其环回监听器。

532* **运行器记录包含 `rejecting the malformed poll response` 的 `Poll failed` 行**:运行器收到的工作轮询响应的正文不是队列的预期 JSON,最常见的原因是运行器和 `api.anthropic.com` 之间的某些内容(例如拦截代理或强制门户)用自己的页面进行了应答。运行器拒绝响应,在 `claude_code_self_hosted_runner_poll_errors_total` [指标](/docs/zh-CN/self-hosted-environments-reference#prometheus-metrics) 的 `transport` 类型下计数,并按 [会话生命周期](/docs/zh-CN/self-hosted-environments#session-lifecycle) 中描述的失败轮询计划重试。运行器继续为其实时会话提供服务。配置代理以将来自 `api.anthropic.com` 的响应原封不动地传递。在 v2.1.246 之前,运行器将这样的响应读取为空工作队列,这可能会结束其实时会话或使其退出。532* **运行器记录包含 `rejecting the malformed poll response` 的 `Poll failed` 行**:运行器收到的工作轮询响应的正文不是队列的预期 JSON,最常见的原因是运行器和 `api.anthropic.com` 之间的某些内容(例如拦截代理或强制门户)用自己的页面进行了应答。运行器拒绝响应,在 `claude_code_self_hosted_runner_poll_errors_total` [指标](/docs/zh-CN/self-hosted-environments-reference#prometheus-metrics) 的 `transport` 类型下计数,并按 [会话生命周期](/docs/zh-CN/self-hosted-environments#session-lifecycle) 中描述的失败轮询计划重试。运行器继续为其实时会话提供服务。配置代理以将来自 `api.anthropic.com` 的响应原封不动地传递。在 v2.1.246 之前,运行器将这样的响应读取为空工作队列,这可能会结束其实时会话或使其退出。

533* **会话的分支在远程上不再存在**:对于会话仅从中读取的 git 源,运行器跳过该源并继续处理其余源。对于会话推送结果的源,删除的分支(通常是因为它被合并并自动删除)会导致会话失败,并显示一个错误,命名存储库和分支,并要求您恢复分支并重试。当跳过会导致它完全没有存储库时,运行器会以相同的错误失败会话。在 v2.1.228 之前,这样的会话在空目录中启动。533* **会话的分支在远程上不再存在**:对于会话仅从中读取的 git 源,运行器跳过该源并继续处理其余源。对于会话推送结果的源,删除的分支(通常是因为它被合并并自动删除)会导致会话失败,并显示一个错误,命名存储库和分支,并要求您恢复分支并重试。当跳过会导致它完全没有存储库时,运行器会以相同的错误失败会话。在 v2.1.228 之前,这样的会话在空目录中启动。

534* **会话启动时缺少其中一个存储库**:在没有 [`checkout` hook](/docs/zh-CN/self-hosted-environments-configuration#checkout) 的运行器上,git 主机可能会拒绝运行器对会话仅从中读取的存储库的访问检查。运行器随后跳过该存储库,记录一条 `[runner:warn] could not access context source` 行,命名拒绝,并在其余存储库上启动会话。

535 

536 运行器仅跳过明确的拒绝:主机回答存储库未找到,git 找不到主机的凭证,或身份验证失败。网络故障、超时或 HTTP `403` 仍会导致会话启动失败,对于会话推送结果的存储库的拒绝也是如此。运行器仍会失败一个会话,跳过会导致它完全没有存储库。使用 [`--use-anthropic-git-proxy`](#use-the-anthropic-git-proxy),运行器仅跳过 git 代理本身拒绝的存储库。

537 

538 访问检查在每次会话在运行器上启动时再次运行,因此一旦运行器的 git 身份具有读取访问权限,下一次启动就会克隆存储库。在 v2.1.274 之前,这些拒绝中的每一个都导致会话启动失败。

534* **会话需要数分钟才能启动**:初始克隆通常占主导地位。观察 `claude_code_self_hosted_runner_session_init_duration_seconds` [指标](/docs/zh-CN/self-hosted-environments-reference#prometheus-metrics) 以确认,并使用 [预热检出](#reuse-a-pre-warmed-checkout) 或更小的 `CLAUDE_RUNNER_FETCH_DEPTH` 减少克隆。539* **会话需要数分钟才能启动**:初始克隆通常占主导地位。观察 `claude_code_self_hosted_runner_session_init_duration_seconds` [指标](/docs/zh-CN/self-hosted-environments-reference#prometheus-metrics) 以确认,并使用 [预热检出](#reuse-a-pre-warmed-checkout) 或更小的 `CLAUDE_RUNNER_FETCH_DEPTH` 减少克隆。

540* **轮次以 401 失败**:每个会话使用运行器从 Anthropic 获取并通过会话的 stdin 轮换的短期 [`CLAUDE_CODE_OAUTH_TOKEN`](/docs/zh-CN/self-hosted-environments-configuration#wrapper-scripts) 对模型调用进行身份验证。当轮次以来自模型 API 的 401 或 403 结束时,运行器获取新令牌并将其传递给会话。失败的轮次不会重试。

541 

542 当获取失败时,运行器记录一条 `inference_token refresh failed` 行,说明何时重试,并在会话运行期间继续重试。

543 

544 如果每个调用在会话大约 30 分钟后开始失败,包装脚本可能已断开会话的 stdin,因此令牌轮换无法到达它;请参阅 [保持 stdin 和文件描述符 3 附加](/docs/zh-CN/self-hosted-environments-configuration#keep-stdin-and-file-descriptor-3-attached)。

545 

546 在 v2.1.274 之前,运行器在几次尝试后停止重试失败的获取,并等待下一个计划的获取。失败的轮次不会触发获取,因此每个轮次都会失败,显示 401,直到下一个计划的获取。

535* **Pod 在耗尽中途被杀死**:将 `terminationGracePeriodSeconds` 提高到至少运行器在启动时记录的值。请参阅 [关闭时序](#shutdown-timing)。547* **Pod 在耗尽中途被杀死**:将 `terminationGracePeriodSeconds` 提高到至少运行器在启动时记录的值。请参阅 [关闭时序](#shutdown-timing)。

536 548 

537初始化日志后,运行器将其生命周期日志(包括 `[runner:fatal]` 行)写入 stdout,将调试输出写入 stderr,全部作为纯文本行而不是 JSON。上述故障排除条目中描述的启动失败在该点之前打印到 stderr。使用 `--log-file` 捕获两个流,这也让 `self-hosted-runner doctor` 能够跟踪它们,或使用您的平台的日志收集。549初始化日志后,运行器将其生命周期日志(包括 `[runner:fatal]` 行)写入 stdout,将调试输出写入 stderr,全部作为纯文本行而不是 JSON。上述故障排除条目中描述的启动失败在该点之前打印到 stderr。使用 `--log-file` 捕获两个流,这也让 `self-hosted-runner doctor` 能够跟踪它们,或使用您的平台的日志收集。

Details

103| `SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS` | `30000` | 运行器在后台任务完成后认为会话繁忙的时间,而读取结果的后续轮次尚未开始。[`--drain-wait-sec` 和 `--release-idle-session-min` 行](#runner-cli-flags)描述了保持在排空和空闲释放时的应用位置,[运行器生命周期](/docs/zh-CN/self-hosted-environments#runner-lifecycle)描述了它在 `--retire-at` 退休时的应用位置。`0` 或不可用的值回退到默认值,因此无法关闭保持。需要 Claude Code v2.1.228 或更高版本。 |103| `SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS` | `30000` | 运行器在后台任务完成后认为会话繁忙的时间,而读取结果的后续轮次尚未开始。[`--drain-wait-sec` 和 `--release-idle-session-min` 行](#runner-cli-flags)描述了保持在排空和空闲释放时的应用位置,[运行器生命周期](/docs/zh-CN/self-hosted-environments#runner-lifecycle)描述了它在 `--retire-at` 退休时的应用位置。`0` 或不可用的值回退到默认值,因此无法关闭保持。需要 Claude Code v2.1.228 或更高版本。 |

104| `SELF_HOSTED_RUNNER_HOST_CONFIG_DIR` | `~/.claude` | 捕获到运行器启动快照中并播种到每个会话的 `CLAUDE_CONFIG_DIR` 的目录;磁盘上的更改在运行器重新启动后应用。设置变量也会移动运行器读取 `.claude.json` 的位置以进行 [MCP 播种](/docs/zh-CN/self-hosted-environments-configuration#mcp-servers),因此设置它(包括其自己的默认值)会重新定位该查找;指向空目录以完全禁用播种。 |104| `SELF_HOSTED_RUNNER_HOST_CONFIG_DIR` | `~/.claude` | 捕获到运行器启动快照中并播种到每个会话的 `CLAUDE_CONFIG_DIR` 的目录;磁盘上的更改在运行器重新启动后应用。设置变量也会移动运行器读取 `.claude.json` 的位置以进行 [MCP 播种](/docs/zh-CN/self-hosted-environments-configuration#mcp-servers),因此设置它(包括其自己的默认值)会重新定位该查找;指向空目录以完全禁用播种。 |

105| `SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS` | `900000` | 运行器在会话达到其 `--kill-session-after-min` 限制后等待的时间,以便运行中的轮次完成或释放完成,然后才终止会话 |105| `SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS` | `900000` | 运行器在会话达到其 `--kill-session-after-min` 限制后等待的时间,以便运行中的轮次完成或释放完成,然后才终止会话 |

106| `SELF_HOSTED_RUNNER_POST_TURN_SETTLE_MS` | `7000` | 运行器在轮次完成后计算会话繁忙的时间上限,用于 `--drain-wait-sec` 排空,而会话的进程向 Anthropic 报告轮次的结束。`0` 或不可用的值回退到默认值,因此无法关闭保持。需要 Claude Code v2.1.275 或更高版本。 |

106| `SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS` | `30000` | 运行器等待操作系统向陷入不可中断 I/O 的子进程传递 `SIGKILL` 的时间,然后自己退出。下限为 `--post-session-hook-timeout-sec` 加 15 秒,设置 `--push-outcome-on-release` 时再加 30 秒,因此有效最小值在默认值处为 75 秒。 |107| `SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS` | `30000` | 运行器等待操作系统向陷入不可中断 I/O 的子进程传递 `SIGKILL` 的时间,然后自己退出。下限为 `--post-session-hook-timeout-sec` 加 15 秒,设置 `--push-outcome-on-release` 时再加 30 秒,因此有效最小值在默认值处为 75 秒。 |

107| `CLAUDE_RUNNER_FETCH_DEPTH` | `50` | 新克隆的 git 获取深度。设置正整数,或 `full` 或 `0` 以进行完整获取。工作区中已存在的存储库保持其现有深度。 |108| `CLAUDE_RUNNER_FETCH_DEPTH` | `50` | 新克隆的 git 获取深度。设置正整数,或 `full` 或 `0` 以进行完整获取。工作区中已存在的存储库保持其现有深度。 |

108| `CLAUDE_RUNNER_SKIP_GIT_VERIFY` | 未设置 | 当为 `1` 时,跳过 `checkout` 钩子运行后的 `.git` 存在检查。当您的钩子物化非 git 源时设置此项。 |109| `CLAUDE_RUNNER_SKIP_GIT_VERIFY` | 未设置 | 当为 `1` 时,跳过 `checkout` 钩子运行后的 `.git` 存在检查。当您的钩子物化非 git 源时设置此项。 |

slack.md +3 −1

Details

231 231 

232此条目适用于使用 [Claude Tag](https://claude.com/docs/claude-tag/overview) 的工作区,其中 Claude 在频道中作为您组织的共享身份工作,而不是作为任何成员的账户。如果您在 [claude.ai/code](https://claude.ai/code) 创建了频道的云环境,它属于您的个人账户,Claude 无法在个人环境中启动频道会话。Claude Code 会立即使会话失败,重试也无法帮助。232此条目适用于使用 [Claude Tag](https://claude.com/docs/claude-tag/overview) 的工作区,其中 Claude 在频道中作为您组织的共享身份工作,而不是作为任何成员的账户。如果您在 [claude.ai/code](https://claude.ai/code) 创建了频道的云环境,它属于您的个人账户,Claude 无法在个人环境中启动频道会话。Claude Code 会立即使会话失败,重试也无法帮助。

233 233 

234如果您是所有者,请从[管理设置](https://claude.ai/admin-settings)中的**云环境**页面将环境重新创建为[组织共享环境](/docs/zh-CN/cloud-environments#organization-shared-environments)。您可以通过两种方式应用它:234如果您是所有者且环境是您自己的,请从环境选择器中[与组织共享](/docs/zh-CN/cloud-environments#organization-shared-environments)。否则,所有者可从[管理设置](https://claude.ai/admin-settings)中的**云环境**页面将其重新创建为组织共享环境。

235 

236您可以通过两种方式应用它:

235 237 

236* 在 [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) 将其设置为组织默认值。238* 在 [claude.ai/admin-settings/claude-code](https://claude.ai/admin-settings/claude-code) 将其设置为组织默认值。

237* [在 Claude Tag 管理设置中的频道上设置它](https://claude.com/docs/claude-tag/admins/troubleshooting#channel-sessions-use-the-wrong-environment-or-can%E2%80%99t-find-one)。239* [在 Claude Tag 管理设置中的频道上设置它](https://claude.com/docs/claude-tag/admins/troubleshooting#channel-sessions-use-the-wrong-environment-or-can%E2%80%99t-find-one)。

Details

196<Steps>196<Steps>

197 <Step title="打开差异视图">197 <Step title="打开差异视图">

198 差异指示器显示整个会话中添加和删除的行,例如 `+42 -18`。选择它以打开差异视图,左侧是文件列表,右侧是更改。198 差异指示器显示整个会话中添加和删除的行,例如 `+42 -18`。选择它以打开差异视图,左侧是文件列表,右侧是更改。

199 

200 差异默认将会话的更改与其基础分支进行比较。要与不同的分支进行比较,选择**Compare against**并选择一个。

199 </Step>201 </Step>

200 202 

201 <Step title="留下内联注释">203 <Step title="留下内联注释">


207 </Step>209 </Step>

208 210 

209 <Step title="在 PR 后继续迭代">211 <Step title="在 PR 后继续迭代">

210 创建 PR 后会话保持活跃。将 CI 失败输出或审查者注释粘贴到聊天中,并要求 Claude 解决它们。要让 Claude 自动监控 PR,请参阅[自动修复拉取请求](/docs/zh-CN/claude-code-on-the-web#auto-fix-pull-requests)。212 会话在创建 PR 后保持活跃。将 CI 失败输出或审查者注释粘贴到聊天中,并要求 Claude 解决它们。要让 Claude 自动监控 PR,请参阅[自动修复拉取请求](/docs/zh-CN/claude-code-on-the-web#auto-fix-pull-requests)。

211 </Step>213 </Step>

212</Steps>214</Steps>

213 215