Benchmark models
Cross-model benchmark. Runs one prompt or skill through Claude, GPT (Codex CLI), and Gemini side by side and compares latency, tokens, cost, tool calls, and optionally output quality via an Anthropic-API judge. Answers "which model is actually best for this skill?" with data. Use when you say "benchmark models", "compare models", "which model is best for X", "cross-model comparison", or "model shootout". Do NOT use to measure web page performance.From its SKILL.md
npx -y skills add rjmurillo/ai-agents --skill benchmark-modelsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
7.8 KB, as published. Nobody here has run it
benchmark-models
Run the same prompt across providers and compare them on data, not vibes. The
deterministic work lives in scripts/model_benchmark.py (stdlib-only, ported
from gstack's bun benchmark; no SDKs, no gstack runtime). This skill is the
interactive wrapper: pick a prompt, preview auth with a dry-run, confirm
providers, run, interpret, optionally save.
Providers wrap existing CLIs and their own auth (no API keys needed except the optional judge):
claudeviaclaude -p --output-format jsongptviacodex exec ... -s read-only --jsongeminiviagemini -p ... --output-format stream-json
Triggers
Invoke this skill when the user says any of:
benchmark modelscompare modelsmodel shootoutwhich model is bestcross-model comparison
Do NOT invoke for web page performance (that is a different concern).
Preconditions
- At least one provider CLI installed and authenticated. The Step 1 dry-run reports exactly which are ready; if none are, the skill stops.
- The optional quality judge needs
ANTHROPIC_API_KEY(adds ~$0.05/run).
Process
Resolve the driver first. In a repository checkout, use BENCH="$(git rev-parse --show-toplevel)/.claude/skills/benchmark-models/scripts/model_benchmark.py". From an installed skill copy, use the local skill path: BENCH="$PWD/scripts/model_benchmark.py" when your shell is in the benchmark-models skill directory.
Step 1: Pick a prompt and preview auth (dry-run)
Decide the prompt with AskUserQuestion:
-
A) Benchmark a skill: pass that skill's
SKILL.mdpath as the prompt. To list candidates, search the installed skills dir, not just.(skills usually live under~/.claude/skills/or~/.copilot/skills/, not the project root).Allowed-root constraint:
$BENCHreads a prompt file only when it resolves under the repo checkout, the current directory, or a path listed inMODEL_BENCHMARK_SKILL_ROOTS(seeresolve_promptand_allowed_prompt_rootsin the benchmark script). ASKILL.mdunder~/.claude/skills/or~/.copilot/skills/is outside the repo and cwd, so the run aborts with exit code 2 ("prompt file must be under an allowed root") and benchmarks nothing. Before running, export the skills dir, for exampleexport MODEL_BENCHMARK_SKILL_ROOTS=~/.claude/skills(or~/.copilot/skills), or copy the file into and run from an allowed root. A prompt already inside the repo or cwd needs no env var. -
B) Inline prompt: pass
--prompt "<text>". -
C) A prompt file on disk: pass its path (verify it exists first).
Then preview availability without spending anything:
python3 "$BENCH" --prompt "dry-run" --models claude,gpt,gemini --dry-run
The "Adapter availability" block shows OK or NOT READY (with a remediation hint)
per provider. If ALL are NOT READY, STOP: nothing can run. Suggest claude,
codex login, or gemini login / export GOOGLE_API_KEY.
Step 2: Confirm providers and judge
From the dry-run, AskUserQuestion which providers to include (default: all authed). Unauthed providers are skipped cleanly and never abort the batch.
If ANTHROPIC_API_KEY is set, AskUserQuestion whether to enable --judge
(quality scoring, ~$0.05). Never auto-enable it; it costs real money. If the key
is absent, omit --judge.
Step 3: Run
python3 "$BENCH" <prompt-spec> --models <picked> [--judge] --output table
<prompt-spec> is --prompt "<text>" (B) or a file path (A/C). Stream the
output; each provider runs the full prompt, so expect 30s-5min.
For an installed-skill path (A) under ~/.claude/skills/ or ~/.copilot/skills/
(outside the repo and cwd), export MODEL_BENCHMARK_SKILL_ROOTS first (see Step 1
Option A) or the run aborts with exit code 2 before any provider starts.
Step 4: Interpret and optionally save
Summarize: fastest (latency), cheapest (cost), highest quality (if judged), and a best-overall call that names the tradeoff. Call out any provider that errored, with its remediation path. Offer to save a JSON baseline so future runs can be diffed for regressions:
python3 "$BENCH" <prompt-spec> --models <picked> [--judge] --output json > benchmark-$(date +%Y%m%d)-<slug>.json
Scripts
model_benchmark.py
Runs the benchmark. Pure stdlib; safe to run directly.
python3 scripts/model_benchmark.py <prompt-file | --prompt "text"> \
[--models claude,gpt,gemini] [--judge] [--dry-run] \
[--output table|json|markdown] [--workdir PATH] [--timeout-ms N] [--skip-unavailable]
Exit codes (ADR-035): 0 success, 1 logic/runtime error, 2 config or usage
error, 3 external dependency failure, 4 authentication or authorization
failure.
Notes:
--dry-runresolves auth and prints availability without sending any prompt.- The judge posts to the Anthropic Messages API via stdlib
http.client(no SDK) and fails soft: a judge error warns and leaves quality blank, it never aborts the run. - Do not place secrets in prompts. The
gptandgeminiCLIs receive the prompt through command arguments, which some systems expose through process listings or crash reports. - Safety asymmetry: the
gpt/codex adapter runs-s read-only; thegeminiadapter passes--yolo(auto-approve), which is NOT sandboxed. Benchmark in a disposable--workdirif the prompt could trigger file writes. - The driver only runs providers concurrently when every selected provider is read-only GPT/Codex. Claude and Gemini run sequentially because they can mutate the workdir.
- Pricing lives in the
PRICINGtable at the top of the script. An unpriced model costs0.0with a stderr warning; add a row rather than guess.
Anti-Patterns
| Avoid | Why | Instead |
|---|---|---|
| Running the benchmark before the dry-run | Spends API calls on unauthed providers that will just error | Always Step 1 dry-run first; only run authed providers |
Auto-enabling --judge | It adds real per-run cost the user did not approve | Opt-in only, after the Step 2 question |
| Benchmarking in a live repo with a write-prone prompt | The gemini adapter is not sandboxed (--yolo) | Use a disposable --workdir |
| Guessing a price for an unlisted model | Produces a wrong cost number that looks authoritative | Add a row to the PRICING table; unlisted stays 0.0 with a warning |
Listing skills to benchmark via find . only | Installed skills live under ~/.claude / ~/.copilot, not the project root | Search the installed skills dir |
Verification
The skill run is complete when:
- Step 1 dry-run ran and its availability block was shown to the user.
- If zero providers were authed, the run STOPPED (no benchmark attempted).
- The benchmark ran only the user-confirmed providers.
- If the prompt was a skill
SKILL.mdoutside the repo/cwd,MODEL_BENCHMARK_SKILL_ROOTSwas set (or the file staged under an allowed root) so the run did not abort with exit code 2. -
--judgewas included only after explicit user opt-in. - Results name the fastest, cheapest, and (if judged) highest-quality model, with errors and their remediation surfaced.
-
python3 -m pytest .claude/skills/benchmark-models/testspasses (the driver carries unit tests at 100% coverage).