The terminal experience. How Claude Code renders markdown, handles input, and creates a polished developer UX.
โ Back to Main | โ Authentication
graph TB
subgraph "CLI Core"
INPUT["Input Handler<br/>(line reader + completion)"]
COMMANDS["Command Dispatcher<br/>(slash commands)"]
STREAM["Stream Display<br/>(real-time token rendering)"]
TOOLS_UI["Tool Call UI<br/>(box borders, spinner)"]
PERM_UI["Permission Prompter<br/>(Y/N for escalation)"]
end
subgraph "Terminal Renderer"
MD["Markdown Parser"]
SYNTAX["Syntax Highlighter"]
SPINNER["Spinner Widget"]
TABLE["Table Formatter"]
end
subgraph "External"
RT["Runtime Core"]
TERM["Terminal Output"]
end
INPUT --> COMMANDS
INPUT --> RT
RT --> STREAM
STREAM --> MD
MD --> SYNTAX
MD --> TABLE
TOOLS_UI --> SPINNER
MD --> TERM
SYNTAX --> TERM
SPINNER --> TERM
flowchart TD
START(["๐ข Start REPL"]) --> INIT["Initialize:<br/>- Load config<br/>- Build system prompt<br/>- Connect MCP servers<br/>- Show welcome message"]
INIT --> PROMPT["Show prompt: >"]
PROMPT --> READ["Read input<br/>(rustyline with history)"]
READ --> CHECK{"Input type?"}
CHECK -->|"Empty"| PROMPT
CHECK -->|"Starts with /"| SLASH["Execute slash command"]
CHECK -->|"Regular text"| SEND["Send to conversation loop"]
SLASH --> PROMPT
SEND --> STREAM_DISPLAY["Stream & display response"]
STREAM_DISPLAY --> PROMPT
CHECK -->|"Ctrl+C"| EXIT(["๐ด Exit"])
CHECK -->|"Ctrl+D (EOF)"| EXIT
graph LR
subgraph "Input Handling"
RL["Rustyline Library"]
HIST["Command History<br/>(~/.claude/history)"]
COMP["Tab Completion<br/>(slash commands)"]
MULTI["Multi-line Input<br/>(Shift+Enter)"]
end
RL --> HIST
RL --> COMP
RL --> MULTI
| Feature | How |
|---|---|
| History | Up/Down arrows cycle through previous inputs |
| Completion | Tab completes slash commands (/com โ /compact) |
| Multi-line | Shift+Enter adds a newline without submitting |
| Editing | Emacs-style keybindings (Ctrl+A, Ctrl+E, etc.) |
flowchart TD
INPUT["Streaming text<br/>from assistant"] --> STATE["MarkdownStreamState"]
STATE --> DETECT{"Detect block type"}
DETECT -->|"```language"| CODE["Code Block"]
CODE --> SYNTAX["Apply syntax highlighting<br/>(language-aware)"]
SYNTAX --> BOX["Draw box borders<br/>โโโโโโโโโโโโ<br/>โ code โ<br/>โโโโโโโโโโโโ"]
DETECT -->|"# Heading"| HEADING["Bold + Color"]
DETECT -->|"- item"| LIST["Bullet formatting"]
DETECT -->|"|col|col|"| TABLE["Table alignment<br/>& borders"]
DETECT -->|"Regular text"| WRAP["Word wrap to<br/>terminal width"]
BOX --> OUTPUT["Terminal Output"]
HEADING --> OUTPUT
LIST --> OUTPUT
TABLE --> OUTPUT
WRAP --> OUTPUT
When the assistant calls a tool, it's displayed with clear visual boundaries:
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ ๐ง read_file โ
โ file_path: "src/main.rs" โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โ Reading file...
โญโ Result โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ fn main() { โ
โ println!("Hello, world!"); โ
โ } โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
graph TD
OUTPUT{"--output-format?"}
OUTPUT -->|"text (default)"| TEXT["Rich terminal output<br/>Markdown, colors, borders"]
OUTPUT -->|"json"| JSON["Structured JSON<br/>One object per message"]
OUTPUT -->|"ndjson"| NDJSON["Newline-delimited JSON<br/>Stream-friendly"]
claw [OPTIONS] [PROMPT]
Options:
--model <MODEL> Model to use (opus/sonnet/haiku)
--permission-mode <MODE> ReadOnly/WorkspaceWrite/DangerFullAccess
--config <PATH> Custom config file
--output-format <FORMAT> text/json/ndjson
--resume <SESSION_ID> Resume a saved session
Subcommands:
init Initialize project configuration
login Authenticate via OAuth
logout Clear stored credentials
- Sandbox Execution โ โ How bash commands are isolated
- Slash Commands โ โ The full command registry