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 —— 官方生態整合入口。