Terminal renderer CPU spin: 100% CPU with 625K writes/0 blits on large session

Open 💬 13 comments Opened Jan 28, 2026 by privitera

Description

Claude Code enters a pathological state where the main thread consumes 100% CPU due to the terminal renderer performing ~625,000 write operations with zero blits (no diffing optimization) per render cycle. The session becomes unusable (30+ second input lag) and requires kill -9 to terminate.

Additionally, raw JSONL session/API data (including requestId, usage, cache_read_input_tokens, stop_reason, etc.) is rendered directly to the terminal instead of being parsed.

Environment

  • Version: 2.1.22
  • Platform: Linux 6.11.0-1016-nvidia (aarch64)
  • Terminal size: 2099x472
  • Runtime: Bun

Reproduction

  1. Start a session in a large Rust project with rust-analyzer MCP server
  2. Launch 50+ subagents (background Task agents) over ~1.5 hours
  3. Session progressively becomes unresponsive
  4. Raw JSONL appears in terminal output instead of rendered content
  5. CPU hits 100% and stays there permanently
  6. kill (SIGTERM) does not work; requires kill -9
  7. Resuming with claude --continue immediately reproduces the 100% CPU state

Diagnostic Data

Debug log (~/.claude/debug/<session-id>.txt)

The key line repeating every ~17 seconds:

High write ratio: blit=0, write=625433 (100.0% writes), screen=2099x472

Full tail of debug log:

2026-01-28T22:57:43.905Z [DEBUG] Stream started - received first chunk
2026-01-28T22:58:02.253Z [DEBUG] High write ratio: blit=0, write=625433 (100.0% writes), screen=2099x472
2026-01-28T22:58:19.847Z [DEBUG] High write ratio: blit=0, write=625433 (100.0% writes), screen=2099x472
2026-01-28T22:58:19.866Z [ERROR] AxiosError: Error
    at <anonymous> (/$bunfs/root/claude:47:10681)
2026-01-28T22:58:19.880Z [ERROR] Error: 1P event logging: 10 events failed to export (code=ECONNABORTED, timeout of 10000ms exceeded)
2026-01-28T22:58:55.220Z [DEBUG] High write ratio: blit=0, write=625432 (100.0% writes), screen=2099x472
2026-01-28T22:59:12.825Z [DEBUG] High write ratio: blit=0, write=625676 (100.0% writes), screen=2103x472

Process diagnostics

PID %CPU %MEM    VSZ      RSS      ELAPSED
1482399 79.0 3.0  94.3g    3.7g     01:11:19
  • Main thread (PID = process PID) at 99.9% CPU; all other threads (Bun Pool, HTTP Client, File Watcher) at 0%
  • Killing rust-analyzer child process had no effect on CPU
  • 50 threads total, only main thread spinning
  • Session grew to 3.7GB RSS / 94GB VSZ

Raw JSONL in terminal output

Instead of rendered content, the terminal displayed raw API transport data:

{"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":1,
"cache_creation_input_tokens":307,"cache_read_input_tokens":148581,
...},"requestId":"req_011CXaW3Yr62aB1dFwmcgMME","type":"assistant",
"uuid":"97197d7e-...","timestamp":"2026-01-28T21:44:02.136Z"}

Including subagent permission errors rendered raw:

{"toolUseResult":"Error: Permission to use Write has been auto-denied 
(prompts unavailable).","sourceToolAssistantUUID":"97197d7e-..."}

Analysis

The terminal renderer appears unable to diff/blit the screen buffer when the content exceeds a certain size, falling back to full rewrite of ~625K characters every render cycle. This creates a CPU-bound hot loop in the main Bun event loop that starves all other processing (input handling, API calls, etc.).

The raw JSONL rendering suggests the output parsing pipeline also breaks down, possibly related to the same buffer size issue.

Steps ruled out

  • rust-analyzer MCP server: killed it, no CPU change
  • Zombie child processes: already reaped, no effect
  • Session history loading: RSS was dropping while CPU stayed at 100%, ruling out memory-bound loading
  • Network issues: telemetry ECONNABORTED errors are secondary (caused by the main thread being too busy)

View original on GitHub ↗

This issue has 13 comments on GitHub. Read the full discussion on GitHub ↗