Wox Memory Debug

SkillDocs & knowledge

Lets your agent check whether the Wox launcher's memory keeps growing by replaying searches and sampling the process.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Wox Memory Debug skill

About this capability

Diagnose memory leaks in the current single-process Wox Go UI by launching the real debug build with its automation endpoint enabled, replaying representative launcher searches and settings-window open/close cycles, sampling the same process across repeated workload blocks, and comparing Go heap pro

What this skill tells your AI

The instructions your AI receives, as published by wox-launcher/wox in .agents/skills/wox-memory-debug/SKILL.md and read by ahel’s review.

Goal

Run the real Go UI in debug mode with the wox_automation endpoint, exercise normal launcher searches and the independent settings-window lifecycle through the semantics tree, and decide whether memory settles after warm-up or grows with repeated work. Treat Wox as one Go process and use post-warm-up growth rather than an absolute memory budget as the leak criterion.

Run the Debug Build

  1. Stop other Wox instances so sampling cannot select the wrong process.
  2. Start the real Wox debug build under Delve with both production dependencies and the automation endpoint enabled:
cd /Users/qianlifeng/Projects/Wox/wox.core
WOX_AUTOMATION_INFO_FILE=/tmp/wox-memory-automation.json /Users/qianlifeng/go/bin/dlv debug . --build-flags=-tags=sqlite_fts5,wox_automation
  1. At the Delve prompt, run continue.
  2. Wait until startup and plugin initialization finish, then wait for WOX_AUTOMATION_INFO_FILE to be written.
  3. Record the debuggee PID from the debugger. Always pass this PID to the sampler because debugger-built executables may have temporary names.

Keep the debugger running normally. Do not pause at breakpoints while collecting memory samples. This uses the real Wox process with only the automation server compiled in; do not launch the separate Go UI smoke-test runner.

Establish a Warm Baseline

Use the bundled automation workload driver against the real launcher:

cd /Users/qianlifeng/Projects/Wox/wox.core
go run ../.agents/skills/wox-memory-debug/scripts/run-query-workload.go -info /tmp/wox-memory-automation.json -mode queries -count 20 -seed 1
  1. Run two warm-up blocks before recording the baseline.
  2. In each block, replay 20 queries drawn repeatedly from these safe categories:
    • Calculator, such as 1+1.
    • System command lookup, such as settings.
    • Application or general search, such as wox.
    • File-oriented search, such as readme.
  3. Use a different deterministic seed for each block so the workload is reproducible while still varying result types.
  4. The driver waits for the query value, allows results to settle, records the visible result count and semantics generation, clears the query, and continues. It does not execute results or commands.
  5. At the end of the block, the driver hides the launcher. Wait 10 seconds so every checkpoint uses the same idle state.

Take the warm baseline only after these blocks. Initial startup growth, lazy font loading, icon decoding, and cache creation are expected and are not leak evidence.

Sample the Same Process

macOS

/Users/qianlifeng/Projects/Wox/.agents/skills/wox-memory-debug/scripts/sample-wox-memory-macos.sh --pid <PID> --samples 3 --interval 2

Use PhysicalFootprintMB. Absolute debug memory is not the leak criterion.

Windows

powershell -ExecutionPolicy Bypass -File C:\dev\Wox\.agents\skills\wox-memory-debug\scripts\sample-wox-memory.ps1 -Pids <PID> -Samples 3 -IntervalSeconds 2

Use PrivateWorkingSetMB.

Do not compare macOS physical footprint with Windows private working set. Compare checkpoints from the same PID, OS, debug session, workload, and idle state.

Run the Measured Query Workload

  1. Record the warm baseline.
  2. Run five measured blocks of 10 or 20 queries using distinct seeds and the same query pool.
  3. After each block, clear the query, hide the launcher, wait 10 seconds, and sample the same PID three times.
  4. Record the median of each three-sample checkpoint to reduce sampler noise.
  5. Report cumulative query count, median memory, change from the warm baseline, and the observed shape of the series.

Use more blocks only when the trend is ambiguous. Keep the process alive for the whole run; restarting Wox invalidates the comparison.

Test Settings Window Cleanup

Run this lifecycle check after the query workload. It opens settings through the real Open Wox Settings result, waits for the independent settings semantics host, closes the settings window, waits until the launcher host owns automation again, and clears the opening query:

cd /Users/qianlifeng/Projects/Wox/wox.core
go run ../.agents/skills/wox-memory-debug/scripts/run-query-workload.go -info /tmp/wox-memory-automation.json -mode settings -count 1
  1. Run one settings cycle as warm-up. Wait 10 seconds and record the closed-settings baseline.
  2. Run at least three measured blocks of five open/close cycles:
go run ../.agents/skills/wox-memory-debug/scripts/run-query-workload.go -info /tmp/wox-memory-automation.json -mode settings -count 5
  1. After each block, keep both launcher and settings closed, wait 10 seconds, and sample the same PID three times. Record the median.
  2. Confirm every cycle reports both an opened_generation and closed_generation. The driver considers close complete only after settings-search-field disappears and launcher.query.input returns, which means settingsView and settingsHost have left the active automation surface.
  3. Compare measured block medians with the post-warm-up closed-settings baseline. Repeat one identical five-cycle block after a 30-second idle checkpoint when the trend is ambiguous.

The first settings open may retain shared fonts, icons, and reusable renderer caches. Do not require the process to return to its pre-first-open value. Window-scoped settings state and native resources must not accumulate across later cycles: after warm-up, closed-settings checkpoints should plateau within sampler jitter instead of growing with cumulative open/close count.

macOS Debug Reference

Use the August 10, 2026 macOS arm64 run as a comparison point for the current settings cleanup behavior, not as an absolute budget. The run used macOS 26.5.2, Go 1.26.2, Delve 1.26.2, the sqlite_fts5,wox_automation build tags, real Wox data, one PID, a 10-second hidden/closed wait, and three PhysicalFootprintMB samples at two-second intervals.

The query baseline was recorded after two 20-query warm-up blocks. The settings baseline was recorded after one complete warm-up open/close cycle:

CheckpointMedian PhysicalFootprintMBChange from closed-settings baseline
Hidden after 40 warm-up queries89.1 MBN/A
Settings closed warm baseline99.5 MB0.0 MB
5 measured settings cycles100.9 MB+1.4 MB
10 measured settings cycles101.4 MB+1.9 MB
15 measured settings cycles101.7 MB+2.2 MB
30-second idle confirmation102.3 MB+2.8 MB

Classify this series as no leak signal: the closed-settings checkpoints remained around 100-102 MB, and the 30-second confirmation stayed within observed sampler and allocator variation. vmmap reported no resident IOSurface memory after close; CoreGraphics and IOAccelerator residency was negligible. A Go heap comparison captured during the investigation showed only about 15 KB of retained delta, which redirected attribution to native window ownership rather than Go settings state.

Preserve these cleanup contracts when investigating a regression:

  • Keep at most one live wox.settings window, while still treating each close/reopen as a new native lifetime.
  • Release settings-only plugin catalogs, search indexes, forms, and application candidates on close, and invalidate in-flight loads so they cannot refill released caches.
  • Load the plugin store and application candidates only when their UI needs them.
  • Release the macOS NSWindow, view, and delegate hierarchy synchronously on close. Do not defer them to the application-lifetime autorelease pool.

Before the native close fix, a separate same-shape debug run rose from 104.8 MB after the warm settings close to 112.8 MB after 15 measured cycles. Treat a return of that cumulative, window-count-scaled shape as a regression even when the absolute starting footprint differs.

Windows Debug Reference

Use the September 22, 2026 Windows run as a comparison point for hidden idle memory, not as a budget. The run used a dev build with sqlite_fts5,wox_automation, real Wox data, two 20-query warm-up blocks, and three PrivateWorkingSetMB samples 45 seconds after hide, when both the 10-second and 30-second release stages had run:

CheckpointMedian PrivateWorkingSetMBLive Go heap
Staged trims plus prepared search text and pinyin release63.8 MB17.2 MB
Shared plugin logger and shared fsnotify watcher60.8 MB15.2 MB
Live-object reductions (wox.core/ui/README.md, "Hidden-state ownership rules")55.4 MB11.0 MB

Hidden memory drops in two steps: about 2-4 MB at 10 seconds and about 40 MB at 30 seconds, so sampling before 45 seconds compares different lifecycle states. When attributing what remains, use Delve goroutines -group userloc for goroutine ownership and the woxmemory go / woxmemory native commands for the Go-versus-native split; the largest native owners are NT heap fragmentation from show/hide churn and renderer objects that survive hide.

Decide Whether Memory Leaks

Interpret the post-warm-up series, not a single number:

  • No leak signal: memory rises during warm-up and then plateaus, oscillates within a stable range, or drops after an idle checkpoint.
  • Possible leak: the settled checkpoint median keeps increasing across at least three consecutive measured blocks and the increase is materially larger than sampler jitter.
  • Strong leak signal: retained growth continues after another identical workload, scales with cumulative query or settings-cycle count, and does not settle during a longer 30-60 second idle checkpoint.

Apply the same classification independently to cumulative queries and cumulative settings cycles. A stable query series does not rule out a settings-window lifecycle leak.

Go may retain heap arenas after objects become unreachable, so a high or non-decreasing process footprint alone is not proof. Report the result as no leak signal, possible leak, or strong leak signal, together with the measurements that support it.

Attribute Persistent Growth

Only profile after the repeated-query or settings-lifecycle run shows a possible or strong leak signal.

  1. Trigger the Wox Memory plugin's woxmemory profile command through the automation driver after warm-up:
go run ../.agents/skills/wox-memory-debug/scripts/run-query-workload.go -info /tmp/wox-memory-automation.json -mode profile
  1. Copy the generated profile immediately because the next capture overwrites it:
cp ~/.wox/memory.prof /tmp/wox-memory-before.prof

On Windows, copy %USERPROFILE%\.wox\memory.prof to a distinct temporary file instead.

  1. Repeat the measured workload, run the command again, and copy the second profile:
cp ~/.wox/memory.prof /tmp/wox-memory-after.prof
  1. Compare retained Go heap growth from wox.core:
go tool pprof -top -base /tmp/wox-memory-before.prof /tmp/wox-memory-after.prof

If process memory grows but the Go heap delta stays small, inspect Go UI native owners next: GPU textures and image caches, decoded result icons, preview resources, platform window allocations, and query-result cleanup. For settings-only growth, inspect settingsView, settingsHost, settings editors/forms, theme wallpaper previews, cloud/model state, asynchronous reloads, and native window/renderer destruction. On macOS, compare vmmap <PID> -summary checkpoints and pay particular attention to IOAccelerator and IOSurface. If repeated identical queries still grow, inspect lazy-image cache identity, per-draw Metal texture creation, and drawable-size churn before attributing growth to unique query strings.

Use -query terminal with query mode for an identical-query control only when the mixed workload needs further attribution.

Report

Include:

  • OS, debug configuration, PID, workload, and checkpoint timing.
  • A checkpoint table with cumulative queries and median process memory.
  • A separate closed-settings checkpoint table with cumulative open/close cycles and median process memory.
  • The trend classification and whether a longer confirmation block was needed.
  • Go heap delta owners only when profiling was necessary.
  • Any limitation that prevented consistent UI automation or reliable sampling.

Do not edit production code until the measurements identify a reproducible trend and a likely owner.

Signals

GitHub stars
27k
Forks
2k
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
wox-memory-debug
Source
github.com/wox-launcher/wox