Cookies on Tamperan

We use cookies and similar technologies for the things below. You can accept all, reject everything except what's essential, or pick what you're OK with.

Preferences
Remembers things like your last workspace and how you had a list sorted. Improves the experience but the site works without.
Improvement
Anonymous usage measurement so we can fix bugs and prioritise work.
Marketing
Lets us measure whether ads we run send people who actually use the site. We don't share personal data with advertisers.

Read our cookies policy and the privacy policy.

Loading…

Writing

How I run 19 agent sessions at once

A coding-agent session is worth treating as a long-lived named worker rather than a process you start per task. Nineteen of mine run permanently on one headless machine, reset in place with /clear and re-pointed with a slash command. Here's the addressing scheme, what forces a real restart, and the two places it falls over.

Shane Wright agents tooling process

Most advice about running coding agents assumes one session, started when you sit down and gone when you close the lid. That falls apart somewhere around the third concurrent piece of work, and the usual fix - more terminal tabs - just moves the problem.

The thing that fixed it here was cheap and slightly boring: stop restarting the session. A session is a long-lived named worker. You reset its context in place with /clear, re-point it at a different job with a slash command, and you only kill the process when something read at startup has changed.

Measured on this machine at 08:30 on 31 August 2026:

interactive agent sessions 19
tmux sessions / windows 10 / 44
windows running an agent 19
reachable over Remote Control 18 of 19
oldest session 8 days 21 hours
distinct CLI versions running 5 (2.1.235, .239, .240, .241, .251)

That 8-day-21-hour figure isn't a lifetime, it's a floor. The machine's uptime is 8 days 20 hours, so a reboot on 22 August is the only reason it isn't longer. Nothing else has restarted them.

The reset is /clear, not a new process

/clear drops the conversation and leaves everything else standing - the process, the shell state, the MCP connections, the tmux window, the name. What it costs you is the context you'd already established, which is the thing you wanted to drop anyway.

Then you tell the session what it is now:

/tam:dev kythene
/tam:qa acheev
/tam:plan haven
/tam:mktg tam

Those are plugin commands, one file each. mktg.md is 404 words and contains the mode's boundaries (no app code, tickets go on the parent product project), the standing constraints, and a per-project block with the repos, the URLs and where that product's knowledge lives. The command resolves the project from its first argument, prints the context back, and stops.

So the reset-and-re-init is two lines and about fifteen seconds, against a restart that costs the process, the MCP handshakes, the name and the resume history. Across the 1,928 session transcripts on disk (main and subagent, 23 July to 31 August 2026) that's 128 /clear resets and 166 /tam:* invocations, against nineteen processes.

The mode-plus-project contract is the bit I'd steal if I were doing this from scratch, and it's described properly in the note on the whole setup. What's new here is the lifecycle around it.

The name is the address

Once sessions outlive tasks, the session name stops being decoration and starts being how you refer to work. haven-plan is a place. So is mktg-dev. You go there, you don't recreate it.

Set it at launch or after the fact:

claude --name haven-plan
/rename haven-plan

And put it where you can see it. The status line here reads the name first, because with 44 tmux windows open the directory and the model tell you almost nothing:

input=$(cat)
name=$(jq -r '.session_name // (.session_id[0:8])' <<<"$input")
dir=$(jq -r '.workspace.current_dir // ""' <<<"$input")
model=$(jq -r '.model.display_name // ""' <<<"$input")
ctx=$(jq -r '((.context_window.used_percentage // 0))|floor' <<<"$input")
seg=$(printf '%s' "$dir" | rev | cut -d/ -f1-2 | rev)
printf '\033[1;36m%s\033[0m  %s  ·  %s  ·  ctx %s%%' "$name" "$seg" "$model" "$ctx"

Wired in ~/.claude/settings.json as statusLine.command.

The name is also the messaging address - one session can hand something to another by name, which is how you stop two of them editing the same working tree. That mechanism is in the note; the point here is that it only works if the names mean something, and by default they don't. Eleven of the nineteen running right now are on auto-derived names like tam-c0 and tam-31, which are unique, stable and completely useless to a person. Eight are hand-named. That gap is mine, not the tool's.

One session, three machines

Remote Control is what makes the permanence pay off. The session lives on the headless box; you attach from wherever you are - tmux at the desk, the laptop on a train, the phone in a car park. Same session, same context, no handover.

claude --remote-control haven-plan

18 of the 19 are bridged. The odd one out has been running since 22 August and has simply never been re-launched with the flag, which is the same trade as the version drift below.

One thing I would not do is share them. A named session is tempting to treat as a team mailbox - anyone can reach haven-plan and its accumulated context is right there. But the context is the value, and two people driving one worker towards different ends is how that context stops being worth anything. Sessions stay single-operator here. The handoff surfaces are the ones that were built for it: tickets, and a shared knowledge store. Those are designed for several people writing to them, and a session is not.

What actually forces a restart

Two things, and neither is "it's been a while":

  • A CLI upgrade. The binary is fixed when the process starts, so an upgrade reaches a session only when that session next dies. Which is exactly why five versions are running here concurrently, eleven of them on 2.1.251 and eight trailing behind it.
  • MCP server config. Servers are connected at startup, so a new one or a changed one doesn't reach a running session. Everything else lands without one. A skill or a slash command is a file read when you invoke it, so editing one takes effect the next time any session calls it - no restart, no reload step.

Where it falls over

Version drift bites you when you're debugging. Five concurrent versions is fine until behaviour differs between two of them and you're comparing a session on 2.1.235 against one on 2.1.251. Check the version before you file the bug.

The default naming undoes the whole scheme. A derived name is generated per session and tells you nothing, so unless you actually rename, you're back to counting tmux windows. Do it at launch with --name and it costs nothing.

And a reboot takes the lot. Nineteen sessions with weeks of context vanish together, which is a worse day than it sounds. tmux-resurrect and tmux-continuum bring the windows back - @continuum-restore 'on', saving every 10 minutes, pane contents captured - but they restore layout, not processes. You come back to 44 correctly-arranged windows sitting at a shell prompt.

That last one is the open problem. --resume recovers a conversation by id, so the parts exist - a script that walks the session files under ~/.claude/sessions, matches each tmux field back to its window and relaunches with --name and --resume, would rebuild the whole board in a minute. I haven't written it. If you have, I'd like to see it.