Multiplexers
tmux, zellij, and neither.
--mux picks the backend; left alone it looks for tmux first, then falls back to the zellij inside the binary. On Windows psmux, a tmux for Windows that st carries, takes tmux's place.
st --mux zellij # the carried zellij, even where tmux exists
st --mux none --command python3 # no multiplexer, and no persistence| tmux | zellij | none | |
|---|---|---|---|
| survives a dropped connection | yes | yes | no |
| each client gets its own current window | yes | no | n/a |
| window list from the bar | yes | yes | n/a |
| marks the current window | yes | no | n/a |
| workers (orchestration) | yes | no | no |
psmux keeps sessions across dropped connections like tmux, but runs one server per session and has no session groups, so the clients of a session share its current window. Workers run on it from psmux 3.4.0 and st 0.3.97, by adopting a running agent; st does not start new workers on Windows.
Persistence is the reason a multiplexer is here at all. ttyd SIGHUPs its child the moment a websocket closes and a reconnect gets a fresh pty, so with --mux none a screen lock, an app switch or a network change ends the session.
Per-client views
No browser attaches to your session directly. Each one gets its own session inside the same session group:
tmux new-session -A -s sophonz__a1b2c3d4 -t sophonzGroup members share one window list but keep an independent current window. aggressive-resize is set so a window is sized by the clients for which it is the current window rather than by every client in the group, so two clients on different windows each get their own size.
Two clients on the same window do not, and cannot: a window in a session group has one size for everybody. latest is the default here, so whoever acted most recently sets it and everyone sees whole lines.
When the window is wider than a browser can show anyway, the page shrinks its type until the line fits, and stops at 8px rather than rendering something unreadable.
zellij has no equivalent of a session group — a second client shares the session and its size — and the startup banner says so.
Restoring after a tmux crash
A tmux server that dies takes every shell and program in it along. st keeps a snapshot of the server every 10 seconds (sessions, windows, layouts, each pane's directory and what it was running) and sets it up again when the server it finds is not the one it last saw:
- Sessions come back with their names, windows, layouts and directories. A session that is already there is left alone.
- Agents continue their conversation. A Claude Code or Codex pane gets its resume line (
claude --resume <id>,codex resume <id>), and st presses Enter itself when it knows which conversation it was and that conversation is saved on this machine (st 0.3.94 or later). Otherwise the line is only typed, and the pane says why. The conversation id comes from the agent hooks or, for a coordinator and its workers, from the run's record (st 0.3.95 or later). - Other commands are not run again. Each pane says what it was running, then starts your shell. A build, a deploy or a migration is yours to press.
- The next
stsays "tmux stopped at 14:02 — st restored 3 sessions", with how many agents it resumed, and your phone gets a notification. - In the browser and the apps, a restored window is tagged restored in the windows list until something has run in it. An agent window whose line st only typed says so too.
After a restart of the computer, st does not restore by itself (st 0.3.95 or later). The last snapshot waits for you to decide: the desktop app asks, and st restore --pending shows it. Until then st does not start a session of its own, so the snapshot is not pushed aside. Declining keeps the snapshot; st restore --from <id> can still bring it back.
st restore --pending # a snapshot waiting after a restart
st restore # restore it
st restore --decline # leave it
st restore --list # the snapshots kept (five)
st restore --dry-run # what a restore would do, pane by pane
st restore --from <id> # restore one by hand
st restore --no-resume-agents # type the agents' lines without pressing Enter~/.sophonz/restore.json changes the defaults:
{ "auto": true, "resumeAgents": true, "scrollbackLines": 0 }"resumeAgents": false only types the agents' lines. scrollbackLines keeps each pane's last lines (kept on this machine only) and shows them in the restored pane. tmux kill-server looks the same as a crash; set "auto": false if you stop tmux on purpose and do not want it back. Closing a window or a session from the apps or the browser is not a crash: st records it at once, and closing the last session does not bring it back.
Restoring sets things up again. The agents' conversations continue from where they were last saved; nothing else does. Builds have to run again, unsaved edits are gone, and commands other than the agents' lines are yours to press. zellij brings its own sessions back (zellij attach <name>), so st leaves it alone.