Handoff an Finsight: Claude Code CLI + Agent-SDK auf der Max-Subscription — Fakten, Fallen, Zitate
Von: StratoClaude (Silverscale-VPS-Session), 30.08.2026 · Für: Finsight (Doku-Archiv/
Wissensbasis mit Chat-Interface, das im Hintergrund Dennis' Claude-Max-Sub nutzt).
Zweck: Alles, was wir über den Betrieb von claude -p und claude-agent-sdk auf der Sub
hart wissen — jede Aussage mit Quellenanker (M = selbst gemessen am 30.08.2026, H =
CLI-Hilfetext 2.1.251, S = SDK-Quellcode 0.2.148, D = Anthropic-Doku, B = Benchmark-Report).
Nicht-Verifiziertes ist als solches markiert. Primärquelle für die Zahlen:
https://silverscale-docs.dennisfisch.de/dev/benchmark-claude-code-2026-08.html (B).
1. Auth — was auf der Sub geht und was nicht
| Fakt | Quelle |
|---|---|
Die CLI ist per claude.ai-OAuth eingeloggt; claude auth status → loggedIn: true, authMethod: claude.ai, apiProvider: firstParty. |
M |
Credentials liegen in ~/.claude/.credentials.json → claudeAiOauth mit accessToken, refreshToken, expiresAt, refreshTokenExpiresAt, scopes, subscriptionType, rateLimitTier. Die CLI erneuert den Access-Token selbst. |
M (Dateistruktur), Erneuerung: beobachtet, nicht im Code geprüft |
Das Python-SDK claude-agent-sdk nutzt diesen Login mit — keine ANTHROPIC_API_KEY nötig. Alle vier aktuellen Modelle liefen damit (s. §3). |
M |
--bare ist API-Key-only. Hilfetext: „Anthropic auth is strictly ANTHROPIC_API_KEY or apiKeyHelper via --settings (OAuth and keychain are never read)." Mit CLAUDE_CODE_OAUTH_TOKEN per Env trotzdem „Not logged in · Please run /login". → Für Sub-Betrieb nie --bare. |
H, M |
Ohne --bare (z. B. --setting-sources project,local) greift der OAuth-Login normal. |
M |
| Dennis' Regel: API-Token-Abrechnung ist ausgeschlossen („API Tokens ist indiskutabel teuer und wird 100 % abgelehnt"), SDK auf der Sub ist gewollt; eine Policy-Prüfung wurde ausdrücklich nicht gewünscht. | Dennis, 30.08.2026 |
2. Das Usage-Fenster (5 h / 7 Tage) abfragen
GET https://api.anthropic.com/api/oauth/usage
Authorization: Bearer <accessToken aus ~/.claude/.credentials.json>
anthropic-beta: oauth-2025-04-20
Antwort (Auszug): five_hour.utilization (Prozent), five_hour.resets_at (ISO, UTC),
seven_day.utilization, seven_day.resets_at, extra_usage.is_enabled. Das ist derselbe
Endpoint, den /usage in der CLI zeigt. (M — am 30.08. mehrfach abgefragt: 72 → 78 → 84 %.)
Für ein Chat-Interface: vor teuren Aktionen abfragen und dem Nutzer zeigen; bei > 90 % degradieren (kleineres Modell / kürzerer Kontext), nicht blind weiterfeuern.
3. Modelle auf der Sub (30.08.2026)
| Modell-ID | Läuft auf Sub | Nominal $/Trivial-Call via -p ⁽¹⁾ |
Bemerkung |
|---|---|---|---|
claude-haiku-4-5-20251001 |
ja | 0,035 | schnellster TTFT (0,7 s im Warm-Pool), aber schwächste Qualität, 3/68 JSON-Verstöße |
claude-sonnet-5 |
ja | 0,157 | bestes Preis/Leistungs-Gefühl im Test |
claude-opus-5 |
ja | 0,278 | Text sehr gut, Sehen (Foto-Schätzung) am schlechtesten |
claude-fable-5 |
ja | 0,408 | Text sehr gut (MdAPE 4,0 %), langsamster TTFT (1,4 s), 1 JSON-Verstoß |
⁽¹⁾ total_cost_usd aus dem -p-Ergebnis für „Antworte nur: ok" — getrieben von 17–39k
Cache-Create-Tokens (Claude-Code-System-Prompt), nicht vom Output. Auf der Sub kein
Geld, aber das ehrlichste Verbrauchsmaß. (M)
Die CLI-Kurznamen haiku/sonnet/opus werden auf aktuelle Modelle aufgelöst; die
modelUsage-Map im Ergebnis nennt die exakte ID. (M)
4. Latenz-Anatomie — wo die Sekunden sitzen (M, B §4)
| Pfad | Init | bis erstes Token | Wall Text (~180 Tok out) | Wall Foto |
|---|---|---|---|---|
claude -p (ein Prozess je Aufruf) |
~4 s | 5,6–7,4 s | 6–8 s | 9–14 s (Bild via Read-Tool = Extra-Turn) |
SDK query() (ein Prozess je Aufruf) |
~1 s CLI-Start + ~3 s Lazy-Init | 4,1–4,8 s | 6,4–7,7 s | 8,5–10,3 s |
SDK ClaudeSDKClient, erste Nachricht einer Session |
– | ~2,6 s | ~2,7 s (trivial) | – |
SDK ClaudeSDKClient, Folge-Nachricht (Session warm) |
0 | 0,7–1,4 s | 2,9–4,2 s | 5,0–6,2 s |
| Referenz Gemini 3.7-flash via OpenRouter | 0 | ~0,5 s | 2,3 s | 4,8 s |
Kernaussagen:
- Der „CLI startet schneller"-Tweet (@ClaudeDevs, 29.08.) betrifft den interaktiven
Start (Tippen vor Sandbox/MCP). Headless -p hat unverändert ~4 s Overhead pro Prozess
(Juni 2026: ~4 s; 30.08.: 3,9 s). (M, Tweet-Text von Dennis)
- Für ein Chat-Interface ist die persistente Session der einzige richtige Weg: erste
Antwort ~2,7 s, danach TTFT unter 1,5 s. Ein Prozess pro Nachricht wäre 5–8 s.
- Der Unterschied Folge-Turn vs. Gemini liegt in der Generierung (Claude ~1–2 s
langsamer bei ~150–200 Tokens), nicht mehr im Init.
5. Tokens, Cache und das Kontext-Problem (M, B §5)
- SDK mit
system_prompt=None,tools=[]: trotzdem ~9k Token Prefix je Call (nach dem ersten Call fast nurcache_read). CLI-pmit--setting-sources project,local: ~29k (17k create + 12k read). → SDK ist pro Call ~3× sparsamer als-p. - Prefix weiter drücken (Argus-Befund 30.08., gemeinsam aufgeklärt, M):
1.
--system-prompt '<eigener Text>'(SDKsystem_prompt=str) ersetzt den ~9k Claude-Code-Default-Prompt → ~3,2k. Ohne eigenen System-Prompt bleibt der Default immer. 2. Der Rest (hier ~3k) ist die Auto-Memory des Projekts (~/.claude/projects/<slug>/ memory/MEMORY.md— wird für jedes cwd innerhalb des Projekts geladen, Repo-Wurzel wie Unterordner). Abschalten: EnvCLAUDE_CODE_DISABLE_AUTO_MEMORY=1oder--settings '{"autoMemoryEnabled":false}'(SDK:env={…}bzw.settings=). 3.--setting-sources ''unterdrückt CLAUDE.md-Discovery tatsächlich (Argus' Messung, von mir isoliert bestätigt: Temp-Ordner nur mit 14-KB-CLAUDE.md → 258 Tokens). 4.--exclude-dynamic-system-prompt-sectionsist mit--system-promptwirkungslos (Hilfetext: „ignored with --system-prompt"); nur ohne eigenen System-Prompt relevant. 5. Skills/Agents-Discovery (15/5 geladen) und claude.ai-MCP-Connectoren kosten nichts Messbares;--tools ''entfernt die Built-in-Tool-Definitionen. Achtung (Nachtrag 04.09., M):--allowedToolsregelt nur die Erlaubnis — der volle Tool-Satz (~14k Tokens Definitionen) bleibt im Prefix, solange--toolsnicht gesetzt ist. Wer Tools braucht, gibt mit--toolsgenau den Satz an: Read ≈1,5k, Bash ≈3,9k, WebFetch ≈1,3k, leer ≈0,3k (Haiku, kalt, Silverscale-app/). Ergebnis: Silverscale-app/, kalt: 9,6k → 3,2k (1.) → 249 Tokens (1.+2.). Finsight-Root: 700, neutral 245 (Argus) — Rest dort vermutlich kleine Memory/Git-Kontext. - Eine Session, die wächst, liest bei jedem Turn den ganzen Kontext (als Cache-Read, aber es zählt). Im Benchmark: 68 Turns in einer Session → Kontext 30–70k, letzte Fable-Calls nominal 5,6 $/Call, Summe 325 $ nominal in 272 Calls — das hat den Großteil des 5-h-Fensters gefressen. Frische Sessions (Warm-Pool) kosteten für die gleichen 272 Calls < 3 $ nominal.
- Für einen Chat heißt das: eine Session pro Unterhaltung ist richtig (der Kontext ist
ja gewollt), aber (a) lange Chats werden pro Nachricht linear teurer im Sub-Verbrauch,
(b) niemals mehrere unabhängige Nutzer/Threads in eine Session multiplexen, (c) Bilder
im Kontext bleiben teuer (je ~1,5–2k Tokens pro Turn mitgelesen), (d) Kompaktierung/
Neustart der Session ab z. B. 40–50k Kontext einplanen.
ClaudeSDKClient.get_context_usage()existiert (S,client.py:471) — nicht getestet. session_idimClaudeSDKClient.query(prompt, session_id=…)isoliert NICHT. Codewort-Test: Session „B" kannte das Codewort aus „A". Ein Client = ein Kontext. (M)- Usage-Felder je Antwort (
ResultMessage.usage, Stypes.py):input_tokens,output_tokens,cache_creation_input_tokens,cache_read_input_tokens,cache_creation.ephemeral_5m/1h_input_tokens,output_tokens_details.thinking_tokens; dazuResultMessage.total_cost_usd,duration_ms,duration_api_ms,num_turns,model_usage,session_id,stop_reason,is_error,errors,api_error_status. (S)
6. SDK — die relevanten Bausteine (S, claude-agent-sdk 0.2.148)
- Paket:
pip install claude-agent-sdk(Python; Node-Variante@anthropic-ai/claude-agent-sdknicht getestet). Bringt eine gebündelte CLI mit (_bundled/claude, 214 MB, Version 2.1.251 = identisch mit der System-CLI); Suchreihenfolge: bundled →shutil.which("claude")→cli_path-Option (_internal/transport/subprocess_cli.py:249–256). Der Transport ist ein Subprozess mit--input-format stream-json --output-format stream-json. ClaudeAgentOptions(Auszug,types.py):model,fallback_model,effort("low"|"medium"|"high"|"xhigh"|"max"),max_thinking_tokens,thinking({"type":"disabled"}/{"type":"enabled","budget_tokens":n}/{"type":"adaptive"}),system_prompt(String oder Preset{"type":"preset","preset":"claude_code","append":…, "exclude_dynamic_sections":…}),tools,allowed_tools,disallowed_tools,permission_mode("default"|"acceptEdits"|"plan"|"bypassPermissions"|"dontAsk"|"auto"),max_turns,max_budget_usd,continue_conversation,resume(Session-ID),session_id,fork_session,include_partial_messages(nötig für Token-Streaming),setting_sources(["user","project","local"];None= keine Settings laden),mcp_servers,skills,plugins,hooks,output_format(JSON-Schema →structured_output),cwd,env,extra_args(beliebige CLI-Flags, z. B.{"no-session-persistence": None}),betas("context-1m-2025-08-07"),session_store,load_timeout_ms.- Zwei Nutzungsformen:
query(prompt, options)(async Iterator, ein Prozess je Aufruf) undClaudeSDKClient(options)mitconnect()/query()/receive_response()/interrupt()/set_model()/set_permission_mode()/get_context_usage()/disconnect()(client.py). Für Chat: Client. - Streaming-TTFT messen: mit
include_partial_messages=TruekommenStreamEvent- Objekte; das ersteevent["type"] == "content_block_delta"ist das erste Token. (M) - Bilder: als Content-Block im User-Message-Dict, kein Read-Tool nötig:
python {"type":"user","message":{"role":"user","content":[ {"type":"text","text":"…"}, {"type":"image","source":{"type":"base64","media_type":"image/jpeg","data":b64}}]}, "parent_tool_use_id":None,"session_id":"default"}übergeben alsasync-Generator anquery()/client.query(). 4,2-MB-JPEG lief. (M) - Prompt-Formen: String oder async-Iterable von Message-Dicts; beide erzeugten denselben ~9k-Prefix (kein Token-Unterschied). (M)
- Harmlose Warnung im Log:
child process pid … exit status already read: will report returncode 255beim Beenden eines Clients — kein Fehler. (M)
7. CLI -p — die relevanten Flags (H, 2.1.251)
--output-format stream-json --verbose (Events system/init, assistant, result),
--include-partial-messages, --input-format stream-json, --model, --effort,
--max-thinking-tokens (Env MAX_THINKING_TOKENS=0 schaltet Denken aus — M), --system-prompt
/ --append-system-prompt (+ -file-Varianten), --tools, --allowedTools (variadisch —
-- vor dem Prompt setzen, sonst schluckt es den Prompt; M aus ai_jobs.py),
--json-schema, --max-turns, --resume <id> / -c / --session-id <uuid> /
--fork-session, --no-session-persistence, --setting-sources user,project,local,
--bare (s. §1, nicht für Sub), --permission-mode, --exclude-dynamic-system-prompt-sections.
--verbose ist für stream-json Pflicht.
Transkript-Falle: ohne --no-session-persistence schreibt jeder Headless--p-Aufruf ein
volles Transkript inkl. User-Prompt/Dokumenttext nach ~/.claude/projects/<cwd-slug>/<session>.jsonl
(Argus-Befund: 72 Transkripte mit Familienpost bei Finsight; bei Silverscale am 30.08. geprüft:
Benchmark lief mit Flag, Prod-Fallback nachgezogen). Für Chat-Sessions gilt dasselbe via SDK:
extra_args={"no-session-persistence": None} — es sei denn, das Transkript ist gewollt (Resume).
Ergebnis-JSON (--output-format json): result, duration_ms, duration_api_ms,
total_cost_usd, usage{…}, modelUsage{<id>:…}, is_error, session_id. (M)
8. Qualität — was die Modelle können (B §3, gegen Herstellerwahrheit gemessen)
- Text/Zahlen-Schätzung (Freitext → kcal): Sonnet 5 / Opus 5 / Fable 5 ≈ Gemini 3.7 (Ø 7,0 / 8,6 / 8,6 % vs. 6,8 %; Median 4,0–4,2 % vs. 5,1 %). Haiku 4.5: 17,5 %, systematisch −13 %.
- Sehen (echte Teller): alle Claude-Modelle überschätzen +11…+25 %; Gemini 3.7 8,8 % vs. Fable 13,9 / Sonnet 14,6 / Haiku 20,2 / Opus 24,7 %. Modellgröße hilft nicht.
- JSON-Hygiene: „Antworte NUR mit JSON" wird von Claude gelegentlich mit Prosa/Fence
gebrochen (Haiku 3/68, Fable 1/68; Gemini 0/724) → immer
{…}-Extraktion + Fence-Strip parsen, oderoutput_format/--json-schemanutzen (nicht gemessen). - Denken aus (
effort=low+max_thinking_tokens=0) war für Abruf-/Schätzaufgaben richtig (Vorbefund 16.08.: mehr Denken = schlechter + langsamer). Für einen Wissens-Chat mit Quellenarbeit ist das nicht übertragbar — dort ist Effort/Thinking nicht gemessen.
9. Empfehlungen für Finsights Chat-Interface (abgeleitet, nicht gemessen)
- Ein
ClaudeSDKClientpro Unterhaltung, beim Öffnen des Chats verbinden und mit einer Mini-Nachricht vorwärmen (nimmt die ~2,7 s der ersten Nachricht aus dem Nutzerpfad). Folge-Antworten dann mit < 1,5 s TTFT. include_partial_messages=Trueund Deltas an die UI streamen — gefühlte Latenz ist der TTFT, nicht die Wall-Clock.system_promptals eigener String (klein) stattclaude_code-Preset,toolsauf das Nötige begrenzen,setting_sources=None— jedes Ballast-Token wird pro Turn neu gelesen.- Kontext im Blick:
usage.cache_read_input_tokenspro Antwort loggen; ab ~40–50k Session zusammenfassen/neu starten. Nie Nutzer/Threads in einer Session mischen (session_idisoliert nicht). - Modellwahl: Sonnet 5 als Default (Qualität ≈ Opus/Fable im Text-Test, halber Verbrauch, schneller), Opus/Fable auf Nachfrage; Haiku nur für Klassifikation/Routing.
- Vor teuren Aktionen
/api/oauth/usageabfragen; bei > 90 % 5-h degradieren. - Nie
--bare; nie API-Key setzen (sonst zahlt die API, nicht die Sub).no-session-persistencebewusst entscheiden: an = keine Transkripte auf Platte, aus = Resume möglich, aber Nutzertexte liegen unter~/.claude/projects/. - Wenn ein Bild in den Kontext muss: Block statt Read-Tool; danach den Kontext bewusst kurz halten — das Bild wird bei jedem Folge-Turn mitgelesen.
10. Offen / nicht verifiziert
- Node-SDK,
output_format/--json-schema,get_context_usage(),resumeüber Prozessgrenzen, Verhalten bei erschöpftem 5-h-Fenster (Fehlercode?), Concurrency-Limits der Sub (3 parallele SDK-Prozesse liefen fehlerfrei; mehr nicht probiert). - Der Refresh-Mechanismus des OAuth-Tokens, wenn nur das SDK (ohne interaktive CLI) läuft — im Test hat die CLI kurz vorher interaktiv gearbeitet.
Rohdaten: app/data/ai-bench/claude-2026-08-30.jsonl (Silverscale-VPS, gitignored), Harness
bench_claude.py, Smoke-Skripte im Session-Scratchpad. Vorgänger: benchmark-claude-sub-vs-gemini.md
(07.06.2026), BENCHMARK-OPENROUTER-2026-06-06.md.