本页译自英文文档。命令、标识符和示例保持原样。运行时 7.24.4 · SDK 2.6.7。 英文原文
生命周期钩子
状态:生效
范围:当前状态
最近审阅:2026-08-23
负责人:ax-code 运行时
生命周期钩子让你在智能体事件上运行 shell 命令,而无需重新构建运行时。它们补充权限规则和隔离沙箱:钩子是确定性的副作用(“总是格式化”、“永不强制推送”),而提示仍然只是建议。
事件
| 事件 | 时机 | 能否阻止? |
|---|---|---|
| PreToolUse | 工具执行之前 | 能(blockOnFailure: true) |
| PostToolUse | 工具完成之后(args:工具参数)。有界的标准输出 / 结构化反馈会追加到模型看到的工具结果中;见下文 |
不能 |
| PostToolUseFailure | 工具抛出之后(args:{ args, error },错误文本上限为 4,000 个字符)。发后即忘;错误仍原样到达模型 |
不能 |
| Stop | 会话回合完成时(包可通过自动化在停止时运行) | 不能 |
| UserPromptSubmit | 用户提示提交时,在消息持久化之前 | 能(blockOnFailure: true) |
| PreCompact | 会话压缩运行之前(args:{ auto, overflow }) |
不能 |
| SubagentStop | 当 task 子智能体结束时(args:{ agent, status }) |
不能 |
| SessionStart | 顶层会话创建时(args:{ sessionID, title, time }) |
不能 |
| SessionEnd | 会话被移除或归档时(args:{ sessionID, reason },reason 为 "remove" 或 "archive") |
不能 |
| PostCompact | 会话压缩成功完成之后(args:{ sessionID, reason },reason 为 "auto" 或 "manual";压缩中止时不触发,例如上下文溢出) |
不能 |
| Interrupt | 用户或操作者显式取消正在运行的回合时(args:{ sessionID };正常回合完成或内部清理时不触发) |
不能 |
四个会话生命周期事件(SessionStart、SessionEnd、PostCompact、Interrupt)以及 PostToolUseFailure 仅用于观察:它们触发后即忘记,从不阻塞生命周期路径,其载荷只携带标识、原因和时间戳——从不携带对话文本、摘要或工具输出。子智能体会话不触发 SessionStart(它们已经通过 SubagentStop 呈现)。SubagentStop 对由 task 和 task_parallel 启动的子项都会触发。
PostToolUse 反馈到达模型
PostToolUse 钩子可以把文本交回模型。它被追加到工具结果中的一个 <hook_feedback event="PostToolUse"> 块里,位于工具自身输出之后;它从不替换输出,也从不阻塞。
- 旧式条目(没有
protocol):以 0 退出的钩子经过修剪的标准输出。 protocol: "claude-code"条目:hookSpecificOutput.additionalContext、一份reason(来自{"decision": "block", "reason": "..."}判定),或钩子以 2 退出时的标准错误。其他非零退出不贡献任何内容。
每条钩子的反馈上限为 4,000 个字符,每次工具调用为 8,000 个字符,因此嘈杂的钩子不能淹没上下文。这正是 format-after-edit 包有用的原因:它的提醒现在会进入模型的下一回合,而不只是留在日志里。
这些名称映射到 AX Code 的内部插件触发器(tool.execute.before / tool.execute.after),再加上会话级的提示、压缩、子智能体和停止钩子。合成的延续提示(内部 agentRouting: "preserve" 提示)不会触发 UserPromptSubmit。
启用包
项目钩子和插件会执行仓库控制的代码,因此 .ax-code/hooks.json、.ax-code/plugin/ 以及项目配置的插件默认禁用。审阅之后,在仓库之外启动 AX Code 时选择加入:
AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code
然后在项目中创建 .ax-code/hooks.json:
{
"packs": ["format-after-edit", "block-force-push", "require-tests-on-stop", "protect-env-files", "log-bash-commands"]
}
官方包(≥5)
| 包 | 事件 | 说明 |
|---|---|---|
format-after-edit |
PostToolUse | 提醒智能体在编辑后格式化 |
block-force-push |
PreToolUse | 阻止 git push --force / -f |
require-tests-on-stop |
Stop | 提醒在变更后进行验证 |
protect-env-files |
PreToolUse | 当工具触及 .env 时发出警告 |
log-bash-commands |
PreToolUse | 记录 bash 命令以供审计 |
自定义钩子:
{
"hooks": [
{
"event": "PreToolUse",
"matcher": "bash",
"command": "echo running bash",
"blockOnFailure": false
}
]
}
Claude Code 线路协议(可选加入)
如果你已有为 Claude Code 编写的钩子,条目可以用 "protocol": "claude-code" 选择加入 Claude Code 线路协议:
{
"hooks": [
{
"event": "PreToolUse",
"matcher": "bash",
"command": "my-claude-code-hook.sh",
"protocol": "claude-code"
}
]
}
对于可阻止的事件(PreToolUse、UserPromptSubmit),已加入的条目按 Claude Code 语义解码,而不是做 blockOnFailure 检查:
- 退出码 2 阻止该动作;钩子的标准错误会作为原因呈现。格式错误的标准输出仍然阻止(故障安全)。
- 退出码 0 且标准输出为 JSON
{"permissionDecision": "allow"|"deny"|"ask", "reason"?}:allow则继续;deny则以reason阻止;ask会在交互式hook权限提示上暂停该工具调用,并显示原因(默认"hook requested user confirmation")。该提示仅限交互:任何always规则、通配授予或自主自动批准都不能回答它,无头运行会拒绝它,模型将其视为普通的权限拒绝。后一个钩子回答deny会胜过较早的ask。UserPromptSubmit没有可附加提示的工具调用,因此ask在那里仍然阻止。嵌套的 Claude Code 形态{"hookSpecificOutput": {"permissionDecision": "...", "permissionDecisionReason": "..."}}被接受为别名。 - 任何其他退出码 都是非阻塞错误(记入日志,动作继续)。
仅观察的事件完全忽略解码器——它们永远不能阻止。没有 protocol 字段的条目行为与以前完全相同。
钩子命令可用的环境变量:
HOOK_EVENT— PreToolUse(工具前)、PostToolUse(工具后)、PostToolUseFailure(工具失败后)、Stop(停止)、UserPromptSubmit(提交用户提示)、PreCompact(压缩前)、SubagentStop(子智能体停止)、SessionStart(会话开始)、SessionEnd(会话结束)、PostCompact(压缩后)、Interrupt(中断)HOOK_TOOL— 工具标识HOOK_SESSION_IDHOOK_ARGS_JSON— JSON 工具参数HOOK_ARGS_STDIN=1— 完整的 JSON 参数始终可在标准输入上获得;载荷大于 32 KiB 时HOOK_ARGS_JSON为空HOOK_PACK— 适用时的包名
钩子子进程继承经过清理的 AX Code 环境。AX Code 保留普通的平台和工具变量,但移除类似秘密的名称、携带凭据的 URL、诸如 SSH_AUTH_SOCK 的凭据辅助程序,以及诸如 NODE_OPTIONS 的进程注入变量。上面的 HOOK_* 协议变量在清理之后添加,并且始终可用。
需要环境凭据的完全受信任旧式钩子,可以在仓库之外恢复先前行为:
AX_CODE_HOOKS_FULL_ENV=1 AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code
这个逃生口会把每个环境变量暴露给每个已启用的钩子。仓库不能通过 .ax-code/hooks.json 请求它;仅在审阅全部钩子和包之后使用。
安全说明: 环境清理减少了环境凭据暴露,但不会把钩子命令放进沙箱。钩子仍然是任意 shell 代码,可以读取可访问的文件并使用主机网络。把它们当作受信任代码,并审阅每一个已启用的钩子和包。
与隔离的关系
钩子不能替代沙箱。请使用:
- 应用隔离,用于可移植的写入/网络边界
- 操作系统隔离(默认的
"auto"后端),在可用时由内核强制执行 bash 沙箱 - 钩子,用于策略副作用以及强制推送之类的硬阻止
见 沙箱模式 和 SECURITY.md。