# Cursor Hooks 说明 ## 文件 ```text hooks/ ├── run-hook.ps1 # Windows dispatcher;读取 local-env.json 并校验 JSON 输出 ├── session-init.ps1 # sessionStart(PowerShell) ├── session-init.sh # sessionStart(Bash) ├── check-changelog.ps1 # stop / changelog guard(PowerShell) ├── check-changelog.sh # stop / changelog guard(Bash) ├── changelog-scan.json # cursor-init 按项目类型生成的活动扫描策略 ├── tests/ # PowerShell / Bash 共用回归测试 └── README.md ``` ## Windows 配置(当前模板) `.cursor/hooks.json` 统一通过 dispatcher 调用: - `sessionStart`:`powershell -ExecutionPolicy Bypass -File .cursor/hooks/run-hook.ps1 session-init`,超时 5 秒。 - `stop`:`powershell -ExecutionPolicy Bypass -File .cursor/hooks/run-hook.ps1 check-changelog`,超时 10 秒,`loop_limit` 为 1。 dispatcher 从 `.cursor/local-env.json` 读取 `shell`: - `powershell` / `pwsh`:运行同名 `.ps1`。 - `bash` / `zsh` / `sh`:选择同名 `.sh`,并通过 `bash` 执行。 stdin 以 UTF-8 原样转发。子脚本成功时,dispatcher 校验并规范化其 JSON 对象;脚本缺失、配置无效、启动失败、非零退出或输出无效时,只向 stderr 写诊断,并向 hook 返回非阻断的 `{}`。 ## macOS / Linux 切换 macOS/Linux 不需要 Windows dispatcher。将 `.cursor/hooks.json` 改为 Bash 直调: ```json { "version": 1, "hooks": { "sessionStart": [ { "command": "bash .cursor/hooks/session-init.sh", "timeout": 5 } ], "stop": [ { "command": "bash .cursor/hooks/check-changelog.sh", "timeout": 10, "loop_limit": 1 } ] } } ``` 同时把本机 `.cursor/local-env.json` 的 `shell` 设为 `bash`(或实际使用的 `zsh`)。Bash 脚本不依赖 `jq`;优先用 `python3`(Windows Git Bash 可回退 `python`)读取扫描配置并生成 JSON,解释器缺失或解析失败时 fail-open 返回 `{}`。 ## 行为 - `session-init` 清除上一会话的 `.cursor/changelog/.changelog-ack`,并刷新 gitignored 的 `.cursor/changelog/.session-start`。非 `agent` 模式通过 hook `env` 设置 `CURSOR_SKIP_CHANGELOG=1`。 - Cursor 的 `stop` 输入不包含可靠的工具编辑历史,因此 `check-changelog` 使用 Git 工作区状态与文件时间共同判断。只有 `changelog-scan.json` 命中的项目源码/配置同时存在未提交内容差异,且晚于本会话起点与当前 changelog 时,才返回 `followup_message`。 - `.session-start` 缺失、Git 不可用、状态读取失败或工作区无内容差异时均 fail-open 返回 `{}`。不得只因文件 mtime 较新就要求写开发日志。 - 扫描文件名、扩展名与排除目录由 common + 所选项目类型 manifest 合并生成;Hook 代码不得重新硬编码 Godot 或 Roblox 列表。 - 所有正常与失败路径都在 stdout 输出一个合法 JSON 对象;检查失败默认不阻断。