# A tmux wall to watch every agent

One Ghostty window with a split per running agent, each one more tmux client on its session, so I can read every chat at once.

Topic: Agents &amp; review
Tested: 2026-10-24
Revision: 1
By Roman Vaisman
Page: https://eng.vaisman.me/entries/tmux-wall/

## In 30 seconds

- Every agent runs in its own tmux session; a wall is one window with a split per running agent on its list.
- Each split is one more client on that session, next to its normal tab; closing it only detaches.
- Cells sit side by side in one row, in a fixed order, at a smaller font.
- Each session follows the client last typed in, so a zoomed cell prints full width.

## Problem

On 2026-10-14 at 09:51 I asked for all my agents' chats side by side on my big monitor. Each agent runs in its own tmux server, on my Mac laptop or a Linux box, with one Ghostty tab each. A first wall ran live at 10:17.

## What I tried

| Attempt | What happened |
| --- | --- |
| A three-by-two grid of cells | Cells came out uneven widths; I asked for one row, side by side. |
| Sizing each session to its smallest client | A zoomed cell's history stayed wrapped at the narrow cell's width. |
| Finding the wall by its titles and cell count | Rejected in review: the tab window would match too. |
| Rebuilding walls by hand after restarts | After agent restarts the walls went stale; starts now rebuild them. |

## What worked

**Never starts an agent.** Each cell is one more tmux client on an agent's session, local or over SSH, next to its tab; typing in it reaches the agent like the tab. Closing a cell only detaches.

**Only live agents.** A cell needs the assistant actually running in the session; a leftover shell or an agent still being set up is skipped, with the reason printed.

**One row, fixed order.** Cells sit side by side, with an override to wrap. Ghostty can't move a split, so order comes from a list at build time: to rearrange, I edit it and rebuild. The font is smaller than in tabs; I drag the window to the big monitor and maximize it.

**Size follows the last client typed in.** Claude Code wraps output at the width current when it prints and never reflows history. Sized to the smallest client, even the tabs printed at cell width. Now a zoomed cell or the tab prints full width once I type in it.

**Recorded after each step.** The script drives Ghostty through its AppleScript interface, never simulated keystrokes. It records the window id after the first cell, then which cell holds which agent after each split. If a record can't be written, it closes what it just made and checks it is gone; if that fails, it tells me to close it by hand.

**Heal after a start.** A re-run brings an open wall to the front. After my start or restart command, a wall whose cells are gone is closed by its recorded id and rebuilt; a failed heal is only a warning.

## Numbers

The wall's narrow cells are why each session follows its last-typed client, not its smallest.

| Label | Value | Kind |
| --- | --- | --- |
| Wall font size | 11 | configured |
| Agents on one wall (2026-10-24) | 5 | measured |

## When it stops being true

A wall Ghostty restores after a laptop restart has new ids, so I close it by hand. A wall cell counts as an attached client, so my start script skips that agent's tab. A cell I haven't typed in may show a clipped view of a wider session.

## Agent brief

```agent-brief
You are helping me watch all my coding agents in one terminal window.

First ask me:
- Which machines my agents run on, and how sessions start.
- My terminal app and its version.
- My agent list and order, or build one with me.

Constraints:
- Never start, stop or restart an agent; typing in a cell reaches it like its tab.
- Each cell is another tmux client on the agent's own session; closing detaches.
- Script splits via the terminal's interface (Ghostty: AppleScript), not keystrokes; check its dictionary and minimum version.
- Cells only for agents whose assistant process runs; print skip reasons.

Steps:
- Call tools by full path; the terminal may lack my PATH.
- Remote cells: prompt-free SSH; a common terminal type if the remote lacks mine.
- One row in my order, optionally wrapped.
- Size by the last-typed client (tmux's default since 3.1; drop any smallest setting); it's server-wide.
- Record the window id, then each cell's id and agent; if a write fails, close what you made.
- Re-run: bring the wall forward; if a recorded cell is gone, close by id and rebuild all.

Pitfalls:
- Smallest-client sizing leaves history wrapped at cell width, even in the tab.
- A same-title or same-count window may be another of mine.
- An unrecorded wall gets a twin next run.
- A leftover shell looks like a live session.
- A reboot-restored wall has new ids; close it by hand.
- Anything treating attached sessions as in use sees one more client.
- Cells share the session's current window; switching it moves the tab too.
- Closing the wall may ask to confirm.

Done when:
- A dry run lists cells and skip reasons, changing nothing.
- Each running agent's session lists one more client; its tab still types.
- A second run opens nothing new; with a cell closed, it rebuilds.
- Typing in a zoomed cell makes new output full width.
```

## Related

- [Back up your agent's memory, not just its code](https://eng.vaisman.me/entries/back-up-agent-memory.md)
- [CI that shares agent boxes and yields to their owner](https://eng.vaisman.me/entries/ci-that-yields-to-its-owner.md)
