멀티플렉서
tmux, zellij, 그리고 둘 다 없을 때.
--mux 가 백엔드를 고릅니다. 그냥 두면 tmux를 먼저 찾고 없으면 바이너리 안의 zellij로 갑니다. Windows에서는 st가 담아 오는 Windows용 tmux, psmux가 tmux 자리를 대신합니다.
st --mux zellij # tmux가 있어도 동봉된 zellij로
st --mux none --command python3 # 멀티플렉서 없이 — 세션 유지도 없습니다| tmux | zellij | none | |
|---|---|---|---|
| 연결이 끊겨도 살아남는다 | 예 | 예 | 아니오 |
| 클라이언트마다 자기 현재 창 | 예 | 아니오 | 해당 없음 |
| 키바에서 윈도우 목록 | 예 | 예 | 해당 없음 |
| 현재 윈도우 표시 | 예 | 아니오 | 해당 없음 |
| 워커(오케스트레이션) | 예 | 아니오 | 아니오 |
psmux는 tmux처럼 연결이 끊겨도 세션을 유지하지만, 세션마다 서버를 하나씩 띄우고 세션 그룹이 없어서 한 세션의 클라이언트들이 그 세션의 현재 윈도우를 같이 씁니다. psmux 3.4.0과 st 0.3.97부터는 psmux에서도 워커가 실행됩니다. 실행 중인 에이전트를 데려오는 방식이고, st가 Windows에서 새 워커를 띄우지는 않습니다.
멀티플렉서가 여기 있는 이유는 지속성 하나입니다. ttyd는 웹소켓이 닫히는 순간 자식 프로세스에 SIGHUP을 보내고 다시 붙으면 새 pty를 줍니다. --mux none 으로는 화면 잠금, 앱 전환, 망 변경 하나하나가 세션의 끝입니다.
per-client 뷰
브라우저는 사용자의 세션에 직접 붙지 않습니다. 각자 같은 세션 그룹 안의 자기 세션을 받습니다:
tmux new-session -A -s sophonz__a1b2c3d4 -t sophonz그룹 멤버는 윈도우 목록을 공유하면서 현재 창은 각자 갖습니다. aggressive-resize 를 켜면 창은 그 창을 현재 창으로 보고 있는 클라이언트에 맞춰지므로, 서로 다른 창을 보는 두 클라이언트는 각자의 크기를 갖습니다.
같은 창을 보는 두 클라이언트는 그럴 수 없습니다. 세션 그룹에서 창 크기는 모두에게 하나입니다. 기본값은 latest 라, 가장 최근에 움직인 쪽이 크기를 정하고 모두가 온전한 줄을 봅니다.
그래도 창이 브라우저보다 넓으면, 페이지가 줄이 들어갈 때까지 글꼴을 줄입니다. 읽을 수 없는 것을 그리느니 8px에서 멈춥니다.
zellij에는 세션 그룹에 해당하는 것이 없어 두 번째 클라이언트가 같은 세션과 크기를 공유합니다. 시작 화면이 그 사실을 알려줍니다.
tmux 서버가 죽었을 때
tmux 서버가 죽으면 그 안의 셸과 프로그램도 함께 종료됩니다. st는 10초마다 서버의 스냅샷(세션, 창, 레이아웃, 각 패널의 디렉터리와 실행 중이던 프로그램)을 기록하고, 마지막으로 확인한 서버가 아닌 서버를 발견하면 이를 다시 구성합니다.
- 세션은 이름, 창, 레이아웃, 디렉터리가 그대로 복원됩니다. 이미 있는 세션은 변경하지 않습니다.
- 에이전트는 대화를 이어 갑니다. Claude Code나 Codex 패널에는 이어가기 명령(
claude --resume <id>,codex resume <id>)이 입력되고, st가 어느 대화였는지 알고 그 대화가 이 장치에 저장되어 있으면 Enter까지 직접 누릅니다(st 0.3.94 이상). 그렇지 않으면 명령만 입력해 두고, 그 이유를 패널에 표시합니다. 대화 id는 에이전트 훅에서, 코디네이터와 워커는 실행 기록에서도 가져옵니다(st 0.3.95 이상). - 그 밖의 명령은 다시 실행하지 않습니다. 각 패널은 실행 중이던 프로그램을 표시한 뒤 셸을 시작합니다. 빌드, 배포, 마이그레이션은 사용자가 직접 실행합니다.
- 다음
st가 "tmux stopped at 14:02 — st restored 3 sessions"와 함께 이어 간 에이전트 수를 알려 주고, 폰에도 알림이 전송됩니다. - 브라우저와 앱에서는 복원된 창에 창 목록의 restored 표시가 붙고, 그 창에서 무언가가 실행되면 사라집니다. st가 명령만 입력해 둔 에이전트 창은 그 사실도 함께 표시합니다.
컴퓨터를 재시작한 뒤에는 st가 스스로 복원하지 않습니다(st 0.3.95 이상). 마지막 스냅샷은 사용자가 결정할 때까지 대기합니다. 데스크톱 앱이 복원 여부를 묻고, st restore --pending으로도 확인할 수 있습니다. 그동안 st는 자체 세션을 만들지 않으므로 스냅샷이 밀려나지 않습니다. 거절해도 스냅샷은 남으며, st restore --from <id>로 나중에 복원할 수 있습니다.
st restore --pending # 재시작 뒤 대기 중인 스냅샷
st restore # 그 스냅샷 복원
st restore --decline # 복원하지 않음
st restore --list # 보관된 스냅샷(다섯 개)
st restore --dry-run # 복원하면 패널마다 무엇을 할지
st restore --from <id> # 하나를 선택해 직접 복원
st restore --no-resume-agents # 에이전트 명령을 입력만 하고 Enter는 누르지 않음~/.sophonz/restore.json으로 기본값을 변경합니다.
{ "auto": true, "resumeAgents": true, "scrollbackLines": 0 }"resumeAgents": false로 설정하면 에이전트 명령을 입력만 합니다. scrollbackLines는 패널마다 마지막 줄들을 이 장치에만 보관했다가 복원한 패널에 표시합니다. tmux kill-server도 크래시와 구별되지 않으므로, 의도적으로 종료한 tmux가 복원되지 않기를 원하면 "auto": false로 설정합니다. 앱이나 브라우저에서 창이나 세션을 닫는 것은 크래시가 아닙니다. st가 즉시 기록하며, 마지막 세션을 닫아도 다시 복원하지 않습니다.
복원은 환경을 다시 구성하는 것입니다. 에이전트의 대화는 마지막으로 저장된 지점부터 이어지지만, 그 밖의 작업은 이어지지 않습니다. 빌드는 다시 실행해야 하고, 저장하지 않은 편집 내용은 남지 않으며, 에이전트 명령 외의 명령은 사용자가 직접 실행합니다. zellij는 세션을 스스로 복원하므로(zellij attach <이름>) st가 관여하지 않습니다.