| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| Category | petmedi-workflow |
| Complexity | moderate |
| MCP Servers | zenhub, sequential |
/zenhub:epic#
Context Framework Note: This command creates ZenHub Epic/Story based on feature requirements.
Triggers#
- When creating issues from feature requirements
- When called from
/figma:analyzePhase 4 - When manually creating ZenHub issues
Context Trigger Pattern#
/zenhub:epic {feature_name} {entity_name} [--options]
Parameters#
Required Parameters#
| Parameter | Description | Example |
|---|---|---|
feature_name | Feature name (snake_case) | community |
entity_name | Entity name (PascalCase) | Post |
Image Analysis Options (Optional)#
| Parameter | Description | Example |
|---|---|---|
--images |
Image files to analyze (comma-separated) | "list.png,detail.png,form.png" |
--images-dir | Image directory path | ./screenshots/ |
--attach-images |
Attach to Issue after committing to repo (default: false) | true/false |
--min-confidence |
Minimum confidence for screen type identification (default: 70%) | 80 |
--skip-analysis | Skip image analysis | true/false |
--no-cache | Ignore cache and re-analyze | true/false |
Other Options (Optional)#
| Parameter | Description | Example |
|---|---|---|
--requirements |
Requirements document path | claudedocs/community/requirements.md |
--bdd-dir |
BDD scenario directory | claudedocs/community/bdd/ |
--labels | Additional labels | "sprint-1,mvp" |
--screens | Screens to generate | "list,detail,form" |
--points | Story Point setting | "3,3,5" |
--sprint | Sprint assignment | "current" |
Workspace Info Query (required โ before Step 0)#
Issue Type ID, Repository ID, and Pipeline ID differ per workspace.
Dynamically query based on the workspace configured in .mcp.json at the project root:
// 1. Repository ID + Pipeline ID
const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();
const repoId = workspace.repositories.find(r = > /* GitHub ๋ ํฌ ์ ํ */).id;
// 2. Issue Type ID
const issueTypes = await mcp__zenhub__getIssueTypes();
const epicTypeId = issueTypes.find(t = > t.name === " Epic " ).id;
const featureTypeId = issueTypes.find(t = > t.name === " Feature " ).id;
const subtaskTypeId = issueTypes.find(t = > t.name === " Sub-task " ).id;
Behavioral Flow#
Step 0: Image Analysis (when --images provided)#
Executed when --images or --images-dir parameter is provided.
0.1 Image Load
Supported formats: PNG, JPG, JPEG, WEBP Recommended size: Max 5MB/file, 1920x1080 or smaller recommended
# Specify individual files
--images " list.png,detail.png,form.png "
# Specify directory (auto-filter supported formats)
--images-dir ./screenshots/
0.2 Screen Type Identification
Identify each image via Claude multimodal analysis:
| Image | Screen Type | Confidence | Key Components |
|---|---|---|---|
| list.png | List | 95% | AppBar, ListView, FAB |
| detail.png | Detail | 90% | SliverAppBar, ContentSection |
| form.png | Form | 92% | Form, TextField, Button |
Screen Type Identification Criteria:
- List: Multiple repeating cards/items, scrollable layout, FAB
- Detail: Full info of single item, large image/gallery, action buttons
- Form: Input fields (TextField, Dropdown, etc.), save/cancel buttons
Confidence threshold (--min-confidence, default: 70%):
- Screens below threshold request manual user confirmation
- e.g.: With
--min-confidence 80, confidence below 80% needs confirmation
0.3 Entity Field Extraction
Infer Entity fields from UI elements in images:
entity:
name: {EntityName}
fields:
- name: title
type: String
required: true
ui_component: TextField
validation:
max_length: 100
source_screen: form.png
- name: content
type: String
required: true
ui_component: TextArea
validation:
max_length: 5000
source_screen: form.png
- name: category
type: " {EntityName}Category "
required: true
ui_component: Dropdown
options: [general, notice, event]
source_screen: form.png
- name: imageUrls
type: " List < String > ? "
required: false
ui_component: ImagePicker
validation:
max_count: 5
source_screen: form.png
0.4 BDD Scenario Generation
Apply default BDD scenario templates based on screen type.
Language: BDD scenarios are generated in Korean (project convention).
List screen:
- List loading success
- Pull to refresh
- Infinite scroll
- Card tap โ navigate to detail
- Apply filter
- Empty list
Detail screen:
- Display detail info
- Like toggle
- Edit/delete
- Go back
Form screen:
- Valid form submission
- Required field missing
- Image attachment
- Cancel creation
0.5 Requirements Document Generation
Save analysis results as markdown:
Path: claudedocs/{feature_name}/requirements.md
# {Feature} Requirements Specification
> Auto-generated from image analysis
## Entity Definition
### {Entity}
| Field | Type | Required | Description |
|------|------|------|------|
| title | String | โ
| Title |
| content | String | โ
| Content |
...
## Screen Definition
### 1. List Screen (list.png)
- Components: AppBar, ListView, FAB
- Actions: Card tap โ navigate to detail, FAB tap โ create
...
0.6 Image Save and URL Generation (with --attach-images true)
Default:
--attach-imagesis disabled (false) by default. You must explicitly specify--attach-images trueto commit images to the repo.
Save images to repo and generate GitHub raw URLs:
โ ๏ธ Caution: Pushes directly to the current branch. May fail for protected branches (main/development).
User confirmation prompt:
๐ผ๏ธ ์ด๋ฏธ์ง๋ฅผ repo์ commitํ์๊ฒ ์ต๋๊น?
- ๋์ ํ์ผ: list.png, detail.png, form.png
- ์ ์ฅ ๊ฒฝ๋ก: claudedocs/{feature}/screenshots/
- ํ์ฌ ๋ธ๋์น: {current_branch}
**๊ณ์ํ์๊ฒ ์ต๋๊น? (y/N)**
# 1. Copy images to claudedocs
cp {input_images} claudedocs/{feature}/screenshots/
# 2. Add to Git (current branch)
git add claudedocs/{feature}/screenshots/
git commit -m " docs: ๐ธ {feature} ์คํฌ๋ฆฐ์ท ์ถ๊ฐ "
git push origin HEAD
# 3. Generate GitHub raw URLs
# https://raw.githubusercontent.com/{owner}/{repo}/{branch}/claudedocs/{feature}/screenshots/{image}
Protected Branch Handling:
- Recommend running from feature branch
- If push fails, proceed without image URLs (use local paths)
0.7 User Confirmation
## ๐ธ ์ด๋ฏธ์ง ๋ถ์ ๊ฒฐ๊ณผ
### ์๋ณ๋ ํ๋ฉด
| # | ์ด๋ฏธ์ง | ํ๋ฉด ํ์
| ์ปดํฌ๋ํธ ์ |
|---|--------|----------|-----------|
| 1 | list.png | List | 5 |
| 2 | detail.png | Detail | 4 |
| 3 | form.png | Form | 6 |
### ์ถ์ถ๋ Entity ํ๋
| ํ๋ | ํ์
| ํ์ | ์ถ์ฒ |
|------|------|------|------|
| title | String | โ
| form.png |
| content | String | โ
| form.png |
| category | Enum | โ
| form.png |
### ์์ฑํ BDD ์๋๋ฆฌ์ค
- ๋ชฉ๋ก: 8๊ฐ
- ์์ธ: 6๊ฐ
- ํผ: 7๊ฐ
**๋ถ์ ๊ฒฐ๊ณผ๊ฐ ์ ํํฉ๋๊น? (Y/n)**
0.8 Error Handling
| Situation | Handling |
|---|---|
| Image file not found | Output โ File not found: {path} and exit |
| Unsupported format | Only PNG, JPG, JPEG, WEBP supported. Other formats ignored with warning |
| Git push failure | Proceed without image URLs, use local paths (show warning) |
| Analysis confidence < threshold | Request manual user confirmation: โ ๏ธ Confidence {n}% - please verify screen type |
| No images in directory | Output โ ๏ธ No supported images in directory: {path} and exit |
| Entity field extraction failure | Proceed with empty fields, request manual input from user |
Step 1: Load Requirements#
Priority:
- Requirements generated in Step 0 (when using
--images) - File specified via
--requirements - Default path:
claudedocs/{feature}/requirements.md
## ์๊ตฌ์ฌํญ ๋ก๋
1. claudedocs/{feature}/requirements.md ์ฝ๊ธฐ
2. BDD ์๋๋ฆฌ์ค ํ์ผ๋ค ์ฝ๊ธฐ (์๋ ๊ฒฝ์ฐ)
3. Entity ํ๋ ์ ์ ์ถ์ถ
4. ํ๋ฉด ์ ์ ์ถ์ถ
Step 2: Epic Creation#
MCP call example:
mcp__zenhub__createZenhubIssue({
title: " {feature} ๊ธฐ๋ฅ ๊ตฌํ " ,
body: " {epic_body_template} " ,
repositoryId: repoId, // getWorkspacePipelinesAndRepositories()์์ ์กฐํ
issueTypeId: epicTypeId, // getIssueTypes()์์ ์กฐํ
labels: [ " epic " , " feature " , " {feature_name} " ]
})
## Epic ์์ฑ ํ์ธ
**์ ๋ชฉ**: {feature} ๊ธฐ๋ฅ ๊ตฌํ
**๋ด์ฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ**:
---
# Epic: {Feature} ๊ธฐ๋ฅ ๊ตฌํ
## ๐ ๊ฐ์
{feature_description}
## ๐ผ ๋น์ฆ๋์ค ๊ฐ์น
**์ฌ์ฉ์๋ก์**, {capability}์(๋ฅผ) ์ํฉ๋๋ค.
**๊ทธ๋์** {value}์(๋ฅผ) ์ป์ ์ ์์ต๋๋ค.
## ๐ ๋ฒ์
- โ
๋ชฉ๋ก ํ๋ฉด
- โ
์์ธ ํ๋ฉด
- โ
ํผ ํ๋ฉด
## ๐ ๏ธ ๊ธฐ์ ๋
ธํธ
| ํญ๋ชฉ | ๊ฐ |
|------|-----|
| Entity | `{EntityName}` |
| Backend | Serverpod endpoint |
| Caching | SWR |
---
**๋ผ๋ฒจ**: epic, feature, {feature_name}, petmedi
**์์ฑํ์๊ฒ ์ต๋๊น? (Y/n)**
Step 3: Story Creation#
Create per-screen Stories after confirmation:
MCP call example (repeated per screen):
mcp__zenhub__createZenhubIssue({
title: " {feature} {screen} ํ๋ฉด " ,
body: " {story_body_template} " ,
repositoryId: repoId, // getWorkspacePipelinesAndRepositories()์์ ์กฐํ
issueTypeId: featureTypeId, // getIssueTypes()์์ ์กฐํ
parentIssueId: " {epic_id} " , // Epic๊ณผ ์ฐ๊ฒฐ
labels: [ " story " , " {feature_name} " , " {screen_type}-view " ]
})
## Story ์์ฑ
| # | Screen | Title | Point | Acceptance Criteria Count |
|---|------|------|-------|-------|
| 1 | List | {feature} ๋ชฉ๋ก ํ๋ฉด | 3 | 8 |
| 2 | Detail | {feature} ์์ธ ํ๋ฉด | 3 | 9 |
| 3 | Form | {feature} ํผ ํ๋ฉด | 5 | 10 |
**Total Stories**: 3
**Total Points**: 11
Step 3.5: Sub-task Creation (Optional)#
Create detailed tasks as Sub-tasks under Stories.
MCP call example:
mcp__zenhub__createZenhubIssue({
title: " [{PREFIX}-00X-0Y] {task_description} " ,
body: " {subtask_body} " ,
repositoryId: repoId, // getWorkspacePipelinesAndRepositories()์์ ์กฐํ
issueTypeId: subtaskTypeId, // getIssueTypes()์์ ์กฐํ
parentIssueId: " {story_id} " , // Story์ ์ฐ๊ฒฐ
labels: [ " subtask " , " {feature_name} " , " p{priority} " ]
})
Auto-generated Sub-tasks by screen type:
| Screen Type | Sub-task List |
|---|---|
| List | Table column definition, search, filter, sort, pagination |
| Detail | Data display, action buttons, edit/delete confirmation |
| Form | Field validation, form submission, cancel handling, image upload |
Sub-task title format:
[{PREFIX}-001-01]: First Sub-task of Story 001[{PREFIX}-001-02]: Second Sub-task of Story 001- PREFIX is based on feature_name (e.g.,
AUTH,INST,BOOK)
Step 4: Epic-Story Linking#
## ์ฐ๊ฒฐ ์๋ฃ
โ
Epic #{epic_number} ์์ฑ ์๋ฃ
โ
Story #{story_1} ์ฐ๊ฒฐ๋จ
โ
Story #{story_2} ์ฐ๊ฒฐ๋จ
โ
Story #{story_3} ์ฐ๊ฒฐ๋จ
### ์์ฑ๋ ์ด์ ๋งํฌ
- Epic: https://github.com/cocode/petmedi/issues/{epic_number}
- ๋ชฉ๋ก: https://github.com/cocode/petmedi/issues/{story_1}
- ์์ธ: https://github.com/cocode/petmedi/issues/{story_2}
- ํผ: https://github.com/cocode/petmedi/issues/{story_3}
Output Files#
claudedocs/{feature_name}/
โโโ screenshots/ # ์ด๋ฏธ์ง ๋ถ์ ์ ์ ์ฅ (--images ์ฌ์ฉ ์)
โ โโโ list.png
โ โโโ detail.png
โ โโโ form.png
โโโ image_analysis.md # ์ด๋ฏธ์ง ๋ถ์ ๊ฒฐ๊ณผ (--images ์ฌ์ฉ ์)
โโโ requirements.md # ์๊ตฌ์ฌํญ (์๋ ์์ฑ ๋๋ ๊ธฐ์กด ํ์ผ)
โโโ bdd/ # BDD ์๋๋ฆฌ์ค (์๋ ์์ฑ)
โ โโโ {feature}_list.feature
โ โโโ {feature}_detail.feature
โ โโโ {feature}_form.feature
โโโ zenhub/
โโโ epic.md # Epic ์์ธ ์ ๋ณด
โโโ stories/
โโโ list_story.md # ๋ชฉ๋ก Story ์ ๋ณด
โโโ detail_story.md # ์์ธ Story ์ ๋ณด
โโโ form_story.md # ํผ Story ์ ๋ณด
Epic Template#
# Epic: {Feature} ๊ธฐ๋ฅ ๊ตฌํ
## ๐ ๊ฐ์
{Feature์ ๋ํ ๊ฐ๋ตํ ์ค๋ช
}
## ๐ผ ๋น์ฆ๋์ค ๊ฐ์น
**์ฌ์ฉ์๋ก์**, {feature_capability}์(๋ฅผ) ์ํฉ๋๋ค.
**๊ทธ๋์** {business_value}์(๋ฅผ) ์ป์ ์ ์์ต๋๋ค.
## ๐ ๋ฒ์
### ํฌํจ
- โ
{screen_1} ํ๋ฉด
- โ
{screen_2} ํ๋ฉด
- โ
{screen_3} ํ๋ฉด
### ์ ์ธ
- โ (ํ์์ ๋ช
์)
## ๐ ๏ธ ๊ธฐ์ ๋
ธํธ
| ํญ๋ชฉ | ๊ฐ |
|------|-----|
| Entity | `{EntityName}` |
| Backend | Serverpod endpoint |
| Caching | {SWR / Cache-First} |
| Location | `feature/{location}/{feature_name}` |
## ๐จ ๋์์ธ ์คํฌ๋ฆฐ์ท
> `--images` ์ฌ์ฉ ์ ์๋ ์์ฑ๋จ
### ๋ชฉ๋ก ํ๋ฉด

### ์์ธ ํ๋ฉด

### ํผ ํ๋ฉด

> ๋๋ Figma ๋งํฌ: {figma_urls}
## ๐ ๊ด๋ จ Story
- [ ] #{story_1_number} - ๋ชฉ๋ก ํ๋ฉด
- [ ] #{story_2_number} - ์์ธ ํ๋ฉด
- [ ] #{story_3_number} - ํผ ํ๋ฉด
---
> ๐ค Generated by `/zenhub:epic`
Story Template#
# Story: {Screen Name}
## ๐ ์ฌ์ฉ์ ์คํ ๋ฆฌ
**{user_type}๋ก์**, {screen_capability}์(๋ฅผ) ์ํฉ๋๋ค.
**๊ทธ๋์** {value}์(๋ฅผ) ์ป์ ์ ์์ต๋๋ค.
## โ
์ธ์ ๊ธฐ์ค (Acceptance Criteria)
### AC1: {scenario_1_name}
Given {precondition_1} When {action_1} Then {expected_result_1}
- **Priority**: {High/Medium/Low}
- **Tag**: @{tag}
### AC2: {scenario_2_name}
Given {precondition_2} When {action_2} Then {expected_result_2}
- **Priority**: {High/Medium/Low}
- **Tag**: @{tag}
## ๐ ๏ธ ๊ธฐ์ ์์
### Backend
- [ ] Serverpod endpoint ๊ตฌํ
- [ ] DTO ์ ์
### Domain
- [ ] Entity ์ ์
- [ ] Repository Interface ์ ์
- [ ] UseCase ๊ตฌํ
- [ ] UseCase ํ
์คํธ ์์ฑ
### Data
- [ ] Repository ๊ตฌํ
- [ ] Serverpod Mixin ๊ตฌํ
- [ ] ์บ์ฑ ์ ๋ต ์ ์ฉ
### Presentation
- [ ] BLoC ๊ตฌํ (Event/State)
- [ ] Page ์์ ฏ ๊ตฌํ
- [ ] Widget ์ปดํฌ๋ํธ ๊ตฌํ
- [ ] Route ๋ฑ๋ก
- [ ] BDD ํ
์คํธ ์์ฑ
### Widgetbook
- [ ] Component story ์ถ๊ฐ
## ๐จ ๋์์ธ ์ฐธ์กฐ
> `--images` ์ฌ์ฉ ์ ์๋ ์์ฑ๋จ

> ๋๋ Figma ๋งํฌ: {figma_link}
## ๐ ์์ Story Point
{point_value}
---
> ๐ค Generated by `/zenhub:epic`
> ๐ Epic: #{epic_number}
MCP Integration#
| Task | MCP Server | Purpose |
|---|---|---|
| Issue creation | ZenHub | Epic/Story creation |
| Template structuring | Sequential | Systematic issue organization |
Examples#
Basic Usage#
/zenhub:epic community Post
Specify Requirements File#
/zenhub:epic community Post \
--requirements claudedocs/community/requirements.md \
--bdd-dir claudedocs/community/bdd/
Specify Sprint and Labels#
/zenhub:epic community Post \
--labels " sprint-1,mvp " \
--sprint current
Custom Story Points#
/zenhub:epic community Post \
--screens " list,detail,form " \
--points " 5,3,8 "
Create Epic from Image Files (new)#
/zenhub:epic community Post \
--images " list.png,detail.png,form.png "
Create Epic from Image Directory#
/zenhub:epic community Post \
--images-dir ./screenshots/community/
Images + Additional Options#
/zenhub:epic community Post \
--images " list.png,detail.png,form.png " \
--labels " sprint-1,mvp " \
--sprint current
Analysis Only Without Image Attachment#
/zenhub:epic community Post \
--images " list.png,detail.png,form.png " \
--attach-images false
Reference Agent#
Detailed implementation rules: ~/.claude/commands/agents/zenhub-integration-agent.md
Key Rules#
- Epic First: Create Epic before Stories
- Link Required: All Stories must be linked to Epic
- Include Acceptance Criteria: Include BDD-based Acceptance Criteria in each Story
- Label Consistency: Follow the defined label system
- Create After Confirmation: Create actual issues only after user confirmation
- Documentation: Save creation results to claudedocs
-
Image Analysis: Detailed analysis via Claude multimodal when using
--images -
Image Attachment: On
--attach-images true, commit to repo after user confirmation to attach URLs to Issues - BDD Language: Auto-generated BDD scenarios are written in Korean