In early October I migrated my development server off my laptop onto a Mac mini, mostly to answer a boring question about memory and battery. The interesting thing happened a few days later: I shut the laptop at night, opened it in the morning, and the Claude Code sessions on the mini had simply kept going. Nothing was waiting for me. Nothing had died with my lid.
That’s when the job titles changed. The laptop wasn’t a worker anymore. It was the seat you call the round from.
In Counter-Strike, the in-game leader is the player who runs the round. Five people, one plan. The IGL reads the situation, calls the strat, decides when to buy and when to save. The IGL is rarely the top fragger — the job is information and decisions, under time pressure, with incomplete knowledge of where the enemy is. Somewhere in that first week the name arrived and refused to leave, so the tool is called igl, and it keeps me honest about what the laptop is for: the call matters more than the frag.
Why manage multiple Claude Code sessions from one seat?
The roster is small and deliberately boring. The laptop (M3 Pro, 18 GB) is head office: it runs igl, holds the secrets, and does no long-running work. Two Mac minis — s1 and s2 — are session hosts: tmux, Claude Code sessions, project dev stacks, Caddy, a Supabase per project, all reachable over Tailscale. A Mac Studio is planned as a compute node for the heavy stuff, because the key fact about this whole setup is that a Claude Code session is cheap to host — it mostly waits on the Anthropic API. The limit on how many you can run is your plan, not your hardware. A fleet of agents doesn’t need a datacenter; it needs a ₹60,000 mini that never sleeps.
If you’ve tried running Claude Code on more than one machine, you’ve hit the island problem: each computer has its own sessions, its own terminals, its own paths. The Reddit threads write themselves — “Anyone else using Claude Code across multiple PCs? I’m syncing context with a claude.md file — feels clunky”, “How do you track multiple Claude Code sessions?”, “How do you get two Claude Code sessions to talk to each other?”. The demand is real enough that commercial “remote fleet” products are appearing for exactly this.
I built mine instead, because the shape I wanted wasn’t a dashboard. It was a seat.
Comms are short: the one-word command grammar
A good IGL doesn’t narrate. peek, watch, up, stop, shot — words you can say while something else is happening. Here’s the radar, today, for real:
┌ igl ls
◇ servers
│ ✓ s1 4 sessions
│ ✓ s2 0 sessions
PROJECT SERVER FOLDER SESSION CLAUDE ATTACHED STATE
callback s1 ~/zero8.dev/callback callback yes yes working · 3m ago
callback-dev – – –
inboxstack s1 ~/zero8.dev/inboxstack inboxstack yes yes idle: The token works: `/api/v1/version` return… · 18m ago
igl s1 ~/zero8.dev/igl none
└ Done in 403ms
Next: igl callback One screen, 403 milliseconds: which agents are mid-round, which one finished and what its last words were. The grammar from there:
igl callback # attach to the project, wherever it lives
igl peek callback 40 # read its screen without attaching
igl up callback # buy round: start the dev stack on its server
igl shot # send the screenshot on my clipboard into a session's prompt
igl auth # finish an OAuth login a server-side Claude asked for Sessions live in tmux on the servers, so they survive the laptop sleeping, changing networks, or being shut in a bag. When the ssh link drops mid-attach, a reconnect panel ticks in place — probing s1…, re-forwarding 5173…, back — instead of leaving a frozen line. Opening the laptop is checking the radar, not waking the team.
The part I like most: agents need an inbox, not a chat
Here’s the feedback mechanism, and it’s my favourite thing in the system.
Every igl agent is a plain Claude Code session with a small mod inside — a plugin that hooks the engine’s events and reports what the session is actually doing: working, idle, needs-input, needs-approval, with the tool it’s on and since when. That’s where the STATE column above comes from. Before the mod, igl could only guess “working” from whether the tmux pane had changed in the last 30 seconds. Now the agent says so itself, and when it goes idle it reports the first line of its last message — which is how I knew, from the radar alone, that inboxstack had finished verifying a token.
On top of the reports sit two commands:
igl call <session>@<server> --wait "<order>"— a direct order with an answer. First live test: the laptop got an agent’s answer back from s1 in 6.4 seconds.igl fb <project> "text"— feedback into the project’s inbox, delivered at the agent’s next natural boundary: an idle agent gets it as its next turn, a busy one at the end of its current turn, a project with no live agent at its next session.
That second one is the insight. You don’t interrupt a player mid-round to discuss strategy. Feedback goes in any time, silently; the agent picks it up when picking it up costs nothing. Delivery is at-least-once — a message survives an interrupted turn and gets retried rather than lost — which means orders are written to tolerate the rare duplicate, exactly like messages between people who trust the channel more than the timing.
The design on top of this is one email a day: decisions needed (numbered, each with the agent’s recommendation), done, blocked, tomorrow, and what happened to your feedback — built on the server by cron, arriving whether the laptop is open or not, answered by reply: “1: yes, 2: use B, 3: stop.” I should be honest about status: the reporting mod, the call channel, and the inbox are built and running on s1 today. The digest is still a design. Right now the day’s report arrives the old way — me, typing igl.
The feedback loop ate the tool too
The same discipline points inward. igl has a FEEDBACK.md: anyone — person or agent — who hits something wrong running igl files an entry with the verbatim output, a severity (P0 wrong behaviour down to P3 polish), and the design rule it breaks. One pass filed 31 issues. Thirty were fixed in the next release; one was an honest wontfix with the reason recorded.
My favourite is F-31: before the consent rules were tightened, a real igl up callback quietly rewrote a startup script on the server — seven lines added, six removed, nobody asked. The fix wasn’t just the bug; it became a design rule (piped commands can’t act without explicit consent) and a selftest seam that now gates every release.
So the agents that igl manages also review igl, in writing, against its own design doc. The in-game leader gets coached by the team.
What this buys a company of one
Speed with a safety net, mostly. igl went from v0.1.0 to v0.9.0 in nine days — but the thing I’d actually show off is the release conveyor that made that pace safe: every machine updates itself daily at 07:00; a beta machine runs a selftest from the new build and rolls itself back and files a GitHub issue if a seam fails; a beta only goes stable after a 48-hour soak on the canary, and the promote step reads the beta’s own logs before agreeing. Logs ship with eight credential shapes redacted, because agents’ logs cross machines now.
And it’s the connective tissue for everything else I’ve written about this year: the 2,269 sessions the builder retrospective mined now have a place to run that isn’t my lap; the daemon that taught me process lifecycle runs on this fleet; the 29 websites of the one percent internet deploy from it.
igl itself is private — it’s wired to my machines and my config. But nothing in it is exotic: the mechanics are tmux, ssh, Tailscale, and a Claude Code plugin. If you build your own seat, the four patterns worth stealing are: (1) agents report state from inside, via a plugin, instead of being guessed at from outside; (2) feedback is an inbox delivered at turn boundaries, not an interruption; (3) agents never block — reversible default, assumption recorded, decision batched; (4) keep a feedback file that anyone, including the agents, can write to against your own design rules.
The honest caveats: the memory and secrets areas are still design folders, s2 is freshly provisioned and mostly empty, old z8 paths still leak out of corners (a recorded wontfix, because renaming them needs a migration on every server), and the digest — the piece that would make this fully asynchronous — isn’t built. The README’s own status line says it best: “Ideas are parked here and built only when we choose to.”
Rounds are lost to bad information, not bad aim
Ten years of async remote work taught me that interruptions are how rounds get lost, and that written handoffs beat presence. The agents get the same contract a good async teammate gets: autonomy during the day, decisions batched, one structured report. The surprise of this October is how little of it needed inventing — the mechanics are tmux, ssh, Tailscale, and a plugin; the design is just management, applied to software that can finally be managed.
The laptop took the demotion well. It was never the top fragger anyway.