[BUG] Idle session pinned at ~100% CPU — event-loop busy-spin (kevent64 immediate-return) on macOS ARM64, v2.1.177
Summary
On macOS (Apple Silicon), idle Claude Code CLI sessions intermittently get pinned at ~100% CPU with the main thread stuck in an event-loop busy-spin. This happens with no user activity and no agent task running — the machine heats up and fans spin while the terminal becomes laggy / unable to accept input. This looks like the same class of problem as #17148, #10493, #21006, #18532, #22275, #19393, #11122.
I'm attaching 5 consecutive /usr/bin/sample captures that pin down the spin, in case the stacks help.
Environment
- Claude Code: v2.1.177
- OS: macOS 15.7.3 (24G419), Apple Silicon (ARM64)
- Launched via:
claude --dangerously-skip-permissions(several long-lived sessions, some via--resume, parentzsh) - Several MCP servers / plugins active (oh-my-claudecode bridge, codegraph MCP, etc.)
What happened
Activity Monitor showed three separate claude (shown as 2.1.177) processes each at 99.7–99.9% CPU simultaneously, with huge accumulated CPU time while the machine was idle:
| PID | Elapsed | Accumulated CPU time |
|-------|-------------|----------------------|
| 12343 | 1d 14h | ~4h38m |
| 30623 | 9h 37m | ~3h20m |
| 57104 | 8h 56m | ~2h27m |
These were idle sessions (no prompt running) yet had burned hours of CPU.
Evidence (sampling)
I captured the worst offender (pid 12343) with sample 5 times in a row. Key observations:
- All 5 captures are byte-for-byte identical → the process is locked in a stable repeating state.
- The main thread (
com.apple.main-thread) sits in the event loop withkevent64returning immediately and being re-armed in a tight loop (note the varied return offsets), rather than blocking:
2156 start (in dyld)
2156 ??? (in 2.1.177) ... <-- main entry
1781 ??? (in 2.1.177) + 0x1014354
! 1649 ??? (in 2.1.177) + 0x85dc04
! : 1640 kevent64 (in libsystem_kernel.dylib) + 8,4,... <-- spinning, immediate return
- "Sort by top of stack" is dominated by waiting/polling primitives (worker threads parked, main loop churning), with no single hot compute frame — the classic signature of a wake/poll storm rather than real work:
__psynch_cvwait 21560
__ulock_wait2 21560
kevent64 3796
mach_msg2_trap 2156
This lines up with #17148 (uv__run_check → CheckImmediate → setImmediate() busy-wait) and #10493 (non-blocking poll + immediate retry), except on macOS the spin surfaces through kevent64 instead of epoll_pwait.
Recovery behavior (matches #21006)
When the terminal was frozen and unresponsive, simply opening a new Claude session knocked the stuck session out of the spin — without killing it. Right after, the stuck PIDs dropped to ~0.1–0.3% CPU and their accumulated CPU time stopped growing (only +0.2–0.4s over several minutes). The process stayed alive but idle. This is the same "new session in the same dir recovers it" behavior reported in #21006.
So it appears to be an intermittent UI/event-loop spin that a terminal state change (SIGWINCH / focus / foreground-pgrp change) can break out of.
Contributing factor
Multiple long-lived idle sessions accumulating in the background made this much more likely / more impactful (9+ claude processes were running, several 8h–2d old) — consistent with #11122.
Sample files
Full 5 captures (no sensitive data — sample auto-redacts user paths to /Users/USER/*, and the binary is stripped):
👉 https://gist.github.com/echo-layker/1d38915d4cbdfa27de2672a21cc22f21
Repro
Intermittent. Leave one or more claude sessions open and idle for hours on macOS ARM64; some sessions eventually enter the 100% CPU spin. Hard to trigger on demand.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗