关于 loop-it
loop-it 是一个自动处理 GitHub 开放 issue 的技能,适合希望按依赖顺序实现、审查并交付任务的开发流程。它逐项运行实现、/review-it 和 /ship-it,并将进度写入检查点文件以便中断后恢复。
主要功能
- 01获取开放 issue 并解析依赖
- 02按依赖顺序逐项处理
- 03内联实现并运行测试与 lint
- 04调用 /review-it 和 /ship-it
- 05检查点记录与中断恢复
适用场景
- 01按依赖关系批量处理 GitHub issue
- 02中断后从状态文件恢复任务
- 03在审查和交付步骤间跟踪 issue 进度
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ smallnest/ goal-workflow --skill loop-it安装后在 Claude Code 中输入/loop-it确认已加载。
详细介绍
loop-it — 带检查点恢复的自动化 Issue 实现循环
Fetch all open GitHub issues, resolve dependency order, implement each through the full pipeline (内联实现 → /review-it → /ship-it), persist progress to state file, and resume from checkpoint on crash.
⚠️ 关键前提:实现步骤由 agent 内联自主完成,不依赖任何外部
/goal命令。 本环境中不存在可调用的goal命令或 skill。因此「实现 issue」这一步必须由 agent 内联完成:直接读取该 issue 的标题与正文(含其引用的 PRD/SPEC 与验收条件),自主完成"理解需求 → 写/改代码 → 跑测试与 lint → 满足全部验收条件"的闭环,持续工作直到该 issue 的验收条件全部满足且测试/构建通过。不要尝试用 Skill 工具调用goal(会报goal is a UI command, not a skill),也不要因为找不到/goal而中止循环。/review-it、/ship-it仍是真实 skill,经 Skill 工具调用。loop-it 循环中不调用/note-it。
Overview
前置检查 → 读取状态文件 → Fetch Issues → 构建依赖图 → 拓扑排序
|
┌───────────────────────────────────────────────────────────┘
|
v
┌──────────────── 单 Issue 循环 ────────────────┐
| |
| 从检查点恢复?—— 跳过已完成/失败的 |
| |
| 分支准备 (checkout main, pull, create branch) |
| | |
| Skip/Blocked? ── 是 → 标记 skipped/blocked, 写检查点 |
| | |
| 否 |
| | |
| 内联实现 → 出错?→ 分类 → 恢复 → 重试 |
| | | |
| | 失败 → 检查点, 下一个 |
| | |
| /review-it → 有问题?→ 修复 → 重跑 review |
| | |
| /ship-it → 出错?→ 分类 → 恢复 |
| | |
| 分支清理 (checkout main, pull, delete branch) |
| | |
| 检查点 (标记 shipped) |
| | |
└────────┴──────────────────────────────────────┘
|
v
全部完成 → 最终 Summary
前置检查
开始循环前,按顺序验证所有前提条件。任何检查失败则停止并打印错误。
Check 1: gh CLI 认证
gh auth status
失败 → 打印 ❌ gh CLI 未认证。运行: gh auth login,退出。
Check 2: Git 仓库
git rev-parse --is-inside-work-tree
失败 → 打印 ❌ 不在 git 仓库中,退出。
Check 3: Git 工作树清洁度
git status --porcelain
有输出(dirty)→ 打印 ⚠️ 工作树有未提交的更改,提供选项:
- A.
git stash暂存后继续 - B. 中止,让用户自行处理
- C. 强制继续(不推荐)
默认 B。
Check 4: 在默认分支上
git branch --show-current
不在 main/master → 打印 ⚠️ 当前在 {branch} 分支,提供选项:
- A.
git checkout main && git pull切换 - B. 继续在当前分支
Check 5: 远程可达
git ls-remote --heads origin
失败 → 打印 ❌ 无法访问远程仓库。检查网络和权限,退出。
Check 6: 状态文件存在?
cat .loop-state.json
存在 → 打印进度摘要,提供选项:
- A. 从检查点恢复
- B. 从头开始(删除状态文件)
- C. 中止
状态文件
位置
.loop-state.json,放在 repo 根目录。必须添加到 .gitignore。如果文件被 git 跟踪,打印警告并建议用户添加到 .gitignore。
格式
{
"version": 1,
"started_at": "2025-06-09T10:00:00Z",
"updated_at": "2025-06-09T10:30:00Z",
"repo": "owner/repo-name",
"total_issues": 8,
"issues": {
"3": {
"status": "shipped",
"branch": "feat/issue-3-add-priority",
"started_at": "2025-06-09T10:00:00Z",
"completed_at": "2025-06-09T10:15:00Z",
"attempts": 1
},
"4": {
"status": "failed",
"phase": "goal",
"error_class": "build_failure",
"branch": "feat/issue-4-filter-tasks",
"started_at": "2025-06-09T10:15:00Z",
"updated_at": "2025-06-09T10:30:00Z",
"attempts": 3,
"last_error": "test TestFilterPriority failed: expected 3, got 0"
},
"7": {
"status": "pending"
}
}
}
状态值
pending | in_progress | skipped | shipped | failed | blocked
写入规则
- 每次状态转换后立即写入(
pending→in_progress、in_progress→shipped/failed/skipped等) - 写入使用
cat > .loop-state.json << 'LOOPSTATE'\n{json}\nLOOPSTATE - 如果状态文件已存在但内容损坏(非法 JSON),打印警告,提供从头开始或中止的选项。绝不自动覆盖损坏文件
- 循环完成后保留状态文件(作为记录),用户可手动删除
Step 1: Fetch Issues & Build Dependency Graph
Fetch all open issues:
gh issue list --state open --json number,title,labels,body --limit 100
Parse Dependencies
Read each issue body, look for patterns:
Dependencies: #3, #5orDepends on: #3depends on #3orrequires #3(in body text)
Build a dependency graph. Sort using topological order:
- Issues with no dependencies first (sorted by number ascending)
- Issues whose dependencies are all shipped/closed next
- Blocked issues (depend on other open issues) last
- Circular dependencies → print warning
⚠️ 循环依赖检测到: #A ↔ #B,按编号顺序处理,break cycle by number order
If no dependency patterns found in any issue body, fall back to number-ascending sort.
Print ordered list:
📋 Found N open issues (topological sort):
#1: Add priority field (无依赖)
#3: Display indicator (依赖 #1)
#5: Add selector (依赖 #1)
#7: Filter view (依赖 #1, #3)
If no open issues → print ✅ No open issues found. Nothing to do. and exit.
Step 2: Resume or Initialize
If .loop-state.json exists (from 前置检查 Check 6)
- Read the file
- Print progress summary:
📊 从检查点恢复 (上次更新: {updated_at})
✅ Shipped: #1, #3
⏭️ Skipped: #2 (question)
❌ Failed: #4 (build_failure — 3 attempts)
📋 Remaining: #5, #7
- For each
failedissue: ask user — retry or skip? - For
in_progressissues: check if branch exists, changes exist → decide resume from current state or restart - Skip all
shipped/skippedissues - Continue from first pending/retryable issue
If no state file
- Initialize new state file with all fetched issues as
pending - Start from first issue in topological order
Step 3: Process Single Issue
For each issue, print a banner:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔄 Processing Issue #{number}: {title}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
3a. Branch Prep
Prepare a clean git environment for this issue:
# 确认在 main 上
git checkout main
git pull
# 创建功能分支
git checkout -b feat/issue-{N}-{short-desc}
Branch naming: feat/issue-N-short-desc or fix/issue-N-short-desc(与 /ship-it 保持一致)
3b. 跳过或实现
阅读 issue 标题和正文。判断是否需要通过代码实现:
如果 issue 属于以下情况,则跳过:
- 问题/讨论/澄清
- 仅涉及文档(拼写错误、措辞)
- 已经实现(检查代码库)
- 与其他 issue 重复
- 明确标记为
wontfix、question、discussion或invalid - 不可执行(没有明确的验收条件,且无法推断)
如果 issue 存在尚未解决的依赖,则跳过(阻塞):
- 检查第 1 步中的依赖关系图
- 如果任何依赖 issue 尚未
shipped(仍为pending、failed、blocked,或不在状态文件中)→ 作为阻塞项跳过 - 依赖 issue 本身可能已失败或被跳过——无论哪种情况,此 issue 都无法安全推进
跳过时:
⏭️ Skipping Issue #{number}: {title}
Reason: {why}
阻塞时:
🔒 Blocking Issue #{number}: {title}
Reason: dependency #{dep_number} not shipped ({status})
更新状态:pending → skipped 或 pending → blocked,写入检查点,运行 3g 分支清理,继续处理下一个 issue。
3c. 实现(内联自主实现)
更新状态:pending → in_progress,phase: "implement",写入检查点。
由 agent 内联完成实现(本环境无 goal 命令/skill 可调用,必须自己干):
- 读取该 issue 的标题与正文,提取需求与全部验收条件(Acceptance Criteria);若正文引用了 PRD/SPEC 文件(如
tasks/prd-*.md),一并读取作为上下文 - 阅读相关现有代码,遵循项目既有风格、命名与依赖约定
- 实现/修改代码以满足全部验收条件
- 运行项目的构建、测试与 lint(如
go build ./...、go vet ./...、go test ./...) - 持续工作直到该 issue 的验收条件全部满足且测试/构建/lint 通过
不要尝试用 Skill 工具调用
goal(会报goal is a UI command, not a skill),也不要因找不到/goal而中止——实现就是你自己内联完成的工作。
成功时:
✅ Issue #{number} implementation complete
写入检查点,设置 phase: "implement_done"。
失败时——对错误分类(参见错误分类与恢复),应用恢复策略,最多重试。若用尽所有重试次数:
⚠️ Issue #{number} failed: {error_class} after {N} attempts
Manual intervention required.
更新状态:in_progress → failed,写入检查点,运行 3g 分支清理,继续处理下一个 issue。
3d. 使用 /review-it 审查
写入检查点,设置 phase: "review"。
/review-it
如果审查发现可处理的问题:
🔍 Review found N issue(s) for #{number}. Fixing...
修复每一项已接受的发现,重新运行 /review-it。重复此过程,直到审查通过或达到最多 2 轮审查。
如果审查通过:
✅ Review clean for Issue #{number}
写入检查点,设置 phase: "review_done"。
3e. 使用 /ship-it 发布
/ship-it
此操作会提交、推送、创建 PR、合并并关闭 issue。
成功时:
🚀 Issue #{number} shipped successfully!
失败时——对错误分类(参见错误分类与恢复),应用恢复策略。若无法解决:
⚠️ Issue #{number} ship failed: {error}. Manual merge required.
更新状态:in_progress → failed,设置 phase: "ship",写入检查点,运行 3g 分支清理,继续处理下一个 issue。
3f. 检查点
成功发布后,更新状态:in_progress → shipped,设置 completed_at,写入检查点。
打印进度(参见进度可观测性)。
3g. 分支清理
每个 issue 处理完成后(已发布、已跳过或失败):
# 切回 main
git checkout main
git pull
# 删除本地功能分支(仅当 shipped 时)
git branch -d feat/issue-{N}-{short-desc}
对于失败的 issue:不要删除分支。保留分支以供调查。
下一个 Issue
按拓扑顺序返回第 3 步处理下一个 issue。
处理完所有 issue 后,打印最终摘要:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Loop Complete — Summary
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Shipped: N issues (#1, #3, ...)
⏭️ Skipped: N issues (#2 — reason, #5 — reason, ...)
🔒 Blocked: N issues (#7 — depends on #4, ...)
❌ Failed: N issues (#4 — error, ...)
📋 Total: N issues
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
错误分类与恢复
发生错误时,先分类,再按策略恢复。
| 错误类别 | 检测信号 | 恢复策略 | 最大重试 |
|---|---|---|---|
| build_failure | 编译错误、undefined、类型错误 | 读取错误,修复代码,重新构建 | 3 |
| test_failure | 断言失败、test failed | 读取测试输出,修复实现,重新运行测试 | 3 |
| lint_failure | lint 错误、格式问题 | 自动修复 (lint --fix),重新运行 | 2 |
| merge_conflict | CONFLICT 标记 | rebase origin/main,解决冲突,push | 2 |
| ci_failure | gh pr checks 失败 | 读取 CI 日志,本地修复,push | 2 |
| auth_failure | 403、401、认证错误 | 停止,告知用户重新认证 | 0 |
| rate_limit | rate limit、secondary abuse | 等待 60s,重试 | 3 |
| issue_unclear | issue 无验收条件且无法推断需求 | 跳过,标记 failed | 0 |
| network_error | timeout、connection refused | 等待 30s,重试 | 3 |
| unknown | 其他情况 | 记录完整错误,跳过 | 0 |
恢复协议:
- 匹配错误类别
- 匹配成功 → 应用恢复策略,最多重试 N 次
- 全部重试失败 → 标记
failed,写入检查点,继续处理下一个 issue - 无法匹配 → 标记
failed(error_class:unknown),继续 - 绝不无限重试。绝不未经确认 force-push。
进度可观测性
每完成一个 issue 后,打印结构化进度:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Progress: 3/8 issues (37%)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Shipped: #1, #3
⏭️ Skipped: #2 (question), #6 (duplicate)
🔒 Blocked: #7 (depends on #4 — failed)
❌ Failed: #4 (build_failure — 3 attempts)
📋 Remaining: #5, #8
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
日志规则
每个关键步骤都必须打印一行带有表情符号前缀的日志:
| 表情符号 | 含义 |
|---|---|
| 📋 | 获取 / 列出 |
| 🔄 | 正在处理 issue |
| ⏭️ | 跳过 |
| 🔒 | 受阻(未提供依赖项) |
| ✅ | 成功 |
| ❌ | 失败 |
| 🔍 | 审查 |
| 🚀 | 发布 |
| ⚠️ | 警告 / 重试 |
| 📊 | 进度 / 摘要 |
安全防护措施
- 绝不强制推送到 main/master — 始终使用功能分支
- 绝不跳过审查 — 在
/ship-it之前始终运行/review-it - 每种错误类别的最大重试次数 — 参见错误分类与恢复表,不要无限重试
- 最多 2 轮审查 — 不要过度打磨
- CI 失败时暂停 — 记录日志并继续,不要自动绕过分支保护
- 保留 issue 标签 — 仅关闭已实际发布的 issue
- 绝不自动删除失败的分支 — 保留以供调查
- 每次状态转换都创建检查点 — 每次状态变更都写入检查点,不仅仅是在发布时
- 状态文件完整性 — 文件损坏时警告用户,绝不自动覆盖
- 将状态文件加入 .gitignore — 提醒用户添加
.loop-state.json - 严格按顺序处理 — 一次只处理一个 issue(实现会修改工作树,不能并行)
- 跳过受依赖阻塞的 issue — 依赖的 issue 尚未发布时,将其标记为
blocked - 由 Agent 内联完成实现 — 本环境没有可调用的
goal命令 / skill;「实现 issue」必须由 Agent 自行读取 issue、编写代码并运行测试。遇到goal is a UI command, not a skill时不要中止,直接内联实现
边缘情况
| 情况 | 处理方式 |
|---|---|
| 没有未关闭的 issue | 打印 "nothing to do" 并退出 |
| 所有 issue 都是问题 | 全部跳过,并报告摘要 |
gh 未通过身份验证 | 打印错误,建议运行 gh auth login,然后退出 |
| Issue 没有正文 | 仅根据标题决定跳过还是实现 |
| Issue 引用了 PRD/SPEC | 读取被引用的 PRD/SPEC 作为上下文,由 Agent 内联实现 |
| 多个 issue 相互依赖 | 进行拓扑排序;先处理依赖已发布的 issue |
| 开始前 Git 仓库处于脏状态 | 前置检查 Check 3:暂存 / 中止 / 强制处理 |
| 状态文件损坏(无效 JSON) | 警告用户,并提供从头开始或中止的选项。绝不自动覆盖 |
| 状态文件来自其他仓库 | 检测 repo 字段不匹配,发出警告,并提供从头开始的选项 |
上次运行留下状态为 in_progress 的 issue | 检查分支是否存在、是否有变更 → 恢复或重新开始 |
| 用户在循环中止 | 状态文件已包含最新检查点,下次运行时可恢复 |
| 循环期间创建了新 issue | 不重新获取。完成当前批次后运行新的 /loop-it |
| 循环依赖 | 打印警告,并按编号顺序打破循环 |
.loop-state.json 已被 Git 跟踪 | 警告用户将其添加到 .gitignore,然后继续 |
误以为需要外部 goal 命令 | 本环境没有此命令;「实现 issue」由 Agent 内联完成(读取 issue → 编写代码 → 测试),不要中止循环 |
与其他技能的关系
/loop-it
├── 内联实现 ← implement each issue(agent 自主读 issue、写代码、测试;非外部命令)
├── /review-it ← review code before shipping(skill)
└── /ship-it ← commit, PR, merge, close(skill)
属于 goal-workflow 流水线的一部分:
/prd → /prd-to-spec → /to-issues → /loop-it (→ 内联实现 → /review-it → /ship-it)×N