.claude/skills/review-resource-leaks/SKILL.md
Audit for memory leaks, handle leaks, GDI leaks, and CPU churn
npx skillsauth add cwilliams5/Alt-Tabby review-resource-leaksInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Enter planning mode. Systematically audit the codebase for resource leaks and unnecessary CPU churn. Use maximum parallelism — spawn explore agents for independent areas.
GDI+ objects (brushes, pens, fonts, bitmaps, graphics) that are created but never deleted. Each leaked object consumes a GDI handle — Windows limits these per-process (~10,000). Over time, leaks cause rendering failures or crashes.
Known safe pattern: D2D_GetCachedBrush and gD2D_Res cache objects intentionally — these are NOT leaks. The rendering pipeline uses D2D now — look for D2D resource create/release patterns and any remaining GDI+ usage in src/lib/.
Look for:
static cached objects per ahk-patterns.md)Handles from DllCall that require explicit cleanup:
CreateFile / CloseHandle — named pipe handles, file handlesOpenProcess / CloseHandle — process handles for icon/info extractionDllCall("SetWinEventHook") / DllCall("UnhookWinEvent") — event hooksLoadImage / DestroyIcon — icon handles (HICON)CreateCompatibleDC / DeleteDC — device contextsLook for handles stored in variables that go out of scope without cleanup, and error paths that skip CloseHandle.
FileOpen() calls where the file object is never closed, or where an error path skips .Close(). Also check for FileAppend in tight loops (each call opens+closes — not a leak, but a performance concern that could be replaced with a single FileOpen + .Write()).
The IPC system uses named pipes (ipc_pipe.ahk). Check that:
SetTimer calls without corresponding SetTimer(callback, 0) to disable. A timer that fires after its context is gone can cause errors or unnecessary CPU work. Also check for one-shot timers (SetTimer(cb, -period)) that should be negative but aren't.
Unnecessary polling or computation when idle:
ahk-patterns.md caller-side log guards)Data structures that grow over time without pruning:
gD2D_Res brush/font cache — intentional lifetime cache, cleaned up on exitstatic buffers in hot-path functions — intentional reuse per ahk-patterns.md.bak sentinel files — intentional crash-safety patternSplit by resource type for independent parallel exploration:
src/gui/gui_paint.ahk, src/gui/gui_overlay.ahk, src/gui/gui_gdip.ahk, any file using D2D_* functions. Some Gdip_* may remain in src/lib/ but the paint pipeline is D2D nowsrc/core/ producers, src/shared/ipc_pipe.ahk, DllCall-heavy files. Use query_function_visibility.ps1 to trace cleanup call chains and query_callchain.ps1 -Reverse to find all callers that should reach cleanup — verify every Create/Open has a corresponding Close/Delete reachable from all callers. Use query_global_ownership.ps1 <resource> to determine who declares and writes resource handles (responsible for cleanup). Use query_impact.ps1 <cleanup_func> to assess the blast radius if a cleanup function is missing or broken.query_timers.ps1 to inventory all timers, then check each for proper cleanupsrc/shared/ipc_pipe.ahk, src/pump/ filessrc/shared/window_list.ahk (window store), icon/process cachesAfter explore agents report back, validate every finding yourself. Resource "leaks" are frequently false positives where cleanup happens in a different function, on a timer, or at process exit.
For each candidate:
file.ahk lines X–Y" with actual code quoted.Group by severity (per-paint > per-event > per-session > theoretical):
| File | Lines | Resource Type | Leak Description | Impact | Fix |
|------|-------|--------------|-----------------|--------|-----|
| file.ahk | 42–58 | D2D Brush | D2D brush created in paint loop, never released | ~60 handles/sec | Use D2D_GetCachedBrush or static |
For CPU churn findings, use a separate table:
| File | Lines | Pattern | Frequency | Fix |
|------|-------|---------|-----------|-----|
| file.ahk | 100–120 | Timer polls every 100ms, no-ops 99% of the time | 10/sec idle | Adaptive interval or event-driven |
Ignore any existing plans — create a fresh one.
tools
Create a new git worktree and switch the session into it
tools
Spawn agent to trace code flow via query tools — answer only, no context cost
tools
Commit, push, and create a PR for the current branch
tools
Retire a shader by moving its files to legacy/shaders_retired