High CPU usage (100%+) when Claude Code instances are idle - v2.1.12

Open 💬 26 comments Opened Jan 20, 2026 by vanman2024

Description

Claude Code instances are consuming excessive CPU (100%+) even when idle/waiting for input. This makes the tool nearly unusable - constant freezing, lag when typing, and fans running constantly.

Environment

  • Claude Code Version: 2.1.12
  • OS: Ubuntu on WSL2 (Linux 5.15.167.4-microsoft-standard-WSL2)
  • Node: v22.20.0
  • RAM: 24GB (plenty available)

Observed Behavior

Two Claude Code instances running showed:

PID 26557 (claude --resume): 105-130% CPU
PID 7530 (claude): 59-70% CPU

This is sustained CPU usage while idle - not during tool execution or API calls.

Impact

  • Terminal becomes unresponsive
  • Have to repeatedly press Escape to interrupt
  • Typing lag even in VS Code (resource contention)
  • Unusable for development work

Timeline

Started approximately 2 weeks ago. Was working fine before.

Additional Context

  • Multiple MCP servers enabled (may be contributing)
  • Large ~/.claude/projects/ directory (cleaned up, didn't help CPU issue)
  • Killing and restarting doesn't resolve - new instances also spin CPU

Steps to Reproduce

  1. Start Claude Code in a terminal
  2. Observe CPU usage with top or ps aux
  3. Note sustained 50-130% CPU even when Claude is idle waiting for input

Expected Behavior

Claude Code should use minimal CPU when idle/waiting for user input.

View original on GitHub ↗

26 Comments

github-actions[bot] · 5 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/17148
  2. https://github.com/anthropics/claude-code/issues/17880
  3. https://github.com/anthropics/claude-code/issues/19064

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

Chapoly1305 · 5 months ago

Observed similar issue on macOS 15.

Butanium · 5 months ago

yeah our cluster login node went down due to this issue lol: login node cpus were fully used by idling claude sessions

dzek69 · 5 months ago

For me CPU usage is much worse (~90% of single core) if i type /hooks, select Stop, where I have defined one hook (idk if this matters) and I leave it on this screen.

If I go back to the main input mode, it's all fine.

agustinprod · 5 months ago

Additional data from v2.1.17 (macOS ARM64) - Same issue persists

Environment

  • Claude Code version: 2.1.17
  • OS: macOS 26.0.1 (Darwin 25.0.0)
  • Platform: ARM64 (Apple Silicon)
  • Process uptime when sampled: 4+ hours

Symptoms

  • Process showing "modelo no aparece" (model not appearing) in terminal title
  • 0 TCP connections to API but 66% CPU usage
  • Process stuck in reconnection/render loop
  • Oscillating CPU: 0-1% (sleeping) → 100%+ (running) intermittently

Profiling Data (5-second sample)

Top syscalls by sample count:
__ulock_wait2 47,278 samples ← Lock contention
__psynch_cvwait 21,462 samples ← Condition variable wait
kevent64 7,829 samples ← Event loop
mach_msg2_trap 4,301 samples
__workq_kernreturn 4,298 samples

Critical Finding: All Bun Pool threads blocked on same lock

Thread_1075895: Bun Pool 0
→ 0x51b648 → 0x89a89c → 0x51bde4 → 0x2e52a14 → __ulock_wait2 (BLOCKED)

Thread_1075896: Bun Pool 1
→ 0x51b648 → 0x89a89c → 0x51bde4 → 0x2e52a14 → __ulock_wait2 (BLOCKED)

Thread_1075897: Bun Pool 2
→ 0x51b648 → 0x89a89c → 0x51bde4 → 0x2e52a14 → __ulock_wait2 (BLOCKED)

[... same pattern for all 11 Bun Pool threads]

All 11 Bun Pool worker threads are waiting on the same lock at offset 0x2e52a14 in the binary, causing massive lock contention.

Thread CPU Distribution

Main Thread: ~20% (kevent64 + JS execution bursts)
Heap Helper (x3): waiting on pthread_cond_wait
Bun Pool (x11): ALL blocked on __ulock_wait2
JIT Worklist Helper: waiting on pthread_cond_wait

Memory

  • Current: 1.4GB RSS
  • Peak: 9.6GB (suggests large JSON processing at some point)

Open file descriptors

  • Only 63 FDs open
  • No session JSONL file open (abnormal - should have one)
  • No TCP connections (lost connection to API)
  • Only reading: settings.json, settings.local.json, stats-cache.json
Chapoly1305 · 5 months ago

I gave up because it lags so much. I turned to Codex.

yulonglin · 5 months ago

Pretty annoying, but here's a small workaround to clear Claude Code sessions in the background in case anyone finds it helpful!

https://github.com/anthropics/claude-code/issues/4953#issuecomment-3792297455

Bastien59960 · 5 months ago

Same here on ubuntu serveur 100% processor usage on one core when the limit is reached ! I'm not happy with that !

!Image

infactai · 5 months ago

Same bug. Linux. Been going on both months, but more common now with tasks + sub-agents.

yrks12 · 5 months ago

Additional findings from M4 Pro MacBook (macOS 26.2)

Environment

  • Device: MacBook Pro M4 Pro
  • OS: macOS 26.2 (Darwin 25.2.0)
  • Claude versions observed: 2.1.17, 2.1.21, 2.1.25

Observations

Multiple idle Claude CLI sessions consuming 40-80% CPU each:

| PID | Version | CPU | Running For | Total CPU Time |
|-----|---------|-----|-------------|----------------|
| 28394 | 2.1.17 | 48% | 7 days | 57 hours accumulated |
| 1951 | 2.1.21 | 77% | 2 days | 11.5 hours accumulated |
| 42313 | 2.1.25 | 34% | 20 min | 1.7 min |

The older versions (2.1.17, 2.1.21) appear to have worse CPU usage than 2.1.25, but all versions exhibit the idle CPU bug.

Impact

  • Battery drain from 100% to 0% in ~4 hours on M4 Pro (should last 15-20 hours)
  • System load average constantly at 6-8 with multiple sessions
  • caffeinate child processes spawned by Claude prevent system sleep

Process sampling

sample output shows continuous activity in the main thread even when waiting for input - consistent with the busy-wait/lock contention theory.

Workaround

Killing old Claude sessions immediately drops system load. But this loses conversation context.

Would appreciate a fix - having to manually kill sessions to preserve battery life is not ideal.

kerim · 5 months ago

Same issue on MacBook Air running macOS 26.2 and claude code 2.1.29

spkrka · 5 months ago

I've been investigating this issue and found some interesting data that might help narrow down the root cause.

_Note: This analysis was developed collaboratively - a human user investigating the issue worked with Claude (AI) to analyze the strace data and formulate this hypothesis._

Strace Evidence: Event Loop Polling Pattern

I ran strace on an idle Claude Code process (v2.1.29 on Linux) and observed constant event loop activity:

$ timeout 10 strace -p <pid> -e epoll_pwait2 -c
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00    0.013534          10      1235           epoll_pwait2

~123 epoll calls per second even when idle. Here's a sample of the timeout values:

epoll_pwait2(4, [...], 1024, {tv_sec=0, tv_nsec=0}, [], 8) = 6
epoll_pwait2(4, [...], 1024, {tv_sec=0, tv_nsec=2999995}, [], 8) = 1
epoll_pwait2(4, [...], 1024, {tv_sec=0, tv_nsec=0}, [], 8) = 4
epoll_pwait2(4, [], 1024, {tv_sec=0, tv_nsec=3991058}, [], 8) = 0

The key observation: many calls use {tv_sec=0, tv_nsec=0} (0ms timeout = "return immediately"). This is polling behavior - the CPU never sleeps.

What This Suggests

A truly idle process should either:

  1. Block indefinitely (NULL timeout) until I/O events arrive, or
  2. Use meaningful sleep timeouts

The 0ms timeouts suggest the event loop never reaches a fully idle state. This matches @agustinprod's profiling data showing oscillating CPU usage between 0-1% and 100%.

Root Cause Hypothesis: Infinite Callback Chain

The most common cause of this pattern is callbacks that continuously generate new callbacks, preventing the event loop from ever draining:

// Example patterns:

// Recursive setImmediate
function doWork() {
    // ... work ...
    setImmediate(doWork);  // ⚠️ Schedules itself forever
}

// Infinite promise chains
function keepGoing() {
    return Promise.resolve().then(() => {
        return keepGoing();  // ⚠️ Never terminates
    });
}

// Self-rescheduling short timers
setInterval(() => {
    setImmediate(someCallback);
}, 1);  // ⚠️ Generates immediate work constantly

Even one instance of this pattern anywhere in the codebase (or in a dependency) will keep the event loop perpetually "active".

Workaround That Confirms The Diagnosis

I created an LD_PRELOAD wrapper that intercepts epoll_pwait2 and enforces a minimum 16ms timeout (replacing any 0ms timeouts):

int epoll_pwait2(int fd, struct epoll_event *events, int maxevents,
                 const struct timespec *timeout, const sigset_t *sigmask) {
    struct timespec min_timeout = {.tv_sec = 0, .tv_nsec = 16000000};  // 16ms

    if (!timeout || (timeout->tv_sec == 0 && timeout->tv_nsec == 0)) {
        timeout = &min_timeout;
    }

    return real_epoll_pwait2(fd, events, maxevents, timeout, sigmask);
}

Result: CPU usage drops from 50-100% to ~5-10%. This confirms the issue is the constant 0ms polling.

Suggested Investigation for Anthropic Team

Since you have access to the source code, here's a prompt you could use with Claude (or any AI tool) to audit the codebase for problematic patterns:

---

AI Audit Prompt:

I need to find patterns in our codebase that could cause infinite event loop activity.
Please search for:

1. SETIMMEDIATE RECURSION
   - Functions that call setImmediate() to schedule themselves
   - Pattern: setImmediate(functionName) inside functionName's definition

2. INFINITE PROMISE CHAINS
   - Functions that return Promise.resolve().then(() => recursiveCall())
   - Async functions that await themselves in a loop without exit condition

3. TIGHT TIMER LOOPS
   - setInterval with intervals < 10ms
   - setTimeout that immediately reschedules itself with 0 or very small delay

4. EVENT LISTENER LOOPS
   - Event listeners that emit the same event they're listening to
   - Cyclical event patterns

5. POLLING PATTERNS
   - while(true) loops with async operations but no await/delay
   - Recursive async functions without proper yielding

For each match:
- Show file path and line number
- Explain why this could cause infinite loop activity
- Indicate if this is intentional (e.g., server main loop) or likely a bug

Focus on background services, watchers, monitoring code, connection pools,
retry logic, and cache refresh mechanisms.

---

Additional Investigation Ideas

  1. Git bisect: Find which commit introduced the high CPU usage
  2. Dependency audit: Check if a recent dependency update introduced the pattern
  3. Runtime profiling: Use --inspect to see what JavaScript runs between epoll calls
  4. Feature isolation: Disable features one by one to narrow down the source

Why This Correlates With Thread Lock Issues

This could explain @agustinprod's observation of "11 Bun Pool threads blocked on the same lock":

  • If the event loop never idles, worker threads may be constantly contending for locks
  • The oscillating CPU (0-1% to 100%) matches the pattern of: drain batch → brief pause → new work arrives → drain batch

Hope this helps narrow down the investigation! Happy to provide more details or test potential fixes.

duboisf · 5 months ago

Had similar symptoms (high cpu use, laggy text input, even when idling). I fixed it (in my case) by uninstalling all MCPs and plugins. Disabling didn't help, had to uninstall. Might still be a bug in claude code but in my particular case it's one of the MCPs/plugins at fault (need to figure out which one).

spkrka · 5 months ago

Seems to be fixed by 2.1.31 (which is the auto-update I got - may also be in 2.1.30)

cstahie · 5 months ago

Same issue here. MacOS w/ Apple silicon. An idle session since yesterday is eating 100% cpu. Another instance from a few hours ago (prompt and task finished, should be idle) is eating 30% cpu.

Had to kill the big offender to use machine properly. Then used another Claude Code instance to investigate itself on the 25% CPU but idle session. It said:
-------
Claude CLI Bug

Root Cause: The Claude CLI (PID 47169) has a bug where it continuously runs ICU text segmentation (icu::RuleBasedBreakIterator) for terminal rendering even when completely idle.

Evidence:

  • 47+ minutes of CPU time accumulated on an idle session
  • 8-32% CPU constantly fluctuating (not the VS Code MCP connection - that's at 0%)
  • Heavy ubrk_clone, ubrk_next, ubrk_current calls in sampling
  • This is text wrapping/layout calculation running in a loop

Workaround:
kill 47169

This appears to be a bug in Claude CLI v2.1.31's terminal rendering - you may want to report it

-------

If you search issues here you will find tens or more similar cases reported. Chose this issue as it had enough comments. If Anthropic is not fixing this, you can consider they started mining bitcoins with their agents or at least competing on who wastes more power globally. 😄

pkit · 5 months ago

@cstahie I can confirm that RuleBasedBreakIterator is on the hot path in 2.1.31
Looks like the problem is not "running text segmentation" but that it never reuses RuleBasedBreakIterator instance and just creates a brand new one each loop (every 16ms for 60 fps)

ei-grad · 4 months ago

For me it is still same on 2.1.44

mossein · 4 months ago

Still reproducing on v2.1.51 (macOS, Apple M-series).

Single idle session sitting at 90% CPU right now. No MCPs, no plugins, no hooks configured.

One additional data point that may be compounding the issue for long-term users: my ~/.claude/projects/ directory has 128 .jsonl session files totaling 271MB, but only 3 are tracked in sessions-index.json. The other 125 are orphaned. It's unclear whether these are being scanned/loaded at runtime, but it seems like there's no garbage collection for old session files — they just accumulate indefinitely.

Even if the orphaned files aren't the CPU issue itself, it feels like a separate bug worth noting: session files are never cleaned up, and there's no size cap or TTL.

The core 60fps rendering loop identified by @spkrka and the RuleBasedBreakIterator re-instantiation every frame identified by @pkit seem like the real fix needed here. Any update on whether either of those are being addressed?

mark14wu · 4 months ago

Still reproducing on our shared university cluster (Slurm). Multiple idle Claude Code sessions accumulate enough CPU load to degrade the login node for all users. This has been a recurring issue for us, literally every day. Looking forward to a fix ASAP.

ei-grad · 4 months ago
Looking forward to a fix ASAP.

Tried to write to the support on a similar case - it is hard to go over AI bot, which can't even make an internal ticket, and when I reached support engineer - dialog was closed immediately with a rude standard unrelated response. No one at Anthropic is aware/bothered of this issue.

sctinmarius · 3 months ago

On my MacBook (running macOS Tahoe), I noticed an issue when allow to runing tests during a session.
The agent opens multiple Node.js (Vitest) instances, causing a sudden spike in CPU usage 😞

As a workaround, I am switching to "ask me before running" the tests.

patrick-elmore · 2 months ago

Posting a brief WSL2-specific data point here since this is the most active WSL2 thread. Full quantified data, reproduction commands, and cross-references are in #22275.

The unusual signal in my reproduction: not all idle sessions are affected. Same WSL2/Ubuntu 24.04 + Windows Terminal, claude 2.1.128, 7 concurrent idle sessions. With 4 idle claudes on identical version / model / repo, all four write the same 8 bytes/sec to their pty (~1 write syscall/sec). Only some receive ~50 bytes/sec back from the pty (~2 read syscalls/sec):

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

On the Windows side, the wsl.exe relay processes for the looping sessions burn 15-21% of one core each, with thread count grown from 4 to 7-12. Relays for the silent sessions burn 0% with the normal 4 threads. Same Windows Terminal instance, same uptime, same configuration. Once a relay is in the looping state it stays there for its lifetime. Restarting the affected tab spawns a fresh wsl.exe relay that may or may not enter the loop on the new connection.

This may explain the variance in reports here. Small numbers of sessions tend to all hit the loop (uniform 100% spinning). Larger numbers show partial effects (some looping, some silent). The differentiator is on the terminal-side, not in claude itself.

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. Same workaround validated in microsoft/terminal#17787 discussions.

Full reproduction commands (Linux + PowerShell), per-relay measurements, and cross-references including microsoft/terminal#19772 (where WT maintainer @lhecker identifies the Ink re-render-everything pattern as the root cause) are in #22275.

TelpeNight · 1 month ago

It is not fixed up to stable 2.1.153

johanneslarsson · 27 days ago

Yes, I have the same issue. Usually it also freezes the claude code session so its non responsive and has to be killed.

Still a problem in 2.1.179 for me

OS: macOS Ventura 13.7.8 x86_64
Host: MacBook Pro (15-inch, 2017)
Kernel: Darwin 22.6.0
Shell: fish 4.3.3
Terminal: ghostty 1.3.2-main-+e8e7fea10

I end up here when I leave claude code prompt open and lock the screen over the night.

CaseReed · 24 days ago

Same problem here, still happening on the latest version 2.1.185.

Setup:

  • MacBook Pro M5 (Apple Silicon, 10 cores), 32 GB RAM
  • macOS 26.5.1 (build 25F80)
  • Claude Code 2.1.185
  • Terminal: Warp, 4 Claude Code sessions open at the same time
  • I also have several MCP servers enabled

What I see: the Mac runs hot, around 80C or 95C (read from CleanMyMac), even when all 4 sessions are idle and I am not typing. Fans stay on.

Numbers I captured while idle:

Claude Code   : 2.1.185
macOS         : 26.5.1 (25F80)
Chip / cores  : Apple M5 / 10 cores
RAM           : 32 GB
node procs    : 56 total (sessions + their MCP servers)
load average  : 5.44, 4.40, 4.29  (on 10 cores)
CPU snapshot  : about 35% busy, 65% idle (top -l 1)
memory in use : 30 GB of 32 GB

One detail that may help: in my case no single node process shows 100% in ps aux. The top ones read about 0% at the snapshot (the %CPU column there is a lifetime average). But the load average stays above 5 on a 10 core machine and the chip stays hot even when nothing is running. So for me it is not one process pegged at 100%, it looks more like many small wakeups that add up.

This fits the pty data point in #22275, where each idle session keeps doing tiny pty reads and writes (about 1 to 2 syscalls per second). With 4 sessions plus their MCP servers, that is a lot of constant small wakeups, which keeps the cores busy and warm.

Happy to run anything that helps narrow it down (powermetrics, fs_usage or dtrace on a given pid).

CaseReed · 8 days ago

@anthropics really need to fix this problem.. very bad for health of my laptop.