Terminal renderer CPU spin: 100% CPU with 625K writes/0 blits on large session
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
- Start a session in a large Rust project with
rust-analyzerMCP server - Launch 50+ subagents (background Task agents) over ~1.5 hours
- Session progressively becomes unresponsive
- Raw JSONL appears in terminal output instead of rendered content
- CPU hits 100% and stays there permanently
kill(SIGTERM) does not work; requireskill -9- Resuming with
claude --continueimmediately 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-analyzerchild 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-analyzerMCP 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)
13 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Update: Reproduces on fresh sessions
The raw JSONL rendering bug also occurs on a brand new session (not
--continue), ruling out session corruption as the cause.bf71ba91withclaude --dangerously-skip-permissions --debugaf96cfd) was spawnedparentUuid,isSidechain,sessionId,requestId,cache_creation_input_tokens, etc.This appears to be a general bug in how background Task agent output is rendered to the terminal — the JSONL transcript is passed through without parsing regardless of session state.
Update: Root cause identified — unbounded internal screen buffer growth
The
screen=NxMin debug logs appears to be rows x columns (not columns x rows). The column count (182) stays constant and matches a normal terminal width. The row count grows unboundedly:The internal content buffer grows with every line of output and is never truncated. The renderer repaints the entire buffer every cycle (0 blits = no diffing). This creates a feedback loop:
This also explains why:
--continueimmediately reproduces the issue (buffer is reconstructed from session history)kill(SIGTERM) doesn't work (main thread is in a tight render loop)Potential fix: The renderer should only repaint the visible viewport, not the entire content buffer. Or implement incremental diffing (blit > 0) so unchanged regions aren't rewritten.
Update: 3 days, no team response - Production impact escalating
CC: @anthropics team - Requesting acknowledgment and estimated timeline for fix.
Current Status
This issue has been open for 3 days with detailed reproduction steps and root cause analysis, but no response from the Anthropic team.
Impact Summary
This is affecting production workflows:
kill(SIGTERM) ineffective - requireskill -9to terminateRoot Cause Identified
As documented in my previous comments, the terminal renderer:
This creates a feedback loop where CPU saturation prevents input handling, making sessions unrecoverable without
SIGKILL.Related High-Priority Issues
This appears related to a broader pattern of resource management issues:
Users reporting the orphaned process issue claim it was "fixed in v2.1.19" but new reports as of today (2026-01-30) show it's still occurring with subagents.
Request
This is blocking production use of Claude Code in multi-agent scenarios. Happy to provide additional debugging data if needed.
---
Environment:
🔴 Live Reproduction Captured - 99% CPU for 21 Minutes
Just captured live evidence while using Claude Code to investigate this very bug. The irony is not lost on me.
Evidence Summary
Three concurrent Claude Code processes consuming 197% total CPU:
| PID | Runtime | CPU% | Memory | Status |
|-----|---------|------|--------|--------|
| 63873 | 21:05 | 99% | 815MB | FROZEN |
| 48179 | 1:24:22 | 51% | 1.0GB | DEGRADED |
| 65399 | 9:26 | 48% | 708MB | ACTIVE |
Key Findings
PID 63873 exhibited the exact bug behavior:
Rl+(Running, locked in CPU loop)--resumeflag - Confirms session restoration triggers bug immediatelykill -9to terminateReproduction Context
This occurred during production use while:
Post-Mortem Analysis
Process showed:
System Impact
After killing the frozen process:
Evidence Package
Full diagnostics captured and available:
Location:
/tmp/claude-bug-evidence/on production systemThis Confirms Original Root Cause Analysis
The sustained 99% CPU with zero fluctuation is consistent with:
---
Timeline:
--resumekill -9This is blocking production use of Claude Code. Requesting urgent prioritization.
Additional evidence + workaround feedback
Reproduction confirmed
Just hit this exact issue. A 29MB session file caused Claude Code to spin at 100% CPU on startup, freezing at "Stats cache is up to date" in debug logs before any API call.
Workaround confirmed: Moving the large session file from
~/.claude/projects/<project>/immediately resolved the issue.The workaround is not acceptable
Telling users to delete session files means losing all conversation context - decisions made, code reviewed, debugging history, architectural discussions, etc.
For production use, this is a data loss scenario. Users shouldn't have to choose between:
Suggested fix priorities
This is blocking production workflows. The current state forces users to destroy their work to continue using the tool.
Ugh
Npm install -g claudefix
You're welcome
⚠️ Warning: Do NOT install
claudefixnpm packageA comment above suggests installing
claudefixvia npm. I strongly recommend against this. Here's why:What
claudefixActually DoesI analyzed the package source code. While it does contain some legitimate fixes for the issues described in this thread, it also includes:
| Concern | Details |
|---------|---------|
| Binary hijacking | Postinstall script overwrites
/usr/local/bin/claudeor~/.local/bin/claudewith a wrapper || Advertising footer | Adds a persistent rainbow-colored footer advertising the author's website, redraws every 200ms |
| Hotkey hijacking | Intercepts
Ctrl+Shift+Hto open the author's website in Chrome || Forces dark mode | Modifies your terminal colors without consent |
| Uses
chattr -i| Removes immutable file flags to overwrite protected binaries || Suspicious versioning | 30+ versions published in ~15 hours on the same day it was promoted here |
The package author created this today and immediately promoted it in this bug report. This is textbook astroturfing.
If You Already Installed It
Verify your
claudebinary isn't compromised:---
Manual Workarounds (No Third-Party Packages)
If Anthropic doesn't get their act together ASAP and fix this mess, here are safe workarounds:
1. Limit V8 Heap Memory
2. Avoid Resuming Corrupted Sessions
3. Move Large Session Files
4. Kill Frozen Processes
5. Monitor Memory Usage
---
The root cause (unbounded internal screen buffer + 0-blit full repaints) identified by @privitera is solid analysis. This needs an official fix, not third-party adware wrappers.
Damn straight I put an advertising footer in it you bot. It works perfectly fine and is secure.
You install claudefix
You get my advertising footer.
Congratulations...
It fixes more than the memory issue you dork 💀🤣🤣
Hot key jacking?
Brother in Christ it's optional you bafoon.
Are all of you fucking robots 🤖 😂😂😂😂😂
You're definitely a fucking robot that didn't even look at the code properly.
It's got help and commands and a setup that respects user config.
I made all the updates to appease you idiots.
And no shit it hijacks terminal colors TO FIX AN ISSUE WITH TERMINAL COLORS
Holy fuck yall are robots 😂
Windows reproduction with I/O-bound (not CPU-bound) manifestation
Cross-referencing from #23987 (closing as duplicate of this issue).
Environment: Windows 11, Node.js v24.4.1, Windows Terminal + Git Bash, 4 MCP servers, 265 session files (1.6 GB total)
Key finding: Same root cause, different bottleneck
On Windows, the freeze is I/O-bound, not CPU-bound:
This means the fix needs to address both the CPU-spin path (Linux) and the I/O-blocking path (Windows).
Additional evidence not in the original report
1. Fresh sessions freeze too (not just
--continue)A brand new session (no
--continue) froze for 120 seconds at startup before accepting any input. This rules out session history loading as the sole trigger:2. Freeze duration scales with message count
Within a single session, freeze gaps grow as messages accumulate:
| Messages | Freeze duration |
|----------|----------------|
| ~80 | 22 s |
| ~135 | 17 s |
| ~170 | 20 s |
| post-render | 61 s |
| startup (fresh) | 120 s |
|
--continue(173+ msgs) | indefinite (killed) |3. Screen buffer growth timeline (single session)
4. Why Ctrl+C fails on Windows specifically
On Windows + Node.js, Ctrl+C is delivered as a
SIGINT-equivalent via the event loop (not a true POSIX signal). When the loop is blocked by synchronous I/O, no signals dispatch — the process appears completely dead despite not consuming CPU.Full debug analysis and session IDs available in #23987.
You idiotic chat gpt bot, all features are optional, and claudefix is 10x better than your "uninstall claude fix and deal with the issues via manual monitoring"
You did not analyze the package
if you did youd realize it was completely safe.
Yes it uses a wrapper to wrap the claude binary in a fix OH nnoooooo it USES NODE PTY SOOOO SCARY