关于 hooks-management
hooks-management 是用于通过自然语言配置和维护 Agent 钩子的技能,涵盖事件、配置位置、验证和处理器模式,并涉及 Claude Code、Codex 与 Devin。
主要功能
- 01添加、列出、更新和移除钩子
- 02保存前验证钩子配置
- 03配置事件与工具匹配条件
- 04使用命令、HTTP、MCP 工具、提示词或 Agent 处理器
- 05支持 Claude Code、Codex 和 Devin 配置
适用场景
- 01在工具执行前记录命令
- 02阻止修改敏感文件
- 03文件变更后运行格式化
- 04为高风险命令请求审批
MCP 相关
它介绍了通过 `mcp_tool` 处理器调用已配置 MCP 服务工具的钩子模式。该技能本身并非 MCP 服务或客户端。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ codealive-ai/ ai-driven-development --skill hooks-management安装后在 Claude Code 中输入/hooks-management确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/claude-event-schemas.mdclaude-templates.mdcodex-hooks.mddevin-hooks.mdopencode-hooks.mdscripts/validate_hooks.py详细介绍
钩子管理
通过自然语言命令管理钩子和自动化。
重要:添加、修改或移除钩子后,务必告知用户需要重启 Agent,更改才能生效。钩子会在启动时加载。
快速参考
钩子事件(Claude Code,截至 2026-04,共 28 个事件):
- 会话生命周期:SessionStart、SessionEnd、InstructionsLoaded
- 用户输入:UserPromptSubmit、UserPromptExpansion
- 工具执行:PreToolUse、PostToolUse、PostToolUseFailure、PostToolBatch
- 权限:PermissionRequest、PermissionDenied
- 模型输出:Stop、StopFailure
- 子 Agent/任务:SubagentStart、SubagentStop、TaskCreated、TaskCompleted、TeammateIdle
- 配置/状态:ConfigChange、FileChanged、CwdChanged
- 压缩:PreCompact、PostCompact
- 工作树:WorktreeCreate、WorktreeRemove
- MCP:Elicitation、ElicitationResult
- 通知:Notification
处理程序类型:command、http、mcp_tool、prompt、agent。部分事件仅支持命令处理程序(PostCompact、PermissionDenied、Elicitation/ElicitationResult、FileChanged、CwdChanged、ConfigChange、InstructionsLoaded、WorktreeCreate/Remove、SubagentStart、StopFailure、TeammateIdle、Setup、SessionStart、SessionEnd、Notification)。
Claude Code 设置文件:
- 用户级:
~/.claude/settings.json - 项目级:
.claude/settings.json - 本地(不提交):
.claude/settings.local.json - 独立策略片段:
~/.claude/managed-settings.d/(仅限 managed-settings)
Codex CLI / Codex App 设置文件(截至 2026-06 的当前版本):
- 用户配置:
~/.codex/config.toml - 用户钩子:
~/.codex/hooks.json或<hooks>内联[hooks]表,位于~/.codex/config.toml - 项目钩子:
<repo>/.codex/hooks.json或<hooks>内联[hooks]表,位于<repo>/.codex/config.toml(仅限受信任的项目) - Codex App 和 CLI 共用这些配置层。在 App/IDE 中,设置界面会打开同一个
config.toml。 - 钩子默认启用。使用
[features].hooks = false禁用。codex_hooks是已弃用的别名。 - 非托管的 Codex 命令钩子必须通过
/hooks审查/信任;更改后的钩子定义在获得信任前会被跳过。
Devin CLI / 桌面端钩子位置:
- 项目级:
.devin/hooks.v1.json(独立钩子对象,推荐),或.devin/config.json/.devin/config.local.json中的"hooks" - 用户级:
~/.config/devin/config.json中的"hooks"(Windows 上为%APPDATA%\devin\config.json) - 当
read_config_from.claude开启时(默认),会自动导入.claude/下的 Claude 格式钩子 - 事件:PreToolUse、PostToolUse、PermissionRequest、UserPromptSubmit、Stop、PostCompaction、SessionStart、SessionEnd;
matcher是针对tool_name的正则表达式 - 完整的事件/输出约定请参阅 references/devin-hooks.md
Claude Code 对 PreToolUse 的默认控制机制:在标准输出中输出 JSON,并将 hookSpecificOutput.permissionDecision 设为 "allow"、"deny"、"ask"(触发内置的用户确认提示),或 "defer"(暂停无头工具调用;使用 -p --resume 恢复)。请参阅决策控制。不要自行设计确认机制(环境变量标志、交互式 osascript 提示、绕过令牌)——这些机制会破坏内置体验,并且在现有 permissions.allow 条目下会静默失效。
Codex 例外:Codex PreToolUse 目前尚不支持 "ask"。在 Codex 配置中,硬性拦截请使用 deny / 退出代码 2;提供建议性上下文请使用 additionalContext;原生提示请使用 Codex 审批策略/权限。
禁用所有钩子:在 settings.json 中设置 disableAllHooks: true。
工作流
1. 了解请求
解析用户的需求:
- 添加/创建:为特定事件和工具创建新钩子
- 列出/显示:显示当前钩子配置
- 移除/删除:移除指定钩子
- 更新/修改:更改现有钩子
- 验证:检查钩子是否存在错误
2. 写入前进行验证
保存前务必运行验证:
python3 "$SKILL_PATH/scripts/validate_hooks.py" ~/.claude/settings.json
3. 读取当前配置
cat ~/.claude/settings.json 2>/dev/null || echo '{}'
4. 应用更改
修改文件时使用 Edit 工具,新建文件时使用 Write 工具。
添加钩子
将自然语言转换为钩子配置
| 用户说 | 事件 | 匹配器 | 备注 |
|---|---|---|---|
| "记录所有 bash 命令" | PreToolUse | Bash | 记录到文件 |
| "编辑后格式化文件" | PostToolUse | Edit|Write | 运行格式化工具 |
| "阻止更改 .env 文件" | PreToolUse | Edit|Write | 退出代码 2 会阻止操作 |
| "完成后通知我" | Notification | "" | 桌面通知 |
| "代码更改后运行测试" | PostToolUse | Edit|Write | 按扩展名筛选 |
| "危险命令前先询问" | PreToolUse | Bash | Claude Code:发出 JSON permissionDecision: "ask"(内置确认界面)。Codex:尽可能使用审批策略;不支持在钩子层使用 ask。 |
| "X 操作需要手动批准" | PreToolUse | Bash/Edit/Write | Claude Code:发出 JSON permissionDecision: "ask",而不是退出代码 2。Codex:选择策略提示或硬性阻止。 |
| "未经确认则阻止" | PreToolUse | Bash | Claude Code:JSON "ask" 可让用户逐次批准调用。Codex:目前无法通过钩子创建确认提示。 |
钩子配置模板
{
"hooks": {
"EVENT_NAME": [
{
"matcher": "TOOL_PATTERN",
"hooks": [
{
"type": "command",
"command": "SHELL_COMMAND",
"timeout": 60
}
]
}
]
}
}
简单钩子与复杂钩子
复杂钩子优先使用脚本文件。包含嵌套引号、osascript 或多步逻辑的内联命令通常会因 JSON 转义问题而出错。
| 复杂度 | 方式 | 示例 |
|---|---|---|
| 简单 | 内联 | jq -r '.tool_input.command' >> log.txt |
| 中等 | 内联 | 使用基本条件判断的单条 grep/jq 管道 |
| 复杂 | 脚本文件 | 对话框、多项条件、osascript、错误处理 |
脚本位置:~/.claude/hooks/(如有需要,请创建目录)
PreToolUse 的脚本模板(~/.claude/hooks/my-hook.sh)——将 JSON 决策控制作为主要机制;退出代码仅作为简单阻止操作的后备方案:
#!/bin/bash
set -euo pipefail
# Read JSON input from stdin
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
# Your logic here
if echo "$cmd" | grep -q 'pattern-requiring-confirmation'; then
# PRIMARY PATTERN for "require user confirmation": emit JSON on stdout.
# Claude Code will show its built-in confirm prompt to the user.
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "Explain why this call is risky"
}
}'
exit 0
fi
if echo "$cmd" | grep -q 'pattern-to-hard-block'; then
# Hard block (no user override possible): JSON deny, NOT exit 2.
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Reason shown to Claude"
}
}'
exit 0
fi
exit 0 # Allow (silent)
为何使用 JSON 决策,而不是退出代码 2 或自制提示:
permissionDecision: "ask"会触发 Claude Code 内置的确认界面,用户会看到清晰的提示,并可逐次允许或拒绝。exit 2是直接阻止操作;用户无法在界面中覆盖此决定,而且 Claude 往往会尝试通过其他方式继续操作。- 自制方案(如
CONFIRMED=1之类的环境变量标志、osascript对话框、绕过令牌)会破坏原生交互体验、将内容泄露到命令历史中;如果工具已有匹配的permissions.allow规则,这些方案还会被静默绕过。
使用脚本的钩子配置:
{
"type": "command",
"command": "~/.claude/hooks/my-hook.sh"
}
其他处理程序类型(2026):http(将事件 JSON 通过 POST 发送到 URL)、mcp_tool(调用已配置 MCP 服务上的工具)、prompt(使用大模型评估提示词,支持 $ARGUMENTS)、agent(运行带工具的 Agent 式验证器)。某些事件仅支持命令处理程序(PostCompact、PermissionDenied、Elicitation/ElicitationResult、FileChanged、CwdChanged、ConfigChange、InstructionsLoaded、WorktreeCreate/Remove、SubagentStart、StopFailure、TeammateIdle、SessionStart/End、Notification)。
务必:
- 在
~/.claude/hooks/中创建脚本 - 添加可执行权限:
chmod +x ~/.claude/hooks/my-hook.sh - 使用示例输入进行测试:
echo '{"tool_input":{"command":"test"}}' | ~/.claude/hooks/my-hook.sh
常见模式
日志记录(PreToolUse):
{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.command' >> ~/.claude/command-log.txt"
}]
}
文件保护(PreToolUse,使用退出代码 2 阻止):
{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | grep -qE '(\\.env|secrets)' && exit 2 || exit 0"
}]
}
自动格式化(PostToolUse):
{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "file=$(jq -r '.tool_input.file_path'); [[ $file == *.ts ]] && npx prettier --write \"$file\" || true"
}]
}
桌面通知(Notification):
{
"matcher": "",
"hooks": [{
"type": "command",
"command": "osascript -e 'display notification \"Claude needs attention\" with title \"Claude Code\"'"
}]
}
决策控制(Claude Code PreToolUse)
Claude Code PreToolUse hook 通过在 stdout 上输出 JSON 来控制工具执行。这是默认机制——只要意图不止是“静默允许/强制阻止”,尤其是需要询问用户确认时,就应使用它,而不是使用退出码。
permissionDecision | 行为 | 用途 |
|---|---|---|
"allow" | 绕过权限检查,静默继续 | 预先批准安全调用 |
"deny" | 阻止调用,并向 Claude 显示原因 | 强制阻止(用户无法覆盖) |
"ask" | 向用户显示 Claude Code 内置确认界面 | “要求手动批准 X”——规范用法 |
"defer" | 暂停无头工具调用,通过 -p --resume 恢复 | 无头(-p)会话中的外部系统集成 |
其他 JSON 字段:
permissionDecisionReason— 向用户显示"allow"/"ask"的原因,向 Claude 显示"deny"的原因updatedInput— 在执行前修改工具输入additionalContext— 在工具执行前向 Claude 注入上下文
在执行危险命令前询问用户(规范用法)
当用户提出类似**“要求手动确认”、“执行 X 前先询问”、“未经我批准,不要运行 Y”**的要求时,应使用此模式。不要自行设计绕过用的环境变量、osascript 对话框或确认令牌。内置提示已能处理每次调用的允许/拒绝,并且这是唯一能正确集成现有 permissions.allow 规则的方式。
#!/bin/bash
set -euo pipefail
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')
if echo "$cmd" | grep -qE 'supabase\s+db\s+reset'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "ask",
permissionDecisionReason: "This will destroy and recreate the local database."
}
}'
else
exit 0
fi
拒绝并说明原因(强制阻止)
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
注意事项:"ask" 与现有 permissions.allow 规则的区别
如果工具调用已匹配 .claude/settings.local.json → permissions.allow 中的某个条目(例如,本会话对 "Bash" 一律放行),hook 的 "ask" 就会被绕过,调用会静默继续。表现:hook 看起来没有生效。排查时请检查 .claude/settings.local.json 并收紧允许规则,或在 hook 生效期间移除匹配项的一律放行规则。
完整的输出架构请参阅 references/claude-event-schemas.md。
Codex CLI / Codex App 钩子
截至 2026 年 6 月,Codex 钩子默认已启用,Codex CLI、Codex IDE 扩展以及 Codex App/桌面会话通过相同的 ~/.codex 和受信任项目 .codex 配置层共享这些钩子。
当前 Codex 生命周期事件:
SessionStartSubagentStartPreToolUsePermissionRequestPostToolUsePreCompactPostCompactUserPromptSubmitSubagentStopStop
新配置中不要添加旧的功能标志。如果必须禁用钩子,请使用:
[features]
hooks = false
最简 PreToolUse 阻止钩子:
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 ~/.codex/hooks/policy.py'
timeout = 30
statusMessage = "Checking Bash command"
等效的 ~/.codex/hooks.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "^Bash$",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 ~/.codex/hooks/policy.py",
"timeout": 30,
"statusMessage": "Checking Bash command"
}
]
}
]
}
}
每个配置层优先只使用一种表示方式:hooks.json 或内联 [hooks]。Codex 会加载两者,并在同一层中两者同时存在时发出警告。
阻止语义:退出码 2 会阻止操作(stderr 是原因),或者输出 JSON {"hookSpecificOutput": {"hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "..."}}。
Codex 的一个重要不足:PreToolUse 目前不支持 permissionDecision: "ask"。返回 "ask" 会导致钩子运行失败,Codex 随后仍会继续调用工具。若要确保失败时默认拒绝,应将 Claude 风格的 ask 映射为 Codex 的 deny。
将 Claude Code 的 ask 钩子迁移到 Codex 时,优先按以下顺序处理:
- 如果命令未经审核就不得运行,请使用硬性
deny/退出码2。 - 如果可以通过命令 argv 前缀表达风险操作,且用户明确接受尽力而为的 Codex 原生提示,请使用 Codex 规则来显示提示,并让钩子在该特定原因代码下保持静默。
- 除非你有意只记录日志,否则不要让整个钩子进入影子模式;这样会放行钩子原本会拦截的所有风险操作。
对于 bash-guard,Codex 实时模式会默认对内部 ask 决策执行硬性 deny。只有列在 BASH_GUARD_CODEX_DEFER_REASON_CODES 中的原因代码才会被允许传递给 execpolicy;只有用户传入 --codex-native-prompts 时,安装程序才会添加该环境变量。每个延后处理的原因代码都必须有相匹配的 prefix_rule(... decision="prompt");否则风险命令会被静默放行。
只有当 Codex 已准备请求批准时,才会触发 PermissionRequest。它可以返回 allow、deny 或不作决定;它无法为 Codex 原本会直接运行而不询问的命令创建提示。
Codex PreToolUse 可以拦截 Bash、apply_patch 文件编辑和 MCP 工具调用,但它不是完整的强制执行边界:对更复杂的 shell 路径,拦截能力并不完善;WebSearch/非 shell/非 MCP 工具调用也不在其范围内。
完整的 Codex 钩子参考、所有事件的输入/输出架构、常见模式,以及从旧版 AfterAgent/AfterToolUse 事件迁移的说明,请参阅 references/codex-hooks.md。
OpenCode 钩子(基于插件)
OpenCode(anomalyco/opencode v1.14.x)不使用基于配置的 shell 钩子。钩子是订阅生命周期事件的 TypeScript/JavaScript 插件。最接近 PreToolUse 的对应项是 tool.execute.before——在其中抛出异常会阻止工具调用。
// .opencode/plugins/env-protection.ts
import type { Plugin } from "@opencode-ai/plugin"
export default (async () => ({
tool: {
execute: {
before: async (input, output) => {
if (output.args.filePath?.includes(".env")) {
throw new Error("Reading .env is forbidden")
}
},
},
},
})) satisfies Plugin
插件位置:
- 项目:
.opencode/plugins/*.ts - 全局:
~/.config/opencode/plugins/*.ts - npm 包:在
opencode.json的plugin: []下列出
常见事件:tool.execute.before、tool.execute.after、session.idle、session.created、file.edited、permission.asked、command.executed(总计约 25 个)。
重要注意事项(v1.14.x):tool.execute.* 钩子不会对 MCP 工具调用触发——应改用 opencode.json 中的 permission 块来控制 MCP 工具访问。
对于“执行前询问”语义,优先使用 permission 规则,而不是在插件中抛出异常——规则可与内置确认界面集成:
{ "permission": { "bash": { "rm -rf *": "ask" } } }
完整的事件目录、从 Claude Code 钩子迁移的模式,以及 npm 插件分发说明,请参阅 references/opencode-hooks.md。
事件输入架构
完整的各事件类型的 JSON 输入架构(Claude Code),请参阅 references/claude-event-schemas.md。
验证
运行验证脚本检查钩子:
python3 "$SKILL_PATH/scripts/validate_hooks.py" <settings-file>
验证内容:
- JSON 语法
- 必填字段(type、command/prompt)
- 有效事件名称
- 匹配器模式(正则表达式有效性)
- 命令语法基础检查
移除钩子
- 读取当前配置
- 根据事件 + 匹配器 + 命令模式识别钩子
- 从 hooks 数组中移除
- 如果数组为空,则移除匹配器条目
- 如果事件为空,则移除事件键
- 验证并保存
退出代码
| 代码 | 含义 | 使用场景 |
|---|---|---|
| 0 | 成功/允许 | 继续执行 |
| 2 | 阻止 | 简单阻止(对于 PreToolUse,优先使用 JSON 决策控制) |
| 其他 | 错误 | 记录到 stderr,在详细模式下显示 |
安全检查清单
添加钩子前,请确认:
- 不记录凭据
- 不暴露敏感数据
- 使用具体的匹配器(尽可能避免
*) - 验证输入解析
- 为长时间运行的操作设置适当的超时时间
故障排除
钩子未触发:检查匹配器是否区分大小写,并确保事件名称完全一致。
命令执行失败:使用示例 JSON 输入单独测试命令。
权限被拒绝:确保脚本可执行(chmod +x)。
超时:增大 timeout 字段的值,或优化命令。