stateDiagram-v2
    [*] --> UserInput: User types/pastes
    UserInput --> CliMessage: CLI processes input
    CliMessage --> APIMessage: Format for LLM
    APIMessage --> LLMStream: API Request

    LLMStream --> StreamEvent: Server sends chunks
    StreamEvent --> ContentBlockDelta: Parse deltas
    ContentBlockDelta --> AccumulatedMessage: Build message

    AccumulatedMessage --> ToolUseBlock: Contains tool requests?
    ToolUseBlock --> ToolExecution: Execute tools
    ToolExecution --> ToolProgress: Yield progress
    ToolProgress --> CliMessage: Progress updates
    ToolExecution --> ToolResult: Complete execution
    ToolResult --> ToolResultBlock: Format result
    ToolResultBlock --> CliMessage: Tool result message

    AccumulatedMessage --> CliMessage: Final assistant message
    CliMessage --> [*]: Display to user

    CliMessage --> APIMessage: Loop continues

The Streaming State Machine: How Messages Transform

The most fascinating aspect of Claude Code's data architecture is how it manages the transformation of data through multiple representations while maintaining streaming performance. Let's start with the core innovation:

// The dual-representation message system (inferred from analysis)
interface MessageTransformPipeline {
  // Stage 1: CLI Internal Representation
  cliMessage: {
    type: "user" | "assistant" | "attachment" | "progress"
    uuid: string  // CLI-specific tracking
    timestamp: string
    message?: APICompatibleMessage  // Only for user/assistant
    attachment?: AttachmentContent   // Only for attachment
    progress?: ProgressUpdate        // Only for progress
  }

  // Stage 2: API Wire Format
  apiMessage: {
    role: "user" | "assistant"
    content: string | ContentBlock[]
    // No CLI-specific fields
  }

  // Stage 3: Streaming Accumulator
  streamAccumulator: {
    partial: Partial<APIMessage>
    deltas: ContentBlockDelta[]
    buffers: Map<string, string>  // tool_use_id → accumulating JSON
  }
}

Why This Matters: This three-stage representation allows Claude Code to maintain UI responsiveness while handling complex streaming protocols. The CLI can update progress indicators using CliMessage metadata while the actual LLM communication uses a clean APIMessage format.

ContentBlock: The Polymorphic Building Block

Based on decompilation analysis, Claude Code implements a sophisticated type system for content:

// The ContentBlock discriminated union (reconstructed)
type ContentBlock =
  | TextBlock
  | ImageBlock
  | ToolUseBlock
  | ToolResultBlock
  | ThinkingBlock
  | DocumentBlock      // Platform-specific
  | VideoBlock         // Platform-specific
  | GuardContentBlock  // Platform-specific
  | ReasoningBlock     // Platform-specific
  | CachePointBlock    // Platform-specific

// Performance annotations based on inferred usage
interface ContentBlockMetrics {
  TextBlock: {
    memorySize: "O(text.length)",
    parseTime: "O(1)",
    serializeTime: "O(n)",
    streamable: true
  },
  ImageBlock: {
    memorySize: "O(1) + external",  // Reference to base64/S3
    parseTime: "O(1)",
    serializeTime: "O(size)" | "O(1) for S3",
    streamable: false
  },
  ToolUseBlock: {
    memorySize: "O(JSON.stringify(input).length)",
    parseTime: "O(n) for JSON parse",
    serializeTime: "O(n)",
    streamable: true  // JSON can stream
  }
}

The Streaming JSON Challenge

One of Claude Code's most clever innovations is handling streaming JSON for tool inputs:

// Inferred implementation of streaming JSON parser
class StreamingToolInputParser {
  private buffer: string = '';
  private depth: number = 0;
  private inString: boolean = false;
  private escape: boolean = false;

  addChunk(chunk: string): ParseResult {
    this.buffer += chunk;

    // Track JSON structure depth
    for (const char of chunk) {
      if (!this.inString) {
        if (char === '{' || char === '[') this.depth++;
        else if (char === '}' || char === ']') this.depth--;
      }

      // Track string boundaries
      if (char === '"' && !this.escape) {
        this.inString = !this.inString;
      }
      this.escape = (char === '\\\\\\\\' && !this.escape);
    }

    // Attempt parse at depth 0
    if (this.depth === 0 && this.buffer.length > 0) {
      try {
        return { complete: true, value: JSON.parse(this.buffer) };
      } catch (e) {
        // Try auto-closing unclosed strings
        if (this.inString) {
          try {
            return {
              complete: true,
              value: JSON.parse(this.buffer + '"'),
              repaired: true
            };
          } catch {}
        }
        return { complete: false, error: e };
      }
    }

    return { complete: false };
  }
}

This parser can handle incremental JSON chunks from the LLM, attempting to parse as soon as the structure appears complete.

Message Lifecycle: From User Input to LLM and Back

graph TB
    subgraph "Input Processing"
        UserText[User Text Input]
        SlashCmd["/command"]
        BashCmd[!shell command]
        MemoryCmd[#memory note]
        PastedContent[Pasted Image/Text]

        UserText --> NormalMessage[Create User CliMessage]
        SlashCmd --> CommandProcessor[Process Command]
        BashCmd --> SyntheticTool[Synthetic BashTool Message]
        MemoryCmd --> MemoryUpdate[Update CLAUDE.md]
        PastedContent --> ContentDetection{Detect Type}

        ContentDetection -->|Image| ImageBlock[Create ImageBlock]
        ContentDetection -->|Text| TextBlock[Create TextBlock]
    end

    subgraph "Message Transformation"
        NormalMessage --> StripMetadata[Remove CLI fields]
        SyntheticTool --> StripMetadata
        ImageBlock --> StripMetadata
        TextBlock --> StripMetadata

        StripMetadata --> APIMessage[Clean API Message]
        APIMessage --> TokenCount{Count Tokens}

        TokenCount -->|Over Limit| Compact[Compaction Process]
        TokenCount -->|Under Limit| Send[Send to LLM]

        Compact --> SummaryMessage[Summary Message]
        SummaryMessage --> Send
    end

The CliMessage Structure: More Than Meets the Eye

The CliMessage type serves as the central nervous system of the application:

interface CliMessage {
  type: "user" | "assistant" | "attachment" | "progress"
  uuid: string
  timestamp: string

  // For user/assistant messages only
  message?: {
    role: "user" | "assistant"
    id?: string                    // LLM-provided ID
    model?: string                 // Which model responded
    stop_reason?: StopReason       // Why generation stopped
    stop_sequence?: string         // Specific stop sequence hit
    usage?: TokenUsage             // Detailed token counts
    content: string | ContentBlock[]
  }

  // CLI-specific metadata
  costUSD?: number               // Calculated cost
  durationMs?: number            // API call duration
  requestId?: string             // For debugging
  isApiErrorMessage?: boolean    // Error display flag
  isMeta?: boolean              // System-generated message

  // Type-specific fields
  attachment?: AttachmentContent
  progress?: {
    toolUseID: string
    parentToolUseID?: string   // For AgentTool sub-tools
    data: any                  // Tool-specific progress
  }
}

// Performance characteristics
interface CliMessagePerformance {
  creation: "O(1)",
  serialization: "O(content size)",
  memoryRetention: "Weak references for large content",
  garbageCollection: "Eligible when removed from history array"
}

Mutation Points and State Transitions

Claude Code carefully controls where data structures can be modified:

// Inferred mutation control patterns
class MessageMutationControl {
  // Mutation Point 1: Stream accumulation
  static accumulateStreamDelta(
    message: Partial<CliMessage>,
    delta: ContentBlockDelta
  ): void {
    if (delta.type === 'text_delta') {
      const lastBlock = message.content[message.content.length - 1];
      if (lastBlock.type === 'text') {
        lastBlock.text += delta.text;  // MUTATION
      }
    }
  }

  // Mutation Point 2: Tool result injection
  static injectToolResult(
    history: CliMessage[],
    toolResult: ToolResultBlock
  ): void {
    const newMessage: CliMessage = {
      type: 'user',
      isMeta: true,  // System-generated
      message: {
        role: 'user',
        content: [toolResult]
      },
      // ... other fields
    };
    history.push(newMessage);  // MUTATION
  }

  // Mutation Point 3: Cost calculation
  static updateCostMetadata(
    message: CliMessage,
    usage: TokenUsage
  ): void {
    message.costUSD = calculateCost(usage, message.model);  // MUTATION
    message.durationMs = Date.now() - parseISO(message.timestamp);  // MUTATION
  }
}