Issue-to-Beads
Converts a GitHub issue into a structured Beads work breakdown with epics, tasks, and sub-tasks - each with 3-5 objectively verifiable acceptance criteria. All beads must have relationships and dependencies mapped out.
Prerequisites
- The user's project must have Beads initialized (
bd initalready run) - The
bdCLI must be available on PATH - The
ghCLI must be authenticated for the target GitHub repo - The user should be in (or specify) the project directory containing
.beads/ - The project should have an
AGENTS.mdfile — read it first, as its acceptance criteria conventions and landing-the-plane workflow take precedence over this skill's defaults
Workflow Overview
GitHub Issue → Fetch → Branch & Worktree → Plan-Only → Work Breakdown → File Beads → Review & Refine (up to 5x) → Handoff
The skill operates in seven phases:
- Fetch — Pull the GitHub issue content and present a summary
- Branch — Create a git branch and check out a worktree for the issue
- Plan — Load the plan-only skill to explore the codebase and develop an approved plan
- Breakdown — Collaborate with the user to agree on the Beads work breakdown
- File — Create detailed Beads epics, tasks, sub-tasks, verifiable criteria, and beads relationships and dependencies
- Refine — Review, proofread, polish, and iterate (up to 5 rounds)
- Handoff — Show the tree, ready queue, and sync to git
Phase 1: Fetch the GitHub Issue
Accept any of these input formats:
- Issue number:
#42or42 - Full URL:
https://github.com/owner/repo/issues/42 - Owner/repo + number:
myorg/myrepo#42
Fetch the issue using gh:
gh issue view <number> --json title,body,labels,assignees,milestone,comments --repo <owner/repo>
If --repo is not specified, gh will use the current directory's git remote. If the fetch fails, ask the user for the correct repo.
Also fetch any linked issues or referenced PRs mentioned in the body to build context.
After fetching, present a brief summary to the user covering: the issue's goal, key requirements, constraints, and any open questions or ambiguities you noticed. This sets the stage for planning.
Phase 2: Branch & Worktree
After fetching the issue, create a dedicated branch and worktree so all Beads work happens in isolation from the main branch.
Branch Naming
Derive the branch name from the issue number and title:
<issue-number>-<slugified-title>
For example, issue #42 titled "Add user authentication" becomes 42-add-user-authentication. Keep the slug short — truncate to ~50 characters if needed.
Create Branch and Worktree
# Create the branch from the current HEAD
git branch <branch-name>
# Check out a worktree for the branch
git worktree add ../<branch-name> <branch-name>
The worktree is created as a sibling directory to the current repo. After creating it, all subsequent work (planning, filing beads, syncing) must happen inside the worktree directory.
If a branch or worktree with that name already exists, ask the user whether to reuse it or pick a different name.
Phase 3: Plan (via plan-only skill)
IMPORTANT: Do NOT use EnterPlanMode or built-in plan mode. Built-in plan mode auto-executes after approval, which is not what we want here.
Load the plan-only skill using the Skill tool:
Skill: beads-planner:plan-only
The plan-only skill will:
- Explore the codebase using Explore/Plan agents
- Develop an implementation plan
- Write it to
.claude/plans/<slug>.md - Present it to the user for approval
- Stop — no auto-execution
Once the plan-only skill completes and the user has approved the plan, copy the plan file into the project's .plan directory so it persists as a project artifact:
mkdir -p .plan
# Find the plan file that plan-only just wrote (most recent file in .claude/plans/)
ls -t .claude/plans/*.md | head -1
# Copy it with the issue-derived name
cp <plan-file> .plan/<issue-number>-<slug>.md
Use the issue number and slug from Phase 2 for the destination filename (e.g., .plan/42-add-user-authentication.md). The source file is whatever plan-only actually wrote — do not assume its slug matches the branch slug. Find the most recently created .md file in .claude/plans/ and use that.
Then proceed to Phase 4. The plan file serves as a reference for the work breakdown — it is not a trigger for implementation.
If the user rejects the plan, stop the entire workflow.
Phase 4: Work Breakdown
Using the approved plan as a foundation, propose the Beads work breakdown. This is where the plan gets translated into concrete, trackable work items.
Step 4a: Propose the Work Breakdown
Present a draft work breakdown structured as:
Epic: [Title derived from issue]
├── Task 1: [Title]
│ ├── Acceptance Criteria: [verifiable criteria]
│ └── Blocked by: —
├── Task 2: [Title]
│ ├── Acceptance Criteria: [verifiable criteria]
│ └── Blocked by: Task 1
└── Task 3: [Title]
├── Acceptance Criteria: [verifiable criteria]
└── Blocked by: — (can parallelize with Task 1)
Pay careful attention to:
- Organization: All tasks must belong to an Epic, which is effectively the top-level container for the GitHub issue.
- Dependencies: Which tasks block which? Get this right — it determines what shows up in
bd ready. - Parallelization: Tasks that are independent of each other should have no blocking dependency between them, so multiple workers can pick them up simultaneously.
- Granularity: File a bead for any work that would take longer than about 2 minutes to finish. If something is trivially quick, it can be a bullet point inside a parent task's description rather than its own bead.
- Detailed designs: Each task description should give the implementing agent enough context to start working without needing to re-read the entire GitHub issue.
Solicit feedback on the breakdown:
- Are these the right tasks?
- Is the dependency ordering correct?
- Are any tasks missing?
- Should any tasks be split or merged?
Step 4b: Refine Acceptance Criteria
Every task must have acceptance criteria that are objectively verifiable — meaning a different person (or an AI agent) could determine pass/fail without subjective judgment.
Follow the conventions from the project's AGENTS.md:
Always include as the final criterion:
- "Typecheck passes"
For tasks with testable logic, also include:
- "Tests pass"
For tasks that change UI, also include:
- "Verify in browser"
Good acceptance criteria examples:
- "Status column added to tasks table with default 'pending'"
- "Filter dropdown has options: All, Active, Completed"
- "Clicking delete shows confirmation dialog"
- "Running
npm testproduces 0 failures" - "The endpoint
GET /api/usersreturns HTTP 200 with a JSON array" - "The file
src/auth/jwt.tsexists and exports averifyTokenfunction"
Bad acceptance criteria (too vague — never use these):
- "Works correctly"
- "User can do X easily"
- "Good UX"
- "Handles edge cases"
If something is inherently subjective (like design quality), decompose it into measurable proxies:
- "The component renders without console errors"
- "Lighthouse accessibility score ≥ 90"
- "All text meets WCAG AA contrast ratio (4.5:1)"
Present the acceptance criteria to the user for approval.
Step 4c: Final Confirmation
Show the complete plan one more time with all tasks, dependencies, priorities, and acceptance criteria. Ask the user to confirm before proceeding to filing.
Phase 5: File Beads
Now grind through creating every issue in Beads. This is the execution-heavy phase — be thorough and methodical.
Beads Hierarchy
Beads uses hierarchical IDs rooted on an epic:
bd-a3f8 Epic
bd-a3f8.1 Task (child of epic)
bd-a3f8.2 Task (child of epic)
bd-a3f8.2.1 Sub-task (child of task)
Use --parent <id> when creating to place items in the hierarchy. Beads auto-assigns the dotted ID.
| Plan Element | Beads Type | bd Flag |
|---|---|---|
| Top-level work item | epic | -t epic |
| Individual work unit (>2 min) | task | -t task --parent <epic-id> |
| Smaller piece within a task | task (sub-task) | -t task --parent <task-id> |
| Bug found during analysis | bug | -t bug |
Priority Mapping
The following table is provided for completeness, only. All tasks created for GitHub issues are considered essential and, therefore, should be one of P0, P1, P2, P3. Do not use P4 as that priority level suggests the task is unnecessary.
| Priority | When to use |
|---|---|
| P0 | Blocking other teams or production |
| P1 | Core path — must be done for the issue to be considered complete |
| P2 | Important but not on the critical path |
| P3 | Nice-to-have, polish, optimization |
| P4 | Backlog / future consideration |
Creation Order
- Create the top-level epic first
- Create tasks as children of the epic
- Create sub-tasks as children of their respective tasks (if needed)
- Add
blocksdependencies between tasks - Add any
relatedordiscovered-fromlinks
Command Pattern
# 1. Create epic (returns an ID like bd-a3f8)
bd create "Epic Title" -t epic -p 1 \
-d "Description including GitHub issue reference.
Acceptance Criteria:
- [Objective criterion 1]
- [Objective criterion 2]
- Typecheck passes" \
--json
# 2. Create tasks under epic (auto-assigns bd-a3f8.1, bd-a3f8.2, etc.)
bd create "Task Title" -t task -p 1 \
--parent <epic-id> \
-d "Detailed description of what to implement and how.
Acceptance Criteria:
- [Objective criterion 1]
- [Objective criterion 2]
- Typecheck passes" \
--json
# 3. Create sub-tasks under a task if needed (auto-assigns bd-a3f8.1.1, etc.)
bd create "Sub-task Title" -t task -p 1 \
--parent <task-id> \
-d "Focused piece of work within the parent task.
Acceptance Criteria:
- [Objective criterion 1]
- Typecheck passes" \
--json
# 4. Add blocking dependencies
bd dep add <blocked-task-id> <blocker-task-id> --type blocks
# 5. Add discovered-from links (if applicable)
bd dep add <new-issue-id> <source-issue-id> --type discovered-from
Description Format
Every Beads issue description must follow this structure:
[Detailed functional description of what needs to be done.
Include enough context that a worker agent can start implementing
without re-reading the full GitHub issue. Mention specific files,
functions, APIs, or patterns to use where relevant.]
Source: GitHub Issue <owner>/<repo>#<number>
Acceptance Criteria:
- [Objective criterion 1]
- [Objective criterion 2]
- Typecheck passes
Dependency Best Practices
- Tasks that produce artifacts consumed by later tasks get
blocksdependencies - Tasks within the same phase that are independent get no dependency — this enables parallelization
- All child tasks get
parent-childlinks to their epic automatically via--parent - Use
discovered-fromfor bugs or follow-up work found during analysis
Phase 6: Review & Refine
This phase is critical for quality. After filing all the beads, step back and do a thorough review. The goal is to ensure that worker agents will have as smooth a time as possible when they pick up these tasks.
Review Checklist
For each bead, check:
- Clarity: Could a worker agent understand what to do without asking questions?
- Acceptance criteria: Are they truly objectively verifiable? No vague language?
- Standard criteria included: Does every task end with "Typecheck passes"? Do testable tasks include "Tests pass"? Do UI tasks include "Verify in browser"?
- Dependencies: Are all blocking relationships correct? Are parallelizable tasks actually unblocked from each other?
- Descriptions: Do they include enough detail about files, functions, and approach?
- Granularity: Is every bead scoped to more than ~2 minutes of work? Are any too large and should be split?
- Titles: Are they clear and specific enough to understand at a glance in
bd readyoutput? - Priorities: Do they accurately reflect importance and critical path?
Iteration Loop
After each review pass, make updates using bd update:
# Fix a description or acceptance criteria
bd update <id> -d "Improved description..." --json
# Fix priority
bd update <id> -p <new-priority> --json
# Add a missing dependency
bd dep add <blocked-id> <blocker-id> --type blocks
# Add a missing task discovered during review
bd create "Newly discovered task" -t task --parent <epic-id> -p 2 \
-d "Description...
Acceptance Criteria:
- [criteria]
- Typecheck passes" --json
Repeat this review-and-refine cycle up to 5 times. Each pass should focus on progressively finer details:
- Pass 1: Structural correctness — are the right tasks present with correct dependencies?
- Pass 2: Description quality — are descriptions detailed enough for a cold-start worker?
- Pass 3: Acceptance criteria rigor — are all criteria truly objective and verifiable?
- Pass 4: Parallelization opportunities — can any blocking deps be removed to enable more concurrent work?
- Pass 5: Final polish — titles, priorities, consistency, anything remaining
After each pass, briefly note what was changed. Stop early if a pass produces no meaningful improvements — say "I don't think we can do much better than this" and move on to handoff.
Phase 7: Handoff
Once refinement is complete:
- Run
bd syncto ensure the JSONL index reflects all Phase 6 changes - Run
bd dep tree <epic-id>to show the user the full hierarchy - Run
bd ready --jsonto show what's immediately actionable - Summarize what was created: epic count, task count, dependency count, how many tasks are parallelizable
- Invoke the git-push-and-tag skill to stage, commit, push, and label the issue:
Skill: beads-planner:git-push-and-tag
Work is NOT complete until the skill finishes successfully. Never stop before pushing — that leaves work stranded locally.
Edge Cases
- Tiny issues (single task, no decomposition needed): One epic, one task. Still include acceptance criteria with "Typecheck passes" as the final criterion.
- Enormous issues (20+ tasks): Suggest breaking the GitHub issue into multiple Beads epics, each with its own task hierarchy. Ask the user how they'd like to group them.
- Vague issues (missing requirements): Use Phase 4 aggressively to fill gaps. Create "Research" or "Spike" tasks for unknowns with acceptance criteria like "A decision document exists at
docs/decisions/001-auth-approach.mdwith Status, Context, Decision, and Consequences sections." - Issues with existing Beads work: Run
bd list --jsonto check for duplicates before creating. Alert the user if overlap is found.
Reference
For detailed Beads CLI syntax and advanced patterns, read references/beads-cli-reference.md.
