关于 ralph-builder
用于根据给定目标准备仓库,以运行 Ralph 循环的技能。它会创建 Beads 任务图、执行计划,以及供会话内和外部循环驱动使用的独立提示文件。
主要功能
- 01初始化 Beads 运行 Epic
- 02将目标拆分为依赖任务
- 03编写仓库专属执行计划
- 04为两种循环模式创建提示文件
- 05验证任务图和输出文件
适用场景
- 01根据项目目标准备自主执行任务
- 02按工作树组织并行 Ralph 运行
- 03为任务设置逐项验证指引
MCP 相关
此技能未描述 MCP 接口;它会为 Ralph 循环驱动准备 Beads 任务和提示文件。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jimweller/ clanker-skills --skill ralph-builder安装后在 Claude Code 中输入/ralph-builder确认已加载。
详细介绍
STARTER_CHARACTER = 🔁
Ralph Builder
为当前仓库编写运行 ralph loop 所需的制品,使其能够自主运行。任务存储在 beads(bd)图数据库中。计划和两个提示词包装文件存放在 .llmtmp/ 中。
参数
用户会提供目标描述,其中可能会引用包含 PRD、计划或任务列表的文件。请从调用消息中提取目标。
输出制品
| 路径 | 用途 |
|---|---|
.beads/ | Beads 数据库(任务状态的唯一来源) |
.llmtmp/ralph-plan.md | 与模式无关的执行计划 |
.llmtmp/ralph-prompt-insession.md | 为会话内 ralph-loop 插件提供的斜杠命令包装文件 |
.llmtmp/ralph-prompt-external.md | scripts/ralph.sh 提供给 claude --print 的正文 |
每个提示词包装文件都包含特定模式的正文:会话内循环会持续运行,外部模式则在每项任务后停止。
流程
步骤 1:收集上下文
阅读仓库内容,为计划提供依据:
- 项目根目录中的
README.md .llmdocs/中的所有.md文件- 用户目标参数中引用的任何文件
如果 .llmtmp/ 不存在,请创建它。
步骤 2:初始化 beads 并创建本次运行的 epic
同一仓库的各个工作树共享 bead 图。每次 ralph 运行都按独立的 epic 组织,这样不同工作树中的并发运行便可通过 --parent 筛选保持隔离。
if ! bd list >/dev/null 2>&1; then
bd init --skip-agents
fi
slug=$(git branch --show-current | tr '/' '-')
epic=$(bd q "Ralph: ${slug}" -t epic -p 1 -l "ralph:${slug}")
--skip-agents 会禁止 bd 默认生成 AGENTS.md、修改 CLAUDE.md 以及注入 .claude/settings.json。项目现有的 Agent 指引和 beads 技能已提供 bd 工作流所需的上下文;bd 的项目级 Agent 文件是多余的,也与项目约定相冲突。
epic 带有标签 ralph:${slug},用作运行标识。步骤 3 创建的子项同时带有 --parent "${epic}" 和相同的标签,提供两种独立标识,以便审核者发现孤立项。
步骤 3:将目标转换为 bd 图
ralph 运行中的每项操作都是一个 bead。每个 bead 都有一个标题(祈使句式的单行描述)和一个说明(为该任务提供给执行者的完整指示)。生命周期脚手架(创建分支、BEGIN 标记、END 标记)以普通 bead 的形式编码,并且都以本次运行的 epic 为父项。
使用 bd create -t task --parent "${epic}" -l "ralph:${slug}" -q --json | jq -r .id 创建子 bead。记录每个 ID,以供后续调用 bd link。使用 bd update <id> -d "<text>"(或通过 heredoc 使用 --body-file - 写入多行内容)设置说明。使用 bd link <a> <b> 设置依赖关系(b 会阻塞 a)。每次运行都以分支任务和 BEGIN 标记任务开头;每次运行都以 END 标记任务结尾,并且该任务以传递方式依赖所有其他任务。
示例
下面的代码块展示了一次假设的运行:向 lib/greeting.go 添加三个问候函数,并更新 README。字面值(SLUG、文件路径、函数名、提交前缀)仅供说明;请替换为实际运行中的信息。Bead 描述只包含任务特定的信息。每个编码任务描述都采用下文定义的 RED/GREEN/VERIFY 结构。通用规则(约定式提交、角色约束)已写在 CLAUDE.md 中。整个运行通用的约定(构建、测试、lint 命令)写在 ralph-plan.md 中。描述中无需重复其中任何一项。
DATE=$(date +%Y%m%d)
SLUG=greeting # derive from the goal; lowercase alphanumeric plus hyphen, max ~20 chars
HASH=$(openssl rand -hex 2 | head -c 3)
RUN="${DATE}-${SLUG}-${HASH}"
BRANCH="ralph/${RUN}"
# slug and epic are in scope from Step 2.
bdc() {
bd create "$1" -t task -p 2 --parent "${epic}" -l "ralph:${slug}" -q --json | jq -r .id
}
T_BRANCH=$(bdc "Switch to branch ${BRANCH}")
bd update "$T_BRANCH" -d "Switch to branch ${BRANCH}, creating it if missing. Verify: git rev-parse --abbrev-ref HEAD prints ${BRANCH}."
T_BEGIN=$(bdc "Tag RALPH-${RUN}-BEGIN")
bd link "$T_BEGIN" "$T_BRANCH"
bd update "$T_BEGIN" -d "Run: git tag RALPH-${RUN}-BEGIN. Verify: git tag -l RALPH-${RUN}-BEGIN is non-empty."
T1=$(bdc "Add hello() to lib/greeting.go")
bd link "$T1" "$T_BEGIN"
bd update "$T1" --body-file - <<'DESC'
TDD workflow: write failing tests first, then implement minimum code to pass.
RED phase (write first):
Create lib/greeting_test.go. Test cases: hello() returns "world".
GREEN phase (then implement):
Create hello() in lib/greeting.go returning "world".
VERIFY: go test ./lib/... passes. Commit: feat(greeting): add hello
DESC
T2=$(bdc "Add goodbye() to lib/greeting.go")
bd link "$T2" "$T_BEGIN"
bd update "$T2" --body-file - <<'DESC'
TDD workflow: write failing tests first, then implement minimum code to pass.
RED phase (write first):
Add to lib/greeting_test.go. Test cases: goodbye() returns "bye".
GREEN phase (then implement):
Create goodbye() in lib/greeting.go returning "bye".
VERIFY: go test ./lib/... passes. Commit: feat(greeting): add goodbye
DESC
T3=$(bdc "Add greet(name) to lib/greeting.go")
bd link "$T3" "$T1"
bd link "$T3" "$T2"
bd update "$T3" --body-file - <<'DESC'
TDD workflow: write failing tests first, then implement minimum code to pass.
RED phase (write first):
Add to lib/greeting_test.go. Test cases: greet("Jim") returns
"world Jim bye".
GREEN phase (then implement):
Create greet(name) in lib/greeting.go composing hello() and goodbye().
VERIFY: go test ./lib/... passes. Commit: feat(greeting): add greet
DESC
T4=$(bdc "Document greetings API")
bd link "$T4" "$T3"
bd update "$T4" -d "Run the docs skill (/docs, \$docs) to document hello(), goodbye(), and greet() now exposed by lib/greeting.go. Commit: docs: document greetings API"
T_END=$(bdc "Tag RALPH-${RUN}-END")
bd link "$T_END" "$T4"
bd update "$T_END" -d "Run: git tag RALPH-${RUN}-END. Verify: git tag -l RALPH-${RUN}-END is non-empty."
3 个字符的哈希后缀可防止多个 ralph 运行共用同一日期和 slug 时出现分支和标签冲突。
编写完成后,断言不存在循环依赖、每个子项都有描述、至少有一个任务已就绪,并且父项集合与标签集合相等(不包括 epic):
bd dep cycles
bd list --parent "${epic}" --json | jq -e 'all(.[]; (.description // "") | length > 0)'
bd ready --parent "${epic}" --json | jq 'length'
parent_ids=$(bd list --parent "${epic}" --json | jq -r '.[].id' | sort)
label_ids=$(bd list --label "ralph:${slug}" --json | jq -r '.[] | select(.issue_type != "epic") | .id' | sort)
[[ "${parent_ids}" == "${label_ids}" ]] || { echo "parent/label set mismatch: orphans or misclassified beads"; exit 1; }
标题规则:
- 使用祈使语气,限一行
- 写明交付成果,而非操作流程
- 不要创建“阅读代码库”或“理解架构”等元任务
描述规则:
- 仅包含任务特定的信息:涉及的文件、行为、此任务的提交消息
- 只有在验证命令与本次运行的标准测试命令不同时,才注明验证命令(通常是标签和分支任务)
- 不要重复代码风格或角色规则;这些已写在
CLAUDE.md中。不要重复整个运行通用的构建、测试或 lint 命令;这些已写在ralph-plan.md中 - 每个编码任务描述都采用 RED/GREEN/VERIFY 结构:RED 阶段注明测试文件,并列出具体测试用例及预期行为。GREEN 阶段仅描述实现。VERIFY 阶段注明测试命令和约定式提交消息。生命周期、配置、SQL、shell、Helm 和文档 bead 不受此要求限制。
- 切勿创建独立的“编写测试”“添加单元测试”或“集成检查点”bead。测试应通过 RED 阶段纳入各编码任务。不得创建仅用于测试的 bead,也不得延后创建测试套件 bead。
技能委派(强制):
| 工作 | 技能 |
|---|---|
更新 README.md、CLAUDE.md 或 .llmdocs/ 中的任何文件 | docs(/docs、$docs) |
这些类别的 bead 必须在描述中调用技能,而不是直接编写编辑内容。例如:Run the docs skill to document the new auth middleware,而不是 Edit .llmdocs/architecture.md to add an Authentication subsection。技能自带防护措施和并行处理能力;在任务描述中自行复现其工作会失去这两者。
第 4 步:编写 .llmtmp/ralph-plan.md
每次迭代都会在没有先前运行记忆的情况下读取此文件。所有命令、模式和约定都必须写在这里。内容详尽且针对仓库是正确的。
“Run Identity”部分记录第 2 步生成的字面值 ${slug} 和 ${epic},这样 Agent 每次迭代都能直接读取,而不必重新推导。
“Inputs”部分的 plan documents: 行记录规划器通过用户参数收到的源文档。审阅者会解析该行,并将所列路径作为权威意图来读取。这是一项原样传递:必须恰好列出用户参数中的文件,不多不少,也不得推断并添加其他文件。如果引用的路径不存在,应以明确的错误使构建失败,而不是将其删去。
必需部分:
# Ralph Plan
## Goal
<one paragraph>
## Approach
<strategy specific to this goal; include all relevant repo-specific detail directly>
## Inputs
plan documents: <comma-separated paths from the user's arguments, or empty if none>
## Run Identity
- Branch slug: `<slug from Step 2>`
- Epic ID: `<epic ID from Step 2>`
- Epic label: `ralph:<slug>`
- Driver: `scripts/ralph.sh .llmtmp/ralph-prompt-external.md`
## Conventions
<repo-specific patterns, tools, test commands, build commands, commit style>
## Git Workflow
All git operations execute as bd tasks per the per-task workflow. Branch creation, BEGIN tag, code commits, docs commits, and END tag are first-class beads in the graph, parented to the run epic. Never commit on `main`.
## Per-Task Workflow
Exactly ONE task per iteration. After step 5, follow the driver instruction. The driver controls whether the agent loops in-session or stops for a fresh context.
Each iteration:
1. Read the epic ID and slug from the "Run Identity" section above.
2. Run `bd ready --parent <epic-id> --json`. If the result is `[]`, run `bd close <epic-id> -m "ralph run complete"`, output `<promise>ALLDONE</promise>`, and stop.
3. Pick the first task. Run `bd show <id>` to read the title and description.
4. Execute the description exactly. The description names the files, commands, verification step, and commit message for this task.
5. Run `bd close <id>`. Follow the driver instruction below.
The sentinel `<promise>ALLDONE</promise>` is emitted only on the iteration where step 2 finds the ready queue empty (all children closed and the epic just closed).
## Driver Instruction
计划规则:
- 指令必须基于实际的仓库结构和工具
- 已知时,包含构建、测试和 lint 命令
- 不要重复项目的
CLAUDE.md - 明确任务“完成”的标准(测试通过、lint 无误)
- 仅陈述当前事实
plan documents:必须恰好列出用户参数中引用的文件。不要添加README.md、CLAUDE.md或.llmdocs/*(审阅者会独立读取这些文件作为基线)。不得从.llmtmp/或其他位置推断相关文件。如果引用的路径不存在,应以明确的错误使构建失败,而不是将其删去。
步骤 5:编写提示词包装
每种模式都有自己的正文,因为驱动指令各不相同。
会话内正文(循环执行,不停止):
Read .llmtmp/ralph-plan.md and follow it. After closing each task, return to step 1 of the Per-Task Workflow to pick the next ready task. Do not stop between tasks.
外部正文(每次调用执行一个任务):
Read .llmtmp/ralph-plan.md and follow it. After closing each task, STOP. The driver spawns a fresh context for the next task.
.llmtmp/ralph-prompt-insession.md 是使用会话内正文的一行内容:
/ralph-loop:ralph-loop "<in-session body>" --max-iterations 100 --completion-promise ALLDONE
.llmtmp/ralph-prompt-external.md 仅包含外部正文,不含包装。
验证
完成前,请确认:
-
bd list >/dev/null 2>&1以零退出码退出 -
bd dep cycles以零退出码退出 -
本次运行存在一个未关闭的 epic:
bd list -t epic -l "ralph:${slug}" --json | jq -e 'length == 1' -
bd ready --parent "${epic}" --json | jq 'length'的结果大于零 -
epic 的每个子项都有非空描述:
bd list --parent "${epic}" --json | jq -e 'all(.[]; (.description // "") | length > 0)' -
父项集合与标签集合相同(不包括 epic 本身):
diff <(bd list --parent "${epic}" --json | jq -r '.[].id' | sort) \ <(bd list --label "ralph:${slug}" --json | jq -r '.[] | select(.issue_type != "epic") | .id' | sort) -
.llmtmp/ralph-plan.md、.llmtmp/ralph-prompt-insession.md、.llmtmp/ralph-prompt-external.md均存在 -
计划中的“Run Identity”部分记录了字面 slug 和 epic ID
-
会话内提示词包含 "return to step 1" 和 "Do not stop between tasks"
-
外部提示词包含 "STOP" 和 "fresh context"
如果任何断言失败,请修复并重新验证。