前言¶
用 AI 写代码时,常见的一幕是:Agent 改完一版,跑一下测试,挂了几条;你让它再修,又挂;来回几轮,对话还没结束,上下文已经很长,人也累了。很多时候失败原因并不复杂——断言对不上、类型报错、lint 违规——真正耗时间的是「修 → 跑 → 看输出 → 再修」这个循环本身。
grinding-until-pass 就是把这个循环写成可复用的 Agent Skill:指定一条以退出码判定成败的命令,让 Agent 在本地自主循环,直到测试通过、构建成功或 lint 干净,而不是改一次就停下来等你催下一轮。
这是什么¶
grinding-until-pass(文档里也写作 Grind Until Pass)来自 Spencer Pauly 维护的开源合集 awesome-cursor-skills,目录为 resources/grinding-until-pass/,核心是一份标准的 SKILL.md。它不替代测试框架,也不发明新的 CI,而是约束 Agent 的工作方式:在明确的成功条件(命令退出码为 0)下,持续执行「修复 → 运行 → 检查 → 重复」,直到目标达成或触达安全上限。
这类 Skill 基于通用 SKILL.md 格式,在 Cursor、Codex CLI、Claude Code 等支持 Agent Skills 的工具里都可以安装使用;各工具的目录名可能不同,但文件形态一致。
核心流程与约束¶
官方 SKILL.md 把流程拆成四步,逻辑很直白:
- 定义目标命令:用哪条命令的退出码判断「绿了」。例如测试用
npm test或npx vitest run,构建用npm run build,lint 用npm run lint,类型检查用npx tsc --noEmit;也可以串起来,例如:
npm run lint && npx tsc --noEmit && npm test && npm run build
-
运行命令:执行并保留完整输出。
-
失败则分析并最小修复:读错误、定位根因(断言失败、类型错误、lint、import 等),只做最小改动,不做顺手重构,然后回到第 2 步。
-
通过则停止并汇报:说明修了什么、迭代了几轮、改动摘要。
循环还有几条硬规则,这也是它和「随便让 AI 修到能跑」的差别:
- 最多 10 轮:10 次后仍失败就停,向人汇报卡点,避免空转烧 token。
- 一次只修一件事:先修第一个错误再重跑,下游错误有时会连带消失。
- 不要删测试:测试挂了就改实现;只有测试明显写错(例如测的是已故意废弃的旧行为)才改测试。
- 不要靠压制过关:禁止用
@ts-ignore、eslint-disable、随意any等方式把错误闷掉。 - 盯住错误数量:若错误越改越多,停下来重新评估思路。
安装与启用¶
仓库说明:在 Cursor 里,Skill 一般放在项目的 .cursor/skills/(或个人全局目录)下,由 Agent 自动发现。官方合集也推荐用社区 CLI npx skills 安装。
方式一:CLI 安装(推荐)
安装单个 Skill:
npx skills add spencerpauly/awesome-cursor-skills --skill grinding-until-pass
若在 Claude Code 中使用,可指定 agent,安装到当前项目的 .claude/skills/:
npx skills add spencerpauly/awesome-cursor-skills --skill grinding-until-pass --agent claude-code
方式二:手动拷贝
从仓库取出 resources/grinding-until-pass/SKILL.md,放到本机对应目录,例如:
# Cursor 项目级
.cursor/skills/grinding-until-pass/SKILL.md
# 或个人全局(Cursor)
~/.cursor/skills/grinding-until-pass/SKILL.md
Cursor 还会兼容读取 .agents/skills/、.claude/skills/、.codex/skills/ 以及对应的用户主目录路径;Codex / Claude Code 则按各自约定使用 .codex/skills/、.claude/skills/。以你当前工具文档为准即可。
启用后,在对话里用 /grinding-until-pass,或用 @ 附上该 Skill,再说明目标命令;也可以直接描述「按 grinding-until-pass,把 npm test 磨到全绿」。
典型用法¶
大重构后测试一片红、依赖升级带出类型错误、合完分支要清冲突相关失败时,都可以把目标说清楚,让 Agent 按 Skill 循环。例如:
按 grinding-until-pass 执行。
目标命令:npm test
要求:一次只修一个失败;不要删测试;不要用 @ts-ignore / eslint-disable 压制。
最多 10 轮;通过后汇报改了什么、迭代次数。
若希望类型、lint、测试、构建一起过:
目标命令:npm run lint && npx tsc --noEmit && npm test && npm run build
用 grinding-until-pass 磨到全部通过。
官方还给出进阶做法:用 Cursor Hooks,在 Agent 本轮结束后自动再跑测试;若仍失败,通过 hook 脚本返回 followup_message 继续催下一轮。示例配置写在项目的 .cursor/hooks.json:
{
"hooks": [
{
"event": "stop",
"command": "bash .cursor/scripts/check-tests.sh",
"description": "Re-run tests after agent stops and send follow-up if failing"
}
]
}
其中 check-tests.sh 需自行实现:检查测试退出码,失败时返回 follow-up 消息。这样可以把「磨到绿」从对话里的一次请求,延伸成回合结束后的自动接力。
适用场景与注意点¶
适合的场景与官方说明一致:大重构后多测失败、依赖升级引入类型错误、合并冲突后要清编译/测试、以及你信任测试套件、只想「先变绿」时把机械循环交给 Agent。
使用前注意几点:
- 测试要快:官方写明,套件动辄 5 分钟以上时,整段循环会很慢;优先用单元测试或带
--bail/--fail-fast的命令,尽早停在第一个失败上。 - 绿不等于设计对:Skill 强调 Agent 会比较「死磕」但不擅长大改架构;需要产品或设计层面的调整时,仍要人来定方向。
- 成功标准要可机器判定:目标必须是退出码明确的一条(或一组)命令;没有稳定测试/构建命令时,这个 Skill 施展不开。
- 10 轮是保险丝:反复修不好往往说明根因不在局部补丁,该停下来看环境、数据或需求本身。
小结¶
grinding-until-pass 把「修到绿」从口头催促,落成可安装、可复用的 Agent 工作流:目标命令清晰、最小修复、禁止删测和压制错误,并带 10 轮上限。对日常「测试红了、类型炸了、lint 不过」这类机械债,它能明显减少人肉来回;对需要换设计的问题,它会诚实地停在卡点上把球交回给你。
官方地址:https://github.com/spencerpauly/awesome-cursor-skills/tree/main/resources/grinding-until-pass