oh-my-claudecode ultragoal 实战指南:基于 Claude Code/goal的持久化多目标工作流
【免费下载链接】oh-my-claudecodeTeams-first Multi-agent orchestration for Claude Code项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-claudecode
导读
ultragoal是 oh-my-claudecode(OMC)提供的一套仓库原生的持久化多目标工作流:它把一段 brief 拆解为有序目标集合,以追加式(append-only)账本记录 start/checkpoint/blocker/failure 事件,并通过打印模型可读的交接文本(handoff),指导当前 Claude agent 在会话内驱动 Claude Code 的/goal斜杠命令。本文将从使用场景、命令全集、工件布局、质量门禁到并行会话约束,完整讲解这套工作流,并深入对应源码(CLI 命令实现、核心工件逻辑、快照对账),帮助你在大规模多步骤任务、跨会话续跑和多仓库并行场景下落地使用。
为什么需要 ultragoal:/goal的会话级局限
Claude Code 的/goal是一个会话级(session-scoped)Stop hook:它会阻止会话停止,直到某个条件成立,并在条件满足时自动清除。作为单一会话内的执行原语,/goal非常有效,但它存在三个天然短板:
- 跨会话丢失状态:会话重启后
/goal状态不保留; - 无最终评审门禁:
/goal本身不强制最终 review 关卡; - shell 无法操作它:从 shell 无法直接调用或修改 Claude Code 的
/goal状态。
ultragoal在这之上叠加了持久计划(plan)、账本(ledger)和门禁(gating)层,让一个长期多步骤的 initiative 可以在会话重启、全新 worktree、评审迭代之间存活,同时仍然借助/goal保持当前 agent 聚焦于目标。正如 SKILL.md 中明确指出的:
It does not — and cannot — mutate Claude
/goalstate from the shell; it persists durable repo state and prints a model-facing handoff that the active agent must act on in-session.
何时使用 / 何时不用
ultragoal适合以下场景(见 SKILL.md 的 Use_When):
- 用户需要一个跨多个 Claude 会话或 worktree的、仓库原生的 ultragoal 追踪方式;
- 工作量大到值得拆成多个有序 "stories",每个 story 带尝试次数(attempt count)与逐 story 证据(evidence);
- 用户希望最终完成被
ai-slop-cleaner+ verification +$code-review门禁强制把关; - 用户希望把活跃的 Claude
/goal指令与账本协调,使会话重启不丢进度。
与之相对,不要使用它的情况:
- 任务只是单个小改动——应直接委派或使用
ralph; - 用户希望助手从 shell 直接调用
/goal本身——这不可能,omc ultragoal只写工件并打印交接文本; - 用户只想要纯规划工件、没有执行循环——应改用
plan。
从源码结构看,ultragoal在工作流注册表中被明确保留为"直接可调用的持久化多目标工作流"(Retained as the durable multi-goal workflow with its own .omc/ultragoal artifacts),并可通过 CLI 入口 的omc ultragoal子命令体系访问。
工件布局:.omc/ultragoal/下到底存了什么
ultragoal的全部持久化状态存放在仓库的.omc/ultragoal/目录下,包含三个核心工件(常量定义见 artifacts.ts):
| 文件 | 作用 |
|---|---|
brief.md | 原始 brief 文本,来自--brief/--brief-file/ stdin |
goals.json | 计划本身:goal 列表、各自状态、尝试次数、active goal id、aggregate 完成记录 |
ledger.jsonl | 追加式事件账本,每行一个 JSON 事件 |
多计划布局(通过--plan-id或--auto-plan-id启用)则写入:
.omc/ultragoal/plans/{planId}/brief.md .omc/ultragoal/plans/{planId}/goals.json .omc/ultragoal/plans/{planId}/ledger.jsonlplanId是稳定字符串;自动生成格式为{epochMs}-{slug},其中 slug 取自 brief 首个非空标题(实现见 makePlanId)。
ledger.jsonl支持的事件类型(见 UltragoalLedgerEntry)包括:plan_created、goal_started、goal_resumed、goal_completed、goal_blocked、goal_failed、goal_retried、aggregate_completed、goal_added、final_review_failed、goal_review_blocked。由于是追加式写入(appendFile,见 appendLedger),账本天然不可变、可审计。
goal ID 采用G001-{slug}形式,slug 由标题派生,例如G001-build-the-cli(见 normalizeGoalId,测试断言见 artifacts.test.ts)。
完整命令参考
omc ultragoal提供以下子命令(完整帮助文本见 ULTRAGOAL_HELP):
omc ultragoal create-goals [--brief <text> | --brief-file <path> | --from-stdin] [--goal <title::objective>] [--claude-goal-mode <aggregate|per-story>] [--force] [--plan-id <id> | --auto-plan-id] [--json] omc ultragoal complete-goals [<goal-id>] [--retry-failed] [--plan-id <id>] [--json] omc ultragoal add-goal --title <title> --objective <text> [--evidence <text>] [--plan-id <id>] [--json] omc ultragoal record-review-blockers --goal-id <id> --title <title> --objective <text> --evidence <review-findings> --claude-goal-json <active-json-or-path> [--plan-id <id>] [--json] omc ultragoal checkpoint --goal-id <id> --status <complete|failed|blocked> [--evidence <text>] [--claude-goal-json <json-or-path>] [--quality-gate-json <json-or-path>] [--plan-id <id>] [--json] omc ultragoal status [--claude-goal-json <json-or-path>] [--plan-id <id>] [--json] omc ultragoal list-plans [--json]别名:create→create-goals;complete/next/start-next→complete-goals。所有子命令都支持--json输出结构化结果(--json输出实现见 printJson)。
1. 创建计划:create-goals
从 brief 文件创建:
omc ultragoal create-goals --brief-file plan.md或显式指定 stories:
omc ultragoal create-goals --brief "ship the migration" \ --goal "Schema::Add new columns" \ --goal "Backfill::Backfill rows in batches" \ --goal "Cutover::Drop old columns and switch reads"--goal的格式是title::objective,冒号前是标题、之后是目标文本(解析逻辑见 parseGoalArg)。若未传任何--goal,则会从 brief 自动派生候选目标:优先提取列表项(-/*/+或数字序号开头),其次按空行分段取段落(见 deriveGoalCandidates)。
默认模式为aggregate(一个 Claude/goal覆盖整次运行);传--claude-goal-mode per-story可让每个 story 各自拥有/goal。两个模式之间可通过--force重新创建已有计划——但注意,默认会拒绝覆盖已存在的goals.json(见 createUltragoalPlan),并校验planId只允许a-z、0-9、点、下划线、连字符。
多仓库工作区 / 并行会话:当同一工作区内有多个 Claude 会话需要并发运行/ultragoal时,必须传--plan-id <stable-id>或--auto-plan-id,让计划写入.omc/ultragoal/plans/{planId}/而非共享的单计划路径;否则两个会话创建目标会互相覆盖。--auto-plan-id从 brief 标题派生{epochMs}-{slug}。之后该会话内所有后续子命令都要带上同一个--plan-id <id>,需要时用omc ultragoal list-plans枚举可用 planId。
2. 开始(或恢复)下一个 story:complete-goals
omc ultragoal complete-goals [<goal-id>]- 不带 goal id:保持默认行为——恢复活跃 story,或开始第一个 pending story;
- 带 goal id:精确定位该具名可执行 story(允许乱序开始一个 pending story),且绝不回退到其他 story;
- 若存在其他活跃 story、id 未知、已完成、review-blocked,或失败但未传
--retry-failed,则拒绝且不产生任何状态变更; - 具名且 in-progress 的 story 会被恢复,不改变其 attempt 计数。
这些规则在 startNextUltragoal 中有完整实现:恢复活跃 story 会写goal_resumed事件;开始新 story 会attempt += 1、写入goal_started事件;失败 story 只有在--retry-failed时才先写goal_retried事件再置回 pending。
该命令会打印一条面向模型的交接文本(handoff),由活跃 Claude agent 阅读并执行。handoff 内容由 buildClaudeGoalInstruction 按模式分发到 buildPerStoryClaudeGoalInstruction 或 buildAggregateClaudeGoalInstruction,包含:计划与账本路径、目标 id、/goal集成约束、建议的/goalpayload JSON、以及最终 story 才有的强制质量门禁说明。测试对此断言了关键措辞(artifacts.test.ts)。
拿到 handoff 后,活跃 Claude agent 需要:
- 为本会话设置原生 Claude
/goal——在独立 Claude Code 中,shell 和 agent 都无法代劳,需请用户输入/goal <aggregate objective>并等待。注意--claude-goal-json只做账本对账,不满足PreToolUse/goal守卫——该守卫会阻止工具调用,直到它观察到真实的活跃/goal; - 推进该 story;
- story 完成后(若是最后一个 story,还需通过完整质量门禁),回传活跃
/goal状态的快照并调用checkpoint。
3. 记录进度:checkpoint
omc ultragoal checkpoint --goal-id G001-... --status complete \ --evidence "tests/files/PR evidence" \ --claude-goal-json '{"goal":{"objective":"...","status":"active"}}'--status仅接受complete | failed | blocked三选一(校验见 ultragoal.ts)。checkpoint 只允许作用于活跃的 in-progress goal(assertActiveInProgressCheckpoint):
complete:会校验/goal快照(见下文"快照对账"),写goal_completed事件并清除 activeGoalId;failed:记录failedAt与failureReason,写goal_failed事件;blocked:用于"已完成的历史 Claude goal 阻塞本会话设置新/goal"的场景,要求传入一个status 为 complete 且 objective 与本计划不同的/goal快照(见 checkpointUltragoal 与 buildCompletedLegacyGoalRemediation),随后建议在全新 Claude Code 会话中继续本 ultragoal。
对于最后一个 story,还需传--quality-gate-json,包含aiSlopCleaner、verification、codeReview三部分证据(全部 clean)。
4. 最终评审未通过:record-review-blockers
当最终 review 不干净时,不要标记 complete,而是记录 blockers:
omc ultragoal record-review-blockers --goal-id G00X-... \ --title "Resolve final code-review blockers" \ --objective "Fix the listed review findings and rerun final gates" \ --evidence "<the review findings>" \ --claude-goal-json '{"goal":{"objective":"...","status":"active"}}'该命令会把原 goal 置为review_blocked、追加一个新的 blocker story,并让 Claude/goal保持 active(实现见 recordFinalReviewBlockers)。它的前置条件很严格:goal 必须处于in_progress,且必须是唯一未解决的 story(isFinalRunCompletionCandidate 要求其余 goal 全部为 complete 或 review_blocked)。账本会依次写入final_review_failed、goal_added、goal_review_blocked三个事件。
5. 随时查看状态:status 与 list-plans
omc ultragoal status omc ultragoal list-plansstatus输出形如ultragoal: 2/5 complete, 1 pending, 1 in progress, 1 failed, 0 review-blocked,并用*标记活跃 goal(见 printStatus);若传了--claude-goal-json还会附带对账警告。list-plans枚举plans/目录下的全部 planId,目录不存在时返回空列表。
两种 Claude/goal模式:aggregate 与 per-story
--claude-goal-mode决定/goal与账本 story 的映射关系(模式定义见 UltragoalClaudeGoalMode,CLI 归一化见 normalizeClaudeGoalMode):
- aggregate(默认):一个 Claude
/goal覆盖整个 ultragoal 运行,OMC 在持久账本里逐个 checkpoint G001/G002 等 story。创建计划时会自动生成 aggregate objective——前缀Complete all ultragoal stories in .omc/ultragoal/goals.json:,后接每个 goal 的{id} {title},总长超过 4000 字符时回退到简短引用形式(见 aggregateClaudeObjective)。中途 story 完成时/goal保持 active,直到最后一个 story 才允许清除。 - per_story:每个 story 拥有自己的
/goal。--claude-goal-mode同时接受per-story与per_story两种拼写;检查点要求每个 story 的/goal快照状态为complete。
预期 objective 的推导见 expectedClaudeObjective:aggregate 模式用计划级claudeObjective,per-story 模式用该 goal 的objective。status命令的对账也按此选择 expectedObjective(ultragoal.ts)。
快照对账机制:--claude-goal-json 如何工作
--claude-goal-json接受内联 JSON 或文件路径两种形式(readClaudeGoalSnapshotInput)。快照的合法形状包括:
{ "goal": { "objective": "...", "status": "active" } } { "objective": "...", "status": "complete" }condition被接受为objective的同义词;status的合法取值归一化为active | complete | cancelled | failed | unknown(normalizeStatus),active接受active/in_progress/pending/running等写法。
对账逻辑(reconcileClaudeGoalSnapshot)做三件事:
- 检查快照是否存在且可解析(
available); - 校验
objective与计划期望文本是否一致(做了空白归一化); - 校验
status是否在允许集合内,requireComplete时还要求状态为complete。
重要边界:这些快照是模型提供的、关于活跃/goal状态的证据;OMC 只验证其文本与计划期望目标、账本事件的一致性,无法独立观察Claude/goal的真实状态,也不满足PreToolUse/goal守卫——守卫要求真实的活跃/goal(宿主编入的快照,或用户在本会话设置的原生/goal)。如果 Claude/goal斜杠命令被重命名或重构,只需调整交接文本措辞,对账逻辑与名称无关(见 SKILL.md 的 Important_Limitations)。
最终质量门禁:quality-gate-json
最后一个 story 的checkpoint --status complete必须携带--quality-gate-json,其结构(类型定义见 UltragoalQualityGate,校验见 validateQualityGate)如下:
{ "aiSlopCleaner": { "status": "passed", "evidence": "ai-slop-cleaner ran on changed files" }, "verification": { "status": "passed", "commands": ["npm test"], "evidence": "tests passed after cleaner" }, "codeReview": { "recommendation": "APPROVE", "architectStatus": "CLEAR", "evidence": "$code-review approved with CLEAR architecture" } }校验规则(源码强制,测试示例见 artifacts.test.ts):
aiSlopCleaner.status必须为"passed"且带 evidence——即使是无操作也要运行ai-slop-cleaner;verification.status必须为"passed",commands必须是非空字符串数组;codeReview.recommendation必须为"APPROVE"、architectStatus必须为"CLEAR"——出现COMMENT/REQUEST CHANGES或WATCH/BLOCK时,必须改用record-review-blockers而不是标记完成。
只有最后 story 且未显式放宽时才强制校验门禁(checkpointUltragoal)。另外还有一个特殊路径:aggregate 模式下,如果快照 objective 与期望不同但为complete,OMC 会尝试"任务级 aggregate 对账"(canReconcileCompletedTaskScopedAggregateSnapshot)——要求证据中提及.omc/ultragoal/goals.json或ledger.jsonl、点名活跃 OMC goal id、包含"实现完成 + 验证/评审通过"语义,且快照 objective 能映射到 brief——满足时才允许以aggregate_completed收尾。
并行会话与多仓库工作区
SKILL.md 专门给出了三条并行会话注意事项(Parallel session caveats),与 docs/REFERENCE.md 的状态根解析规则一一对应:
- 多仓库工作区锚点:在父目录放置
.omc-workspace标记,让跨子仓库的多个会话共享一个.omc/。状态根解析顺序为OMC_STATE_DIR > .omc-workspace > git > cwd(详见 REFERENCE.md 状态根解析)。.omc-workspace内容可为空 JSON(echo '{}' > .omc-workspace),仅作标记使用(REFERENCE.md 多仓库工作区)。OMC_STATE_DIR则将状态集中到$OMC_STATE_DIR/{project-id}/,可在 worktree 删除后保留状态(REFERENCE.md OMC_STATE_DIR)。 - 会话 id 来源:CLI 上下文优先取
OMC_SESSION_ID环境变量;hook 上下文取payload.data.session_id(hook payload 的 session_id 已按 Claude Code 会话隔离)。 - 计划 id:同一工作区两次运行会争用共享计划工件。要么使用互不相同的 session id,要么传
--plan-id让并行 ultragoal 运行落在独立账本上。 - 并行裁决:受支持——每个会话写入各自的会话级状态。
多计划解析规则(resolveActivePlanId):显式--plan-id优先;其次是遗留单计划goals.json(向后兼容);再次是恰好存在一个多计划时自动选中;存在多个计划时--plan-id成为必填。--plan-id与--auto-plan-id互斥(createUltragoalPlan)。相关多仓库行为有专门测试覆盖:artifacts.multirepo.test.ts。
限制与边界(务必牢记)
- shell 无法调用或修改 Claude Code
/goal状态。omc ultragoal只持久化工件并打印供活跃 Claude agent 在会话内执行的指令; - 快照是模型自证的:OMC 校验文本一致性,但不能独立观察
/goal状态,也不能用快照顶替 PreToolUse/goal守卫; /goal命名无关性:斜杠命令被重命名或重构时,只需改交接文本措辞,对账逻辑不受影响;- 单一小任务不要用:应直接委派或使用
ralph;纯规划请用plan。
深入阅读指引
- 技能说明:skills/ultragoal/SKILL.md
- CLI 命令与帮助文本:src/cli/commands/ultragoal.ts
- 计划/账本/门禁核心实现:src/ultragoal/artifacts.ts
/goal快照解析与对账:src/goal-workflows/claude-goal-snapshot.ts- 单元测试(单计划/多计划):src/ultragoal/tests/artifacts.test.ts、src/ultragoal/tests/artifacts.multirepo.test.ts
- 状态根解析与多仓库锚点:docs/REFERENCE.md
掌握这套工作流后,你可以在一次"史诗级"任务中把 brief 拆成可追踪、可审计、可跨会话续跑的目标序列,让 Claude/goal与 OMC 账本各司其职,最终在ai-slop-cleaner + verification + $code-review全部通过后才真正收尾。
【免费下载链接】oh-my-claudecodeTeams-first Multi-agent orchestration for Claude Code项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-claudecode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考