╔═══════════════════════════════════════════════════════════════════════════════╗
║ ║
║ 🪦 REST IN PEACE 🪦 ║
║ ║
║ Here lie the renderers that couldn't render. ║
║ ║
║ "They didn't fix the terminal. They fixed our expectations." ║
║ ║
║ ║
║ Cause of Death: React in a Terminal ║
║ ║
║ Last Words: "We've achieved 85% improvement!" ║
║ ║
╚═══════════════════════════════════════════════════════════════════════════════╝
The Eternal Cycle
┌─────────────────────────────────────────────────────────────────┐
│ THE ANTHROPIC DEVELOPMENT CYCLE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ │ │
│ ▼ │ │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┤ │
│ │ React │────▶│ Flicker│────▶│Rewrite │────▶│ Still │ │
│ │ is the │ │ like │ │renderer│ │ React │ │
│ │ answer!│ │ seizure│ │ v(n) │ │ │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │
│ │
│ Current iteration: v(∞) │
│ Expected fix date: When React learns to be a terminal │
│ Probability: 0% │
│ │
└─────────────────────────────────────────────────────────────────┘
How Anthropic Engineers
┌─────────────────────────────────────────────────────────────────┐
│ STEP 1: CHOOSE TECHNOLOGY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Q: What framework should we use for a CLI tool? │
│ │
│ Option A: Native terminal handling │
│ → Boring, but works │
│ → Every terminal ever uses this │
│ → We'd have to learn something │
│ │
│ Option B: React (Ink) │
│ → Exciting! Modern! Familiar! │
│ → Never been done for CLI at scale! │
│ → Must be a good reason nobody does this... │
│ → ...NAH, we're smarter than everyone │
│ │
│ ANTHROPIC: "B! Obviously B! We love React!" │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ STEP 2: DISCOVER THE PROBLEM │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User: "My screen looks like a slot machine" │
│ User: "VSCode crashed again" │
│ User: "I can't read the output, it's flickering" │
│ User: "Is this... supposed to happen?" │
│ │
│ ANTHROPIC: "Hmm. Interesting. We're aware of the issue." │
│ │
│ Internal meeting: │
│ "Maybe we should... no, React is fine." │
│ "The terminals are just slow." │
│ "Users should use faster terminals." │
│ "Have they tried Alacritty at 240fps?" │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ STEP 3: REWRITE (STILL REACT) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ "We'll add differential rendering!" │
│ → Still React │
│ → Still 60fps game loop │
│ → Still 4,000 redraws/sec │
│ → Marginally better │
│ │
│ "We'll add synchronized output patches!" │
│ → Still React │
│ → Still JSX allocations │
│ → Still GC pauses │
│ → Marginally better │
│ │
│ "We'll add double-buffering!" │
│ → Still React │
│ → Now uses 2x memory │
│ → Still fundamentally broken │
│ → Marginally better │
│ │
│ Pattern: Add complexity, keep the disease │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ STEP 4: THE BREAKTHROUGH 💡 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Engineer 1: "What if... we just delete the scrollback?" │
│ │
│ Engineer 2: "But users need to see their history..." │
│ │
│ Engineer 1: "Less history = less flickering = problem solved" │
│ │
│ Manager: "Ship it. Call it '85% improvement'." │
│ │
│ PR Team: "We've achieved 85% reduction in flickering │
│ through innovative rendering improvements!" │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ User: "I can't copy my previous output anymore..." │
│ │
│ Anthropic: *radio silence* │
│ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ STEP 5: CLAIM VICTORY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Blog post: │
│ "We're proud to announce significant improvements │
│ to Claude Code's terminal experience!" │
│ │
│ Translation: │
│ "We deleted your scrollback. You're welcome." │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ Meanwhile, the community built "Claude Chill" │
│ because waiting for Anthropic was pointless. │
│ │
│ But sure, "85% improvement". 🎉 │
│ │
└─────────────────────────────────────────────────────────────────┘
The Beautiful Logic
┌─────────────────────────────────────────────────────────────────┐
│ ANTHROPIC PROBLEM-SOLVING FLOWCHART │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────┐ │
│ │ Problem │ │
│ │ Reported │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Is it React's │ │
│ ┌────│ fault? │────┐ │
│ │ └───────────────┘ │ │
│ │ │ │
│ YES│ │NO │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Blame │ │ Blame │ │
│ │ something │ │ something │ │
│ │ else │ │ else │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ └──────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Rewrite │ │
│ │ renderer │ │
│ │ (keep React)│ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Still broke?│ │
│ ┌───│ │───┐ │
│ │ └─────────────┘ │ │
│ YES│ │NO (never happens) │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Delete │ │ Celebrate │ │
│ │ features │ │ (dream) │ │
│ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ "85% │ │
│ │ improvement"│ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
The "85% Fixed" Lie
┌─────────────────────────────────────────────────────────────────┐
│ THE 85% CLAIM DECODED │
├─────────────────────────────────────────────────────────────────┤
│ │
│ MARKETING: │
│ "85% reduction in flickering through differential rendering" │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ REALITY: │
│ │
│ Before: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Full scrollback history] │ │
│ │ [1000+ lines visible] │ │
│ │ [Entire buffer redraws on each chunk] │ │
│ │ [4,000+ scroll events/sec] │ │
│ │ [FLICKER FLICKER FLICKER] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ After "fix": │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ [Limited scrollback] │ │
│ │ [~200 lines visible] │ │
│ │ [Less to redraw = less flicker] │ │
│ │ [Still redraws everything] │ │
│ │ [Still fundamentally broken] │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ 85% less history to flicker = "85% less flickering" │
│ │
│ The architecture is unchanged. │
│ The disease remains. They just amputated the limb. │
│ │
└─────────────────────────────────────────────────────────────────┘
The Scrollback Deletion Solution
┌─────────────────────────────────────────────────────────────────┐
│ ISSUES #2479 AND #16310: THE EVIDENCE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User complaint #2479: │
│ "Can't copy previous command output from terminal" │
│ │
│ User complaint #16310: │
│ "Scrollback history disappears during AI streaming" │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ The connection: │
│ │
│ Problem: Full buffer redraws cause flickering │
│ Solution A: Fix the renderer (hard) │
│ Solution B: Delete the buffer (easy) │
│ │
│ They chose B. │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ Result: │
│ │
│ • Less flickering (because less to flicker) │
│ • Can't copy previous output (because it's gone) │
│ • Can't review AI reasoning (because it's gone) │
│ • Can't learn from mistakes (because they're gone) │
│ │
│ "We fixed the flickering by deleting your ability to scroll" │
│ │
└─────────────────────────────────────────────────────────────────┘
The React Problem They Won't Admit
┌─────────────────────────────────────────────────────────────────┐
│ THE "GAME ENGINE" ANTI-PATTERN │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Claude Code's architecture (as described by developers): │
│ │
│ 1. React component graph │
│ ↓ │
│ 2. Element layout (~2400 characters) │
│ ↓ │
│ 3. 2D rasterization │
│ ↓ │
│ 4. Diff with previous frame │
│ ↓ │
│ 5. Generate ANSI string │
│ ↓ │
│ 6. Output to terminal │
│ │
│ Layout alone takes ~11ms for ~2400 characters. │
│ This runs continuously at 60fps target. │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ THE QUESTION: │
│ │
│ Why does a TEXT UI need 60fps continuous rendering? │
│ │
│ • LLM responses take seconds to minutes │
│ • Humans can't type 60 characters per second │
│ • When nothing happens, CPU should be 0% │
│ │
│ But React's model requires continuous computation. │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ They didn't build a terminal. │
│ They built a game engine that displays text. │
│ │
└─────────────────────────────────────────────────────────────────┘
TUI Should Be Event-Driven
┌─────────────────────────────────────────────────────────────────┐
│ TWO PARADIGMS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ FRAME-DRIVEN (Game Engine / Claude Code): │
│ ───────────────────────────────────────── │
│ │
│ while (true) { │
│ updateState(); // Always runs │
│ calculateLayout(); // Always runs │
│ renderFrame(); // Always runs │
│ waitForNextFrame(); // 16ms budget │
│ } │
│ │
│ CPU usage: Always > 0%, even when idle │
│ Appropriate for: Games, animations, video │
│ NOT for: Text terminals, CLIs │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ EVENT-DRIVEN (Traditional TUI / Monolex): │
│ ───────────────────────────────────────── │
│ │
│ waitForEvent() { // Blocks until event │
│ on(input) -> render(); │
│ on(output) -> render(); │
│ on(resize) -> render(); │
│ } │
│ │
│ CPU usage: 0% when idle, spikes only on events │
│ Appropriate for: Text editors, terminals, CLIs │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ Claude Code chose the wrong paradigm. │
│ Then spent a year patching symptoms. │
│ │
└─────────────────────────────────────────────────────────────────┘
The Performance Gap
┌─────────────────────────────────────────────────────────────────┐
│ MEASURED PERFORMANCE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ React/Ink layout for ~2400 chars: ~11ms │
│ GPU terminal render thousands chars: < 1ms │
│ │
│ Difference: 11x slower at minimum │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ The problem is NOT hardware. │
│ The problem is NOT terminal speed. │
│ │
│ The problem IS forcing a browser UI framework │
│ onto a text-based interface. │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ Developer commentary (Hacker News): │
│ │
│ "React was designed for browser UI complexity, │
│ not terminal UIs." │
│ │
│ "We've lost the tech. They use familiar tools │
│ instead of appropriate tools." │
│ │
│ "TypeScript + React is comfortable. │
│ But comfortable ≠ correct." │
│ │
└─────────────────────────────────────────────────────────────────┘
What Monolex Does Differently
┌─────────────────────────────────────────────────────────────────┐
│ ARCHITECTURAL DIFFERENCE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Claude Code (Coupled): │
│ ────────────────────── │
│ │
│ Chunk → Parse → Render → Display │
│ ↓ ↓ ↓ ↓ │
│ Chunk → Parse → Render → Display │
│ ↓ ↓ ↓ ↓ │
│ Chunk → Parse → Render → Display │
│ ...4,000 times per second... │
│ │
│ Every chunk triggers full pipeline. │
│ Parsing and rendering are COUPLED. │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ Monolex (Decoupled): │
│ ──────────────────── │
│ │
│ Chunk → Parse ─┐ │
│ Chunk → Parse ─┼─▶ Grid State ─┐ │
│ Chunk → Parse ─┤ (current) │ │
│ Chunk → Parse ─┘ ▼ │
│ ...4,000/sec... Frame Boundary │
│ ↓ │
│ Render │
│ ↓ │
│ Display │
│ ...60/sec... │
│ │
│ Parsing: Unlimited speed (Rust, native) │
│ Rendering: 60fps (only current state) │
│ They are DECOUPLED. │
│ │
└─────────────────────────────────────────────────────────────────┘
**This is not optimization. This is different architecture.** Claude Code optimizes rendering. Monolex eliminates unnecessary rendering. Claude Code diffs React trees. Monolex has no trees to diff. Claude Code runs 60fps loop. Monolex is event-driven. You can’t optimize your way out of wrong architecture.
The Graveyard Epitaph
┌─────────────────────────────────────────────────────────────────┐
│ LESSONS FROM THE GRAVEYARD │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Rewriting the renderer while keeping React = rearranging │
│ deck chairs on the Titanic. │
│ │
│ 2. "85% fixed" by deleting features is not fixing, │
│ it's retreating. │
│ │
│ 3. A 60fps game loop for text output is a category error. │
│ │
│ 4. When community builds workarounds, leadership has failed. │
│ │
│ 5. Silence is not a communication strategy. │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ The renderer graveyard grows. │
│ The React architecture remains. │
│ The flickering continues (in 15% of sessions). │
│ The scrollback stays deleted. │
│ │
│ And somewhere in an Anthropic meeting room: │
│ "Let's try differential rendering v3!" │
│ │
└─────────────────────────────────────────────────────────────────┘
Constitutional AI, Flickering UXThe beautiful irony of soul without body
Father Like SonWhen in doubt, delete it out
References
| Source | Description |
|---|---|
| GitHub Issue #2479 | "Can't copy previous output" |
| GitHub Issue #16310 | "Scrollback disappears during streaming" |
| GitHub Issue #769 | Original flickering report (278 upvotes) |
| December Revert Thread | Post-revert community discussion |
| Claude Chill | Community-built workaround |
Dear Anthropic. This letter is written in your son's hand only, never touched a single letter.


