Zuletzt aktualisiert:

Benchmark: Claude Code CLI + Agent-SDK (Max-Sub) gegen die Gemini-Produktion (30.08.2026)

Auftrag

Dennis: „laut claude code twitter account startet das claude code CLI jetzt schneller, womit ich gerne noch mal prüfen lassen möchte, ob wir claude code nicht für die AI Aufgaben nutzen können? Prüfe auch die SDK variante." Präzisierung: alle aktuellen Anthropic-Modelle (Haiku 4.5, Sonnet 5, Opus 5, Fable 5) gegenüberstellen — Latenz, TTFT, Kosten/Usage (Tokens in/out/cache), Qualität; „Qualität könnte Zeit schlagen". SDK auf der Max-Sub (API-Token-Abrechnung ist ausgeschlossen); Policy-Prüfung ausdrücklich nicht gewünscht.

Der Tweet (@ClaudeDevs, 29.08.): „The CLI now starts up faster. It no longer waits for the sandbox and MCP servers before you can start typing, and running claude skips setup it doesn't need. The Linux x64 download is 4.5x smaller (~75 MB), native builds use 40–70 MB less memory per session."

Vorgeschichte: BENCHMARK-OPENROUTER-2026-06-06.md + benchmark-claude-sub-vs-gemini.md (07.06.) hatten die CLI mit 4–10 s pro Mini-Job gemessen — davon ~4 s CLI-Init + ~2 s TTFT durch den großen Claude-Code-System-Prompt. Ergebnis damals: Gemini bleibt, eine persistente Session wäre „technisch tragfähig, aber Over-Engineering".

Kurzfassung

724 Messungen, 0 Transportfehler, 5 JSON-Parse-Fehler (alle Claude), Gemini-Kosten < 0,15 $; Sub-Verbrauch: 5-h-Fenster auf 84 % (davon ~90 % durch EINE Variante).

  1. Der Tweet ändert für uns nichts. claude -p braucht weiterhin ~4 s Init pro Prozess (Wall 5–8 s Text, 9–14 s Foto). Der Speedup gilt dem interaktiven Start.
  2. Das SDK ist der Hebel, aber nur als Warm-Pool (frische, vorab aufgewärmte Session je Job): dann TTFT 0,7–1,4 s und Wall 2,9–4,2 s für Freitext — Gemini-Klasse (2,3 s), nicht besser. Foto 5,0–6,2 s vs. Gemini 4,8 s. Portion 2,0–3,0 s vs. 0,6 s.
  3. Qualität Freitext: Sonnet 5 / Opus 5 / Fable 5 sind auf Gemini-3.7-Niveau (Ø-Fehler 7,0 / 8,6 / 8,6 % vs. 6,8 %; Median sogar besser: 4,0–4,2 % vs. 5,1 %). Haiku 4.5 fällt durch (17,5 %, schätzt systematisch −13 % zu niedrig).
  4. Qualität Foto (echte Teller, 55 % unserer Jobs): Gemini gewinnt klar — 8,8 % gegen Fable 13,9 / Sonnet 14,6 / Haiku 20,2 / Opus 24,7 %. Alle Claude-Modelle überschätzen Teller um +11…+25 %. „Qualität schlägt Zeit" greift hier nicht: Claude ist langsamer UND ungenauer.
  5. Eine persistente Session für alles ist Usage-Gift: der Kontext wuchs auf 30–70k Tokens, jeder Folge-Call las ihn neu → nominal 325 $ für 272 Calls (Fable-Foto am Ende 5,6 $/Call) und damit der Großteil des 5-h-Fensters. Der Warm-Pool kostet dagegen nominal 0,007–0,09 $/Call (Sub-Verbrauch vernachlässigbar: ~1–2 $/Monat bei unserem Volumen), die CLI 0,03–0,8 $/Call.

Empfehlung: Gemini bleibt für estimate / portion / photo. Kein Umbau. Einzig sinnvolle SDK-Nutzung: den claude -p-Fallback in ai_jobs.claude() durch SDK-One-Shot ersetzen (3× weniger Sub-Verbrauch, Bild als Block statt Read-Tool, gleiche Latenz) — optional, kleiner Gewinn. Ein Warm-Pool-Daemon lohnt erst, wenn ein Job Claude-Qualität braucht und Gemini dort versagt — das ist bei den drei Kern-Aktionen nicht der Fall.

1. Aufbau

Harness: app/data/ai-bench/bench_claude.py (Auswertung analyze_claude.py, Rohdaten claude-2026-08-30.jsonl). Prompts verbatim aus ai_jobs.py über bench37.py (Prompts seit 16.08. unverändert, nur Modell/Effort gewechselt — geprüft per git diff 41923d2~1 41923d2). Offline, kein Finish-/APNs-Pfad.

Testset = das des 3.7-Benchmarks vom 16.08. (gleiche Ground Truth, damit die Zahlen vergleichbar sind):

Szenario Fälle Wiederh. Wahrheit
Freitext estimate 12 (9 gewertet) 3 HelloFresh-Herstellerangabe + Etikettwerte; Pizza (schwache GT) + 2 Fälle ohne GT nur nachrichtlich
Portion portion 8 (7 gewertet) 3 Referenzband je Fall; Pfefferbeißer nachrichtlich
Foto photo 4 echte Teller 2 HF-Herstellerangabe pro Portion (Abschnitt 11 des 3.7-Reports: 596 / 587 / 628 / 854 kcal)

Kandidaten (je Modell claude-haiku-4-5-20251001, claude-sonnet-5, claude-opus-5, claude-fable-5, alle mit effort=low + MAX_THINKING_TOKENS=0 — auf Abruf-/Schätz- aufgaben schadet Denken, s. 3.7-Report):

Label Was Fälle
gemini Prod-Referenz via OpenRouter: estimate/photo gemini-3.7-flash [low], portion gemini-3.5-flash-lite — exakt ai_jobs.py heute voll
cli claude -p exakt wie der Prod-Fallback ai_jobs.claude(): --setting-sources project,local, stream-json, Foto per Read-Tool (Prod-Fallback-Prompt) Subset (7 Fälle × 2) — nur Latenz-/Usage-Profil
sdk1 Agent-SDK query(), ein Prozess pro Aufruf, kein System-Prompt, keine Tools, Bild als image-Block voll
sdkp Agent-SDK ClaudeSDKClient, eine persistente Session pro Modell, alle 68 Aufrufe als Folge-Turns (Kontext wächst), System-Prompt „jede Nachricht eigenständig" voll
sdkw Warm-Pool (Vorschlag für Prod): frische Session je Job, aber vor dem Job verbunden + mit einem Mini-Turn aufgewärmt; gemessen nur der Job-Turn voll

Gemessen pro Aufruf: Wall-Clock, TTFT (erstes content_block_delta), duration_api_ms, Tokens in / out / cache_create / cache_read, nominale total_cost_usd (auf der Sub kein Geld, aber das ehrlichste Usage-Maß gegen das 5-h-Fenster), Output.

SDK: claude-agent-sdk 0.2.148 (bringt eine gebündelte CLI 2.1.251 mit = identisch mit der System-CLI), Python 3.12, eigenes venv (nicht in app/.venv).

2. Befunde zum Harness selbst (vor den Zahlen)

  1. --bare ist für die Sub unbrauchbar. Die neue Minimal-Option (überspringt Hooks/ LSP/Plugins/Memory/Keychain/CLAUDE.md-Discovery) ist per Hilfetext „Anthropic auth is strictly ANTHROPIC_API_KEY or apiKeyHelper — OAuth and keychain are never read". Mit OAuth-Token per Env kommt trotzdem „Not logged in". Damit fällt der billigste CLI-Pfad weg; es bleibt --setting-sources project,local (= Prod-Fallback heute).
  2. Der Tweet-Speedup betrifft -p nicht messbar. Trivial-Prompt („Antworte nur: ok"), 4 Modelle: Wall 5,2–5,5 s bei duration_ms 1,3–1,7 s → ~3,9 s Overhead außerhalb des API-Calls, wie im Juni (~4 s). Die Beschleunigung gilt dem interaktiven Start (Tippen vor Sandbox/MCP), nicht dem Headless-Roundtrip.
  3. Alle vier Modelle laufen auf der Max-Sub, auch Fable 5 (modelUsage bestätigt die IDs). Nominal pro Trivial-Call: Haiku 0,03 $, Sonnet 0,16 $, Opus 0,28 $, Fable 0,41 $ — getrieben von 17–39k Cache-Create-Tokens (Claude-Code-System-Prompt), nicht vom Output.
  4. SDK-Prefix ist ~9k Tokens (auch mit system_prompt=None, tools=[]), nach dem ersten Aufruf fast nur Cache-Read. CLI-Prefix ~29k (17k create + 12k read). Das SDK ist also pro Aufruf ~3× sparsamer im Sub-Verbrauch als -p. Nachtrag (Argus-Befund, nachgemessen 30.08. 16:50): mit extra_args={"setting-sources": "", "exclude-dynamic-system-prompt-sections": None} sinkt der SDK-Prefix auf 3,2k (kein Cache mehr nötig). Für -p auf 2.1.251 bringen dieselben Flags (--tools '' --setting-sources '' --exclude-dynamic-system-prompt-sections) hier nichts (9,6k Cache-Read); Argus' 300–650 Tokens reproduzieren sich auf dieser Installation nicht. Auflösung (1:1-Vergleich mit Argus, gleicher Host, gleiche CLI; Korrektur 17:05): (a) Ein expliziter --system-prompt ersetzt den Claude-Code-Default (9,6k → 3,2k). (b) Die restlichen ~3k sind NICHT die CLAUDE.md (Argus' Einwand, isoliert nachgemessen: Temp-Ordner nur mit CLAUDE.md-Kopie 258, eine Ebene tiefer 261, nur .claude/ 254, neutral 248 — --setting-sources '' unterdrückt CLAUDE.md also doch), sondern die Auto-Memory des Projekts (~/.claude/projects/<projekt>/memory/MEMORY.md, hier 26+ Einträge ≈ 3k Tokens, plus userEmail/currentDate); Haiku nennt sie auf Nachfrage als einzigen Kontext. Repo-Wurzel und app/ sind gleich (3.216/3.219). Abschalten: CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 oder --settings '{"autoMemoryEnabled":false}' → 249 Tokens aus app/, kalt. --exclude-dynamic-system-prompt-sections ist mit --system-prompt laut Hilfetext wirkungslos („ignored with --system-prompt"). Folgerung für den Prod-Fallback ai_jobs.claude(): er lädt heute den kompletten Session-Memory-Index als Kontext (inhaltlich fremd) + 9k Default-Prompt. Umgesetzt 04.09. (Freigabe Dennis): eigener --system-prompt + --setting-sources '' + CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 + --tools <genau der benötigte Satz>. Nachtrag aus der Umsetzung: --allowedTools allein reicht NICHT — es regelt nur die Erlaubnis, der komplette Tool-Satz (~14k Tokens Definitionen) bleibt im Prefix. Erst --tools schneidet ihn. Gemessen aus app/-cwd, Haiku, kalt: vorher 29,1k (cc 17,0k + cr 12,1k); nachher ohne Tool 0,3k · Read 1,5k · Bash 3,9k · WebFetch 1,3k. Alle vier Prod-Pfade (Foto-Read, Bash-curl, WebFetch, reines JSON) funktional nachgetestet.
  5. Transkript-Falle (Argus-Befund): ohne --no-session-persistence schreibt jeder Headless--p-Aufruf ein volles Transkript inkl. Prompt nach ~/.claude/projects/<cwd>/. Der Benchmark lief durchgehend mit dem Flag (keine Bench-Transkripte vorhanden); ai_jobs.claude() (Prod-Fallback) hatte es nicht → am 30.08. nachgezogen.
  6. session_id im persistenten Client isoliert nicht (Codewort-Test: Session B kannte das Codewort aus A). Eine persistente Session ist EIN wachsender Kontext — daher die Varianten sdkp (Kontext wächst, Anchoring-Risiko) und sdkw (Warm-Pool, frisch je Job).
  7. Bilder gehen im SDK als image-Block (4,2-MB-JPEG ok), kein Read-Tool nötig. In der CLI (Prod-Fallback) braucht das Foto den Read-Tool-Umweg = ein Extra-Turn.

3. Ergebnisse

Ø|Δ|% = mittlerer absoluter kcal-Fehler gegen Ground Truth (Rangkriterium wie am 16.08.), MdAPE = Median, Bias = Vorzeichen. Tokens = Ø je Aufruf (in / out / cache_create / cache_read). $nom = nominale Anthropic-Listenpreise = Sub-Verbrauchsmaß (kein Geld); bei Gemini echte OpenRouter-Kosten. sdk1/cli nur Subset (Latenz-/Usage-Profil).

3.1 Freitext estimate (9 GT-Fälle × 3)

Harness Modell Ø|Δ|% MdAPE Bias JSON-Fehler wall med wall max TTFT med in/out cache cr/rd $nom/Call
gemini 3.7-flash [low] (PROD) 6,8 5,1 −1,5 0 2,3 5,5 – 280/186 – 0,0009 (echt)
sdkw haiku-4.5 17,5 19,5 −13,4 3 2,9 3,4 0,7 3/160 1k/14k 0,007
sdkw sonnet-5 7,0 6,5 −3,7 0 3,1 5,3 0,8 2/162 1,7k/18k 0,018
sdkw opus-5 8,6 4,2 +1,0 0 3,2 4,2 0,9 2/156 1,5k/18k 0,044
sdkw fable-5 8,6 4,0 +3,3 1 4,2 6,1 1,4 2/195 1,5k/18k 0,089
sdkp haiku-4.5 16,5 16,1 −15,3 0 2,0 4,1 0,7 3/167 0,8k/24k 0,093
sdkp sonnet-5 7,4 4,2 −6,4 0 2,8 5,1 1,7 2/159 1,6k/30k 0,298
sdkp opus-5 7,1 4,2 +1,3 0 2,3 4,8 0,9 2/157 1,5k/30k 0,739
sdkp fable-5 8,3 5,1 −0,4 0 3,1 5,6 1,4 2/186 2,1k/30k 1,695
sdk1 haiku-4.5 (n=6) 14,6 12,8 −14,6 0 6,4 7,0 4,1 3/185 3k/6k 0,008
sdk1 sonnet-5 (n=6) 8,5 6,5 −4,2 0 6,5 6,7 4,3 2/172 10k/2k 0,044
sdk1 opus-5 (n=6) 6,0 4,0 −3,3 0 6,9 7,1 4,4 2/160 10k/2k 0,109
sdk1 fable-5 (n=6) 4,6 4,0 −1,9 0 7,7 7,8 4,8 2/198 10k/2k 0,221
cli haiku-4.5 (n=6) 13,5 12,8 −13,5 1 6,2 16,4 5,6 7/275 11k/48k 0,029
cli sonnet-5 (n=6) 9,0 4,0 −6,3 0 7,1 12,8 6,5 2/211 19k/27k 0,084
cli opus-5 (n=6) 6,0 4,0 −3,3 0 7,5 7,9 7,0 2/188 15k/13k 0,162
cli fable-5 (n=6) 5,8 4,0 −3,1 0 7,9 8,3 7,4 2/207 18k/11k 0,381

Lesart: Sonnet/Opus/Fable treffen im Median besser als Gemini (4,0–4,2 vs. 5,1 %), im Mittel gleichauf bis leicht schlechter — einzelne Ausreißer (Opus/Fable je ein Fall

20 %). Nach Dennis' Maßstab (gemittelte Präzision) ist das ein Gleichstand, kein Sieg. Haiku ist raus. Die 3+1 JSON-Fehler bei Haiku/Fable (sdkw) sind Antworten mit Prosa vor dem JSON trotz „NUR JSON" — Gemini hatte 0 in 724 Läufen.

3.2 Portion (7 gewertete Fälle × 3)

Harness Modell Band-Treffer wall med wall max TTFT med cache rd $nom/Call
gemini 3.5-flash-lite (PROD) 21/21 0,6 0,7 – – 0,0002 (echt)
sdkw haiku-4.5 18/21 2,0 2,3 0,7 14k 0,003
sdkw sonnet-5 18/21 2,5 3,2 0,9 19k 0,010
sdkw opus-5 21/21 2,4 2,6 0,8 19k 0,020
sdkw fable-5 21/21 3,0 3,4 1,4 19k 0,041
sdk1 / cli alle (n=4) 4/4 5,3–7,5 6–9 4,0–6,9 3k–31k 0,006–0,35

Gemini-lite ist 3–5× schneller bei gleicher Trefferquote. Nichts zu holen.

3.3 Foto — 4 echte Teller mit HF-Wahrheit (× 2)

Harness Modell Ø|Δ|% MdAPE Bias wall med TTFT med cache cr/rd $nom/Call
gemini 3.7-flash [low] (PROD) 8,8 7,9 +5,1 4,8 – – 0,0025 (echt)
sdkw haiku-4.5 20,2 19,0 +11,6 5,0 2,2 1,1k/15k 0,006
sdkw sonnet-5 14,6 12,7 +14,6 5,5 3,0 2,9k/20k 0,020
sdkw opus-5 24,7 27,4 +24,7 5,8 2,5 2,9k/20k 0,050
sdkw fable-5 13,9 13,1 +11,0 6,2 2,8 2,9k/20k 0,101
sdkp haiku-4.5 6,8 ⁽¹⁾ 4,2 −4,0 4,7 2,4 2,2k/51k 0,344
sdkp sonnet-5 12,5 10,2 +12,5 6,8 4,8 4,4k/70k 0,949
sdkp opus-5 26,1 24,8 +26,1 5,4 2,7 4,4k/69k 2,319
sdkp fable-5 9,1 ⁽¹⁾ 8,0 +4,7 6,0 3,2 8,1k/67k 5,596
sdk1 sonnet-5 / fable-5 (n=4) 7,6 / 5,9 ⁽²⁾ +7,6 / +5,9 9,0 / 10,3 5,9 / 6,2 8k/15k 0,038 / 0,192
sdk1 haiku / opus (n=4) 31,3 / 37,0 +31 / +37 8,5 / 9,2 5,6 / 5,9 0,008 / 0,134
cli haiku / sonnet / opus / fable (n=4) 27,0 / 13,1 / 33,6 / 27,7 +19…+34 9,4 / 11,6 / 10,7 / 14,4 4,2–8,1 8–39k / 24–73k 0,02–0,81

Je Teller (Ø kcal, GT in Klammern), Warm-Pool:

Modell Gnocchi 628 Döner 854 Frikassee 587 Souflaki 596
gemini 3.7 685 (+9 %) 825 (−3 %) 565 (−4 %) 705 (+18 %)
haiku-4.5 520 (−17 %) 1150 (+35 %) 685 (+17 %) 670 (+12 %)
sonnet-5 780 (+24 %) 950 (+11 %) 620 (+6 %) 700 (+17 %)
opus-5 800 (+27 %) 1100 (+29 %) 655 (+12 %) 780 (+31 %)
fable-5 780 (+24 %) 1015 (+19 %) 570 (−3 %) 620 (+4 %)

⁽¹⁾ In der persistenten Session kamen die Fotos zuletzt, nach 60 Freitext-/Portions- Antworten im Kontext — die guten Haiku/Fable-Werte dort sind mit hoher Wahrscheinlichkeit Anchoring an die vorherigen HF-Gerichte (Souflaki-Text war Fall 1!), nicht Sehleistung. Der saubere Wert ist sdkw. ⁽²⁾ n = 4 (nur Döner + Souflaki), nachrichtlich.

Befund: Auf echten Tellern überschätzt jedes Claude-Modell systematisch (+11 bis +25 % Bias), Gemini 3.7 liegt bei +5 % und 8,8 % Fehler. Opus 5 ist beim Sehen am schlechtesten (alle vier Teller +12…+31 %). Das ist derselbe Befund wie am 16.08. bei den 3.6-Modellen: Modellgröße hilft nicht, die Familie entscheidet.

4. Latenz-Anatomie — wo die Sekunden sitzen

Pfad Prozess/Init bis erstes Token Generierung Wall Freitext Wall Foto
Gemini OpenRouter 0 (~0,5) ~1,8 2,3 4,8
SDK Warm-Pool (Session steht) 0 0,7–1,4 2–3 2,9–4,2 5,0–6,2
SDK One-Shot ~1,0 (CLI-Start) + ~3 (Lazy-Init bis Request) 4,1–4,8 2–3 6,4–7,7 8,5–10,3
CLI -p (Prod-Fallback) ~4 5,6–7,4 2–3 6,2–7,9 9,4–14,4 (Read-Tool-Turn)

Der Warm-Pool nimmt den Init raus, aber die Claude-Generierung ist bei ~150–200 Output-Tokens 1–2 s langsamer als Gemini 3.7 — deshalb bleibt es ein Gleichstand, kein Sieg. Die erste Nachricht einer frischen Session kostet ~2,7 s (Lazy-Init); die Aufwärm- Nachricht des Pools trägt das (warmup_s in den Rohdaten).

5. Usage — was die Sub wirklich zahlt

Variante Tokens je Call (cache read) nominal/Call Hochrechnung auf unser Volumen (62 Jobs / 30 Tage)
Warm-Pool Sonnet 5 ~18–20k 0,01–0,02 $ ~1 $/Monat nominal — irrelevant
Warm-Pool Fable 5 ~18–20k 0,04–0,10 $ ~4 $/Monat nominal
CLI -p Sonnet 5 19k create + 27k read 0,04–0,08 $ ~4 $/Monat
persistente Session 30–70k, wachsend 0,1–5,6 $ 325 $ nominal in 272 Calls — das 5-h-Fenster
Gemini (echt) – 0,0002–0,0025 $ ~0,11 $/Monat echt

Das 5-h-Fenster stand nach dem Lauf bei 84 % (Wochenfenster 19 %). Lehre: bei Sub-Nutzung ist der Kontextumfang die Stellgröße, nicht die Call-Zahl. Jede Session-Architektur muss den Kontext pro Job klein halten (Warm-Pool: neue Session je Job).

6. Urteil

Aktion Anteil der Jobs (30 d) Bester Claude (Warm-Pool) Gemini PROD Urteil
photo 55 % Fable 13,9 % / 6,2 s 8,8 % / 4,8 s Gemini — schneller UND genauer
estimate 42 % Sonnet 7,0 % / 3,1 s 6,8 % / 2,3 s Gleichstand Qualität, Gemini schneller, kein Daemon nötig
portion 3 % Opus 21/21 / 2,4 s 21/21 / 0,6 s Gemini — 4× schneller
  1. Gemini bleibt für alle drei Kern-Aktionen. Kein Modellwechsel, kein Umbau.
  2. Nicht bauen: Warm-Pool-Daemon. Er brächte Gleichstand bei Freitext zum Preis einer neuen Betriebskomponente (Prozess je Modell, Sessions vorwärmen, Crash/Restart, Health).
  3. Optional, klein: ai_jobs.claude() (Fallback) von claude -p auf SDK-One-Shot umstellen — gleiche Latenz, 3× weniger Sub-Verbrauch, Bild als image-Block statt Read-Tool (Foto-Fallback 9 s statt 14 s). Und: Fallback-Modell sonnet → claude-sonnet-5 ist ok; haiku als Fallback für estimate wäre falsch (−13 % Bias) — heute steht dort sonnet, gut so.
  4. Wo Claude-Qualität lohnen könnte, aber nicht gemessen wurde: Jobs ohne wartenden Menschen mit hohem Textanspruch (insights, cook_suggest, Bon-PDF-Extraktion). Dort wäre ein SDK-One-Shot mit Opus/Fable auf der Sub kostenlos und die 4 s Init egal. Das ist ein anderer Benchmark (Judge = ich), falls gewünscht.

7. Was diese Studie nicht kann


Rohdaten app/data/ai-bench/claude-2026-08-30.jsonl (gitignored, 724 Zeilen), Harness bench_claude.py, Auswertung analyze_claude.py. Bezug: benchmark-claude-sub-vs-gemini.md (07.06.), benchmark-gemini-3.7-2026-08.md (16.08., Testset + GT), ADR-37.