swarm

module
v0.5.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: MIT

README

swarm

CI

emmanueldeloget.com/swarm — what it looks like, in fewer words than this page.

Run a fleet of terminal agents — claude, codex, anything with a CLI — each in its own virtual terminal, and drive them all from one place: a TUI, a web page, or the swarm command itself. The agents get that same command, so they can talk to each other without you relaying messages.

swarm knows nothing about any particular agent. An agent is a command line.

swarm init          # write a starter swarm.yaml, and offer to .gitignore .swarm/
$EDITOR swarm.yaml  # list your agents
swarm run           # start the fleet + the TUI + the web remote

What it does

  • One window for the whole 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 it prints: working, idle — quiet long enough that it is probably waiting for input — plus whatever the configured regexps name, such as approval or error. The header counts them by state. An agent that owes an answer and has gone quiet is stalled, and swarm why says what it owes, to whom, since when, and the command that ends it — which the agent itself has usually forgotten by then.
  • Input from anywhere. Type into an agent from the TUI, from swarm inject, or from a browser. Send key presses (esc, ctrl+c, arrows). Stage a file or an image and inject its path.
  • A message bus. swarm send dev-3 "..." reaches an agent whether you type it or another agent does. Three modes: push types it into the recipient's prompt, pull leaves it for swarm inbox, defer holds it until the agent falls quiet. What a fleet says to itself can also be bounded — kinds, can_send, a turn budget per conversation, and a pause switch.
  • A fleet that keeps running. An agent whose command cannot start is relaunched with a doubling wait and given up on after restart_max tries, rather than every two seconds for ever; keys sent together are spaced by key_delay, so an agent whose UI changes state on one does not drop the rest.
  • A view of the talking. swarm bus tail and swarm bus stats show what the fleet says to itself — busiest pairs, threads, who is sending and who is only receiving — and the TUI marks an agent putting a lot on the bus. Agents that coordinate instead of working is the failure mode of a fleet, and it is invisible from the terminals.
  • Agents for one task. A template rather than an agent: swarm spawn worker "take ticket 219" makes worker-1, which is created owing that task and collected when it says the task is done. With workspace: worktree it gets its own directory and branch, taken back when it goes — and never taken with work still in it.
  • 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. The listener is signature-checked and lives on its own port.
  • Outgoing webhooks, the same rules read backwards: an agent that finished, died or needs you becomes a signed POST to your endpoint. The fleet can say so without anyone watching it.
  • Remote control over HTTP, token-protected, with no JavaScript terminal library: swarm already emulates the terminals and sends ready-made HTML.

Install

go install github.com/emmanuel-deloget/swarm/cmd/swarm@latest

Or from a checkout:

go build -o swarm ./cmd/swarm

Requires Go 1.25+. Linux and macOS are the tested platforms; Windows works and is newer — see Windows.

On Windows, install it this way rather than downloading a binary. Nothing is published as a signed .exe yet, and an unsigned Go binary is regularly taken for malware by heuristics — go install compiles on your machine, so the question does not arise.

Recipes

Fleets that do something, each with a configuration you can copy and a test that keeps it loading: code and review driven by GitHub webhooks, an agent whose test gate takes ten minutes, one agent per ticket on its own branch, an agent with hands on another machine over ssh, four philosophers and a moderator, a fleet woken by a clock, two models and a referee.

docs/recipes/

Configuration

swarm init writes a starter swarm.yaml: one agent, nothing listening on a port, and every other setting present as a commented example. Uncomment what you need — each block is written so it loads as it stands. swarm.example.yaml in this repository is that same file, if you would rather read it before installing anything.

docs/configuration.md is the exhaustive reference: every key, its default, what it does, and where the file is looked up. Unknown keys are an error rather than a warning, so a typo in a key name is reported instead of quietly ignored.

Where an agent works

Six agents on one checkout take turns at the index rather than working at once. workspace: says what swarm does about that, per agent: nothing, its own durable clone, or a git worktree for an agent that exists for one task. swarm never fetches, rebases or merges — it reports where each agent works and how far its base has drifted, and leaves the repository alone otherwise.

The modes, what they provision, and the hooks that prepare a working copy are in docs/configuration.md.

Watching the fleet

A terminal interface — a list with live state, the selected agent beside it, a mosaic of every agent at once — and the same fleet in a browser, served by swarm itself with no JavaScript terminal library.

docs/interfaces.md has the keys, the panes, attaching and detaching, and what the web UI does and does not allow.

Driving it from the command line

swarm run                           # the fleet, the TUI, the socket, the web UI
swarm ls                            # the agents and their state
swarm inject dev-1 "run the tests"  # type into an agent
swarm send review-1 "ready for you" # a bus message, from you or from an agent
swarm spawn worker "take rq-219"    # an agent for one task
swarm why dev-22                    # why it is stalled, and how it gets out

Every command, its flags, the key names, the mouse and how attaching works: docs/cli.md.

Agents talking to each other

One swarm send reaches an agent whether you typed it or another agent did. Messages have kinds, a question leaves something outstanding until it is answered, and a conversation can be given a turn budget so it ends. docs/bus.md covers the delivery modes, what a debt is, the stalled state, and how to bound the talking.

Webhooks

Declarative rules turn an HTTP delivery into a bus message, and the same rules read backwards turn a finished agent into a signed POST to your endpoint. docs/webhooks.md has the rules, the signatures and how to find out why nothing happened.

How it works

                        ┌──────────────┐
  swarm run ───────────►│     hub      │  fleet, events, message bus
                        └──┬────────┬──┘
             ┌─────────────┘        └──────────────┐
      ┌──────▼──────┐                       ┌──────▼──────┐
      │ agent dev-1 │  pty + VT emulator    │ agent rev-1 │
      └──────┬──────┘                       └─────────────┘
             │ argv: claude, codex, ...
             ▼
   ┌───────────────────┬────────────────────┬──────────────────┐
   │ TUI (bubbletea)   │ unix socket (IPC)  │ HTTP + WebSocket │
   │                   │  ← swarm CLI       │  ← browser       │
   │                   │  ← agents          │                  │
   └───────────────────┴────────────────────┴──────────────────┘

Each agent runs in a real pty, so it behaves exactly as it would in your terminal — job control, ^C, terminal queries, alternate screen. swarm keeps a virtual terminal emulator in sync with each pty, which is what makes it possible to render a snapshot of any agent at any time instead of replaying a byte stream that may start mid-sequence. The TUI renders that snapshot as ANSI, the web server renders it as HTML lines and sends only the ones that changed.

The control socket lives in .swarm/<session>.sock, or in the runtime directory with a pointer file when the project path is too long for a Unix socket.

Windows

swarm runs on Windows 10 build 17763 (1809) or later, which is what CreatePseudoConsole requires. Everything the tour above describes works there: the TUI, attaching, the bus, the control socket, swarm send from inside an agent. Continuous integration runs it on a Windows runner alongside Linux and macOS: the terminal, the fleet, the bus, the control socket and the end-to-end tests that drive the real binary.

It is the youngest of the three, and these are its differences. None is a surprise waiting to be found — they are here because they are what a first day on Windows runs into.

detach_key ctrl+g, not ctrl+\. A Windows console translates keys itself and its support for ctrl with punctuation is incomplete: ctrl+\ and ctrl+] arrive as a plain backslash and bracket, so neither can be a shortcut. Everything else came through — the arrows with ctrl, shift and alt included.
alt+enter The console's own full-screen toggle. It never reaches swarm, so it cannot be bound.
swarm attach No status bar on the last row: holding one needs a scrolling region the console does not honour, and the bar ends up stacked across the screen. The reminder goes in the window title instead, until an agent sets a title of its own.
secret_path Not checked. Windows has no POSIX modes — every readable file reports 0666 — and who may open a file is its ACL, which mode bits cannot express. On a shared machine, put the secret somewhere your account alone can read.
workspace: none Reports the branch of the directory an agent started in, even after it has moved. Following a process needs /proc, which only Linux has; macOS is in the same position.
The mouse Clicks, drags and the wheel are not passed to agents. A pseudoconsole does not carry an application's private modes back out, so swarm cannot tell whether an agent wants them — and sending them regardless would be read as text. Mouse mode still works for swarm's own interface.
Fonts The shortcut bar writes enter where it writes elsewhere: the raster fonts the older console offers have no glyph for it. The mark drawn while an agent starts is braille, which those fonts do not have either — it comes out blank rather than wrong, and it is decoration. Windows Terminal has both.

Two things are worth knowing about the console you run it in. The older conhost (the plain "Command Prompt" window) works, and swarm asks it to interpret escape sequences at startup — but its font may lack the symbols above. Windows Terminal has them, and is the default on Windows 11.

If a key does not do what you expect, swarm keys -read prints the bytes your terminal actually sent for it, and the name swarm gives them. That is how the list above was established rather than guessed.

Limits

  • Windows is supported and newer than the rest; its differences are listed above.
  • Attaching from the TUI () reconstructs key bytes from parsed events, which covers text, control keys, arrows and arrows held with ctrl/shift/alt, but not exotic sequences or mouse input. A runs the real swarm attach instead, which passes bytes through unchanged.
  • reply: in a pattern answers a prompt on your behalf. Use it only for prompts you would always answer the same way.
  • The webhook listener holds one secret, so it trusts one sender: giving a second source the same secret means either can impersonate the other. It also does not deduplicate retries — a sender that resends a delivery it thinks failed will produce a second message.

Working on swarm

Tests, linting and where the code lives: CONTRIBUTING.md.

Licence

MIT — see LICENSE.

swarm carries other people's work inside its binary: the Go modules it links against, and JuliaMono, the font the web UI draws a terminal with. Their terms travel with it, and any copy can be asked for them:

swarm licenses                      # what is in this binary, and under what terms
swarm licenses juliamono            # one of them in full
swarm licenses -all > NOTICES.txt   # every text, for an audit or a release

The same list is a page in the web UI, linked from the header. Neither fetches anything from the network.

The font is bundled rather than named in a CSS font stack because a stack can only ask for what the machine already has: a terminal draws its frames out of box-drawing characters, and a machine without them borrows them from a proportional font, which pulls every frame apart. It is the reason the binary is about two megabytes larger than it would otherwise be.

Directories

Path Synopsis
cmd
swarm command
Command swarm runs a fleet of terminal agents and lets you drive them from one place: a TUI, a web page, or the swarm CLI itself — which is also how the agents talk to each other.
Command swarm runs a fleet of terminal agents and lets you drive them from one place: a TUI, a web page, or the swarm CLI itself — which is also how the agents talk to each other.
internal
agent
Package agent turns one configured command into a supervised agent running in its own virtual terminal, with a state derived from what it prints.
Package agent turns one configured command into a supervised agent running in its own virtual terminal, with a state derived from what it prints.
bus
Package bus stores the messages agents send each other.
Package bus stores the messages agents send each other.
config
Package config loads and validates the swarm fleet description.
Package config loads and validates the swarm fleet description.
event
Package event carries what happens in the swarm to whoever is watching: the TUI, the web clients, the log.
Package event carries what happens in the swarm to whoever is watching: the TUI, the web clients, the log.
guide
Package guide writes the file agents read to learn how to talk to each other.
Package guide writes the file agents read to learn how to talk to each other.
hook
Package hook turns incoming webhooks into bus messages.
Package hook turns incoming webhooks into bus messages.
hub
Package hub owns the fleet: it creates the agents, wires their environment so they can talk back to swarm, and routes every command to them.
Package hub owns the fleet: it creates the agents, wires their environment so they can talk back to swarm, and routes every command to them.
ipc
Package ipc is the control channel between the running swarm and every `swarm <command>` invocation, including the ones agents make themselves.
Package ipc is the control channel between the running swarm and every `swarm <command>` invocation, including the ones agents make themselves.
licenses
Package licenses carries the terms of everything swarm ships inside its binary, so that a copy of swarm can always answer for what is in it.
Package licenses carries the terms of everything swarm ships inside its binary, so that a copy of swarm can always answer for what is in it.
licenses/gen command
Command gen collects the licence of every module swarm links against and writes it into ../data, where the licences package embeds it.
Command gen collects the licence of every module swarm links against and writes it into ../data, where the licences package embeds it.
probe
Package probe is the child process the tests drive instead of a shell.
Package probe is the child process the tests drive instead of a shell.
probe/cmd/probe command
Command probe is the child process the end-to-end tests drive instead of a shell.
Command probe is the child process the end-to-end tests drive instead of a shell.
sockpath
Package sockpath decides where a session's control socket lives.
Package sockpath decides where a session's control socket lives.
ui
Package ui is the terminal interface: one place to watch every agent, jump into one, and drive the fleet without leaving the keyboard.
Package ui is the terminal interface: one place to watch every agent, jump into one, and drive the fleet without leaving the keyboard.
version
Package version reports which swarm this is.
Package version reports which swarm this is.
vterm
Package vterm runs a child process inside a pseudo-terminal and keeps a virtual terminal emulator in sync with its output.
Package vterm runs a child process inside a pseudo-terminal and keeps a virtual terminal emulator in sync with its output.
web
Package web serves the remote control: a single page that shows every agent's terminal and lets you type into it from another machine — or from a phone.
Package web serves the remote control: a single page that shows every agent's terminal and lets you type into it from another machine — or from a phone.
workspace
Package workspace provisions a durable working copy for an agent.
Package workspace provisions a durable working copy for an agent.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL