Agent skill
epic-management
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.
Install this agent skill to your Project
npx add-skill https://github.com/troykelly/codex-skills/tree/main/skills/epic-management
SKILL.md
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 label
gh 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 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"
Step 3.5: Set Project Board Fields (MANDATORY)
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_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; then
if gh project field-list "$GITHUB_PROJECT_NUM" --owner "$GH_PROJECT_OWNER" --format json | jq -e '.fields[] | select(.name == "Issue Type")' >/dev/null 2>&1; then
TYPE_FIELD_NAME="Issue Type"
fi
fi
TYPE_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 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 --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 = 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
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 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
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 issues
issues 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 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]"
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
## 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"
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
## 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"
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
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
hook-development
Use when the user wants to create Codex workflow hooks (pre/post run gates, tool-use validators, stop checks) or needs guidance on hook scripts and hooks.json configuration.
sentry-setup-ai-monitoring
Setup Sentry AI Agent Monitoring in any project. Use this when asked to add AI monitoring, track LLM calls, monitor AI agents, or instrument OpenAI/Anthropic/Vercel AI/LangChain/Google GenAI. Automatically detects installed AI SDKs and configures the appropriate Sentry integration.
agent-development
Use when the user wants to design Codex agent equivalents (specialized workers/profiles/prompt files), define triggering conditions, or build reusable agent prompts and validation tools.
skill-development
Use when the user wants to create or refine Codex skills, improve skill descriptions, organize skill resources, or follow Codex skill best practices.
sentry-setup-logging
Setup Sentry Logging in any project. Use this when asked to add Sentry logs, enable structured logging, setup console log capture, or integrate logging with Sentry. Supports JavaScript, TypeScript, Python, Ruby, React, Next.js, and other frameworks.
frontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Didn't find tool you were looking for?