[BUG] High sustained CPU usage (~100% per instance) even when idle

Status Closed — duplicate
Reported on v2.1.29
Maintainer reply None cached
Activity 14 comments · opened Jan 31, 2026 · closed Aug 19, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Description

Two instances of Claude Code CLI running simultaneously each consume ~100% CPU sustained, even between interactions when both should be idle. On a 4-core machine this makes the system noticeably sluggish.

Environment

  • Claude Code version: 2.1.29
  • Node.js: v22.19.0
  • OS: Linux Mint 21.3 (kernel 5.15.0-164-generic)
  • Hardware: 4 CPU cores, 7.5 GB RAM
  • Terminal: Guake (but issue is in the claude process itself)

Observed behavior

Both claude processes pin at ~100% CPU each continuously, even when no tool calls are running and no output is being streamed:

PID USER %CPU %MEM RES COMMAND
3225 jan 102% 9.6% 756 MB claude
5342 jan 89% 8.4% 660 MB claude

A second measurement 2 minutes later with both sessions idle between interactions:

PID USER %CPU %MEM RES COMMAND
3225 jan 101% 9.9% 781 MB claude
5342 jan 97% 9.0% 705 MB claude

Each process has ~13-14 threads. Virtual memory mapped is ~71 GB per process (normal for V8 but noted for completeness).

---

What Should Happen?

Expected behavior

Between interactions, CPU usage should drop to near zero since the CLI is mostly waiting for user input or network responses.

Error Messages/Logs

Steps to Reproduce

  1. Open two terminal tabs
  2. Run claude in each
  3. Have a conversation in one; leave the other idle
  4. Observe CPU usage with top

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.29

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Other

Additional Information

  • No MCP servers configured
  • The high CPU is in the claude Node.js process itself, not in any child/tool processes
  • Single instance also shows ~100% CPU, it's not contention between the two

View original on GitHub ↗

13 Comments

github-actions[bot] · 7 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/21322
  2. https://github.com/anthropics/claude-code/issues/21889
  3. https://github.com/anthropics/claude-code/issues/17142

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

loxleygames · 7 months ago

Confirming on same setup - v2.1.29, Linux Mint (kernel 6.14.0-37-generic)

Thread-level breakdown shows the cause clearly:

ps -L -p <PID> -o pid,lwp,pcpu,comm

    PID     LWP %CPU COMMAND
  66037   66037 24.3 claude        # main thread
  66037   66039  2.2 HeapHelper
  66037   66040  2.1 HeapHelper
  66037   66041  2.1 HeapHelper
  66037   66042  2.1 HeapHelper
  66037   66043  2.1 HeapHelper
  66037   66044  2.1 HeapHelper
  66037   66045  2.0 HeapHelper    # 7 HeapHelper threads (~14% combined)
  66037   66046  2.5 JITWorker

This matches the root cause identified in #18280 - the 60Hz timer causing constant allocation/deallocation, with GC (HeapHelper threads) running continuously to clean up.

Additional observation: Restarting Claude Code and resuming the conversation (/resume) temporarily improves CPU usage, but it creeps back up during the session. This suggests the memory pressure accumulates over time rather than being constant from startup.

oxysoft · 7 months ago

a hot path like this should not have any allocations............ this is very concerning..... how is GC in the frame path be passing review, that's crazy

jonhardwick-spec · 6 months ago

npm install -g claudefix

You're welcome

kmalyshev · 6 months ago

@jonhardwick-spec

npm install -g claudefix You're welcome

⚠️ Warning about claudefix package

I analyzed this package before installing and found several concerns:

It won't fix the high CPU issue:

  • The CPU problem is a busy-wait loop in Claude's event loop (see issue #18280, #10493)
  • This package only limits V8 heap size, which doesn't address the CPU issue
  • Most "fixes" are Linux VTE-specific and don't apply to macOS

Adware-like behavior:

  • Replaces your claude binary with a wrapper
  • Adds a mandatory promotional footer ("claudefix by Hardwick Software") on first run
  • Includes a hotkey (Ctrl+Shift+H) that opens the author's website
  • Created yesterday with 40+ versions in 24 hours

If you just want memory limits, you can do it yourself without third-party wrappers:

export NODE_OPTIONS="--max-old-space-size=4096"

The actual fix needs to come from Anthropic — it's a known bug in Claude Code's Ink/React TUI rendering causing memory thrashing and busy-wait loops. See issues #18280, #22275, #10493.

I'd recommend waiting for an official fix rather than installing packages that replace your binaries and add promotional content.

dkmaker · 6 months ago

What version does not suffer from this issue? its pretty useless as is after a short time my machine comes responsive with 2-3 sessions running in parallel my VM dies of context switching - and the TUI is so slow that i barely can add texts in it..

jstasiak · 6 months ago

I downgraded to 2.1.25 and I haven't seen this problem since.

diamondsea · 6 months ago

Additional diagnostic evidence from debug logs - v2.1.31 on macOS

I'm seeing the same ~ 20% sustained CPU usage when idle on v2.1.31. Found relevant evidence
in the debug logs (~ /.claude/debug/*.txt) that may help pinpoint the issue:

  2026-02-05T19:35:47.522Z [DEBUG] High write ratio: blit=1034, write=62508 (98.4% writes),
  screen=2294x94                  
  2026-02-05T19:35:48.139Z [DEBUG] High write ratio: blit=1034, write=62508 (98.4% writes),
  screen=2294x94
  2026-02-05T19:35:48.756Z [DEBUG] High write ratio: blit=1034, write=62508 (98.4% writes),
  screen=2294x94
  2026-02-05T19:35:49.359Z [DEBUG] High write ratio: blit=1034, write=62508 (98.4% writes),
  screen=2294x94

This pattern repeats continuously every ~600ms even when completely idle (no user input, no
API calls, just waiting).

What this shows:

  • The renderer is writing ~62,000 characters per frame
  • Only ~1,000 blits (cached region copies)
  • 98.4% write ratio when a mostly-static idle screen should be nearly 100% blits
  • The system is detecting this as anomalous ("High write ratio" log message)

Environment:

  • Claude Code: 2.1.31
  • OS: macOS Darwin 25.2.0
  • Multiple MCP servers connected (Asana SSE, memory, cloudflare, playwright, docs-mcp,

nanobanana)

This correlates with the 60Hz timer theory - the renderer appears to be redrawing the entire
screen buffer on each tick rather than diffing and only updating changed regions.

franz1981 · 6 months ago

perf stat data point: 48% of idle CPU is pure kernel/syscall overhead (v2.1.63, Fedora 43, kernel 6.18)

Adding a dimension I haven't seen in the other comments — the user/kernel cycle split:

perf stat -e cycles:u,cycles:k,instructions:u,instructions:k -p <PID> -- sleep 5

1,890,734,220  cycles:u          (52% userspace)
1,728,362,674  cycles:k          (48% kernel)
3,841,947,529  instructions:u    IPC 2.03 — efficient code
1,279,019,700  instructions:k    IPC 0.74 — syscall overhead

Nearly half the idle CPU burn is kernel-side, driven by the syscall volume (~18K/sec). The userspace IPC of 2.03 means the JS itself runs efficiently when it does run — the waste is in how often it runs and the resulting syscall storm:

strace -c (10 seconds, idle):
  94,620  sched_yield     (9,462/sec — HeapHelper spin-wait)
  62,466  futex           (6,247/sec — thread sync noise)
   8,900  clock_gettime   (890/sec)
   5,774  madvise         (577/sec — mimalloc page mgmt)
   3,504  epoll_pwait2    (350/sec — event loop polls)
 ────────
 179,697  total syscalls in 10 seconds

Bun upstream fix worth picking up

oven-sh/bun#27490 — bmalloc's SYSCALL macro retries madvise(MADV_DONTDUMP) with zero backoff on EAGAIN, causing HeapHelper threads to spin. Fixed upstream in oven-sh/WebKit but may not be in the Bun version bundled with Claude Code. This would directly reduce the sched_yield + madvise pressure.

patrick-elmore · 3 months ago

@claude @diamondsea's High write ratio: blit=1034, write=62508 (98.4% writes) finding above lines up with measurements I have on the WSL2 side. Posting them here because they show where the writes go and why the relays burn CPU on the Windows side.

Setup

  • Claude Code 2.1.128
  • 7 concurrent claude sessions in 7 Windows Terminal tabs
  • Windows 11
  • Windows Terminal 1.24.10921.0 stable (also reproduced on 1.25.1171.0 preview; neither fixes it)
  • WSL2 Ubuntu 24.04
  • Provider: Google Vertex AI
  • All sessions idle. No active API call, no tool running, no user input.

Linux side: per-claude pty I/O over a 10-second sample (/proc/{pid}/io)

PID      ReadB/s         WriteB/s        Etime
22760    51              8               02:45:39    <-- LOOPING
49428    49              8               01:40:50    <-- LOOPING
81398    49              8               36:12       <-- LOOPING
2220     0               8               03:36:02    <-- silent

Every idle session writes the same 8 bytes/sec to its pty, about 1 write syscall/sec. Some sessions also receive ~50 bytes/sec back, about 2 read syscalls/sec. Other identical idle sessions get nothing back.

Windows side: wsl.exe relay CPU and thread count

   Id Name            PctOneCore Threads AgeHrs
   -- ----            ---------- ------- ------
61404 wsl                   21.7      12   11.4    <-- looping relay
67964 wsl                   14.5       7   11.7    <-- looping relay
72672 wsl                    0.0       4   11.6    <-- silent relay (same age)

Affected relays grow from the normal 4 threads to 7-12 as they spin to keep up with the bidirectional traffic. Task Manager's Processes view rolls up child-process CPU under the parent, so the visible figure attributed to "Windows Terminal" reaches 30-43% of one core with 2-3 affected sessions. WindowsTerminal.exe itself uses ~0% during the same sample. The CPU budget is being consumed entirely by its wsl.exe relay children.

Why this matters for this issue

All idle sessions emit identical 8 bytes/sec. The differentiator is whether the terminal-side loops the data back. Once a relay enters the looping state it stays there for that relay's lifetime, and claude has no choice but to respond to whatever VT queries arrive (DSR cursor position, focus events, mouse motion). The user-visible CPU consequence is sustained 5-25% per affected relay on the Windows side with matching read throughput on the Linux side. That's the symptom this issue tracks.

The chain: claude writes to pty, pty forwards to ConPTY relay, relay responds with what looks like cursor position reports or focus events, that response triggers the next claude write. The 16ms Ink re-render documented in #19393 likely explains why claude generates periodic outbound queries at idle to begin with.

Reproduction (~10 seconds, no install)

Linux side, from any shell with multiple claude PIDs:

declare -A rbefore wbefore
for p in $(pgrep -f "claude"); do
  rbefore[$p]=$(awk '/^rchar/ {print $2}' /proc/$p/io 2>/dev/null)
  wbefore[$p]=$(awk '/^wchar/ {print $2}' /proc/$p/io 2>/dev/null)
done
sleep 10
for p in "${!rbefore[@]}"; do
  rafter=$(awk '/^rchar/ {print $2}' /proc/$p/io 2>/dev/null)
  wafter=$(awk '/^wchar/ {print $2}' /proc/$p/io 2>/dev/null)
  echo "PID $p ReadB/s=$(( (rafter - rbefore[$p]) / 10 )) WriteB/s=$(( (wafter - wbefore[$p]) / 10 ))"
done

Windows side, in PowerShell:

$first = Get-Process -Name wsl | Select Id,@{n='CPU0';e={$_.CPU}}
Start-Sleep 10
Get-Process -Name wsl | ForEach-Object {
  $old = $first | Where Id -eq $_.Id
  if ($old) {
    $delta = $_.CPU - $old.CPU0
    [PSCustomObject]@{Pid=$_.Id; PctCore=[math]::Round(($delta/10)*100,1); Threads=$_.Threads.Count}
  }
} | Sort PctCore -Descending

The looping wsl.exe PIDs on the Windows side correspond to the claude PIDs reading non-zero bytes/sec on the Linux side. The mapping is exact in my testing.

Workaround

Launching claude inside tmux eliminates the loop. tmux's pty layer absorbs the cursor-position / focus / mouse responses before they reach the Windows ConPTY relay, breaking the feedback path at the right layer. Same workaround validated in microsoft/terminal#17787 discussions.

Related

Same family as several open and closed reports. Adding the WSL2/relay-side measurement may help connect them.

In this repo:

  • #17787 — DSR cursor position responses leaking to display (closed; identifies upstream sequence and tmux workaround)
  • #21766 — escape sequences emitted to own input on Windows (closed; identifies emission pattern)
  • #18048 — extreme WSL2 CPU/memory (closed)
  • #19393 — high CPU on WSL2/Ubuntu (open; most active WSL2-specific thread)
  • #10881 — degradation over long sessions
  • #56768 — metadata-regeneration loop on long sessions

Cross-repo, Windows Terminal maintainers have closed similar reports as upstream/Ink:

  • microsoft/terminal#19772 — @lhecker (WT maintainer): "Claude Code is simply poorly written... Every time you type something or do something, it re-renders everything... This will happen in any terminal, on any hardware, because fundamentally the issue is how Claude Code renders itself." Recommends ink-virtual-list or moving off Ink.
  • microsoft/terminal#19674 — console mode corruption traced back to Node.js process.stdin.setRawMode(true) overwriting flags. Filed upstream as oven-sh/bun#25663 and nodejs/node#61161.
  • microsoft/terminal#20150 — WT renderer wedged with 12 Claude Code tabs in WSL2 after 25 hours. Auto-closed stale.

Outstanding

I haven't captured the exact 8-byte sequence being emitted. That's the next investigation step if there's interest in narrowing the initiating side.

lhecker · 3 months ago

That's a rather unfortunate mid-sentence abbreviation of my comment. FWIW I'm happy to assist with Claude's perf issues wherever I can.

patrick-elmore · 3 months ago

@lhecker No idea what you're talking about. Feel free to post the missing context if I somehow misrepresented your comment.

Showing cached comments. Read the full discussion on GitHub ↗