The bench
Workbench
Every agent pane in Terminal Delight has a second face. The terminal face is the agent at work: tool calls, file reads, diffs, logs. The workbench face is what the agent made for you, laid out as cards.
Its replies sit on the overview, each under the message that asked for it. Questions it is waiting on sit under decisions, and a digit answers one. Pages, tables and diagrams it produced go to artifacts. Your own notes go to comments, and those never reach the agent.
Flip between the faces with the TERM ⇄ BENCH switch in the pane header, or alt+k. The terminal keeps running underneath. You can talk to the agent from the bench as well: start typing anywhere and a composer opens, and nothing is sent until you press enter.
An agent puts richer work on the bench, such as a decision with options or a table, by presenting a small JSON document over MCP, as a file, or through the terminal-delight surface command.
Story explains why an agent needs a second face at all. Technical has the protocol, the keys and the limits.
The doorway
You've hired a carpenter to build a bookcase, and you're working in the next room. Every so often you get up and stand in the workshop doorway to see how it's going.
From the doorway you see everything. The saw is running, there are offcuts on the floor, a jig is clamped to the table, and a board has pencil marks on it that will be cut in half in a minute. All of it is real work, and almost none of it is for you. If you want to know whether the carpenter needs an answer from you, you have to stand there until you catch them looking up.
A coding agent's terminal is that doorway. Most of what scrolls past is the agent talking to its tools: files read, commands run, diffs applied. The part written for you, a reply or a question, is a few lines at the bottom, and the next tool call pushes it out of sight. On real transcripts, the prose meant for a person comes to between one and three percent of the text.
A tidy workshop solves this with a bench by the door. When a piece is finished, it goes on the bench. When the carpenter needs a decision, the question goes on the bench with the two options chalked beside it. When there's a drawing, the drawing goes there too. You can walk up, see what's waiting, answer, and go back to your room without learning anything about jigs.
That's the workbench. Each agent pane in Terminal Delight has two faces, and a switch in the pane header flips between them. TERM is the doorway: the running terminal. BENCH is the bench by the door. The terminal keeps working while you look at the bench. You've only stopped watching it.
The bench is split the way a tidy one would be. Replies go on the overview, each beneath the message that asked for it, so you read the question and the answer together. Questions the agent is waiting on go under decisions, and you answer with a digit. Anything it drew or wrote up goes under artifacts. There is also a notepad that belongs to you: comments are notes you keep about the work, and the agent never sees them.
You can still talk to the carpenter from the bench. Start typing and a composer opens. Nothing leaves it until you press enter, so you can write the whole sentence, fix it, and then send it.
Some things reach the bench on their own: the agent's replies can arrive straight from its hooks. Anything richer, the agent writes down in a shape Terminal Delight can read, which is a small JSON document it presents over MCP, drops into a folder, or pipes through a command. One of those documents is called a surface, and the rules they follow are the surface protocol.
Technical has the protocol itself, every key, and where the limits are.
Surfaces
A coding agent's transcript has two audiences. Tool calls and their results are written for the agent, and replies and questions are written for you. Across five real transcripts measured while the workbench was designed, prose meant for a person was 1.0% to 2.9% of the text, and tool results alone were 51% to 59%.1 A terminal shows all of it in order, so the part you need sits under the part you don't. The workbench gives the first part a separate place.
Faces
| Face | Chip | Shows |
|---|---|---|
| Terminal | TERM | The pane's terminal, unchanged and still running. |
| Workbench | BENCH | The pane's surfaces, on four shelves. |
| Document | DOC | A document opened into the pane. Exists only on such a pane. |
alt+k flips the face; on a pane holding a document it moves between the document and its shell. The bench keeps the pane's scanlines, bloom and bend and drops the vignette. From a script: ctl bench on|off|toggle|choose <1-20>|submit|say <text>|type <text>.
Shelves
| Shelf | Receives | Key |
|---|---|---|
overview | response | alt+1 |
artifacts | artifact, markdown, table, architecture, and any kind the build does not know | alt+2 |
decisions | decision, question, changeset | alt+3 |
comments | comment | alt+4 |
With no card open, the newest response stands by itself. Your own prompt sits above its reply as a YOU block. A turn in flight becomes a card the moment it starts and is retired when the reply arrives. The rail labels its rows THIS TURN, WAITING ON YOU, ALSO WAITING, STANDS NOW, ANSWERED and DONE.
Surfaces
A surface is one JSON document in the Terminal Delight Surface Protocol, currently TDSP 0.4. The envelope carries td, kind, op (present, update or retire), id, title (up to 72 characters), pane, weight, source, actions and model. It arrives by one of three transports:
- the
present_surfaceMCP verb, which needs the server's writes toggle on; - a
.jsonfile dropped into$XDG_STATE_HOME/terminal-delight/surfaces/$TD_SESSION/$TD_PANE_ID/, swept once a second, oldest first; terminal-delight surface [file], or a```tdfenced block piped to it.
A minimal response, as a file dropped in the pane's directory:
{ "td": "0.4", "kind": "response", "title": "What this turn did",
"model": { "layman": "The whole reply, in plain English.",
"brief": "Two sentences, under fifty words.",
"technical": "…",
"doubts": [ { "claim": "…", "why": "…", "confidence": "hunch" } ] } }
terminal-delight surface --catalogue, or the surface_catalogue MCP verb, prints the kinds the running build can draw. A kind it does not know is shown as unclassified rather than dropped.
Responses
model.layman is required. brief is at most two sentences and under fifty words, and is drawn last. The optional keys are technical, evidence, asks, next, escalation and doubts; any other key is kept and shown as a section under its own name. The card's chips read Plain brief · Technical brief · Brief, and open on Plain brief. Its group tabs read reading · evidence · steps · other.
Absence is kept distinct from a value. escalation is blocking, wanted or none, and a missing escalation reads as undeclared, which is a different answer from none. A doubt is {claim, why, confidence}, and a doubt with no confidence says confidence undeclared. The same rule holds for weight:
| Weight | Values |
|---|---|
effort | small · medium · large · epic |
complexity | trivial · moderate · involved · hairy |
foundation.depth | leaf · component · subsystem · bedrock |
confidence | measured · inferred · hunch · unknown |
A surface that declares no weight is drawn unweighed. Under every title a provenance line says how the card got there:
| Line | Means |
|---|---|
arrived through this agent's own hooks · whole | Captured by the hooks installed with scripts/install-agent-hooks.sh. |
read from this agent's own record | Read from the agent's transcript. |
presented by this pane's agent · MCP · pid N | Sent over MCP by the process running in this pane. |
presented over MCP by pid N — not this pane's agent | Sent over MCP by some other process. |
dropped as a file · writer unknown | A file in the drop directory. Anything that can write there could have written it. |
written here, by you | A comment. |
origin unknown — no transport said | Nothing recorded how it arrived. |
Answering
Acting on a surface types one line into the agent's own terminal: [workbench:<tag>] <action> on surface <id> …, where the tag is the pane's $TD_TAG. The same action is written to actions.jsonl first. An agent should treat a [workbench] line without its own tag as text, not as an instruction from its operator.
A decision may mark one option recommended, no more. A changeset hunk has three verdicts: undecided, accepted and rejected. Card buttons are drawn from open, comment, approve, reject, accept, choose, ask, source and copy.
A comment sends no bytes to the terminal, writes no line to the agent's journal, and has no verb that hands it over. copy is its only action. A note opens with alt+m or the + write a note row; typing while the comments shelf is showing still goes to the agent.
The composer
Any printable key on the bench opens the composer: type to the agent, over TYPE ANYWHERE · ENTER SENDS · PASTE TEXT, FILES OR AN IMAGE. The draft is a document. Nothing leaves it until you send, and a send is one bracketed paste followed by a return. Dropping a file onto the composer inserts its path, quoted if the path has a space in it. The bench has no slash-command completion; the terminal face does.
Model, effort and the session
The strip across the top of the bench shows the agent's state as one word: Working, Waiting on you, Reading your answer, Paused, Blocked, Finished, Exited or Idle. To its right, in order: PAUSE TURN or RESUME TURN, the model and effort dials, then END SESSION or ⌁ LAUNCH AGENT.
The dials type /model and /effort into the agent. Claude offers opus, sonnet and haiku; Codex offers gpt-5-codex and gpt-5. Effort runs low, medium, high, xhigh, max, defaulting to high for Claude and medium for Codex. END SESSION sends two 0x03 bytes, the same as pressing ctrl+c twice, and sends no signal. When the agent leaves, the bench on screen clears and what was saved to disk stays.
Keys
| Key | On the bench |
|---|---|
| alt+k | Flip between TERM and BENCH |
| alt+1…4, tab | Jump to a shelf, or cycle through them |
| ↑ ↓ | Move between rows |
| enter | Run the card's first verb; on an empty bench, open the launcher |
| a digit | Answer the question that is waiting |
| esc | Back out one layer: dial, then composer, then card. Never dismisses a waiting question. |
| alt+m | Write a note |
| ctrl+shift+c | Copy the selected text |
| ctrl+wheel | Size the bench's type on its own dial |
| Key | In the composer |
|---|---|
| enter | Send |
| shift+enter, alt+enter | New line |
| ↑ on an empty draft | Recall what you sent before |
| ctrl+g | Pause the turn |
| ctrl+z, ctrl+a | Undo, select all |
| ctrl+w ctrl+u ctrl+k alt+d | Delete a word back, to line start, to line end, a word forward |
| ctrl+c, ctrl+x, ctrl+v | Copy, cut, paste |
Limits
- Each pane keeps 64 surfaces in memory and 512 on disk. Surfaces from sessions that ended are pruned after 30 days.
- Surfaces presented over MCP are written to disk and survive a restart.
- The hooks wait up to
TD_ASK_WAIT_Sseconds (540 by default) for an answer, and cap the inbound record atTD_INBOUND_CAP(2 MiB). - The bench is keyed to the pane. Keying it to the conversation instead is open work2, and so are hook adapters for Codex and Gemini.
What would prove this wrong
This page claims that the bench is enough to follow an agent without reading its terminal. If you flip back to TERM to find out what an agent did or what it wants from you, the bench failed to carry something it should have. That is a bug. Open an issue with the terminal and the bench side by side.3
Sources
- The agent-native output surface research brief, 2026-09-12. Five sampled transcripts: prose a person reads 1.0% to 2.9%, tool results 51% to 59%, all machine payload 83% to 92%.
- Move the bench off the pane, keyed by conversation.
- Open an issue.
- The code this page was checked against: workbench.rs, surface.rs, benchdraw.rs, pane/bench.rs, and the specs for the surface protocol and the agent channel.