Changed
- wmux describes itself as the workspace multiplexer for AI agents, not AI coding agents. The panes, channels, worktrees, and browser wmux multiplexes were never specific to agents that write code, and the narrower line kept implying they were. README, the package description, and the Chocolatey summary now say "AI agents"; nothing about what wmux detects or how it behaves changes.
Added
- A phone that is too old to talk to your daemon can now say so. The phone API had no version on it, so once a mobile build ships it is pinned to whatever HTTP surface the daemon happens to serve — and a mismatch would have surfaced as routes failing one by one with no explanation.
GET /api/config, the call a client already makes at connect, now reports the protocol the daemon speaks, the oldest one it still accepts, and the release it was spawned from. A client below the floor can show "update the app" instead of a broken screen. Nothing that already works changes: a daemon predating this simply has no version fields, which reads as the pre-handshake protocol, and a phone that ignores them behaves exactly as it does today.
Fixed
-
The cold-start perf gate no longer fails the build because CI got a slow machine. The gate compared the median of three boots against a blessed baseline, and its only defence against a noisy runner was to measure again — on the same runner. That covers a spike lasting a second; it does not cover a host that is degraded for the whole job. One was on 2026-07-27: the daemon needed 2.2s just to spawn its Node process and 2.0s to take a file lock, the median landed at 2470ms against a 1207ms baseline, the re-run reproduced it exactly as designed, and main went red over a commit whose entire diff was the length of a web pairing code. The gate now reads the fastest of the boots, because interference is one-sided — a busy host makes a boot slower, never faster — so the fastest one is the sample least polluted by the machine. That run would have read 1442ms and passed; a real regression slows every boot and still trips both thresholds. The median is still measured, still published to the trend, and now reported on its own when it regresses while the fastest boot does not, since a slowdown only some boots hit is worth a look even though it is not worth a red build.
-
The "Serve panes to a browser" Start button no longer fails with "tailscale is not on PATH" when Tailscale is installed. On macOS, an app launched from the Dock inherits launchd's minimal PATH, so the GUI could not find a
tailscaleCLI that worked fine in a terminal — the HTTPS option failed withspawn tailscale ENOENTeven with the desktop app installed. The GUI now searches the way a shell would (Homebrew,/usr/local/bin,~/.local/bin) and falls back to the CLI inside/Applications/Tailscale.appitself, which a stock install never puts on any PATH.wmux web --tailscalein a terminal was never affected. -
A pane no longer goes dead while the shell inside it keeps running. On Windows, node-pty sometimes reports that a terminal exited when in fact only its output socket closed — the code it hands back is empty, and
powershell.exeand whatever agent it was hosting are still very much alive. wmux believed the report, marked the pane dead, and walked away, which meant an agent kept burning memory and API quota with nothing left to reach it or shut it down, and the pane came back in your home directory instead of your project. wmux now asks the operating system whether the process is actually gone before believing any exit that arrives without a code. If it is still there, wmux shuts the whole tree down itself — the shell and everything it started — and closes the pane properly, saying so in the log. The exact report from the terminal layer is logged verbatim, which is what the underlying investigation needs. Real exits are untouched: an exit that carries a code, or a signal, still behaves exactly as before. (#646) -
Shells orphaned by that bug are now cleaned up at startup. Because the pane had already been written off, nothing ever reaped those processes — one report found shells still running eleven and twelve days after the daemon that spawned them had gone. On startup wmux now checks its own records of closed panes: if one still points at a running process, and the machine has not rebooted since (so the process id can't belong to something else), and it really is the shell wmux started, it is shut down and noted in the log. Anything uncertain is left alone.
Security
- Web pairing codes now use eight characters instead of six. The existing unambiguous base-32 alphabet now provides 40 bits of code space while preserving the ten-minute lifetime, single-use redemption, five-attempt burn limit, and timing-safe comparison. QR pairing still requires no typing; manual pairing asks for two additional characters. (#615)
What's Changed
- feat(web): phone-API protocol version handshake by @openwong2kim in #648
- fix(daemon): reap phantom PTY exits instead of tombstoning live shells by @openwong2kim in #649
- security: widen web pairing codes to eight characters by @snowyukitty in #647
- perf(gate): judge cold start on the fastest boot, not the median by @openwong2kim in #651
- docs: position wmux for AI agents, not AI coding agents by @openwong2kim in #654
- fix(web): find the Tailscale CLI from the GUI process on macOS by @openwong2kim in #653
- test,ci: make the git context watcher tests deterministic and retry apt by @openwong2kim in #656
- test: deflake brick-recovery TTL prune (fixture pid could be alive on CI) by @openwong2kim in #660
- chore(release): 3.37.2 by @openwong2kim in #661
Full Changelog: v3.37.1...v3.37.2