Orchestration engine for driving a fleet of headless coding agents (Cursor, OpenCode, Codex, Antigravity, Claude Code) from one driver via MCP + Skills
Project description
Run a fleet of AI coding agents in parallel, in isolated git worktrees, and know exactly what each one cost.
Proof
One task, four routing strategies, measured cost and latency from the ledger — not a guess.
| Strategy | Backend | Model | Status | Cost | Source | Duration | Tokens (in / out) |
|---|---|---|---|---|---|---|---|
| deepseek | opencode | opencode-go/deepseek-v4-flash | succeeded | $0.0029 | native | 81.8 s | 11,740 / 1,977 |
| claude | claude-code | claude-sonnet-4-6 | succeeded | $0.3374 | native | 121.4 s | 17 / 6,837 |
| cmdcode | command-code | zai-org/GLM-5.2 | succeeded | unavailable |
unavailable | 252.6 s | 0 / 0 |
| codex-glm | codex | z-ai/glm-5.1 (via EastRouter) | succeeded | unavailable |
unavailable | 283.0 s | 231,075 / 7,812 |
cheapest: deepseek ($0.0029) · fastest: deepseek (81.8 s)
Each produced solution's tests: deepseek, claude, and cmdcode passed 6/6 — deepseek was cheapest, fastest, and correct, for ~1/115th of claude's cost. Full methodology and tables: examples/benchmark-output.md and docs/nerds.md.
Install
You need Python 3.11+, uv, git, and at least one backend CLI
installed and logged in — Marshal drives agents, it does not ship one. marshal doctor tells you
which are ready. (The Claude Code plugin launches the MCP server through uv, so it is required on
that path too.)
Claude Code plugin — the fastest path. Brings the Skills and the MCP server in one step:
/plugin marketplace add chiruu12/marshal
/plugin install marshal@marshal
From GitHub, for the CLI and the Python library:
uv tool install "marshalfleet[mcp] @ git+https://github.com/chiruu12/marshal@v0.1.0"
# or
pipx install "marshalfleet[mcp] @ git+https://github.com/chiruu12/marshal@v0.1.0"
Drop @v0.1.0 to track main. The [mcp] extra is what makes marshal mcp work — without it the
server exits before a host can connect.
Not on PyPI yet.
uv tool install "MarshalFleet[mcp]"is the intended command once it is published; until then use the GitHub URL above, which installs the same package.
Backend CLI auth and MCP wiring: SETUP.md.
60 seconds
1. Configure a fleet. From your project repo, scaffold a starter fleet.config.yaml:
marshal init # scaffolds fleet.config.yaml in the current repo
The scaffold ships every client commented out, so uncomment at least one and save. Using the
codex example:
clients:
codex:
backend: codex
model: gpt-5.5
2. Check the fleet is ready. doctor verifies auth, not just that a CLI is on $PATH — a backend you cannot actually run fails here rather than 3 seconds into a job.
$ marshal doctor
✓ repo: /path/to/your-repo (branch main)
✓ config: fleet.config.yaml (1 client)
✓ backend:codex: available
✓ plan:codex: logged-in
3. Dispatch a job. It returns immediately with a run id — the agent works in its own git worktree on its own branch. Your checkout is never touched.
$ marshal spawn --client codex --goal "Add a docstring to hello()"
hello-docstring.codex.d56489fe codex/gpt-5.5 running (poll: marshal status)
4. Watch the fleet. Any number of agents, any mix of providers, each with its own cost line.
$ marshal status
hello-docstring.codex.d56489fe codex exited_clean unavailable .marshal/worktrees/hello-docstring.codex.d56489fe
5. Review, then merge. From a driver agent over MCP: collect_run("<run_id>") returns the diff read-only, and integrate("<run_id>", message="...") merges it. exited_clean means the process exited cleanly — it does not mean the code is correct, so the diff review is not optional.
MCP tool reference: docs/mcp-tools.md. Orientation for drivers: call marshal_quickstart() first.
Why Marshal
- One base class, many backends — backend choice is a per-call parameter, never global.
- Parallel by default — each agent runs in its own git worktree until you explicitly integrate.
- Per-provider usage tracking — every run's cost is tagged by provenance; unknown cost is
unavailable, never a fake $0. - Robust headless execution — hard timeouts, process-group kill, and no prompting modes that deadlock without stdin.
How it compares
| Worktree isolation | Real parallelism | Per-provider cost accounting | Human merge review | Multi-repo | |
|---|---|---|---|---|---|
| Marshal | yes — one worktree per run | yes — capped run_many |
yes — native / admin-api / unavailable | yes — collect_run then integrate |
yes — one MCP server, many workspaces |
| Hand-rolled git worktree scripts | yes — if you build it | possible — you manage threads/processes | no — unless you wire it yourself | possible — you own the merge step | no — one repo per script unless you extend it |
| Subagents inside a single coding harness | partial — often same checkout or sandbox | limited — shared process/context | partial — whatever the host exposes | varies — some hosts auto-apply | no — bound to one session/repo |
| Generic workflow orchestrators (CI, Airflow, Temporal) | no — not their job | yes — at the workflow layer | no — not agent-token aware | yes — human gates are the point | yes — but not coding-agent native |
What you can drive it with
Seven backend adapters. Model is set per client in fleet.config.yaml (or ad-hoc via --model / MCP model=).
| Backend | Model flag | Cost provenance |
|---|---|---|
cursor |
optional (defaults to CLI default) | unavailable — individual plans expose no per-run cost |
opencode |
opencode-go/* (required pattern) |
native — tokens + cost from the CLI |
codex |
provider/model (e.g. gpt-5.5) |
admin-api via EastRouter usage_api; else unavailable |
claude-code |
claude-* (e.g. claude-sonnet-4-6) |
native — total_cost_usd + tokens |
command-code |
provider/model (e.g. zai-org/GLM-5.2) |
unavailable — hosted account, no token/cost in stdout |
goose |
provider/model or bare model (e.g. cursor-agent/auto) |
native when the provider reports positive cost; else unavailable (best-effort stream-json) |
antigravity (experimental) |
gemini-*, claude-*, etc. |
unavailable — text-only output |
Routing playbook: docs/model-playbook.md. Verification matrix: docs/status.md.
Architecture
Marshal is the infrastructure layer between a driver agent and a fleet of headless coding CLIs. The driver plans; Marshal creates worktrees, runs backends with timeouts, records usage to an immutable ledger, and returns diffs for review. A future end-user product (Chauffeur) will sit on top — see docs/chauffeur-future.md.
Full design: docs/design.md.
Documentation
SETUP.md— clone-to-first-run setup.docs/usage.md— configure a fleet; drive it via MCP, CLI, or library.docs/mcp-tools.md— MCP tool reference.docs/config.md— everyfleet.config.yamlkey.docs/model-playbook.md— which client to route a task to.docs/status.md— what's built and verified.docs/design.md— architecture and backend cheat sheets.docs/nerds.md— numbers, methodology, and the stuff we argue about.docs/sources.md— primary sources.examples/— runnable copy-paste examples (library_quickstart, pipelinedthenreview,read_paths, adversarial teams, multi-workspace, per-clientenv:); seeexamples/README.md.
Contributing
CONTRIBUTING.md— dev setup, quality gate, adding a backend.SECURITY.md— security model and private disclosure.CHANGELOG.md·CODE_OF_CONDUCT.md
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file marshalfleet-0.2.0.tar.gz.
File metadata
- Download URL: marshalfleet-0.2.0.tar.gz
- Upload date:
- Size: 703.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d294de4c4a55c28937882a5f0807753f8c811243f4c0a9e8d93934c4beb81df8
|
|
| MD5 |
41d0f1e9dbd9c4cae614e087d5528e0f
|
|
| BLAKE2b-256 |
735e72f86632bbec27d31fb130b5735f7be46668ab72e2fa0e394d306a8335a7
|
Provenance
The following attestation bundles were made for marshalfleet-0.2.0.tar.gz:
Publisher:
release.yml on chiruu12/marshal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marshalfleet-0.2.0.tar.gz -
Subject digest:
d294de4c4a55c28937882a5f0807753f8c811243f4c0a9e8d93934c4beb81df8 - Sigstore transparency entry: 2292393875
- Sigstore integration time:
-
Permalink:
chiruu12/marshal@90edd39921345d5a4262f9c848c304a6007eb890 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/chiruu12
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@90edd39921345d5a4262f9c848c304a6007eb890 -
Trigger Event:
release
-
Statement type:
File details
Details for the file marshalfleet-0.2.0-py3-none-any.whl.
File metadata
- Download URL: marshalfleet-0.2.0-py3-none-any.whl
- Upload date:
- Size: 226.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d34ed5b6ce4a0e7206bd1a6386a63d252cfa4e4e49c97afaf3697021a5c08bda
|
|
| MD5 |
0322eb3797719cf11486aa892c4c3a19
|
|
| BLAKE2b-256 |
7b4b01ccdbb46608a33d5fee6a00d3665efe0a972097438ef86660404d5058fe
|
Provenance
The following attestation bundles were made for marshalfleet-0.2.0-py3-none-any.whl:
Publisher:
release.yml on chiruu12/marshal
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
marshalfleet-0.2.0-py3-none-any.whl -
Subject digest:
d34ed5b6ce4a0e7206bd1a6386a63d252cfa4e4e49c97afaf3697021a5c08bda - Sigstore transparency entry: 2292393939
- Sigstore integration time:
-
Permalink:
chiruu12/marshal@90edd39921345d5a4262f9c848c304a6007eb890 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/chiruu12
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@90edd39921345d5a4262f9c848c304a6007eb890 -
Trigger Event:
release
-
Statement type: