From macos-plugin
macOS EndpointSecurity/EDR high CPU & battery drain. Use when Kandji ESF / XProtect pegs a core; trace the exec storm via powermetrics + eslogger.
How this skill is triggered — by the user, by Claude, or both
Slash command
/macos-plugin:endpoint-security-cpuThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
| Use this skill when... | Use something else when... |
| Use this skill when... | Use something else when... |
|---|---|
| A security extension (Kandji ESF, XProtect, an EDR) sits at sustained high CPU | launchservicesd is the hot process — use launchservices-health |
Battery drains fast and powermetrics blames the security stack | The machine actually hung or panicked — use macos-incident-postmortem |
syspolicyd/trustd/tccd/auditd are all elevated together | One ordinary app is hot — use ps/top directly |
| You suspect a process-spawn (exec) storm is taxing the system | Auditing kernel-extension inventory — systemextensionsctl list alone |
macOS-only. EndpointSecurity, eslogger (macOS 13+), powermetrics, and systemextensionsctl are Darwin-specific.
test "$(uname -s)" = "Darwin" || { echo "macos-plugin: not Darwin, refusing"; exit 1; }
An EndpointSecurity (ES) client — Kandji's ESF extension, XProtect's behavioral service, a corporate EDR — subscribes to the kernel's exec/open/rename event stream. Its CPU is proportional to the system-wide rate of those events. When something spawns hundreds of short-lived processes per second, every behavioral/security monitor must inspect each one, so they light up together:
XprotectService behavioral malware scan, per exec
syspolicyd Gatekeeper code-signing assessment, per binary
io.kandji…ESF corporate EDR, per exec/open
trustd / tccd cert eval / privacy, per access
auditd audit record, per event
kernel_task servicing the syscall + interrupt load
That column lighting up at once is the signature: one exec storm, taxing the whole stack. Restarting the EDR clears its queue for a few seconds, then the storm refills it. The fix is upstream — find and stop whatever is spawning the processes.
A hot ES extension with near-zero wakeups confirms this: it is draining a real inbound event queue in user space, not timer-spinning. High CPU with a high wakeup count and a quiet eslogger points instead at an internally wedged extension — the one case where restarting it (below) actually helps.
Both probes need root. If sudo isn't cached, hand them to the user with the ! prefix.
1. Per-process energy + wakeups — who is taxed, and is it spawn churn?
sudo powermetrics --samplers tasks --show-process-energy -n 1 | head -45
Read three things:
DEAD_TASKS high (CPU + deadlines + wakeups) = a storm of processes that spawned and exited within the sample — the exec churn made visible.2. The EndpointSecurity firehose — name the generator.
eslogger subscribes to the same stream the EDR consumes, and reports the initiating process. Rank the offenders over a short sample:
sudo eslogger exec 2>/dev/null | head -400 | jq -r '.process.executable.path' | sort | uniq -c | sort -rn | head -15
Whatever path dominates is the storm's source. If the stream scrolls instantly to 400 lines, the event rate itself is the problem. If it only trickles while the ESF stays hot, the extension is wedged internally — restart it.
Recurring sources, with the upstream fix that removes the load (not the symptom):
Generator (fingerprint in eslogger) | Fix |
|---|---|
uvx --from git+https://… MCP / tools re-resolving the git source on every launch | Install once (uv tool install git+…) and invoke the bare command |
brew invoked in a loop (portable-ruby + Homebrew bash + git) — often a menubar "outdated" poller or per-invocation auto-update | export HOMEBREW_NO_AUTO_UPDATE=1; throttle/remove the caller |
Many concurrent dev/AI sessions spawning short-lived git/node/bun/gh | Collapse duplicate sessions; dedupe per-session helper servers |
| A status tool shelling out on a tight timer | Lengthen its interval or cache its result |
macOS rewards not rebooting — both the EDR and the inventory are inspectable and (mostly) restartable live.
eslogger trickled while it stayed hot): sudo killall -9 <ESF-process-name>. sysextd relaunches the [activated enabled] extension within seconds. No reboot, no logout.systemextensionsctl list. Over long uptime, each EDR update leaves the prior version as [terminated waiting to uninstall on reboot]. Those are terminated — zero CPU — pure disk/registry cruft that only a reboot clears, and never the performance problem. Don't reboot for them.| Context | Command |
|---|---|
| ESF extension CPU now | ps -Ao pcpu,comm | grep -i ESF-Extension |
| Storm source (top initiators) | sudo eslogger exec 2>/dev/null | head -400 | jq -r '.process.executable.path' | sort | uniq -c | sort -rn | head |
| Security-stack energy snapshot | sudo powermetrics --samplers tasks --show-process-energy -n 1 | head -45 |
| Stale sysext versions (reboot-gated cruft) | systemextensionsctl list | grep -c 'waiting to uninstall' |
| Restart wedged ESF (sysextd relaunches) | sudo killall -9 <esf-process-name> |
| Tool | Role | Root? |
|---|---|---|
powermetrics --samplers tasks | Per-process energy, wakeups, DEAD_TASKS churn | yes |
eslogger exec open rename | The ES event stream the EDR consumes; names the initiator | yes (macOS 13+) |
systemextensionsctl list | Extension inventory + reboot-gated stale versions | no |
ps -Ao pcpu,comm | Instantaneous CPU per process | no |
launchservices-health — when launchservicesd (not an ES extension) is the hot processmacos-incident-postmortem — when the load caused an actual hang/panic; reconstruct from DiagnosticReportsnpx claudepluginhub laurigates/claude-plugins --plugin macos-pluginLive macOS/Apple-Silicon performance triage — find what's heating the Mac (hot WindowServer, GPU compositing, a CPU-heavy browser/Electron app) and attribute it to the driving process. Use when fans spin up, the Mac is hot/slow, or WindowServer/an app shows high CPU/GPU.
Diagnoses macOS workstation issues including kernel panics, failing drives, launchd startup audit, wake reasons, TCC denials, and APFS snapshot space.
Diagnoses and resolves macOS disk and memory issues including kernel panics, Jetsam events, and low disk space. Sets up automated alerting via LaunchAgent and uses Mole for safe cleanup.