skills/pick-epic/SKILL.md
Execute an epic by running children in dependency-ordered waves using parallel subagents, one isolated worktree and PR per issue, squash-merging as CI and automated reviews (CodeRabbit + Copilot) pass. Use when user types /pick-epic or asks to execute an epic with parallel agents.
npx skillsauth add jamesc/skills pick-epicInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Execute an epic by grouping its children into dependency-ordered waves and running each wave as parallel subagents, one per issue. Each issue gets its own isolated worktree, its own PR (squash-merged to main), and is merged as soon as CI passes and automated reviews (CodeRabbit + Copilot) are satisfied. Waves are sequential — Wave N+1 starts only after all Wave N PRs are merged.
Key difference from /do-refactor: This skill uses isolated worktrees and parallel subagents for maximum throughput — one PR per issue, not one PR for the whole epic. Use this for any L/XL epic where issues touch non-overlapping files.
streamlinear-cli get BT-XXX
Then fetch all child issues with their blocking relationships and sizes:
streamlinear-cli graphql "query {
issue(id: \"<epic-node-id>\") {
children {
nodes {
id identifier title state { name }
labels { nodes { name } }
relations { nodes { type relatedIssue { identifier state { name } } } }
}
}
}
}"
Done or In Progressneeds-spec label — tell the user which ones need specDone (the epic has unresolved external dependencies)agent-ready label is present on all workable childrenGroup children into waves using these rules:
Wave assignment:
Conflict check: Within a wave, scan file overlap between issues. If two issues in the same wave touch the same files, push the lower-priority one to the next wave.
Present the wave plan and proceed immediately — no confirmation needed:
Wave 1 (parallel): BT-XXX (S), BT-YYY (M), BT-ZZZ (M)
Wave 2 (parallel): BT-AAA (L), BT-BBB (L)
Wave 3 (parallel): BT-CCC (XL)
Only pause if dependency ordering is ambiguous (e.g. two issues block each other, or a blocker is not in this epic).
For each wave:
4a. Launch one subagent per issue in the wave (all in parallel):
Use Agent tool with isolation: "worktree" and run_in_background: true for every issue in the wave simultaneously. Each agent receives a complete self-contained prompt (see Agent Prompt Template below).
4b. Wait for all agents in the wave to complete.
4c. For each completed agent:
gh pr view <PR> --json statusCheckRollupgh api repos/<owner>/<repo>/pulls/<PR>/reviews \
--jq '[.[] | select(.user.login | test("copilot|coderabbit"; "i")) | {user: .user.login, state}]'
COMMENTED (never blocking), but their findings are valuable:
gh api -X PUT repos/<owner>/<repo>/pulls/<PR>/reviews/<review-id>/dismissals -f message="..." to dismiss blocking reviewsgh pr merge <PR> --squash --admin
git worktree remove --force <worktree-path>
git branch -D <branch-name>
4d. Once all PRs in the wave are merged, start Wave N+1.
After each PR is merged:
streamlinear-cli update BT-YYY --state Done
After all waves complete:
streamlinear-cli update BT-XXX --state Done
streamlinear-cli comment BT-XXX "All child issues completed in <N> waves. PRs: #P1, #P2, ..."
## Epic Complete: BT-XXX — <title>
Wave 1: BT-AAA (#PR1, merged), BT-BBB (#PR2, merged)
Wave 2: BT-CCC (#PR3, merged), BT-DDD (#PR4, merged)
Total: X issues, Y PRs, merged in Z waves.
Follow-up issues created: BT-NNN (<title>), BT-MMM (<title>)
When spawning a subagent for an issue, use this template. Fill in all fields from the Linear issue:
Work on <BT-NNN> using the standard skill chain: /pick-issue → /review-code → /done.
1. `/pick-issue BT-NNN` — loads issue, creates branch, sets In Progress, implements
2. `/review-code` — multi-pass review, fix any 🔴/🟡 findings
3. `/done` — commit, push, create PR
**IMPORTANT: In /done, the bot-review gate (step 12) will wait up to 10 minutes
for Copilot / CodeRabbit reviews and may HALT** if unresolved findings remain,
prompting you to resolve (chain to /resolve-pr), dismiss with reason, or override
with the literal phrase `merge anyway`. The parent agent owns CI watching, review
handling, and merging — but expect /done to block at the gate when bots find
something. Pick override only if you've audited the findings and accepted the
risk; the override is logged in the final report.
That's it — keep the prompt minimal. /pick-issue and /done already contain all the rules (license headers, CLAUDE.md guidelines, test commands, commit format). No need to repeat them.
When a subagent's PR has a CI failure:
gh pr view <PR> --json statusCheckRollupgh api repos/<owner>/<repo>/actions/jobs/<job-id>/logsCommon cross-platform issues:
String vs &str when a #[cfg(windows)] rebind creates an owned valueCopilot reviews are COMMENTED (non-blocking) but contain valuable findings. Do not skip them.
gh api repos/<owner>/<repo>/pulls/<PR>/reviews/<review-id>/comments \
--jq '[.[] | {id, path, body: .body[:200]}]'
| Finding type | Action | |---|---| | Bug introduced by this PR | Fix it, push a commit, reply with fix hash | | Valid improvement, small scope | Fix it inline if < 10 lines | | Valid improvement, large scope | Create a follow-up Linear issue, reply with issue link | | Pre-existing code | Reply: "Pre-existing, not introduced by this PR" | | False positive / style nitpick | Skip — no reply needed |
gh api repos/<owner>/<repo>/pulls/<PR>/comments/<comment-id>/replies \
-f body="Fixed in <commit-hash>"
CodeRabbit may block merging with CHANGES_REQUESTED. Evaluate each finding:
| Finding type | Action |
|---|---|
| Bug introduced by this PR | Fix it, push a commit |
| Scope creep added by the agent | Remove the extra code, push a commit |
| Pre-existing code (exists on main) | Dismiss: "Pre-existing, not introduced by this PR" |
| Valid improvement, large scope | Create a Linear issue, add it as a child of the epic, then dismiss: "Tracked as <BT-NNN>" |
When creating a follow-up issue for a valid-but-out-of-scope finding, use /create-issue and set the epic as its parent. Collect all follow-up issues created during the epic and report them at the end — don't interrupt the wave flow to work on them.
Dismiss blocking reviews via the GitHub API:
gh api -X PUT repos/<owner>/<repo>/pulls/<PR>/reviews/<review-id>/dismissals \
-f message="<reason>"
Then re-attempt merge.
| Epic size | Expected waves | Typical parallelism | |---|---|---| | 3–5 issues | 1–2 waves | 3–5 parallel | | 6–10 issues | 2–3 waves | 3–5 parallel per wave | | 10+ issues | 3+ waves | Cap at 5 parallel (context overhead) |
Never run more than 5 subagents in a single wave — context overhead degrades quality beyond that.
Stop and ask the user for guidance if:
tools
Find the next logical piece of work. Use when user types /whats-next or asks what they should work on next, or wants recommendations for the next task.
development
Use when navigating code, finding references, looking up definitions, understanding types, or tracing call hierarchies in TypeScript, Rust, or Beamtalk (.bt) files. Prefer LSP over Grep/Glob for any navigation task where symbol semantics matter.
data-ai
Find and update Linear issues that need labels, blocking relationships, or metadata. Use when user says '/update-issues' with criteria like 'no labels', 'missing agent-ready', 'needs size', etc.
data-ai
Sync modified skills and agents back to the repo and create a PR. Use when user types /sync-skills or wants to save in-session skill improvements.