| name | herdr-orchestrator |
| description | Use when the user explicitly asks for herdr-based multi-agent orchestration,
multiple visible Claude/Codex worker panes, or cross-CLI comparison inside
herdr, especially when workers need distinct CLI/account/browser state.
|
herdr-orchestrator
herdr 위에서 다수 worker (claude, codex) 를 visible TUI pane 으로 병렬
호출하기 위한 free-form orchestrator. 기본 판단은 "subagent/lightweight delegation 먼저,
herdr pane 은 필요할 때만" 이다. pane 을 만들기로 결정한 뒤의 협업 패턴 (fan-out / split /
역할 분담) 은 호출자가 prompt 로 결정 — 이 skill 은 spawn·대기·회수·정리 primitive 를
제공한다.
발동 / 비발동
발동:
- "herdr 로 claude+codex 둘 다 시켜봐"
- "herdr pane 새로 띄워서 codex 한테도 시켜"
- "여러 visible worker pane 으로 동시에 보여줘"
- "브라우저 조작이 필요한 claude 워커와 일반 codex 워커를 분리해"
- 서로 다른 CLI/OAuth 계정/브라우저 세션/샌드박스 상태가 필요한 worker 병렬 실행
- 사용자가 herdr pane fan-out 자체를 명시
아래 표현만으로는 발동하지 않음 (조건부 발동):
- "두 에이전트 병렬로 같은 task 던져봐"
- "한쪽은 plan, 다른쪽은 dev 로 나눠서 동시에"
- "여러 worker 병렬"
- worker 3개 이상 fan-out
이 경우 visible pane, 별도 CLI/account/browser state, 사용자의 herdr 지정이 추가로 없으면
새 herdr pane 을 만들지 말고 subagent/lightweight delegation 으로 처리한다. 즉 "병렬"이라는
단어만으로는 pane 생성 사유가 되지 않는다.
비발동:
- 단일 worker 만 필요 —
herdr 공식 skill 직접 호출.
- 단순 pane 송수신 — 다른 가벼운 skill.
- visible TUI 가 필요 없는 코드 탐색/리뷰/계획 분담 — subagent/lightweight delegation 우선.
- 같은 repo·같은 계정·같은 권한에서 독립 분석만 병렬화하면 충분한 경우 — subagent 우선.
- herdr 밖 환경 — 이 skill 범위 밖.
Pane 생성 라우팅 게이트 (v0.10 — 토큰 절감)
WORKER_CMDS 를 만들기 전에 다음 질문을 순서대로 통과해야 한다.
- 사용자가 herdr, pane, visible TUI, Claude+Codex CLI 비교를 명시했나?
- worker 마다 서로 다른 CLI/OAuth 계정/browser 인증/sandbox/cwd 관찰 상태가 필요한가?
- 사용자가 각 worker 진행 상황을 herdr pane 에서 직접 봐야 하는가?
- in-process subagent 나 기존 pane 메시지 송수신으로는 목표를 달성할 수 없는가?
하나도 해당하지 않으면 이 skill 로 새 tab/pane 을 만들지 않는다. subagent 를 쓰되
task 를 좁게 나누고, 필요하면 low/medium effort 를 우선한다. 하나 이상 해당해도 pane 수는
최소화한다: 같은 목적의 3~9개 fan-out 보다 1개 핵심 pane + 내부 subagent 를 먼저 고려하고,
실패·불일치·사용자 명시가 있을 때만 추가 pane 을 연다.
인증 / 과금 정책 (불변)
- 모든 모델 호출은 다음 둘 중 하나의 OAuth/구독 인증을 통한다:
claude --dangerously-skip-permissions (Claude Code CLI)
codex --dangerously-bypass-approvals-and-sandbox (Codex CLI)
- skill body, spawned pane, 어떤 단계에서도
ANTHROPIC_API_KEY /
OPENAI_API_KEY 등 과금 API 키 사용 금지.
- anthropic / openai SDK 직접 import,
api.anthropic.com / api.openai.com
직접 HTTP 호출 금지.
- 이 정책을 어기는 PR/commit 은 거부 대상.
claude 워커 계정 분리 (v0.8 — 불변)
claude 워커는 두 OAuth 계정 프로필을 슬롯별로 가른다 (둘 다 구독 인증 — API 키 아님):
- 기본 = 개인 kangho (
ccp · ~/.claude-personal) — claude 워커의 일반 작업 전부.
회사 플랜 소진을 막고 개인 한도로 분산한다.
- browser 슬롯만 = 회사 harry (
ccq · ~/.claude) — WORKER_BROWSER[i]=1 로 표시한 슬롯.
claude-in-chrome / 브라우저 조작이 필요한 워커는 반드시 ccq. claude-in-chrome 인증
(.credentials.json)이 ~/.claude 에만 있어 개인 프로필로는 브라우저 도구를 못 쓴다.
- codex 워커엔 무효 — ccq/ccp 는 claude 전용. codex 슬롯의
WORKER_BROWSER 는 무시된다.
- 계정 prefix 는
build_launch() 가 claude_acct_prefix() 로 base 명령 앞에 합성 (ccq/ccp 함수
우선 + 함수 미정의 시 env 인라인 fallback). prefix 가 abort 하면 그 워커는 띄우지 않는다.
워커 실행 모드 (불변): 인터랙티브 TUI only
worker pane 에는 항상 인터랙티브 TUI 세션을 띄운다. prompt 는 CLI 인자로 붙이지
않고, 세션이 시작된 뒤 send-text / send-keys 로 주입한다. 그래야 사용자가 pane
에서 에이전트가 실시간으로 일하는 모습을 직접 볼 수 있다.
올바름 (인터랙티브 — 세션 유지, 사용자 관찰 가능):
claude --dangerously-skip-permissions → 이후 send-text 로 prompt 주입
codex --dangerously-bypass-approvals-and-sandbox → 이후 send-text 로 prompt 주입
금지 (headless one-shot — 사용자 눈에 안 보이고 즉시 종료해 백그라운드처럼 느껴짐):
claude -p "..." / claude --print "..."
codex exec "..."
- prompt 를 CLI 인자로 직접 붙여 한 번에 실행하는 모든 형태
즉 pane run 으로 띄우는 명령에는 prompt 가 절대 포함되지 않는다. 명령은 TUI 를
띄우기만 하고, prompt 는 반드시 별도 prompt 주입 단계(4)에서 넣는다.
예외 아님 — model/effort 플래그는 prompt 가 아니라 launch 옵션이므로 launch 명령에
붙여도 된다 (claude --model X, codex -m X -c model_reasoning_effort=Y). 금지 대상은
어디까지나 prompt(-p / exec / 인자 prompt)다.
메시지 송신 불변 (v0.9): send-text 직후 반드시 Enter
워커(또는 다른 herdr 세션)에 메시지를 보낼 때는 send-text 한 번에 끝내지 말고
반드시 곧바로 send-keys Enter 로 제출한다. Enter 가 빠지면 prompt 가 입력창에 그대로
떠 있고 워커는 영원히 idle 상태라, "메시지는 들어갔는데 한참 작업이 안 됨" 사고가 난다
(실제로 자주 발생). 이건 send_prompt·toggle_mode·toggle_model 뿐 아니라 orchestrator 가
보내는 모든 ad-hoc 메시지에 예외 없이 적용되는 불변 규칙이다.
- 순서 고정:
send-text → (텍스트가 입력창에 안착 확인) → send-keys Enter. Enter 가
paste 보다 앞서 레이스 나면 빈 줄만 제출되므로, 긴 prompt 일수록 안착 확인 후 Enter.
- 제출 확인 + 재시도: 송신 후 워커가 실제로 실행을 시작했는지(agent-status / pane
내용) 본다. 시작이 확인 안 되면(입력창에 prompt 가 남아 있으면) Enter 를 한 번 더
보내 제출을 강제한다. 이미 실행 중이면 빈 Enter 는 양 CLI 에서 no-op 라 안전하다.
- 절대 금지: 메시지를 입력창에 넣어두고 Enter 없이 다음 단계로 넘어가는 것.
모델·effort 자율 조정 (v0.5 — 호출자 재량)
orchestrator 는 새 pane 이 필요하다고 판단한 경우에만 각 worker pane 의 model 과 effort 를
task 난이도에 따라 자율적으로 고른다. 어려운·장기·핵심 판단 작업엔 당시 가장 강한 모델 +
높은 effort 를, 단순·대량 병렬 분석은 가능하면 pane fan-out 대신 subagent/lightweight
delegation 으로 낮은 effort 를 배정해 비용·지능을 계층화한다.
최신 모델 확인 (필수 — 구버전 하드코딩 금지)
모델 라인업은 자주 바뀐다 (Claude 는 Fable 출시, Codex 도 신모델 릴리스). worker 에
모델을 배정하기 전에 반드시 그 시점의 실제 사용 가능 모델 목록을 런타임에 확인하고,
구버전을 박지 말 것. 아래 스냅샷은 작성 시점 참고용일 뿐 — 매번 검증한다.
- Claude 워커: TUI 에서
/model (인자 없이) → 사용 가능 모델 목록. launch 플래그는
claude --model <name>. claude --help 로 현재 허용 이름 확인. mid-session 전환은
/model <name> 슬래시(4.6 toggle_model).
- Codex 워커:
codex --help / codex -m <model> (launch). reasoning effort 는
-c model_reasoning_effort="<level>" (레벨 집합은 codex 버전마다 다름 — codex --help/
config 로 확인). TUI /model 은 모델+effort picker.
스냅샷 (검증 대상, 최신 우선 — 이름·존재 여부는 런타임 /model/--help 로 재확인):
- Claude 강함 순: fable(최상위·신규 티어) > opus(4.8) > sonnet(4.6) > haiku(4.5).
"가장 강한 모델" 요청 = 사용 가능한 것 중 fable(없으면 최신 opus). opus-4-5 이하·
sonnet-3.x·haiku-3.x 등 구버전 선택 금지.
- Claude effort:
low | medium | high | xhigh | max (Claude Code 기본 xhigh,
코딩·에이전트엔 xhigh, 최고 정확도엔 max).
- Codex 모델/effort 레벨: 버전 의존 → 반드시
codex --help//model 로 확인.
낯선 모델 이름이 보이면 (학습 컷오프 이후 출시라) 그게 최신일 가능성이 크다 — 목록에 있으면
실재 모델이다. 자기 기억으로 모델 ID 를 지어내지 말 것.
난이도 → 모델/effort 배정 (가이드, 고정 아님)
| 난이도 / 역할 | 모델 | effort |
|---|
| 매우 어려움 · 장기 자율 에이전트 · 핵심 판단 | 당시 최강(예: fable / 최신 opus) | highxhighmax |
| 보통 구현·리뷰 | 중상위(최신 opus/sonnet) | high / medium |
| visible TUI 가 꼭 필요한 단순 worker | 싸고 빠른(haiku 등) | low / medium |
아래 라우팅 게이트와 effort 계층 규약(1단계)과 합쳐: 먼저 subagent 로 해결 가능한지 보고,
workflow subagent 는 low 로 두어 비용 절감, orchestrator pane(또는 핵심 worker)만 xhigh/max 로
깊게 판단.
실측 라우팅 정책 (v0.7 — 2026-06-11 model-bench, easy tier n=8 paired)
qplace 모노레포 실작업(api-cms tsc 에러 해소)으로 sonnet 4.6 / opus 4.8 / codex(gpt-5.5)
를 paired 벤치마크한 결과 (원데이터: qplace repo model-bench/results.jsonl):
- 품질: opus 9.88 > codex 8.25 > sonnet 6.50 (paired Wilcoxon, opus>codex p=0.031 유의,
opus>sonnet p=0.0625 양측·0.031 단측). PASS@1 은 셋 다 100% — 격차는 "돌아가느냐"가
아니라 해법 품질(선례 준수·타입 안전)에서 남.
- opus 는 medium effort 로 낮춰도 품질 10 유지 + wall 최단(125~145s) — easy tier 에서
opus 기본 effort 는 medium 으로 충분 (high 대비 비용·시간 절감).
- sonnet 의 구조적 약점: 제네릭 변성 등 "타입 설계 갈림길"에서 8회 중 7회
any-escape(
as any[]/TestBed<Hono<any>> + biome 억제)를 선택. effort 를 max 로
올려도 불안정(2회 중 1회만 캐노니컬 해법) — effort 상향으로 sonnet 의 품질 문제를
풀려 하지 말 것. 반면 선례가 명확한 순수 기계적 수정에선 opus 와 바이트 동일 diff 를
1/8 비용으로 냄 (T3).
- codex: 출력 토큰 최소(3
9k)·플랜 비용·품질 89 안정(제3의 타입 안전 변형을
자주 선택). 단 sandbox 가 git add/commit 을 막으면 orchestrator 대리 커밋 필요.
| easy-tier task 유형 | 배정 | 비고 |
|---|
| 선례 명확·기계적 수정 (가드 추가, 단순 치환) | sonnet medium | 최저 비용. diff 게이트(아래) 필수 |
| 타입 설계 판단 포함 (제네릭, 공유 fixture, 시그니처) | opus medium | high 와 동품질, 더 빠르고 저렴 |
| Claude 플랜 소진·토큰 절약 우선 | codex high | 품질 8+ 안정, 대리 커밋 준비 |
| medium tier 이상 (기능 개발·리팩토링) | opus high~xhigh | easy 외 데이터 부족 — 기존 가이드 유지 |
orchestrator diff 게이트: worker 결과 회수 시 diff 에서 as any·<any·biome-ignore
패턴을 grep — 검출 시 객관 기준 PASS 라도 리워크 대상으로 간주하고 한 단계 위 모델로
재배정한다 (sonnet 산출물에서 특히 빈발). fable worker 는 정책상 금지 — 필요하다고
판단되면 사용자 보고를 선행한다.
ultracode — worker 를 워크플로 오케스트레이션 모드로 (Claude Code 전용)
ultracode 는 effort 레벨이 아니라 Claude Code 의 별도 설정이다. 내부적으로 xhigh 를
보내면서 + substantive task 마다 Claude 가 알아서 Workflow(멀티에이전트 오케스트레이션)를
구성·실행한다 (이해→변경→검증을 여러 workflow 로 연쇄). 토큰 비용을 제약하지 않아 더 느리고
비싸다 — 라우팅 게이트를 통과한 뒤에도 최대 철저함이 목표인 어려운 slot 에만 쓴다.
herdr 와의 결합 = 필요할 때만 2단계 fan-out: 먼저 pane 없이 subagent/lightweight
delegation 으로 충분한지 본다. visible TUI 또는 별도 CLI/account/browser state 때문에 herdr
worker pane 을 열어야 할 때만, ultracode 워커 pane 이 그 안에서 다시 Workflow subagent 를
펼친다. 어려운 단일 slot 을 ultracode 로 돌리면 그 pane 하나가 통째로 멀티에이전트
오케스트레이션이 되므로, 여러 pane 을 여는 것보다 이 형태를 먼저 고려한다.
켜는 법 (claude 워커 한정 — codex 엔 ultracode 없음, /effort 처럼 skip):
- 세션 standing:
/effort ultracode (그 세션 내내 적용). toggle_mode <i> ultracode 로 주입
가능 — /effort 메뉴가 ultracode 옵션을 제공하므로 슬래시는 유효하다 (단 ultracode 는 effort
레벨이 아니라 별도 설정임을 유의). 해제는 /effort high 또는 /effort auto(모델 기본).
- 단일 턴: 주입 prompt 에 자연어로 "이 작업을 workflow 로 오케스트레이션해라" 를 넣는다.
리터럴 키워드
ultracode 도 단일-턴 트리거지만 /config 에서 꺼져 있거나 버전 차로 안 먹을
수 있어 — worker 주입엔 자연어 워크플로 지시가 더 안정적이다.
비용 계층 규약(위 effort 계층 규약)과 결합: pane 밖 subagent 도, ultracode 워커가 펼치는 workflow
subagent 도 가능한 한 low/medium effort 로 두고 핵심 orchestrator/pane 만 깊게 판단한다.
"비용 무제약" 이 subagent 까지 무분별하게 번지지 않게 한다.
goalcraft / goal 활용 (v0.5 — 호출자 재량)
orchestrator 는 거친 요구사항을 worker 에 던지기 전에 goalcraft skill 로 goal 최적화
프롬프트로 다듬거나, worker 에게 /goal 을 쓰게 할 수 있다 (Claude Code·Codex 양쪽 모두
/goal 보유). 의무 아님 — 판단은 호출자 재량.
- prompt 정제: 모호한 task 는 orchestrator 가 goalcraft 를 돌려(또는 동일 원리로 직접)
목표·범위·완료조건이 박힌 prompt 로 만들어
WORKER_PROMPTS 에 넣는다. 측정 가능한
"done" 이 있으면 worker 가 스스로 멈출 신호가 생겨 장기 자율 실행이 안정된다 — 높은
effort·강한 모델과 특히 잘 맞는다.
- worker 가
/goal 사용: 장기·자율 작업을 맡길 땐 주입 prompt 에 "/goal 로 목표를
고정하고 진행하라" 를 넣을 수 있다 (/goal 본문 4000자 제한 — 상세는 파일로 빼고 goal 은
검증 가능한 종료상태·체크 커맨드에 쓴다).
- target 규약: Claude Code worker → Claude 최적화 goal, Codex worker → Codex 최적화 goal
(goalcraft 는 executor-adaptive). 명시 target 이 있으면 그걸 우선.
위계 매핑
| herdr 개념 | 용도 |
|---|
| workspace | 호출자(orchestrator) workspace 를 그대로 공유 — HERDR_PANE_ID 로 확정(focused 추측 아님). 새로 만들지 않는다. |
| tab | worker pane 그룹. 한 task = 새 tab(들). 각 tab 최대 9 pane (3×3). label SLUG-1, SLUG-2, ... 호출자 tab 과 격리. |
| pane | 실제 worker (claude 또는 codex). slot 순서로 채움. |
호출자(orchestrator) 본인 pane(LAUNCHER_PANE)이 있는 tab(LAUNCHER_TAB)은 그대로 두고
절대 건드리지 않는다. 이 셋(pane/tab/workspace)은 모두 Preflight 에서 HERDR_PANE_ID 로
확정한다 — focused(사용자가 지금 보고 있는 pane)로 추정하지 않는다. worker tab_id ≠
LAUNCHER_TAB 를 매 send·close 직전 검증.
3×3 grid 배치
┌─────────┬─────────┬─────────┐
│ slot 0 │ slot 3 │ slot 6 │ ← row 0
├─────────┼─────────┼─────────┤
│ slot 1 │ slot 4 │ slot 7 │ ← row 1
├─────────┼─────────┼─────────┤
│ slot 2 │ slot 5 │ slot 8 │ ← row 2
└─────────┴─────────┴─────────┘
col 0 col 1 col 2
slot index = col * 3 + row (column-major)
worker 수 N 분배:
N ≤ 9 → 단일 worker tab SLUG-1, 필요한 슬롯만 split.
N > 9 → 매 9개마다 새 worker tab (SLUG-2, …).
- 부족한 슬롯은 split 자체 skip (예: N=5 → col0 전체 + col1 의 row0/row1 만).
Prerequisite
HERDR_ENV=1 (herdr 안에서 실행 중).
herdr CLI PATH 에 있음.
claude, codex CLI 둘 다 OAuth/구독 로그인 완료.
- (선택) 공식
herdr skill 도 활성화되어 있으면 워크스페이스/탭/페인 CLI 상세
사양을 추가 참조 가능. 없어도 본 SKILL 의 레시피로 충분.
워크플로우
-1. Routing gate (필수)
Preflight 와 WORKER_CMDS 구성 전에 새 herdr pane 이 꼭 필요한지 먼저 판정한다.
- subagent/lightweight delegation 으로 충분하면 여기서 멈추고 이 skill 의 spawn 절차를
실행하지 않는다.
- herdr pane 을 여는 경우에도 필요한 외부 세션 경계만 worker 로 센다. 예: "브라우저 인증을
가진 claude 1개 + codex 비교 1개" 는 2 pane 이지만, "리뷰 관점 6개" 는 보통 subagent 6개다.
- 사용자가 "herdr 로", "pane 새로", "Claude/Codex 둘 다 visible 하게" 처럼 명시했거나,
worker 별 CLI/OAuth/browser/cwd 관찰 상태가 달라야 할 때만 다음 단계로 간다.
0. Preflight (필수)
[ "${HERDR_ENV:-0}" = "1" ] || { echo "not inside herdr — stop"; exit 1; }
command -v herdr >/dev/null || { echo "herdr CLI missing"; exit 1; }
command -v claude >/dev/null || { echo "claude CLI missing"; exit 1; }
command -v codex >/dev/null || { echo "codex CLI missing"; exit 1; }
[ -n "${HERDR_PANE_ID:-}" ] || { echo "HERDR_PANE_ID 미설정 — 내 pane 식별 불가, stop (focused 추측으로 fallback 하지 않음)"; exit 1; }
LAUNCHER_INFO=$(herdr pane get "$HERDR_PANE_ID")
LAUNCHER_PANE=$(echo "$LAUNCHER_INFO" | jq -r '.result.pane.pane_id')
LAUNCHER_WS=$(echo "$LAUNCHER_INFO" | jq -r '.result.pane.workspace_id')
LAUNCHER_TAB=$(echo "$LAUNCHER_INFO" | jq -r '.result.pane.tab_id')
[ -n "$LAUNCHER_PANE" ] && [ "$LAUNCHER_PANE" != "null" ] || { echo "cannot resolve launcher pane from HERDR_PANE_ID — stop"; exit 1; }
[ -n "$LAUNCHER_WS" ] && [ "$LAUNCHER_WS" != "null" ] || { echo "cannot resolve launcher workspace from HERDR_PANE_ID — stop"; exit 1; }
[ -n "$LAUNCHER_TAB" ] && [ "$LAUNCHER_TAB" != "null" ] || { echo "cannot resolve launcher tab from HERDR_PANE_ID — stop"; exit 1; }
echo "launcher: pane=$LAUNCHER_PANE ws=$LAUNCHER_WS tab=$LAUNCHER_TAB (HERDR_PANE_ID=$HERDR_PANE_ID)"
1. 호출자 결정 변수
호출자(Claude Code 또는 Codex)는 routing gate 를 통과한 뒤에만 두 배열을 정의한다.
배열에는 subagent 로 처리할 작업을 넣지 않고, 실제 visible TUI/session boundary 가 필요한
worker 만 넣는다.
WORKER_CMDS=(
"claude --dangerously-skip-permissions"
"codex --dangerously-bypass-approvals-and-sandbox"
)
WORKER_PROMPTS=(
"$PROMPT_FOR_SLOT_0"
"$PROMPT_FOR_SLOT_1"
)
WORKER_MODELS=(
)
WORKER_MODES=(
)
WORKER_BROWSER=(
)
N=${#WORKER_CMDS[@]}
[ "$N" -eq "${#WORKER_PROMPTS[@]}" ] || { echo "len(WORKER_CMDS) != len(WORKER_PROMPTS)"; exit 1; }
[ "$N" -ge 1 ] || { echo "N must be >= 1"; exit 1; }
declare -a WORKER_MODES=("${WORKER_MODES[@]}")
for ((i=0; i<N; i++)); do : "${WORKER_MODES[$i]:=plain}"; done
declare -a WORKER_MODELS=("${WORKER_MODELS[@]}")
for ((i=0; i<N; i++)); do : "${WORKER_MODELS[$i]:=}"; done
declare -a WORKER_BROWSER=("${WORKER_BROWSER[@]}")
for ((i=0; i<N; i++)); do : "${WORKER_BROWSER[$i]:=0}"; done
: "${KEEP_TABS:=0}"
: "${TIMEOUT_MS:=600000}"
협업 패턴 예시 (호출자가 prompt 단계에서 결정):
- visible CLI 비교 → claude/codex 각각이 실제 TUI 세션이어야 할 때만 각 slot 에 배치.
- external state split → browser 인증·계정·cwd 관찰 상태가 다른 worker 만 slot 에 배치.
- 단순 fan-out / 리뷰 관점 분리 → 새 pane 대신 subagent/lightweight delegation 우선.
- 역할 분담 → slot 별로 claude/codex 비율 + prompt 를 매핑하되, pane 이 필요한 역할만 포함.
(v0.3) effort 계층 규약 — ultracode/xhigh 워커에 prompt 를 줄 때 다음 한 줄을
접미로 포함해 비용을 계층화한다: "workflow 를 쓸 때 subagent 는 low effort 로 생성해
비용을 절감하고, 너(orchestrator pane)만 xhigh 로 판단해라." — pane(세션) effort 는
herdr 가 WORKER_MODES/toggle_mode 로 제어하지만, pane 밖 subagent 와 워커가 띄우는
workflow subagent 의 effort 는 별도 delegation/prompt 규약으로 강제.
2. workspace 결정 (호출자 workspace 공유 — 새로 만들지 않음)
worker 는 호출자와 같은 workspace 에 둔다 (새 workspace 를 만들면 workspace 가
계속 쌓여 불편). 격리는 workspace 가 아니라 tab 단위로 한다 — 3단계에서 worker 마다
새 tab 을 만들고 LAUNCHER_TAB(orchestrator 본인 tab)은 건드리지 않는다. cwd 는 기존과
동일하게 $PWD 를 따른다.
WS_ID="$LAUNCHER_WS"
SLUG="herdr-orc-$(date +%Y%m%d-%H%M%S)"
파일시스템까지 격리하려면(같은 repo 동시 쓰기 충돌 방지) 이 skill 범위 밖의
herdr worktree / git worktree 를 호출자가 별도로 준비한다. workspace 분리는
herdr UI 상의 분리였을 뿐 cwd 격리가 아니었다 (worker cwd 는 늘 $PWD).
3. worker pane spawn (3×3 grid + tab spillover)
build_grid_in_tab() {
local TAB_ID="$1" COUNT="$2"
[ "$COUNT" -gt 9 ] && COUNT=9
local root
root=$(herdr pane list --tab "$TAB_ID" | jq -r '.result.panes[0].pane_id')
local cols_needed=$(( (COUNT + 2) / 3 ))
local -a col=( "$root" )
for ((c=1; c<cols_needed; c++)); do
col+=( "$(herdr pane split "${col[$((c-1))]}" --direction right --no-focus \
| jq -r '.result.pane.pane_id')" )
done
local -a slots=()
local placed=0
for ((c=0; c<cols_needed; c++)); do
local rows_in_col=$(( COUNT - placed ))
[ "$rows_in_col" -gt 3 ] && rows_in_col=3
local r0="${col[$c]}"
slots+=( "$r0" ); placed=$((placed+1))
local prev="$r0"
for ((r=1; r<rows_in_col; r++)); do
prev=$(herdr pane split "$prev" --direction down --no-focus \
| jq -r '.result.pane.pane_id')
slots+=( "$prev" ); placed=$((placed+1))
done
done
echo "${slots[@]}"
}
declare -a TAB_IDS=()
declare -a PANES=()
remaining=$N
batch=0
while [ "$remaining" -gt 0 ]; do
batch=$((batch+1))
TID=$(herdr tab create --workspace "$WS_ID" --cwd "$PWD" --no-focus \
| jq -r '.result.tab.tab_id')
[ -n "$TID" ] && [ "$TID" != "null" ] || { echo "tab create 실패 — abort"; exit 1; }
[ "$TID" = "$LAUNCHER_TAB" ] && { echo "새 tab 이 LAUNCHER_TAB 과 충돌 — abort"; exit 1; }
herdr tab rename "$TID" "${SLUG}-${batch}"
TAB_IDS+=( "$TID" )
this_count=$(( remaining > 9 ? 9 : remaining ))
read -r -a NEW_PANES <<< "$(build_grid_in_tab "$TID" "$this_count")"
PANES+=( "${NEW_PANES[@]}" )
remaining=$(( remaining - this_count ))
done
claude_acct_prefix() {
local I="$1"
if [ "${WORKER_BROWSER[$I]:-0}" = "1" ]; then
printf '%s' '{ type ccq >/dev/null 2>&1 && ccq >/dev/null || { export CLAUDE_CONFIG_DIR="$HOME/.claude"; unset CLAUDE_CODE_OAUTH_TOKEN; }; } && '
else
printf '%s' '{ type ccp >/dev/null 2>&1 && ccp >/dev/null || { export CLAUDE_CONFIG_DIR="$HOME/.claude-personal"; export CLAUDE_CODE_OAUTH_TOKEN="$(security find-generic-password -s Claude-personal-oauth-token -w 2>/dev/null)"; }; [ -n "${CLAUDE_CODE_OAUTH_TOKEN:-}" ] || { echo "ccp 개인 토큰 미설정 — 개인 계정으로 claude 못 띄움 (ccp-token-save 먼저)"; exit 1; }; } && '
fi
}
build_launch() {
local I="$1"
local CMD="${WORKER_CMDS[$I]}" MODEL="${WORKER_MODELS[$I]:-}" MODE="${WORKER_MODES[$I]:-plain}"
case "$CMD" in
claude*)
[ -n "$MODEL" ] && CMD="$CMD --model $MODEL"
CMD="$(claude_acct_prefix "$I")$CMD"
;;
codex*)
[ -n "$MODEL" ] && CMD="$CMD -m $MODEL"
[ "$MODE" != "plain" ] && CMD="$CMD -c model_reasoning_effort=\"$MODE\""
;;
esac
printf '%s' "$CMD"
}
for ((i=0; i<N; i++)); do
herdr pane run "${PANES[$i]}" "$(build_launch "$i")"
done
WORKER_CMDS 에는 prompt 가 없다 (불변 규칙). claude -p / codex exec 같은
headless one-shot 으로 띄우지 말 것 — 사용자가 못 보고 즉시 끝난다.
CLI 가 prompt 입력 가능 상태가 되도록 잠깐 대기 (claude / codex 시작 대기). 안전한
방법은 각 worker pane 에서 "ready" 신호를 wait output 으로 받는 것:
for ((i=0; i<N; i++)); do
herdr wait output "${PANES[$i]}" --match ">" --timeout 30000 || true
done
3.5 worker tab 보이기 (focus — 필수)
worker TUI 가 다 떴으면 사용자가 실시간으로 볼 수 있도록 worker 의 첫 tab 으로 focus
를 전환한다. orchestrator 본인 pane(LAUNCHER_TAB)은 같은 workspace 의 다른 tab 에서
백그라운드로 계속 동작하므로 focus 를 옮겨도 조율은 멈추지 않는다.
herdr tab focus "${TAB_IDS[0]}"
4. prompt 주입 (격리 가드)
is_worker_tab() {
local T="$1"
[ "$T" = "$LAUNCHER_TAB" ] && return 1
local wt
for wt in "${TAB_IDS[@]}"; do [ "$wt" = "$T" ] && return 0; done
return 1
}
send_prompt() {
local PANE="$1" PROMPT="$2"
local PANE_TAB
PANE_TAB=$(herdr pane list \
| jq -r --arg p "$PANE" '.result.panes[] | select(.pane_id==$p) | .tab_id')
is_worker_tab "$PANE_TAB" || { echo "pane $PANE tab($PANE_TAB) is not a worker tab — abort"; return 1; }
echo "send: from=orchestrator(tab:$LAUNCHER_TAB) to=$PANE(tab:$PANE_TAB)"
herdr pane send-text "$PANE" "$PROMPT"
local TAIL; TAIL="$(printf '%s' "$PROMPT" | tail -c 24)"
herdr wait output "$PANE" --match "$TAIL" --timeout 5000 >/dev/null 2>&1 || true
herdr pane send-keys "$PANE" Enter
}
for ((i=0; i<N; i++)); do
[ "${WORKER_MODES[$i]}" != "plain" ] && toggle_mode "$i" "${WORKER_MODES[$i]}"
send_prompt "${PANES[$i]}" "${WORKER_PROMPTS[$i]}" || exit 1
done
for ((i=0; i<N; i++)); do
herdr wait agent-status "${PANES[$i]}" --status running --timeout 15000 >/dev/null 2>&1 \
|| { echo "slot $i 미시작 의심 (Enter 누락?) — Enter 재송신"; herdr pane send-keys "${PANES[$i]}" Enter; }
done
4.5 toggle_mode — 세션 중간 effort/모드 전환 (v0.3)
워커 pane 의 effort/모드를 세션 중간에 싸게 전환하는 primitive. Opus 4.8 의
mid-conversation system message 덕에, Claude Code 가 /effort 슬래시를 messages 배열
꼬리에 system 엔트리로 반영 → 앞선 긴 컨텍스트의 prompt cache 가 보존된다
(top-level system 수정 시 발생하는 전체 재처리를 회피). 즉 "평소엔 가볍게, 깊은
구간에서만 ultracode" 운영이 경제적이다.
toggle_mode() {
local I="$1" MODE="$2"
local PANE="${PANES[$I]}" CMD="${WORKER_CMDS[$I]}"
case "$CMD" in
claude*) : ;;
*) echo "toggle_mode: slot $I 는 claude 가 아님 ($CMD) — skip"; return 0 ;;
esac
case "$MODE" in
max|xhigh|high|medium|low|auto|ultracode) : ;;
*) echo "toggle_mode: 알 수 없는 mode '$MODE'"; return 1 ;;
esac
local PANE_TAB
PANE_TAB=$(herdr pane list \
| jq -r --arg p "$PANE" '.result.panes[] | select(.pane_id==$p) | .tab_id')
is_worker_tab "$PANE_TAB" || { echo "toggle_mode: pane $PANE tab($PANE_TAB) is not a worker tab — abort"; return 1; }
echo "toggle_mode: slot $I (tab:$PANE_TAB) → /effort $MODE"
herdr pane send-text "$PANE" "/effort $MODE"
herdr pane send-keys "$PANE" Enter
herdr wait output "$PANE" --match "$MODE" --timeout 8000 \
|| echo "toggle_mode: slot $I effort 라벨 확인 실패 (계속 진행)"
}
단계별 재-escalation (선택, 고급) — 한 워커를 "가볍게 1차 → 깊게 2차" 로 운영.
1차 완료를 기다린 뒤 ultracode 로 올리고 후속 prompt 를 던진다. cache 가 보존되므로
1차 컨텍스트를 그대로 들고 깊이만 키운다:
herdr wait agent-status "${PANES[0]}" --status done --timeout "$TIMEOUT_MS"
toggle_model 0 fable
toggle_mode 0 xhigh
send_prompt "${PANES[0]}" "1차 결과를 바탕으로, workflow 로 전 구간을 교차검증해줘."
4.6 toggle_model — 세션 중간 모델 전환 (v0.5, claude 전용)
claude worker pane 의 모델을 세션 중간에 바꾸는 primitive. /model <name> 슬래시를 주입한다
(effort 의 /effort 와 동형). codex 는 /model 이 인터랙티브 picker 라 send-text 로 못 몰아
skip — codex 모델은 spawn 시 -m 플래그로만 정한다(build_launch). 모델 교체는 모델-스코프
캐시를 새로 쓰므로 effort 슬래시만큼 cache 를 보존하진 않으나, 컨텍스트(메시지)는 유지된다.
사용처: "가볍게 1차(싼 모델) → 깊게 2차(최강 모델)" 단계 escalation, 또는 1차 결과로 난이도를
재평가해 모델을 올리/내릴 때.
toggle_model() {
local I="$1" MODEL="$2"
local PANE="${PANES[$I]}" CMD="${WORKER_CMDS[$I]}"
case "$CMD" in
claude*) : ;;
*) echo "toggle_model: slot $I 는 claude 가 아님 ($CMD) — skip (codex 는 -m 로 spawn 시 고정)"; return 0 ;;
esac
[ -n "$MODEL" ] || { echo "toggle_model: 빈 모델 이름"; return 1; }
local PANE_TAB
PANE_TAB=$(herdr pane list \
| jq -r --arg p "$PANE" '.result.panes[] | select(.pane_id==$p) | .tab_id')
is_worker_tab "$PANE_TAB" || { echo "toggle_model: pane $PANE tab($PANE_TAB) is not a worker tab — abort"; return 1; }
echo "toggle_model: slot $I (tab:$PANE_TAB) → /model $MODEL"
herdr pane send-text "$PANE" "/model $MODEL"
herdr pane send-keys "$PANE" Enter
herdr wait output "$PANE" --match "$MODEL" --timeout 8000 \
|| echo "toggle_model: slot $I 모델 라벨 확인 실패 (계속 진행)"
}
5. 병렬 대기
declare -a WAIT_PIDS=()
declare -a WAIT_RCS=()
for ((i=0; i<N; i++)); do
herdr wait agent-status "${PANES[$i]}" --status done --timeout "$TIMEOUT_MS" &
WAIT_PIDS+=( "$!" )
done
for ((i=0; i<N; i++)); do
wait "${WAIT_PIDS[$i]}"
WAIT_RCS+=( "$?" )
done
WAIT_RCS[i] != 0 인 slot 은 실패 (timeout / blocked).
6. 결과 회수
declare -a OUTPUTS=()
for ((i=0; i<N; i++)); do
OUTPUTS+=( "$(herdr pane read "${PANES[$i]}" \
--source recent-unwrapped --lines 300)" )
done
herdr tab focus "$LAUNCHER_TAB"
orchestrator (호출자) 가 ${OUTPUTS[@]} 를 자연어로 사용자에게 정리 보고. 집계
포맷은 호출자 재량 — 비교 / 합치기 / 요약 자유.
7. Cleanup (v0.9 — 작업 완료 시 worker tab 자동 close)
worker tab 은 이 task 가 만든 것이므로, 작업이 끝나면 기본적으로 orchestrator 가
자기가 연 worker tab(TAB_IDS)을 닫는다. tab 을 쌓아두지 않는 게 기본이다 (이전엔
사용자 확인을 기다렸지만, 닫지 않은 tab 이 누적돼 불편 → 자동 close 로 전환). 호출자
workspace 와 LAUNCHER_TAB 은 절대 닫지 않는다 — orchestrator 본인이 거기 있다.
판정은 tab 단위로 한다: 그 tab 의 모든 slot 이 성공(rc=0)이면 close, 하나라도
실패한 tab 은 디버깅용으로 보존한다. 전부 성공이면 worker tab 이 통째로 정리된다.
절차:
- orchestrator 가
${OUTPUTS[@]} 를 자연어로 사용자에게 보고한다.
- 성공한 tab 은 보고 직후 자동 close, 실패 slot 이 있는 tab 만 보존하고 tabs /
panes / rcs 를 안내한다.
- resume 한계: 닫으려는 pane 이 workflow 진행 중일 수 있으면 close 전 경고한다 (단,
여기서는 이미 5단계에서
agent-status done 까지 기다렸으므로 정상 흐름에선 안전).
if [ "${KEEP_TABS:-0}" = "1" ]; then
echo "KEEP_TABS=1 — worker tab 자동 close 생략, 전부 보존: ${TAB_IDS[*]}"
else
for ((b=0; b<${#TAB_IDS[@]}; b++)); do
t="${TAB_IDS[$b]}"
[ "$t" = "$LAUNCHER_TAB" ] && { echo "guard: refuse to close LAUNCHER_TAB"; continue; }
tab_ok=1
for ((i=b*9; i<(b+1)*9 && i<N; i++)); do
[ "${WAIT_RCS[$i]}" = "0" ] || { tab_ok=0; break; }
done
if [ "$tab_ok" = "1" ]; then
herdr tab close "$t" && echo "cleanup: worker tab $t closed (성공). workspace/LAUNCHER_TAB 보존."
else
echo "cleanup: worker tab $t 보존 — 실패 slot 있음(디버깅용)."
echo " tab=$t rcs(batch)=${WAIT_RCS[*]:$((b*9)):9}"
fi
done
fi
- default: 작업 완료 후 성공한 worker tab 은 자동 close, 실패 slot 이 있는 tab 만 보존.
KEEP_TABS=1: 자동 close 를 생략하고 worker tab 을 전부 유지 (사용자가 수동 정리).
호출자별 진입점
Claude Code 호출자
이 SKILL.md 자체가 발동하더라도 먼저 routing gate 를 통과해야 한다. 통과하지 못하면
subagent/lightweight delegation 으로 처리하고, 통과한 경우에만 위 워크플로우의 bash 스니펫을
단계별 실행한다. 호출자는 필요한 visible TUI/session boundary 만 WORKER_CMDS /
WORKER_PROMPTS 로 구성하고, 최종 ${OUTPUTS[@]} 을 자연어로 사용자에게 보고.
Codex 호출자
Codex CLI 는 SKILL.md 자동 발동 메커니즘이 없으므로, 사용자가 다음 중 하나로
진입:
- 사용자 prompt 에 "이 파일 따라줘:
claude-plugins/herdr/skills/herdr-orchestrator/SKILL.md" 명시.
- 또는 호출자 codex 세션에서
cat claude-plugins/herdr/skills/herdr-orchestrator/SKILL.md
를 먼저 읽고 동일 절차 수행.
Codex 호출자도 본인은 orchestrator 로 남는다. routing gate 를 통과한 경우에만 worker pane
(claude/codex 어느 쪽이든)을 호출자 workspace 안의 새 tab 에 별도 spawn 한다.
안전 / 격리 규칙 (요약)
- Routing gate 먼저 —
WORKER_CMDS 를 만들기 전에 subagent/lightweight delegation 으로
충분한지 판정한다. visible TUI, 별도 CLI/OAuth/browser/cwd 상태, 명시적 herdr pane 요청 중
하나도 없으면 새 tab/pane 을 만들지 않는다.
- HERDR_ENV 가드 — pane 생성 절차에 들어가면 skill 시작점에서 무조건 확인. 실패 시 stop.
- 새 tab 강제 + LAUNCHER_TAB 격리 — 호출자 workspace 를 공유하되, worker 는
매번 새 tab 에 만든다.
LAUNCHER_TAB(orchestrator 본인 pane) 및 기존 tab 은
재사용·split 금지. 새 workspace 는 만들지 않는다 (workspace 누적 방지).
- send 직전 worker-tab 검증 — pane 의 tab_id 가 worker
TAB_IDS 에 속하고
LAUNCHER_TAB 이 아닐 때만 송신 (is_worker_tab).
- (v0.9) 완료 시 자동 정리 (기본) — 작업이 끝나면 orchestrator 가 자기가 연
worker tab 을 닫는 게 기본이다. tab 단위로 모든 slot 성공이면 close, 실패 slot 이 있는
tab 만 보존(디버깅용)하고 tabs / panes / rcs 안내. workspace/LAUNCHER_TAB 은 절대
닫지 않는다.
KEEP_TABS=1 로 자동 close 비활성(전부 보존).
- 인증 정책 불변 — API 키 사용 금지. OAuth CLI 만.
- 인터랙티브 TUI only — worker 는 항상 TUI 로 띄우고 prompt 는
send-text 로
주입. claude -p / codex exec 등 headless one-shot 금지. spawn 후 worker
tab 으로 focus 전환해 사용자가 실시간 관찰 가능하게 함.
- (v0.3) 모드/모델 전환도 격리 가드 적용 —
toggle_mode·toggle_model 은
send_prompt 와 동일하게 송신 직전 pane tab_id 가 worker tab 인지(is_worker_tab)
검증. codex pane 에는 /effort·/model 슬래시를 보내지 않는다(no-op skip — codex
모델/effort 는 spawn 시 -m/-c 로만 고정).
- (v0.5) 최신 모델 확인 후 선택 — worker 모델 배정 전 런타임에 사용 가능 목록을
/model·--help 로 확인하고 구버전(opus-4-5 이하·sonnet-3.x·haiku-3.x 등)을 박지
않는다. 자기 기억으로 모델 ID 추측 금지. goalcraft//goal 활용은 호출자 재량(의무 아님).
- (v0.6) launcher 식별은
HERDR_PANE_ID 로 못 박는다 — LAUNCHER_WS/LAUNCHER_TAB/
LAUNCHER_PANE 은 Preflight 에서 herdr pane get "$HERDR_PANE_ID" 로 확정한다.
focused(사용자가 지금 보고 있는 pane)로 workspace/tab 을 절대 추정하지 않는다 —
orchestrator 가 도는 동안 focus 가 다른 workspace 로 이동하면 worker 가 그 엉뚱한
workspace 에 생성되기 때문(이번에 수정한 버그). HERDR_PANE_ID 미설정이면 stop —
focused 추측으로 fallback 하지 않는다 (pane list 출력엔 .result.focused 키 자체가
없어 과거 fallback 도 신뢰 불가였다).
- (v0.8) claude 워커 계정 분리 — claude 워커는 기본 개인(
ccp · ~/.claude-personal).
WORKER_BROWSER[i]=1 슬롯(claude-in-chrome/브라우저 조작)만 회사(ccq · ~/.claude,
claude-in-chrome 인증 보유 유일 프로필). build_launch()→claude_acct_prefix() 가 base
명령 앞에 prefix 합성. codex 워커엔 무효(ccq/ccp 는 claude 전용). ccq/ccp 는 ~/.zshrc 함수라
pane 셸에서 미정의일 수 있어 env 인라인 fallback 을 동반한다.
- (v0.9) send-text 직후 반드시 Enter — 모든 pane 메시지(
send_prompt·toggle_mode·
toggle_model·ad-hoc)는 send-text 후 곧바로 send-keys Enter 로 제출한다. Enter 가
빠지면 prompt 가 입력창에 남아 워커가 멈춘다(잦은 사고). 송신 후 워커 실행 시작을
확인하고, 미시작이면 Enter 를 재송신해 제출을 강제한다(빈 Enter 는 no-op 라 안전).
dynamic workflow 는 세션 종료 시 cross-session resume 불가 (다음 세션 fresh start).
herdr 워커 pane = 그 세션 자체이므로, workflow 진행 중인 pane 을 죽이면 그 안의
workflow 도 증발한다. cleanup(7단계)에서 "해당 pane 이 workflow 진행 중일 수 있으면
close 전 강한 경고" 를 안내할 것. (자동 감지는 v0.4 폴링 기능 — v0.3 은 문구 가드만.)
비기능 / 미구현 (v0.3 YAGNI)
다음은 본 버전 범위 밖. 필요해지면 별도 spec → 후속 버전.
- manifest.json / 영속 상태.
- resume 모드 (worker tab 닫히면 끝).
- 결과 자동 비교/diff/투표 알고리즘 — 호출자 자연어 처리.
- workflow 진행 폴링 중계 / 결과 펜스(
=== RESULT_JSON ===) 자동 파싱 — v0.4 후보.
- pane 수 × pane 당 동시성 ≤ 물리 코어 예산 자동 배분 — v0.4 후보.
- TDD 파이프라인 (RED/GREEN), 디자인 일치도 검증 등 풀 파이프라인.
- bats 테스트 — 본 버전은 SKILL.md 중심.
변경 이력
- v0.10 (2026-06-16) — subagent 우선 라우팅 + herdr pane 생성 최소화.
WORKER_CMDS 구성 전 필수 routing gate 를 추가해 visible TUI, 별도 CLI/OAuth/browser/cwd
상태, 명시적 herdr pane 요청 중 하나가 없으면 새 tab/pane 을 만들지 않도록 했다. "두 에이전트
병렬", "여러 worker 병렬", 리뷰 관점 fan-out 은 기본적으로 subagent/lightweight delegation 으로
처리하고, pane 이 필요한 경우에도 1개 핵심 pane + 내부 subagent 를 먼저 고려한다. interactive
TUI only, send-text 후 Enter, tab 격리, 자동 cleanup 불변 규칙은 pane 생성 이후 절차로 보존.
- v0.9 (2026-06-14) — 메시지 송신 Enter 강제 + 작업 완료 시 worker tab 자동 close(기본).
(1) "send-text 후 Enter 누락 → 워커 한참 멈춤" 사고 해소:
send_prompt 가 텍스트 안착을
확인한 뒤 반드시 Enter 로 제출(paste 레이스 방지)하고, prompt 주입 후 각 워커의 실행 시작을
확인해 미시작이면 Enter 를 재송신한다. "메시지 송신 불변" 절·안전 규칙 11 신설.
(2) Cleanup(7단계)을 "사용자 확인 후 보존(기본)" → "완료 시 성공 tab 자동 close, 실패 tab 만
보존(tab 단위 판정)" 으로 전환. KEEP_TABS 의미를 "자동 close opt-out" 으로 바꾸고(=1 이면
전부 유지), 안전 규칙 4 갱신.
- v0.8 (2026-06-13) — claude 워커 OAuth 계정 슬롯별 분리 (ccp 기본 / browser=ccq).
WORKER_BROWSER(slot 별 브라우저 필요 플래그) 추가, claude_acct_prefix() 신설(회사 ccq /
개인 ccp env prefix, ~/.zshrc 함수 우선 + env 인라인 fallback), build_launch() 의 claude
갈래가 prefix 를 base 명령 앞에 합성. claude-in-chrome 인증(.credentials.json)이
~/.claude(회사 harry)에만 있어 브라우저 워커는 회사 계정 필수 — 그 외 claude 워커는
개인(kangho) 한도로 분산. codex 워커엔 무효. "claude 워커 계정 분리" 인증 절·안전 규칙 10 신설.
- v0.6 (2026-06-10) — launcher 식별을
focused → HERDR_PANE_ID 로 전환 (worker 가
엉뚱한 workspace 에 생성되던 버그 수정). Preflight 가 herdr pane get "$HERDR_PANE_ID" 로
orchestrator 본인 pane 의 workspace_id/tab_id/pane_id 를 확정한다. 기존 코드는
.result.focused.* 를 먼저 보고 select(.focused==true) 로 fallback 했는데, (1) pane list
출력엔 .result.focused 키가 아예 없어 항상 fallback 으로 떨어졌고 (2) focused 는 "사용자가
지금 보고 있는 pane" 이라 orchestrator 가 도는 동안 다른 workspace 로 옮겨가면 worker tab 이
그 엉뚱한 workspace 에 만들어졌다. LAUNCHER_PANE 기록 추가, 안전 규칙 9 신설, HERDR_PANE_ID
미설정 시 stop(추측 fallback 금지). 위계 매핑·2단계 주석도 "focused 추측 아님" 으로 보강.
- v0.5 (2026-06-10) — worker model/effort 난이도별 자율 조정 + 최신 모델 확인 규약 +
goalcraft/
/goal 활용. WORKER_MODELS(slot 별 모델) 추가, build_launch() 로 launch 시
모델/effort 플래그 합성(claude --model, codex -m/-c model_reasoning_effort),
toggle_model()(claude /model mid-session 전환) 추가. "최신 모델 확인(구버전 하드코딩
금지 — Claude=Fable 출시, Codex 신모델)" 절·난이도→모델/effort 배정표·goalcraft 활용 절
신설. 격리 가드를 toggle_model 까지 확장. 또한 ultracode(Claude Code 별도 설정 =
xhigh + substantive task 자동 Workflow 오케스트레이션)를 effort 레벨과 분리 명시하고,
herdr 2단계 fan-out(pane→workflow subagent)·켜는 법(/effort ultracode 또는 자연어 워크플로
지시)·비용 계층을 다룬 ultracode 절 신설. effort 화이트리스트에 auto 추가.
- v0.4 (2026-06-09) — workspace 격리 → tab 격리 전환. 새 workspace 를 만들지
않고 호출자 workspace 를 공유, worker 는 매번 새 tab(
SLUG-batch)에 배치 (workspace
누적 불편 해소). LAUNCHER_TAB(orchestrator 본인 tab) 기록·격리, 격리 가드/cleanup 을
tab 기준으로 전환(is_worker_tab, herdr tab close — workspace/LAUNCHER_TAB 보존).
focus 전환도 workspace focus → tab focus. Preflight 의 focused pane 해석을
.result.panes[] | select(.focused==true) fallback 으로 보정.
- v0.3 (2026-05-29) —
WORKER_MODES + toggle_mode() (세션 중간 effort/모드 전환,
Opus 4.8 mid-conversation system message 로 cache 보존), effort 계층 규약, resume 한계
경고. spec: docs/superpowers/specs/2026-05-29-herdr-orchestrator-v0.3-toggle-mode.md.
- v0.2 — 인터랙티브 TUI only + focus 전환 + 확인 후 정리.
- v0.1 — 최초 spawn/대기/회수/정리 primitive.