Use when orchestrating parallel Claude Code instances across tmux panes with git worktree isolation — managing multiple concurrent development tasks visually
Scanned 9/7/2026
Install to Claude Code
npx -y skills add JeremyDev87/codingbuddy --skill taskmaestro --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Taskmaestro?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/jeremydev87-taskmaestro)More formats (shields.io, HTML) on the badges page.
---
name: taskmaestro
description: Use when orchestrating parallel Claude Code instances across tmux panes with git worktree isolation — managing multiple concurrent development tasks visually
argument-hint: <start|assign|status|watch|send|stop> [args...]
user-invocable: true
---
# TaskMaestro — tmux 패널 오케스트레이터
현재 tmux 세션의 기존 패널들에서 Claude Code를 병렬로 실행하고, 이 패널(지휘자)에서 제어한다.
각 패널은 독립된 git worktree에서 작업하며, 지휘자가 작업 지시, 상태 감시를 수행한다.
**전제 조건:** 지휘자(이 Claude Code)가 tmux 패널 중 하나에서 실행 중이어야 하며, 나머지 패널들이 이미 열려있어야 한다.
## Arguments 파싱
`$ARGUMENTS`를 파싱하여 서브커맨드와 인수를 분리한다:
- `start [--repo <path>] [--base <branch>] [--panes <1,2,3>] [--review-pane] [--no-review-pane]`
- `assign <패널번호> "<작업 지시>"`
- `status`
- `watch`
- `send <패널번호> "<텍스트>"`
- `stop [패널번호|all]`
서브커맨드에 해당하는 섹션으로 이동한다.
## 현재 tmux 환경 감지
모든 서브커맨드에서 먼저 실행:
```bash
# 현재 tmux 소켓, 세션, 윈도우 정보를 자동 감지
TMUX_SOCKET=$(tmux display-message -p '#{socket_path}')
# 소켓 이름 추출 (경로에서 마지막 부분)
SOCKET_NAME=$(basename "$TMUX_SOCKET")
SESSION=$(tmux display-message -p '#{session_name}')
WIN_IDX=$(tmux display-message -p '#{window_index}')
MY_PANE=$(tmux display-message -p '#{pane_index}')
```
> tmux 명령어에서 `-L` 플래그는 소켓 이름을 사용한다. `tmux -L "$SOCKET_NAME" send-keys ...` 형태로 사용.
---
## Worker Completion Signaling (RESULT.json)
워커가 작업을 완료하면 `.taskmaestro/wt-N/RESULT.json` 파일을 생성하여 지휘자에게 결과를 알린다.
이 파일은 watch 모드의 **1차 감지 수단**이며, capture-pane은 fallback으로만 사용한다.
### RESULT.json 스키마
```json
{
"status": "success | failure | error | review_pending | review_addressed | approved",
"issue": "#767",
"pr_number": 123,
"pr_url": "https://github.com/org/repo/pull/123",
"timestamp": "2026-03-22T01:13:00.000Z",
"cost": "$0.45",
"error": null,
"review_cycle": 0,
"review_comments": []
}
```
| 필드 | 타입 | 필수 | 설명 |
|------|------|------|------|
| `status` | `"success" \| "failure" \| "error" \| "review_pending" \| "review_addressed" \| "approved"` | ✅ | 작업 결과. `success`: PR 생성 완료 (리뷰 대기), `failure`: 작업 실패 (테스트 실패 등), `error`: 예기치 못한 오류, `review_pending`: 지휘자 리뷰 코멘트 작성 완료 (워커 응답 대기), `review_addressed`: 워커가 리뷰 반영 완료 (재리뷰 대기), `approved`: 지휘자 최종 승인 (진짜 완료) |
| `issue` | `string \| null` | ❌ | 관련 이슈 번호 (예: `"#767"`) |
| `pr_number` | `number \| null` | ❌ | 생성된 PR 번호 |
| `pr_url` | `string \| null` | ❌ | 생성된 PR URL |
| `timestamp` | `string` | ✅ | ISO 8601 완료 시각 |
| `cost` | `string \| null` | ❌ | 세션 비용 (예: `"$0.45"`) |
| `error` | `string \| null` | ❌ | 에러 메시지 (`status`가 `"error"`일 때) |
| `review_cycle` | `number` | ❌ | 현재 리뷰 사이클 횟수 (기본값: 0) |
| `review_comments` | `string[]` | ❌ | 지휘자가 남긴 리뷰 코멘트 요약 목록 |
### 파일 경로 규칙
- 위치: `<repo>/.taskmaestro/wt-<N>/RESULT.json` (각 워커의 worktree 루트)
- 워커는 작업 완료 **직전** (커밋/PR 생성 후, 세션 종료 전)에 이 파일을 작성한다
- 지휘자는 이 파일의 존재 여부로 워커 완료를 감지한다
## Review Cycle Protocol
워커가 `RESULT.json`에 `status: "success"`를 기록하면 리뷰 사이클이 시작되고, `status: "approved"`가 될 때까지 반복된다. 승인이 "진짜 완료"다.
> **Canonical source:** 리뷰 사이클 프로토콜의 단일 소스는 [`packages/rules/.ai-rules/rules/pr-review-cycle.md`](../../../packages/rules/.ai-rules/rules/pr-review-cycle.md)이다.
> 아래 섹션은 taskmaestro 전용 구현 세부사항(tmux 트리거, `taskmaestro-state.json` 구조)만 남기고, 프로토콜 전체는 canonical 문서를 참조한다.
### Trigger (taskmaestro 관점)
지휘자의 watch 모드는 `.taskmaestro/wt-N/RESULT.json`의 `status` 필드를 감지한다:
| `status` | 지휘자 동작 |
|----------|-------------|
| `success` | 리뷰 사이클 시작 (done으로 보고하지 않음) |
| `failure` / `error` | 사용자에게 보고, 리뷰 미진행 |
| `review_pending` | 워커 응답 대기 |
| `review_addressed` | 재리뷰 시작 |
| `approved` | 진짜 완료 ✅ |
### Review Routing
- `review_pane`이 설정되지 않았으면 (기본) → **Conductor Review** 실행
- `review_pane`이 설정되었으면 → 해당 패널의 **Review Agent**로 위임
두 경우 모두 실행하는 프로토콜(CI gate → local verify → diff → code quality → spec → tests → write review → approve)은 canonical 문서를 따른다. Severity 등급(critical/high/medium/low), approval 조건, commit hygiene(amend + force-with-lease), 최대 3회 사이클 상한도 canonical 문서가 정의한다.
> **Conductor Review가 기본 동작인 이유:** 지휘자는 PLAN 컨텍스트를 보유하지만, 워커 리뷰어는 그렇지 않다.
### taskmaestro 고유: 파일 기반 리뷰 트리거
프로토콜의 "워커에게 리뷰 반영 지시" 단계를 taskmaestro는 **file-based trigger**로 구현한다. 긴 프롬프트를 `send-keys`로 직접 전송하면 잘릴 수 있으므로:
1. `Review Fix TASK.md`를 워커 worktree 루트(`$REPO/.taskmaestro/wt-$PANE_IDX/TASK.md`)에 작성한다. 내용은 아래 Review Fix TASK.md 템플릿을 따른다.
2. 짧은 트리거만 `send-keys`로 전송한다:
```bash
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE_IDX" \
"Read TASK.md and execute all steps." Enter
```
리뷰 에이전트 패널(`$REVIEW_PANE`)에 리뷰 프롬프트를 전송할 때도 동일한 파일 기반 패턴을 사용한다.
#### Review Fix TASK.md 템플릿
워커 worktree에 작성하는 `TASK.md`의 내용:
```markdown
# Review Fix Task
See rules/pr-review-cycle.md for the canonical worker response protocol.
## Steps
1. `gh pr view <PR_NUMBER> --comments` 로 리뷰 코멘트를 확인한다.
2. 각 코멘트에 대응: 수용 시 코드 수정, 거부 시 반박 코멘트, `Resolved: ...` 회신.
3. MANDATORY 사전 체크: `yarn prettier --write . && yarn lint --fix && yarn type-check && yarn test` — 모두 통과해야 push 한다.
4. 커밋 위생: `git commit --amend --no-edit && git push --force-with-lease` (fix 커밋을 쌓지 말 것).
5. `RESULT.json`을 업데이트한다: `{ "status": "review_addressed", "review_cycle": <current_cycle> }`
[CONTINUOUS] DO NOT stop. Only stop AFTER updating RESULT.json to "review_addressed".
```
> **핵심:** 워커는 리뷰 반영 후 반드시 `RESULT.json`의 `status`를 `review_addressed`로 업데이트해야 watch cron이 재리뷰를 트리거한다.
### taskmaestro 고유: 상태 스키마
리뷰 사이클 중 각 패널의 `taskmaestro-state.json` 필드:
```json
{
"index": 1,
"role": "worker",
"worktree": "...",
"branch": "...",
"task": "...",
"status": "review_pending",
"result": { "...RESULT.json 내용..." },
"review_cycle": 1,
"pr_number": 42
}
```
리뷰 에이전트 패널은 `role: "reviewer"`, `status: "reviewing"`을 사용한다. 리뷰 에이전트의 결과 파일(`<repo>/.taskmaestro/wt-<review_pane>/RESULT.json`)은 다음 스키마를 따른다:
```json
{
"status": "success",
"review_result": "approve | changes_requested",
"issues_found": 3,
"critical_count": 0,
"high_count": 1
}
```
Severity 카운트 필드(`critical_count`, `high_count`)는 [`rules/severity-classification.md`](../../../packages/rules/.ai-rules/rules/severity-classification.md)의 Code Review Severity 스케일을 따른다.
지휘자는 리뷰 에이전트 결과를 읽고:
1. `review_result: "approve"` → 워커 `RESULT.json`을 `approved`로 업데이트, 승인 코멘트 게시, 사용자에게 완료 보고
2. `review_result: "changes_requested"` → 워커 `RESULT.json`을 `review_pending`으로 업데이트하고 `review_cycle` 증가, file-based 리뷰 수정 트리거 전송
3. 리뷰 에이전트 `RESULT.json`을 삭제해 다음 리뷰를 위해 초기화
`status` 값 매핑:
- `working` → 워커 작업 중
- `reviewing` → 리뷰 에이전트가 PR 리뷰 중 (reviewer 패널 전용)
- `review_pending` → 리뷰 코멘트 작성 완료, 워커 응답 대기
- `review_addressed` → 워커 리뷰 반영 완료, 재리뷰 대기
- `approved` → 최종 승인 완료 (진짜 done)
- `done` → 리뷰 없이 완료 (failure/error)
---
## Merge Policy (MANDATORY)
**The conductor MUST NEVER merge PRs or modify the master/main branch.**
Prohibited commands:
- `gh pr merge` (all flags: --squash, --merge, --rebase, --admin, --auto)
- `git merge`
- `git pull origin master` / `git pull origin main` (includes merge)
- Any command that modifies the remote default branch
Allowed:
- `git fetch origin` (read-only)
- `gh pr create` (create PR, not merge)
- `gh pr view` (read-only)
**Protocol:**
1. Worker creates PR via `/ship` → reports PR URL
2. Conductor reports PR URL to user
3. User merges PR at their discretion
4. User notifies conductor: "머지했음" / "merged"
5. Conductor runs `git fetch origin` to verify, then proceeds
**Wave transition:**
- After all workers in a wave create PRs, report to user: "Wave N complete. PRs: #X, #Y, #Z. 머지 후 알려주세요."
- Wait for user confirmation before creating next wave's worktrees
---
## Wave Analysis: Shared File Prediction
Before assigning issues to a wave, predict the FULL file footprint per issue:
1. **Explicit files**: Listed in issue body
2. **Implicit shared files** (always check):
- `package.json` — dependency changes
- `config.schema.ts` / `*.config.*` — schema/config updates
- `index.ts` / barrel exports — new module exports
- `README.md` — documentation updates
- `.gitignore` — new artifacts
3. **MCP server issues**: Always flag `config.schema.ts` as potential overlap
### MCP Server Issues — Mandatory Overlap Check
ANY issue that creates a new MCP handler MUST flag these files as modified:
- `apps/mcp-server/src/mcp/handlers/index.ts`
- `apps/mcp-server/src/mcp/mcp.module.ts`
ANY issue that creates a new NestJS module MUST flag:
- `apps/mcp-server/src/app.module.ts`
ANY issue that adds to an existing module MUST flag that module file.
Two issues touching the same barrel/module file → MUST be in different waves.
**Overlap check:**
```
For each pair of issues in the wave:
shared_files = issue_A.files ∩ issue_B.files
if shared_files is not empty:
→ Move one issue to next wave OR make sequential in same pane
```
**Reference incidents:**
- Wave A PR #876/#879 — config.schema.ts modified by two issues not listed in issue body, causing merge conflict.
- Wave 1 PR #1142 — handlers/index.ts and mcp.module.ts modified by two MCP handler issues (#1120, #1122) not listed in issue body, causing merge conflict.
---
## Shell Script Safety Rules
### Array Indexing Ban
**NEVER use array indexing in monitoring/watch scripts.** zsh is 1-indexed, bash is 0-indexed. This causes wrong issue mapping.
```bash
# ❌ BANNED — index mismatch between shells
EXPECTED=("#888" "#811")
echo ${EXPECTED[$IDX]}
# ✅ REQUIRED — explicit key:value mapping
for PANE_INFO in "1:#888" "2:#811" "3:#813"; do
N="${PANE_INFO%%:*}"
EXP="${PANE_INFO##*:}"
done
```
**Reference incident:** zsh 1-based indexing caused pane 3 and 4's valid RESULT.json to be deleted.
---
## Session Management
### Compact Cadence
For long taskMaestro sessions (multiple waves):
- **Compact after every 2 waves** to prevent context degradation
- **Compact before starting a new batch** of waves
- **Save critical state** to `docs/codingbuddy/context.md` before compact (via `update_context`)
- **After compact**: re-read taskmaestro-state.json to restore wave context
Recommended flow:
```
Wave 1 → Wave 2 → compact → Wave 3 → Wave 4 → compact → ...
```
**Warning signs** that compact is needed:
- Session cost exceeds $2
- Context usage exceeds 50%
- Response quality noticeably degrading
- Session duration exceeds 2 hours
---
## Subcommand: start
`/taskmaestro start [--repo <path>] [--base <branch>] [--panes <1,2,3>] [--review-pane] [--no-review-pane]`
현재 세션의 기존 패널들에 worktree + Claude Code를 세팅한다.
### Step 1: 인수 파싱 및 기본값 설정
- `--repo`: 대상 레포 경로 (기본값: 현재 작업 디렉토리)
- `--base`: 베이스 브랜치 (기본값: 현재 브랜치)
- `--panes`: 사용할 패널 번호 목록 (기본값: 지휘자 패널을 제외한 모든 패널)
- `--review-pane`: 리뷰 전용 패널 할당 (기본값: 비활성화). 활성화하려면 `--review-pane` 명시 사용
- **Rationale:** Conductor has PLAN context; worker reviewers do not. Conductor Review is the primary and default review method.
### Step 2: 사전 검증
```bash
# repo가 git 레포인지 확인
git -C "$REPO" rev-parse --git-dir
```
에러 시 "대상 경로가 git 레포지토리가 아닙니다" 출력 후 중단.
```bash
# 사용 가능한 패널 목록 확인 (지휘자 패널 제외)
tmux -L "$SOCKET_NAME" list-panes -t "$SESSION:$WIN_IDX" -F '#{pane_index} #{pane_current_command}'
```
지휘자 패널($MY_PANE)을 제외한 패널들이 워커 대상이 된다. `--panes`로 지정하지 않으면 모든 비활성 패널을 사용한다.
**리뷰 패널 할당 (`--review-pane`, 기본 비활성화):**
`--review-pane` 플래그를 명시하면 사용 가능한 패널 중 마지막 패널을 리뷰 에이전트 전용으로 할당한다.
기본값은 비활성화이며, 지휘자가 직접 리뷰를 수행한다 (Conductor Review).
**Rationale:** Conductor has PLAN context; worker reviewers do not.
```bash
# 리뷰 패널 할당 (기본: 비활성화 — --review-pane 명시 시에만 활성화)
if [ "$REVIEW_PANE_ENABLED" = true ]; then
REVIEW_PANE=$(echo "$AVAILABLE_PANES" | tail -1)
WORKER_PANES=$(echo "$AVAILABLE_PANES" | head -n -1)
# 워커 패널이 최소 1개는 있어야 함
if [ -z "$WORKER_PANES" ]; then
echo "ERROR: 리뷰 패널을 할당하면 워커 패널이 없습니다. --no-review-pane을 사용하거나 패널을 추가하세요."
exit 1
fi
else
REVIEW_PANE=""
WORKER_PANES="$AVAILABLE_PANES"
fi
```
> **최소 패널 요구:** `--review-pane` 사용 시 지휘자 + 워커 1개 + 리뷰어 1개 = 최소 3개 패널이 필요하다.
**워커 패널이 없는 경우:** 지휘자 패널만 존재하면, 첫 번째 숫자 인수(기본값 3)만큼 새 패널을 생성한다:
```bash
PANE_COUNT=${1:-3} # 기본 3개
DIR=$(cd "$REPO" && pwd)
for ((i = 0; i < PANE_COUNT; i++)); do
tmux -L "$SOCKET_NAME" split-window -t "$SESSION:$WIN_IDX" -c "$DIR"
tmux -L "$SOCKET_NAME" select-layout -t "$SESSION:$WIN_IDX" tiled
done
# 지휘자 패널로 포커스 복귀
tmux -L "$SOCKET_NAME" select-pane -t "$SESSION:$WIN_IDX.$MY_PANE"
```
생성 후 다시 패널 목록을 조회하여 워커 패널을 결정한다.
### Step 3: 기존 상태 파일 확인
```bash
cat ~/.claude/taskmaestro-state.json 2>/dev/null
```
이미 활성 세션이 존재하면 AskUserQuestion으로 사용자에게 질문:
- "기존 세션에 연결" → 기존 세션 정보를 로드하고 종료
- "기존 세션 정리 후 새로 생성" → 기존 worktree/세션을 정리하고 계속 진행
### Step 4: worktree 생성
```bash
TIMESTAMP=$(date +%s)
DIR=$(cd "$REPO" && pwd)
BASE_BRANCH="${BASE:-$(git -C "$DIR" branch --show-current)}"
mkdir -p "$DIR/.taskmaestro"
# .gitignore에 .taskmaestro/ 추가
grep -qxF '.taskmaestro/' "$DIR/.gitignore" 2>/dev/null || echo '.taskmaestro/' >> "$DIR/.gitignore"
# 각 워커 패널 + 리뷰 패널에 대해 worktree 생성
ALL_PANES="$WORKER_PANES"
[ -n "$REVIEW_PANE" ] && ALL_PANES="$ALL_PANES $REVIEW_PANE"
for PANE_IDX in $ALL_PANES; do
BRANCH="taskmaestro/$TIMESTAMP/pane-$PANE_IDX"
WT_PATH="$DIR/.taskmaestro/wt-$PANE_IDX"
if [ -d "$WT_PATH" ]; then
if git -C "$DIR" worktree list | grep -q "$WT_PATH"; then
git -C "$DIR" worktree remove "$WT_PATH" --force
else
rm -rf "$WT_PATH"
fi
fi
git -C "$DIR" worktree add "$WT_PATH" -b "$BRANCH" "$BASE_BRANCH"
done
```
### Step 4.5: Worker Pre-Flight Verification
Before launching Claude Code, verify each worktree:
```bash
# 워커 + 리뷰 패널 모두 사전 검증
ALL_PANES="$WORKER_PANES"
[ -n "$REVIEW_PANE" ] && ALL_PANES="$ALL_PANES $REVIEW_PANE"
for PANE_IDX in $ALL_PANES; do
WT_PATH="$DIR/.taskmaestro/wt-$PANE_IDX"
# 1. Remove stale artifacts
rm -f "$WT_PATH/RESULT.json" "$WT_PATH/TASK.md"
# 2. Copy permission presets (#905)
if [ -f "$REPO/.claude/settings.local.json" ]; then
mkdir -p "$WT_PATH/.claude"
cp "$REPO/.claude/settings.local.json" "$WT_PATH/.claude/settings.local.json"
fi
# 3. Install dependencies (CRITICAL — without this, yarn prettier/lint/test all fail)
echo "Installing dependencies in wt-$PANE_IDX..."
(cd "$WT_PATH" && yarn install --immutable 2>/dev/null) || echo "WARNING: yarn install failed in wt-$PANE_IDX"
# 4. Verify git status clean
if ! git -C "$WT_PATH" diff --quiet 2>/dev/null; then
echo "WARNING: wt-$PANE_IDX has uncommitted changes"
fi
done
```
This prevents:
- Stale RESULT.json from previous waves being detected as "completed"
- **Workers unable to run local CI checks due to missing node_modules** (root cause of repeated CI failures)
- Permission prompt interruptions blocking worker progress (#905)
- Dirty worktree state causing unexpected behavior
### Step 5: 각 패널에 Claude Code 실행
```bash
# 워커 패널에 Claude Code 실행
for PANE_IDX in $WORKER_PANES; do
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE_IDX" \
"unset CLAUDECODE && cd $DIR/.taskmaestro/wt-$PANE_IDX && claude --dangerously-skip-permissions" Enter
done
# 리뷰 패널에 Claude Code 실행
if [ -n "$REVIEW_PANE" ]; then
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$REVIEW_PANE" \
"unset CLAUDECODE && cd $DIR/.taskmaestro/wt-$REVIEW_PANE && claude --dangerously-skip-permissions" Enter
fi
```
> **중요:** 지휘자 Claude Code 세션의 tmux 패널은 `CLAUDECODE` 환경변수를 상속받아 중첩 실행이 차단된다. `unset CLAUDECODE`로 해제해야 한다.
### Step 6: 초기 프롬프트 자동 처리
Claude Code 시작 시 trust 프롬프트와 약관 동의 프롬프트가 나타날 수 있다:
```bash
# 10초 대기 후 trust 프롬프트 승인 (Enter = "Yes, I trust")
sleep 10
for PANE_IDX in $WORKER_PANES; do
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE_IDX" Enter
done
# 3초 대기 후 약관 동의 프롬프트 처리 (Down → "Yes, I accept" → Enter)
sleep 3
for PANE_IDX in $WORKER_PANES; do
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE_IDX" Down
done
sleep 1
for PANE_IDX in $WORKER_PANES; do
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE_IDX" Enter
done
```
> 이미 동의한 환경에서는 이 프롬프트가 나타나지 않을 수 있다. send-keys는 무해하게 무시된다.
10초 대기 후 각 패널의 Claude Code가 프롬프트(`❯`) 상태인지 capture-pane으로 확인한다.
### Step 7: 상태 파일 기록
`~/.claude/taskmaestro-state.json`에 세션 정보를 기록한다.
```json
{
"socket_name": "workspace-1",
"session": "workspace-1",
"window_index": 0,
"conductor_pane": 0,
"review_pane": 3,
"repo": "절대경로",
"base_branch": "브랜치",
"created_at": "ISO timestamp",
"watch_cron_id": null,
"panes": [
{"index": 1, "role": "worker", "worktree": "절대경로/.taskmaestro/wt-1", "branch": "taskmaestro/ts/pane-1", "task": null, "status": "idle", "result": null},
{"index": 2, "role": "worker", "worktree": "절대경로/.taskmaestro/wt-2", "branch": "taskmaestro/ts/pane-2", "task": null, "status": "idle", "result": null},
{"index": 3, "role": "reviewer", "worktree": "절대경로/.taskmaestro/wt-3", "branch": "taskmaestro/ts/pane-3", "task": null, "status": "idle", "result": null}
]
}
```
- `review_pane`: 리뷰 에이전트 패널 인덱스. `--no-review-pane` 사용 시 `null`
- `role`: 각 패널의 역할. `"worker"` 또는 `"reviewer"`
- 리뷰 패널이 없는 경우(`review_pane: null`), 모든 패널의 `role`은 `"worker"`
### Step 8: watch 자동 시작
CronCreate로 30초 주기 cron job을 생성하여 watch 모드를 자동 시작한다.
생성된 cron job ID를 상태 파일의 `watch_cron_id`에 기록한다.
프롬프트: 각 워커 패널에 대해 **1차: RESULT.json 파일 확인 → 2차: capture-pane fallback** 순서로 상태를 감지한다. 워커의 `"success"` 감지 시 Review Routing (review_pane 존재 시 리뷰 에이전트에 위임). 리뷰 에이전트 패널의 RESULT.json도 확인하여 리뷰 결과 처리. 완료/에러 상태 패널이 있으면 사용자에게 보고한다.
### Step 9: 결과 보고
사용자에게 보고:
```
TaskMaestro 시작 완료!
세션: workspace-1
레포: /path/to/repo
지휘자: 패널 0
워커: 패널 1, 2
리뷰어: 패널 3
베이스: main
/taskmaestro assign <번호> "작업" 으로 작업을 배정하세요.
/taskmaestro status 로 상태를 확인하세요.
```
> **리뷰 패널이 없는 경우** (`--no-review-pane`): "리뷰어" 줄을 생략하고 모든 패널을 워커로 표시한다.
---
## Subcommand: assign
`/taskmaestro assign <패널 번호> "<작업 지시>"`
특정 패널의 Claude Code에 새 작업을 배정한다. 상태 파일의 task/status를 업데이트한다.
### Step 1: 상태 파일 로드 및 검증
```bash
cat ~/.claude/taskmaestro-state.json
```
소켓/세션/윈도우 정보를 가져온다.
패널 번호가 워커 패널 목록에 포함되는지 검증한다. 지휘자 패널이거나 존재하지 않는 패널이면 에러 출력 후 중단.
### Step 2: 작업 지시 파일 작성 및 트리거 전송
워커에게 작업 지시와 함께 **RESULT.json 작성 지시**를 포함한 프롬프트를 **TASK.md 파일**로 전달한다.
> **중요:** 긴 프롬프트를 `send-keys`로 직접 전송하면 잘릴 수 있다. 반드시 TASK.md 파일에 작성하고 짧은 트리거만 `send-keys`로 전송한다.
#### Step 2a: TASK.md 파일 작성
워커 worktree 루트에 `TASK.md`를 작성한다:
```bash
WT_PATH="$REPO/.taskmaestro/wt-$PANE"
cat > "$WT_PATH/TASK.md" << 'TASKEOF'
# Task: <작업 지시 요약>
<작업 지시 전체 내용>
---
[MANDATORY PR RULES]
When creating PR with gh pr create, ALWAYS include --add-label with appropriate labels (feat, chore, fix, etc.).
[MANDATORY PRE-PUSH] yarn prettier --write . && yarn lint --fix && yarn type-check && yarn test — ALL must pass before push.
[COMPLETION] Write RESULT.json: {"status":"success|failure|error","issue":"#NNNN","pr_number":N,"pr_url":"URL","timestamp":"ISO","cost":null,"error":null}
[CONTINUOUS] DO NOT stop. Complete ALL steps. Only stop AFTER RESULT.json.
TASKEOF
```
#### Step 2b: 짧은 트리거 전송
```bash
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE" \
"Read TASK.md and execute all steps. Follow TDD. Create PR with correct labels. Write RESULT.json when done. " Enter
```
> **참고:** 트리거 메시지에 핵심 지시를 한 줄로 요약하여 포함한다. 상세 지시는 TASK.md에서 읽게 된다.
### Step 3: 상태 파일 업데이트
해당 패널의 task와 status를 업데이트한다:
- `task`: 작업 지시 내용
- `status`: "working"
### Worker Completion & Review Fix Protocol
워커는 작업 완료 후 RESULT.json을 작성한다. 이후 리뷰 사이클이 시작되면:
1. 지휘자(또는 watch cron)가 Review Fix TASK.md를 워커 worktree에 작성한다
2. 워커는 `"Read TASK.md and execute all steps."` 트리거를 받고 TASK.md를 읽어 실행한다
3. 워커가 리뷰 반영을 완료하면:
- 코드 수정 → pre-push 검증 → push
- **RESULT.json의 `status`를 `"review_addressed"`로 업데이트** (필수)
4. watch cron이 `"review_addressed"`를 감지하여 재리뷰를 트리거한다
> **핵심:** 워커가 리뷰 반영 후 RESULT.json을 `"review_addressed"`로 업데이트하지 않으면, watch cron이 재리뷰를 시작할 수 없다. TASK.md 템플릿에 이 지시가 포함되어 있다.
### Step 4: 결과 보고
```
패널 $PANE에 작업을 배정했습니다: "<작업 지시>"
```
---
## Subcommand: send
`/taskmaestro send <패널 번호> "<텍스트>"`
특정 패널에 텍스트를 직접 전송한다.
이미 진행 중인 작업에 후속 지시나 응답을 보낼 때 사용한다.
assign과 달리 상태 파일의 task/status를 변경하지 않는다.
### Step 1: 상태 파일 로드 및 검증
소켓/세션/윈도우 정보를 가져온다.
패널 번호 유효성 검증.
### Step 2: 텍스트 전송
```bash
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE" "<텍스트>" Enter
```
### Step 3: 결과 보고
```
패널 $PANE에 전송 완료: "<텍스트>"
```
---
## Subcommand: status
`/taskmaestro status`
모든 워커 패널의 현재 상태를 수집하여 요약 보고한다.
### Step 1: 상태 파일 로드
```bash
cat ~/.claude/taskmaestro-state.json
```
### Step 2: RESULT.json 확인 (1차 감지)
각 워커 패널의 worktree에서 RESULT.json 존재 여부를 먼저 확인한다:
```bash
for PANE_IDX in $WORKER_PANES; do
RESULT_FILE="$REPO/.taskmaestro/wt-$PANE_IDX/RESULT.json"
if [ -f "$RESULT_FILE" ]; then
STATUS=$(cat "$RESULT_FILE" | jq -r '.status')
PR_NUMBER=$(cat "$RESULT_FILE" | jq -r '.pr_number // empty')
REVIEW_CYCLE=$(cat "$RESULT_FILE" | jq -r '.review_cycle // 0')
# → status 값에 따라 적절한 상태 아이콘과 메시지 표시
fi
done
```
RESULT.json이 존재하는 패널은 status 값에 따라 분기하여 표시한다:
- `"success"` → 리뷰 대기 (PR 생성 완료)
- `"review_pending"` → 리뷰 코멘트 작성 완료, 워커 응답 대기
- `"review_addressed"` → 워커 리뷰 반영 완료, 재리뷰 대기
- `"approved"` → 최종 승인 완료 (진짜 done)
- `"failure"` / `"error"` → 실패/에러 (기존 동작)
### Step 3: capture-pane fallback (2차 감지)
RESULT.json이 없는 패널에 대해서만 capture-pane으로 상태를 확인한다:
```bash
for PANE_IDX in $NO_RESULT_PANES; do
tmux -L "$SOCKET_NAME" capture-pane -t "$SESSION:$WIN_IDX.$PANE_IDX" -p -S -30 | tail -15
done
```
캡처된 내용을 분석:
- 마지막 줄에 Claude Code 프롬프트 (`❯` 또는 `>` 로 시작하는 입력 대기) → "idle"
- 도구 실행 중 (스피너, 코드 출력 진행 중) → "working"
- 에러 패턴 (`Error`, `error`, `failed`, `FAIL`) → "error"
- 프로세스 없음 (zsh 프롬프트만 보임) → "crashed"
### Step 4: 요약 보고
상태 파일의 task 정보와 결합하여 테이블로 출력:
```
TaskMaestro 상태 (workspace-1):
패널 1: ✅ approved - "API 엔드포인트 구현" → PR #42 (review complete) (worker)
패널 2: 🔍 reviewing - PR #43 (reviewer)
패널 3: 📝 review_addressed - "모듈 리팩토링" → PR #44 (awaiting re-review) (worker)
패널 4: 🔄 working - "인증 기능 추가" (worker)
패널 5: ⏳ review_pending - "캐시 레이어" → PR #45 (awaiting worker response) (worker)
패널 6: ❌ error - "모듈을 찾을 수 없음" (worker)
```
**상태별 아이콘:**
| status | 아이콘 | 설명 |
|--------|--------|------|
| `approved` | ✅ | 최종 승인 완료 (진짜 done) |
| `success` (리뷰 시작 전) | 🔍 | 리뷰 사이클 진행 중 |
| `reviewing` | 🔍 | 리뷰 에이전트가 PR 리뷰 중 (reviewer 패널 전용) |
| `review_pending` | ⏳ | 리뷰 완료, 워커 응답 대기 |
| `review_addressed` | 📝 | 워커 반영 완료, 재리뷰 대기 |
| `working` | 🔄 | 작업 중 |
| `failure` | ❌ | 작업 실패 |
| `error` | ❌ | 예기치 못한 오류 |
- `approved` 패널: RESULT.json에서 pr_url, cost, review_cycle 등을 함께 표시
- 리뷰 진행 중 패널: PR 번호와 현재 리뷰 사이클 횟수 (N/3) 표시
- `error`/`crashed` 패널: capture-pane 내용 마지막 10줄도 함께 표시
### Status Report Format (with evidence)
Every status line MUST include parenthetical evidence:
```
패널 1: ✅ approved - "task" → PR #N (RESULT.json: approved, review cycles: 2, pane idle ✓) (worker)
패널 2: 🔄 working - "task" (active: ✽ Implementing… · ↓ 5.3k tokens) (worker)
패널 3: 🔍 reviewing - PR #N (RESULT.json: reviewing PR #N for #M, pane active ✓) (reviewer)
패널 4: ⏳ review_pending - "task" → PR #N (RESULT.json: review_pending, cycle 1/3, awaiting worker) (worker)
패널 5: 📝 review_addressed - "task" → PR #N (RESULT.json: review_addressed, cycle 2/3, awaiting re-review) (worker)
패널 6: ⚠️ uncertain - "task" (RESULT.json exists BUT pane still active — cross-verify needed) (worker)
패널 7: ❌ error - "task" (error in last 10 lines: "ModuleNotFoundError") (worker)
```
**Rules:**
- Never report bare ✅ without evidence
- RESULT.json `approved` + pane idle = confirmed done
- RESULT.json `success` = start review cycle (NOT done)
- RESULT.json `review_pending` = awaiting worker response
- RESULT.json `review_addressed` = awaiting conductor re-review
- RESULT.json + pane active = UNCERTAIN (investigate)
- No RESULT.json + pane idle = needs nudge
- Active spinner (… + ↓ tokens) = confirmed working
- "thinking" alone ≠ working — check token count changes
---
## Subcommand: watch
`/taskmaestro watch`
주기적 감시 모드를 토글한다 (시작/중지).
### 감지 전략 (2단계)
watch 모드는 **RESULT.json 파일 기반 감지**를 1차 수단으로 사용하고, **capture-pane을 fallback**으로만 사용한다.
#### 1차: RESULT.json 파일 감지 (빠르고 정확)
```bash
# 1차: 워커 패널의 RESULT.json 확인
for PANE_IDX in $WORKER_PANES; do
RESULT_FILE="$REPO/.taskmaestro/wt-$PANE_IDX/RESULT.json"
if [ -f "$RESULT_FILE" ]; then
STATUS=$(cat "$RESULT_FILE" | jq -r '.status')
case "$STATUS" in
"success")
# → Review Routing: review_pane 존재 시 리뷰 에이전트에 위임, 없으면 직접 리뷰
# Review Cycle Protocol 참조
;;
"failure"|"error")
# → 사용자에게 에러/실패 보고 (기존 동작 유지)
;;
"review_pending")
# → 워커 응답 대기 중. 지휘자는 대기한다
;;
"review_addressed")
# → Review Routing: review_pane 존재 시 리뷰 에이전트에 재리뷰 위임, 없으면 직접 재리뷰
;;
"approved")
# → 진짜 완료 ✅. 상태를 "done"으로 업데이트하고 사용자에게 보고
;;
esac
fi
done
# 2차: 리뷰 에이전트 패널의 RESULT.json 확인
if [ -n "$REVIEW_PANE" ]; then
REVIEW_RESULT_FILE="$REPO/.taskmaestro/wt-$REVIEW_PANE/RESULT.json"
if [ -f "$REVIEW_RESULT_FILE" ]; then
REVIEW_STATUS=$(cat "$REVIEW_RESULT_FILE" | jq -r '.status')
REVIEW_RESULT=$(cat "$REVIEW_RESULT_FILE" | jq -r '.review_result')
if [ "$REVIEW_STATUS" = "success" ]; then
# → Conductor Handling of Review Agent Result 참조
# review_result에 따라 워커 PR approve 또는 changes_requested 처리
# 처리 후 리뷰 에이전트의 RESULT.json 삭제 (다음 리뷰 준비)
rm -f "$REVIEW_RESULT_FILE"
fi
fi
fi
```
**RESULT.json status 매핑:**
| status | watch 동작 |
|--------|-----------|
| `"success"` | 리뷰 사이클 시작 ("done"이 아님) |
| `"failure"` / `"error"` | 사용자에게 보고 (기존 동작 유지) |
| `"review_pending"` | 워커 응답 대기 중 |
| `"review_addressed"` | 지휘자 재리뷰 시작 |
| `"approved"` | 진짜 완료 ✅ |
- RESULT.json이 존재하면: status 값에 따라 위 매핑대로 분기한다.
- RESULT.json이 없으면: 아직 작업 중이거나 파일 미작성. fallback으로 진행한다.
#### 2차 (fallback): capture-pane 기반 감지
RESULT.json이 없는 패널에 대해서만 capture-pane으로 상태를 확인한다:
```bash
for PANE_IDX in $NO_RESULT_PANES; do
CAPTURED=$(tmux -L "$SOCKET_NAME" capture-pane -t "$SESSION:$WIN_IDX.$PANE_IDX" -p -S -30 | tail -15)
# 캡처 내용 분석:
# - 프롬프트 대기 (❯) → "idle" (작업 완료했으나 RESULT.json 미작성)
# - 도구 실행 중 → "working"
# - 에러 패턴 → "error"
# - 프로세스 없음 → "crashed"
done
```
### 시작 (watch_cron_id가 null인 경우)
1. 상태 파일에서 정보 로드
2. CronCreate로 30초 주기 cron job 생성. 프롬프트에 아래 전체 로직을 포함한다:
**워커 패널 순회 (1차: RESULT.json → 2차: capture-pane fallback):**
각 워커 패널에 대해 `$REPO/.taskmaestro/wt-$PANE_IDX/RESULT.json`을 확인하고, status에 따라 분기한다:
- **`"success"` 감지 (리뷰 사이클 시작):**
1. 상태 파일에서 `review_pane` 확인
2. `review_pane` 존재 시 → Review Agent Protocol에 따라 리뷰 에이전트에 위임
3. `review_pane` 없으면 → Conductor Review 실행:
a. `gh pr diff <PR_NUMBER>` 로 PR 변경사항 읽기
b. codingbuddy `generate_checklist` 도구로 체크리스트 생성
c. `gh pr review <PR_NUMBER> --comment --body "<리뷰>"` 로 리뷰 코멘트 작성
d. 워커의 RESULT.json 업데이트: `status: "review_pending"`, `review_cycle` 증가, `review_comments` 추가
e. 워커 worktree에 Review Fix TASK.md 작성 (아래 템플릿 참조):
```bash
# Review Fix TASK.md를 워커 worktree에 작성
cat > "$REPO/.taskmaestro/wt-$PANE_IDX/TASK.md" << 'TASKEOF'
# Review Fix Task
... (Review Fix TASK.md Template 참조)
TASKEOF
```
f. 워커에게 짧은 트리거 전송:
```bash
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE_IDX" \
"Read TASK.md and execute all steps." Enter
```
- **`"review_addressed"` 감지 (재리뷰):**
1. `review_cycle` 확인. 3 이상이면 사용자에게 보고하고 해당 패널 리뷰 중단
2. 상태 파일에서 `review_pane` 확인
3. `review_pane` 존재 시 → 리뷰 에이전트에 재리뷰 위임
4. `review_pane` 없으면 → Conductor Review 재실행:
a. `gh pr diff <PR_NUMBER>` 재확인
b. 미해결 코멘트 확인 (`gh pr view <PR_NUMBER> --comments`)
c. 충분히 개선 → `status: "approved"`, PR approve 코멘트 작성, 사용자에게 완료 보고
d. 아직 부족 → 새 리뷰 코멘트 작성 후 Review Fix TASK.md를 다시 워커에게 전달
- **`"approved"` 감지:** 진짜 완료 ✅. 상태를 "done"으로 업데이트하고 사용자에게 보고
- **`"failure"` / `"error"` 감지:** 사용자에게 에러/실패 보고 (기존 동작 유지)
- **`"review_pending"` 감지:** 워커 응답 대기 중. 지휘자는 대기한다
**리뷰 에이전트 패널 확인 (review_pane이 설정된 경우):**
`$REPO/.taskmaestro/wt-$REVIEW_PANE/RESULT.json` 확인:
- `review_result: "approve"` → 워커의 RESULT.json을 `status: "approved"`로 업데이트, PR approve 코멘트 작성, 리뷰 에이전트 RESULT.json 삭제
- `review_result: "changes_requested"` → 워커의 RESULT.json을 `status: "review_pending"`으로 업데이트 (`review_cycle` 증가), 워커 worktree에 Review Fix TASK.md 작성, 워커에게 `"Read TASK.md and execute all steps."` 트리거 전송, 리뷰 에이전트 RESULT.json 삭제
**Fallback (RESULT.json 없는 패널):**
capture-pane으로 상태 확인. idle인데 status가 "working"이면 Auto-Nudge Protocol 실행.
Claude Code가 비정상 종료된 패널이 있으면 재시작 여부를 사용자에게 질문한다.
3. cron job ID를 상태 파일의 `watch_cron_id`에 기록
4. 보고: "Watch 모드를 시작합니다 (30초 주기). 중지하려면 `/taskmaestro watch`를 다시 실행하세요."
### 중지 (watch_cron_id가 존재하는 경우)
1. 상태 파일에서 `watch_cron_id` 확인
2. CronDelete로 해당 cron job 제거
3. `watch_cron_id`를 null로 업데이트
4. 보고: "Watch 모드를 중지했습니다."
### Auto-Nudge Protocol
When a pane is detected as idle (❯ prompt visible) but its task status is "working":
1. **First idle detection**: Send `tmux send-keys "continue" Enter`
2. **Second consecutive idle**: Send `tmux send-keys "continue with the next incomplete task" Enter`
3. **Third consecutive idle**: Send explicit instruction with task context
4. **Track nudge count** per pane in the watch report
Include in watch cron prompt:
```
If pane is idle (❯ visible) and status is "working":
nudge_count[pane] += 1
if nudge_count <= 1: send "continue"
elif nudge_count == 2: send "continue with the next incomplete task"
else: send explicit instruction
Report: "Pane N: IDLE → auto-nudged (#count)"
```
### 제한 사항
CronCreate job은 현재 Claude Code 세션에 종속되며, 7일 후 자동 만료된다.
세션이 종료되거나 만료 시 watch도 중단된다. 재시작하려면 `/taskmaestro watch`를 다시 실행한다.
---
## Subcommand: stop
`/taskmaestro stop [패널 번호|all]`
Claude Code를 종료하고 worktree를 정리한다.
### 인수 파싱
- 인수 없음 또는 `all`: 모든 워커 패널 종료
- 숫자: 해당 패널만 종료
### 단일 패널 종료
1. 패널 번호가 워커 패널인지 검증. 아니면 에러 출력 후 중단.
2. 해당 패널에 Claude Code 종료 전송:
```bash
tmux -L "$SOCKET_NAME" send-keys -t "$SESSION:$WIN_IDX.$PANE" "/exit" Enter
```
3. 5초 대기 후 worktree 정리:
```bash
# uncommitted changes 확인
if git -C "$WORKTREE_PATH" diff --quiet && git -C "$WORKTREE_PATH" diff --cached --quiet; then
git -C "$REPO" worktree remove "$WORKTREE_PATH"
else
# AskUserQuestion으로 사용자에게 알림
# "패널 N의 worktree에 커밋되지 않은 변경사항이 있습니다. 강제 삭제할까요?"
# Yes → git worktree remove --force
# No → worktree 보존, 경로 안내
fi
```
4. 패널 닫기:
```bash
tmux -L "$SOCKET_NAME" kill-pane -t "$SESSION:$WIN_IDX.$PANE"
```
5. 상태 파일에서 해당 패널 정보 제거
6. 보고: `패널 N을 종료했습니다. (브랜치 taskmaestro/xxx/pane-N 유지됨)`
### 전체 종료 (all)
1. watch cron 중지 (활성 상태인 경우 CronDelete)
2. 각 워커 패널에 `/exit` 전송
3. 5초 대기
4. 각 worktree 정리 (uncommitted changes 확인 포함)
5. 워커 패널들 닫기 (역순으로):
```bash
for PANE_IDX in $(echo "$WORKER_PANES" | sort -rn); do
tmux -L "$SOCKET_NAME" kill-pane -t "$SESSION:$WIN_IDX.$PANE_IDX"
done
```
6. `.taskmaestro/` 디렉토리가 비었으면 삭제:
```bash
rmdir "$REPO/.taskmaestro" 2>/dev/null
```
7. 상태 파일 초기화
8. 보고:
```
TaskMaestro 종료 완료.
정리된 워커: N개
유지된 브랜치: taskmaestro/xxx/pane-1, pane-2, ...
```
> **주의:** `stop all`은 tmux 세션을 종료하지 않는다. 패널들은 그대로 남아있으며 zsh 상태로 돌아간다.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!