/cc-dev:zenhub:init-workspace — 작업 보드 초기 세팅#
| 항목 | 내용 |
|---|---|
| 실행 명령 | /cc-dev:zenhub:init-workspace |
| 분류 | 개발 사이클 |
| 난이도 | ●○○ 간단 |
| MCP 서버 | zenhub |
한마디로#
새 프로젝트를 시작할 때 ZenHub 작업 보드(칸반)의 칸들을 표준 형태로 한 번에 정리해 주는 명령입니다. 이사 들어가기 전에 빈 방에 똑같은 규격의 정리 선반을 미리 짜 넣어 두는 것과 같아요.
누가·언제 쓰나요#
- ZenHub 작업 공간에 새 GitHub 저장소를 막 연결한 직후
- 팀마다 제각각인 보드 칸 구조를 표준 형태로 통일하고 싶을 때
/cc-dev:run같은 개발 자동화 흐름을 본격적으로 시작하기 전 초기 세팅으로
무엇을 해주나요#
-
작업 보드를 표준 6칸 구조로 정리합니다:
New Issues → Icebox → Product Backlog → Sprint Backlog → In Progress → Review/QA - 더 이상 쓰지 않는 Done 칸을 비웁니다 — 그 안에 남아 있던 일감은 모두 자동으로 완료(Closed) 처리합니다. (완료는 이제 PR이 합쳐질 때 자동으로 처리되므로 Done 칸이 필요 없습니다.)
-
저장소·조직·일감 종류·각 칸의 ID를 한곳에 모아 둔 설정 파일
.claude/config/bmad/zenhub-conventions.yaml을 자동으로 만들어 줍니다. (다음 명령들이 매번 다시 조회하지 않고 빠르게 쓸 수 있게 해 주는 일종의 주소록입니다.) - 프로젝트의
.mcp.json에 ZenHub 연결 설정이 제대로 들어 있는지 확인해 줍니다. - 마지막에 "무엇이 끝났고, 무엇을 손으로 더 해야 하는지" 정리한 보고서를 보여 줍니다.
참고: ZenHub의 기술적 제약 때문에 칸을 직접 지우거나 새로 추가하는 작업은 사람이 손으로 해야 합니다. 명령은 어디서 무엇을 눌러야 하는지 링크와 함께 안내만 해 줍니다.
어떻게 쓰나요#
# 기본 — 작업 공간 ID를 .mcp.json에서 자동으로 읽어 옵니다
/cc-dev:zenhub:init-workspace
# 작업 공간 ID를 직접 지정할 때
/cc-dev:zenhub:init-workspace --workspace-id 69c4c110fc3a90000f3387d9
--workspace-id 는 생략해도 됩니다. 생략하면 프로젝트의 .mcp.json 파일에서 ID를 알아서 찾습니다.
안에서 무슨 일이 벌어지나요#
- 현황 조회 — 지금 작업 보드에 어떤 칸들이 있고, 어떤 저장소가 연결돼 있는지 읽어 옵니다.
- 표준과 비교 — 현재 칸 목록을 표준 6칸과 견줘서 빠진 칸, 지워야 할 Done 칸, 표준에 없는 별도 칸을 가려냅니다.
- 분석 보고 — "현재 상태 / 추가가 필요한 작업"을 표로 보여 줍니다.
- Done 칸 정리 — Done 칸에 남은 일감을 모두 완료(Closed) 처리하고, Done 칸 자체를 지우는 방법(주소와 클릭 위치)을 안내합니다.
- 일감 종류 조회 — Epic·Feature·Task·Bug 같은 일감 유형 정보를 가져옵니다.
- 설정 파일 생성 — 위에서 모은 ID들을
zenhub-conventions.yaml파일로 저장합니다. - 연결 설정 확인 —
.mcp.json에 ZenHub 설정이 있는지 점검합니다. -
완료 보고 — 끝난 일과 사람이 손으로 해야 할 다음 단계(빠진 칸 추가, Done 칸 삭제,
/cc-dev:run시작)를 정리해 보여 줍니다.
⚙️ 상세 옵션·실행 명세 (개발자 / AI 에이전트용)
Triggers#
- Right after adding a new GitHub repo to a ZenHub workspace
- When you want to standardize workspace pipeline structure
- Initial setup before starting development workflows like
/cc-dev:run
Context Trigger Pattern#
/cc-dev:zenhub:init-workspace [--workspace-id < id > ]Parameters#
| Parameter | Required | Description | Example |
|---|---|---|---|
--workspace-id | Optional | Workspace ID (reads from .mcp.json if omitted) | 69c4c110fc3a90000f3387d9 |
Standard Pipeline Structure#
After initialization, the workspace should contain only these pipelines:
New Issues → Icebox → Product Backlog → Sprint Backlog → In Progress → Review/QA| Pipeline | Purpose | Notes |
|---|---|---|
| New Issues | Newly created issues | Auto-placement |
| Icebox | On hold/low priority | Optional |
| Product Backlog | Approved backlog | After triage |
| Sprint Backlog | Assigned to current sprint | During sprint planning |
| In Progress | Work in progress | On branch creation |
| Review/QA | Code review/QA | On PR creation |
Done pipeline is not used. Issues auto-close via GitHub
Closes #keyword on PR merge.
Execution Flow#
Step 1: Query Workspace Info#
const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();Extract from query results:
workspace.pipelines→ Current pipeline listworkspace.githubRepositories→ Connected repo list (필드명:githubRepositories,repositories아님)workspace.zenhubOrganization.id→ Organization ID (setDatesForIssue의zenhubOrganizationId)
Step 2: Analyze Current Pipelines#
Compare current pipeline list with the standard structure:
const STANDARD_PIPELINES = [
" New Issues " ,
" Icebox " ,
" Product Backlog " ,
" Sprint Backlog " ,
" In Progress " ,
" Review/QA "
];
const PIPELINES_TO_REMOVE = [ " Done " ];
const currentNames = workspace.pipelines.map(p = > p.name);
const missing = STANDARD_PIPELINES.filter(name = > !currentNames.includes(name));
const toRemove = workspace.pipelines.filter(p = > PIPELINES_TO_REMOVE.includes(p.name));
const extra = currentNames.filter(name = >
!STANDARD_PIPELINES.includes(name) & & !PIPELINES_TO_REMOVE.includes(name)
);Step 3: Analysis Report#
Report current state and required actions to the user:
╔════════════════════════════════════════════════════════════════╗
║ ZenHub Workspace Pipeline Analysis ║
╠════════════════════════════════════════════════════════════════╣
║ ║
║ Workspace: {workspace_id} ║
║ Repositories: {repo_names} ║
║ ║
║ Current Pipelines: ║
║ ✅ New Issues ║
║ ✅ Product Backlog ║
║ ✅ In Progress ║
║ ✅ Review/QA ║
║ ⚠️ Done (needs removal) ║
║ ❌ Icebox (missing) ║
║ ❌ Sprint Backlog (missing) ║
║ ║
╚════════════════════════════════════════════════════════════════╝Step 4: Handle Done Pipeline#
When the Done pipeline exists:
- Check issues in the Done pipeline:
const doneIssues = await mcp__zenhub__getIssuesInPipeline({
pipelineId: donePipeline.id
});- Close issues if any exist (대문자
"CLOSED"— 소문자"closed"는 enum 거부로 false-success):
for (const issue of doneIssues) {
// GitHub 가 source of truth — 직접 닫고 ZenHub state 동기화
await Bash(`gh issue close ${issue.number} --reason completed`);
await mcp__zenhub__updateIssue({ issueId: issue.id, state: " CLOSED " });
}
// ⚠️ 파이프라인 삭제 안내(아래) 전에 전부 CLOSED 인지 재확인 — 미완 이슈가 컬럼 제거와 함께 은닉되지 않도록.
for (const issue of doneIssues) {
const st = (await Bash(`gh issue view ${issue.number} --json state -q .state`)).trim();
if (st !== " CLOSED " ) throw new Error(`Done 이슈 #${issue.number} 미종료 — 파이프라인 삭제 보류`);
}- Guide Done pipeline removal (모든 Done 이슈가 CLOSED 검증된 뒤에만):
The ZenHub MCP API does not support pipeline deletion. Please manually remove the Done pipeline at the following URL:
https://app.zenhub.com/workspaces/{workspace_id}/board
→ Done pipeline header (...) → Delete pipelineStep 5: Query and Cache Issue Types#
const issueTypes = await mcp__zenhub__getIssueTypes();Step 6: Generate zenhub-conventions.yaml#
Generate a .claude/config/bmad/zenhub-conventions.yaml file at the project root to cache IDs:
Note:
cc-product's BMAD Method workflow (/cc-product:workflow-init) generates an analogous cache atbmad/zenhub-conventions.yaml(no.claude/config/prefix) with a different schema (seeplugins/cc-product/references/templates/zenhub-conventions-template.md). The two caches are independent — this command does not read or write thecc-productpath, and vice versa.
# Auto-generated by /cc-dev:zenhub:init-workspace
# Date: {current_date}
repository:
id: " {repo.id} "
owner: " {repo_owner} "
name: " {repo_name} "
organization:
id: " {workspace.organizationId} "
issue_types:
epic: " {epicType.id} "
feature: " {featureType.id} "
task: " {taskType.id} "
bug: " {bugType.id} "
pipelines:
new_issues: " {newIssuesPipeline.id} "
icebox: " {iceboxPipeline.id} "
product_backlog: " {backlogPipeline.id} "
sprint_backlog: " {sprintBacklogPipeline.id} "
in_progress: " {inProgressPipeline.id} "
review_qa: " {reviewQAPipeline.id} "
# Done pipeline not used — Closed on PR merge
sprints:
active:
id: " "
name: " "
upcoming:
id: " "
name: " "
issue_creation:
method: " github "
# 제목/본문 접두사 규칙은 여기서 설정하지 않는다 — SoT: rules/zenhub-conventions.md
# → " Issue Title Conventions " (fix:/feat:/chore:, Project/Epic/Story는 접두사 없음)
last_updated: " {ISO_8601_timestamp} "Step 7: Verify .mcp.json#
Verify that ZenHub MCP configuration exists in the project root's .mcp.json:
// Read .mcp.json file
const mcpConfig = readFile( " .mcp.json " );
// Check zenhub server configuration
if (!mcpConfig.mcpServers?.zenhub) {
// Need to create .mcp.json or add zenhub configuration
}Step 7b: Verify token actually scopes to THIS project's workspace (필수)
토큰 존재 여부만으로는 불충분하다 — ZenHub API 토큰은 단일 기본 워크스페이스에 스코프되며, 한 조직에 여러 워크스페이스(예: 프로젝트 전용 + 범용/공용)가 있으면 .mcp.json 에 값이 들어 있어도 다른 워크스페이스를 가리킬 수 있다. Step 1 에서 이미 조회한 workspace.githubRepositories 를 대상 저장소와 대조한다:
const currentRepoName = (await Bash(`gh repo view --json name -q .name`)).trim();
const scoped = workspace.githubRepositories.some(r = > r.name === currentRepoName);
if (!scoped) {
// ⚠️ 토큰이 다른 워크스페이스에 스코프됨. 이 상태에서는:
// - createGitHubIssue / getIssueTypes(repositoryId) / setIssueEstimate 는 정상 동작(노드 ID 직접 지정, 워크스페이스 무관)
// - getWorkspacePipelinesAndRepositories / searchLatestIssues / moveIssueToPipeline 는 이 워크스페이스 기준이라 대상 저장소와 무관하거나 실패
// 이 경우 초기화를 계속 진행해도 파이프라인 이동(Step 3~4, 이후 /cc-dev:zenhub:breakdown 등)이 실패한다.
// 사용자에게 올바른 워크스페이스로 스코프된 토큰 발급/교체를 안내하고 중단.
// 상세 진단·해결: ../rules/zenhub-conventions.md " Token / Workspace Scope Pitfall "
}이 검증을 건너뛰면, 이후 이슈 생성까지는 조용히 성공하다가 파이프라인 이동(/cc-dev:zenhub:breakdown 등 후속 명령)에서 처음으로 실패가 드러나 원인 파악에 시간이 걸린다.
Step 8: Completion Report#
╔════════════════════════════════════════════════════════════════╗
║ Workspace Initialization Complete ║
╠════════════════════════════════════════════════════════════════╣
║ ║
║ ✅ Pipeline analysis complete ║
║ ✅ Done issues ({N}) → Closed ║
║ ⚠️ Done pipeline manual removal needed (URL guided) ║
║ ✅ zenhub-conventions.yaml generated ║
║ ✅ .mcp.json verification complete ║
║ ║
║ 📋 Missing Pipelines: ║
║ → Manual addition needed in ZenHub Board: {missing_names} ║
║ ║
║ 🏁 Next Steps: ║
║ 1. Manually remove Done pipeline ║
║ 2. Manually add missing pipelines ║
║ 3. Start development with /cc-dev:run ║
║ ║
╚════════════════════════════════════════════════════════════════╝Completion Rules#
- All issues in Done pipeline are Closed (automatic)
- Done pipeline deletion is manual (MCP API limitation)
- Missing pipeline addition is manual (MCP API limitation)
- zenhub-conventions.yaml is auto-generated (ID caching)
- Re-run after pipeline changes to refresh cache
Related Commands#
| Command | Description |
|---|---|
/cc-dev:zenhub:manage | PR linking and pipeline state management |
/cc-dev:zenhub:breakdown | Initiative/Project/Epic/Feature/Bug/Task creation (scale auto-inferred) |
/cc-dev:run | Full development cycle automation |