Hooks
基于 Cursor 官方 Hooks 文档解释 agent loop hook、事件、配置路径、command hooks、prompt hooks 和 exit code。
Hooks(钩子,在固定事件上自动执行的脚本)让你用 custom scripts 观察、控制和扩展 Cursor agent loop。官方文档说明,hooks 是 spawned processes(派生进程,独立启动的子进程),通过 stdio(标准输入输出)双向传递 JSON,在 agent loop 的指定阶段前后运行。
阅读目标:读完本章,你应该能判断什么时候需要 hook,怎样配置 project/user hooks,并理解 command-based 和 prompt-based hooks 的失败行为。
1. Hooks 能做什么
官方列出的典型用途:
- Edit 后运行 formatter。
- 记录 analytics events。
- 扫描 PII(Personally Identifiable Information,个人可识别信息)或 secrets。
- Gate risky operations,例如 SQL writes。
- 控制 subagent,也就是 Task tool execution。
- 在 session start 注入 context。
flowchart TD
Event["Agent event"] --> Hook["Hook process"]
Hook --> Observe["Observe"]
Hook --> Block["Block"]
Hook --> Modify["Modify behavior"]
Observe --> Agent["Agent loop continues"]
Block --> Deny["Deny / ask"]
Modify --> Agent
Cloud agents 也会运行 repo hooks。Enterprise plans 下,它们还会运行 team hooks 和 enterprise-managed hooks。
2. Agent 和 Tab 事件
Hooks 同时支持 Cursor Agent 和 Cursor Tab,但事件不同。
| 范围 | 事件 |
|---|---|
| Agent lifecycle | sessionStart / sessionEnd |
| Generic tool use | preToolUse / postToolUse / postToolUseFailure |
| Subagent lifecycle | subagentStart / subagentStop |
| Shell | beforeShellExecution / afterShellExecution |
| MCP | beforeMCPExecution / afterMCPExecution |
| Files | beforeReadFile / afterFileEdit |
| Prompt | beforeSubmitPrompt |
| Context compaction | preCompact |
| Completion | stop |
| Agent response | afterAgentResponse / afterAgentThought |
| Tab completions | beforeTabFileRead / afterTabFileEdit |
官方把 Agent 和 Tab 分开,是因为 Tab 的 inline completions 更偏自动补全,Agent 更偏用户指令驱动。两个入口应该能使用不同策略。
3. 配置路径
创建 hooks.json。
| 类型 | 文件 | 作用域 | 脚本运行目录 |
|---|---|---|---|
| User hooks | ~/.cursor/hooks.json | 当前用户全局 | ~/.cursor/ |
| Project hooks | <project>/.cursor/hooks.json | 当前 repo | project root |
User 示例:
{
"version": 1,
"hooks": {
"afterFileEdit": [{ "command": "./hooks/format.sh" }]
}
}Project 示例:
{
"version": 1,
"hooks": {
"afterFileEdit": [{ "command": ".cursor/hooks/format.sh" }]
}
}Project hooks 从 project root 运行,所以路径用 .cursor/hooks/...。Cursor 会 watch hooks config files 并自动 reload。
4. Command-based hooks
Command hooks 是默认类型。脚本从 stdin 接收 JSON input,并通过 stdout 返回 JSON output。
{
"hooks": {
"beforeShellExecution": [
{
"command": ".cursor/hooks/approve-network.sh",
"timeout": 30,
"matcher": "curl|wget|nc"
}
]
}
}Exit code 行为:
| Exit code | 行为 |
|---|---|
0 | Hook succeeded,使用 JSON output |
2 | Block action,等价于返回 permission: "deny" |
| 其它 | Hook failed,action 默认继续(fail-open,失败默认放行,与 fail-closed 失败默认拦截相反) |
默认 fail-open 意味着 hook 脚本报错不等于阻止危险动作。用于安全 gate 的 hook 要把失败路径设计清楚,关键策略不要只靠可能崩溃的脚本。
5. Prompt-based hooks
Prompt hooks 用 LLM 判断自然语言条件,适合不想写脚本的 policy enforcement。
{
"hooks": {
"beforeShellExecution": [
{
"type": "prompt",
"prompt": "Does this command look safe to execute? Only allow read-only operations.",
"timeout": 10
}
]
}
}官方说明:
- 返回结构化
{ ok: boolean, reason?: string }。 - 使用 fast model 做快速判断。
$ARGUMENTS会自动替换为 hook input JSON。- 如果没有
$ARGUMENTS,hook input 会自动追加。 - 可用
model字段覆盖默认 LLM model。
6. 适合和不适合
适合 hooks:
- 低延迟、明确、可自动判定的检查。
- 格式化、审计、日志、只读安全 gate。
- 组织需要统一执行的检查。
不适合 hooks:
- 复杂产品判断。
- 需要大量上下文和人工审阅的任务。
- 失败后会造成生产副作用的自动化。
- 没有日志和回滚的拦截逻辑。
深读:为什么 hook 要从只读审计开始
Hook 处在 agent loop 里,触发频率高,失败后很容易打断正常工作。第一次落地时先做只读审计,比如记录 shell 命令、文件编辑和 MCP 调用。
当你确认事件 payload、性能、日志和误报率之后,再把 hook 升级成 block 或 ask。这样比一开始就拦截所有动作更可控。
7. 验收清单
上线 hook 前检查:
hooks.json放在正确作用域。- Project hooks 使用 project-root 相对路径。
- 脚本可执行。
- stdin JSON 和 stdout JSON 都能被独立测试。
- exit code
2的 deny 行为可验证。 - 非
0/2的 fail-open 风险可接受。 - 安全类 hook 有日志。
- Cloud Agent / team / enterprise hooks 的作用域清楚。
本章自检
完成本章后,用这 3 个问题检查自己是否真正理解:
- Agent hooks 和 Tab hooks 的事件为什么要分开?
- User hooks 和 Project hooks 的脚本运行目录有什么差异?
- Command hook 返回 exit code
2和其它非零 exit code 有什么不同?
通过标准:你能写出一个 beforeShellExecution hook,拦截网络命令,并说明失败时是否 fail-open。
官方来源
- Cursor Hooks —— 官方说明 hook 机制、事件、配置、command hooks、prompt hooks 和示例。
- Third Party Hooks —— 官方说明第三方 hooks 兼容。
- Partner Integrations —— 官方生态集成入口。