GitHub Project Scoping
Use this skill to turn a high-level goal ("build a user authentication system") into a concrete, ordered set of GitHub issues with a milestone, proper labels, and cross-references. The output is a fully-created GitHub milestone with all issues filed.
Prerequisites
gh auth status # must be authenticated gh repo view # must be inside a git repo with a GitHub remote
Scoping Workflow Overview
- Understand the goal
- Identify the milestone (or create one)
- Decompose into issues
- Validate the scope with the user
- Create labels
- Create the milestone
- Create issues in dependency order
- Cross-reference related issues
- Print the summary
Step 1 — Understand the Goal
Ask the user for:
Question Why it matters
What is the end-user outcome when this project is done? Keeps issues outcome-focused, not task-focused
What is explicitly out of scope for this project? Prevents unbounded scope during decomposition
Is there a target release date or sprint? Informs milestone due date
Are there known dependencies or constraints? Surfaces blockers early
Who is the primary audience — users, developers, or operators? Shapes how acceptance criteria are written
Step 2 — Decompose Into Issues
Break the goal into the smallest independently shippable units of work. Each issue must:
-
Be completable without requiring another issue in this project to merge first (or have an explicit dependency noted)
-
Have clear acceptance criteria on its own
-
Represent a meaningful increment — not a micro-task like "write a test" unless that's genuinely isolated work
Decomposition patterns
Feature slice (recommended default): cut vertically through the stack for each user-visible capability.
❌ "Build the database layer" ← horizontal, not shippable alone ✓ "User can register with email" ← vertical, delivers value
Dependency chain: when sequential work is unavoidable, make dependencies explicit.
Issue 1: Set up database schema for users Issue 2: Implement registration API (depends on #1) Issue 3: Build registration UI (depends on #2)
Spike: when the right approach is unknown, create a time-boxed investigation issue.
Title: "Spike: evaluate auth library options (2h timebox)" Acceptance criteria: Decision documented in issue comments with recommendation
Typical issue count
Project size Issues Milestone duration
Small feature 2–5 1–2 sprints
Medium feature 5–10 2–4 sprints
Large feature / epic 10–20 1–2 quarters
If decomposition yields more than 20 issues, the scope is too large — split into multiple milestones.
Step 3 — Validate With the User
Before creating anything, present the full plan:
Milestone: <name> (due: <date or TBD>)
Issues:
- [type: feature, size: small] "Set up database schema for users"
- [type: feature, size: medium] "Implement registration API" (depends on #1)
- [type: feature, size: medium] "Build registration UI" (depends on #2)
- [type: chore, size: small] "Add integration tests for registration flow"
- [type: docs, size: small] "Document registration API endpoints"
Total estimated size: ~3 days of focused work
Ask: "Does this capture everything? Anything missing or out of scope?"
Make adjustments before proceeding. Do not create issues until the user confirms.
Step 4 — Create the Milestone
Check if the milestone already exists
gh milestone list
Create it (due-on is optional, format: YYYY-MM-DDTHH:MM:SSZ)
gh api repos/{owner}/{repo}/milestones
--method POST
--field title="<milestone name>"
--field description="<one-line description of what this milestone delivers>"
--field due_on="<YYYY-MM-DDTHH:MM:SSZ>"
Note the milestone number from the response — you'll need it when creating issues.
Step 5 — Create Labels
Check which labels exist and create any missing ones:
gh label list
Standard label sets — see gh-issue skill for the full table. Create missing labels:
gh label create "type: feature" --color "0075ca" --description "New capability" gh label create "size: small" --color "c2e0c6" --description "Under 4 hours" gh label create "size: medium" --color "fef2c0" --description "4–16 hours" gh label create "size: large" --color "f9d0c4" --description "Over 16 hours"
Step 6 — Create Issues in Dependency Order
Create issues starting with those that have no dependencies. Use the gh-issue skill's body template for each:
gh issue create
--title "<title>"
--body "$(cat <<'BODY'
Background
<why this issue exists in the context of the project>
Acceptance Criteria
- <criterion>
- <criterion>
Out of Scope
- <item>
Technical Notes
Part of milestone: <milestone name>
BODY
)"
--label "type: feature,size: medium"
--milestone "<milestone name>"
Capture each issue number after creation. gh issue create outputs the URL — extract the number from it.
Step 7 — Add Cross-References
After all issues exist, edit any that have dependencies to add references:
gh issue edit <number> --body "$(gh issue view <number> --json body --jq .body)
Depends on: #<other-number>"
For issues that are blocked by another:
Add a note to the blocked issue
gh issue comment <blocked-number> --body "Blocked by #<blocking-number> — will begin after that merges."
GitHub automatically creates backlinks when you reference an issue number, so both issues surface the relationship.
Step 8 — Print the Summary
After all issues are created, output a summary the user can paste into a project doc or team channel:
<Milestone Name>
Milestone: <URL>
| # | Title | Labels | Size |
|---|---|---|---|
| #1 | Set up database schema | type: feature | small |
| #2 | Implement registration API | type: feature | medium |
| #3 | Build registration UI | type: feature | medium |
| #4 | Integration tests | type: chore | small |
| #5 | Document API endpoints | type: docs | small |
Total issues: 5 | Estimated: ~3 days
Keeping Issues Focused
As you draft each issue, apply these checks:
-
The title is a complete thought: "Add password reset flow" not "Password reset"
-
Acceptance criteria are outcomes, not tasks: "User receives a reset email within 30 seconds" not "Call SendGrid API"
-
Each issue could be assigned to a different person: if coupling is so tight that two issues must go to the same person, consider merging them
-
The out-of-scope section names at least one thing: forces explicit boundary-drawing
Common Pitfalls
-
Creating the milestone last: create it first so you can attach issues as you go.
-
Circular dependencies: if A depends on B and B depends on A, merge them into one issue.
-
Forgetting non-feature work: chores (migrations, config), tests, and docs are real work — include them in the scope.
-
Skipping the validation step: creating 15 issues and then restructuring them is painful. Always confirm the plan first.
-
No out-of-scope on the milestone: add a "What this milestone does NOT include" section to the milestone description to prevent scope creep at the project level.