Skip to main content

Components & Rendering

How Claude Code renders its terminal UI — the React/Ink component architecture, key components, and theming.

Architecture

Claude Code uses React with Ink to render a rich terminal UI. Ink translates React components into terminal output using Yoga (flexbox layout engine).

Framework
React 19
Ink 6 — Terminal React Renderer
Layout
Yoga Layout Engine (Flexbox)
Output
Terminal Output (ANSI escape codes)
Components
App (Root)
REPL Screen
Message List
Prompt Input
Permission Dialogs
Spinners / Progress

Component Hierarchy

Root
App — state providers + theme
Shell
RootTUI → REPL Screen
REPL Children
Messages (scrollable list)
PromptInput (keyboard input)
StatusBar (model, tokens, cost)
Message Types
UserMessage
AssistantMessage
Assistant Blocks
Text (markdown)
ToolUse (invocation)
ToolResult (output)
Overlays
PermissionRequest (dialog)
Activity Spinner
Toast Notifications

Key Components

App (src/components/App.tsx)

Root component that wraps the entire application with providers:

  • AppStateProvider — central state store
  • NotificationProvider — toast messages
  • ModalProvider — dialog management
  • Theme configuration

REPL Screen (src/screens/REPL.tsx)

The main interactive screen:

  • Manages the conversation view
  • Handles keyboard input routing
  • Coordinates between message display and input

Messages

Virtual scrolling for large conversations:

  • Only renders visible messages
  • Smooth scrolling through history
  • Supports message folding/expansion

PromptInput

The text input area at the bottom:

  • Multi-line input with history
  • Tab completion for commands and file paths
  • Keyboard shortcuts (Ctrl+C to cancel, etc.)
  • Prompt suggestions

PermissionRequest

The approval dialog shown when a tool needs permission:

  • Shows tool name and input summary
  • Options: Allow, Deny, Always Allow
  • Animated border for visibility

Tool-Specific Renderers

Each tool has custom rendering:

  • FileEdit — shows a diff view with syntax highlighting
  • Bash — shows command and output with truncation
  • Read — shows file content with line numbers
  • Agent — shows agent status and progress

Theming

Claude Code supports light and dark themes:

// Theme detection
const colorMode = {
defaultMode: 'dark',
respectPrefersColorScheme: true, // Follows terminal theme
}

Colors

  • Dark theme — dark backgrounds, light text, syntax highlighting via Dracula palette
  • Light theme — light backgrounds, dark text, syntax highlighting via GitHub palette
  • Terminal capability detection — graceful degradation for terminals with limited color support

Rendering Pipeline

💾
AppState Update
⚙️
React Reconciler
🧩
Ink Renderer
📐
Yoga Layout — compute positions
🔄
Cell-level Diff
📤
ANSI Escape Codes → Terminal Output

Cell-Level Diffing

Ink maintains a virtual terminal buffer and only writes the cells that changed — similar to how React DOM does virtual DOM diffing, but for terminal characters.

Yoga Layout

Components use flexbox-style layout:

<Box flexDirection="column" padding={1}>
<Box flexDirection="row">
<Text bold>Claude</Text>
<Text> is thinking...</Text>
</Box>
<Spinner type="dots" />
</Box>

Statistics

MetricCount
React components150+
Custom hooks100+
Ink custom elements96 files in src/ink/
ScreensREPL (main), plus modal overlays

Key Source Files

FilePurpose
src/components/App.tsxRoot component
src/screens/REPL.tsxMain REPL screen
src/components/150+ components (389 files total)
src/hooks/React hooks (104 files)
src/ink/Custom Ink renderer extensions (96 files)