Claude Code Is a Game Engine for Text: How DX Bloat Consumed the Terminal
Matthias Bigl

Matthias Bigl

34 views

Claude Code Is a Game Engine for Text: How DX Bloat Consumed the Terminal

When your terminal app needs scene graphs, frame budgets, and more RAM than VS Code, "developer experience" has become a trap

The Tweet That Broke Engineering Twitter

On February 11, 2026, Anthropic engineer Thariq Shihipar posted a thread that sent the developer community into a spiral of disbelief. The revelation? Claude Code's terminal interface—black background, monospace font, zero graphics—isn't "just a TUI." It's closer to a small game engine:

"Most people's mental model of Claude Code is that 'it's just a TUI' but it should really be closer to 'a small game engine'. For each frame our pipeline constructs a scene graph with React → layouts elements → rasterizes them to a 2D screen → diffs that against the previous screen → finally uses the diff to generate ANSI sequences to draw. We have a ~16ms frame budget..."

A terminal application. Architected like it's rendering Doom. For text.

ThePrimeagen captured the community's reaction in a video that quickly gained traction: "I see nothing in Claude's output that needs a scene graph... No game engine would construct a scene graph and diff every frame [for text]." His disbelief resonated because it exposed something deeper than one team's architecture choices. It revealed how "developer experience"—that seductive promise of familiar tools and fast iteration—can accumulate into complexity so dense it becomes invisible.

This isn't a story about bad engineers. It's a case study in how reasonable decisions compound into unexpected architecture—and why the path of least resistance often leads somewhere nobody intended to go.

The Number That Should Embarrass Everyone

Here's the part that breaks brains: Claude Code's TUI sometimes consumes more RAM than VS Code.

VS Code. The Electron app. The one developers mock for memory bloat. The full-featured IDE with syntax highlighting, git integration, extensions, a debugger, and an integrated terminal.

A terminal application—text in, text out—occasionally spikes higher than the entire IDE hosting it. GitHub issues document the extremes: 11.6GB per process, 23GB after fourteen hours, and 120GB+ before OOM kill. Even typical usage sits at 200-400MB+ idle, with peaks reaching 746MB in community benchmarks.

For context, native TUIs built with Ratatui (Rust) or Bubbletea (Go) typically idle at 10-20MB. Claude Code carries 10-20x the baseline overhead before you factor in the leaks.

When your TUI needs more resources than the IDE people use to write TUIs, something has gone structurally wrong. Not wrong as in "engineers don't know better," but wrong as in "the abstraction is fighting the problem domain."

How React Ended Up in a Terminal

The path to "game engine for text" wasn't a single catastrophic decision. It was a series of logical ones, each following from the last:

  1. "We know React." The team has deep React expertise. Shared mental models. Fast onboarding. This is real value—familiarity reduces cognitive load and speeds iteration.

  2. "Ink exists." Ink is a mature React renderer for terminals, battle-tested at GitHub Copilot CLI, Gemini CLI, and now Claude Code. It provides component models, layouts, and state management out of the box.

  3. "We can share components." React in the terminal means potential code-sharing with web interfaces. One mental model across platforms.

  4. "React needs reconciliation." Virtual DOM diffing is how React works. You don't get to opt out.

  5. "Diffing needs a render loop." So you get frame budgets—16ms to maintain 60 FPS for... text.

  6. "Frame budgets need optimization." So you get scene graphs, rasterizers, packed TypedArrays, and a rendering pipeline that would be overkill for a spreadsheet.

Nobody chose to build a game engine. They chose React, and the rest accumulated like sediment. Each layer solved a problem created by the layer beneath it, until the architecture became a game of Jenga where removing any piece risks collapse.

The DX Trap

Developer Experience (DX) is the silent force behind many architecture decisions. Familiar tools reduce onboarding friction. Shared patterns ease maintenance. These benefits are genuine and measurable in sprint velocity and bug fix times.

But DX optimizes for today's comfort, not necessarily tomorrow's correctness. It treats "what we know" as equivalent to "what fits," and "fast to build" as synonymous with "right to build." The trap is that DX makes the complex path feel smooth. Engineers don't overengineer because they're careless—they overengineer because familiarity disguises the friction until it's baked into production.

DX JustificationHidden Cost
Team knows ReactScene graphs for character grids
Shared web components60 FPS render loops for static text
TypeScript everywhereGC pauses from JSX churn
Fast iterationMemory footprint exceeding native TUIs 10-20x
"We can always optimize later"400MB+ baseline before memory leaks

The real cost isn't visible in the sprint where you choose React. It appears six months later, when flickering bugs force a rewrite of the renderer, when GC pauses cause seconds of input lag on slower machines, when GitHub issues accumulate with titles like "Memory leak: 120GB RAM usage".

What Actually Went Wrong (And Right)

To be fair to the Claude Code team: they knew the tradeoffs and shipped fixes. Shihipar's thread wasn't defensive—it was transparent. He explained that the original rendering caused flickering and GC pauses severe enough to make the tool unusable on some hardware. The fixes were serious engineering:

  • Rewriting the renderer to diff at the cell level (~85% flicker reduction)

  • Converting screen buffers to packed TypedArrays to reduce GC pressure

  • Contributing synchronized output support upstream to VS Code's terminal and tmux

This is not incompetence. It's the opposite: talented engineers solving hard problems created by their own abstractions. They're now optimizing a rendering pipeline for a tool that prints text. The irony writes itself.

And the memory issue? Still there. You can optimize rendering all you want, but React's component tree, Ink's layout engine (Yoga-based Flexbox), and Node.js's baseline overhead add up. The leaks are bugs; the 200-400MB baseline is architecture. A Rust or Go TUI using Ratatui or Bubbletea would idle at 10-20MB. Claude Code's "fixed" version still carries an order of magnitude more weight.

A terminal app. Heavier than an IDE. Because of architectural choices made for developer comfort.

What "Simple" Would Look Like

Traditional TUI architecture is boring by comparison:

  1. Maintain a character buffer (your "screen")

  2. Track dirty regions

  3. On change: update buffer, render only what changed

  4. For spinners: a timer toggling a character

No scene graph. No rasterization. No frame budget. Tools like Ratatui (Rust), Bubbletea (Go), and ncurses have done this for decades. The complexity is bounded. The resource usage is predictable. The mental model is "bytes in, bytes out."

But here's the catch: those tools don't give you React's component model. Claude Code has complex layouts, focus management, rich Unicode rendering, and accessibility features. A simple ncurses wrapper wouldn't deliver that—at least not without rebuilding half of what Ink provides.

The real question isn't "why didn't they use ncurses?" It's "was React's component model worth the rendering complexity and memory overhead?" That's a harder call than critics admit. Component models do accelerate development of complex interfaces. But when your TUI rivals an IDE in resource consumption and attracts GitHub issues about 120GB memory leaks, the answer starts to lean one direction.

The Lesson for Engineers

The Claude Code TUI isn't a cautionary tale about bad engineers. It's a cautionary tale about invisible decisions—choices so embedded in team culture and tooling that nobody remembers making them, or remembers that alternatives exist.

Before your next architecture decision, ask:

  • "What is this actually?" (A terminal that prints text, not a browser)

  • "What's the boring solution?" (Event-driven rendering to a character grid)

  • "What are the resource implications?" (Will this TUI outweigh an IDE?)

  • "Are we solving real problems or self-created ones?" (Frame budgets for loading spinners)

  • "What would someone outside our stack do?" (Use a TUI library, not a web framework)

  • "Can we afford the abstraction tax?" (React's baseline overhead plus leak surface area)

You won't always choose the boring solution—sometimes React is the right call, especially for complex UIs with rich interaction patterns. But you should choose it consciously, not by default. You should know what you're buying and what you're borrowing against.

The Terminal Doesn't Care

Here's the final irony: terminals are the most forgiving interface computers have invented. They accept anything. Bytes in, bytes out. They'll run your game engine. They'll tolerate your scene graph. They won't complain about your 16ms frame budget or your 400MB memory footprint or your occasional 120GB leak.

That forgiveness is dangerous. It lets complexity accumulate without friction. The terminal won't reject your architecture—it'll just flicker more, consume more memory, spawn more GitHub issues, and eventually prompt an engineer to tweet about frame budgets while the internet asks: why?

The best tools feel simple because someone made hard decisions about what not to build. Claude Code's TUI works. Users like it. The team ships fixes and contributes upstream. But it's a reminder that complexity often arrives not as a decision, but as an accumulation—layer upon layer of reasonable choices until one day your terminal app is heavier than the IDE it's supposed to replace.

Next time you're architecting something, notice when expertise becomes assumption. When comfort becomes cost. When "we know this" silently replaces "this is correct."

And maybe ask how did we get here? before you have to explain it in a tweet.

The best time to question your stack is before you build. The second best time is now.

Matthias Bigl

Matthias Bigl

Insert pretentious stuff about yourself here

Leave a Reply

Bigl's Blog

Personal blog by Matthias Bigl — Exploring technology, software development, and innovation. bigls.net

© 2026 Matthias Bigl. All rights reserved.

Connect with Matthias Bigl

Bigl's Blog is the personal technology blog of Matthias Bigl (bigls.net), featuring articles on software development, web technologies, and tech insights.