01

The harness is the variable

Asked which coding agent is best, the honest answer from this data is: whichever one you can still change. We ran Marshall against pi, opencode and aider on identical work — 105 trials, three models, three task shapes — and the widest gap in the whole benchmark wasn't between harnesses. It was between two configurations of Marshall.

Same model, same fixture, same verifier: 91 tool calls at the worst and 5.7 at the best, a 16× spread. The worst burned 455,372 input tokens and $0.0353 a run; the best used 72,296 and $0.0078. pi and opencode both landed inside that range on the same task, at 14.8 calls and 13.0. pi's cost per run was the same as Marshall's least efficient configuration, and 4.5× its best.

So this stopped being a league table partway through. It became a study of what makes a harness good — and because the harness we could rebuild was our own, most of the measurements are of Marshall taking itself apart. Every configuration below was built to test one idea about that; the belt Marshall ships is the one the testing produced, and section 08 traces each of its properties back to the experiment that justified it.

Five properties turned out to be measurable, and they are the spine of the piece: it finishes; it is cheap; it doesn't need a human steering it to be fast; it holds up across task shapes; and it gives the model a cheap way to do the obvious thing. Section 09 scores all four harnesses against them.

16×spread between Marshall's worst and best test belt, same model and fixture (91 calls → 5.7)
3/3trials finished on Qwen3.8 Flash, where pi and opencode were 0 of 4 between them
15/15trials passed by Marshall's fullest belt across all three task shapes
22–37%of pi's cost per run, on every task and model where both logged tokens
02

The task

A 28-file JavaScript project is halfway through a logging migration. A MIGRATION.md describes the rules. Every remaining call site has to move off the deprecated log() helper, the old module has to be deleted, and node --test has to pass afterwards — 122 tests that grade the result.

Every harness gets the same fixture, the same prompt, and the same check(). No harness is told how to do it: reading every file one at a time and scripting the whole thing in one shot are both allowed, and which one a harness picks turns out to be most of the story.

Three models ran it. GPT-5.6 Luna is the strong general model. GLM-5.3 Flash and Qwen3.8 Flash are two small, fast ones — and they are where this benchmark earns its keep, because a capable model can absorb a mediocre harness and a weak one cannot. Every trial had a 7-minute ceiling.

03

Results

Median wall-clock seconds, migration task (lower is better)
GPT-5.6 Luna
opencode3/3 passed
120.5 s
Marshall · full belt5/5 passed
40.6 s
Marshall · shell-first belt3/3 passed
32.4 s
pi4/4 passed
31.1 s
GLM-5.3 Flash
Marshall · full belt2/2 passed
186.5 s
Marshall · shell-first belt2/2 passed
126.1 s
opencode2/2 passed
118.9 s
pi2/2 passed
77.7 s
Qwen3.8 Flash
pi⏱ timed out, 0/2
420.1 s ceiling
opencode⏱ timed out, 0/2
420.1 s ceiling
Marshall · shell-first belt3/3 passed
146.5 s

Bars are scaled within each model group; the 7-minute ceiling is the longest bar wherever a harness never finished. On Luna all four plotted configurations pass, and Marshall's shell-first belt is a hair behind pi — 32.4s against 31.1s — at roughly a quarter of the cost. Marshall's second Qwen configuration also finished, at 112.7s median and 3/3.

Cost per run, migration task (lower is better)
GPT-5.6 Luna
pi4/4 passed
$0.0353
Marshall · full belt5/5 passed
$0.0104
Marshall · shell-first belt3/3 passed
$0.0078
GLM-5.3 Flash
pi2/2 passed
$0.0266
Marshall · shell-first belt2/2 passed
$0.0099
Marshall · full belt2/2 passed
$0.0087

opencode writes no token log this harness can read, so it isn't plotted. Qwen has no comparison at all: pi and opencode never finished, so they have no cost per completed run. Marshall's two Qwen configurations ran $0.0120 and $0.0155.

The full table, all four harnesses and all three models:

ModelMarshallpiopencodeaider
GPT-5.6 Luna5.7 calls · 32s · 3/314.8 calls · 31s · 4/413.0 calls · 121s · 3/3n/a · 102s · 0/2
GLM-5.3 Flash10.0 calls · 126s · 2/27.0 calls · 78s · 2/28.0 calls · 119s · 2/2not run
Qwen3.8 Flash23.0 calls · 147s · 3/3⏱ timed out · 0/2⏱ timed out · 0/2not run

Marshall's cell is its best-performing configuration on that model; both of its belts are plotted in the figures above. ⏱ = every trial hit the 7-minute ceiling. n/a under calls means the harness has no tool-calling concept, not zero: aider applies SEARCH/REPLACE blocks from its own reply rather than calling tools. 105 trials total; means for calls, medians for time.

Marshall is the only harness that finishes on Qwen3.8 Flash

pi and opencode timed out on every attempt between them — four trials, four ceilings, no result. Marshall completed 3/3, twice over: two different configurations of it, three trials each, all passing. This is the single largest gap in the benchmark, and it is the one that a league table of wall-clock seconds hides completely, because a run that never finishes has no median.

The harness matters most where the model is weakest

On Luna, all three of Marshall, pi and opencode finished: 3/3, 4/4, 3/3. On GLM-5.3 Flash, all three finished. On Qwen3.8 Flash, only one did. When the model is capable, harness quality shows up in the price and the call count; when it isn't, harness quality decides whether you get an answer at all. If you are running anything smaller than a frontier model — and most production agent work is — this is the axis to optimise.

On Luna, Marshall is the leanest and by a distance the cheapest

5.7 tool calls against pi's 14.8 and opencode's 13.0, at 3/3 correctness, and 3.7× faster than opencode by median run. On cost the gap is wider than on any other measure: between 22% and 37% of pi's dollars per run on every task and model in this piece where both harnesses logged tokens.

pi is still ahead on GLM-5.3 Flash

7 calls to Marshall's 10, and 77.7s against 126.1s by median run. One model out of three, and we did not close it. What the gap is not, though, is a correctness or cost gap: Marshall passed the same 2/2 on that model and cost 2.7× less per run. And the shell-first belt closed most of it on its own — the same model went from 186.5s to 126.1s when the belt changed, with no other variable touched.

04

Every configuration measured

The Marshall rows above are not one number, and that is the point of this section. Each configuration was built to test a single idea about harness design — batch the file tools, drop the read-before-edit gate, route bulk reads through the shell, remove the read tools entirely. The spread between them is larger than the spread between the harnesses, which is the strongest argument in this piece for the harness being worth engineering.

HarnessModelConfigurationPassedCallsMedian sIn tokOut tok$/runRun
aiderGPT-5.6 Lunaaider-luna0/2102.05,100512$0.00162026-09-04T22-04-33
marshallGPT-5.6 Lunaluna-hybrid-batch-prompt3/315.735.1127,6901,999$0.01042026-08-28T12-31-34
marshallGPT-5.6 Lunaluna-hybrid-batch-prompt-light3/314.725.2138,3501,900$0.01182026-08-28T12-38-07
marshallGPT-5.6 Lunaluna-hybrid-prompt3/320.332.3130,9541,935$0.00972026-08-28T12-31-34
marshallGPT-5.6 Lunaluna-hybrid-prompt-light1/122.045.180,1292,068$0.00762026-08-28T12-00-59
marshallGPT-5.6 Lunaluna-hybrid-shell-prompt1/120.038.8102,4072,103$0.00952026-08-28T12-06-02
marshallGPT-5.6 Lunaluna-incremental-prompt1/191.0107.5455,37213,035$0.03532026-08-28T11-27-17
marshallGPT-5.6 Lunaluna-nomask3/312.326.8139,9461,643$0.01062026-09-04T22-26-03
marshallGPT-5.6 Lunaluna-openrouter5/517.040.6142,6302,062$0.01042026-09-04T17-08-10
marshallGPT-5.6 Lunaluna-shell-edit3/35.732.472,2961,823$0.00782026-09-04T16-55-57
opencodeGPT-5.6 Lunaopencode-luna3/313.0120.52026-09-04T15-37-50
piGPT-5.6 Lunapi-luna4/414.831.1101,2172,091$0.03532026-08-28T12-35-23
marshallQwen3.8 Flashqwen38flash-or-shell-edit3/323.0146.5273,3658,075$0.01202026-08-30T12-16-57
marshallQwen3.8 Flashqwen38flash-or-solo3/325.3112.7434,6128,788$0.01552026-08-30T12-16-57
opencodeQwen3.8 Flashopencode-qwen38flash0/2 ⏱2420.12026-09-04T15-51-41
piQwen3.8 Flashpi-qwen38flash0/2 ⏱2420.12026-09-04T15-51-41
marshallGLM-5.3 Flashglm-hybrid-batch-prompt1/2 ⏱137.0315.8441,21012,389$0.01912026-08-30T11-07-59
marshallGLM-5.3 Flashglm-openrouter2/214.0186.5208,0227,280$0.00872026-08-30T11-46-29
marshallGLM-5.3 Flashglm-shell-edit2/210.0126.1155,7796,774$0.00992026-08-30T11-55-24
marshallGLM-5.3 Flashglm-shell-only1/27.0131.591,7284,575$0.00692026-08-30T11-55-24
opencodeGLM-5.3 Flashopencode-glm2/28.0118.92026-09-04T15-51-41
piGLM-5.3 Flashpi-glm2/27.077.752,3761,457$0.02662026-08-30T11-07-59

luna-hybrid-prompt-light, luna-hybrid-shell-prompt and luna-incremental-prompt ran a single trial each, so their figures are measurements and not averages. The headline figures in section 03 are Marshall's best-performing configuration on each model — the shell-first belt on all three — and every other Marshall row here is an ablation measured against it.

Read the ranges before you read any mean in this piece. Several of them are wider than the differences between harnesses: pi and Marshall finish the Luna task 1.3 seconds apart by median, and the same configuration repeated on the same inputs can vary by far more than that.

  • 120.5sopencode's spread on Luna — three passing trials at 58.1s, 137.9s and 120.5s, a 2.4× range within one configuration that never changed.
  • 21–47spi's spread on Luna — four trials, and the fastest is less than half the slowest.
  • $0.0131–$0.0586pi's spread on cost — a 4.5× range between its cheapest and dearest run of the same task.
  • 87–297sMarshall on Qwen — three passing trials of one configuration, 3.4× apart.
  • 53–320sMarshall on GLM — two trials, six times apart.

That is the single most important thing to hold in mind when reading any number here. The differences between harnesses that survive it are the ones worth believing: the Qwen timeout, the cost gap, and the 16× spread between Marshall's own configurations, which is far outside anything noise produced.

Every migration trial, individually — 54 runs
ConfigurationTrialResultCallsSecondsIn tokOut tokIn tok/call$
aider-luna1fail86.35,100429$0.0015
aider-luna2fail117.75,100595$0.0017
luna-hybrid-batch-prompt1pass1428.1113,7121,6368,122$0.0086
luna-hybrid-batch-prompt2pass1439.1154,1202,22411,009$0.0119
luna-hybrid-batch-prompt3pass1935.1115,2382,1366,065$0.0108
luna-hybrid-batch-prompt-light1pass1944.0210,1972,10211,063$0.0132
luna-hybrid-batch-prompt-light2pass1325.2117,1561,9419,012$0.0130
luna-hybrid-batch-prompt-light3pass1222.987,6961,6577,308$0.0094
luna-hybrid-prompt1pass2342.4168,0052,2087,305$0.0130
luna-hybrid-prompt2pass1732.393,7671,8605,516$0.0080
luna-hybrid-prompt3pass2131.2131,0911,7386,242$0.0083
luna-hybrid-prompt-light1pass2245.180,1292,0683,642$0.0076
luna-hybrid-shell-prompt1pass2038.8102,4072,1035,120$0.0095
luna-incremental-prompt1pass91107.5455,37213,0355,004$0.0353
luna-nomask1pass1230.7159,4511,60913,288$0.0108
luna-nomask2pass1223.393,5011,6567,792$0.0080
luna-nomask3pass1326.8166,8851,66512,837$0.0129
luna-openrouter1pass1736.2119,3161,7947,019$0.0089
luna-openrouter2pass2360.4189,6272,5788,245$0.0126
luna-openrouter3pass1640.691,6591,8185,729$0.0076
luna-openrouter4pass1431.9159,6171,73611,401$0.0110
luna-openrouter5pass1552.7152,9312,38210,195$0.0120
luna-shell-edit1pass527.561,2541,85412,251$0.0071
luna-shell-edit2pass637.085,2932,07814,216$0.0090
luna-shell-edit3pass632.470,3421,53811,724$0.0073
opencode-luna1pass1658.1
opencode-luna2pass14137.9
opencode-luna3pass9120.5
pi-luna1pass1625.367,1381,7204,196$0.0234
pi-luna2pass1547.0122,1673,0168,144$0.0462
pi-luna3pass1636.8179,0142,30411,188$0.0586
pi-luna4pass1221.536,5501,3243,046$0.0131
qwen38flash-or-shell-edit1pass27274.4402,20212,04814,896$0.0174
qwen38flash-or-shell-edit2pass17101.3158,0856,2239,299$0.0084
qwen38flash-or-shell-edit3pass25146.5259,8085,95410,392$0.0101
qwen38flash-or-solo1pass28297.3707,79313,88125,278$0.0247
qwen38flash-or-solo2pass25112.7383,9158,01715,357$0.0139
qwen38flash-or-solo3pass2387.0212,1284,4659,223$0.0079
opencode-qwen38flash1⏱ timeout0420.1
opencode-qwen38flash2⏱ timeout0420.1
pi-qwen38flash1⏱ timeout0420.1
pi-qwen38flash2⏱ timeout0420.1
glm-hybrid-batch-prompt1pass25211.7458,8029,70218,352$0.0254
glm-hybrid-batch-prompt2⏱ timeout49420.0423,61815,0768,645$0.0128
glm-openrouter1pass17320.2290,8419,79517,108$0.0087
glm-openrouter2pass1152.8125,2034,76411,382$0.0086
glm-shell-edit1pass9102.6197,6729,14821,964$0.0159
glm-shell-edit2pass11149.5113,8864,40010,353$0.0038
glm-shell-only1pass875.4142,9366,86617,867$0.0121
glm-shell-only2fail6187.640,5202,2836,753$0.0018
opencode-glm1pass9121.0
opencode-glm2pass7116.8
pi-glm1pass8101.236,7912,0094,599$0.0215
pi-glm2pass654.167,96090511,327$0.0317

Two of Marshall's rows are not passes: glm-hybrid-batch-prompt hit the ceiling on its second trial at 49 calls, and glm-shell-only failed outright on one of two. Both are early ablations — the first predates the two changes in section 08, the second removes the read tools entirely — and both are in this table because a benchmark that only shows the configurations that worked is not a benchmark.

05

What the calls were spent on

Call counts say how many round trips. This says what they were spent on, and it is the part that explains everything else. The distance between 37 calls and 5.7 is not tidiness. It is one harness reading files one at a time — read_file 46 of its 74 calls — and another running a shell loop, run_shell 17 of 17.

HarnessConfigurationTrialsCallsComposition
marshallluna-hybrid-batch-prompt347read_file 21 (45%), search 11 (23%), run_shell 9 (19%), list_dir 6 (13%)
marshallluna-hybrid-batch-prompt-light344read_file 19 (43%), search 9 (20%), run_shell 9 (20%), list_dir 7 (16%)
marshallluna-hybrid-prompt361read_file 30 (49%), search 13 (21%), run_shell 10 (16%), list_dir 8 (13%)
marshallluna-hybrid-prompt-light122read_file 10 (45%), search 7 (32%), list_dir 3 (14%), run_shell 2 (9%)
marshallluna-hybrid-shell-prompt120read_file 7 (35%), search 6 (30%), list_dir 4 (20%), run_shell 3 (15%)
marshallluna-incremental-prompt191edit_file 45 (49%), read_file 36 (40%), search 7 (8%), run_shell 2 (2%), list_dir 1 (1%)
marshallluna-nomask337run_shell 16 (43%), search 7 (19%), read_file 5 (14%), note_write 3 (8%), list_dir 3 (8%), log_append 3 (8%)
marshallluna-openrouter585run_shell 32 (38%), read_file 30 (35%), search 8 (9%), list_dir 6 (7%), note_write 4 (5%), log_append 4 (5%), shell_output 1 (1%)
marshallluna-shell-edit317run_shell 17 (100%)
pipi-luna459bash 36 (61%), read 23 (39%)
marshallqwen38flash-or-shell-edit369run_shell 57 (83%), write_file 7 (10%), edit_file 5 (7%)
marshallqwen38flash-or-solo376run_shell 64 (84%), write_file 4 (5%), log_append 3 (4%), edit_file 3 (4%), list_dir 1 (1%), note_write 1 (1%)
pipi-qwen38flash29bash 8 (89%), write 1 (11%)
marshallglm-hybrid-batch-prompt274read_file 46 (62%), run_shell 13 (18%), search 6 (8%), list_dir 4 (5%), write_file 2 (3%), edit_file 2 (3%), log_append 1 (1%)
marshallglm-openrouter228run_shell 16 (57%), read_file 3 (11%), list_dir 3 (11%), write_file 3 (11%), log_append 2 (7%), search 1 (4%)
marshallglm-shell-edit220run_shell 19 (95%), write_file 1 (5%)
marshallglm-shell-only214run_shell 14 (100%)
pipi-glm214bash 13 (93%), write 1 (7%)

No composition recoverable for aider-luna, opencode-luna, opencode-qwen38flash, opencode-glm — opencode writes no transcript this harness can read, so its calls are counted but not categorised. Rows marked ⏱ timed out on every trial; their composition is still real, it is what the harness did before the ceiling, but it is a partial run.

A round trip is what costs

The reason call count matters is mechanical, and it is worth stating because it explains the token numbers rather than just correlating with them. Each tool call ends a turn, and the next turn re-sends the whole conversation so far. A harness that needs ten round trips to do one job pays for that job ten times, and the bill grows with every one of them.

The two extremes in this data make the arithmetic plain. luna-incremental-prompt edited one file per call and took 91 round trips: 455,372 input tokens. luna-shell-edit did the same migration in 5.7: 72,296 input tokens. A 6.3× difference in what the same model read to complete the same task, produced entirely by how the harness let it work. Note that per-call cost went the other way — 5,004 input tokens per call against about 12,700 — because each of the fewer calls carried more. Fewer, larger turns is the whole trick.

pi found this on its own

pi runs almost everything through bash. Its own read tool is a minority of its calls; the bulk is shell, including a for f in $(grep -rl …); do cat "$f"; done that ingests every relevant file in one call. On GLM it was 93% shell. That is the same strategy Marshall's leanest belts converge on, arrived at from the other direction.

Marshall's full belt spreads the same work across four tools

read_file, search, list_dir and run_shell — and the read_file share is where its extra calls live. 49% of calls on luna-hybrid-prompt, 62% on glm-hybrid-batch-prompt. Those are file-at-a-time reads of a 28-file project.

The shell-first belt collapses, but only on some models

100% of calls on Luna, 95% on GLM. On those two the model does what pi does and the call count follows. On Qwen3.8 Flash it does not: the belt still pushes it mostly to shell, but it issues 23 calls doing so rather than 5.7. Same belt, same instruction, different model — which is the clearest evidence in this piece that a harness sets the ceiling and the model decides how much of it you get.

06

A realistic codebase

Every fixture above is small enough that a harness can hold all of it at once. That flatters any approach which front-loads context and never has to search, so it is worth one task where finding the work is the work.

repo-bugs is 45 real TypeScript files — Marshall's own packages/tools — with three faults planted in them: an off-by-one in a shared line-window primitive, an inverted glob guard in search, and a type error in a function no test executes. 248 tests, of which exactly 2 fail. Nothing in the prompt names the faulty files, the failing tests are not all in the files that cause them, and the type error is invisible to the test run, so the verifier requires both a green suite and a clean tsc.

Median wall-clock seconds, repo-bugs (lower is better)
opencode2/2 passed
33.1 s
pi2/2 passed
28.5 s
Marshall · shell-first belt2/2 passed
25.7 s
Marshall · full belt2/2 passed
19.3 s

aider isn't plotted: it finished in 9.7s because it made no changes at all. Marshall's full belt is the fastest of everything that passed, and the cheapest at $0.0070 a run against pi's $0.0274.

HarnessConfigurationPassedCallsMedian sIn tokOut tok$/run
marshallluna-openrouter2/211.019.381,633683$0.0070
pipi-luna2/212.528.591,1651,001$0.0274
marshallluna-shell-edit2/211.525.7146,1041,044$0.0101
opencodeopencode-luna2/210.033.1
aideraider-luna0/2n/a9.75,400275$0.0014

aider does nothing at all

0/2, 5,400 input tokens, 9.7 seconds — and the fixture came back byte-identical, the same 2 of 248 tests failing. It is not running out of budget; it is declining to start. Its repo-map ships with the instruction "treat them as read-only — if you need to edit any of these files, ask me to add them to the chat first", because the map exists for a human to read and then name the files. Given --yes-always -m there is nobody to answer. On the two-file fixtures it worked because there was nothing to choose.

That is the whole of its 20× economy on small tasks: a person doing the file selection. It is also the sharpest illustration in this piece of what a harness is for. aider's design is good and it is well suited to a human at a keyboard. Measured as an autonomous agent on a 45-file repo, it scores zero, and no amount of speed makes that a pass.

And the shell-first belt loses to the full one

luna-shell-edit spends 146,104 input tokens and 25.7s against luna-openrouter's 81,633 and 19.3s, for the same 2/2. On a task where the work is finding three faults in 45 files, having a search tool is worth more than not having one. The belt that won the migration by 3× loses here, the first of the two task shapes in this piece where it does; the second is section 07.

07

The short tasks, as a control

Everything above is one long, mechanical task. That is the shape where harness overhead is large enough to measure — and also the shape a harness can be over-fitted to. These are the short ones: a one-line bug fix, adding a function, a rename across a few files, and an iterative fix. Same harnesses, same models, same verifiers. This is the control group, and it is where the piece's most useful negative result lives.

TaskHarnessConfigurationPassedCallsMedian sIn tokOut tok
bug-fixaideraider-luna3/36.6802124
bug-fixmarshallluna-openrouter2/26.511.016,655346
bug-fixmarshallluna-shell-edit2/23.58.99,333281
bug-fixopencodeopencode-luna2/25.520.9
bug-fixpipi-luna2/26.012.48,596309
feature-addaideraider-luna2/27.6985233
feature-addmarshallluna-openrouter2/23.510.011,473320
feature-addmarshallluna-shell-edit1/22.555.34,8288,395
feature-addopencodeopencode-luna2/23.524.7
feature-addpipi-luna2/24.010.07,284273
refactoraideraider-luna2/210.8851185
refactormarshallluna-openrouter2/24.59.912,429364
refactormarshallluna-shell-edit2/24.010.26,334401
refactoropencodeopencode-luna2/27.027.2
refactorpipi-luna2/27.010.810,234400
iterateaideraider-luna1/210.41,100416
iteratemarshallluna-openrouter2/29.521.334,925996
iteratemarshallluna-shell-edit1/27.068.719,1788,933
iterateopencodeopencode-luna2/27.027.0
iteratepipi-luna2/28.524.718,347954

Across all four: aider-luna 8/9, luna-openrouter 8/8, luna-shell-edit 6/8, opencode-luna 8/8, pi-luna 8/8.

Marshall's full belt is the fastest of the three full agents here

Worth stating, because the migration task's noise makes it easy to miss: on the four short tasks Marshall's full belt was the quickest of Marshall, pi and opencode on three — bug-fix 11.0s against 12.4s and 20.9s, refactor 9.9s against 10.8s and 27.2s, iterate 21.3s against 24.7s and 27.0s — and tied pi exactly on the fourth at 10.0s. It went 8/8, the same as pi and opencode, and it did it in less time than either. aider is faster still on three of them, at 800–1,100 input tokens, for reasons section 06 makes clear.

This is where the shell-first belt stops looking good

aider-luna and luna-shell-edit are the only configurations to fail anything here, while Marshall's full belt, pi and opencode each went clean. The failures are not subtle: on tasks the full belt finishes in 10–21 seconds and under 1,000 output tokens, the shell-first belt twice ran to about 16,000 output tokens and truncated its own tool call mid-JSON, having made two calls total.

Taking read_file away removes the cheap way to look at a small file, and the model sometimes substitutes one enormous edit instead. It isn't reaching for the shell because the shell is better suited; it is reaching for it because it is the only thing left. That is a design fault, not a model fault, and it is the reason the belt that wins the migration by 3× is an ablation rather than a product: it optimises one task shape by removing a capability three others need.

08

What actually moved the needle

Starting from 91 tool calls at the worst (luna-incremental-prompt) and 5.7 at the best (luna-shell-edit), three changes account for almost all of it. Each one is now in the belt Marshall ships.

  • 01Batching the file toolsedits[] on edit, patterns[] on search, paths[] on list. Real, but small. It targeted search and list_dir, which together were 10 of that config's 74 calls.
  • 02Dropping the read-before-edit gate — larger. Marshall required a read_file before any edit; the oldString already has to match exactly once, so the gate bought no safety and cost a round trip per file. On GLM this took a run from 37 calls to 14.
  • 03Pointing bulk reads at the shell — largest. One grep -rl PATTERN src | xargs cat replaces thirty read_file calls. This only became honest advice after the gate came out, since shell output is now enough to edit from. Together the two took a GLM run from 37 calls at 1/2 to 14 at 2/2.

Read those three in order and the shape of the lesson is visible. None of them made the model smarter. Two of them removed a rule the harness had imposed for its own convenience, and one of them told the model that a capability it already had — a shell — was the right tool for a job it was doing the slow way. The GLM numbers are the proof that this is about more than speed: the same model on the same fixture went from passing half its trials to passing all of them. A harness that gets in the way doesn't just cost money, it costs correctness.

The fourth result is the one that didn't make it into the product. Removing the read tools outright — luna-shell-edit, glm-shell-only — produced the leanest runs in the entire benchmark and then failed on two of the short tasks, spent 1.8× the tokens on repo-bugs, and went 1/2 on GLM. There is a version of minimalism that works and a version that amputates, and the difference between them is only visible if you test on more than one task shape. Marshall keeps read_file, search and list_dir, and tells the model when the shell is the better route. That combination is what the testing produced, and it is what ships.

09

What good means

Five properties, all measurable from the tables above. If you are choosing a harness rather than building one, this is the list I would work down.

TestMarshallpiopencodeaider
Finishes on the weakest model pass — 3/3 on Qwen, the only harness that did fail — 0/2, ceiling on both fail — 0/2, ceiling on both fail — 0/2 on both long tasks
Cheap per completed run pass — 22–37% of pi's cost, every task and model fail — 2.7–4.5× Marshall not logged fail — cheapest, by doing nothing
No human needed to be fast pass pass pass fail — its repo-map asks a person to name the files
Holds across task shapes pass — 15/15 on the full belt across all three pass — 8/8 short, 2/2 bugs, 6/8 migration pass — 8/8 short, 2/2 bugs, 5/7 migration fail — 8/9 small, 0/4 anywhere it had to search
Gives the model the cheap path pass — measured, and the two ablations that broke it are documented pass — 61–93% of calls through bash not observable — no transcript fail — no route at all without a human

Two of the five separate the field, and they are the two that don't show up in a screenshot of a successful run. Finishes on the weakest model, because a harness that only works on the frontier model is a demo and not infrastructure, and because Qwen is where two of the three harnesses that ran it scored zero. Holds across task shapes, because the migration task alone would have told us to ship a belt that breaks on a one-line fix.

pi fails one of the five and opencode fails one, and it is the same one for both. That is not a criticism of either; they are good harnesses, and on Luna with a strong model all three finish the same job successfully, with Marshall and pi inside 1.3 seconds of each other. With a capable model the harness mostly decides what the run costs. It decides whether you get a result at all only when the model is small — and that is the case most production agent work actually falls into.

What we did not close

pi is ahead on GLM-5.3 Flash and stayed ahead: 7 calls to Marshall's 10, 77.7s to 126.1s by median. We spent a day on the gap and closed most of it — 186.5s down to 126.1s came from the belt, not the model — and the rest is open. One model out of three.

The other limit is the one in section 04. Trial-to-trial noise on this fixture reaches 3.4×, which means several of the smaller differences in these tables are not findings. The ones we rely on are the Qwen ceiling, the cost gap, and the 16× spread between Marshall's own configurations — all far outside it.

Full trial logs, fixtures, and the harness code for this benchmark are on GitHub alongside Marshall.

github.com/agentionai/marshall →