[BUG] Per-session 1Hz `sh -c 'sleep 1' + date + ps` exec loop generates EDR telemetry storm & battery drain
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Each running claude CLI process spawns a fresh /bin/sh -c ... subprocess approximately once per second, which in turn execs /bin/date, /bin/ps, and /bin/sleep 1. Every iteration creates brand-new (sequential) bash PIDs — i.e. the loop is shell-based, not a persistent child. With N Claude Code sessions open, this produces ~3N short-lived processes per second system-wide.
On machines with endpoint-security software that logs every exec() (FortiDLP, Tanium, CrowdStrike, etc.), this causes a sustained telemetry storm: every sleep, date, and ps is written to the EDR log, which drives measurable CPU/battery drain.
Key observations:
- Fresh bash PID per iteration (28853649 → 28853676 → 28853692 → ...). The loop is invoking
system()/child_process.exec('sh -c ...')rather than keeping a persistent helper alive. - Order is always
date → ps → sleep, repeating every ~600–700 ms per session. - Each
claudechild process I can see viapshas a livesleep 1child with matching PPID:
``claude
28941 33514 sleep 1 # parent PID 33514 is a processclaude
28939 99189 sleep 1 # parent PID 99189 is a process``
28937 76700 sleep 1
28936 34817 sleep 1
Measured impact
Over a 30-second fs_usage -f exec capture on my machine (5 Claude sessions open):
| Child process (parent = bash) | Count in 30s |
|---|---:|
| /bin/date | 54 |
| /bin/sleep | 47 |
| /bin/ps | 47 |
| /bin/cat | 15 |
| Total bash-spawned execs | ~167 |
That is ~5.6 execs/sec from Claude Code alone, i.e. just over 1 full iteration per session per second. The cat entries are likely a separate helper (perhaps stdin reads), but the date/ps/sleep triad is the dominant, persistent pattern.
What Should Happen?
Idle Claude Code instances should not spawn subprocesses, as this causes significant CPU activity on machines with enterprise security software.
Error Messages/Logs
Steps to Reproduce
On macOS:
# While any Claude Code instance is running (but idle):
sudo /usr/bin/fs_usage -w -f exec bash sh 2>/dev/null | head -60
You will see a repeating triad per active Claude session:
17:41:31.970926 execve /bin/date 0.001004 bash.28853649
17:41:31.988497 execve /bin/ps 0.001770 bash.28853651
17:41:32.100139 execve /bin/sleep 0.000308 bash.28853654
17:41:32.613523 execve /bin/date 0.000449 bash.28853676
17:41:32.622288 execve /bin/ps 0.000344 bash.28853678
17:41:32.709861 execve /bin/sleep 0.000252 bash.28853683
17:41:33.219743 execve /bin/date 0.000316 bash.28853692
17:41:33.229838 execve /bin/ps 0.000256 bash.28853694
17:41:33.292868 execve /bin/sleep 0.000273 bash.28853696
...
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.132
Platform
AWS Bedrock
Operating System
macOS
Terminal/Shell
Other
Additional Information
Suggested fix
Replace the sh -c polling loop with an in-process timer. In Node this is as simple as setTimeout(tick, 1000) — no subprocess required, and the tick callback can read Date.now() and inspect the parent/children (if needed) via /proc or libproc/kinfo_proc bindings without fork+exec.
If the loop specifically needs:
- a timestamp →
Date.now()instead ofexec('date') - a parent-alive check →
process.kill(ppid, 0)orkqueue EVFILT_PROC NOTE_EXIT - process-list scanning → macOS
libproc'sproc_listallpids, or on Linuxreaddir('/proc'); avoidexec('ps') - a 1s delay →
setTimeout/setInterval
Any of these eliminate the exec entirely and make the loop invisible to EDR.
Cross-references
Possibly related issues:
- #22509 — macOS high CPU at idle (open)
- #22275 — Linux equivalent (open)
- #17142 —
sched_yield/futexbusy-wait - #22633 — main thread
STAT=Rbusy-wait
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗