Skill v1.0.1
currentAutomated scan100/1001 files
version: "1.0.1" name: epic-management description: Use for LARGE work requiring feature-level grouping. Creates epic tracking issues, manages related issues under a common label, tracks epic progress, and coordinates with milestones.
Epic Management
Overview
An epic groups related issues that together deliver a feature or capability. This skill creates, tracks, and manages epics using GitHub's native features.
Core principle: An epic is a collection of issues that together deliver user value.
Announce at start: "I'm using epic-management to structure this feature into a tracked epic with related issues."
What is an Epic?
An epic is:
- A parent issue with the
epiclabel - A collection of related issues sharing an
epic-[name]label - Optionally associated with a milestone
- Part of an initiative (if the work is massive)
Epic Structure in GitHub
Epic (Parent Issue)├── Label: epic├── Label: epic-[name]├── Milestone: [optional]└── Project: [with epic fields]Related Issues├── Label: epic-[name]├── Reference: "Part of #[EPIC_NUMBER]"└── Milestone: [same as epic]
Creating an Epic
Step 1: Create Epic Label
# Create the epic-specific labelgh label create "epic-[SHORT-NAME]" \--color "0E8A16" \--description "[Brief description of epic goal]"
Step 2: Create Epic Tracking Issue
gh issue create \--title "[Epic] [NAME]" \--label "epic,epic-[SHORT-NAME]" \--body "## Epic: [NAME]## Goal[What this epic delivers when complete]## Success Criteria- [ ] [High-level criterion 1]- [ ] [High-level criterion 2]- [ ] [High-level criterion 3]## Context[Background, why this epic exists, any relevant links]## Dependencies- **Requires:** [Other epics/issues that must complete first]- **Enables:** [Other epics/issues that depend on this]## Issues### Ready- [ ] #[N] - [Title]### In Progress[None yet]### Done[None yet]## Progress**Issues:** 0 / [TOTAL] complete**Last Updated:** [DATE]---## Initiative[Part of #[INITIATIVE] if applicable, or 'Standalone epic']## Milestone[Associated milestone or 'Not assigned']"
Step 3: Add to Project Board (MANDATORY GATE)
This step is NOT optional. Epics MUST be in the project board.
# Get the epic issue URLEPIC_URL=$(gh issue view [EPIC_NUMBER] --json url -q '.url')# Add epic to project - REQUIREDgh project item-add "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --url "$EPIC_URL"if [ $? -ne 0 ]; thenecho "ERROR: Failed to add epic to project. Cannot proceed."exit 1fi# Get the item ID - REQUIREDITEM_ID=$(gh project item-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r ".items[] | select(.content.number == [EPIC_NUMBER]) | .id")if [ -z "$ITEM_ID" ] || [ "$ITEM_ID" = "null" ]; thenecho "ERROR: Epic added but item ID not found."exit 1fiecho "Epic #[EPIC_NUMBER] added to project with item ID: $ITEM_ID"
Step 3.5: Set Project Board Fields (MANDATORY)
All epics must have Type = Epic set in project board.
# Get project and field IDsPROJECT_ID=$(gh project list --owner "$GH_PROJECT_OWNER" --format json | \jq -r ".projects[] | select(.number == $GITHUB_PROJECT_NUM) | .id")STATUS_FIELD_ID=$(gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r '.fields[] | select(.name == "Status") | .id')TYPE_FIELD_NAME="Type"if ! gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --format json | jq -e '.fields[] | select(.name == "Type")' >/dev/null 2>&1; thenif gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --format json | jq -e '.fields[] | select(.name == "Issue Type")' >/dev/null 2>&1; thenTYPE_FIELD_NAME="Issue Type"fifiTYPE_FIELD_ID=$(gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r --arg type_field "$TYPE_FIELD_NAME" '.fields[] | select(.name == $type_field) | .id')# Get option IDsBACKLOG_OPTION_ID=$(gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r '.fields[] | select(.name == "Status") | .options[] | select(.name == "Backlog") | .id')EPIC_TYPE_OPTION_ID=$(gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r --arg type_field "$TYPE_FIELD_NAME" '.fields[] | select(.name == $type_field) | .options[] | select(.name == "Epic") | .id')# Set Status = Backlog (or Ready if no issues yet to create)gh project item-edit --project-id "$PROJECT_ID" --id "$ITEM_ID" \--field-id "$STATUS_FIELD_ID" --single-select-option-id "$BACKLOG_OPTION_ID"# Set Type = Epicgh project item-edit --project-id "$PROJECT_ID" --id "$ITEM_ID" \--field-id "$TYPE_FIELD_ID" --single-select-option-id "$EPIC_TYPE_OPTION_ID"# Verify fields were setecho "Verifying project board fields..."VERIFY=$(gh project item-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq ".items[] | select(.content.number == [EPIC_NUMBER])")echo "Status: $(echo "$VERIFY" | jq -r '.status.name')"echo "Type: $(echo "$VERIFY" | jq -r '.type.name // "not set"')"
Skill: project-board-enforcement
Creating Issues Within an Epic
Issue Template for Epic Issues
gh issue create \--title "[TYPE] [Title]" \--label "epic-[SHORT-NAME]" \--body "## Description[What this issue delivers]Part of epic #[EPIC_NUMBER]: [Epic Title]## Acceptance Criteria- [ ] [Criterion 1]- [ ] [Criterion 2]## Technical Notes[Any implementation details]## Dependencies- Requires: #[N] (if any)- Blocks: #[N] (if any)"
Linking Issues to Epic
Every issue in an epic must:
- Have the
epic-[name]label - Reference the epic in description: "Part of epic #[N]"
- Share the same milestone (if set)
- Be in the project board with Status and Type set
- Have Epic field set to parent epic number (if field exists)
Adding Child Issues to Project Board (MANDATORY)
# After creating child issue, add to project boardCHILD_URL=$(gh issue view [CHILD_NUMBER] --json url -q '.url')gh project item-add "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --url "$CHILD_URL"# Get item IDCHILD_ITEM_ID=$(gh project item-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r ".items[] | select(.content.number == [CHILD_NUMBER]) | .id")# Set Status = Readygh project item-edit --project-id "$PROJECT_ID" --id "$CHILD_ITEM_ID" \--field-id "$STATUS_FIELD_ID" --single-select-option-id "$READY_OPTION_ID"# Set Type (Feature, Bug, etc. as appropriate)gh project item-edit --project-id "$PROJECT_ID" --id "$CHILD_ITEM_ID" \--field-id "$TYPE_FIELD_ID" --single-select-option-id "$TYPE_OPTION_ID"# Link to parent epic (if Epic field exists)EPIC_FIELD_ID=$(gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \--format json | jq -r '.fields[] | select(.name == "Epic") | .id')if [ -n "$EPIC_FIELD_ID" ] && [ "$EPIC_FIELD_ID" != "null" ]; thengh project item-edit --project-id "$PROJECT_ID" --id "$CHILD_ITEM_ID" \--field-id "$EPIC_FIELD_ID" --text "#[EPIC_NUMBER]"fi
Skill: project-board-enforcement
Tracking Epic Progress
Update Epic Issue Regularly
When issues change status, update the epic:
gh issue comment [EPIC_NUMBER] --body "## Progress Update - [DATE]**Completed:** #[N] - [Title]**Current Status:**- Ready: [X] issues- In Progress: [Y] issues- Done: [Z] issues- Total: [X+Y+Z] / [TOTAL]**Next up:** #[N] - [Title]"
Reorganize Epic Body
Keep the epic body current:
## Issues### Ready-[ ] #102 - Database schema-[ ] #103 - API endpoints### In Progress-[ ] #101 - Initial setup (assignee: @dev)### Done-[x] #100 - Research spike## Progress**Issues:** 1 / 4 complete (25%)**Last Updated:** 2025-12-02
Epic Lifecycle
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐│ Planning │────▶│ Active │────▶│ Closing │────▶│ Done │└────────────┘ └────────────┘ └────────────┘ └────────────┘│ │ │ │▼ ▼ ▼ ▼Creating Issues Last issues All issuesissues in progress completing closed
Epic States
| State | Project Status | Indicators | |
|---|---|---|---|
| Planning | Backlog | Issues being created, no work started | |
| Active | In Progress | At least one issue in progress | |
| Closing | In Review | All issues done or in review | |
| Done | Done | All issues closed, epic closed |
Completing an Epic
Pre-Completion Checklist
Before closing an epic:
- [ ] All issues in epic are closed
- [ ] Success criteria in epic are checked off
- [ ] Any dependent epics are updated
- [ ] Initiative (if any) is notified
Close the Epic
# Final progress updategh issue comment [EPIC_NUMBER] --body "## Epic Complete 🎉**All issues resolved:**- [x] #100 - Research spike- [x] #101 - Initial setup- [x] #102 - Database schema- [x] #103 - API endpoints**Success criteria met:**- [x] Criterion 1- [x] Criterion 2- [x] Criterion 3**Completed:** [DATE]**Duration:** [X days/weeks]"# Close the epicgh issue close [EPIC_NUMBER]# Update initiative if applicablegh issue comment [INITIATIVE_NUMBER] --body "## Epic Complete: #[EPIC_NUMBER][Epic Name] is now complete. [X] issues resolved.**Remaining epics:** [List]"
Epic Dependencies
Documenting Dependencies
In the epic body:
## Dependencies### This Epic Requires-#[EPIC_A] - [Title] - **Status:** [Done/In Progress]-Blocked items in this epic: #101, #102### This Epic Enables-#[EPIC_B] - [Title] - Will unblock when this completes
Managing Blocked Issues
When an issue is blocked by another epic:
gh issue edit [ISSUE_NUMBER] --add-label "blocked"gh issue comment [ISSUE_NUMBER] --body "**Blocked by:** Epic #[OTHER_EPIC]Waiting for: #[SPECIFIC_ISSUE] to complete.Will unblock when: [Condition]"
Epic Without Initiative
For standalone epics (not part of a larger initiative):
gh issue create \--title "[Epic] [NAME]" \--label "epic,epic-[SHORT-NAME]" \--body "## Epic: [NAME]## Goal[What this epic delivers]## Success Criteria- [ ] [Criterion 1]- [ ] [Criterion 2]## Issues[To be created]## Progress**Issues:** 0 / 0 complete---**Type:** Standalone epic**Milestone:** [If applicable]"
Example: Dark Mode Epic
Create Epic
gh label create "epic-dark-mode" --color "1D76DB" \--description "Dark mode theme implementation"gh issue create \--title "[Epic] Dark Mode Support" \--label "epic,epic-dark-mode" \--milestone "Q1 2026" \--body "## Epic: Dark Mode Support## GoalUsers can toggle between light and dark themes, with preference persistence.## Success Criteria- [ ] Theme toggle in settings- [ ] All components respect theme- [ ] Preference persists across sessions- [ ] System preference detection## Issues### Ready- [ ] #201 - Design tokens for dark theme- [ ] #202 - Theme context provider- [ ] #203 - Settings toggle UI- [ ] #204 - Component theme updates- [ ] #205 - Preference persistence- [ ] #206 - System preference detection## Progress**Issues:** 0 / 6 complete**Last Updated:** 2025-12-02"
Create Issues
gh issue create \--title "[Feature] Design tokens for dark theme" \--label "epic-dark-mode,feature" \--body "Part of epic #200: Dark Mode Support## DescriptionCreate CSS custom properties for dark theme colors.## Acceptance Criteria- [ ] Dark theme color palette defined- [ ] CSS variables for all theme colors- [ ] Documentation of token usage"
Memory Integration
mcp__memory__create_entities([{"name": "Epic-[NAME]","entityType": "Epic","observations": ["Created: [DATE]","Goal: [GOAL]","Issue: #[NUMBER]","Label: epic-[SHORT-NAME]","Status: [Planning/Active/Done]","Issues: [COUNT]","Initiative: #[N] or Standalone"]}])
Checklist
- [ ] Created epic-specific label
- [ ] Created epic tracking issue
- [ ] Added epic to project board (VERIFIED with ITEM_ID)
- [ ] Set project Status = Backlog or Ready
- [ ] Set project Type = Epic
- [ ] Defined success criteria
- [ ] Documented dependencies
- [ ] Created initial issues with epic label
- [ ] Added all child issues to project board
- [ ] Set Status and Type for all child issues
- [ ] Linked children to epic (Epic field if available)
- [ ] Set milestone (if applicable)
- [ ] Linked to initiative (if applicable)
- [ ] Stored in knowledge graph
Gate: Cannot create child issues or begin work without epic and all issues in project board.
Skill: project-board-enforcement