You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Host-specific: melo-desk-001 (Windows 11 Pro 10.0.26200, Intel Core Ultra 9 285K, 24 logical CPUs, 64 GB). Not a plugin defect. Filed so the diagnosis captured on 2026-09-04 is not lost, and so the follow-up (reboot, then attribute the leaker from an admin shell) can run in a fresh session. Needs a human with an elevated shell; not agent-ready.
Symptom
Every process creation on the host costs 1.4 to 4 s, system-wide, at 6 to 7% CPU load with 26 to 30 GB of RAM free. This is not Claude Code churn: it reproduces from a bare PowerShell with nothing else on the critical path.
probe (2026-09-04, ~03:30 to 12:30 local)
measured
this host's documented healthy floor (claude-ops/skills/audit-performance/reference/known-performance-issues.md)
cmd /c exit 0 via [Diagnostics.Process]::Start, absolute path, no PATH search
1,339 to 1,573 ms
206 ms
jq -n 1 from PowerShell (absolute path)
1,599 to 2,546 ms
not recorded
bash -c true (Git Bash usr/bin/bash.exe)
3,555 to 4,347 ms
123 ms drained, 1,144 ms under a 13-session storm
$(echo hi) subshell (MSYS fork, no exec)
769 to 2,271 ms
not recorded
claude --version
4,113 ms
not recorded
claude plugin list
5,780 ms
not recorded
Split of one cmd.exe creation with CREATE_SUSPENDED (P/Invoke CreateProcess, then ResumeThread + wait): kernel-side create 668 ms, resume-to-exit 683 ms. For jq.exe: 1,488 ms + 1,058 ms. The kernel half alone is 3 to 7x the whole healthy spawn, so the cost is inside process creation itself, not in DLL loading or the console layer.
Consequence measured on the plugin fleet: one claude-opsfleet-state.sh run (736 process creations at the time) took 17.0 minutes; the pre-rewrite --all mode took 51 minutes; each Bash tool call in a Claude Code session carries 30 to 60 s of overhead. PR #3714 cuts the script to 12 creations, but the per-creation floor is the host's.
Kernel state (the lead)
Kernel object-type table via NtQueryObject(NULL, ObjectTypesInformation):
type
objects
handles
high-water objects
Token
3,811,482 → 3,813,997 within an hour
1,739
equal to current (never freed since boot)
Key
189,005
189,011
189,595
File
170,466
18,926
279,542
Event
67,560
72,546
EtwRegistration
50,926
50,926
Section
30,744
10,046
70,603
Process
837 to 901 (\Objects\Processes) vs 611 to 664 visible
1,364
Pool: paged 9,894 MB, nonpaged 2,452 MB (\Memory\Pool Paged Bytes, \Memory\Pool Nonpaged Bytes). 3.8M tokens at a realistic 2 to 3 KB each accounts for the paged pool. Token growth rate at "idle" (other sessions running): 6.6 to 13.9 tokens/s; 20 cmd /c exit spawns did not raise it beyond background, so the minter is not per-process-creation but something continuous (impersonation-shaped, e.g. RPC/ALPC or a driver IOCTL path).
Uptime at capture: 2 days 0 h 55 min (boot 2026-09-02 02:53:19Z). No Resource-Exhaustion-Detector or pool events in the System log.
What was ruled out (measured, not assumed)
Session churn / spinning shells. 190 to 214 bash.exe and 65 to 71 conhost.exe alive; 43 bash are direct children of 6 claude.exe sessions, ~53 are orphans. Four bash.exe running skill-quality/scripts/check-skill.sh --require-evals <legacy|newbie> from /tmp/tmp.* test copies have been spinning since Sept 2 to 3 with no child processes (PIDs 25092 at 8,391 CPU-s, 12704 at 5,409, 61144 at 2,333, 55592). Suspending all four with NtSuspendProcess moved the spawn floor from 2,978 to 2,514 ms (15%). Resumed afterwards. They are victims and a separate defect (a shell loop in check-skill.sh that never terminates on this host), not the cause.
ASUS ADU.exe (PID 2516, user session, elevated). Holds 174,378 handles, 173,808 of one type (registry Key). Suspending it changed nothing. A real leak, but not this one.
Antivirus / EDR.WinDefend, Sense, WdNisSvc all Stopped; WdFilter not loaded; no third-party security process or minifilter visible (fltmc needs admin). Get-MpComputerStatus: provider load failure.
WDAC / Smart App Control / AppLocker / AppInit / IFEO. Kernel CI enforced (HVCI), user-mode CI off, Smart App Control 0, no AppLocker rules, LoadAppInit_DLLs 0, IFEO not readable without admin.
PATH. 36 entries, all present, none UNC, longest probe 14 ms. Absolute-path CreateProcess is equally slow.
AppCompat. 12 custom shims, 208 PCA store entries. Not unusual.
Tracing tools. No procmon/sysmon/wpr/xperf running; logman query -ets shows no sessions (unprivileged view).
Non-Microsoft kernel drivers running: ASUS AsIO3.sys, IOMap64.sys; MICSYS MsIo64.sys; Creative CtiAIo64.sys; NVIDIA nvlddmkm, nvhda64v, nvvad64v; Intel platform/graphics/NPU set; Realtek audio/NIC/BT. The three raw-I/O drivers (AsIO3, IOMap64, MsIo64) are polled continuously by Armoury Crate / lighting services, which is the profile that fits a per-IOCTL token or reference leak, but this is a hypothesis, not a measurement.
Add-Type-TypeDefinition @'using System; using System.Runtime.InteropServices;public static class ObjTypes { [DllImport("ntdll.dll")] static extern int NtQueryObject(IntPtr h, int cls, IntPtr buf, int len, out int ret); public static long Count(string type) { int len=1024*1024; IntPtr buf=Marshal.AllocHGlobal(len); int ret; if (NtQueryObject(IntPtr.Zero,3,buf,len,out ret)!=0) return -1; int n=Marshal.ReadInt32(buf); IntPtr p=buf+8; long r=-1; for (int i=0;i<n;i++){ ushort nl=(ushort)Marshal.ReadInt16(p,0); ushort nm=(ushort)Marshal.ReadInt16(p,2); string name=Marshal.PtrToStringUni(Marshal.ReadIntPtr(p,8),nl/2); if(name==type){ r=(uint)Marshal.ReadInt32(p,16); break;} p=p+(0x68+((nm+7)&~7)); } Marshal.FreeHGlobal(buf); return r; } }'@
[ObjTypes]::Count('Token'); Start-Sleep20; [ObjTypes]::Count('Token')
Capture the pool tag before rebooting, from an admin shell: poolmon -b (WDK) or Process Explorer's kernel memory view; expect Toke to dominate paged pool. If WinDbg is available: !poolused 2 Toke and !token on a sample. This is the one measurement that cannot be taken after a reboot.
Reboot. Then re-run the spawn-floor probe. Expected: cmd /c exit back near 200 ms and bash -c true near 120 ms. If not, the leak is not the cause and this issue needs a different lead.
Attribute the minter after the reboot, from an admin shell: sample [ObjTypes]::Count('Token') over 60 s, then stop one candidate at a time and re-sample: ArmouryCrateService, LightingService (Aura), ROG Live Service, AsusFanControlService, AsusUpdateCheck, asComSvc, then Razer (RzBTLEManager), NVIDIA (nvcontainer), Wispr Flow. A rate that drops to ~0 names the culprit. Growth that persists with all of them stopped points at a Windows component (CloudAP / AzureAD-joined token path is the next suspect; the account is AzureAD\KyleSexton).
Kill the four spinning check-skill.sh shells (PIDs above; verify command lines first, they belong to old sessions) and file the loop as its own skill-quality defect with the --require-evals legacy / newbie fixture names.
Optional: ADU.exe's 174K registry-key handle leak is worth an Armoury Crate update or removal on its own.
Another session's read of the same slowness attributed it to six Claude Code sessions spawning 144 shells in 30 minutes. That churn is real but secondary: the per-creation floor is 10 to 25x this host's own healthy baseline with no storm present, and suspending the busiest shells moved it 15%.
Note
Host-specific:
melo-desk-001(Windows 11 Pro 10.0.26200, Intel Core Ultra 9 285K, 24 logical CPUs, 64 GB). Not a plugin defect. Filed so the diagnosis captured on 2026-09-04 is not lost, and so the follow-up (reboot, then attribute the leaker from an admin shell) can run in a fresh session. Needs a human with an elevated shell; not agent-ready.Symptom
Every process creation on the host costs 1.4 to 4 s, system-wide, at 6 to 7% CPU load with 26 to 30 GB of RAM free. This is not Claude Code churn: it reproduces from a bare PowerShell with nothing else on the critical path.
claude-ops/skills/audit-performance/reference/known-performance-issues.md)cmd /c exit 0via[Diagnostics.Process]::Start, absolute path, no PATH searchjq -n 1from PowerShell (absolute path)bash -c true(Git Bashusr/bin/bash.exe)$(echo hi)subshell (MSYS fork, no exec)claude --versionclaude plugin listSplit of one
cmd.execreation withCREATE_SUSPENDED(P/InvokeCreateProcess, thenResumeThread+ wait): kernel-side create 668 ms, resume-to-exit 683 ms. Forjq.exe: 1,488 ms + 1,058 ms. The kernel half alone is 3 to 7x the whole healthy spawn, so the cost is inside process creation itself, not in DLL loading or the console layer.Consequence measured on the plugin fleet: one
claude-opsfleet-state.shrun (736 process creations at the time) took 17.0 minutes; the pre-rewrite--allmode took 51 minutes; each Bash tool call in a Claude Code session carries 30 to 60 s of overhead. PR #3714 cuts the script to 12 creations, but the per-creation floor is the host's.Kernel state (the lead)
Kernel object-type table via
NtQueryObject(NULL, ObjectTypesInformation):\Objects\Processes) vs 611 to 664 visiblePool: paged 9,894 MB, nonpaged 2,452 MB (
\Memory\Pool Paged Bytes,\Memory\Pool Nonpaged Bytes). 3.8M tokens at a realistic 2 to 3 KB each accounts for the paged pool. Token growth rate at "idle" (other sessions running): 6.6 to 13.9 tokens/s; 20cmd /c exitspawns did not raise it beyond background, so the minter is not per-process-creation but something continuous (impersonation-shaped, e.g. RPC/ALPC or a driver IOCTL path).Uptime at capture: 2 days 0 h 55 min (boot 2026-09-02 02:53:19Z). No Resource-Exhaustion-Detector or pool events in the System log.
What was ruled out (measured, not assumed)
bash.exeand 65 to 71conhost.exealive; 43 bash are direct children of 6claude.exesessions, ~53 are orphans. Fourbash.exerunningskill-quality/scripts/check-skill.sh --require-evals <legacy|newbie>from/tmp/tmp.*test copies have been spinning since Sept 2 to 3 with no child processes (PIDs 25092 at 8,391 CPU-s, 12704 at 5,409, 61144 at 2,333, 55592). Suspending all four withNtSuspendProcessmoved the spawn floor from 2,978 to 2,514 ms (15%). Resumed afterwards. They are victims and a separate defect (a shell loop incheck-skill.shthat never terminates on this host), not the cause.ADU.exe(PID 2516, user session, elevated). Holds 174,378 handles, 173,808 of one type (registryKey). Suspending it changed nothing. A real leak, but not this one.WinDefend,Sense,WdNisSvcall Stopped;WdFilternot loaded; no third-party security process or minifilter visible (fltmc needs admin). Get-MpComputerStatus: provider load failure.LoadAppInit_DLLs0, IFEO not readable without admin.SharedSection=1024,20480,768(defaults).logman query -etsshows no sessions (unprivileged view).Non-Microsoft kernel drivers running: ASUS
AsIO3.sys,IOMap64.sys; MICSYSMsIo64.sys; CreativeCtiAIo64.sys; NVIDIAnvlddmkm,nvhda64v,nvvad64v; Intel platform/graphics/NPU set; Realtek audio/NIC/BT. The three raw-I/O drivers (AsIO3, IOMap64, MsIo64) are polled continuously by Armoury Crate / lighting services, which is the profile that fits a per-IOCTL token or reference leak, but this is a hypothesis, not a measurement.Reproduce the measurements (no admin needed)
Spawn floor:
Token object count (compile once per shell):
Pool:
Get-Counter '\Memory\Pool Paged Bytes','\Memory\Pool Nonpaged Bytes','\Objects\Processes'.Next steps (in order)
poolmon -b(WDK) or Process Explorer's kernel memory view; expectToketo dominate paged pool. If WinDbg is available:!poolused 2 Tokeand!tokenon a sample. This is the one measurement that cannot be taken after a reboot.cmd /c exitback near 200 ms andbash -c truenear 120 ms. If not, the leak is not the cause and this issue needs a different lead.[ObjTypes]::Count('Token')over 60 s, then stop one candidate at a time and re-sample:ArmouryCrateService,LightingService(Aura),ROG Live Service,AsusFanControlService,AsusUpdateCheck,asComSvc, then Razer (RzBTLEManager), NVIDIA (nvcontainer), Wispr Flow. A rate that drops to ~0 names the culprit. Growth that persists with all of them stopped points at a Windows component (CloudAP / AzureAD-joined token path is the next suspect; the account isAzureAD\KyleSexton).check-skill.shshells (PIDs above; verify command lines first, they belong to old sessions) and file the loop as its ownskill-qualitydefect with the--require-evals legacy/newbiefixture names.ADU.exe's 174K registry-key handle leak is worth an Armoury Crate update or removal on its own.Related