a73x

d825ab6a

docs: a daemon lives until muxd stop

a73x   2026-08-28 19:53

Commit message
docs: a daemon lives until muxd stop

The invariant, the decision and the user-facing sentence for the change
above: `x` ends a session and never a box, an emptied daemon stays up to
be born into, and `muxd run`'s only nonzero exit is a boot failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

CLAUDE.md
Old New
@@ -117,6 +117,13 @@ real pty), `wsclient` (browser stand-in), `rawmode`, `delaypipe`, `render`.
117 a masterless pty across the exec. A daemon with no arm answers nothing 117 a masterless pty across the exec. A daemon with no arm answers nothing
118 and the client banners `[daemon too old to end a session]`. The tile 118 and the client banners `[daemon too old to end a session]`. The tile
119 leaves on the next list, not on the keypress. 119 leaves on the next list, not on the keypress.
120 - **A daemon lives until `muxd stop`; emptiness is not an exit.** `x` ends a
121 session, never a box: `reap` and `pumpOnce` answer nothing, a shell's code
122 reaches that shell's own clients as `exit_status`, and an emptied daemon
123 keeps serving so a birth can take the default name back. One idle process
124 per machine is the accepted cost. `muxd run` exits 0 on every shutdown —
125 a supervisor reads nonzero on a clean stop as a crash — and nonzero only
126 for the boot failures `main.run` picks before anything binds.
120 - **The layout sidecar is derived convenience, not authored intent.** 127 - **The layout sidecar is derived convenience, not authored intent.**
121 `$XDG_STATE_HOME/mux/layout` stores the pane tree on last detach, from 128 `$XDG_STATE_HOME/mux/layout` stores the pane tree on last detach, from
122 every wall left on a TERMINAL (`shared.is_tty`) — a piped `mux` is a wall 129 every wall left on a TERMINAL (`shared.is_tty`) — a piped `mux` is a wall
README.md
Old New
@@ -114,6 +114,11 @@ later; there is no session that cannot be ended. Dropping a whole MACHINE
114 is `mux hosts rm`, not a chord: it is rarer than ending a shell and must not 114 is `mux hosts rm`, not a chord: it is rarer than ending a shell and must not
115 sit one key from `n`. 115 sit one key from `n`.
116 116
117 `x` ends a session, never a box. A daemon whose last session ends stays up
118 and empty, and the next `mux HOST` is born into it — so emptying a machine
119 costs you nothing but the shell you meant to end. Ending the daemon itself
120 is `muxd stop`.
121
117 A session whose shell exits ends `mux` with that shell's exit code when it 122 A session whose shell exits ends `mux` with that shell's exit code when it
118 was the only tile on the wall — so `mux` stays something you can put in a 123 was the only tile on the wall — so `mux` stays something you can put in a
119 script — and drops you to the wall when it was not, with the tile that ended 124 script — and drops you to the wall when it was not, with the tile that ended
@@ -505,7 +510,9 @@ wins). A session survives logout (this assumes systemd-logind's default
505 `KillUserProcesses=no`; a box configured to kill user processes at logout 510 `KillUserProcesses=no`; a box configured to kill user processes at logout
506 kills the daemon with them), though not a reboot. 511 kills the daemon with them), though not a reboot.
507 `muxd run` refuses a socket another daemon already owns; there is no 512 `muxd run` refuses a socket another daemon already owns; there is no
508 socket-stealing. 513 socket-stealing. It runs until something stops it — no session's exit ends
514 it — and exits 0 when `muxd stop` or a supervisor's SIGTERM asks; a nonzero
515 exit means it never got as far as serving.
509 516
510 Rolling a new daemon out does **not** mean killing the sessions. Install the 517 Rolling a new daemon out does **not** mean killing the sessions. Install the
511 new binary and run `muxd upgrade` — the new binary asks the running daemon 518 new binary and run `muxd upgrade` — the new binary asks the running daemon
docs/decisions.md
Old New
@@ -7302,3 +7302,22 @@ writes that file any more, so a fresh machine's hub wall is empty until
7302 someone names tiles on its command line or in the page. Stated in the README 7302 someone names tiles on its command line or in the page. Stated in the README
7303 rather than smoothed over, because a hub that quietly shows a different wall 7303 rather than smoothed over, because a hub that quietly shows a different wall
7304 from the terminal is the two-lists bug again, one layer out. 7304 from the terminal is the two-lists bug again, one layer out.
7305
7306 ## 2026-08-28 — a daemon lives until `muxd stop`
7307
7308 **`x` ends a session, never a box.** `reap` returned the last dead shell's
7309 code and `pumpOnce` handed it to `run`, so a daemon left with its last
7310 session. Invisible while the wall listed daemons from a file; with the wall
7311 listing live sessions and a picker offering hosts to be born into, it means
7312 emptying a host destroys it and the picker offers what is not there.
7313
7314 So `reap` and `pumpOnce` answer nothing. A shell's code goes to that shell's
7315 own clients (`exit_status`) and nowhere else; an emptied table is a daemon
7316 with nothing on it. The picker says `no sessions`, a birth brings it back,
7317 and one idle process per machine is the accepted cost — one daemon per
7318 machine is the real use.
7319
7320 `muxd run` exits 0 on every shutdown, `muxd stop` and SIGTERM alike: a
7321 supervisor reads a nonzero exit on a clean stop as a crash. Nonzero is a boot
7322 failure only, stated in `main.run`'s doc block. The 130 that imitated SIGINT
7323 went with the shell's code.