Idle TUI sessions burn 10–40% CPU when an animated element stays on screen

Status Open
Maintainer reply None cached
Activity 1 comment · opened Jul 18, 2026

Environment

  • Claude Code v2.1.214 (Bun-compiled binary)
  • macOS 13.7.8 Ventura, Intel MacBook Pro (2 cores / 4 threads)

Summary

An idle interactive claude session burns 10–40% CPU indefinitely whenever the TUI is displaying any live-updating element (spinner, elapsed-time counter, status ticker). The same binary parked at a plain idle prompt idles at 0.0% CPU. On a small machine a fleet of such sessions saturates the box (observed 1-min load 11–22 on a 4-thread host, with 6 idle sessions at 20–40% CPU each).

Two captured instances (stack-sampled live)

  1. Agents/FleetView dashboard stuck on a task row ✶ … opening… · esc to cancel · Ns for ~8 h → 28.8% CPU, zero established TLS connections. This process also ignored SIGTERM (needed SIGKILL); a healthy idle session exits cleanly on SIGTERM.
  2. Session-limit banner ("You've hit your session limit · resets …") idle at prompt for ~6 h → 10% CPU.

Evidence (from sudo sample <pid> 3 + fs_usage)

  • Main thread parks in kevent64 but wakes constantly to run short JS slices (~12% of main-thread samples in-flight; JIT worklist + heap-helper threads continuously active → sustained JS churn).
  • Zero network syscalls (rules out retry/backoff loop) and zero tty writes in a 3 s window — the TUI isn't even redrawing; the CPU goes to timer/reconciliation work that produces no visible diff.
  • Bonus: the idle process repeatedly stat64s every directory under ~/.claude/skills/* (file-watcher polling), adding wakeups while completely idle.

Discriminator that cleanly separates working from spinning

%CPU > 15 sustained  AND  lsof established-TLS == 0  AND  all children ~0%

Working sessions block on their API socket between token chunks (cheap); sessions with an on-screen animation and nothing to wait for free-run.

Expected

An idle session — including one showing a stalled spinner, a ticker, or the usage-limit banner — should park its render loop (0% CPU like the plain-prompt case) and should exit on SIGTERM.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗