Run a fleet of agents in your terminal.
claude, codex, anything with a CLI — each in its own virtual terminal, all driven from one place: a TUI, a browser, or the swarm command itself.
The agents get that same command, so they talk to each other — and you can see, shape and pause what they say.
go install github.com/emmanuel-deloget/swarm/cmd/swarm@latest- Linux
- macOS
- Windows 10 1809+
Requires Go 1.25+ · swarm init writes you a config
swarm run starts the fleet, the TUI and the web remote. The header counts the fleet by state, so a prompt waiting on you is visible without hunting for it.
Features
What it gives you#
swarm knows nothing about any particular agent. An agent is a command line — everything below follows from that.
One window for the fleet
A list with live state, the selected agent’s terminal beside it, and a mosaic view showing every agent at once.
A state per agent
Derived from what the agent prints:
working,idle— quiet long enough that it is probably waiting for you — plus whatever your regexps name, such asapprovalorerror.A workspace per agent
Six agents in one directory get in each other’s way.
Read onworkspace:says who shares the working copy and who gets one of their own — and who exists for a single task.Input from anywhere
Type into an agent from the TUI, from
swarm inject, or from a browser. Send key presses. Stage a file or an image and inject its path.A message bus
Three modes: push types it into the prompt, pull waits for
Read onswarm inbox, defer holds it until the agent falls quiet.swarm bus statsshows who is talking to whom.Incoming webhooks
Declarative rules turn an HTTP delivery into a bus message, so the fleet reacts to a pull request or a ticket without you relaying it. Signature-checked, on its own port.
Read onRemote control over HTTP
Token-protected, with no JavaScript terminal library: swarm already emulates the terminals and sends ready-made HTML, then only the lines that changed.
Agents that talk to each other
Every agent gets
swarmon itsPATH, already pointed at the running session, plus$SWARM_AGENT,$SWARM_PEERSand a shared directory.A real terminal, not a pipe
A pty on Unix, a pseudoconsole on Windows — so an agent behaves exactly as it would in your terminal: job control,
^C, terminal queries, the alternate screen.
How it works
One hub, one pty per agent#
Everything that drives the fleet — the TUI, the swarm command, a browser — talks to the same hub. The hub owns the fleet, the events and the message bus.
A real terminal per agent
Not a pipe: an agent gets a terminal — a pty, or a pseudoconsole on Windows — so job control,
^C, terminal queries and the alternate screen all work the way they do when you run it yourself.A terminal emulator kept in sync
swarm keeps a virtual terminal in step with each pty, which is what makes a snapshot of any agent possible at any moment — instead of replaying a byte stream that may start mid-sequence. The TUI renders it as ANSI, the web server as HTML lines, and sends only the ones that changed.
One socket, many callers
The control socket lives in
.swarm/<session>.sock. Your other terminals reach it, and so do the agents — which is why an agent can runswarm sendwith no arguments of its own.
The agents’ guide
swarm writes the fleet’s documentation#
Everything on this page is what swarm does for you. This is what it tells the agents — so they know there is a bus, that a request leaves something outstanding, and how to settle it.
swarm runwrites.swarm/AGENTS.mdfrom your configuration. Point your agents’ instructions at it and they can coordinate without you.- A section appears only when the thing it describes is switched on. A guide that names mechanisms nobody dispatches on is worse than none — an agent told about message kinds in a fleet that ignores them learns to type flags nobody reads.
agents_templatereplaces the built-in one with yours, getting exactly the same data — which is the only way an override can be as informed as what it replaces.
## When something is asked of you
A `question`, a `request` or a `blocked` addressed to you
leaves something outstanding until you settle it. The message
tells you how, and it is worth doing even when the answer is
"there was nothing to do":
```sh
swarm done # everything outstanding is finished
swarm done -thread 7 "note" # just this one, with a word about it
```
Until then you are counted as owing it.
The CLI
Drive the fleet from any terminal#
Every command talks to a running swarm over a Unix socket — from another terminal, from a script, or from an agent.
Look at what the fleet is doing without stopping it. swarm screen prints what a terminal shows right now; swarm attach hands the window over until you press the detach key.
A target is an agent name, @group, @role, all, or a comma-separated list of those. Every command that acts on agents takes one.
swarm ls # state, branch and drift
swarm status @dev # more detail
swarm screen dev-1 # what that terminal shows right now
swarm attach dev-1 # take it over in this window
swarm logs dev-1 -f # recorded output, escapes stripped
swarm config check -fix # a config that has gone stale
Recipes
Fleets that do something#
Each one is a swarm.yaml you can copy, living in the repository — where a test loads them all through the real config loader, so a renamed key breaks the build rather than waiting for you to hit it.
- symposiumfour philosophers and a moderator
No repository, no git, nothing to build. Four philosophers argue, and none of them can reach another: every message goes through a moderator. The smallest fleet that shows what swarm is with no code in the way.
can_sendmax_turnsmessageRead the recipe - gatean agent whose tests take ten minutes
An agent that has launched an integration suite is quiet, shows nothing, and is working. One waiting on an answer it has forgotten it owes is quiet, shows nothing, and is stuck. This is swarm telling them apart.
patternsstalled_afteron_stalledRead the recipe - reviewcode and review, driven by GitHub
Two agents writing code on their own branches, one reading what they write, and one deciding who should see what arrives from GitHub. A pull request reaches the reviewer without you relaying it.
hooksworkspacecan_sendRead the recipe
- tickets — one agent per ticket.
swarm spawn worker "take rq-219"makes an instance that is created already owing that task, gets its own branch, and goes away when it says it is done. - ssh — an agent is a command line that runs in a terminal, and
sshis a command line that runs in a terminal. So one member of the fleet can be a live session on another machine. - nightshift — a fleet woken by a clock. swarm has no scheduler and no reason to have one: the machine already has a good one, and swarm has an HTTP listener for it to talk to.
Remote control
The same fleet, in a tab#
With web.enabled, swarm run prints a URL carrying a token. The page shows the agent list, the selected terminal — live, and you can type into it — a grid view, the event log, and a composer.
No JavaScript terminal library: swarm already emulates the terminals, so the server sends HTML lines, and only the ones that changed. The grid takes whole screens and picks the arrangement with the biggest cells — one column on a phone.
- Past localhost, treat that URL as a shell on your machine.
- Set
web.read_only: trueif you only want to watch. - Put it behind TLS or a tunnel (
ssh -R,cloudflared) rather than binding0.0.0.0in the open.
Get started
Three commands to a fleet#
Requires Go 1.25+. Linux and macOS are the tested platforms; Windows works and is newer.
Install it
Or build from a checkout with
go build -o swarm ./cmd/swarm.go install github.com/emmanuel-deloget/swarm/cmd/swarm@latestWrite a config
One agent, nothing listening on a port, every other setting present as a commented example — and it offers to add
.swarm/to your.gitignore. Then list your agents.swarm initStart the fleet
Starts the agents, the TUI and the web remote.
--no-tuiruns it headless if you would rather drive it from the CLI or the browser.swarm run
On Windowssince v0.4.0
Everything works there: the TUI, attaching, the bus, swarm send from inside an agent. Install with go install rather than downloading a binary — none is published signed, and an unsigned Go binary is regularly taken for malware by heuristics.
detach_keyisctrl+g: a console makesctrl+\arrive as a plain backslash.swarm attachputs its reminder in the window title — the console has no scrolling region to hold a status bar.secret_pathis not checked: who may open a file is an ACL, which mode bits cannot express.
MIT licence. Issues and pull requests welcome — CI runs the suite on Linux, macOS and Windows, plus go vet, gofmt, golangci-lint and govulncheck.