feat(swarm): one task, a herd of agents, one answer (PRD 0015) - #502
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014HMV1QDcVY1xiaWWrZQM4S
What Claude Code calls ultracode, on any engine moshcode can start. The
herd already had every part — sessions that outlive the terminal, `herd
prompt --wait`, a task ledger holding each session's output — and moshscript
could wire a fan-out by hand. `moshcode swarm "<task>"` is the verb that
composes them:
plan one headless call splits the task into at most --agents
pieces that do not touch the same files (JSON in, JSON out;
a plan that does not parse runs the task as one piece)
fan out one herd session per piece, --agents at a time (default 4,
the same cap the claude engine's defaults put on Claude's own
workflows), prompted and waited on as `herd prompt --wait` is,
so every piece is a task in the ledger
verify --verify: one skeptic per piece, prompted to refute; its
verdict goes to the synthesis, never drops a piece by itself
synthesise one more call folds the outputs into the answer
Sessions are ended when it is done unless --keep. --plan-only shows the
split and starts nothing; --json is the whole run as data. A blocked engine
at boot (a trust dialog on a new directory) gets Enter once, then the
prompt; anything still blocked is reported, not answered.
Everything that touches an engine or a pty goes through an injectable deps
object, so test/swarm.test.mjs runs the four phases against fakes. Works
from the CLI, the pit (/swarm) and moshscript (swarm(...)). README section
and command table, help page, PRD 0015 and index.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014HMV1QDcVY1xiaWWrZQM4S
… prompts land
Four things a live `moshcode swarm` against Claude Code 2.1.270 turned up,
none of them visible to a unit test because they are all about what the real
engine paints:
- The pane title is the herd's handle, and Claude overwrites it through OSC
the moment it is up ("1 awaiting input · claude agents"). The member fell
out of the pane index and read `gone` while it sat waiting for a prompt.
tmuxStartPlan now pins it with `allow-set-title off` (tmux 3.4+, guarded
by tmuxCanPinTitle so an older tmux keeps today's plan).
- A detached session is 80x24 and truncates the status line the idle rule
reads ("? for shortc…"). Sessions start 200x50; a client that attaches
resizes as before.
- Claude 2.1 with permissions bypassed no longer prints "? for shortcuts";
its footer is "bypass permissions on (shift+tab to cycle)" and an empty
composer shows '❯ Try "…"'. Both are idle now, checked after the shared
working rules. The workspace trust dialog is `blocked`, and the claude
engine carries a `boot` spec that answers it with Down, Enter — its default
is "No, exit", so the reflex Enter ends the engine.
- A long prompt typed by send-keys is a paste to the composer, and the Enter
on its heels landed inside it as "+1 lines"; nothing was ever submitted.
sendPrompt settles for a quarter second between the text and Enter.
In the swarm itself: members start with the engine's `agentArgs` rather than
`--agent`, because for Claude `--agent` opens the agents overview, where a
typed prompt starts a background job somewhere else instead of working here;
the prompt wait will not take an idle screen as finished until it has seen
the engine work; and the headless plan/verify/synthesis calls are told to
think, not act — a synthesis run in the working directory did the task itself.
Verified live: two agents, two files, both ledger tasks carry the agents'
SUMMARY sections, the synthesis reads them, sessions ended, exit 0.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014HMV1QDcVY1xiaWWrZQM4S
ThreatCrush Security Scan4 finding(s) in the 13 file(s) this pull request changes. MEDIUM: 4
89 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 8 | **MEDIUM**: 71 | **LOW**: 10Not introduced by this pull request. The full set is in the Security tab.
…and 69 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
ralyodio
added a commit
that referenced
this pull request
Sep 13, 2026
…ts a retry (#503) CI on ubuntu-latest (tmux 3.4) answered `invalid option: allow-set-title` to every session start after #502, so no herd member could start there and the tmux-backed tests went red. The option arrived in 3.5, not 3.4. tmuxCanPinTitle now requires 3.5. And because a version string is a guess about a binary, startSession also learns the answer the hard way: when tmux rejects the pin it kills the half-made session (tmux stops at the command it rejects, after the session exists), remembers "no" for the rest of the process, and starts the member with the plan an older tmux understands. A wrong guess costs one retry, never a member. Verified: the full suite locally (tmux 3.6); the survival, tile and pinned- title suites in a node:22 container with the fake-runner fallback; and, as a baseline, main's own herd.mjs fails the same three tmux tests on Debian's 3.3a, so that older crash is pre-existing and separate. Claude-Session: https://claude.ai/code/session_014HMV1QDcVY1xiaWWrZQM4S Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
What Claude Code calls ultracode, on any engine moshcode can start. The herd already had every part (sessions that outlive the terminal,
herd prompt --wait, a task ledger holding each session's output), and moshscript could wire a fan-out by hand.moshcode swarm "<task>"is the verb that composes them:--agentspieces that do not touch the same files (JSON in, JSON out; a plan that does not parse runs the task as one piece)--agentsat a time (default 4, the same cap the claude engine's defaults put on Claude's own workflows), prompted and waited on so every piece is a ledger task--verify: one skeptic per piece, prompted to refute; its verdict goes to the synthesis and never drops a piece by itselfSessions are ended when it is done unless
--keep.--plan-onlyshows the split and starts nothing;--jsonis the whole run as data. Works from the CLI, the pit (/swarm) and moshscript (swarm(...)). PRD 0015, README section and command table, help page.Herd fixes it needed (second commit)
Running it live against Claude Code 2.1.270 turned up four things no unit test could see:
gonewhile waiting for a prompt.tmuxStartPlanpins it withallow-set-title off(tmux 3.4+, version-guarded).❯ Try "…"). Both are idle now. The trust dialog isblocked, and the claude engine's newbootspec answers it with Down, Enter, because its default is "No, exit".sendPromptsettles 250ms before Enter.In the swarm: members start with the engine's
agentArgs, not--agent(for Claude that opens the agents overview, where a typed prompt starts a background job elsewhere); the prompt wait insists on seeing the engine work before accepting idle; the headless calls are told to think, not act.Verified
node --test: 2967 tests, 0 failures (340 environment-gated skips). New:test/swarm.test.mjs(32),test/herd-pinned-title.test.mjs,test/herd-send-prompt.test.mjs.🤖 Generated with Claude Code
https://claude.ai/code/session_014HMV1QDcVY1xiaWWrZQM4S