Workspacessince v0.2.0
You choose how isolated an agent is#
Six agents in the same directory get in each other’s way. workspace: says, agent by agent, who shares the working copy and who gets one of their own.
- workspace: sharedno isolation
The default: the common
workdir. Right when agents take turns rather than work at once. - workspace: cloneswarm isolates it
A durable copy per agent, provisioned once from the local repository — git hardlinks the objects, so the cost is the working tree, not the history.
- workspace: worktreeswarm isolates it, then takes it back
A git worktree on its own branch, for an instance that exists for one task — collected when it ends. Two worktrees cannot share a branch, which is exactly why a throwaway one can have its own.
- workspace: noneyou isolate it
For an agent in its own container, VM or checkout. swarm presumes nothing and reads the directory the process is actually in.
It is a per-agent setting: one fleet can mix all four.
env:
PORT: "{alloc_port}" # a free port, one per agent
defaults:
on_start: [./scripts/prepare-agent.sh]
agents:
- name: dev-1
command: [claude]
workspace: clone # its own copy of the repository
- name: dev-2
command: [codex]
workspace: clone
- name: review-1
command: [codex]
workspace: shared # reads what the others push
A clone, not a worktree
Two worktrees cannot have the same branch checked out — which settles it the moment two agents sit on main. origin, user.* and gpg.* are carried over, or an agent commits unsigned under the wrong name.
Furnished before it starts
This is the part of isolation no agent can arrange for itself: on_start runs before the process, on_exit after it — install dependencies, copy a .env, point at a test database. A failing one stops the agent instead of launching it into a half-prepared directory.
One word per agent
A directory that is already a checkout is left alone, so a fleet of hand-made clones adopts this by adding one word each. {alloc_port} hands out a free port per agent — two dev servers both want 3000.
An agent for one tasksince v0.5.0
An entry marked ephemeral: true is not an agent — it is the shape of one. Nothing starts for it, and it never appears in swarm ls. swarm spawn makes instances from it, named after it, which run one task and are collected when they say they have finished.
The task is sent as a debt, which is what makes everything already built apply to it: swarm why worker-1 says what it is on and since when, on_stalled asks it where it is if it goes quiet, the debt survives a restart — and swarm done is what collects it, its task being its life.
agents:
- name: triage
command: [claude]
can_spawn: [worker] # who may launch them
- name: worker
ephemeral: true # a template, not an agent
command: [claude]
workspace: worktree # its own branch, taken back after
max_alive: 3
swarm spawn worker "take ticket 219" # prints: worker-1
swarm spawn worker -f brief.md # or - for stdin
swarm why worker-1 # what it owes, and to whom
swarm reports, and never acts
The branch, a star for uncommitted changes, and how far the base has drifted — in swarm ls and in the pane header. No fetch, no rebase, no merge: telling agents to catch up is a webhook rule, not swarm running git behind their backs.