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.
Creates and manages epics that group related issues for feature-level work tracking.
/plugin marketplace add troykelly/claude-skills/plugin install issue-driven-development@troykelly-skillsThis skill is limited to using the following tools:
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."
An epic is:
epic labelepic-[name] labelEpic (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]
# Create the epic-specific label
gh label create "epic-[SHORT-NAME]" \
--color "0E8A16" \
--description "[Brief description of epic goal]"
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']"
This step is NOT optional. Epics MUST be in the project board.
# Get the epic issue URL
EPIC_URL=$(gh issue view [EPIC_NUMBER] --json url -q '.url')
# Add epic to project - REQUIRED
gh project item-add "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --url "$EPIC_URL"
if [ $? -ne 0 ]; then
echo "ERROR: Failed to add epic to project. Cannot proceed."
exit 1
fi
# Get the item ID - REQUIRED
ITEM_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" ]; then
echo "ERROR: Epic added but item ID not found."
exit 1
fi
echo "Epic #[EPIC_NUMBER] added to project with item ID: $ITEM_ID"
All epics must have Type = Epic set in project board.
# Get project and field IDs
PROJECT_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_ID=$(gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" \
--format json | jq -r '.fields[] | select(.name == "Type") | .id')
# Get option IDs
BACKLOG_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 '.fields[] | select(.name == "Type") | .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 = Epic
gh 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 set
echo "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
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)"
Every issue in an epic must:
epic-[name] label# After creating child issue, add to project board
CHILD_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 ID
CHILD_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 = Ready
gh 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" ]; then
gh project item-edit --project-id "$PROJECT_ID" --id "$CHILD_ITEM_ID" \
--field-id "$EPIC_FIELD_ID" --text "#[EPIC_NUMBER]"
fi
Skill: project-board-enforcement
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]"
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
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ Planning │────▶│ Active │────▶│ Closing │────▶│ Done │
└────────────┘ └────────────┘ └────────────┘ └────────────┘
│ │ │ │
▼ ▼ ▼ ▼
Creating Issues Last issues All issues
issues in progress completing closed
| 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 |
Before closing an epic:
# Final progress update
gh 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 epic
gh issue close [EPIC_NUMBER]
# Update initiative if applicable
gh issue comment [INITIATIVE_NUMBER] --body "## Epic Complete: #[EPIC_NUMBER]
[Epic Name] is now complete. [X] issues resolved.
**Remaining epics:** [List]"
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
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]"
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]"
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
## Goal
Users 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"
gh issue create \
--title "[Feature] Design tokens for dark theme" \
--label "epic-dark-mode,feature" \
--body "Part of epic #200: Dark Mode Support
## Description
Create CSS custom properties for dark theme colors.
## Acceptance Criteria
- [ ] Dark theme color palette defined
- [ ] CSS variables for all theme colors
- [ ] Documentation of token usage"
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"
]
}])
Gate: Cannot create child issues or begin work without epic and all issues in project board.
Skill: project-board-enforcement
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.