Ralph 是一个 Bash 脚本,可自主运行 Claude,根据 PRD(产品需求文档)实现功能。它每次迭代处理一个用户故事,每个故事完成后提交一次,当 PRD 全部完成时停止。
安装与首次设置
当用户首次调用 Ralph 时,检查项目是否已设置:
- 如果项目根目录中不存在 ralph.sh,则从 references/ralph-script.md(位于此技能所在目录)创建它
- 使其可执行:chmod +x ralph.sh
- 如果尚未添加,则加入 .gitignore:prd.json、progress.txt
- 如果 tasks/ 目录不存在则创建
- 如果 progress.txt 不存在则创建空文件
- 验证 jq 是否已安装(which jq);如果没有,提示用户安装(brew install jq)
工作流程
- 使用 prd 技能创建 PRD → 保存到 tasks/prd-[feature-name].md
- 使用下方转换规则将 PRD 转换为 prd.json
- 在单独的终端中运行 Ralph:./ralph.sh 10(数字为最大迭代次数)
- 等待完成——Ralph 会逐个实现故事并提交
PRD 到 prd.json 的转换
输出格式:
{ "project": "[Project Name]", "branchName": "ralph/[feature-name-kebab-case]", "description": "[Feature description from PRD title/intro]", "userStories": [ { "id": "US-001", "title": "[Story title]", "description": "As a [user], I want [feature] so that [benefit]", "acceptanceCriteria": [ "Criterion 1", "Criterion 2", "Typecheck passes" ], "priority": 1, "passes": false, "notes": "" } ] }
转换规则:
- 每个用户故事对应一个 JSON 条目
- ID 按顺序编号(US-001、US-002 等)
- 优先级:先按依赖顺序,再按文档顺序
- 所有故事:passes 为 false,notes 为空
- branchName:根据功能名称派生,采用 kebab-case,前缀为 ralph/
- 每个故事的验收标准都必须加上:'Typecheck passes'
故事粒度:最重要的规则
每个故事必须能在一次 Ralph 迭代(一个上下文窗口)内完成。
Ralph 每次迭代都会启动一个全新的 Claude 实例,且不记忆之前的工作。如果故事太大,LLM 会在完成前耗尽上下文,产出损坏的代码。
合适粒度示例:
- 添加一个数据库列和迁移
- 在现有页面添加一个 UI 组件
- 用新逻辑更新一个服务器 action
- 为列表添加一个筛选下拉框
过大(需拆分):
- '构建整个仪表板' → 拆分为:schema、查询、UI 组件、筛选器
- '添加身份验证' → 拆分为:schema、中间件、登录 UI、会话处理
- '重构 API' → 按端点或模式拆分为多个故事
经验法则:如果你无法用 2-3 句话描述该变更,说明它太大了。
故事排序:依赖优先
故事按优先级顺序执行。较早的故事不能依赖较晚的故事。
正确顺序:
- Schema/数据库变更(迁移)
- 服务器 action / 后端逻辑
- 使用后端的 UI 组件
- 聚合数据的仪表板/汇总视图
错误顺序:
- UI 组件(依赖尚不存在的 schema)
- Schema 变更
验收标准:必须可验证
每条标准必须是 Ralph 可以检查的内容,而不是模糊描述。
好的标准(可验证):
- '向 tasks 表添加 status 列,默认值为 pending'
- '筛选下拉框的选项为:All、Active、Completed'
- '点击删除时显示确认对话框'
- 'Typecheck passes'
- 'Tests pass'
差的标准(模糊):
- '运行正确'
- '用户可以轻松完成 X'
- '良好的用户体验'
- '处理边缘情况'
始终包含的最终标准:
- 'Typecheck passes'
对于有可测试逻辑的故事,还要包含:
- 'Tests pass'
对于更改 UI 的故事,还要包含:
- 'Verify in browser'
前端故事在没有经过浏览器视觉验证之前不算完成。
归档先前运行与重置
在写入新的 prd.json 之前,检查是否存在来自不同功能的现有文件:
- 如果存在当前 prd.json,则读取
- 检查 branchName 是否与新功能的 branchName 不同
- 如果不同且 progress.txt 有内容:
- 创建归档文件夹:archive/YYYY-MM-DD-feature-name/
- 将当前 prd.json 和 progress.txt 复制到归档中
始终重置 progress.txt:
写入新的 prd.json 后,将 progress.txt 重置为空:
echo "" > progress.txt
Ralph 工作原理(参考)
每次迭代:
- 找到 passes 为 false 的最高优先级故事
- 实现该功能
- 运行类型检查
- 更新 prd.json:设置 passes 为 true 并添加备注
- 将进度追加到 progress.txt
- 创建一次 git 提交
当所有故事的 passes 都为 true 或迭代次数耗尽时停止。
运行 Ralph
./ralph.sh 10 # 最多运行 10 次迭代
要求
- 已安装 jq(brew install jq)
- Claude CLI 已配置并完成身份验证
安全性
- Ralph 会自动切换到 prd.json 中指定的分支
- 拒绝在 main 或 master 分支上运行
保存 prd.json 前的检查清单
- 先前运行已归档(如果 prd.json 存在且 branchName 不同)
- 每个故事可在一次迭代内完成(足够小)
- 故事按依赖排序(schema → 后端 → UI)
- 每个故事都有 'Typecheck passes' 作为标准
- UI 故事有 'Verify in browser' 作为标准
- 验收标准可验证(不模糊)
- 没有故事依赖后面的故事
- 写入 prd.json 后 progress.txt 重置为空