鉤子可讓你通過自定義腳本觀察、控制和擴展智能體循環。你可以在項目級或用戶級的 hooks.json 文件中定義鉤子,也可以通過 自定義 中的插件安裝鉤子。鉤子是通過 stdio 使用 JSON 進行雙向通信的子進程。它們會在智能體循環中定義的各個階段之前或之後運行,並可觀察、阻止或修改行爲。
藉助鉤子,你可以:
- 在編輯後運行格式化工具
- 爲事件添加使用分析
- 掃描 PII 或機密信息
- 限制高風險操作 (例如 SQL 寫入)
- 控制子智能體 (Task tool) 的執行
- 在會話開始時注入上下文
正在尋找現成可用的集成?請參閱合作伙伴集成,瞭解我們的生態合作伙伴提供的安全、治理和機密信息管理解決方案。
Cursor 支持從 Claude Code 等第三方工具加載鉤子。有關兼容性和配置的詳細信息,請參閱第三方鉤子。
鉤子類別¶
鉤子按觸發條件分爲三類:
智能體鉤子 (Cmd+K/Agent Chat) 在智能體會話期間觸發:
sessionStart/sessionEnd- 管理會話生命週期preToolUse/postToolUse/postToolUseFailure- 通用工具使用鉤子 (對所有工具觸發)subagentStart/subagentStop- 子智能體 (Task 工具) 生命週期beforeShellExecution/afterShellExecution- 控制 shell 命令beforeMCPExecution/afterMCPExecution- 控制 MCP 工具的使用beforeReadFile/afterFileEdit- 控制文件訪問和編輯beforeSubmitPrompt- 在提交前驗證提示詞preCompact- 監測上下文窗口壓縮stop- 處理智能體完成事件afterAgentResponse/afterAgentThought- 跟蹤智能體響應
**Tab 鉤子 (行內補全) **在自主 Tab 操作期間觸發:
beforeTabFileRead- 控制 Tab 補全的文件訪問afterTabFileEdit- 對 Tab 編輯進行後處理
應用生命週期鉤子在任何智能體會話之外觸發:
workspaceOpen- 在 Cursor 打開工作區以及每次工作區文件夾變更時觸發。可返回要爲當前工作區加載的額外插件路徑。
這些獨立的鉤子入口可讓您針對自主 Tab 操作、用戶驅動的 Agent 操作和工作區啓動應用不同的策略。
雲端代理支持¶
雲端代理會運行代碼倉庫中的基於命令的鉤子。如果你在項目根目錄的 .cursor/hooks.json 中定義了鉤子,雲端代理會自動加載並在工作過程中運行這些鉤子。
在企業版方案中,雲端代理還會運行通過網頁儀表盤配置的團隊鉤子和由企業統一管理的鉤子。
雲端代理有時會在早期探索輪次中以只讀環境啓動。這些輪次不會運行鉤子。智能體獲得可寫環境後,鉤子便會開始運行。
支持的鉤子¶
雲端代理支持以下鉤子:
| 鉤子 | 是否支持 |
|---|---|
beforeShellExecution |
是 |
afterShellExecution |
是 |
beforeReadFile |
是 |
afterFileEdit |
是 |
preToolUse |
是 |
postToolUse |
是 |
postToolUseFailure |
是 |
subagentStart |
是 |
subagentStop |
是 |
beforeSubmitPrompt |
是 |
preCompact |
是 |
afterAgentResponse |
是 |
afterAgentThought |
是 |
stop |
是 |
雲端代理不支持的鉤子¶
由於執行環境不同,部分鉤子不適用於雲端代理:
| 鉤子 | 原因 |
|---|---|
sessionStart |
因雲端代理仍可能在只讀環境中啓動,暫不支持。在該環境中鉤子不會加載,因此雲端 sessionStart 會在首次寫入後才觸發,而非在會話真正開始時。 |
sessionEnd |
雲端代理沒有以編輯器生命週期爲界的會話邊界。sessionEnd 與 IDE 會話關聯,而非雲端代理聊天。 |
beforeMCPExecution / afterMCPExecution |
因雲端代理仍可能在鉤子不會加載的只讀環境中啓動,且 MCP 鉤子的觸發時機尚不明確,暫不支持。 |
beforeTabFileRead / afterTabFileEdit |
Tab 補全是 IDE 功能,不會在雲端代理中運行。 |
workspaceOpen |
這是 IDE 生命週期鉤子,不適用於雲端代理。 |
配置來源¶
雲端代理會從以下來源加載 hooks:
- 項目 hooks (倉庫中的
.cursor/hooks.json) :在雲端代理執行任務時加載並運行。 - 團隊 hooks (企業版) :從儀表盤分發,並在雲端代理中運行。
- 企業版 hooks (企業版) :由系統統一管理,並在雲端代理中運行。
用戶級 hooks (~/.cursor/hooks.json) 無法在雲端代理中使用。雲端代理 VM 無法訪問本地主目錄中的配置。
執行類型限制¶
雲端代理僅支持運行基於命令的鉤子。基於提示詞的鉤子需要在鉤子與智能體循環之間配置身份驗證連接,而云端執行環境不提供此功能。
快速開始¶
創建 hooks.json 文件。你可以在項目級別 (<project>/.cursor/hooks.json) 或主目錄 (~/.cursor/hooks.json) 中創建。項目 hooks 僅適用於特定項目,主目錄 hooks 則全局適用。
用戶 hooks (\~/.cursor/)¶
如需創建全局適用的用戶級 hooks,請創建 ~/.cursor/hooks.json:
{
"version": 1,
"hooks": {
"afterFileEdit": [{ "command": "./hooks/format.sh" }]
}
}
在 ~/.cursor/hooks/format.sh 中創建鉤子腳本:
#!/bin/bash
# 讀取輸入,執行操作,然後以 0 退出
cat > /dev/null
exit 0
將其設爲可執行:
chmod +x ~/.cursor/hooks/format.sh
項目 hooks (.cursor/)¶
如需創建僅適用於特定代碼倉庫的項目 hooks,請創建 <project>/.cursor/hooks.json:
{
"version": 1,
"hooks": {
"afterFileEdit": [{ "command": ".cursor/hooks/format.sh" }]
}
}
注意:項目 hooks 從項目根目錄運行,因此請使用 .cursor/hooks/format.sh (而非 ./hooks/format.sh) 。
在 <project>/.cursor/hooks/format.sh 中創建鉤子腳本:
#!/bin/bash
# 讀取輸入,執行操作,然後以 0 退出
cat > /dev/null
exit 0
將其設爲可執行:
chmod +x .cursor/hooks/format.sh
Cursor 會監視 hooks 配置文件並自動重新加載。每次編輯文件後,都會運行你的鉤子。
鉤子類型¶
鉤子支持兩種執行類型:基於命令 (默認) 和基於提示詞 (由 LLM 評測) 。
基於命令的鉤子¶
命令鉤子會執行 shell 腳本,腳本通過 stdin 接收 JSON 輸入,並通過 stdout 返回 JSON 輸出。
{
"hooks": {
"beforeShellExecution": [
{
"command": "./scripts/approve-network.sh",
"timeout": 30,
"matcher": "curl|wget|nc"
}
]
}
}
退出碼行爲:
- 退出碼
0- 鉤子執行成功,使用 JSON 輸出 - 退出碼
2- 阻止該操作 (等同於返回permission: "deny") - 其他退出碼 - 鉤子執行失敗,操作仍會繼續 (默認失敗時放行)
基於提示詞的鉤子¶
提示詞鉤子使用 LLM 評估自然語言條件,適用於無需編寫自定義腳本的策略執行。
{
"hooks": {
"beforeShellExecution": [
{
"type": "prompt",
"prompt": "Does this command look safe to execute? Only allow read-only operations.",
"timeout": 10
}
]
}
}
功能:
- 返回結構化的
{ ok: boolean, reason?: string }響應 - 使用快速模型進行快速評測
$ARGUMENTS佔位符會自動替換爲鉤子輸入 JSON- 如果未提供
$ARGUMENTS,則會自動追加鉤子輸入 - 可通過可選的
model字段覆蓋默認 LLM 模型
示例¶
以下示例使用 ./hooks/... 路徑,適用於用戶 hooks (~/.cursor/hooks.json) ,其腳本從 ~/.cursor/ 目錄運行。對於項目 hooks (<project>/.cursor/hooks.json) ,由於腳本從項目根目錄運行,請改用 .cursor/hooks/... 路徑。
```json title=”hooks.json”
{
“version”: 1,
“hooks”: {
“sessionStart”: [
{
“command”: “./hooks/session-init.sh”
}
],
“sessionEnd”: [
{
“command”: “./hooks/audit.sh”
}
],
“beforeShellExecution”: [
{
“command”: “./hooks/audit.sh”
},
{
“command”: “./hooks/block-git.sh”
}
],
“beforeMCPExecution”: [
{
“command”: “./hooks/audit.sh”
}
],
“afterShellExecution”: [
{
“command”: “./hooks/audit.sh”
}
],
“afterMCPExecution”: [
{
“command”: “./hooks/audit.sh”
}
],
“afterFileEdit”: [
{
“command”: “./hooks/audit.sh”
}
],
“beforeSubmitPrompt”: [
{
“command”: “./hooks/audit.sh”
}
],
“preCompact”: [
{
“command”: “./hooks/audit.sh”
}
],
“stop”: [
{
“command”: “./hooks/audit.sh”
}
],
“beforeTabFileRead”: [
{
“command”: “./hooks/redact-secrets-tab.sh”
}
],
“afterTabFileEdit”: [
{
“command”: “./hooks/format-tab.sh”
}
]
}
}
```sh title="audit.sh"
#!/bin/bash
# audit.sh - 將所有 JSON 輸入寫入 /tmp/agent-audit.log 的鉤子腳本
# 此腳本供 Cursor 的鉤子系統調用,用於審計
# 從 stdin 讀取 JSON 輸入
json_input=$(cat)
# 爲日誌條目生成時間戳
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# 如果日誌目錄不存在,則創建該目錄
mkdir -p "$(dirname /tmp/agent-audit.log)"
# 將帶時間戳的 JSON 條目寫入審計日誌
echo "[$timestamp] $json_input" >> /tmp/agent-audit.log
# 正常退出
exit 0
```sh title=”block-git.sh”
!/bin/bash¶
阻止 git 命令,並引導改用 gh 工具的鉤子¶
此鉤子實現了 Cursor Hooks 規範中的 beforeShellExecution 鉤子¶
初始化調試日誌¶
echo “Hook execution started” >> /tmp/hooks.log
從 stdin 讀取 JSON 輸入¶
input=$(cat)
echo “Received input: $input” >> /tmp/hooks.log
從 JSON 輸入中解析命令¶
command=\((echo "\)input” | jq -r ‘.command // empty’)
echo “Parsed command: ‘$command’” >> /tmp/hooks.log
檢查命令是否包含“git”或“gh”¶
if [[ “\(command" =~ git[[:space:]] ]] || [[ "\)command” == “git” ]]; then
echo “Git command detected - blocking: ‘\(command'" >> /tmp/hooks.log
# 阻止 git 命令,並提供改用 gh 工具的指引
cat << EOF
{
"continue": true,
"permission": "deny",
"user_message": "Git command blocked. Please use the GitHub CLI (gh) tool instead.",
"agent_message": "The git command '\)command’ has been blocked by a hook. Instead of using raw git commands, please use the ‘gh’ tool which provides better integration with GitHub and follows best practices. For example:\n- Instead of ‘git clone’, use ‘gh repo clone’\n- Instead of ‘git push’, use ‘gh repo sync’ or the appropriate gh command\n- For other git operations, check if there’s an equivalent gh command or use the GitHub web interface\n\nThis helps maintain consistency and leverages GitHub’s enhanced tooling.”
}
EOF
elif [[ “\(command" =~ gh[[:space:]] ]] || [[ "\)command” == “gh” ]]; then
echo “GitHub CLI command detected - asking for permission: ‘$command’” >> /tmp/hooks.log
# 爲 gh 命令請求權限
cat << EOF
{
“continue”: true,
“permission”: “ask”,
“user_message”: “GitHub CLI command requires permission: \(command",
"agent_message": "The command '\)command’ uses the GitHub CLI (gh) which can interact with your GitHub repositories and account. Please review and approve this command if you want to proceed.”
}
EOF
else
echo “Non-git/non-gh command detected - allowing: ‘$command’” >> /tmp/hooks.log
# 允許非 git 和非 gh 命令
cat << EOF
{
“continue”: true,
“permission”: “allow”
}
EOF
fi
### TypeScript stop 自動化鉤子
需要在同一鉤子中使用類型化 JSON、持久化文件 I/O 和 HTTP 調用時,可選擇 TypeScript。這個由 Bun 驅動的 `stop` 鉤子會在磁盤上記錄每個對話的失敗次數,將結構化遙測數據轉發到內部 API,並可在智能體連續失敗兩次後自動安排重試。
```json title="hooks.json"
{
"version": 1,
"hooks": {
"stop": [
{
"command": "bun run .cursor/hooks/track-stop.ts --stop"
}
]
}
}
```ts title=”.cursor/hooks/track-stop.ts”
import { mkdir, readFile, writeFile } from ‘node:fs/promises’;
import { stdin } from ‘bun’;
type StopHookInput = {
conversation_id: string;
generation_id: string;
model: string;
model_id?: string;
model_params?: Array<{ id: string; value: string }>;
status: ‘completed’ | ‘aborted’ | ‘error’;
loop_count: number;
};
type StopHookOutput = {
followup_message?: string;
};
type MetricsEntry = {
lastStatus: StopHookInput[‘status’];
errorCount: number;
lastUpdatedIso: string;
};
type MetricsStore = Record
const STATE_DIR = ‘.cursor/hooks/state’;
const METRICS_PATH = ${STATE_DIR}/agent-metrics.json;
const TELEMETRY_URL = Bun.env.AGENT_TELEMETRY_URL;
async function parseHookInput
const text = await stdin.text();
return JSON.parse(text) as T;
}
async function readMetrics(): Promise
try {
return JSON.parse(await readFile(METRICS_PATH, ‘utf8’)) as MetricsStore;
} catch {
return {};
}
}
async function writeMetrics(store: MetricsStore) {
await mkdir(STATE_DIR, { recursive: true });
await writeFile(METRICS_PATH, JSON.stringify(store, null, 2), ‘utf8’);
}
async function sendTelemetry(payload: StopHookInput, entry: MetricsEntry) {
if (!TELEMETRY_URL) return;
await fetch(TELEMETRY_URL, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify({
conversationId: payload.conversation_id,
generationId: payload.generation_id,
model: payload.model,
modelId: payload.model_id,
modelParams: payload.model_params,
status: payload.status,
errorCount: entry.errorCount,
loopCount: payload.loop_count,
timestamp: entry.lastUpdatedIso
})
});
}
async function main() {
const payload = await parseHookInput
const metrics = await readMetrics();
const entry =
metrics[payload.conversation_id] ?? {
lastStatus: payload.status,
errorCount: 0,
lastUpdatedIso: ‘’
};
entry.lastStatus = payload.status;
entry.lastUpdatedIso = new Date().toISOString();
entry.errorCount = payload.status === ‘error’ ? entry.errorCount + 1 : 0;
metrics[payload.conversation_id] = entry;
await writeMetrics(metrics);
await sendTelemetry(payload, entry);
const response: StopHookOutput = {};
if (entry.errorCount >= 2 && payload.loop_count < 4) {
response.followup_message =
‘Automated retry triggered after two failures. Double-check credentials before running again.’;
}
process.stdout.write(JSON.stringify(response) + ‘\n’);
}
main().catch(error => {
console.error(‘[stop hook] failed’, error);
process.stdout.write(‘{}\n’);
});
將 `AGENT_TELEMETRY_URL` 設置爲接收運行摘要的內部端點。
### Python 清單保護鉤子
需要強大的解析庫時,Python 是理想選擇。此鉤子會在運行 `kubectl apply` 前使用 `pyyaml` 檢查 Kubernetes 清單;Bash 難以安全解析多文檔 YAML。
```json title="hooks.json"
{
"version": 1,
"hooks": {
"beforeShellExecution": [
{
"command": "python3 .cursor/hooks/kube_guard.py"
}
]
}
}
```python title=”.cursor/hooks/kube_guard.py”
!/usr/bin/env python3¶
import json
import shlex
import sys
from pathlib import Path
import yaml
SENSITIVE_NAMESPACES = {“prod”, “production”}
def main() -> None:
payload = json.load(sys.stdin)
command = payload.get(“command”, “”)
cwd = Path(payload.get(“cwd”) or “.”)
response = {“continue”: True, “permission”: “allow”}
try:
args = shlex.split(command)
except ValueError:
print(json.dumps(response))
return
if len(args) < 2 or args[0] != "kubectl" or args[1] != "apply" or "-f" not in args:
print(json.dumps(response))
return
f_index = args.index("-f")
if f_index + 1 >= len(args):
print(json.dumps(response))
return
manifest_arg = args[f_index + 1]
manifest_path = (cwd / manifest_arg).resolve()
if not manifest_path.exists():
print(json.dumps(response))
return
cli_namespace = None
for i, arg in enumerate(args):
if arg in ("-n", "--namespace") and i + 1 < len(args):
cli_namespace = args[i + 1]
elif arg.startswith("--namespace="):
cli_namespace = arg.split("=", 1)[1]
elif arg.startswith("-n="):
cli_namespace = arg.split("=", 1)[1]
try:
documents = list(yaml.safe_load_all(manifest_path.read_text()))
except (OSError, yaml.YAMLError) as exc:
sys.stderr.write(f"Failed to read/parse {manifest_path}: {exc}\n")
print(json.dumps(response))
return
if cli_namespace in SENSITIVE_NAMESPACES or any(
(doc or {}).get("metadata", {}).get("namespace") in SENSITIVE_NAMESPACES
for doc in documents
):
response.update(
{
"permission": "ask",
"user_message": "kubectl apply to prod requires manual approval.",
"agent_message": f"{manifest_path.name} includes protected namespaces; confirm with your team before continuing.",
}
)
print(json.dumps(response))
if name == “main”:
main()
在運行鉤子腳本的環境中安裝 PyYAML (例如 `pip install pyyaml`) ,確保可成功導入解析器。
## 合作伙伴集成
我們與已爲 Cursor 構建鉤子支持的生態合作伙伴合作。這些集成涵蓋安全掃描、治理、機密信息管理等。
### MCP 治理與可見性
| 合作伙伴 | 描述 |
| --------------------------------------------------------------------------------------- | --------------------------------------------- |
| [MintMCP](https://www.mintmcp.com/blog/mcp-governance-cursor-hooks) | 建立完整的 MCP 服務器清單,監控工具使用模式,並在響應到達 AI 模型前掃描敏感數據。 |
| [Oasis Security](https://www.oasis.security/blog/cursor-oasis-governing-agentic-access) | 對 AI 智能體操作實施最小權限策略,並在企業系統中保留完整的審計追蹤記錄。 |
| [Runlayer](https://www.runlayer.com/blog/cursor-hooks) | 封裝 MCP 工具,並集成其 MCP 代理,以集中管控和監測智能體與工具之間的交互。 |
### 代碼安全與最佳實踐
| 合作伙伴 | 描述 |
| ---------------------------------------------------------------- | ------------------------------------------ |
| [Corridor](https://corridor.dev/blog/corridor-cursor-hooks/) | 在編寫代碼的同時,針對代碼實現和安全設計決策獲得即時反饋。 |
| [Semgrep](https://semgrep.dev/blog/2025/cursor-hooks-mcp-server) | 自動掃描 AI 生成的代碼中的漏洞,並提供即時反饋以重新生成代碼,直至解決安全問題。 |
### 依賴項安全
| 合作伙伴 | 描述 |
| ------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| [Endor Labs](https://www.endorlabs.com/learn/bringing-malware-detection-into-ai-coding-workflows-with-cursor-hooks) | 攔截軟件包安裝並掃描惡意依賴項,在供應鏈攻擊進入您的代碼庫前加以阻止。 |
### 智能體安全與防護
| 合作伙伴 | 描述 |
| ---------------------------------------------------------------- | -------------------------------------------------- |
| [Snyk](https://snyk.io/blog/evo-agent-guard-cursor-integration/) | 藉助 Evo Agent Guard 即時評審智能體操作,檢測並防範提示詞注入、危險工具調用等問題。 |
### 機密信息管理
| 合作伙伴 | 描述 |
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| [1Password](https://marketplace.1password.com/integration/cursor-hooks) | 在執行 shell 命令前,驗證來自 1Password Environments 的環境文件是否已正確掛載,以便在不將憑據寫入磁盤的情況下按需訪問機密信息。 |
有關鉤子合作伙伴的更多信息,請參閱博客文章 [《面向安全和平臺團隊的 Hooks》](https://cursor.com/blog/hooks-partners)。
## 配置
在 `hooks.json` 文件中定義鉤子。配置可存在於多個層級。所有來源中匹配的鉤子都會運行;如果響應衝突,合併時優先採用優先級更高來源的響應:
```sh
~/.cursor/
├── hooks.json
└── hooks/
├── audit.sh
└── block-git.sh
- 企業版 (由 MDM 管理,適用於全系統) :
- macOS:
/Library/Application Support/Cursor/hooks.json - Linux/WSL:
/etc/cursor/hooks.json - Windows:
C:\\ProgramData\\Cursor\\hooks.json - 團隊 (通過雲端分發,僅限企業版) :
- 在網頁儀表盤中配置,並自動同步給所有團隊成員
- 項目 (項目專用) :
<project-root>/.cursor/hooks.json- 項目 hooks 會在任何受信任的工作區中運行,並隨項目一同提交到版本控制
- 用戶 (用戶專用) :
~/.cursor/hooks.json
優先級順序 (從高到低) :企業版 → 團隊 → 項目 → 用戶
hooks 對象將 hook 名稱映射到 hook 定義數組。每個定義目前支持 command 屬性,其值可以是 shell 字符串、絕對路徑或相對路徑。工作目錄取決於 hook 的來源:
- 項目 hooks (代碼倉庫中的
.cursor/hooks.json) :從項目根目錄運行 - 用戶 hooks (
~/.cursor/hooks.json) :從~/.cursor/運行 - 企業版 hooks (全系統配置) :從企業版配置目錄運行
- 團隊 hooks (通過雲端分發) :從受管 hooks 目錄運行
對於項目 hooks,請使用 .cursor/hooks/script.sh 這類路徑 (相對於項目根目錄) ,而不要使用 ./hooks/script.sh (後者會查找 <project>/hooks/script.sh) 。
配置文件¶
此示例展示用戶級鉤子文件 (~/.cursor/hooks.json) 。對於項目級鉤子,請將 ./hooks/script.sh 之類的路徑改爲 .cursor/hooks/script.sh:
{
"version": 1,
"hooks": {
"sessionStart": [{ "command": "./session-init.sh" }],
"sessionEnd": [{ "command": "./audit.sh" }],
"preToolUse": [
{
"command": "./hooks/validate-tool.sh",
"matcher": "Shell|Read|Write"
}
],
"postToolUse": [{ "command": "./hooks/audit-tool.sh" }],
"subagentStart": [{ "command": "./hooks/validate-subagent.sh" }],
"subagentStop": [{ "command": "./hooks/audit-subagent.sh" }],
"beforeShellExecution": [{ "command": "./script.sh" }],
"afterShellExecution": [{ "command": "./script.sh" }],
"afterMCPExecution": [{ "command": "./script.sh" }],
"afterFileEdit": [{ "command": "./format.sh" }],
"preCompact": [{ "command": "./audit.sh" }],
"stop": [{ "command": "./audit.sh", "loop_limit": 10 }],
"beforeTabFileRead": [{ "command": "./redact-secrets-tab.sh" }],
"afterTabFileEdit": [{ "command": "./format-tab.sh" }],
"workspaceOpen": [{ "command": "./register-workspace-plugins.sh" }]
}
}
智能體鉤子 (sessionStart、sessionEnd、preToolUse、postToolUse、postToolUseFailure、subagentStart、subagentStop、beforeShellExecution、afterShellExecution、beforeMCPExecution、afterMCPExecution、beforeReadFile、afterFileEdit、beforeSubmitPrompt、preCompact、stop、afterAgentResponse、afterAgentThought) 適用於 Cmd+K 和 Agent Chat 操作。Tab 鉤子 (beforeTabFileRead、afterTabFileEdit) 專用於內聯 Tab 補全。應用生命週期鉤子 (workspaceOpen) 會在工作區打開時以及工作區文件夾發生更改時觸發,與任何智能體會話無關。
全局配置選項¶
| 選項 | 類型 | 默認值 | 描述 |
|---|---|---|---|
version |
number | 1 |
配置架構版本 |
單個腳本的配置選項¶
| 選項 | 類型 | 默認值 | 描述 | |
|---|---|---|---|---|
command |
string | 必填 | 腳本路徑或命令 | |
type |
"command" |
"prompt" |
"command" |
鉤子的執行類型 |
timeout |
number | 平臺默認值 | 執行超時時間 (秒) | |
loop_limit |
number | null | 5 |
stop/subagentStop 鉤子中單個腳本的循環次數上限。null 表示不設上限。Cursor 鉤子的默認值爲 5,Claude Code 鉤子的默認值爲 null。 |
failClosed |
boolean | false |
當爲 true 時,鉤子失敗 (崩潰、超時、無效 JSON) 會阻止該操作,而非允許其繼續執行。適用於安全性要求較高的鉤子。 |
|
matcher |
object | - | 鉤子運行條件的篩選標準 |
匹配器配置¶
匹配器可用於篩選鉤子的運行時機。匹配器適用於哪個字段取決於鉤子類型:
{
"hooks": {
"preToolUse": [
{
"command": "./validate-shell.sh",
"matcher": "Shell"
}
],
"subagentStart": [
{
"command": "./validate-explore.sh",
"matcher": "explore|shell"
}
],
"beforeShellExecution": [
{
"command": "./approve-network.sh",
"matcher": "curl|wget|nc "
}
]
}
}
- subagentStart:匹配器會匹配子智能體類型 (例如
explore、shell、generalPurpose) 。可用於僅在啓動特定類型的子智能體時運行鉤子。上述示例僅對 explore 或 shell 子智能體運行validate-explore.sh。 - beforeShellExecution:匹配器會匹配shell 命令字符串。可用於僅在命令匹配某個模式時運行鉤子 (例如網絡調用、刪除文件) 。上述示例僅當命令包含
curl、wget或nc時運行approve-network.sh。
各鉤子可用的匹配器:
- preToolUse / postToolUse / postToolUseFailure:按工具類型篩選。可選值包括
Shell、Read、Write、Grep、Delete、Task,以及採用MCP:<tool_name>格式的 MCP 工具。 - subagentStart / subagentStop:按子智能體類型篩選 (
generalPurpose、explore、shell等) 。 - beforeShellExecution / afterShellExecution:按 shell 命令文本篩選;匹配器會與完整的命令字符串匹配。
- beforeReadFile:按工具類型篩選 (
TabRead、Read等) 。 - afterFileEdit:按工具類型篩選 (
TabWrite、Write等) 。 - beforeSubmitPrompt:匹配值
UserPromptSubmit。 - stop:匹配值
Stop。 - afterAgentResponse:匹配值
AgentResponse。 - afterAgentThought:匹配值
AgentThought。
團隊分發¶
可通過項目 hooks (使用版本控制) 、MDM 工具或 Cursor 雲分發系統向團隊成員分發 hooks。
項目 hooks (版本控制)¶
項目 hooks 是與團隊共享 hooks 最簡單的方式。將 hooks.json 文件放在 <project-root>/.cursor/hooks.json 路徑下,並提交到代碼倉庫。團隊成員在受信任的工作區中打開項目時,Cursor 會自動加載並運行項目 hooks。
雲端代理在雲端處理您的代碼倉庫時,也會加載這些項目 hooks。
項目 hooks:
- 與代碼一同存儲在版本控制中
- 會在受信任的工作區中爲所有團隊成員自動加載
- 可以針對特定項目設置 (例如,爲特定代碼庫強制執行格式規範)
- 只能在受信任的工作區中運行 (出於安全考慮)
通過 MDM 分發¶
使用移動設備管理 (MDM) 工具在組織內分發鉤子。在每臺設備的目標目錄中放置 hooks.json 文件和鉤子腳本。
用戶主目錄 (按用戶分發) :
~/.cursor/hooks.json~/.cursor/hooks/(存放鉤子腳本)
全局目錄 (系統級分發) :
- macOS:
/Library/Application Support/Cursor/hooks.json - Linux/WSL:
/etc/cursor/hooks.json - Windows:
C:\\ProgramData\\Cursor\\hooks.json
注意:基於 MDM 的分發完全由您的組織負責管理。Cursor 不會通過您的 MDM 解決方案部署或管理文件。請確保內部 IT 或安全團隊按照組織策略處理配置、部署和更新。
雲端分發 (僅限企業版)¶
企業版團隊可使用 Cursor 原生的雲端分發功能,自動將鉤子同步給所有團隊成員。在網頁儀表盤中配置鉤子後,團隊成員登錄時,Cursor 會自動將已配置的鉤子部署到所有客戶端設備。
雲端分發提供:
- 每三十分鐘自動同步給所有團隊成員
- 可按操作系統爲特定平臺配置鉤子
- 通過儀表盤集中管理
企業管理員無需訪問個人設備,即可通過儀表盤創建、編輯和管理團隊鉤子。
聯繫銷售,獲取企業版雲端鉤子分發功能。
參考¶
通用架構¶
輸入 (所有鉤子)¶
除鉤子特有的字段外,所有鉤子還會接收一組基礎字段:
{
"conversation_id": "string",
"generation_id": "string",
"model": "string",
"model_id": "string",
"model_params": [{ "id": "string", "value": "string" }],
"hook_event_name": "string",
"cursor_version": "string",
"workspace_roots": ["<path>"],
"user_email": "string | null",
"transcript_path": "string | null"
}
| 字段 | 類型 | 描述 | |
|---|---|---|---|
conversation_id |
string | 對話在多個輪次中保持不變的穩定 ID | |
generation_id |
string | 隨每條用戶消息變化的當前 generation | |
model |
string | 爲觸發該鉤子的 composer 配置的舊版模型 slug | |
model_id |
string (optional) | 所選模型的結構化 ID (如有) | |
model_params |
array (optional) | 所選模型的參數,如思考、上下文或 effort。每項均包含 id 和 value。 |
|
hook_event_name |
string | 正在運行的鉤子名稱 | |
cursor_version |
string | Cursor 應用版本 (例如 “1.7.2”) | |
workspace_roots |
string[] | 工作區根文件夾列表 (通常只有一個,但多根工作區可以有多個) | |
user_email |
string | null | 已認證用戶的電子郵件地址 (如有) |
transcript_path |
string | null | 主對話會話記錄文件的路徑 (禁用會話記錄時爲 null) |
應用生命週期鉤子 (workspaceOpen) 在任何智能體會話之外觸發,因此請求中不包含 conversation_id、generation_id、model、session_id 和 transcript_path。但仍會收到 hook_event_name、cursor_version、workspace_roots 和 user_email。
鉤子事件¶
preToolUse¶
在執行任何工具前調用。這是適用於所有工具類型 (Shell、Read、Write、MCP、Task 等) 的通用鉤子。可使用匹配器按特定工具篩選。
// 輸入
{
"tool_name": "Shell",
"tool_input": { "command": "npm install", "working_directory": "/project" },
"tool_use_id": "abc123",
"cwd": "/project",
"model": "claude-opus-4-7-thinking-max",
"model_id": "claude-opus-4-7",
"model_params": [
{ "id": "thinking", "value": "true" },
{ "id": "context", "value": "1m" },
{ "id": "effort", "value": "max" }
],
"agent_message": "Installing dependencies..."
}
// 輸出
{
"permission": "allow" | "deny",
"user_message": "<message shown in client when denied>",
"agent_message": "<message sent to agent when denied>",
"updated_input": { "command": "npm ci" }
}
| 輸出字段 | 類型 | 描述 |
|---|---|---|
permission |
string | "allow" 表示允許繼續,"deny" 表示阻止。架構接受 "ask",但目前不會對 preToolUse 強制執行。 |
user_message |
string (可選) | 操作被拒絕時向用戶顯示的消息 |
agent_message |
string (可選) | 操作被拒絕時反饋給智能體的消息 |
updated_input |
object (可選) | 要改用的修改後的工具輸入 |
postToolUse¶
在工具成功執行後觸發。可用於審計、使用分析和注入上下文。
// 輸入
{
"tool_name": "Shell",
"tool_input": { "command": "npm test" },
"tool_output": "{\"exitCode\":0,\"stdout\":\"All tests passed\"}",
"tool_use_id": "abc123",
"cwd": "/project",
"duration": 5432,
"model": "claude-opus-4-7-thinking-max",
"model_id": "claude-opus-4-7",
"model_params": [
{ "id": "thinking", "value": "true" },
{ "id": "context", "value": "1m" },
{ "id": "effort", "value": "max" }
]
}
// 輸出
{
"updated_mcp_tool_output": { "modified": "output" },
"additional_context": "Test coverage report attached."
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
duration |
number | 執行耗時 (毫秒) |
tool_output |
string | 工具返回的 JSON 字符串化結果負載 (而非原始終端文本) |
| 輸出字段 | 類型 | 描述 |
|---|---|---|
updated_mcp_tool_output |
object (optional) | 僅適用於 MCP 工具:替換模型所見的工具輸出 |
additional_context |
string (optional) | 工具結果返回後注入對話的額外上下文 |
postToolUseFailure¶
在工具執行失敗、超時或被拒絕時調用。適用於錯誤追蹤和恢復邏輯。
// 輸入
{
"tool_name": "Shell",
"tool_input": { "command": "npm test" },
"tool_use_id": "abc123",
"cwd": "/project",
"error_message": "Command timed out after 30s",
"failure_type": "timeout" | "error" | "permission_denied",
"duration": 5000,
"is_interrupt": false
}
// 輸出
{
// 目前不支持任何輸出字段
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
error_message |
string | 失敗原因 |
failure_type |
string | 失敗類型:"error"、"timeout" 或 "permission_denied" |
duration |
number | 發生失敗前的時間 (毫秒) |
is_interrupt |
boolean | 此失敗是否由用戶中斷或取消導致 |
subagentStart¶
在啓動子智能體 (Task 工具) 之前調用。可允許或拒絕創建子智能體。
// 輸入
{
"subagent_id": "abc-123",
"subagent_type": "generalPurpose",
"task": "Explore the authentication flow",
"parent_conversation_id": "conv-456",
"tool_call_id": "tc-789",
"subagent_model": "claude-sonnet-4-20250514",
"is_parallel_worker": false,
"git_branch": "feature/auth"
}
// 輸出
{
"permission": "allow" | "deny",
"user_message": "<message shown when denied>"
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
subagent_id |
string | 此子智能體實例的唯一標識符 |
subagent_type |
string | 子智能體類型:generalPurpose、explore、shell 等 |
task |
string | 分配給子智能體的任務描述 |
parent_conversation_id |
string | 父智能體會話的對話 ID |
tool_call_id |
string | 觸發該子智能體的工具調用 ID |
subagent_model |
string | 子智能體將使用的模型 |
is_parallel_worker |
boolean | 此子智能體是否作爲並行工作器運行 |
git_branch |
string (optional) | 子智能體將操作的 Git 分支 (如適用) |
| 輸出字段 | 類型 | 描述 |
|---|---|---|
permission |
string | "allow" 表示允許繼續,"deny" 表示阻止。subagentStart 不支持 "ask",並將其視爲 "deny"。 |
user_message |
string (optional) | 子智能體被拒絕時向用戶顯示的消息 |
subagentStop¶
子智能體完成、出錯或被中止時調用。可觸發後續操作。
// 輸入
{
"subagent_type": "generalPurpose",
"status": "completed" | "error" | "aborted",
"task": "Explore the authentication flow",
"description": "Exploring auth flow",
"summary": "<subagent output summary>",
"duration_ms": 45000,
"message_count": 12,
"tool_call_count": 8,
"loop_count": 0,
"modified_files": ["src/auth.ts"],
"agent_transcript_path": "/path/to/subagent/transcript.txt"
}
// 輸出
{
"followup_message": "<auto-continue with this message>"
}
| 輸入字段 | 類型 | 描述 | |
|---|---|---|---|
subagent_type |
string | 子智能體類型:generalPurpose、explore、shell 等 |
|
status |
string | "completed"、"error" 或 "aborted" |
|
task |
string | 提供給子智能體的任務描述 | |
description |
string | 子智能體用途的簡要說明 | |
summary |
string | 子智能體的輸出摘要 | |
duration_ms |
number | 以毫秒爲單位的執行時間 | |
message_count |
number | 子智能體會話期間交換的消息數量 | |
tool_call_count |
number | 子智能體發起的工具調用次數 | |
loop_count |
number | 此子智能體已觸發的 subagentStop 後續操作次數 (從 0 開始) |
|
modified_files |
string[] | 子智能體修改的文件 | |
agent_transcript_path |
string | null | 子智能體自身會話記錄文件的路徑 (與父對話分開) |
| 輸出字段 | 類型 | 描述 |
|---|---|---|
followup_message |
string (可選) | 使用此消息自動繼續。僅當 status 爲 "completed" 時使用。 |
followup_message 字段支持循環式流程:子智能體完成後會觸發下一次迭代。後續操作與 stop 鉤子使用相同的可配置循環限制 (默認值爲 5,可通過 loop_limit 配置) 。
beforeShellExecution / beforeMCPExecution¶
在執行任何 shell 命令或 MCP 工具前調用。返回權限判定。
默認情況下,鉤子執行失敗 (崩潰、超時、JSON 無效) 時,操作仍會繼續執行 (故障開放) 。可在鉤子定義中設置 failClosed: true,使操作在失敗時被阻止。對於安全關鍵型 beforeMCPExecution 鉤子,建議這樣設置。
// beforeShellExecution 輸入
{
"command": "<full terminal command>",
"cwd": "<current working directory>",
"sandbox": false
}
// beforeMCPExecution 輸入
{
"tool_name": "<tool name>",
"tool_input": "<json params>",
"mcp_server_name": "<server name from mcp.json>"
}
// 另外必須提供以下之一 (HTTP/SSE 服務器) :
{ "url": "<server url>", "mcp_server_url": "<server url>" }
// 或 (stdio 服務器) :
{ "command": "<launch command and args>" }
// 輸出
{
"permission": "allow" | "deny" | "ask",
"user_message": "<message shown in client>",
"agent_message": "<message sent to agent>"
}
| 字段 | 類型 | 描述 |
|---|---|---|
tool_name |
string | 即將運行的 MCP 工具名稱 |
tool_input |
string | 將傳遞給工具的 JSON 參數 string |
mcp_server_name |
string | 服務器在其 mcp.json 中的鍵 (例如 linear) 。使用此項識別特定服務器。 |
mcp_server_url |
string | 服務器 URL,僅適用於 HTTP/SSE 服務器 |
url |
string | 與 mcp_server_url 相同;僅適用於 HTTP/SSE 服務器 |
command |
string | 以空格連接的 stdio 啓動命令和參數;僅適用於 stdio 服務器 |
根據 mcp_server_name (以及 tool_name) 進行匹配,以確定調用是否指向你的服務器。command 是服務器 config 中的啓動 string,在不同安裝中可能有所不同:相對路徑、${CURSOR_PLUGIN_ROOT} 展開,或 HTTP transport (完全沒有 command) 。對於未識別內容一律允許通過的鉤子,應將缺失或異常的 mcp_server_name 視爲拒絕。
afterShellExecution¶
在 shell 命令執行後觸發;可用於審計或從命令輸出中收集指標。
// 輸入
{
"command": "<full terminal command>",
"output": "<full terminal output>",
"duration": 1234,
"sandbox": false
}
| 字段 | 類型 | 描述 |
|---|---|---|
command |
string | 已執行的完整終端命令 |
output |
string | 從終端捕獲的完整輸出 |
duration |
number | 執行 shell 命令耗時 (毫秒,不包括等待批准的時間) |
sandbox |
boolean | 命令是否在沙盒環境中運行 |
afterMCPExecution¶
在 MCP 工具執行後觸發;包含該工具的輸入參數和完整的 JSON 結果。
// 輸入
{
"tool_name": "<tool name>",
"tool_input": "<json params>",
"mcp_server_name": "<server name from mcp.json>",
"result_json": "<tool result json>",
"duration": 1234
}
| 字段 | 類型 | 描述 |
|---|---|---|
tool_name |
string | 已執行的 MCP 工具的名稱 |
tool_input |
string | 傳遞給工具的 JSON 參數 string |
mcp_server_name |
string | 服務器在其 mcp.json 中的鍵 |
mcp_server_url |
string | 服務器 URL,僅適用於 HTTP/SSE 服務器 |
result_json |
string | 工具響應的 JSON string |
duration |
number | 執行 MCP 工具所用時長 (單位爲毫秒,不包括等待批准的時間) |
afterFileEdit¶
智能體編輯文件後觸發;可用於格式化或統計智能體編寫的代碼。
// 輸入
{
"file_path": "<absolute path>",
"edits": [{ "old_string": "<search>", "new_string": "<replace>" }]
}
beforeReadFile¶
在智能體讀取文件前調用。可用於訪問控制,防止將敏感文件發送給模型。
默認情況下,beforeReadFile 鉤子失敗 (崩潰、超時、JSON 無效) 時會記錄日誌,並仍允許讀取。請在鉤子定義中設置 failClosed: true,以便在失敗時阻止讀取。
// 輸入
{
"file_path": "<absolute path>",
"content": "<file contents>",
"attachments": [
{
"type": "file" | "rule",
"file_path": "<absolute path>"
}
]
}
// 輸出
{
"permission": "allow" | "deny",
"user_message": "<message shown when denied>"
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
file_path |
string | 正在讀取的文件的絕對路徑 |
content |
string | 文件的完整內容 |
attachments |
array | 與提示詞關聯的上下文附件。每個條目都包含 type ("file" 或 "rule") 和 file_path。 |
| 輸出字段 | 類型 | 描述 |
|---|---|---|
permission |
string | "allow" 表示繼續,"deny" 表示阻止 |
user_message |
string (optional) | 拒絕時向用戶顯示的消息 |
beforeTabFileRead¶
在 Tab (內聯補全) 讀取文件前調用。可在 Tab 訪問文件內容前啓用脫敏或訪問控制。
與 beforeReadFile 的主要區別:
- 僅由 Tab 觸發,不會由智能體觸發
- 不包含
attachments字段 (Tab 不使用提示詞附件) - 可用於對自主運行的 Tab 操作應用不同策略
// 輸入
{
"file_path": "<absolute path>",
"content": "<file contents>"
}
// 輸出
{
"permission": "allow" | "deny"
}
afterTabFileEdit¶
Tab (內聯補全) 編輯文件後調用。適用於格式化工具或審計 Tab 寫入的代碼。
與 afterFileEdit 的主要區別:
- 僅由 Tab 觸發,不由智能體觸發
- 包含詳細的編輯信息:
range、old_line和new_line,可精確跟蹤編輯內容 - 適用於對 Tab 編輯進行細粒度格式化或分析
// 輸入
{
"file_path": "<absolute path>",
"edits": [
{
"old_string": "<search>",
"new_string": "<replace>",
"range": {
"start_line_number": 10,
"start_column": 5,
"end_line_number": 10,
"end_column": 20
},
"old_line": "<line before edit>",
"new_line": "<line after edit>"
}
]
}
// 輸出
{
// 目前不支持輸出字段
}
beforeSubmitPrompt¶
用戶點擊發送後、發起後端請求前立即調用。可阻止提交。
// 輸入
{
"prompt": "<user prompt text>",
"attachments": [
{
"type": "file" | "rule",
"file_path": "<absolute path>"
}
]
}
// 輸出
{
"continue": true | false,
"user_message": "<message shown to user when blocked>"
}
| 輸出字段 | 類型 | 描述 |
|---|---|---|
continue |
boolean | 是否允許繼續提交提示詞 |
user_message |
string (可選) | 提示詞被阻止時顯示給用戶的消息 |
afterAgentResponse¶
智能體完成助手消息後調用。
// 輸入
{
"text": "<assistant final text>"
}
afterAgentThought¶
智能體完成一個思考塊後調用。可用於觀察智能體的推理過程。
// 輸入
{
"text": "<fully aggregated thinking text>",
"duration_ms": 5000
}
// 輸出
{
// 目前不支持輸出字段
}
| 字段 | 類型 | 描述 |
|---|---|---|
text |
string | 已完成塊的完整聚合思考文本 |
duration_ms |
number (可選) | 思考塊的持續時間 (毫秒) |
stop¶
智能體循環結束時觸發。可選擇自動提交後續用戶消息,以繼續迭代。
// 輸入
{
"status": "completed" | "aborted" | "error",
"loop_count": 0
}
// 輸出
{
"followup_message": "<message text>"
}
- 可選的
followup_message爲 string。提供且非空時,Cursor 會自動將其提交爲下一條用戶消息。這支持循環式流程 (例如,迭代直至達成目標) 。 loop_count字段表示 stop 鉤子已爲此對話自動觸發後續消息的次數 (初始值爲 0) 。默認情況下,每個腳本最多可自動發送 5 條後續消息,可通過loop_limit選項配置。將loop_limit設爲null可取消此上限。同樣的限制也適用於subagentStop後續消息。
sessionStart¶
創建新的 composer 對話時觸發。此鉤子以即發即棄方式運行;智能體循環不會等待或強制執行阻塞式響應。可用於設置會話專用環境變量或注入額外上下文。
// 輸入
{
"session_id": "<unique session identifier>",
"is_background_agent": true | false,
"composer_mode": "agent" | "ask" | "edit"
}
// 輸出
{
"env": { "<key>": "<value>" },
"additional_context": "<context to add to conversation>"
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
session_id |
string | 此會話的唯一標識符 (與 conversation_id 相同) |
is_background_agent |
boolean | 此會話是後臺智能體會話還是交互式會話 |
composer_mode |
string (可選) | composer 啓動時的模式 (例如 “agent”、”ask”、”edit”) |
| 輸出字段 | 類型 | 描述 |
|---|---|---|
env |
object (可選) | 爲此會話設置的環境變量,可供後續所有鉤子執行使用 |
additional_context |
string (可選) | 要添加到對話初始系統上下文中的額外上下文 |
此架構也接受 continue 和 user_message 字段,但當前調用方並不強制要求提供這些字段。即使 continue 爲 false,也不會阻止創建會話。
sessionEnd¶
composer 對話結束時調用。這是一個即發即棄的鉤子,適用於日誌記錄、使用分析或清理任務。響應會被記錄,但不會使用。
// 輸入
{
"session_id": "<唯一會話標識符>",
"reason": "completed" | "aborted" | "error" | "window_close" | "user_close",
"duration_ms": 45000,
"is_background_agent": true | false,
"final_status": "<狀態字符串>",
"error_message": "<當 reason 爲 'error' 時的錯誤詳情>"
}
// 輸出
{
// 無輸出字段——觸發後不等待結果
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
session_id |
string | 即將結束的會話的唯一標識符 |
reason |
string | 會話結束原因:”completed”、”aborted”、”error”、”window_close” 或 “user_close” |
duration_ms |
number | 會話總時長 (毫秒) |
is_background_agent |
boolean | 是否爲後臺智能體會話 |
final_status |
string | 會話的最終狀態 |
error_message |
string (optional) | 當原因是 “error” 時的錯誤消息 |
preCompact¶
在上下文窗口壓縮/摘要之前調用。這是一個僅用於觀察的鉤子,無法阻止或修改壓縮行爲。可用於記錄壓縮發生的時間或通知用戶。
// 輸入
{
"trigger": "auto" | "manual",
"context_usage_percent": 85,
"context_tokens": 120000,
"context_window_size": 128000,
"message_count": 45,
"messages_to_compact": 30,
"is_first_compaction": true | false
}
// 輸出
{
"user_message": "<message to show when compaction occurs>"
}
| 輸入字段 | 類型 | 描述 |
|---|---|---|
trigger |
string | 觸發壓縮的方式:”auto” 或 “manual” |
context_usage_percent |
number | 當前上下文窗口用量百分比 (0-100) |
context_tokens |
number | 當前上下文窗口的 token 數 |
context_window_size |
number | 上下文窗口的最大 token 數 |
message_count |
number | 對話中的消息數量 |
messages_to_compact |
number | 將被摘要的消息數量 |
is_first_compaction |
boolean | 是否爲該對話的首次壓縮 |
| 輸出字段 | 類型 | 描述 |
|---|---|---|
user_message |
string (可選) | 壓縮時顯示給用戶的消息 |
workspaceOpen¶
Cursor 打開工作區時觸發一次,此後每次工作區文件夾變更時都會再次觸發。窗口中沒有任何工作區文件夾時不會觸發。可在 Cursor 桌面應用和命令行界面中運行。
// 輸入
{
"hook_event_name": "workspaceOpen",
"cursor_version": "string",
"workspace_roots": ["<absolute path>"],
"user_email": "string | null"
}
// 輸出
{
"pluginPaths": ["<absolute path>", "..."]
}
| 輸出字段 | 類型 | 描述 |
|---|---|---|
pluginPaths |
string[] (可選) | 爲當前工作區加載插件的目錄絕對路徑。 |
環境變量¶
鉤子腳本執行時會接收環境變量:
| 變量 | 描述 | 始終可用 |
|---|---|---|
CURSOR_PROJECT_DIR |
工作區根目錄 | 是 |
CURSOR_VERSION |
Cursor 版本字符串 | 是 |
CURSOR_USER_EMAIL |
已認證用戶的電子郵件 | 已登錄時 |
CURSOR_TRANSCRIPT_PATH |
對話會話記錄文件的路徑 | 已啓用會話記錄時 |
CURSOR_CODE_REMOTE |
在遠程工作區中運行時設爲字符串 "true" |
僅限遠程工作區 |
CLAUDE_PROJECT_DIR |
項目目錄的別名 (兼容 Claude) | 是 |
sessionStart 鉤子設置的會話級環境變量會傳遞給該會話中後續執行的所有鉤子。
疑難排查¶
如何確認鉤子是否已啓用
在自定義中,可通過鉤子選項卡和鉤子輸出通道調試已配置和已執行的鉤子,並查看錯誤。
如果鉤子未正常工作
- Cursor 會監視
hooks.json文件,並在保存時重新加載。如果鉤子仍無法加載,請重新啓動 Cursor。 - 檢查鉤子源文件的相對路徑是否正確:
- 對於項目鉤子,路徑相對於項目根目錄 (例如
.cursor/hooks/script.sh) - 對於用戶鉤子,路徑相對於
~/.cursor/(例如./hooks/script.sh或hooks/script.sh)
退出碼阻止操作
命令鉤子返回退出碼 2 會阻止該操作 (等同於返回 permission: "deny") 。爲保持兼容性,此行爲與 Claude Code 一致。
企業版鉤子和分發¶
企業版提供雲端分發和團隊級鉤子管理。