mattorb Stay curiousTighten Feedback LoopsIterate, Measure, LearnFan of Science, Design, and Systems Thinking

9 agent wins with tmux and cmux

In Adventures in TUIs, I wrote that knowing tmux is a superpower when all the coding agents are TUIs.

In the past, I never saw enough potential value [in tmux] for my use cases to make learning it seem like a worthwhile endeavor. Agentic coding changed the math.

Now I have useful work running in several sessions, on multiple machines, for longer than I plan to sit in front of them. An agent can be writing code, waiting on a test, blocked on a usage limit, or asking for a decision. The terminal has become a place where I kick off a parallel workstreams that comes back at unpredictable times, sometimes needing my attention.

That’s where tmux and cmux fit together for me:

  • tmux keeps the work alive and provides some hooks you can script around.
  • cmux keeps those sessions logically organized so I can understand what is in flight, see associated browsers and test runners, and be notified when one needs attention.

In this post:

  1. tmux keeps going when I don’t
  2. Automate ‘continue’ on usage limit stops
  3. Give an agent an eye in the sky
  4. Let a tool take over the screen inside the agent loop
  5. A crammed screen is not impressive
  6. Easy turns beat constant polling
  7. Pair the browser with the terminal session
  8. Drag a local screenshot into a remote agent
  9. Skills make cmux programmable

Keep Moving and Compounding

1. tmux keeps going when I don’t

The most basic tmux win is still one of the best: start a session on a remote machine, detach, and come back later.

ssh heavy
tmux new-session -A -s agent-work

I can start an agent inside that session, detach with Ctrl-b d, close my laptop, and reconnect later. The remote machine keeps going.

If SSH drops, I reconnect. I don’t lose the agent, its transcript, or whatever it was halfway through doing. If I want to check in and attach to that existing session from a tablet or phone while on the go, also easy! That alone finally made learning a few tmux keybindings worth it to me.

2. Automate ‘continue’ on usage limit stops

Nothing deflates a productive thread of work like discovering an agent spent the last hour politely waiting for me to type continue. If the TUI prints when the limit resets, tmux gives me enough of an API to automate that one boring interruption:

  1. tmux capture-pane reads what’s visible in the target pane.
  2. A small script recognizes and parses the limit message.
  3. After the wait, send-keys types continue and presses Enter.
target="[pane]"  # get actual pane name/id via tmux list-panes
tmux capture-pane -p -J -t "$target" | [parse limit message]
... wait until the reset ...
tmux send-keys -l -t "$target" 'continue'
tmux send-keys -t "$target" Enter

Two details worth noticing: -J joins wrapped lines so the parser sees the full message. Also, continue and Enter are sent separately: -l means literal text, while Enter is a tmux key name.

3. Give an agent an eye in the sky

tmux capture-pane is also enough to let one agent loosely observe another.

That may sound a little token maxxish, but it can be genuinely useful. The observer can translate a noisy terminal into a short status, explain what the worker is doing, call out a question (use an adversarial model from a different family), or rename the window so the current state is more visible. Just ask the agent to watch and summarize the activity/progress in the tmux pane named xyz, and enjoy the ride.

4. Let a tool take over the screen inside the agent loop

Here’s one I didn’t expect: an agent can hand the whole terminal back to me in the middle of its own turn. Wait, what? Instead of making every tool squeeze its result into stdout, a custom tool can temporarily take over the window, collect richer input from me, and then hand control back.

I use this pattern in rep, a human-in-the-loop TUI for reviewing and revising Markdown plans. I can invoke $rep from Codex or /rep from Claude Code. The agent starts rep from inside its own tool loop, but that tool call usually has no interactive terminal for a full-screen TUI.

If rep detects that the agent is running inside tmux, it creates a new pane beside the agent, zooms that pane to fill the window, and focuses it.

When I exit rep, its pane closes and the agent reappears. Behind the scenes, rep bridges the TUI’s final action list back to the waiting tool call. The agent reads those structured instructions, edits the plan, and continues the same turn. There’s no copying annotations out of one app and pasting them into another.

I built rep for plan review, but the trick works for any interaction too rich for a stream of terminal questions: approving a diff, choosing among options, or walking through a debugging view.

5. A crammed screen is not impressive

Keeping more sessions alive creates another problem: where should my attention go?

The answer isn’t to tile a large monitor with twelve tiny terminal panes and squint at all of them. That may make for a cluttered screenshot that looks impressively productive, but mostly it turns me into a security guard watching a wall of camera feeds.

cmux gives me a vertical sidebar of workspaces, split panes inside each workspace, and horizontal surface tabs inside each pane. I only split a pane when seeing two things together is actually useful. One workspace might hold an agent terminal, a test runner, and a browser. Another can disappear into the sidebar until it needs me.

6. Easy turns beat constant polling

Agents have awkward turn-taking. Unless they are implementing to a spec/plan or setting a /goal loop, they may run for twenty minutes and then ask a tiny question that blocks everything. That works great when you have 1 session in flight, but what about when you have 10?

I don’t want to patrol a row of agent tabs. When an integrated agent emits a notification, cmux adds a notification ring to its pane and marks the workspace unread. Cmd+Shift+U jumps to the most recent unread item.

That hotkey changes the feel of managing several agents. I can stay focused on the active decision, then jump directly to the next session waiting on me. No window juggling or spelunking required.

7. Pair the browser with the terminal session

A coding agent and the thing it’s building belong together on-screen.

In cmux, I can split an in-app browser beside the terminal and keep both in the same workspace. The browser is also scriptable, so an agent can inspect the accessibility tree, click controls, fill forms, capture screenshots, read console errors, and execute JavaScript while testing the result.

Browser sessions paired with terminals even work over SSH.

cmux ssh heavy

cmux opens a workspace connected to heavy. A browser pane opened inside that workspace routes through the remote machine, so http://localhost:3000 reaches the server running there without a hand-built SSH port-forward. The browser is still rendered locally, beside the terminal, but its idea of localhost is the remote development environment.

8. Drag a local screenshot into a remote agent

Remote development usually makes one tiny interaction surprisingly annoying: I capture an image on my laptop and need to give it to an agent running inside SSH and tmux.

I no longer have to break my flow to type an scp command. In a cmux-managed SSH session, dragging a local image or file into the remote terminal uploads it through the existing connection and inserts the remote path into the active input. The agent receives a path it can actually read on the machine where it’s running.

9. Skills make cmux programmable

cmux skills give an agent a vocabulary for workspaces, panes, surfaces, browser targets, and settings. With those skills in context you can ask your agent to write scripts and make customizations.

Tip

Don’t hand-write the plumbing from a list of command samples. Ask an agent to inspect your current cmux setup, generate the small script or configuration change for the workflow you want, validate it, and reload it.

cmux’s CLI and socket API are what make that possible: an agent can manage panes, read terminal screens, rename workspaces, send notifications, and drive the in-window browser.

cmux new-split right
cmux read-screen --lines [n]
cmux rename-workspace "checkout: tests passing"
... outputs browser-surface id ...
cmux browser open http://localhost:[port]
cmux browser [browser-surface] snapshot --interactive
cmux browser [browser-surface] eval '[JavaScript]'

That last command runs JavaScript in the page, not in cmux itself. The browser command set is ported from Vercel’s agent browser, so if you have driven a browser with that CLI, this will feel familiar.

Keep Moving and Compounding

New orchestration tools launch weekly, all chasing gaps around how we can best manage and understand AI workloads. In the absence of a clear winner and with the models evolving so rapidly, I am drawn to the idea of stacking up reliable primitives that have minimal lock-in: sessions that survive me, panes I can script against, a sidebar that knows which agent needs me, and a browser that lives next to its terminal.

Related Posts