cyberine
UsageRun recipes

Swarm mode — cyberine run --mode swarm (plan -> parallel-chunk implement -> merge)

For tasks that decompose cleanly into disjoint chunks — large multi-file refactors, sweep updates across many files, any scope where one worker would burn tool rounds but N workers can split the work in parallel — use --mode swarm. The orchestrator decomposes the task, fans out one worker per chunk in isolated worktrees, then merges all the diffs into a single landing.

When to use swarm vs compete (--mode omitted = compete, the previous default):

compete (default)swarm
Topologyone task -> N agents in parallel -> DiffJudge picks ONE winning diffplan -> N parallel chunks -> SwarmMergeJudge merges ALL diffs
Best forsingle design choice with multiple implementations to compare (refactor an auth module, add one tool, fix one bug)mass multi-file scope that decomposes into disjoint chunks (sweep a refactor across many files, update all dependencies, split a large feature across subsystems)
WorkersCYBERINE_BUILD_FLEET (all eligible writers race)CYBERINE_SWARM_FLEET (one worker per chunk; disjoint ownsFiles per chunk)
Judge chain['diff', 'behavior'] (full apply + typecheck + verifyCmd gate)['diff'] (SwarmMergeJudge sequential apply + typecheck + integration-fix retry)
Escalationnone — step errors and the run endsM5: a failed swarm run auto-redispatches in compete mode with the failure lessons appended
Outputthe winning diff (one)the merged diff (union of every chunk)

The flow (plan -> cluster(lanes) -> per-lane workers -> merge). The workflow is src/engine/swarmTaskWorkflow.ts:

  1. plan — at module load the schema-forced SwarmPlanner makes ONE LLM call (DeepSeek-direct preferred, OpenRouter fallback) and decomposes CYBERINE_TASK into a SwarmPlan of disjoint chunks. Each chunk carries ownsFiles (the glob of files it is allowed to edit), prompt (chunk-specific instructions), and dependsOn (DAG edges — see step 2 for the runtime guarantee). The plan also carries a sharedContract that is spliced into every chunk prompt so the chunks stay consistent on types, function signatures, and naming. No live-tree mutation in this step.
  2. cluster (lanes) — clusterChunks (T263) builds a lane graph whose edges are the UNION (or selection — CYBERINE_SWARM_GROUP_BY) of file-overlap edges and dependsOn edges. Connected components of that graph become SwarmLanes; the chunks inside one lane share a worktree and run serially in topological order so a dependent chunk sees its upstream chunk's commits IN TREE. packLanes (T264) bin-packs the lanes under a governor cap (CYBERINE_SWARM_LANES; auto = fleet size). See "Lane grouping" for the invariant and the CYBERINE_SWARM_GROUP_BY / CYBERINE_SWARM_LANES / CYBERINE_SWARM_MAX_LANE_SIZE knobs.
  3. swarm (per-lane workers) — isolate: true + swarmChunks: <plan> + swarmUseLaneRunner: true (the T269 wiring) routes through runSwarmLaneRunner (T265), which provisions ONE worktree per lane and dispatches the lane's chunks serially via chunkDispatch (round-robin pick from the fleet). After each chunk the runner commits (swarm-lane(<laneId>): chunk <id> [title] (i/N)) so the next chunk in the lane sees the prior chunks' work IN TREE; on chunk hard-fail the lane aborts per failureMode: 'stop' and the committed prefix is kept. Lanes run in parallel under the cap. Per-chunk retry-once + per-lane failure handling (T266) surfaces gaps loudly.
  4. merge — LaneMergeJudge (T267) sequentially applies every lane's cumulative diff to a clean integration worktree off HEAD, gates on npm run typecheck (the default; override with CYBERINE_VERIFY_CMD), and on failure runs an LLM-driven integration-fix pass (CYBERINE_SWARM_MERGE_RETRIES=1 default; 0 fail-fast). When the merge passes, the merged diff is emitted as the step's winnerOutput — same land-gate contract as compete (apply it with cyberine apply <runId> or cyberine land <runId>).
  5. review (downstream step) — a cheap adversarial reviewer (opencode plan + loop-deepseek-direct) reads the merged diff and emits a VERDICT: <approve|risk> digest to surface cross-chunk issues typecheck alone cannot catch (wiring drift, dead code, contract drift, semantic garbage).

The command. --mode swarm is the only knob the CLI exposes; the rest is env vars:

# Swarm mode — plan -> parallel-chunk implement -> merge
cyberine run --mode swarm "refactor the auth module across all files"
cyberine run --mode swarm --bg "update all dependency versions"   # detached (shows in cyberine agents)

# Env equivalent (priority: --mode flag > CYBERINE_MODE env)
CYBERINE_MODE=swarm cyberine run --bg "split the audit subsystem"

# Compete mode (default; --mode omitted is the same thing)
cyberine run "fix the off-by-one in pagination"
cyberine run --mode compete "refactor the auth module"   # explicit: full fleet race + BehaviorJudge gate

# Override the swarm worker fleet (defaults to the built-in swarm worker list)
CYBERINE_SWARM_FLEET="opencode-deepseek,claude,codex" \
  cyberine run --mode swarm "..."

Planner failure is non-fatal. When the planner cannot run (no DEEPSEEK_API_KEY / OPENROUTER_API_KEY, network failure, schema parse error, empty CYBERINE_TASK), the workflow falls back to a single-chunk single-worker plan and restricts the fleet to ONE worker — N workers on one chunk would conflict at apply time (every diff targets the same files; only the first applies). A stderr note is printed so the operator notices. The run still completes end-to-end.

Run the swarm workflow directly (no cyberine run parent) for dogfooding:

CYBERINE_TASK="Add a sandbox-pinned grep_files tool as src/tools/grep.ts" \
CYBERINE_SWARM_FLEET="opencode-deepseek,claude,codex" \
  npm run wf -- src/engine/swarmTaskWorkflow.ts

Env knobs (full defaults in the canonical table below): CYBERINE_SWARM_FLEET (worker list, falls back to CYBERINE_BUILD_FLEET then the default swarm list), CYBERINE_SWARM_MAX_CHUNKS (planner cap, [2, 16], default min(8, max(2, fleet length || 4))), CYBERINE_SWARM_MERGE_RETRIES (SwarmMergeJudge integration-fix retry budget, default 1; 0 disables).