| 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.