[Bug] --bg-pty-host processes spin to ~99% CPU per process while wrapped --bg-spare is idle (v2.1.162, macOS)
Environment
- Claude Code version: 2.1.162
- OS: macOS 15.7.7 (24G720), Apple Silicon / x86-64
- Daemon mode: transient (on-demand)
Summary
--bg-pty-host wrapper processes gradually spin up to ~99% CPU each, even when the --bg-spare instance they wrap is completely idle (≤0.1% CPU). Multiple pty-host processes can hit 99% simultaneously, causing 200–300% total CPU drain with just 1–2 sessions.
Steps to reproduce
- Open 1–2 Claude Code sessions (shell + one background fleet job)
- Leave both sessions idle for ~30–40 minutes
- Observe CPU in Activity Monitor or
ps aux
Observed behavior
After ~36 minutes of uptime, two --bg-pty-host processes were each at 99.3% CPU, while the --bg-spare processes they wrap were at 0.1%:
PID %CPU COMMAND
22205 99.3 --bg-pty-host .../254a019d.pty.sock 200 50 -- claude --bg-spare .../254a019d.claim.sock
22208 99.3 --bg-pty-host .../7247fa01.pty.sock 200 50 -- claude --bg-spare .../7247fa01.claim.sock
22209 0.1 --bg-spare .../254a019d.claim.sock ← wrapped by 22205, idle
22211 0.1 --bg-spare .../7247fa01.claim.sock ← wrapped by 22208, idle
CPU time accumulated per process: ~12.5 minutes of CPU in ~36 minutes of wall time (~34% average, peaking at 99%).
Additional observations
- SIGTERM is ignored by the spinning pty-host processes;
kill -9is required. - After SIGKILL, the daemon immediately respawns fresh pty-hosts at 0% CPU.
- The affected processes were orphaned spares adopted from a previous daemon instance (daemon PID 22197 shut down; new daemon 26458 adopted them via
bg adopt: adopted=2). - The spare processes themselves never exceed 0.2% CPU during the entire episode.
sample output (3s sample of PID 22205 at 99% CPU)
Call graph:
180 Thread_2853889 DispatchQueue_1: com.apple.main-thread (serial)
+ 180 start (in dyld)
+ 180 ??? (in 2.1.162)
+ 180 ??? (in 2.1.162)
+ 180 ??? (in 2.1.162)
+ 148 ??? (in 2.1.162) [0x10789f929]
+ ! 124 ??? (in 2.1.162)
+ ! : 124 kevent64 (in libsystem_kernel.dylib) ← busy event loop
+ ! 13 ??? (in 2.1.162) [0xca3f07] → PTY read/write path
+ ! 4 ??? (in 2.1.162) → os_unfair_lock_{lock,unlock}
The pty-host spends nearly all its time in a kevent64 loop, waking up far more frequently than an idle PTY should trigger.
Relevant daemon log
[00:13:14Z] bg spare spawned host pid=22205
[00:13:14Z] bg claimed-spare 521b6fd9 (spare) → spare spawned host pid=22208
[00:13:41Z] bg claimed-spare 985e0f80 (shell) → spare spawned host pid=22327
...
[00:49:56Z] supervisor shutting down ← old daemon 22197 dies
[00:49:57Z] supervisor daemon start pid=26458
[00:49:57Z] bg adopt: adopted=2 respawned=0 dead=0
[00:49:57Z] bg orphan-spare reap: 1
The pty-hosts 22205 and 22208 were spawned under daemon 22197, adopted by daemon 26458, and continued spinning until manually killed.
Expected behavior
--bg-pty-host processes should consume negligible CPU (≤1%) when the wrapped spare instance is idle, regardless of uptime or daemon restarts.
Workaround
# Kill only the spinning pty-host processes (safe if no session is using that spare):
kill -9 <pty-host-pid>
# Or stop the entire daemon:
claude daemon stopThis issue has 2 comments on GitHub. Read the full discussion on GitHub ↗