tmux -V 성공. 실패하면 tmux 미설치로 보고하고 중단
현재 디렉터리가 git 저장소. 아니면 --scope all 사용 여부를 사용자에게 확인
Node 18+ (스크립트는 의존성 없는 .mjs)
<step n="2" name="병렬 수집·요약">
pane 이 3개 미만이면 직접 `capture --lines 160` 을 돌려 읽는다.
3개 이상이면 pane 당 서브에이전트 1개를 <b>한 번에</b> 띄운다. 각 서브에이전트에게 준다.
- 실행할 명령: `node <스킬경로>/scripts/tmux-capture.mjs capture --scope all --target <paneId> --lines 160`
- 아래 <status-rules> 전문
- 반환 스키마: <pane-report>
tail 원문을 메인 컨텍스트로 끌어오지 않는다. 서브에이전트가 읽고 요약본만 돌려준다.
필요하면 서브에이전트가 `--lines 400` 으로 한 번 더 파고들 수 있다고 알려 준다.
</step>
<step n="3" name="교차 분석">
요약본을 모아 다음을 판정한다. 근거 없는 추측은 쓰지 않는다.
- 같은 파일·같은 브랜치를 두 세션이 만지고 있는가 (dirtyFiles 와 요약의 대상 파일로)
- 같은 일을 중복해서 하고 있는가
- WAIT 인 세션이 있는가 — 사람이 막고 있는 것이므로 항상 최우선
- ERROR 가 다른 세션의 전제를 깨는가
</step>
<step n="4" name="보고">
<output-format> 를 <b>글자 그대로</b> 지킨다. 섹션 순서·라벨·상태 토큰을 바꾸지 않는다.
매번 같은 모양이어야 훑어보는 비용이 0 에 수렴한다.
</step>
<step n="5" name="전파" optional="true">
사용자가 전파를 요청했거나, 4단계에서 충돌·중복을 발견해 알릴 필요가 있을 때만 간다.
1. 세션별 전송 문구를 <b>초안으로 먼저 보여주고</b> 승인받는다. 승인 없이 보내지 않는다.
2. `--dry-run` 으로 대상과 본문을 확인한다.
3. 승인되면 dry-run 을 뺀 같은 명령을 돌린다.
4. 결과 JSON 의 `sent` 를 확인해 실패한 pane 을 그대로 보고한다.
전 세션 동일 문구면 `broadcast`, 세션마다 다르면 `send` 를 세션 수만큼.
</step>
WAIT 사람 입력에서 멈춰 있다. 권한 승인 프롬프트, 선택지 목록(`❯ 1.`, `Do you want`),
질문으로 끝난 응답, 빈 입력창에 커서만 있고 직전이 질문인 경우.
WORK 지금 돌고 있다. 스피너·경과시간 표시(`✻`, `esc to interrupt`, `Running`),
도구 호출이 열린 채 끝남, 빌드·테스트 로그가 흐르는 중.
DONE 마지막 응답이 완료 보고이고 더 시킬 것이 없어 대기 중.
ERROR 실패로 끝났다. traceback, `error`/`failed`/`exit 1`, hook 차단, merge conflict.
IDLE 쉘 프롬프트만 있고 에이전트가 떠 있지 않다.
UNKNOWN 위 어디에도 확신이 안 선다. 억지로 배정하지 말고 이걸 쓴다.
판정 근거는 반드시 tail 에서 인용한 한 줄로 남긴다. 인용할 줄이 없으면 UNKNOWN 이다.
```
# 세션 현황 — {저장소명} · {N}개 · {HH:MM}
STATUS SESSION BRANCH AGENT HEADLINE
------ ------------------------ ---------------- ------ ------------------------------
WAIT omc-foo-main-2026… feat/42-login claude 로그인 리다이렉트 승인 대기
WORK omx-foo-main-1785… fix/50-guard codex 가드 테스트 재실행 중
## {세션 이름}
- 지금 : {now}
- 최근 결과 : {lastResult}
- 막힌 것 : {blocker}
- 다음 조치 : {nextAction}
- 근거 : {evidence}
## 교차 분석
- 충돌 : {같은 파일·브랜치를 만지는 세션 쌍, 없으면 없음}
- 중복 : {같은 일을 하는 세션, 없으면 없음}
- 우선순위 : {지금 사람이 손대야 할 세션 순서와 이유}
## 전파 제안
- {세션} ← "{보낼 문구}"
- 명령: node {스킬경로}/scripts/tmux-send.mjs send --target {paneId} --message "{문구}" --dry-run
```
표는 고정폭 ASCII 로만 낸다. 마크다운 표를 쓰지 않는다.
SESSION 열은 24자에서 자르고 `…` 를 붙인다. 세션 카드는 STATUS 표와 같은 순서로 나열한다.
카드 5줄의 라벨과 순서를 바꾸지 않는다. 값이 없으면 "없음".
1---2name: tmux-orchestrate3description: 같은 프로젝트에서 동시에 굴리고 있는 여러 tmux 세션의 상태를 한 번에 파악하고 필요한 지시를 각 세션으로 전파합니다. 세션 목록을 뽑아 pane 별로 병렬 수집·요약하고, 항상 같은 양식(상태표 + 세션 카드 + 교차 분석 + 전파 제안)으로 보고합니다. "세션 현황", "지금 어디까지 됐지", "다른 창들 뭐 하고 있어", "세션 점검", "전부 어떻게 돼가", "다른 세션에 알려줘", "전 세션에 전파", "/tmux-orchestrate" 요청에 씁니다. 워크트리라 경로가 달라도 같은 git 저장소면 한 프로젝트로 묶습니다. 새 tmux 세션을 만들거나 작업을 분배하는 일, 단일 세션 안에서의 구현 작업에는 쓰지 않습니다.4---56<skill>7 <purpose>8 여러 세션에 작업을 흩뿌려 놓았을 때 "어디까지 갔는지" 를 잃어버리는 문제를 푼다.9 각 세션 화면을 병렬로 걷어와 상태를 판정하고, 늘 같은 양식으로 보고하고,10 필요하면 판정 결과를 근거로 각 세션에 지시를 전파한다.11 구현은 하지 않는다. 관측하고, 판정하고, 전달한다.12 </purpose>1314 <inputs>15 <arg name="$ARGUMENTS" optional="true">16 세션 이름 조각으로 대상을 좁힌다. 생략하면 같은 저장소의 모든 pane.17 "전파: <문구>" 형태면 수집·판정 후 전파까지 간다.18 </arg>19 <detected>현재 저장소의 git common-dir, 같은 common-dir 를 쓰는 모든 tmux pane</detected>20 </inputs>2122 <preconditions>23 <item>`tmux -V` 성공. 실패하면 tmux 미설치로 보고하고 중단</item>24 <item>현재 디렉터리가 git 저장소. 아니면 `--scope all` 사용 여부를 사용자에게 확인</item>25 <item>Node 18+ (스크립트는 의존성 없는 .mjs)</item>26 </preconditions>2728 <tools>29 <script path="scripts/tmux-capture.mjs">30 `list` 스코프 안의 pane 목록(JSON). `capture` 목록 + 각 pane 의 마지막 N 줄.31 pane 마다 session·target·paneId·cwd·branch·dirtyFiles·command·title·active·attached 를 붙인다.32 워크트리 판별은 git common-dir 로 하므로 경로가 달라도 같은 프로젝트로 묶인다.33 </script>34 <script path="scripts/tmux-send.mjs">35 `send --target <t> --message <m>` 한 pane 에. `broadcast --message <m>` 스코프 전체에.36 본문은 `send-keys -l` 로 리터럴 입력하고 Enter 는 지연 뒤 따로 보낸다.37 기본으로 개행을 공백으로 접는다 — 개행이 곧 제출인 TUI 에서 메시지가 잘려 나가는 것을 막기 위함.38 </script>39 </tools>4041 <workflow>42 <step n="1" name="스코프 확정">43 `node scripts/tmux-capture.mjs list` 를 돌린다. $ARGUMENTS 에 세션 조각이 있으면 `--target` 으로 넘긴다.44 exit 2(pane 0 개) 면 "이 저장소에 붙은 tmux 세션이 없다" 고 한 줄로 보고하고 끝낸다.45 자기 자신 pane 은 기본으로 빠진다. 이 단계는 tail 을 읽지 않는다 — 목록만 보고 다음 단계 규모를 정한다.46 </step>4748 <step n="2" name="병렬 수집·요약">49 pane 이 3개 미만이면 직접 `capture --lines 160` 을 돌려 읽는다.50 3개 이상이면 pane 당 서브에이전트 1개를 <b>한 번에</b> 띄운다. 각 서브에이전트에게 준다.51 - 실행할 명령: `node <스킬경로>/scripts/tmux-capture.mjs capture --scope all --target <paneId> --lines 160`52 - 아래 <status-rules> 전문53 - 반환 스키마: <pane-report>54 tail 원문을 메인 컨텍스트로 끌어오지 않는다. 서브에이전트가 읽고 요약본만 돌려준다.55 필요하면 서브에이전트가 `--lines 400` 으로 한 번 더 파고들 수 있다고 알려 준다.56 </step>5758 <step n="3" name="교차 분석">59 요약본을 모아 다음을 판정한다. 근거 없는 추측은 쓰지 않는다.60 - 같은 파일·같은 브랜치를 두 세션이 만지고 있는가 (dirtyFiles 와 요약의 대상 파일로)61 - 같은 일을 중복해서 하고 있는가62 - WAIT 인 세션이 있는가 — 사람이 막고 있는 것이므로 항상 최우선63 - ERROR 가 다른 세션의 전제를 깨는가64 </step>6566 <step n="4" name="보고">67 <output-format> 를 <b>글자 그대로</b> 지킨다. 섹션 순서·라벨·상태 토큰을 바꾸지 않는다.68 매번 같은 모양이어야 훑어보는 비용이 0 에 수렴한다.69 </step>7071 <step n="5" name="전파" optional="true">72 사용자가 전파를 요청했거나, 4단계에서 충돌·중복을 발견해 알릴 필요가 있을 때만 간다.73 1. 세션별 전송 문구를 <b>초안으로 먼저 보여주고</b> 승인받는다. 승인 없이 보내지 않는다.74 2. `--dry-run` 으로 대상과 본문을 확인한다.75 3. 승인되면 dry-run 을 뺀 같은 명령을 돌린다.76 4. 결과 JSON 의 `sent` 를 확인해 실패한 pane 을 그대로 보고한다.77 전 세션 동일 문구면 `broadcast`, 세션마다 다르면 `send` 를 세션 수만큼.78 </step>79 </workflow>8081 <status-rules>82 tail 의 <b>마지막 화면</b>을 기준으로 아래 6개 중 하나로만 판정한다. 새 토큰을 만들지 않는다.8384 WAIT 사람 입력에서 멈춰 있다. 권한 승인 프롬프트, 선택지 목록(`❯ 1.`, `Do you want`),85 질문으로 끝난 응답, 빈 입력창에 커서만 있고 직전이 질문인 경우.86 WORK 지금 돌고 있다. 스피너·경과시간 표시(`✻`, `esc to interrupt`, `Running`),87 도구 호출이 열린 채 끝남, 빌드·테스트 로그가 흐르는 중.88 DONE 마지막 응답이 완료 보고이고 더 시킬 것이 없어 대기 중.89 ERROR 실패로 끝났다. traceback, `error`/`failed`/`exit 1`, hook 차단, merge conflict.90 IDLE 쉘 프롬프트만 있고 에이전트가 떠 있지 않다.91 UNKNOWN 위 어디에도 확신이 안 선다. 억지로 배정하지 말고 이걸 쓴다.9293 판정 근거는 반드시 tail 에서 인용한 한 줄로 남긴다. 인용할 줄이 없으면 UNKNOWN 이다.94 </status-rules>9596 <pane-report>97 서브에이전트는 정확히 이 필드만 돌려준다. 산문 서술을 덧붙이지 않는다.98 ```json99 {100 "session": "omc-foo-main-20260101120000",101 "target": "omc-foo-main-20260101120000:0.0",102 "paneId": "%12",103 "branch": "feat/42-login",104 "dirtyFiles": 8,105 "agent": "claude|codex|shell|unknown",106 "status": "WAIT",107 "headline": "한 줄 요약 (40자 이내, 명사형)",108 "now": "지금 무엇을 하고 있는지 한 문장",109 "lastResult": "직전에 끝낸 일과 결과 한 문장",110 "blocker": "막고 있는 것 한 문장, 없으면 없음",111 "nextAction": "사람이 해야 할 다음 조치 한 문장",112 "touchedFiles": ["경로", "..."],113 "evidence": "판정 근거로 tail 에서 인용한 한 줄"114 }115 ```116 </pane-report>117118 <output-format>119 아래 4개 섹션을 이 순서로만 낸다. 빈 섹션은 "없음" 한 줄로 남기고 생략하지 않는다.120121 ```122 # 세션 현황 — {저장소명} · {N}개 · {HH:MM}123124 STATUS SESSION BRANCH AGENT HEADLINE125 ------ ------------------------ ---------------- ------ ------------------------------126 WAIT omc-foo-main-2026… feat/42-login claude 로그인 리다이렉트 승인 대기127 WORK omx-foo-main-1785… fix/50-guard codex 가드 테스트 재실행 중128129 ## {세션 이름}130 - 지금 : {now}131 - 최근 결과 : {lastResult}132 - 막힌 것 : {blocker}133 - 다음 조치 : {nextAction}134 - 근거 : {evidence}135136 ## 교차 분석137 - 충돌 : {같은 파일·브랜치를 만지는 세션 쌍, 없으면 없음}138 - 중복 : {같은 일을 하는 세션, 없으면 없음}139 - 우선순위 : {지금 사람이 손대야 할 세션 순서와 이유}140141 ## 전파 제안142 - {세션} ← "{보낼 문구}"143 - 명령: node {스킬경로}/scripts/tmux-send.mjs send --target {paneId} --message "{문구}" --dry-run144 ```145146 표는 고정폭 ASCII 로만 낸다. 마크다운 표를 쓰지 않는다.147 SESSION 열은 24자에서 자르고 `…` 를 붙인다. 세션 카드는 STATUS 표와 같은 순서로 나열한다.148 카드 5줄의 라벨과 순서를 바꾸지 않는다. 값이 없으면 "없음".149 </output-format>150151 <rules>152 <item>승인 없이 어떤 pane 에도 메시지를 보내지 않는다. 전파는 항상 초안 → 승인 → dry-run → 실행.</item>153 <item>`--allow-outside` 는 사용자가 명시적으로 다른 프로젝트를 지목했을 때만 쓴다.</item>154 <item>tail 원문을 보고서에 붙여넣지 않는다. 인용은 근거 한 줄까지.</item>155 <item>상태를 추측으로 채우지 않는다. 근거 줄이 없으면 UNKNOWN 이다.</item>156 <item>다른 세션의 작업을 이 세션에서 대신 구현하지 않는다. 전파해서 그 세션이 하게 한다.</item>157 <item>broadcast 는 전 세션에 같은 문구가 맞을 때만. 세션마다 맥락이 다르면 send 를 나눠 쓴다.</item>158 </rules>159160 <failure-modes>161 <item>`tmux -V` 실패 → tmux 미설치. 설치 안내 한 줄 후 중단.</item>162 <item>list exit 2 → 붙은 세션 없음. 한 줄 보고 후 종료. 세션을 새로 만들지 않는다.</item>163 <item>send 가 exit 2 → 대상 모호. 스크립트가 출력한 후보를 그대로 보여주고 paneId 로 다시 지정한다.</item>164 <item>send 가 exit 3 → 일부 전송 실패. 실패한 pane 을 숨기지 않고 그대로 보고한다.</item>165 <item>capture 결과가 비어 있음 → 그 pane 은 UNKNOWN. 다른 pane 보고를 막지 않는다.</item>166 </failure-modes>167</skill>