[Bug] High CPU usage at idle/prompt state
Status Open
Reported on v2.1.29
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 12 comments · opened Feb 2, 2026
Bug Description
Claude code 2.1.29 uses close to 100% of my CPU while doing nothing (I'm at prompt). Actually, I've just started a new claude haven't executed anything yet and the CPU usage is 20+ percent.
Environment Info
- Platform: darwin
- Terminal: Apple_Terminal
- Version: 2.1.29
- Feedback ID: 4044b938-d75f-4830-ae82-cfa2e3a4500b
Errors
[{"error":"Error: LSP server plugin:rust-analyzer-lsp:rust-analyzer crashed with exit code 1\n at <anonymous> (/$bunfs/root/claude:2142:21472)\n at emit (node:events:98:22)\n at #handleOnExit (node:child_process:520:14)\n at processTicksAndRejections (native:7:39)","timestamp":"2026-02-02T06:45:39.770Z"}]
12 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Same problem for me:
Platform: darwin
Terminal: ghostty
98.4 CPU Usage AVG
I had three idle processes using ~100%, draining my battery for a day.
I could actually see a few long running idle instances of .23 alongside them not making any such fuss.
I downgraded to .25 to deal with the (now solved) resume bug in .27 and the CPU problem went away.
<img width="320" height="155" alt="Image" src="https://github.com/user-attachments/assets/1a844bb3-fa71-49eb-b368-73be2eb02344" />
I was having the same issue then I found out there are 134 orphan subagents, after killing those my cpu usage decreased to normal levels.
Same issue
Adding detailed Linux diagnostic data with root cause analysis:
Platform: Linux (Kali 6.12.13-amd64)
Version: 2.1.29
Terminal: External terminal
---
strace analysis (3 second sample of idle process)
| Syscall | Calls | % Time | Purpose |
|---------|-------|--------|---------|
|
madvise| 6,456 | 11% | GC memory hints ||
sched_yield| 301 | 5% | CPU yielding ||
futex| 1,499 | 11% | Thread sync ||
epoll_pwait2| 145 | 71% | Event waiting |All madvise calls are
MADV_DODUMP(~2,152/sec) — Bun's garbage collector is stuck in a tight loop.Memory at time of spin
Key finding
Disabling rust-analyzer-lsp plugin did NOT fix the issue. The madvise/GC loop persists even with the plugin disabled. This rules out the plugin crash as the root cause.
Root cause
After sessions accumulate memory during active work, heap fragmentation causes the Bun GC to run continuously without ever settling into idle state. The GC keeps marking/unmarking memory pages even when there's no actual work to do.
Workaround
Kill long-running idle sessions. The bug doesn't appear immediately on fresh sessions — it develops after significant memory accumulation during active use.
macOS Diagnostic Data: Idle Sessions at 80-100% CPU
Environment
Observed Behavior
10 concurrent Claude Code sessions accumulated over days, all with
--continueflag for session persistence. Despite being completely idle (waiting for user input), they consumed 667% total CPU.| Session | Version | Elapsed | CPU% | Memory |
|---------|---------|---------|------|--------|
| A | 2.1.29 | 2d 12h | 95% | 587MB |
| B | 2.1.27 | 3d 22h | 92% | 745MB |
| C | 2.1.29 | 1d 20h | 92% | 530MB |
| D | 2.1.29 | 7h 40m | 78% | 544MB |
| E | 2.1.27 | 3d 11h | 54% | 814MB |
| F | 2.1.29 | 13h | 49% | 457MB |
| G | 2.1.27 | 3d 22h | 14% | 611MB |
| H | 2.1.29 | 1d 20h | 98% | 2.0GB |
System impact: Load average 10.23, swap 9.4GB/10GB used, 24% idle CPU.
Key Finding:
/clearCommand Fixes the IssueAfter running
/clearin session H:| Metric | Before
/clear| After/clear||--------|-----------------|----------------|
| CPU | 98% | 0.0% |
| Memory | 2.0GB | 160MB |
This confirms the issue is related to accumulated session state causing continuous CPU consumption, not the idle input loop itself.
Thread Analysis (via
ps -M)Main thread shows state
R(running) at 78-87% CPU even when idle. Worker threads (3-4 per process) show ~1% each. Main thread is doing work, not blocked waiting for input.sampleOutput Analysis3-second sample shows:
<unknown binary>addresses (JIT-compiled code)Correlation with Session Age and Memory
| Session Age | Memory | CPU |
|-------------|--------|-----|
| < 8h | < 550MB | 50-80% |
| 1-2d | 500-600MB | 90%+ |
| 3-4d | 600-800MB | 85-95% |
Older sessions with more accumulated state run hotter, but even newer sessions (7h) show 78% CPU when idle.
Workaround Confirmed
Running
/clearimmediately drops CPU to 0% and reduces memory significantly. This suggests the fix should target whatever state accumulation triggers the GC thrashing.Questions for Developers
/clearresets?---
Related findings from other users in this thread: GC thrashing (mmap/munmap cycles), Bun heap fragmentation after memory accumulation.
I'm seeing the same behavior on macOS:
/compactthe system became way less laggy butThis is excessive for idling:
Also, I don't recall seeing this before
v2.1.29; seems new.Happens on Windows 11 too. Fairly recent, within a week.
Disclaimer: this comment was written by Claude Opus 4.6 (fast) and reviewed by me for AI slop. Take it with a grain of salt but definitely try the fixes - they literally made my M1 8GB/512GB Mac usable again.
Dug into this pretty deep on my M1 8GB, found 3 separate things causing the CPU/memory issues. Went from 208% CPU / 3.3GB RSS idle down to ~30% / 700MB.
I'm not a Bun/JSC internals expert, I just had my claude (Opus 4.6) trace through Bun source, fs_usage, vmmap etc until we figured out what's going on. So treat this as leads for the Anthropic team to investigate properly, not a definitive root cause report. That said, the workarounds do work.
1. Syntax highlighting is the biggest CPU hog
The syntax highlighter uses Oniguruma (via a Rust native module) with TextMate grammars - same regex engine as VSCode, and prone to the same backtracking issues on certain code blocks. highlight.js is only the JS fallback. Every render frame re-highlights everything visible so it just pins the CPU. I didn't even have code changes in the render view and it was still regexing away. Disabling it instantly dropped me from 208% to ~50%:
2. Memory never gets returned to the OS
Two things here. mimalloc holds onto freed pages forever by default (saw 49% fragmentation in vmmap), and JSC's GC only triggers at 2x heap growth so gradual leaks slip through. This is what causes the 304GB vsize / multi-GB RSS people are seeing.
Workaround - make a wrapper script at
~/.local/bin/claude(or wherever it's first in your PATH):This got me from 3.3GB to ~700MB RSS and fragmentation from 49% to 3%.
3. Config file polling - 638 syscalls/sec while idle
This one's wild. Run
sudo fs_usage -w -f filesys $(pgrep claude) | grep config.jsonand you'll see a wall ofaccess()+stat64()on~/.claude/.config.jsonat ~300+ pairs per second. It's being read every React render frame (the spinner drives the loop). The files never change. Still reproduces on 2.1.39 (44 hits in a single second burst during streaming).Traced the root cause: there's a
getConfig()function that doesexistsSync()(to resolve the path) +statSync()(for mtime-based caching) on every call - so even cache hits cost 2 syscalls. This function is called directly from React render paths (progress bar, spinner tree, verbose flag, tip checks, etc.) instead of going through the zustand store that already exists for settings. There are ~438 direct call sites bypassing the store. The store-backed path (useAppState(s => s.settings)) reads from memory and doesn't touch disk, but most components use the direct disk-reading function instead.The fix on Anthropic's side would be to route those render-path reads through the existing zustand store, or add a time-based TTL to the stat cache instead of checking mtime every call. I built a DYLD interpose dylib that caches stat/access with a 200ms TTL, dropped it from 638/sec to 3/sec. If anyone wants to try it on macOS:
<details>
<summary>DYLD interpose dylib (macOS only)</summary>
Save as
config_cache.c, compile and sign:Then re-sign the claude binary to allow dylib injection (it ships with hardened runtime):
Add to your wrapper script:
Note: you'll need to re-sign after claude updates.
</details>
@jeffgicharu your strace finding of 2152 madvise/sec is the same root cause as #2 above - the
MIMALLOC_PURGE_DELAY=0env var should fix the GC thrashing loop on Linux too.Again this is all based on a few hours of poking around with Claude doing the heavy lifting on Bun internals, so Anthropic folks should definitely verify these findings properly. But the workarounds are working well for me.
@sqdshguy thanks - the wrapper seems to have resovled the memory issue for me, where claude code would have previously gone up to 50G of ram
<img width="1252" height="124" alt="Image" src="https://github.com/user-attachments/assets/f95839de-0348-4079-b960-33c6fea9e46c" />
Adding power consumption measurements that quantify the actual battery impact of this bug.
Environment: Claude Code 2.1.39, Node v20.20.0, macOS 15.7.1, MacBook Pro 16" M1 Pro, 16GB RAM
Power draw: each idle session burns a full CPU core
Using
powermetrics(10-second sample), two completely idle Claude Code sessions — no active prompts, no streaming, no tool execution:Each idle session uses 989ms of CPU per second (100% of one P-core at 3.2 GHz). Two sessions = ~10.6W CPU draw.
For comparison, the entire rest of the system — WebStorm, Brave Browser, iTerm2, WindowServer, Finder, and ~50 other processes — combined to less energy impact than a single idle Claude Code session.
Impact on battery life: Normal workload draws ~3-5W. Two idle Claude sessions add ~10W, roughly cutting battery life in half. Both processes had been running for 6 days:
Stack trace: TLS stream busy-wait loop
sample(5 seconds, 3800/3800 samples on the same stack — main thread never idles):The event loop is stuck in a tight cycle:
uv__io_poll→ TLS stream read → promise fulfillment → async generator resume → microtask queue never drains → back touv__io_pollwhich immediately fires again. The process never reacheskevent()to sleep.This is a different code path from the
uv__run_check/setImmediatepattern in #17148 and the GC thrashing (madvise/MADV_DODUMP) reported by @jeffgicharu — suggesting there may be multiple independent causes for the idle CPU spin, or the same root cause manifests differently depending on session state and platform.