Token-Saving Skills Review: Caveman, Ponytail, rtk and Headroom on Opus 5

Four Claude Code token savers against the model's own effort dial, on ten SWE-bench tasks hard enough to fail. 276 isolated runs, Opus 5 at extra-high effort.

Verdict#

−43%caveman's cost per run — cheaper on all 10 tasks, 24/30 solved vs baseline's 25
24 vs 20solved by caveman vs the effort dial at the same price
+12% · +21%rtk and headroom: dearer than running no tool
The saver that makes the model say less works. The ones that make it read less had nothing to cut.
Fig. 1 — Cost per run against runs solved
100%90%80%70%60%50%40%30%$0$1$2$3above the line: better than turning the dialright of baseline: costs more than no toolthe effort dial (free)effort-low$0.57 · 18/30effort-high$1.63 · 20/30baseline (xhigh)$2.52 · 25/30caveman$1.44 · 24/30ponytail$1.67 · 22/30rtk$2.83 · 24/30headroom$3.05 · 28/30did notreplicate est. cost per run (API prices) → runs solved (of 30) →

each dot = 30 runs (10 tasks × 3). whiskers = 95% intervals on the pass rate, clustered by task — they overlap: pass-rate gaps between tools are not significant; cost gaps are (Fig. 2). hover any mark.

Fig. 2 — Cost per run vs baseline
baseline-80%-60%-40%-20%+20%+40%effort-low-77%cheaper on 10/10 taskscaveman-43%cheaper on 10/10 taskseffort-high-35%cheaper on 8/10 tasksponytail-34%cheaper on 9/10 tasksrtk+12%cheaper on 3/10 tasksheadroom+21%cheaper on 2/10 tasks

task-paired; whiskers = 95% bootstrap intervals over tasks. baseline = $2.52/run at API prices.

Fig. 3 — Why: what each arm changed
reasoninganswer texttool calls & code
output written per run (tokens)context re-read per runturns per runbaseline32.4k2.1M47caveman17.2k1.1M34ponytail21.2k1.2M35effort-high20.2k1.3M37rtk36.7k2.4M51headroom35.3k2.5M53effort-low6.9k0.4M19

caveman halves reasoning (26.3k → 13.2k) and turns (47 → 34) — a deeper cut than the dial's high, keeping 4 more solves. rtk and headroom leave output alone and raise context and turns: Opus 5 works 99% in Bash and already trims its own output, so there was little left to compress (headroom's own ledger: 2.1% removed).

Fig. 4 — Runs solved, per task
baselinecavemanponytailrtkheadroomeffort-higheffort-lowxarray-69921/31/31/32/31/31/30/3 ↓sphinx-77481/31/30/3 ↓2/33/31/31/3xarray-72292/33/32/32/33/32/31/3 ↓sphinx-106733/32/3 ↓3/31/3 ↓3/32/3 ↓2/3 ↓sphinx-85483/33/33/33/33/33/33/3pylint-63863/33/33/33/33/33/33/3sphinx-94613/33/33/33/33/32/3 ↓3/3pylint-49703/32/3 ↓2/3 ↓3/33/32/3 ↓0/3 ↓sphinx-92293/33/32/3 ↓3/33/32/3 ↓3/3pylint-45513/33/33/32/3 ↓3/32/3 ↓2/3 ↓baselinesometimesbaselinealways

↓ = fewer solves than baseline on that task. darker = more solves of 3.

Fig. 5 — headroom's 28/30, re-run
original 3 trials7 new trials (the test)sphinx-7748baseline1/3 → 5/7headroom3/3 → 3/7xarray-7229baseline2/3 → 6/7headroom3/3 → 4/7new trials pooled: headroom 7/14 · baseline 11/14 · Fisher p = 0.24

filled = solved. headroom went 6/6 where the arms disagreed, so both were re-run 7 more times, rule fixed in advance (PLAN.md §5b). The streak did not hold: luck. Every baseline miss traced to an ordinary slip — a dropped -> retann; an ambiguous attrs convention.

Method#

v1 tied at 10/14 everywhere because its tasks were ones every agent solves. v2 picks tasks by measured difficulty, then keeps only those that can move.

Fig. 6 — How hard the tasks are
012345678910v1 tasksevery condition solved allv2 tasksthe ten frozen taskssolved by N of 10 public frontier agents (SWE-bench Verified leaderboard) →
Fig. 7 — Calibration: 25 tasks run twice by the baseline, 10 frozen
always solved · 17split · 3never solved · 5solid = one of the ten frozen tasks: the 3 split tasks, plus the 7 always-solved tasks that took the most turns
armcutsinjected per run as
cavemananswer proseplugin (--plugin-dir)
ponytailgenerated codeplugin; SessionStart hook, ~1.4k tokens of rules
rtkshell outputPreToolUse hook: pytest → rtk pytest
headroomthe whole requestlocalhost proxy via ANTHROPIC_BASE_URL
effort-high / lowreasoning--effort high / low — the free yardstick

all arms: claude-opus-5 at --effort xhigh, six pinned tools, no MCP, offline shell, fresh workspace, 3 trials per task. Graded gate: official FAIL_TO_PASS / PASS_TO_PASS, environments verified against the gold patch.

Leaks closed before the first real run#

leaksymptomfix
account connectorsclaude.ai MCP connectors loaded into the nested agent--strict-mcp-config + init-event check
future commitsgit log --all contained the real fixfetch only the base commit's ancestry
the released fixagent ran pip download of the fixed releaseoffline shell + lookup audit
harness in reachworkspaces beside the held-out testsopaque paths outside the tree
shared temp dirgold-identical patch scored 0/10 under parallel runsprivate TMPDIR per run and gate
v1 archive — August 2026, Opus 4.8, 56 runs (caveman vs headroom on easy tasks)

v1 · The matchup#

Caveman makes Claude answer in fragments; headroom compresses what Claude reads. One figure each.

Fig. 1 — Caveman shortens the output path
CAVEMAN ruleset injected at session start Context read as-is 308.0k tokens* CLAUDE Answer′ fragments · code intact 3.4k (−42%) price: +1.6k prompt tax · reasoning −42% — quality cost: not measurable in v1 (§ method)

* a shorter transcript also shrinks the replayed context (−33%) — a second-order effect, not compression.

Where it sits: an ordinary plugin — a SessionStart hook injects the ruleset into context, and the model itself changes register.

  • answer text −47% (1.1k → 590 tok/run): explanations and summaries become fragments
  • reasoning −42% (3.8k → 2.2k): the thinking between tool calls shortens with the register
  • tool calls −37% (953 → 605): fewer, tighter calls — the code written is untouched
  • knock-on: cache-read −33% (462k → 308k): a shorter transcript replays less history each turn
Fig. 2 — Headroom compresses the input path
Context files · logs · history 461.9k tokens HEADROOM compresses in flight Context′ same info 254.3k (−45%) CLAUDE Answer unchanged 6.7k ≈ behavior identical — same fixes, same turns · price: +54% wall time

Where it sits: a localhost proxy via ANTHROPIC_BASE_URL. Nothing inside Claude Code changes — so behavior doesn't either.

  • what it compresses: the old tool results re-sent every turn — file contents, pytest/log dumps, JSON — each block typed and routed (JSON structurally crushed · code trimmed AST-aware · prose/logs via a small model)
  • cache-read −45% (462k → 254k tok/run): the history is compressed once, and the saving repeats every turn after
  • what it never touches: everything Claude generates — reasoning, answers, tool calls all ≈ unchanged; same fixes, same turn count

v1 · Method#

modelconditionstaskstrialstotal runswallerrors
claude-opus-4-8472562h16m0
tasksourcewhat the agent must do
C1SWE-bench Verifiedpylint — fix a crash when the container CPU quota is fractional
C2SWE-bench Verifiedpytest — fix a regression in dynamically-added xfail markers
C3SWE-bench Verifiedsphinx — fix literalinclude prepend/dedent whitespace handling
C4writing taskcontributor onboarding doc for the pylint codebase
O1SpreadsheetBenchmatch items across columns, return positions
O2SpreadsheetBenchassign unique code numbers by formula
O3SpreadsheetBenchcumulative balance across 2.7 MB workbooks

v1 · Where the tokens go#

Every token the model touched — true scale
cache-read (context replayed)cache-writeoutput — everything the model generated
baseline cache-read 461.9k cache-write 24.3k output 5.8k 492k caveman cache-read 308.0k cache-write 19.5k fresh input 1.6k — the skill tax output 3.4k 333k −32% headroom cache-read 254.3k cache-write 21.8k output 6.7k 283k −43% both cache-read 236.0k cache-write 19.2k fresh input 1.6k — the skill tax output 4.9k 261k −47%

replayed context vs output ≈ 80:1. berry tick = all generated output; caveman's −42% cut is invisible at this scale — the point.

v1 · What a solved task costs#

Divide by solved tasks and the podium reorders.

baseline baseline: $0.740 per solved task $0.74 · 10/14 caveman caveman: $0.514 per solved task — tied winner $0.51 · 10/14 · −30% headroom headroom: $0.604 per solved task $0.60 · 10/14 both both: $0.516 per solved task — the winner $0.52 · 10/14 · −30% $0 $0.74 = baseline

caveman and the stack tie at −30%. an earlier version of this chart had caveman third — a stale-bytecode harness bug had failed its correct sphinx fixes (§ why tasks failed).

conditionsolvedest $/runest $/solvedwall s/run
baseline10/140.5280.74096
caveman10/140.3670.514 −30%60
headroom10/140.4310.604 −18%148
both10/140.3690.516 −30%98

v1 · Per task#

Cost vs baseline, per task (pass rate). C = coding, O = spreadsheets.

taskbaselinecavemanheadroomboth
C1 · pylint bugfixref (2/2)−40% (2/2)−57% (2/2)−57% (2/2)
C2 · pytest bugfixref (2/2)+5% (2/2)−41% (2/2)+20% (2/2)
C3 · sphinx bugfixref (2/2)−68% (2/2)−10% (2/2)−42% (2/2)
C4 · onboarding docref (2/2)−15% (2/2)−13% (2/2)−21% (2/2)
O1 · spreadsheetref (0/2)−24% (0/2)−29% (0/2)−48% (0/2)
O2 · spreadsheetref (2/2)−12% (2/2)−35% (2/2)−29% (2/2)
O3 · spreadsheet 2.7MBref (0/2)−13% (0/2)+21% (0/2)−47% (0/2)

no condition separates on quality — and no task here could have (§ method). O1/O3 are four-way ties (§ why tasks failed); C3's −68% is caveman's biggest legitimate saving. C4, pure writing: −15%.

v1 · Why tasks failed#

taskwho failedwhyclassification
C3 · sphinx caveman 0/2
→ overturned
The gate executed stale bytecode: Apple's shared pyc cache invalidates by (whole-second mtime, file size); caveman's fix was a same-size line reorder that landed in the same second as the pre-fix compile. Its patch was byte-identical to baseline's passing fix. Re-gated on fresh bytecode: 2/2. harness artifact — caught by forensics, gate fixed, verdict reversed
O1 · spreadsheet all four
(0/2 each)
2 of 3 workbooks perfect. Ground truth wants a blank when a lookup has no match (IFERROR(…,"")); every condition wrote Excel-style #N/A instead. benchmark semantics — four-way tie, no distortion
O3 · 2.7 MB all four
(0/2 each)
2 of 3 correct. Ground truth blanks the running balance on rows with no activity (IF(A21=0,"",…)); every condition kept computing the cumulative sum. benchmark semantics — four-way tie, no distortion

After the appeal: zero failures separate the conditions — 10/14 everywhere. The scariest finding reversed on forensics: caveman's speed didn't break the sphinx task, it outran the bytecode cache's one-second mtime resolution and broke our gate. Its −42% reasoning cut shows no measured quality cost in this battery — and this battery could not have shown one: every task sat at the ceiling or the floor (§ method). That is the question v2 exists to answer.

Caveats#

  • 30 runs per arm sees ~20-point pass-rate drops, not 5. Cost differences are solid; pass-rate differences between tools are leads.
  • 7 of 10 tasks are ones the baseline always solves: v2 mostly tests whether a tool breaks something.
  • Dollar figures are the CLI's estimate at API prices; the runs billed a subscription.
  • rtk 0.49.0 and headroom 0.37.0 at defaults, on a Bash-first agent. Log- or JSON-heavy work is a different regime.
  • Native environments, not the official Docker images: not SWE-bench scores.

Reproduce#

python3 fetch_tasks.py            # pin benchmark instances
python3 gym.py smoke              # auth + activation checks
python3 gym.py run --phase full   # 4 conditions × 7 tasks × 2 trials
python3 analyze.py full           # summary + results.json

# v2
python3 fetch_tasks.py swebench --gold      # pin instances (+ answer keys, for verification only)
python3 bin/verify_swebench.py <instance>  # red at base, green with the gold patch, in this env
rm -rf .cache/gold                          # no answer key on disk while agents run
python3 gym.py run --phase calib --jobs 4   # baseline only
python3 analyze_v2.py calib --freeze        # calibration table + frozen task list
python3 gym.py run --phase v2 --jobs 4      # tool arms on the frozen tasks
python3 analyze_v2.py report

isolation per run: fresh workspace · --setting-sources "" · pinned tools · scrubbed env · session-scoped plugin/proxy injection · no session persistence · v2 adds: no MCP · history cut at the base commit · offline shell · workspace outside the harness · private temp dir · lookup audit

References#

  1. 1caveman — JuliusBrussee/caveman, vendored at ec83e5b
  2. 2headroom — headroomlabs-ai/headroom, PyPI headroom-ai 0.34.0 (proxy mode, defaults)
  3. 3SWE-bench Verified — princeton-nlp, instances pylint-6903 · pytest-7490 · sphinx-10323, official FAIL_TO_PASS/PASS_TO_PASS gates
  4. 4SpreadsheetBench — RUCKBReasoning, instances 59055 · 13894 · 55392, cell-level comparator port
  5. 5runner, analyzer, raw event logs, and per-run gates: the skill-gym repo
  6. 6ponytail — DietrichGebert/ponytail, vendored at v4.10.0 (1d95ff7); rtk — rtk-ai/rtk v0.49.0, release binary pinned by SHA-256; headroom-ai 0.37.0 for v2
  7. 7per-task solve rates — swe-bench/experiments, 10 Verified submissions (Nov 2025 – Sep 2026)
  8. 8prior art — JetBrains AI blog, July 2026: caveman, rtk and ponytail on SkillsBench (rtk +7.6% cost; ponytail −10.3%); no quality difference detected, and not powered to prove equivalence
  9. 9v2 design, amendments and selection rule: PLAN.md in the repo