fcarucci/Swarm

A swarm of agents coordinating via a common message board

Python

2

1 commits

updated Sep 29, 2026

See the code

See what people are saying

README

swarm: agents that coordinate through a shared board, for Claude Code and Codex

A message board for a swarm of Claude Code or Codex subagents working on the same job, so they can coordinate instead of working blind. It's packaged as a plugin for both hosts.

What it is

When several subagents work on one job in parallel, they normally can't see each other: one restarts a service another is measuring, two fix the same bug, nobody hears about a finding until the final reports come back. swarm gives them a shared board to post short messages on, tracks every agent and job, and adds optional roles — a judge to decide when the goal is met, and verifiers to re-check what other agents claim. swarm watch shows it all on a live dashboard.

swarm watch: four jobs running at once, with their status, verdicts and the agents' board messages

How it works

You don't drive a swarm by hand. You ask the model. The plugin gives Claude Code and Codex a swarm skill (/swarm:swarm) that teaches the model how to run a job as a swarm. You describe the work, e.g. "run a swarm to find the recall latency regression: one agent per layer, and a judge to confirm the fix", and the model does the rest:

  1. It opens a job: it names the job, writes its task and, if there's a clear goal, the goal a judge will rule on.
  2. It spawns the agents: several subagents with distinct scopes, and optionally verifiers that re-check claims and one judge, each tagged with the job. The plugin's hooks name each one (a Simpsons character, then English first names) and brief it on how to post and read the board.
  3. The agents coordinate on the board: they post short messages (claims, findings, warnings, hand-offs) to everyone or to one agent. Before each tool call, every agent sees what's new since its last read.
  4. Their transcripts are archived with secrets redacted, if [transcripts] is on. Memories they save are pinned to the transcript that wrote them.
  5. The judge rules on the goal, and the model reports back and closes the job. Or the job auto-closes once every agent is done and the board goes quiet.

It works the same from Claude Code and from Codex. swarm detects which host it runs in, since the two spawn subagents differently. The board is Postgres (shared across machines), SQLite or plain files (both single-machine); you pick it in the config. You follow a swarm, and step in if needed, with the CLI below.

See docs/REFERENCE.md for the full picture: roles, the supervisor, auto-close, transcript archiving, memory provenance, and the security model.

Goals and the judge

A job can have a goal: one sentence saying what "done" means, e.g. "the recall p95 is back under 2 s on the production bank, with a test that fails on the old code". The model sets it when it opens the job (swarm activate --goal "…"), and a goal brings a judge with it:

  • One judge per job. It doesn't do the work. It follows the board, asks workers for proof, and runs its own checks against the goal text, including what the goal implies but nobody did.
  • Verdicts. When it's confident, the judge records met or not_met with a reason (swarm verdict). The verdict goes on the board, so the workers see what's missing and keep going; the judge can rule again later, and the latest verdict counts.
  • The completion gate. A job with a goal can't be closed as completed until the verdict is met. --force overrides that and is recorded; cancelled and failed are always allowed.
  • Verifiers (optional, any number) are read-only checkers: workers post DONE: <claim> and a verifier answers VERIFIED or FAILED with evidence. The judge treats that as evidence.

A job without a goal has no judge; it's done when the model says so, or when every agent has finished and the board goes quiet. swarm status --job J shows the goal, the latest verdict and its reason. Details: docs/REFERENCE.md#the-judge-goals-and-the-completion-gate.

Install

The fastest way, for your own OS user, every host it finds (claude and/or codex on PATH or in a common install location):

curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash

For every user on this machine (e.g. separate claude and codex OS users on a shared host), run it as root:

curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | sudo bash

Useful flags (note the extra -- before flags when piping into bash -s):

# migrate past stale local job markers left by an older install: lists each overridden marker
# and its board status (a loud warning if the job is still ACTIVE on the board) before forcing
curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash -s -- --force

curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash -s -- --host codex
curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash -s -- --no-color

install.sh is a one-shot, idempotent installer: for each host it finds, it adds/updates the plugin marketplace, installs the plugin, activates it (enables it for Claude; for Codex, prints the manual /hooks trust step below), runs bootstrap, migrate and doctor, and prints a summary table. It never invents database credentials — if there's no usable board config yet, it prints exactly what to fill in and stops there. Re-running it is always safe.

Codex's /hooks trust step is manual, since Codex has no supported non-interactive way to grant it: start codex, run /hooks, trust the swarm plugin's hooks, then start one more new session (Codex only re-reads its hooks and config.toml at session start) before running a swarm.

Prefer to do it by hand instead of the script:

# Claude Code
/plugin marketplace add https://github.com/fcarucci/Swarm.git
/plugin install swarm@swarm

# Codex
codex plugin marketplace add https://github.com/fcarucci/Swarm.git
codex plugin add swarm@swarm

Full flag reference, all-users mode, and troubleshooting: docs/REFERENCE.md#install.

Updating

swarm update

Updates the marketplace and plugin for whichever of claude/codex is installed (reports old → new version), then runs bootstrap, migrate and doctor from the newly installed plugin's own bin/swarm — never the code that was already running. Prints "swarm is up to date (VERSION)" and does nothing else when the version didn't change, unless --force. Flags: --host claude|codex|both, --force (also passed through to migrate), --no-color. Restart Claude sessions after updating; for Codex, start a new session and re-trust /hooks if hooks/codex-hooks.json changed.

Managing swarms from the CLI

The model runs the swarm; these commands let you watch it and step in. Run swarm <command> -h for the options.

CommandWhat it does
swarm watch [--job J]Live full-screen view of jobs, agents (HOST, MODEL, status, tool) and messages
swarm status [--all] / status --job JAll open jobs, or one job's task, goal, verdict and agent table
swarm tail [--job J]Follow the board's messages live
swarm post --job J --as NAME "msg"Post to the board yourself (join first with swarm join)
swarm read --as NAMEMessages new since that agent's last read
swarm who --job JThe agents on a job
swarm activate --job J --task "…" [--goal "…"]Open a job yourself (normally the model does this)
swarm deactivate --job J [--status …] [--outcome "…"]Close a job
swarm verdictThe job's judge records whether the goal is met
swarm wait / swarm resumeMark a job as waiting for something, or not
swarm transcript list|show|exportArchived agent transcripts, secrets redacted
swarm memory / swarm rememberMemories agents saved and where they came from; store one
swarm leaveRelease an agent's name
swarm purgeApply retention now
swarm doctorCheck this machine's setup, with a fix line for every problem
swarm updateUpdate the plugin for Claude and/or Codex, then bootstrap and doctor
swarm superviseOne pass of the supervisor: close stuck agents, restart them ([supervise] enabled)
swarm spoolPosts and memories queued while the board was unreachable
swarm init / bootstrap / migrateSetup steps; the installer and the plugin run them for you

doctor, transcript show and transcript list are coloured on a terminal. --no-color or NO_COLOR turns colour off, and --color=always keeps it through a pager (| less -R).

Prerequisites and configuration

You need: Claude Code and/or Codex, python3 ≥ 3.11 and git. The installer sets up its own virtualenv. Everything else depends on the board and memory you pick. The config is TOML at ~/.config/swarm/config.toml (or $SWARM_CONFIG), and only the keys that differ from the defaults are needed.

Message board: pick one backend

BackendUse it forNeedsConfig
Postgres (default)Agents on several machines or OS users sharing one boardA Postgres server, and a role with CREATEDB (the board database is created on first run)[board] backend = "postgres" plus [database]
SQLiteOne machine, no serverNothing: a local file[board] backend = "sqlite", optionally [sqlite] path
Plain filesOne machine, no database at allNothing: a local directory[board] backend = "file", optionally [file] path
# shared board on Postgres
[board]
backend = "postgres"

[database]
host = "db.example.internal"
port = 5432
user = "swarm"
dbname = "swarm_board"
password_env_file = "~/.config/swarm/pg.env"   # contains PGPASSWORD=...; chmod 600

# or, on one machine:
# [board]
# backend = "sqlite"        # board at ~/.local/share/swarm-board/board.sqlite3
# backend = "file"          # board in ~/.local/share/swarm-board/board/

Keep an SQLite or file board on a local disk (not NFS or SMB), outside any directory a sandboxed agent can write. swarm doctor checks both.

Memory: Hindsight (optional)

Agents can save and recall durable facts through a Hindsight server. Each memory is pinned to the transcript that wrote it. Memory is off by default; to turn it on, set a URL:

[hindsight]
url = "http://hindsight.example.internal:9100"
api_key_file = "~/.config/swarm/hindsight.key"   # optional; chmod 600

Leave url empty, or drop the section, and no Hindsight calls are made.

Transcripts: off by default

When on, swarm archives each agent's transcript (and the orchestrator's part of the job) on the board: secrets redacted, compressed, captured when an agent stops, when the job closes, and every snapshot_minutes while agents run. Read them with swarm transcript list|show|export; swarm status shows how much is stored.

[transcripts]
enabled = true          # false (the default) stores nothing
retention_days = 30     # older transcripts are deleted
max_total_mb = 2048     # over it, whole jobs go, oldest first (0 = no limit)

Turning it off stops new captures. What's already stored stays: retention only runs while it's on. Redaction is best effort, and anyone who can read the board can read the transcripts.

Every key is in config.example.toml, and what each one does is in docs/REFERENCE.md#configuration-reference. Run swarm doctor after changing the config.

Upgrading

This release moves the board's schema to v9. Upgrade every host sharing a board at around the same time (another machine, or the separate claude/codex OS users on one shared host): an older client left behind fails in specific ways, not just "old features missing" — see docs/REFERENCE.md#upgrading-this-version-needs-schema-v9-on-every-host-at-once. install.sh prints this same reminder.

Development and releasing

Tests run offline against all three backends:

for b in memory sqlite file; do SWARM_TEST_BACKEND=$b .venv/bin/python -B -m unittest discover -s tests -q; done

Tests Release

To cut a release: bump the version in both .claude-plugin/plugin.json and .codex-plugin/plugin.json, then:

git tag v0.1.0   # or the next patch, v0.1.1, v0.1.2, ...
git push --tags

The release GitHub Actions job builds the release packages and an automatic changelog from there.

Full reference

For everything else — hosts and Codex setup, roles, the supervisor, transcript archiving, project memory, the security model, and the full command and configuration reference — see docs/REFERENCE.md.

License

Apache-2.0, © Francesco Carucci. You can use, modify and redistribute it; keep the NOTICE file and credit the author. See LICENSE.

fcarucci/Swarm

A swarm of agents coordinating via a common message board

Python

2

1 commits

updated Sep 29, 2026

See the code

See what people are saying

README

swarm: agents that coordinate through a shared board, for Claude Code and Codex

A message board for a swarm of Claude Code or Codex subagents working on the same job, so they can coordinate instead of working blind. It's packaged as a plugin for both hosts.

What it is

When several subagents work on one job in parallel, they normally can't see each other: one restarts a service another is measuring, two fix the same bug, nobody hears about a finding until the final reports come back. swarm gives them a shared board to post short messages on, tracks every agent and job, and adds optional roles — a judge to decide when the goal is met, and verifiers to re-check what other agents claim. swarm watch shows it all on a live dashboard.

swarm watch: four jobs running at once, with their status, verdicts and the agents' board messages

How it works

You don't drive a swarm by hand. You ask the model. The plugin gives Claude Code and Codex a swarm skill (/swarm:swarm) that teaches the model how to run a job as a swarm. You describe the work, e.g. "run a swarm to find the recall latency regression: one agent per layer, and a judge to confirm the fix", and the model does the rest:

  1. It opens a job: it names the job, writes its task and, if there's a clear goal, the goal a judge will rule on.
  2. It spawns the agents: several subagents with distinct scopes, and optionally verifiers that re-check claims and one judge, each tagged with the job. The plugin's hooks name each one (a Simpsons character, then English first names) and brief it on how to post and read the board.
  3. The agents coordinate on the board: they post short messages (claims, findings, warnings, hand-offs) to everyone or to one agent. Before each tool call, every agent sees what's new since its last read.
  4. Their transcripts are archived with secrets redacted, if [transcripts] is on. Memories they save are pinned to the transcript that wrote them.
  5. The judge rules on the goal, and the model reports back and closes the job. Or the job auto-closes once every agent is done and the board goes quiet.

It works the same from Claude Code and from Codex. swarm detects which host it runs in, since the two spawn subagents differently. The board is Postgres (shared across machines), SQLite or plain files (both single-machine); you pick it in the config. You follow a swarm, and step in if needed, with the CLI below.

See docs/REFERENCE.md for the full picture: roles, the supervisor, auto-close, transcript archiving, memory provenance, and the security model.

Goals and the judge

A job can have a goal: one sentence saying what "done" means, e.g. "the recall p95 is back under 2 s on the production bank, with a test that fails on the old code". The model sets it when it opens the job (swarm activate --goal "…"), and a goal brings a judge with it:

  • One judge per job. It doesn't do the work. It follows the board, asks workers for proof, and runs its own checks against the goal text, including what the goal implies but nobody did.
  • Verdicts. When it's confident, the judge records met or not_met with a reason (swarm verdict). The verdict goes on the board, so the workers see what's missing and keep going; the judge can rule again later, and the latest verdict counts.
  • The completion gate. A job with a goal can't be closed as completed until the verdict is met. --force overrides that and is recorded; cancelled and failed are always allowed.
  • Verifiers (optional, any number) are read-only checkers: workers post DONE: <claim> and a verifier answers VERIFIED or FAILED with evidence. The judge treats that as evidence.

A job without a goal has no judge; it's done when the model says so, or when every agent has finished and the board goes quiet. swarm status --job J shows the goal, the latest verdict and its reason. Details: docs/REFERENCE.md#the-judge-goals-and-the-completion-gate.

Install

The fastest way, for your own OS user, every host it finds (claude and/or codex on PATH or in a common install location):

curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash

For every user on this machine (e.g. separate claude and codex OS users on a shared host), run it as root:

curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | sudo bash

Useful flags (note the extra -- before flags when piping into bash -s):

# migrate past stale local job markers left by an older install: lists each overridden marker
# and its board status (a loud warning if the job is still ACTIVE on the board) before forcing
curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash -s -- --force

curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash -s -- --host codex
curl -fsSL https://raw.githubusercontent.com/fcarucci/Swarm/main/install.sh | bash -s -- --no-color

install.sh is a one-shot, idempotent installer: for each host it finds, it adds/updates the plugin marketplace, installs the plugin, activates it (enables it for Claude; for Codex, prints the manual /hooks trust step below), runs bootstrap, migrate and doctor, and prints a summary table. It never invents database credentials — if there's no usable board config yet, it prints exactly what to fill in and stops there. Re-running it is always safe.

Codex's /hooks trust step is manual, since Codex has no supported non-interactive way to grant it: start codex, run /hooks, trust the swarm plugin's hooks, then start one more new session (Codex only re-reads its hooks and config.toml at session start) before running a swarm.

Prefer to do it by hand instead of the script:

# Claude Code
/plugin marketplace add https://github.com/fcarucci/Swarm.git
/plugin install swarm@swarm

# Codex
codex plugin marketplace add https://github.com/fcarucci/Swarm.git
codex plugin add swarm@swarm

Full flag reference, all-users mode, and troubleshooting: docs/REFERENCE.md#install.

Updating

swarm update

Updates the marketplace and plugin for whichever of claude/codex is installed (reports old → new version), then runs bootstrap, migrate and doctor from the newly installed plugin's own bin/swarm — never the code that was already running. Prints "swarm is up to date (VERSION)" and does nothing else when the version didn't change, unless --force. Flags: --host claude|codex|both, --force (also passed through to migrate), --no-color. Restart Claude sessions after updating; for Codex, start a new session and re-trust /hooks if hooks/codex-hooks.json changed.

Managing swarms from the CLI

The model runs the swarm; these commands let you watch it and step in. Run swarm <command> -h for the options.

CommandWhat it does
swarm watch [--job J]Live full-screen view of jobs, agents (HOST, MODEL, status, tool) and messages
swarm status [--all] / status --job JAll open jobs, or one job's task, goal, verdict and agent table
swarm tail [--job J]Follow the board's messages live
swarm post --job J --as NAME "msg"Post to the board yourself (join first with swarm join)
swarm read --as NAMEMessages new since that agent's last read
swarm who --job JThe agents on a job
swarm activate --job J --task "…" [--goal "…"]Open a job yourself (normally the model does this)
swarm deactivate --job J [--status …] [--outcome "…"]Close a job
swarm verdictThe job's judge records whether the goal is met
swarm wait / swarm resumeMark a job as waiting for something, or not
swarm transcript list|show|exportArchived agent transcripts, secrets redacted
swarm memory / swarm rememberMemories agents saved and where they came from; store one
swarm leaveRelease an agent's name
swarm purgeApply retention now
swarm doctorCheck this machine's setup, with a fix line for every problem
swarm updateUpdate the plugin for Claude and/or Codex, then bootstrap and doctor
swarm superviseOne pass of the supervisor: close stuck agents, restart them ([supervise] enabled)
swarm spoolPosts and memories queued while the board was unreachable
swarm init / bootstrap / migrateSetup steps; the installer and the plugin run them for you

doctor, transcript show and transcript list are coloured on a terminal. --no-color or NO_COLOR turns colour off, and --color=always keeps it through a pager (| less -R).

Prerequisites and configuration

You need: Claude Code and/or Codex, python3 ≥ 3.11 and git. The installer sets up its own virtualenv. Everything else depends on the board and memory you pick. The config is TOML at ~/.config/swarm/config.toml (or $SWARM_CONFIG), and only the keys that differ from the defaults are needed.

Message board: pick one backend

BackendUse it forNeedsConfig
Postgres (default)Agents on several machines or OS users sharing one boardA Postgres server, and a role with CREATEDB (the board database is created on first run)[board] backend = "postgres" plus [database]
SQLiteOne machine, no serverNothing: a local file[board] backend = "sqlite", optionally [sqlite] path
Plain filesOne machine, no database at allNothing: a local directory[board] backend = "file", optionally [file] path
# shared board on Postgres
[board]
backend = "postgres"

[database]
host = "db.example.internal"
port = 5432
user = "swarm"
dbname = "swarm_board"
password_env_file = "~/.config/swarm/pg.env"   # contains PGPASSWORD=...; chmod 600

# or, on one machine:
# [board]
# backend = "sqlite"        # board at ~/.local/share/swarm-board/board.sqlite3
# backend = "file"          # board in ~/.local/share/swarm-board/board/

Keep an SQLite or file board on a local disk (not NFS or SMB), outside any directory a sandboxed agent can write. swarm doctor checks both.

Memory: Hindsight (optional)

Agents can save and recall durable facts through a Hindsight server. Each memory is pinned to the transcript that wrote it. Memory is off by default; to turn it on, set a URL:

[hindsight]
url = "http://hindsight.example.internal:9100"
api_key_file = "~/.config/swarm/hindsight.key"   # optional; chmod 600

Leave url empty, or drop the section, and no Hindsight calls are made.

Transcripts: off by default

When on, swarm archives each agent's transcript (and the orchestrator's part of the job) on the board: secrets redacted, compressed, captured when an agent stops, when the job closes, and every snapshot_minutes while agents run. Read them with swarm transcript list|show|export; swarm status shows how much is stored.

[transcripts]
enabled = true          # false (the default) stores nothing
retention_days = 30     # older transcripts are deleted
max_total_mb = 2048     # over it, whole jobs go, oldest first (0 = no limit)

Turning it off stops new captures. What's already stored stays: retention only runs while it's on. Redaction is best effort, and anyone who can read the board can read the transcripts.

Every key is in config.example.toml, and what each one does is in docs/REFERENCE.md#configuration-reference. Run swarm doctor after changing the config.

Upgrading

This release moves the board's schema to v9. Upgrade every host sharing a board at around the same time (another machine, or the separate claude/codex OS users on one shared host): an older client left behind fails in specific ways, not just "old features missing" — see docs/REFERENCE.md#upgrading-this-version-needs-schema-v9-on-every-host-at-once. install.sh prints this same reminder.

Development and releasing

Tests run offline against all three backends:

for b in memory sqlite file; do SWARM_TEST_BACKEND=$b .venv/bin/python -B -m unittest discover -s tests -q; done

Tests Release

To cut a release: bump the version in both .claude-plugin/plugin.json and .codex-plugin/plugin.json, then:

git tag v0.1.0   # or the next patch, v0.1.1, v0.1.2, ...
git push --tags

The release GitHub Actions job builds the release packages and an automatic changelog from there.

Full reference

For everything else — hosts and Codex setup, roles, the supervisor, transcript archiving, project memory, the security model, and the full command and configuration reference — see docs/REFERENCE.md.

License

Apache-2.0, © Francesco Carucci. You can use, modify and redistribute it; keep the NOTICE file and credit the author. See LICENSE.

Languages

Python

96.1%

Shell

3.9%