# 12. Data Flow Walkthrough > Tracing a single user request from keystroke to rendered response -- end to end. --- ## The Complete Flow This diagram traces exactly what happens when a user types a prompt and presses Enter. ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#4a9eff', 'primaryBorderColor': '#4a9eff'}}}%% flowchart TD TYPE["User types in terminal"]:::input PASTE["Paste: text, image, file"]:::input VOICE["Voice input via STT"]:::input IDE_IN["IDE sends prompt"]:::input SDK_IN["SDK submitMessage"]:::input PARSE["Parse input
slash commands, @mentions"]:::process SLASH{"Slash
command?"}:::decision LOCAL["Execute locally
clear, compact, model"]:::process ATTACH["Build attachments
images, PDFs, CLAUDE.md"]:::process UMSG["Create UserMessage"]:::process SYS["Build system prompt
tool descriptions +
user rules + CLAUDE.md"]:::context GIT["Inject git context
branch, commits, status"]:::context USR["Inject user context
CLAUDE.md, date"]:::context CMP["Run compaction pipeline"]:::context CACHE["Apply cache_control
prompt cache breakpoints"]:::context BUILD["Build API request
model, betas, effort,
task_budget, thinking"]:::api STREAM["Stream SSE response
from Anthropic API"]:::api RETRY["withRetry wrapper
429 backoff, 529 fallback"]:::api THINK["Thinking blocks"]:::response TEXT["Text blocks"]:::response TOOL_USE["tool_use blocks"]:::response VALIDATE["Validate input"]:::toolexec PERMS["Check permissions"]:::toolexec EXEC["Execute tool"]:::toolexec RESULT["Map to tool_result"]:::toolexec FEEDBACK["Push to messages
LOOP BACK"]:::feedback RENDER["Render in terminal"]:::output TRANSCRIPT["Persist transcript"]:::output SDK_OUT["Yield SDK events"]:::output COST["Track cost + usage"]:::output TYPE --> PARSE PASTE --> PARSE VOICE --> PARSE IDE_IN --> PARSE SDK_IN --> PARSE PARSE --> SLASH SLASH -->|"yes"| LOCAL --> RENDER SLASH -->|"no"| ATTACH --> UMSG UMSG --> SYS --> GIT --> USR --> CMP --> CACHE CACHE --> BUILD --> STREAM STREAM --> RETRY --> STREAM STREAM --> THINK --> RENDER STREAM --> TEXT --> RENDER STREAM --> TOOL_USE TOOL_USE --> VALIDATE --> PERMS --> EXEC --> RESULT --> FEEDBACK FEEDBACK ==>|"loop back to
compaction"| CMP TEXT -->|"end_turn"| TRANSCRIPT --> SDK_OUT --> COST classDef input fill:#0d4f4f,stroke:#17a2b8,color:#e0e0e0,stroke-width:2px classDef process fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px classDef decision fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px classDef context fill:#2d1b4e,stroke:#6f42c1,color:#e0e0e0,stroke-width:2px classDef api fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px classDef response fill:#3d2b00,stroke:#fd7e14,color:#e0e0e0,stroke-width:2px classDef toolexec fill:#1a1a4e,stroke:#6f42c1,color:#e0e0e0,stroke-width:2px classDef feedback fill:#4a1a1a,stroke:#dc3545,color:#e0e0e0,stroke-width:3px classDef output fill:#333,stroke:#888,color:#e0e0e0,stroke-width:1px ``` --- ## Phase by Phase ### Phase 1: Input Capture The user's input can arrive from **5 different sources**, all converging into `processUserInput()`: ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#17a2b8', 'primaryBorderColor': '#17a2b8'}}}%% flowchart LR subgraph Sources["Input Sources"] KB["Keyboard input
Direct typing in terminal"] PASTE["Clipboard paste
Text, images, files"] VOICE["Voice
STT transcription"] IDE["IDE Bridge
Prompt from editor"] SDK["SDK
Programmatic submitMessage"] end PUI["processUserInput
Parse slash commands
Resolve @mentions
Build attachments"]:::process subgraph Output["Parse Result"] MSGS["messages array"] SHOULD["shouldQuery boolean"] end Sources --> PUI --> Output classDef process fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px ``` Slash commands (`/clear`, `/compact`, `/model`) are intercepted here and handled locally without an API call. Everything else proceeds to the model. ### Phase 2: Context Assembly Before sending to the API, the system assembles context from multiple sources: ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#6f42c1', 'primaryBorderColor': '#6f42c1'}}}%% flowchart TD subgraph SystemPrompt["System Prompt Assembly"] DEFAULT["Default prompt
Claude Code identity"] TOOL_DESC["Tool descriptions
42+ tool schemas"] SECTIONS["System prompt sections
Cached or volatile"] end subgraph UserContext["User Context"] CLAUDE_MD["CLAUDE.md files
Project instructions"] DATE["Current date"] end subgraph SystemContext["System Context"] GIT_STATUS["Git snapshot
Branch, status, log"] end subgraph Compaction["Compaction Pipeline"] SNIP["Snip compact"] MICRO["Micro compact"] AUTO["Auto compact"] COLLAPSE["Context collapse"] end SystemPrompt --> FINAL["Final API request"]:::api UserContext --> FINAL SystemContext --> FINAL Compaction --> FINAL classDef api fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px ``` ### Phase 3: API Call and Streaming The request goes through `claude.ts` with retry logic: ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#28a745', 'primaryBorderColor': '#28a745'}}}%% flowchart LR REQ["API Request
messages + system + tools"]:::req STREAM["SSE Stream"]:::stream subgraph Events["Stream Events in Order"] E1["message_start
model, id, usage"] E2["content_block_start
type + index"] E3["content_block_delta
incremental text/tool JSON"] E4["content_block_stop"] E5["message_delta
stop_reason + final usage"] E6["message_stop"] end REQ --> STREAM --> Events classDef req fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px classDef stream fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px ``` Each content block is one of three types: **thinking** (internal reasoning), **text** (user-facing response), or **tool_use** (triggers tool execution). ### Phase 4: Tool Execution Loop When the model responds with `tool_use`, the agentic loop kicks in: ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#e83e8c', 'primaryBorderColor': '#e83e8c'}}}%% flowchart TD TOOL_USE["Model returns tool_use blocks"]:::start PAR{"Multiple tools?
isConcurrencySafe?"}:::check PARALLEL["Execute in parallel
Read-only tools"]:::exec SEQUENTIAL["Execute sequentially
Write tools"]:::exec VALIDATE["Zod schema validation"]:::step HOOKS_PRE["PreToolUse hooks"]:::step PERM_CHECK["Permission check chain
deny - allow - tool -
hooks - classifier - dialog"]:::step EXECUTE["tool.call(input, context)"]:::step HOOKS_POST["PostToolUse hooks"]:::step MAP_RESULT["Map to tool_result message"]:::step INJECT["Inject CLAUDE.md attachments
for newly-discovered dirs"]:::step PUSH["Push tool_results to messages
Continue loop"]:::feedback TOOL_USE --> PAR PAR -->|"yes"| PARALLEL PAR -->|"no"| SEQUENTIAL PARALLEL --> VALIDATE SEQUENTIAL --> VALIDATE VALIDATE --> HOOKS_PRE --> PERM_CHECK --> EXECUTE --> HOOKS_POST --> MAP_RESULT --> INJECT --> PUSH PUSH ==>|"Back to
compaction"| TOOL_USE classDef start fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px classDef check fill:#2d2d0d,stroke:#ffc107,color:#e0e0e0,stroke-width:2px classDef exec fill:#0d4f4f,stroke:#17a2b8,color:#e0e0e0,stroke-width:2px classDef step fill:#1b3a1b,stroke:#28a745,color:#e0e0e0,stroke-width:2px classDef feedback fill:#4a1a1a,stroke:#dc3545,color:#e0e0e0,stroke-width:3px ``` The loop continues until the model returns `stop_reason: end_turn`, hits `max_turns`, or is cancelled. ### Phase 5: Response Rendering The final response is rendered and persisted: ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#fd7e14', 'primaryBorderColor': '#fd7e14'}}}%% flowchart LR RESPONSE["Model final response
stop_reason: end_turn"]:::input subgraph Rendering["Terminal Rendering"] MD["Markdown rendering
via marked library"] SYNTAX["Syntax highlighting
for code blocks"] DIFF["Diff rendering
for file changes"] end subgraph Persistence["Persistence"] TRANSCRIPT["recordTranscript
Persist to disk"] USAGE["Accumulate usage
input + output tokens"] COST["Track cost
per-model pricing"] end subgraph SDK_Events["SDK Events"] MSG["SDKMessage stream
Normalized events"] RESULT_E["Result event
total_cost, usage, duration"] end RESPONSE --> Rendering RESPONSE --> Persistence RESPONSE --> SDK_Events classDef input fill:#1a2d4a,stroke:#4a9eff,color:#e0e0e0,stroke-width:2px ``` --- ## A Concrete Example Let's trace what happens when a user types: `fix the bug in utils.ts` ```mermaid %%{init: {'theme': 'dark', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#e0e0e0', 'lineColor': '#4a9eff', 'actorTextColor': '#e0e0e0', 'actorBorder': '#4a9eff', 'signalColor': '#4a9eff', 'noteBkgColor': '#16213e', 'noteTextColor': '#e0e0e0', 'activationBkgColor': '#2d1b4e', 'activationBorderColor': '#e83e8c'}}}%% sequenceDiagram participant U as User participant R as REPL.tsx participant QE as QueryEngine participant Q as query.ts participant C as claude.ts participant T as Tools U->>R: Types "fix the bug in utils.ts" R->>QE: submitMessage(prompt) Note over QE: Not a slash command, proceed QE->>QE: Persist transcript QE->>Q: query(messages, systemPrompt, tools) Note over Q: Turn 1 - Model reads code Q->>Q: Run compaction pipeline Q->>C: queryModel(messages) C-->>Q: tool_use: FileRead("utils.ts") Q->>T: Execute FileRead T-->>Q: File contents Note over Q: Turn 2 - Model analyzes Q->>C: queryModel(messages + file contents) C-->>Q: tool_use: Grep("error pattern") Q->>T: Execute Grep T-->>Q: Search results Note over Q: Turn 3 - Model fixes Q->>C: queryModel(messages + grep results) C-->>Q: tool_use: FileEdit("utils.ts", patch) Note over T: Permission check! T->>U: Allow FileEdit? (Y/n/always) U->>T: Y T-->>Q: Edit applied Note over Q: Turn 4 - Model confirms Q->>C: queryModel(messages + edit result) C-->>Q: text: "Fixed the bug" + end_turn Q-->>QE: Terminal result QE->>QE: Record transcript, track usage QE-->>R: Render response R->>U: Display formatted answer ``` This shows the typical pattern: **read first, analyze, then write** -- with permission checks only on the write operation. --- ## Key Takeaways 1. **Multiple entry points, single pipeline**: Whether input comes from keyboard, IDE, or SDK, it all converges into the same `processUserInput -> query -> claude.ts` pipeline. 2. **Compaction runs every turn**: The 5-stage compaction pipeline runs *before every single API call*, not just when limits are hit. 3. **Tools loop back**: Tool results are pushed to messages, and the entire pipeline (including compaction) runs again. This is the "agentic" part -- the model keeps going until it's done. 4. **Permissions only interrupt writes**: Read-only tools (FileRead, Grep, Glob) in default mode flow through silently. Only write operations (FileEdit, Bash, FileWrite) trigger permission dialogs. 5. **Everything is streamed**: From SSE events to async generators to React state updates, nothing blocks waiting for a full response. The user sees tokens as they arrive. --- **Previous:** [<- MCP Deep Dive](./11-mcp-deep-dive.md)