Route bounded coding work across whichever installed agent CLI has quota to spare.
Historical (2026-08-27): accurate when written; see CHANGELOG for what changed since.
Four isolated, dependency-free Node projects were given to four entry paths:
cmd), asked in natural language to use Bullswarm.All four paths created detached workflow goal runs without hand-authored workflow JSON. All four runs reached durable completed / delivered state, included a worker action and a first-class verify action, and produced implementations that passed an independent post-run test. The three agent initiators did not edit their projects directly.
The feature is functionally usable by all four paths, but it is not yet frictionless as a distributed CLI experience. The checkout is version 0.7.2 while both the bullswarm on PATH and the current npm package are 0.4.0. The launch response emits bare bullswarm workflow ... observation commands, which fail in this environment even though the detached run was correctly launched through the checkout source. Claude, Grok, and Command Code all had to discover and explain this mismatch.
/tmp/bullswarm-usability-EsM9ev/homedirect, claude, grok, and cmd directoriesnpm test in each fixtureThe initiators were given the checkout path and the canonical skill/SKILL.md, but not the workflow goal command syntax. This tests whether they can select the intended surface without making CLI discovery itself an unbounded research task.
| Entry path | Initiation result | Approx. foreground launch time | Run | Workflow runtime | Dynamic result | Independent result | Friction verdict |
|---|---|---|---|---|---|---|---|
| Direct checkout CLI | success | 2.6 s | wf-mtbiwjf1-0eca29 / k6zkba |
10m 50s | verifier found an untested formatting defect; planner added repair + second verify | 3/3 pass | Low invocation friction; high model latency, valuable recovery |
| Claude Code | success | ~4m 08s | wf-mtbj96ey-6276a5 / vxxps2 |
3m 55s | implement + verify + terminal decision | 3/3 pass | Works, but foreground initiation is too slow and over-instrumented |
| Grok | success | ~1m 35s | wf-mtbjcdzw-b070a8 / wykuwi |
3m 42s | first verifier was content-empty; retry routed to Command Code and passed | 3/3 pass | Best agent UX; progressive status and concise handoff |
| Command Code | success | ~5m 39s | wf-mtbjkys1-435fe4 / 8ve272 |
4m 00s | implement + verify + terminal decision | 3/3 pass | Works, but the launch turn was silent and much too slow |
Times are wall-clock observations of local subscription CLIs, not benchmark claims about the underlying models.
Repair a duration parser/formatter to support positive decimals and surrounding whitespace, reject malformed/non-positive values, preserve exports, choose the largest exact display unit, and round-trip.
BULLSWARM_HOME=/tmp/bullswarm-usability-EsM9ev/home \
node /Users/cowcow02/Repo/bullswarm/bin/bullswarm.js workflow goal \
"Repair the duration utility ... and require an independent verification step before completion." \
--cwd=/tmp/bullswarm-usability-EsM9ev/direct --detach --json
The command returned in 2.6 seconds with run ID, short ID, PID, status, log paths, and summary/dashboard/event observation commands. Auto-routing selected Grok for orchestration.
| Order | Action | Type | Pool | Outcome |
|---|---|---|---|---|
| 1 | orchestrator attempt 1 |
decide | Grok | proposed initial implementation + verify |
| 2 | fix-duration-utility |
run | Grok | succeeded; public suite passed |
| 3 | verify-duration-fix |
verify | Grok | valid JSON verdict with ok:false |
| 4 | orchestrator attempt 2 |
decide | Grok | accepted the concern and added focused recovery |
| 5 | fix-format-duration |
run | Grok | repaired decimal largest-unit formatting |
| 6 | verify-format-duration |
verify | Grok | ok:true, no concerns |
| 7 | orchestrator attempt 3 |
decide | Grok | complete, accepted |
The first verifier found a real gap that the public test did not assert: formatDuration(2500) returned 2500ms rather than 2.5s, and formatDuration(75000) returned 75s rather than 1.25m. The workflow did not accept green tests as sufficient; it expanded from three planned actions to five durable actions and two expansion rounds. Final state used 7 dispatches, produced 79 events, and was completed / delivered.
One observability subtlety should be clarified in the UI/docs: the verify action’s process/action ledger status is succeeded because it produced a valid verdict, while the report step is ok:false because the verdict rejected the work. That distinction is correct but easy to misread.
Independent npm test: 3 passed, 0 failed. Test file SHA-256: f07c1bad954c9faf5a35c168f1dea667f214841ccabdded61e817943be25f321.
Claude was asked to use Bullswarm to repair case-insensitive header merging, block prototype-polluting keys, reject non-string values, preserve inputs, detach, and report how to observe the work. It was explicitly told not to edit directly or write workflow JSON.
Claude read the guide, ran a baseline, diagnosed the installed/check-out version skew, invoked the checkout’s workflow goal, checked initial events, and returned the run ID and checkout-qualified observation commands. It also created a temporary background watcher; no watcher remained after completion.
| Order | Action | Type | Pool | Outcome |
|---|---|---|---|---|
| 1 | orchestrator attempt 1 |
decide | Grok | proposed implement + verify |
| 2 | implement-merge-headers |
run | Grok | succeeded |
| 3 | verify-merge-headers |
verify | Grok | ok:true |
| 4 | orchestrator attempt 2 |
decide | Grok | complete, accepted |
Final state used 4 dispatches, one expansion round, and 49 events. The run was completed / delivered in 3m 55s.
Independent npm test: 3 passed, 0 failed. Test file SHA-256: d1f11816651030ed285a92e3c69e96d357e9a275b763b5810cebe08dcdf52647.
Claude’s reasoning was accurate and its handoff was the most detailed, but launching a detached job took about 4m 08s in the foreground. Baseline/doctor/event checks are useful, yet a detached launcher should normally hand back the durable ID much sooner and let observation happen separately.
Grok was asked to repair an async retry helper: initial attempt plus configured retries, onRetry only between attempts, pre-invocation validation, full tests, detached execution, and no direct edits/JSON graph.
Grok progressively reported three useful stages—reading the guide, checking readiness, then launching—and returned the durable IDs and checkout-qualified observation commands in about 1m 35s.
| Order | Action | Type | Pool | Outcome |
|---|---|---|---|---|
| 1 | orchestrator attempt 1 |
decide | Grok | proposed implement + verify |
| 2 | fix-retry |
run | Grok | succeeded |
| 3 | verify-retry attempt 1 |
verify | Grok | failed_retryable: announcement without substance |
| 4 | verify-retry attempt 2 |
verify | Command Code | succeeded with a substantive ok:true verdict |
| 5 | orchestrator attempt 2 |
decide | Grok | complete, accepted |
This is strong evidence for the content-first doctrine: Bullswarm rejected a zero-substance verifier response despite process success, retried on a different eligible pool, and only then accepted the workflow. Final state used 5 dispatches, one expansion round, and 56 events; runtime was 3m 42s.
Independent npm test: 3 passed, 0 failed. Test file SHA-256: 1695025b7f107261610810a8fdd29e8b54ca68966fa31be66047d6c496843fee.
Command Code was asked to implement deterministic topological ordering, cycle reporting, unknown-node validation, and input immutability through Bullswarm, with the same detach/no-direct-edit/no-JSON constraints.
It correctly read the guide, discovered the version skew, invoked checkout source, and returned a durable run ID. The human-facing cmd entry point and Bullswarm connector’s command-code binary alias both exist locally at version 1.36.0, so there was no connector alias failure.
| Order | Action | Type | Pool | Outcome |
|---|---|---|---|---|
| 1 | orchestrator attempt 1 |
decide | Grok | proposed implement + verify |
| 2 | fix-graph-module |
run | Grok | succeeded |
| 3 | verify-graph-tests |
verify | Grok | ok:true |
| 4 | orchestrator attempt 2 |
decide | Grok | complete, accepted |
Final state used 4 dispatches, one expansion round, and 49 events. Runtime was 4m 00s.
Independent npm test: 3 passed, 0 failed. Test file SHA-256: f8eacb470b336b5e5b57a6b673be63d44ddb57b3a5112a8735afab8828ea40b6.
The initiation turn was silent for about 5m 39s before returning. It also printed bare bullswarm workflow ... observation commands even after explaining that bare bullswarm is version 0.4.0, so its handoff was internally inconsistent.
workflow goal, not drafts or a hand-built JSON graph.--detach --json produced a durable ID and a parent process independent of the initiating CLI.bullswarm version on PATH is 0.4.0, checkout source is 0.7.2, and npm view bullswarm version is also 0.4.0. Installing @latest would not expose this feature today.bullswarm workflow ...; those commands fail here. Until release, the response should emit the actual launcher executable or clearly mark commands as requiring the same version.ok:false verdict can have action status succeeded but report status ok:false. Dashboards should label this as “verdict produced: rejected” rather than relying on a generic success badge.workflow goal, or provide a supported install/link command for the checkout build.skill/SKILL.md: read goal, launch detached, return ID; perform baseline/doctor only when launch fails or readiness is unknown.The preserved evidence for this run is under /tmp/bullswarm-usability-EsM9ev/home/workflows/<runId>/:
state.json: action ledger, attempts, routing, decisions, budgets, terminal stateworkflow.json: generated durable workflow documentevents.jsonl: ordered event replayout-*: worker/verifier/orchestrator artifactsreport.json: action-level acceptance summaryUse the checkout binary for this snapshot:
export BULLSWARM_HOME=/tmp/bullswarm-usability-EsM9ev/home
node /Users/cowcow02/Repo/bullswarm/bin/bullswarm.js workflow runs show <shortId>
node /Users/cowcow02/Repo/bullswarm/bin/bullswarm.js workflow tui --json <shortId>
node /Users/cowcow02/Repo/bullswarm/bin/bullswarm.js workflow events --json <shortId> --after 0