the layer with no name
A follow-up to forty terminals: one line from that piece turned out to be a specification defect, and I am now writing it up properly.
I wrote a long piece a few days ago about having forty terminals open and no way to tell which six are working. Most of that piece was reporting. It ended in a wishlist, which is what you write when you have found a hole and cannot yet describe its shape.
One line in it was not a wish. It was a defect, and it is the only part I have kept.
There is a layer between your shell and your terminal, and the protocols have no words for it. Not “no good words.” No words. You cannot say this session belongs to that project, or this one is waiting for you, in any sequence that survives the trip to the screen.
What the maintainer actually said
I assumed this was culture. Terminal people are conservative, tmux is old, nobody wants to move. That answer is wrong and I am glad I checked before writing it down.
tmux does not resist the semantic layer. When somebody asked for OSC 133 support in 2022, the reply was to go ahead and implement it — “So if you want to have a go, that would be great :-)” — and the issue closed six days later. tmux tracks those sequences natively today. Prompt jumping in copy mode. Prompt and output positions out of capture-pane.
What tmux declines is forwarding them outward, to whatever terminal it is running inside. The reason nicm gave on 19 June 2026:
The sequences are not powerful enough to let tmux express everything it would need to — they are meant for shells, not full screen programs.
Read the second half of that sentence slowly. Meant for shells, not full screen programs. A multiplexer is a full-screen program. So is your editor. So is every agent harness that paints its own interface instead of dribbling bytes at you.
Which is to say: the capability layer was specified for one shell talking to one screen, and the layer that has grown up in between — the layer where all my forty terminals actually live — was never given a vocabulary at all.
The concrete version, from the same thread: if tmux writes a prompt marker at row 10, column 10, and you then drag that pane so it sits at 15,15, there is no way for tmux to tell the outer terminal the marker moved. OSC 133 marks a point in a stream. It does not describe a region of a grid that somebody else is laying out.
A capability the multiplexer cannot re-address is a capability the multiplexer cannot forward.
The ladder
I assumed that generalised — that the whole capability layer was broken the same way. It does not generalise. It inverts, and the inversion is the useful part.
Line the protocols up by how much cell geometry each one carries. They sort perfectly.
OSC 8 binds a URI to a range of cells. It is an attribute, like colour, and it is stored the way a colour is stored, so it reflows the way a colour reflows. tmux shipped it in 3.4. A follow-up request to add it was closed the next day, pointing at the commit that had already done the work. Unreleased 3.8 goes further and makes hyperlinks first-class in tmux’s own style layer with a link= attribute.
Kitty graphics addresses image placements to cells. tmux is compositing it right now, in an open pull request, by cutting the screen into per-row spans and emitting the sub-rectangle of the image in each stripe — “we treat the image just exactly like characters on the screen. They can be scrolled up into the copy buffer, moved around on the screen in floating panes, and partially obscured.” Why that is even possible is in the protocol, not the implementation: “Each of those special unicode characters carries with it which piece of which puzzle belongs on top of that character.” It costs a bespoke layering model inside the grid. It is being paid.
Sixel is a framebuffer dump with no addressing whatsoever. tmux has had it since 3.4, opt-in at build time, and by 3.5 the changelog records that tmux deletes Sixel images before reflow. There is nothing to re-address, so the picture goes in the bin. Same absence makes it destructive under composition: print text over a Sixel image and the image vanishes from those cells.
OSC 133 has no spatial extent at all. Tracked internally. Forwarding refused.
Adopted outright. Composited at high cost. Partial and destructive. Refused.
That ordering does not track how ambitious the capability is, or how old, or how badly anyone wanted it. It tracks exactly one property: how much cell geometry the protocol carries.
Flagging this because it is the load-bearing claim in the piece and it is mine, not the maintainer’s — do not go quoting nicm on a spectrum he never drew. Every individual rung is checkable in about a minute. The ladder is an argument. (And the Kitty pull request is open, with unresolved scroll and cursor defects in its own thread. tmux does not support Kitty graphics today. It is trying to.)
So the rule falls out:
Carry your geometry, or you cannot be relayed.
Nouns, and the one string
The rule tells you what cannot cross the multiplexer. It does not hand you what is missing above it.
What is missing is nouns. There is no protocol object for a session. None for the project or customer a session belongs to. None for the state a session is in. The layer has one string — the window title — and that string is a single mutable value with no ownership protocol, written concurrently by the agent, the shell, the multiplexer and your editor, last writer wins.
That framing is my inference. The symptoms are all over public trackers: titles rewritten about once a second, a busy glyph pinned on under every multiplexer, titles blanked on exit and corrupting session-restore tooling, editor tab titles that never refresh, and no way at all to express the one state that matters to a supervising human, which is waiting for you.
Those are not five bugs. They are five programs writing to one variable that was never specified as belonging to any of them.
Vocabulary does exist — inside individual programs, going nowhere. A Zellij layout is a KDL file declaring panes and tabs with per-pane cwd, command, args and name, and Zellij serialises sessions by default, preserving tab order and the command in each pane behind a “Press ENTER to run…” guard so a resurrected session does not fire an rm -rf at you on the way back. That is a real declarative model for project-shaped sessions, built into the multiplexer rather than strapped to the outside of one. Wave has workspaces. Both are good. Neither is addressable from outside the program that implements it. A Zellij layout is invisible to your terminal emulator; a Wave workspace is invisible to your shell; neither is expressible in any escape sequence.
An agent that wants to say this belongs to customer X, project Y, and is blocked on a human has exactly one channel that reaches the screen through a multiplexer. It is the title string. The one with four writers and no owner.
Everyone is standing in the same hole
This is not my private complaint. Warp issue #9382, opened 29 April 2026 and still open, is a user asking for workspace-style project tabs holding multiple independent sessions inside one top-level tab — a coding agent in one, a local server and some shells in the others, without splitting the project across top-level tabs. The company that renamed itself an Agentic Development Environment does not have this yet either.
And an entire tool category has grown into the gap from the other side. Claude Squad “manages multiple Claude Code, Codex, Gemini (and other local agents including Aider) in separate workspaces,” over tmux and git worktrees. It is not alone.
Honesty about that evidence, in the same breath as the evidence: one tracker issue is not a survey, and a category of tools is not a measure of demand. I looked for a study three times and did not find one.
Why I am not building an environment
The obvious move here is to build the thing — a new terminal, integrated, with all the nouns in it.
The record says don’t. The ambitious terminals mostly did not die. They stayed small. DomTerm has been maintained for eleven years by the same person who wrote the OSC 133 proposal, and has 395 stars. Extraterm is alive. That is a different outcome from failure and it is a worse one to plan around, because there is no lesson in it you can fix.
Meanwhile the thing that made it into every terminal you can install was an escape sequence. A sequence degrades: a dumb terminal that does not understand it ignores it and keeps working. An environment does not degrade. You are in it or you are out of it.
So the shape of the answer is fixed by the shape of the problem. Not an environment. Sequences — geometry, ownership, session identity — that carry enough about where they live to survive being relayed, and that a 1978 machine can throw away safely.
That is a specification, not a blog post, and I am writing it as one. A whitepaper: numbered sections, the mechanism specified concretely enough that somebody could build against it, prior work as a citation list at the back rather than the body. Modelled on the Bitcoin paper’s shape, because that document’s whole trick was that you finished it knowing what to implement.
Four sections of it exist. The rest is the actual work.
The environments stay small. The sequences travel. Everything I am proposing has to fit through a program that will not carry it unless it says where it lives.
Sources: tmux issue #3064 ↗ · tmux issue #5237 ↗ · tmux CHANGES ↗ · tmux PR #5274 ↗ · tmux PR #5445 ↗ · Kitty graphics protocol ↗ · Bothner, semantic-prompts proposal ↗ · DomTerm ↗ · Zellij layouts ↗ · Zellij session resurrection ↗ · Wave Terminal docs ↗ · Warp issue #9382 ↗ · Claude Squad ↗