You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rescoped 2026-08-06.#247 has since shipped — the vestigial tmux naming is gone (engineLabel replaces tmuxSession across the API surface). So the "or finish removing the naming" half of this is done, and what remains is the single question: should tmux come back as a selectable engine backend? Everything below still applies to that question.
Direction check: the proposal below adds backend: "stream-json" | "tmux" — a new closed enum on engine presets — while #160 is explicitly about retiring closed enums (capabilities.workflow) in favour of declarative composition. If tmux does come back, it should probably arrive the declarative way rather than as one more hardcoded alternative.
First, the thing that is easy to conflate
tmux is already a platform connector and always has been. lib/connectors/registry.ts:82
declares tmux (tmux_list_sessions, tmux_capture_pane, tmux_run_command), and :72 declares
the generic terminal connector, whose local adapters are tmux, kitty remote control and iTerm2
AppleScript. Both are live, both reach the machine over the runner relay, and the tmux / Terminal /
kitty / iTerm2 Operator agents use them today.
So this ticket is not "add tmux to the platform". It is: restore a tmux-backed engine for
Coder sessions, as a selectable alternative to the stream-json child process — the thing that was
deleted.
What was removed, and when
Commit c94642f, 2026-06-26 — "feat(coding): drive Claude Code via stream-json — one structured
engine, no tmux". It deleted packages/browser-runner/src/coding/session.ts (180 lines) and session.test.ts (110 lines), and pointed CodingRuntime at the new HeadlessSession.
The deleted CodingSession implemented the same surface CodingRuntime still expects:
method
tmux implementation
start()
createSession(name, workDir), export env vars via sendText, then sendText(cliCommand)
snapshot(lines)
capturePane(target, lines)
input(text)
sendText
interrupt() / stop()
send keys / killSession
runState()
inferred by regex over the captured pane
Every tmux primitive it relied on still exists and is still maintained — coding/tmux.ts was kept for the terminal connector (createSession, capturePane, sendText, sendKey, killSession, sessionExists, sanitizeSessionName). So the restore is mostly
re-adding one class, not rebuilding a subsystem.
CodingRuntime.start() (runtime.ts:126) currently constructs new HeadlessSession({…})
unconditionally — no flag, no branch. That single call site is where a backend choice would go.
What the removal traded away, and what has since changed
That commit stated its trade-offs explicitly:
Trade-offs (deliberate): drops the multi-CLI tmux path (gemini/codex/grok) and live-TTY
takeover — both replaced by structured messaging, which fits headless.
One of those has already been reversed by other means: multi-CLI came back. Codex, Grok and
Gemini now run through HeadlessSession as raw spawns with stdout capture (headless.ts, mode: "raw"), so "tmux is needed for non-Claude engines" is no longer true.
What is still genuinely missing without tmux:
A real PTY. Raw-spawn engines get a pipe, not a TTY. A CLI that requires a terminal (full-screen
TUI, prompts that need isatty, colour/width detection) cannot work on the current path.
Live human takeover of the actual terminal — attaching to the same session the agent is driving.
Survival of a runner crash for non-Claude engines. Claude survives via --resume from ~/.claude; a raw spawn dies with the runner, where a tmux session would outlive it.
What it would cost
Honest accounting, since this is re-adding something that was deliberately deleted:
A second engine implementation to maintain behind one interface, and every coding feature must
then work on both.
Run-state goes back to regex over a scraped pane for that backend — the guessing the commit
message called out, and the source of the premature-finish bugs it fixed.
The console's terminal view, /capture, takeover, the Pilot loop and the orphan reconciler all
need to be correct for both backends.
Proposal
Add backend: "stream-json" | "tmux" to the engine preset (CodingEngine in lib/coding-engines.ts, alongside the existing auth field), defaulting to stream-json so
nothing changes for anyone who does not opt in.
Restore CodingSession from c94642f behind the CodingRuntime interface and branch at runtime.ts:126 on the session's chosen backend.
Decide before building. The value case is a real PTY, real attach, and surviving a runner crash
for non-Claude engines. If those are not wanted, the better outcome is to finish #247 — drop the
tmux naming entirely — rather than carry two engines. This ticket exists to make that a decision
rather than an accident of history.
First, the thing that is easy to conflate
tmux is already a platform connector and always has been.
lib/connectors/registry.ts:82declares
tmux(tmux_list_sessions,tmux_capture_pane,tmux_run_command), and:72declaresthe generic
terminalconnector, whose local adapters are tmux, kitty remote control and iTerm2AppleScript. Both are live, both reach the machine over the runner relay, and the tmux / Terminal /
kitty / iTerm2 Operator agents use them today.
So this ticket is not "add tmux to the platform". It is: restore a tmux-backed engine for
Coder sessions, as a selectable alternative to the stream-json child process — the thing that was
deleted.
What was removed, and when
Commit c94642f, 2026-06-26 — "feat(coding): drive Claude Code via stream-json — one structured
engine, no tmux". It deleted
packages/browser-runner/src/coding/session.ts(180 lines) andsession.test.ts(110 lines), and pointedCodingRuntimeat the newHeadlessSession.The deleted
CodingSessionimplemented the same surfaceCodingRuntimestill expects:start()createSession(name, workDir), export env vars viasendText, thensendText(cliCommand)snapshot(lines)capturePane(target, lines)input(text)sendTextinterrupt()/stop()killSessionrunState()Every tmux primitive it relied on still exists and is still maintained —
coding/tmux.tswas kept for the terminal connector (createSession,capturePane,sendText,sendKey,killSession,sessionExists,sanitizeSessionName). So the restore is mostlyre-adding one class, not rebuilding a subsystem.
CodingRuntime.start()(runtime.ts:126) currently constructsnew HeadlessSession({…})unconditionally — no flag, no branch. That single call site is where a backend choice would go.
What the removal traded away, and what has since changed
That commit stated its trade-offs explicitly:
One of those has already been reversed by other means: multi-CLI came back. Codex, Grok and
Gemini now run through
HeadlessSessionas raw spawns with stdout capture (headless.ts,mode: "raw"), so "tmux is needed for non-Claude engines" is no longer true.What is still genuinely missing without tmux:
TUI, prompts that need
isatty, colour/width detection) cannot work on the current path.tmux attachfrom the user's own machine to watch or intervene directly. Users currentlyexpect this, because every session still shows a
pags-<engine>-<id>name (Coding sessions no longer use tmux, but the names, diagnostics, kill-tmux control and docs all still say they do #247).--resumefrom~/.claude; a raw spawn dies with the runner, where a tmux session would outlive it.What it would cost
Honest accounting, since this is re-adding something that was deliberately deleted:
then work on both.
message called out, and the source of the premature-finish bugs it fixed.
/capture, takeover, the Pilot loop and the orphan reconciler allneed to be correct for both backends.
Proposal
backend: "stream-json" | "tmux"to the engine preset (CodingEngineinlib/coding-engines.ts, alongside the existingauthfield), defaulting tostream-jsonsonothing changes for anyone who does not opt in.
CodingSessionfrom c94642f behind theCodingRuntimeinterface and branch atruntime.ts:126on the session's chosen backend.a name you can genuinely
tmux attachto.Decide before building. The value case is a real PTY, real attach, and surviving a runner crash
for non-Claude engines. If those are not wanted, the better outcome is to finish #247 — drop the
tmux naming entirely — rather than carry two engines. This ticket exists to make that a decision
rather than an accident of history.