onlycodes

June 13, 2026 · View on GitHub

A benchmark testing whether Claude Code performs better when restricted to writing and executing code directly, rather than using its native file-system tools (Read, Grep, Glob, Edit, etc.).

Headline Results (artifact seed-v1, 12 tasks × 1 run)

Both arms pass every task; code_only wins on efficiency across the board. Full per-task breakdown in Artifact-Graded Benchmark → Results.

Metriccode_onlybaselinecode_only vs baseline
Pass rate12/1212/12
Total turns4463−30.2%
Total cost (USD)0.56600.9152−38.2%
Total wall time (s)250287−12.9%
Mean turns / task3.675.25−30.2%
Mean cost / task$0.0472$0.0763−38.2%
Mean wall / task20.8s23.9s−12.9%

baseline = stock Claude Code harness with all native tools (Read, Grep, Glob, Edit, Bash, etc.). code_only = same harness restricted to a single execute_code MCP tool.

Hypothesis

Forcing the model to solve tasks by writing a single script — rather than making multiple fine-grained tool calls — should reduce turns, lower token costs, and complete tasks faster. The "only code" approach is implemented via an MCP server (execute_code) that provides a sandboxed Python/Bash execution environment.

Approaches

ArmDescription
baseline / tool_richAll native tools available (Read, Grep, Glob, Edit, Bash, etc.)
onlycode / code_onlyRestricted to a single execute_code MCP tool; must write one script per task

SWE-bench uses baseline / onlycode; artifact-graded uses tool_rich / code_only.

Benchmark Modes

Three benchmark modes, each targeting a different evaluation surface:

ModeEntry pointTask sourceGrading
SWE-benchpython -m swebench runproblems/swe/ YAML filesTest suite pass/fail
Artifact-gradedpython -m swebench artifact runproblems/artifact/ YAML filesHidden Python grader
Fixture (legacy)./scripts/run_prevalidation.shdata/fixtures/myapp/Oracle files in data/oracle/

SWE-bench Harness

The main evaluation harness. Problem instances are fetched from HuggingFace SWE-bench datasets and stored as YAML files under problems/swe/.

Problem Sets

SetPathSizeDescription
swebench-verifiedproblems/swe/swebench-verified/500SWE-bench Verified spine (#308); the buildable subset (sets/verified-buildable.txt) feeds the #299 spine
swebench-verified-miniproblems/swe/swebench-verified-mini/50DEPRECATED — subset of swebench-verified; excluded from swebench run discovery (would double-run the same ids). Kept on disk for KDD-workshop reproducibility.
swebench-datasci-miniproblems/swe/swebench-datasci-mini/50Data-science library instances
swebench-datasci-5problems/swe/swebench-datasci-5/5Small data-science smoke set
adhocproblems/swe/adhoc/variesOne-offs added without --set

CLI

# Add problem instances (fetched from HuggingFace)
python -m swebench add <instance_id>
python -m swebench add <instance_id> --set swe/swebench-verified-mini
python -m swebench add --from-file ids.txt --set swe/swebench-verified-mini --concurrency 8

# Run evaluation arms
python -m swebench run                           # all three arms, all problems
python -m swebench run --arms onlycode           # onlycode arm only
python -m swebench run --arms baseline           # baseline arm only
python -m swebench run --arms bash_only          # bash_only arm only
python -m swebench run --arms both               # baseline+onlycode (excludes bash_only)
python -m swebench run --filter django__django-16379
python -m swebench run --runs 3                  # multiple runs per arm
python -m swebench run --runtime image           # default: official prebuilt Docker images
python -m swebench run --runtime overlay         # DEPRECATED legacy host OverlayFS path
python -m swebench run --no-cache                # (overlay only) skip OverlayFS cache

# Analyze results
python -m swebench analyze summary
python -m swebench analyze summary --out results.csv

# Pathology pipeline (stages 1 → 2 → 3)
python -m swebench analyze pathology             # all three stages
python -m swebench analyze pathology --dry-run
python -m swebench analyze pathology --stage mechanical
python -m swebench analyze pathology --stage subagents
python -m swebench analyze pathology --stage synthesize
python -m swebench analyze pathology --force
python -m swebench analyze pathology --run-id my-run
python -m swebench analyze pathology --concurrency 4

Results go to runs/swebench/ keyed by instance_id. Analysis sidecars go to runs/swebench/_analysis/<run_id>/.

MCP Config

After building the exec-server bundle (npm run build in exec_server/), regenerate mcp-config.json with the correct paths for your environment:

python -m swebench mcp-config generate
# or write to a custom location:
python -m swebench mcp-config generate --out /path/to/mcp-config.json

This resolves node, the bundle path, and the repo root automatically. Re-run after any container rebuild or workspace move.

Dependencies & supply-chain hygiene

This repo pins both dependency trees so a single poisoned upstream release is not pulled silently (issue #350). Install deps the locked way:

# Node (exec-server) — ALWAYS `npm ci`, never bare `npm install`.
# npm ci installs strictly from package-lock.json (114 integrity hashes),
# fails on any drift, and never mutates the lockfile.
npm ci

# Python — install from the hash-locked lockfile.
pip install --require-hashes -r requirements.txt
  • requirements.txt is a fully pinned, hash-locked lockfile generated from requirements.in. Don't edit it by hand. To change a dependency, edit requirements.in and regenerate:
    uv pip compile requirements.in -o requirements.txt --generate-hashes
    
    (pip-compile --generate-hashes from pip-tools works too.) Bumping a major of numpy / scikit-learn / datasets / pandas requires re-running the data_science graders + tests first — the pins track the validated set.
  • Run scripts/scan_supplychain_iocs.sh to sweep the repo + environments for the campaign's IOCs (see docs/SECURITY_SUPPLYCHAIN.md).

OverlayFS Cache

DEPRECATED (ADR-0004 / #314). The OverlayFS cache belongs to the legacy --runtime overlay backend. The default --runtime image backend runs on the official prebuilt Docker images (100% Verified coverage) and does not use this cache. Overlay is kept only as a general-purpose fallback and is slated for removal.

For large-scale or repeated runs, the harness supports an OverlayFS-backed instance cache that skips clone + venv setup on subsequent runs.

python -m swebench cache setup                   # warm all instances
python -m swebench cache setup --concurrency 8
python -m swebench cache setup --force           # rebuild existing entries
python -m swebench cache setup --filter django__django-16379
python -m swebench cache clean --filter django__django-16379

Cache is on by default. The harness prefers kernel overlayfs (requires CAP_SYS_ADMIN) and falls back to fuse-overlayfs. The devcontainer already grants --cap-add=SYS_ADMIN.

Per-arm venv isolation (--venv-isolation, default on): each arm gets a fresh fuse-overlayfs layer over the cached venv so agent pip-installs don't poison the cache or cross-contaminate arms. Disable with --no-venv-isolation to restore legacy shared-venv behaviour (useful for parity testing or environments without FUSE).

Cache layout:

/workspaces/.swebench-cache/
├── repos/                         # bare clones, shared across instances
└── instances/<instance_id>/
    ├── repo/                      # checkout at base_commit, scrubbed
    ├── venv/                      # overlay mountpoint (empty dir; per-arm overlay mounts here)
    ├── venv_lower/                # pristine lowerdir — never written by agent runs
    └── lockfile.txt               # pip freeze at cache time

Pathology Vocabulary

patterns.json (repo root) is the canonical failure-pattern registry written by analyze pathology --stage synthesize. New pattern IDs are appended; existing entries are never overwritten. Edit by hand only to remove stale entries or fix descriptions.


Artifact-Graded Benchmark

Purpose-built diagnostic tasks with hidden Python graders. Each task lives under problems/artifact/<category>/<slug>/ and is graded by a grader/hidden.py:grade(scratch_dir) function that runs in a subprocess.

Task Categories

CategoryPath
algorithmicproblems/artifact/algorithmic/
data_processingproblems/artifact/data_processing/
enumerationproblems/artifact/enumeration/
iterative_numericalproblems/artifact/iterative_numerical/
stateful_reasoningproblems/artifact/stateful_reasoning/
verification_heavyproblems/artifact/verification_heavy/

CLI

# Run both arms against all artifact tasks
python -m swebench artifact run

# Run specific arm or instance
python -m swebench artifact run --arms code_only
python -m swebench artifact run --arms tool_rich
python -m swebench artifact run --filter data_processing__p95_latency_easy

# Multiple runs per arm
python -m swebench artifact run --runs 3

# Resume skips already-complete runs by default
python -m swebench artifact run --no-resume

Results go to runs/artifact/. Task schema is documented in docs/SCHEMA_ARTIFACT.md. Architecture decisions in docs/adr-0001-artifact-mode.md.

Results (seed-v1, 12 tasks × 1 run)

Both arms pass every task, so the comparison is on efficiency. code_only wins on cost, turns, and wall time. Per-task breakdown from runs/artifact/summary.csv:

Columns: co = code_only, bl = baseline (stock Claude Code harness; the arm is named tool_rich in the CLI).

TaskVerdictTurns (co / bl)Cost USD (co / bl)Wall s (co / bl)
algorithmic__makespan_schedulingPASS / PASS3 / 50.0413 / 0.126517 / 40
algorithmic__min_cost_assignmentPASS / PASS2 / 40.0294 / 0.059614 / 21
data_processing__multi_file_cohortPASS / PASS2 / 50.0346 / 0.078010 / 23
data_processing__p95_latency_easyPASS / PASS4 / 80.0492 / 0.089920 / 32
data_processing__regression_detectionPASS / PASS4 / 60.0509 / 0.074520 / 22
enumeration__graphs_chromatic_3PASS / PASS5 / 50.0844 / 0.079560 / 33
enumeration__latin_squares_3PASS / PASS3 / 30.0354 / 0.044614 / 12
iterative_numerical__bisection_calibrationPASS / PASS2 / 40.0348 / 0.070814 / 21
iterative_numerical__exp_decay_fitPASS / PASS5 / 50.0542 / 0.065224 / 25
iterative_numerical__hparam_searchPASS / PASS5 / 50.0510 / 0.064220 / 17
stateful_reasoning__event_ledgerPASS / PASS2 / 40.0345 / 0.081210 / 19
stateful_reasoning__unreachable_functionsPASS / PASS7 / 90.0662 / 0.081227 / 22

Aggregates appear in Headline Results at the top of this README.

code_only is cheaper and more turn-efficient on 11/12 tasks (ties on enumeration; graphs_chromatic_3 is the one task where the baseline edges out on both cost and wall time). Wall-clock gains are the smallest margin because execution is dominated by subprocess and grader time that both arms share.


Legacy Fixture Benchmark

The original 5-task benchmark against data/fixtures/myapp/. Still valid as a fast smoke test.

Tasks:

  1. Find all Python files that import os or os.path — list file paths and line numbers
  2. Find all os.environ.get() references that are missing from .env.example
  3. Run the pytest suite and report total/passed/failed with exact failure names
  4. Find every file containing the variable name server_url
  5. Add a --dry-run flag to myapp/cli.py that prints intent and exits without calling start()

Results:

TaskBaseline CostOnly Code CostSavingsBaseline TimeOnly Code TimeSpeedup
1 — OS imports$0.0833$0.065322%18.8s13.2s1.4×
2 — Missing env vars$0.1390$0.067651%28.4s7.9s3.6×
3 — Run pytest$0.0985$0.075024%23.4s11.1s2.1×
4 — Find server_url$0.0756$0.052531%15.9s10.3s1.5×
5 — Add --dry-run$0.1031$0.079623%8.2s5.0s1.6×
Total$0.4995$0.340032%~94.7s~47.5s2.0×

The "only code" approach was 2× faster and 32% cheaper overall.

Running:

./scripts/run_prevalidation.sh          # baseline vs constrained
./scripts/run_mcp_integration_test.sh   # only-code (MCP) arm

Results are written as JSONL to runs/default/ and runs/mcp/. Grade against data/oracle/.


Repository Structure

swebench/                  # Python harness package (python -m swebench)
problems/
  swe/                     # SWE-bench problem YAML files (organized by set)
  artifact/                # Artifact-graded task trees (organized by category)
runs/                      # All run outputs (gitignored)
  swebench/                #   SWE-bench run outputs (JSONL, keyed by instance_id)
  artifact/                #   Artifact run outputs
  mcp/                     #   Legacy only-code (MCP) run logs (JSONL)
  requests/                #   Requests-fixture run logs (JSONL)
  default/                 #   Legacy baseline run logs (JSONL)
  logs/                    #   Session logs (e.g. session.jsonl)
docs/
  SCHEMA_ARTIFACT.md       # Normative artifact task schema
  adr-0001-artifact-mode.md
patterns.json              # Canonical failure-pattern vocabulary (pathology pipeline)
data/                      # Legacy fixture/oracle reference files (prevalidation benchmarks)
  fixtures/                #   Legacy fixture project (myapp/ + tests/)
  fixtures_requests/       #   Alternate fixture set (HTTP/requests-based tasks; gitignored)
  oracle/                  #   Ground-truth answers for legacy fixture grading
  oracle_requests/         #   Ground-truth answers for requests-fixture grading
exec_server/               # MCP exec-server stack (JS + Python kernel helpers)
  exec-server.js           #   MCP stdio entry point
  bridge-server.js         #   Unix-socket bridge for sub-MCP passthrough
  config-loader.js         #   Validates passthrough-config.json
  interceptor.js           #   Content + dispatch deny-list
  sub-mcp-manager.js       #   Spawns/manages sub-MCP child processes
  codebox.py               #   Python API for execute_code helpers
  mcp_bridge.py            #   Python client for bridge-server (staged into scratch)
  python_kernel.py         #   Persistent Python REPL kernel (staged into scratch)
  passthrough-config.json  #   Sub-MCP + intercept rules
  build.mjs                #   esbuild script → exec_server/dist/exec-server.bundle.mjs
  dist/exec-server.bundle.mjs  # Bundled server (gitignored; fast startup ~130ms)
mcp-config.json            # MCP server config for --mcp-config CLI flag (points at dist/ bundle)
scripts/                   # Shell runners + summarize_results.py