managarten/docs/reports/claude-code-architecture.md
Till JS b1b9bbc269
Some checks are pending
CD Mac Mini / Detect Changes (push) Waiting to run
CD Mac Mini / Deploy (push) Blocked by required conditions
CI / Detect Changes (push) Waiting to run
CI / Validate (push) Waiting to run
CI / Build mana-search (push) Blocked by required conditions
CI / Build mana-sync (push) Blocked by required conditions
CI / Build mana-api-gateway (push) Blocked by required conditions
CI / Build mana-crawler (push) Blocked by required conditions
Docker Validate / Validate Dockerfiles (push) Waiting to run
Docker Validate / Build calendar-web (push) Blocked by required conditions
Docker Validate / Build quotes-web (push) Blocked by required conditions
Docker Validate / Build todo-backend (push) Blocked by required conditions
Docker Validate / Build todo-web (push) Blocked by required conditions
Docker Validate / Build mana-auth (push) Blocked by required conditions
Docker Validate / Build mana-sync (push) Blocked by required conditions
Docker Validate / Build mana-media (push) Blocked by required conditions
Mirror to Forgejo / Push to Forgejo (push) Waiting to run
chore: rename repo mana-monorepo → managarten
Phase-3-Rename des ehemaligen Multi-App-Monorepos zum eigenständigen
Produkt-Repo. Verein heißt mana e.V., Plattform-Domain bleibt mana.how,
apps/mana/ bleibt unverändert — nur der Repo-Container kriegt den
neuen Namen "managarten" (Garten der mana-Apps).

Geändert:
- package.json#name + #description
- README.md (Titel + erster Absatz)
- TROUBLESHOOTING.md
- alle Mac-Mini-Skripte (Pfade ~/projects/mana-monorepo → ~/projects/managarten)
- COMPOSE_PROJECT_NAME-default in scripts/mac-mini/status.sh
- .github/workflows/cd-macmini.yml + mirror-to-forgejo.yml
- apps/docs (astro.config.mjs + content)
- .claude/settings.local.json (Bash-Permission-Pfade)
- alle docs/*.md Pfad-Referenzen
- launchd plists, .env.macmini.example, infrastructure/

Forgejo-Repo + GitHub-Repo bereits via API umbenannt. Lokales
Verzeichnis-Rename + Mac-Mini-Cutover folgen separat.
2026-05-09 01:16:02 +02:00

21 KiB
Raw Permalink Blame History

Claude Code — Anatomie eines Agent-Harness

Stand: 2026-04-23 Quellenlage: Reverse-Engineering / Leaks aus Community-Analysen (siehe §13)

Technischer Bericht über die interne Architektur von Claude Code (Anthropics offiziellem CLI), konsolidiert aus öffentlich dokumentierten Reverse-Engineering-Analysen des minified @anthropic-ai/claude-code-Pakets sowie live mitgeschnittenen API-Roundtrips.


Inhaltsverzeichnis

  1. Kontext zur Quellenlage
  2. System-Architektur
  3. Prompt-System
  4. Tool-System
  5. Sub-Agent-System (I2A / Task-Tool)
  6. Context-Management
  7. Steering-Mechanismen
  8. Security & Sandboxing
  9. Real-Time Steering: h2A
  10. UI/Terminal-Layer
  11. Memory & Todos
  12. Model-Routing
  13. Bemerkenswerte Clever Tricks
  14. Relevanz für das Mana-Monorepo
  15. Quellen

1. Kontext zur Quellenlage

Das ursprünglich viel zitierte Repo shareAI-lab/analysis_claude_code wurde inzwischen archiviert bzw. in shareAI-lab/learn-claude-code überführt — der neue Fokus liegt auf Didaktik („Harness Engineering"), nicht mehr auf den deobfuscierten Funktionsnamen. Die ursprünglichen Funktionsnamen (nO, h2A, wU2, I2A, UH1, gW5, tU2, KN5 etc.) leben aber in mehreren Folge-Analysen weiter (BrightCoding Juli 2025, xugj520 „Efficient Coder", PromptLayer-Blog, Medium Sujay Pawar).

Yuyz0112/claude-code-reverse geht einen komplementären Weg: Statt statische Code-Analyse monkey-patcht er beta.messages.create im installierten cli.js und loggt die echten API-Roundtrips — daraus lassen sich die System-Prompts, Tool-Definitionen und Modell-Routing-Entscheidungen direkt ablesen.

Piebald-AI/claude-code-system-prompts pflegt per Version ein vollständiges Prompt-Archiv. Version 2.1.117 hat ~110 Prompt-Strings, 24 Built-in-Tool-Beschreibungen und ~40 System-Reminder.

Die folgenden Befunde sind die konsolidierte Lesart über diese Quellen.


2. System-Architektur

Die Gesamtarchitektur ist ein vierlagiges Harness:

  1. UI Layer — CLI (Ink/React), VSCode-Plugin, optionale Web-Frontends.
  2. Agent Core Scheduling LayernO (Master-Loop) plus h2A (asynchrone Message-Queue als Steering-Bus).
  3. Execution Layer — Streaming-Generator (wu), Context-Compressor (wU2), Tool-Execution-Engine (MH1), Tool-Scheduler (UH1/gW5).
  4. Storage Layer — Messages, komprimierte Summaries, CLAUDE.md-basierter Langzeitspeicher, ~/.claude/todos/{session}.json.

Der zentrale Prozessor ist nO: ein single-threaded Master-Loop, implementiert als Generator-basierte async-Runtime. Das Muster ist das kanonische

while (response.stop_reason === "tool_use") {
  executeTools();
  appendResults();
  recallModel();
}

das bei reinem Text terminiert. Um diesen Kern-Loop drapiert sich der gesamte Rest der Maschinerie. tU2 ist in den Analysen der Name für den Konversations-Flow-Wrapper, der Messages in nO rein- und rausleitet und dabei System-Reminder einmischt.

Flow-Diagramm

User
  → tU2 (conversation flow)
  → System-Prompt-Zusammenbau + Reminder-Injection
  → nO (master loop)  ←→  h2A (steering bus)
      → Tool-Call?
          → UH1 Permission-Gate
          → gW5 Concurrent-Scheduler (max 10)
          → MH1 exec
      → Results zurück in h2A
      → nO → next iteration

3. Prompt-System

Jeder Turn geht mit drei Schichten an die API:

  1. System-Prompt: Claude-Code-Identität, Kernrichtlinien, Tool-Policies, Sandbox-Regeln, Git-Hinweise. Piebalds Archiv zeigt: mehrere Dutzend Strings werden konditional injiziert je nach Mode (Auto/Learning/Plan), IDE-Integration, aktiviertem Sandboxing etc.
  2. User-Message mit angehängtem <system-reminder>-Block, der den dynamischen Zustand trägt: Working-Directory, Git-Branch, Platform, Date, CLAUDE.md-Inhalte, Todo-Liste, File-Freshness-Warnungen, Skills-Liste.
  3. Turn-spezifische Reminder am Anfang und Ende einer Konversation (system-reminder-start, system-reminder-end bei Yuyz0112) — der Start-Reminder lädt Umgebungskontext, der End-Reminder prüft, ob Todos re-injiziert werden müssen.

Besonderheit: CLAUDE.md-Disclaimer

Der CLAUDE.md-Block wird mit einem expliziten Disclaimer injiziert:

„IMPORTANT: this context may or may not be relevant to your tasks. You should not respond to this context unless it is highly relevant."

Claude Code gibt dem Modell also bewusst die Freiheit, den Projektkontext zu ignorieren. Das adressiert den klassischen Bug, dass lange System-Prompts das Modell zu rigiden Interpretationen zwingen.


4. Tool-System

Die ursprünglichen Analysen sprechen von „15 Kern-Tools"; die aktuelle Version 2.1.117 laut Piebald-Archiv hat 24 Built-in-Tool-Beschreibungen.

Historische Kern-Menge

View/Read, LS, Glob, Grep, Edit, Write/Replace, Bash, WebFetch, WebSearch, NotebookRead, NotebookEdit, TodoWrite, Task (Sub-Agent-Launcher), BatchTool (historischer Vorläufer der heute impliziten Parallel-Tool-Calls), exit_plan_mode.

Neuere Additionen

EnterPlanMode/ExitPlanMode, Worktree-Management, TaskCreate/TaskUpdate, CronCreate, Computer (Browser-Automation), LSP.

Execution-Pipeline

  • UH1 — Permission Gateway: Statisch-strukturelle Prüfung vor Execution. Jeder Tool-Call wird gegen die Whitelist aus settings.json gemappt (z. B. Bash(npm test:*), Edit(src/**)). Read-only Tools (Read, Glob, Grep, LS, WebFetch, WebSearch) sind per Default auto-approved. Writes und Bash-Befehle gehen durch Permission-Prompt, außer der Mode ist acceptEdits, dontAsk oder bypassPermissions. Permission-Modes-Katalog: plan (read-only), default, acceptEdits, dontAsk, bypassPermissions.
  • gW5 — Parallel Scheduler: Concurrent-Executor mit Maximum 10 parallelen Tool-Calls. Wenn das Modell in einem Turn mehrere unabhängige Tool-Blocks zurückgibt (z. B. gleichzeitig Grep + Glob + Read), werden sie in einem Pool von maximal 10 Workern parallel abgearbeitet. Sobald ein Call ein Write ist oder Side-Effects hat, serialisiert gW5 für diesen Block.
  • MH1 — Tool Execution Engine: Der eigentliche Dispatcher mit dem Handler-Map toolName → handler.

Performance-Messwerte (Reverse-Engineering)

Metrik Wert Quelle
gW5/UH1-Overhead ~0.8 ms pro Tool xugj520 (M2 Max)
h2A-Throughput >10 000 msg/s xugj520 (M2 Max)
Max parallele Tool-Calls 10 ComeOnOliver/Analysis

Das sind Reverse-Engineering-Schätzwerte, nicht Anthropic-offiziell.


5. Sub-Agent-System (I2A / Task-Tool)

Das Task-Tool ruft KN5 als Launcher auf, der einen neuen I2A-SubAgent-Kontext startet:

  • Fresh messages[] — der Sub-Agent bekommt ein leeres History-Array, plus die aus dem Parent extrahierte Task-Description als initiale User-Message.
  • Isolation: eigene Tool-Permissions (restriktiver als der Parent, meist read-only + Grep/Glob), eigener Token-Budget, eigener v8-Isolate-ähnlicher Scope.
  • Return-Contract: Nur die finale Zusammenfassung des Sub-Agents wird als ein einzelnes tool_result in die Parent-History eingefügt — das Kernziel: „dirty context" (hunderte gescannte Files) bleibt im Kind, im Parent landet nur der Destillat-Absatz.
  • Rekursionsgrenze: Sub-Agents können keine weiteren Sub-Agents starten („One level deep, no further"). Maximale Parallelität in einem Batch: ebenfalls 10.
  • Modell-Routing per Sub-Agent-Typ: Der Explore-SubAgent läuft auf Haiku (billig + schnell, read-only-Recherche), Plan-Mode auf Sonnet, General-Purpose auf dem Parent-Modell.

6. Context-Management

wU2 — 92%-Threshold-Compressor

Die zentrale Komponente ist wU2 — der 92%-Threshold-Compressor. Sobald die Token-Nutzung der Konversation ca. 92 % des Context-Window-Limits erreicht, feuert wU2 automatisch einen zusätzlichen API-Call mit einem speziellen system-compact-Prompt (per Yuyz0112 belegt).

Das Modell wird instruiert, den Verlauf nach einem festen Schema zu komprimieren:

  • Task Goal
  • Decisions Made
  • Files Changed
  • Current Progress

werden explizit erhalten; verbatim-Details und intermediäre Tool-Outputs fallen weg. Die Analysen berichten Kompressionsraten von ~6.8×.

In neueren Versionen existiert zusätzlich ein „soft"-Trigger bei ~50 % Auslastung, der eine leichte Summary mit einbaut, ohne die Raw-Turns zu ersetzen.

CLAUDE.md-Loading (8-Stage-Pipeline)

In der Praxis landen folgende Scopes gestapelt im System-Prompt:

  1. ~/.claude/CLAUDE.md (global)
  2. Parent-Dirs hoch zur Git-Root
  3. ./CLAUDE.md (Projekt)
  4. ./CLAUDE.local.md (user-local, gitignored)
  5. Sub-Directory CLAUDE.md-Dateien (beim Cd-ähnlichen Navigieren „imported")
  6. Auto-Memory aus ~/.claude/projects/{project}/memory/MEMORY.md
  7. Session-spezifische Reminder
  8. Turn-spezifische Reminder (siehe §7)

Größe wird empfohlen unter 200 Zeilen zu halten.


7. Steering-Mechanismen

Dies ist der unterschätzte Teil. Claude Code injiziert zur Laufzeit kontinuierlich kleine Reminder-Blöcke ins nächste Turn, ohne die Konversations-History zu mutieren — sie kommen als transiente <system-reminder>-Tags im nächsten User-Message-Envelope:

Mechanismus Trigger Effekt
Todo-Re-Injection Nach jedem TodoWrite-Call Modell „sieht" seine Todo-Liste in jedem API-Request
File-Freshness-Tracking File modifiziert nach letztem Read Blockiert nächsten Edit; injiziert „File modified"-Warning
Stale-Todo-Reminder Task-Tools zu lange nicht genutzt Injiziert Hinweis, Planungs-Tools zu verwenden
Hook-Notifications PreToolUse, PostToolUse, SessionStart/End User-Hooks triggern; Output wird als <system-reminder> zurückgespielt

Kernidee: Der Assistant-Teil der History bleibt unberührt — was kritisch ist, weil jede Assistant-Mutation KV-Cache invalidieren würde. Cache-Stability wird explizit priorisiert.


8. Security & Sandboxing

xugj520 beschreibt ein 6-Layer-Permission-Framework:

  1. UI-Input-Validation
  2. Prompt-Analyse auf Injection-Patterns
  3. UH1-Policy-Matching gegen Whitelist
  4. Pro-Tool-Arg-Validation (z. B. Path-Canonicalization mit Blacklist außerhalb des Workspaces)
  5. LLM-basierte Command-Injection-Detection für Bash (ein separater Haiku-Call prüft rm -rf /, curl | sh etc. vor Execution)
  6. Output-Filter/Redaction (Secrets, Tokens)

Das Bash-Tool entstringt explizit Backticks und $()-Substitutionen in User-gelieferten Argumenten. MCP-Server laufen in einem Bridge-Modus mit pro-Policy entweder Docker- oder WASM-Isolation.


9. Real-Time Steering: h2A

h2A ist die namentlich auffälligste Komponente — Dual-Buffer-Async-Message-Queue mit Promise-basiertem Async-Iterator und Backpressure. Funktionell:

  • Zero-Latency-Delivery: Der Producer (Streaming-API-Response-Chunks, Tool-Result-Events, User-Interjections) pusht in Buffer A, während der Consumer aus Buffer B liest. Swap passiert atomar — keine Lock-Kontention, keine Drops.
  • Mid-Task-User-Interjections: Der User kann während ein Tool läuft Input senden; h2A merged das in die nächste Iteration, ohne den Loop neu zu starten. Das erklärt, warum Claude Code auf Tastatureingaben reagiert, während es z. B. einen langen Bash-Command ausführt.
  • Stream-JSON-I/O: Externe Clients (IDE-Plugins, Remote-Control) sprechen Claude Code über line-delimited JSON-Events über stdin/stdout, die direkt in h2A gepumpt werden.

10. UI/Terminal-Layer

Ink (React-Renderer für Terminals) mit einem stark geforkten Custom-Reconciler via react-reconciler. Jeder Frame:

  1. React-Commit
  2. In-memory DOM-Tree (DOMElement/TextNode)
  3. Yoga (Facebook's Flexbox-Engine, als yoga.wasm eingebunden) berechnet Layout
  4. renderNodeToOutput schreibt styled Characters in ein getyptes Screen-Buffer-Array
  5. Diff gegen den vorherigen Frame
  6. Minimale ANSI-Patches werden als single buffered write rausgeschrieben

Primitive: ink-root, ink-box, ink-text, ink-raw-ansi. Version 2.1.x enthält laut DeepWiki-Mirrors 130+ React-Komponenten.


11. Memory & Todos

TodoWrite ist bewusst nicht in-process persistiert — es schreibt einen JSON-File unter ~/.claude/todos/{session_id}.json. Der Persistenz-Pfad erlaubt Session-Resume und Inter-Session-Kontinuität.

Felder: id, content, status (pending/in_progress/completed), priority.

Die Re-Injection (siehe §7) macht den Todo-File zum De-facto-Arbeitsspeicher-Format. Zusätzlich gibt's MEMORY.md (User-Memory, cross-session, per Projekt) und die „Dream"-/Kairos-Features in neueren Builds, die Session-Summaries verdichtet ablegen.


12. Model-Routing

Claude Code ist in Wahrheit ein Multi-Modell-System:

Modell Einsatz
Sonnet 4.x/4.7 Default für den Haupt-Agent-Loop
Opus opt-in via --model opus; auto für Complex Debugging/Plan-Mode
Haiku Hochfrequente Background-Calls (siehe unten)

Haiku-Aufgaben

  • (a) Quota-Check beim Startup — ein 1-Token-Dummy-Request mit Text „quota", gelingt nur, wenn Budget da ist
  • (b) Topic-Detection — nach jedem User-Input (entscheidet, ob der Terminal-Title geupdatet werden muss)
  • (c) Session-Summarization — beim Resume
  • (d) Command-Injection-Detection — pre-Bash
  • (e) Auto-Compact-Fallback — wenn der Primär-Compactor teuer wird

Yuyz0112s Logs zeigen: all das läuft über beta.messages.create mit explizitem model: "claude-haiku-3.5".

Quota-Handling ist proaktiv: Die Haiku-Probe beim Start fängt 429-Fehler bevor der User die erste echte Query tippt; bei Budget-Exhaustion wird auf einen Reduced-Mode degradiert (kein Auto-Compact, kein Topic-Detection).


13. Bemerkenswerte Clever Tricks

Was technisch am interessantesten ist:

  1. Reminder-Injection statt History-Pollution — Der gesamte Steuerungskanal (Todos, File-Freshness, Plan-Mode-Hints) läuft über transiente <system-reminder>-Tags im User-Turn. Der Assistant-Teil der History bleibt unberührt — was kritisch ist, weil jede Assistant-Mutation KV-Cache invalidieren würde. Cache-Stability wird explizit priorisiert.
  2. Der 92%-Trigger vs. hartes Limit — Anstatt bei 100 % zu crashen, wird bei 92 % präventiv komprimiert. wU2 ist eine Insurance-Policy, kein Notausgang.
  3. h2A-Dual-Buffer mit User-Interjection — Agent-Frameworks die man sonst sieht (LangGraph, CrewAI) sind turn-based. Claude Codes User-Interjection mitten im Tool-Call ist architektonisch der Unterschied zwischen „Chat-Loop" und „Interactive Shell".
  4. Sub-Agent als Context-LaunderingI2A ist nicht primär für Parallelisierung da, sondern um „dreckige" Kontexte aus der Parent-History zu isolieren. Pattern stammt wohl aus Reinforcement-Learning-Tradition: Episoden sauber halten.
  5. LLM für Security — Die Haiku-basierte Command-Injection-Detection ist ein bemerkenswerter Bruch mit klassischer Security-Praxis (Regex-Blacklists). Anthropic vertraut einem Modell, Angriffsmuster zu erkennen, die Regex nicht erwischt.
  6. Der versteckte Quota-Ping — Mit einem einzigen „quota"-Token-Request beim Start wird das Budget getestet, bevor der User auch nur getippt hat. Billig und clever.
  7. yoga.wasm — Dass ein CLI-Tool einen Flexbox-Engine aus dem React-Native-Umfeld als WASM einbindet, um Terminal-Layout zu rendern, ist technisch elegant overkill — und erklärt, wie Ink so robust mit Resize-Events umgeht.
  8. Parallel-Tool-Policy ohne WritegW5 parallelisiert nur Read-Tools. Sobald ein Write kommt, wird serialisiert. Das macht Consistency trivial, ohne dass das Modell überhaupt darüber nachdenken muss.
  9. BatchTool wurde deprecated, weil das Modell selbst gelernt hat, mehrere tool_use-Blocks in einem Response-Turn zurückzugeben — das Harness brauchte irgendwann keinen expliziten Batch-Wrapper mehr. Modell-Training hat das Feature wegtrainiert.
  10. CLAUDE.md-Disclaimer — Der „may or may not be relevant"-Disclaimer ist subtile Instruktions-Entkopplung: Anthropic möchte, dass CLAUDE.md Kontext ist, nicht Befehl.

Kurzes Fazit

Das technisch Bemerkenswerte an Claude Code ist nicht eine einzelne Komponente, sondern die Konsequenz, mit der alles, was nicht der Loop ist, zu Harness degradiert wurde. nO ist 20 Zeilen. Der Rest — h2A, wU2, UH1, gW5, I2A, KN5, tU2, die Reminder-Injektion, die Haiku-Nebencalls — ist Environment-Engineering um einen minimalen, modellgetriebenen Kern herum. Die explizite Botschaft der Community-Analysen: Wer heute „Agents" baut und stattdessen in Rule-Trees und Prompt-Ketten denkt, hat das Grundpattern verfehlt.


14. Relevanz für das Mana-Monorepo

Direkte Ableitungen für laufende Initiativen:

  • services/mana-mcp (:3069) — Der Reminder-Injection-Mechanismus aus §7 ist direkt übertragbar: Tool-Results könnten nicht nur rohe JSON-Payloads zurückgeben, sondern transiente <system-reminder>-Blöcke mit Space-Context, Tier-Status oder stale-Data-Warnungen. Siehe docs/plans/mana-mcp-and-personas.md.
  • services/mana-ai Mission-Runner — Das nO/h2A-Pattern (single-threaded Master-Loop + Async-Steering-Bus) ist eine sauberere Alternative zu der cross-tick-Statemachine, die dort aktuell Gemini Deep Research orchestriert. Siehe project_gemini_deep_research-Memory.
  • Shared Tool-Registry (packages/mana-tool-registry) — Das Permission-Gateway (UH1) mit Whitelist-Matching ist ein brauchbares Mental-Model für die Tool-Authorization, die wir persona-scoped einführen müssen.
  • Compression-Pattern (wU2) — Für lange Sync-Logs oder Missions-Historie mit

    50k Tokens sinnvoll: präventives Komprimieren bei 92 % Budget-Auslastung nach festem Schema (Goal / Decisions / Files / Progress).


15. Quellen


Verwandte Berichte in diesem Repo: