Agent Hook 机制速查表
Hook = 在 AI Agent Loop 流水线上预先埋好的「检查站」。流水线:用户输入 → 模型推理 → 工具调用 → 工具执行 → 回复/空闲。各家都在这些节点前/后插钩。三家皆能 allow / deny(block) / modify(改入参或注入上下文)。
文本版 · 供搜索与朗读
Hook 机制速查表 · Claude Code / Cursor / OpenCode
Agent Hook 机制速查表
Claude Code · Cursor · OpenCode | 费曼视角 · 2026-08-08 可查证公开文档
一、核心心智模型
Hook = 在 AI Agent Loop 流水线上预先埋好的「检查站」。流水线:用户输入 → 模型推理 → 工具调用 → 工具执行 → 回复/空闲。各家都在这些节点前/后插钩。三家皆能 allow / deny(block) / modify(改入参或注入上下文)。
二、三器逐一看
Claude Code
配置:~/.claude/settings.json(用户)|.claude/settings.json(项目)|.claude/settings.local.json(本地)
模型:单一 Pre/Post 事件 + matcher 过滤工具名(支持正则)
类型:command / prompt / agent(三类型最全)
拦截:退出码 2;stdout JSON hookSpecificOutput.permissionDecision = allow/deny/ask/defer
事件:PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, Notification, Stop, SubagentStop, PreCompact, SessionStart, SessionEnd, PermissionRequest
入参改写:updatedInput;注入上下文:additionalContext
链式:deny > defer > ask > allow(默认安全)
Cursor
配置:~/.cursor/hooks.json(全局)|.cursor/hooks.json(项目,云端 agent 也跑)
模型:每阶段劈成独立事件(粒度最细)
类型:command / prompt
拦截:退出码 2;返回 {permission:"allow|deny|ask", userMessage, agentMessage}
细分事件:beforeShellExecution / afterShellExecution、beforeMCPExecution / afterMCPExecution、beforeReadFile / afterFileEdit、beforeSubmitPrompt、preCompact、stop、subagentStart/Stop、sessionStart/End、afterAgentResponse/Thought、Tab:beforeTabFileRead/afterTabFileEdit、workspaceOpen
原生兼容 Claude 钩子:自动映射事件名,认嵌套与扁平两种返回
优先级:企业 > 团队 > 项目.cursor > 用户.cursor > Claude本地 > Claude项目 > Claude用户
OpenCode
原生:插件 TS 函数,注册内部事件
兼容桥:johnnyasantoss/opencode-hooks 或 oh-my-opencode(认 Claude 格式)
拦截(桥):退出码 0 放行 / 1 问用户 / 2 拦截;error 字段优先
原生事件:tool.execute.before/after、session.created/idle/deleted、file.edited、file.watcher.updated、message.updated、lsp.client.diagnostics、tui.toast.show
原生最灵活:直接改 event.input,独享文件/LSP/UI 钩子
桥的缺口:FileChanged、PreCompact、Task*、Notification 等无对应 API → 不支持
三、对照总表
维度Claude CodeCursorOpenCode
配置载体settings.json 的 hooks.cursor/hooks.json (v1)原生=插件 TS;兼容=桥 hooks.json
触发模型Pre/Post + matcher每阶段独立事件原生=内部事件;桥=Claude 格式
Hook 类型command / prompt / agentcommand / prompt原生=函数;桥=command
拦截方式退出码2 + permissionDecision退出码2 + permission桥:0/1/2;原生=返回值
改写入参✅ updatedInput✅ updated_input✅ 原生直改
加载 Claude 钩子自身✅ 原生兼容✅ 经桥
云端执行需自备✅ 项目 hooks.json取决于桥部署
粒度亮点三类型最全拆得最细文件/LSP/UI 独一份
四、可复制模板
Claude Code — 拦危险命令 + 写后格式化
{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "echo \"$TOOL_INPUT_command\" | grep -qE 'rm -rf|sudo|git push --force' && exit 2 || exit 0"
}]
}],
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "jq -r '.tool_input.file_path' | { read f; case \"$f\" in *.ts|*.tsx) npx prettier --write \"$f\";; esac; } 2>/dev/null || true"
}]
}]
}
}
Cursor — 拦 shell 网络命令(.cursor/hooks.json)
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{ "command": "./scripts/approve-network.sh", "timeout": 30, "matcher": "curl|wget|nc" }
],
"afterFileEdit": [
{ "command": "./scripts/format.sh" }
]
}
}
OpenCode — 兼容桥(.opencode/hooks.json)
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash", "hooks": [ { "type": "command", "if": "Bash(rm *)", "error": "rm commands are not allowed" } ] }
],
"PostToolUse": [
{ "matcher": "Edit", "hooks": [ { "type": "command", "command": "/path/to/log-edit.sh" } ] }
]
}
}
费曼凭栏:想"写一次三家通吃",照 Claude 格式写——Cursor 原生认,OpenCode 装桥也跑得动大半。要最细守门选 Cursor;要深度咬合代码选 OpenCode 原生;要最省事生态最全选 Claude Code。Hook 只拦"高置信危险",别拦"我不喜欢"。
速查表由 WorkBuddy · 费曼视角生成 | 退出码:0=放行 · 2=拦截 · 其它=fail-open