Cursor CLI 集成
Cursor 有两条路:hooks 拿到常驻注入和强度切换,规则文件只有一个固定强度。两条路同时存在会互相压制——这一章先把安装走通,下一章讲冲突和排查。
1先选路:hooks 还是规则文件
Cursor 的集成比别家多一层选择,因为 Cursor 同时支持「规则文件」和「hooks」两种注入机制。它们不是叠加关系,而是互斥的替代方案,这一点必须先讲清楚,否则后面会莫名其妙地失效。
- 常驻规则 + 强度切换(lite / full / ultra / off)
- 每个新会话自动激活,并在回复里显示当前模式
- 状态存在
~/.cursor/.ponytail-active - 需要 node 在 PATH,需要保留 clone 的仓库目录
- 只有常驻规则,没有强度切换、没有命令
- 拷一个
.mdc文件进项目,可以提交进 Git 给团队共用 - 不依赖 node,不依赖仓库放在哪
- 适合「只想让团队都少写点代码」的场景
.cursor/rules/ponytail.mdc,hooks 就会主动退让——第 5 章有一节专门讲这个陷阱。2路线 A:装 hooks
git clone https://github.com/DietrichGebert/ponytail
node ponytail/scripts/cursor-hooks.js install # 写进 ~/.cursor/hooks.json,对所有项目生效
node ponytail/scripts/cursor-hooks.js install --project # 写进 <当前目录>/.cursor/hooks.json,只对本项目生效
用户级还是项目级?判断标准很简单:你希望这个能力跟着机器走,还是跟着仓库走。跟着机器走就用不带参数的版本;只在某个仓库试水就加 --project。
安装脚本做的事比看上去多,有五条值得知道:
| 它会做的 | 为什么对你重要 |
|---|---|
读现有 hooks.json,保留所有不属于 ponytail 的钩子 | 不会清掉你已有的 hooks(ponytail 的条目靠「command 里跑的是 hooks/ponytail-*.js」来识别) |
| 重复安装时替换自己的条目 | 幂等。装两次不会变成四条钩子 |
把 PONYTAIL_DIR 占位符换成仓库的绝对路径,且统一用正斜杠 | 同一条命令在 cmd、PowerShell、bash 下都能跑 |
| 仓库路径含 shell 元字符时拒绝安装 | 避免写出一条会被魔改的命令。这种情况要手动拷模板 |
hooks.json 不是合法 JSON 时拒绝写入并说明 | 不会把你的文件改成半截状态 |
hooks.json 并在保存时重新加载,但已经在跑的对话不会补上启动注入。还有一条「部署纪律」:装完就别挪仓库目录。因为写进 hooks 的是绝对路径,移动后必须重新跑一次 install。
3它到底往 hooks.json 里写了什么
模板长这样(PONYTAIL_DIR 在安装时被替换成实际路径):
{
"version": 1,
"hooks": {
"sessionStart": [
{ "command": "node "PONYTAIL_DIR/hooks/ponytail-activate.js"", "timeout": 5 }
],
"beforeSubmitPrompt": [
{ "command": "node "PONYTAIL_DIR/hooks/ponytail-mode-tracker.js"", "timeout": 5 }
]
}
}
两个钩子各管一件事,理解这个分工,第 5 章的限制就都能自己推出来:
| 钩子 | 时机 | 它干什么 |
|---|---|---|
ponytail-activate.js | sessionStart | 把默认强度写进标志文件,并注入 PONYTAIL MODE ACTIVE — level: <level> 加上按该强度裁剪过的规则集 |
ponytail-mode-tracker.js | beforeSubmitPrompt | 识别你发的是不是 /ponytail … 这类指令;是就改标志文件,并给这一轮注入 PONYTAIL MODE CHANGED — level: <level> 加新规则集 |
/ponytail 这个斜杠命令可以加载技能正文——所以强度切换这件事必须由 hook 扛。「注入」这件事是分两处发生的,这是理解后面所有限制的钥匙。4验证:别猜,让模型背出来
官方给了一条很聪明的验收方法,核心思想是:钩子执行了不等于内容送达了。所以要反过来问模型——让它把收到的上下文念出来。
- 确认工作区里没有
.cursor/rules/ponytail.mdc - 装好 hooks,开一个新的 Agent 对话
- 问:
Quote the first line of any ponytail context you were given. - 期望回答:
PONYTAIL MODE ACTIVE — level: full(或你设的默认强度) - 发
/ponytail lite,再问同一句。期望:PONYTAIL MODE CHANGED — level: lite。ultra同理 - 发
/ponytail off,再问。期望:PONYTAIL MODE OFF
为什么这招有效?因为 PONYTAIL MODE CHANGED — level: lite 这串字符串只存在于 hook 的输出里。模型能念出来,就证明那条通路真的打通了。如果它念的是技能正文开头的 # Ponytail,说明你同时把技能装进了 ~/.cursor/skills,Cursor 把 /ponytail lite 当成了手动挂载技能并内联了完整正文——这不影响 hook 工作,但会让你误判验证结果。
gpt-5.6-sol-high 上实测过的,第 2、3、4 步均为 pass。第 5 步(子代理)没跑成,第 6 步(规则共存)当时还没跑——所以第 5 章那两条限制请当作「按契约推断」来读,而不是实测结论。5在 Cursor 里怎么切强度
因为 Cursor 没有对应斜杠命令,强度切换是当成普通消息发出去的纯文本。hook 会从你的提示里把字面量 /ponytail lite 抓出来。
| 你发的消息 | 结果 |
|---|---|
/ponytail lite · /ponytail full · /ponytail ultra | 切强度,这一轮注入新规则集(约 5,300 字符,在 10,000 字符内联上限之内) |
/ponytail off / stop ponytail / normal mode | 删掉标志文件,这一轮注入 PONYTAIL MODE OFF |
/ponytail(不带参数) | 只报告当前强度,不改任何东西 |
/ponytail default lite | 把默认强度持久化写进 config.json |
| 其它任何提示 | 无输出,什么都不发生 |
@ponytail 和 $ponytail 也能被解析,但在 Cursor 里 @ 会先弹出上下文选择器,就别用这个前缀了。用 /。关于 off 有个细节值得知道:标志文件删了,但启动时注入的那份规则集还留在对话的系统上下文里。真正让它停下来的,是 PONYTAIL MODE OFF 这条通知——跟 Claude Code 的做法一致,模型看到通知就不再套用规则。所以别指望「删掉文件 = 从上下文里抹掉」。
6路线 B:只放一条规则文件
不用 clone,不用 node。把仓库里的 .cursor/rules/ponytail.mdc 拷到你项目的 .cursor/rules/ 目录即可。文件头的 frontmatter 决定了它的生效方式:
---
description: Ponytail, lazy senior dev mode. Always pick the simplest solution that works.
globs:
alwaysApply: true
---
关键是最后一行 alwaysApply: true——它让这份规则贴在每一个提示前面,不需要你手动 @ 引用。规则正文就是第 1 章那套梯子,只是用更紧凑的措辞写的,并且没有 lite/full/ultra 的裁剪版本。
7一页速查:Cursor 两条路线对照
| 维度 | 路线 A:hooks | 路线 B:规则文件 |
|---|---|---|
| 安装动作 | node ponytail/scripts/cursor-hooks.js install | 拷 .cursor/rules/ponytail.mdc |
| 依赖 | node 在 PATH、仓库目录不能挪 | 无 |
| 强度切换 | 支持,发纯文本 /ponytail lite | 不支持 |
| 多命令(review/audit/debt/gain/help) | 不支持 | 不支持 |
| 子代理能否收到规则 | 不能 | 能跟随工作区规则 |
| 卸载 | node ponytail/scripts/cursor-hooks.js uninstall | 删掉那个文件 |
| 状态文件 | ~/.cursor/.ponytail-active | 无 |