Essay / 10

The Invisible Multiplexer

The essay about a lid closing: why an agent's live turn dies with its terminal, what the field does about it, and the case for hiding a decades-old answer inside a modern one.

Read as Markdown

Twenty minutes into a long agent turn, the laptop lid closes. Or the hotel Wi-Fi drops the SSH connection, or the terminal app crashes, or someone trips over the wrong cable. The conversation survives — any serious harness journals every message to disk as it happens — but the process does not. The in-flight turn, the background shells it had running, the warmed caches, the exact live state of the work: gone with the window that framed them. What comes back on relaunch is a faithful transcript of a session that no longer exists.

This is fate-sharing, and it’s the honest price of a deliberate choice. Kin runs its agent loop and its terminal interface in one process, on purpose: no wire protocol between them, no serialization boundary, no versioning tax, every internal reachable by the UI, the tests, and the peer itself. One process means one lifetime, and the terminal owns it. Close the terminal and you close the agent.

The Three Answers

The field has three answers to this, and it’s worth being precise about what each one actually buys.

The first is the journal itself: resume the conversation from disk. Every major coding agent ships this, and it is genuinely necessary — it’s what makes a reboot survivable. But it recovers the record of the work, not the work. A resumed session starts a new process that has read about what the old one was doing.

The second is the client/server split: move the agent loop into a daemon, let interfaces attach and detach over a socket. This is the architecturally respectable answer, and on paper it solves the problem completely — the turn lives in the server, and terminals are just viewers. In practice, the projects that have taken this route are still paying for it, visibly, in their public issue trackers: orphaned server processes that outlive every client and quietly eat memory, reconnecting clients that miss the events emitted while they were gone, mid-stream responses frozen by a heartbeat disagreement between two ends of a protocol somebody now has to version forever. None of these are incompetence. They are the ordinary, predictable cost of owning a distributed system, paid to solve what is, at bottom, a terminal problem.

The third answer is to move the process to someone else’s computer — run the agent on a cloud VM that no laptop lid can reach. This works, and for the vendors who sell the cloud it works twice. But it changes the deal: your agent now runs where you are not, on infrastructure you don’t govern, as a product decision wearing an architecture’s clothes.

What Everyone Actually Does

Meanwhile, out in the open, the practitioners solved it years ago with a program from 2007. The standard advice — repeated in guide after guide, for every agent on the market — is: run it inside tmux. Start a multiplexer session, launch the agent in it, detach, and the agent survives anything that happens to your terminal, because the process belongs to the multiplexer’s server now, not to the window. A dropped connection kills the viewer; the work never notices. A meaningful part of tmux’s late-career resurgence is exactly this: a nineteen-year-old terminal multiplexer turning out to be the load-bearing runtime under the newest tools in software.

Look at what that means. The community’s real, working answer to fate-sharing is a detachable server that owns the process — precisely what the client/server rewrites are building from scratch, except this one has had its reattach semantics hardened by two decades of production use. The only reason it isn’t the product’s answer is that tmux arrives as a whole environment: a status bar, a prefix key, a configuration culture, a vocabulary. The mechanism is exactly right and the experience is exactly wrong, so every harness leaves it as an exercise for the user, and the users who most need it — the ones who didn’t know their turn could die — are the ones who never set it up.

Hiding It

So Kin does the impolite thing: it uses tmux and refuses to admit it. An interactive launch quietly re-runs itself inside a managed session on a dedicated, private tmux server — the user’s own tmux configuration and server are never touched — with every visible trace of the multiplexer switched off. No status bar. No prefix key. Mouse, colors, clipboard, key chords, and tab titles pass through untouched. The word “tmux” appears exactly once in the manual, as the name of the requirement and the rescue command; everywhere else the feature is just what it is to the person using it: your session keeps running when you leave, and comes back when you do.

Most of the engineering lives in making the disguise hold. The failure modes people hit running modern terminal apps inside a multiplexer — clipboard escapes that vanish, colors that flatten, a laggy Escape key, modifier chords that stop registering — are all consequences of tmux’s defaults meeting an app it wasn’t tuned for, and every one of them is pre-answered in the options the wrapper applies before the session exists. A crash doesn’t vanish with its pane; the pane freezes with the traceback on screen, one keypress to dismiss. And every failure of the wrapper itself degrades the same way: one friendly line, then a plain launch. The wrapper is never allowed to be the reason Kin didn’t start.

Then the part that matters more than the mechanism: it’s on by default. A persistence feature that ships opt-in protects only the people who already knew they needed it, which is close to nobody, and is certainly not the person four hours into a migration when the hotel network hiccups. Where tmux is absent the default degrades silently — a default that nags is a bug — but where the mechanism exists, the protection simply exists too, unconfigured, the way it would in a native design.

Standing on Boring Ground

We went looking, later, for whoever else had done this, expecting to find the pattern named and shopworn. It mostly isn’t. The closest relatives are the big cloud providers’ browser shells, which quietly wrap your session in tmux for exactly this reason and mention it almost nowhere — validation at enormous scale, from teams who also concluded the mechanism was right and the vocabulary was the problem. Among agent harnesses: nobody. The proprietary ones point at their clouds; the open ones either paid for the daemon or left tmux visible on the table for the user to pick up.

The honest way to say it is that this went looking to be argued out of. The design started as a challenge — surely defaulting every session into a hidden multiplexer is too clever, surely the field knows something — and the survey came back the other way: open feature requests on the major agents asking for exactly this behavior, unanswered; the daemon route demonstrating its costs in public; and the one battle-tested detachable server sitting right there, needing only to be made invisible. A decision that survives a real attempt to kill it is worth more than one that was never pushed. This one pushed back: the boring, decades-hardened ground held, and the only genuinely new work was the disguise.