[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C65P8WYYW50FJ3MFCKC2Q2":3,"skill-same:01M6C65P8WYYW50FJ3MFCKC2Q2":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":50,"commitSha":51,"skillDirectory":52,"forksCount":53,"repositoryHtmlUrl":54,"repositoryHomepageUrl":6,"ownerHtmlUrl":55,"ownerBlogUrl":6,"ownerDescription":56,"updatedAt":57,"install":58,"resources":71},"01M6C65P8WYYW50FJ3MFCKC2Q2","launchservices-health",null,"Diagnose macOS LaunchServices DB bloat and launchservicesd CPU spikes. Use when launchservicesd is pegged at high CPU or WindowServer XPC stalls are suspected.","laurigates\u002Fclaude-plugins","laurigates","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F13014001?v=4","01M6C59YHWS9C7KMXKSRX1YXNP","Lauri Gates","01M6C59YP2APG9YAM4DWYQYGFJ",59,"MIT","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fmacos-plugin\u002Fskills\u002Flaunchservices-health\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"health","launchservices health","2026","macos","when","bloat","at","uname","mktemp","ls","CPU","false","awk","db","use","edit","write","read","grep","PS","Bash","uptime","diagnose","2026-11-10 10:12:30",false,"---\nname: launchservices-health\ndescription: Diagnose macOS LaunchServices DB bloat and launchservicesd CPU spikes. Use when launchservicesd is pegged at high CPU or WindowServer XPC stalls are suspected.\nuser-invocable: false\nallowed-tools: Bash(uname *), Bash(ps *), Bash(pgrep *), Bash(uptime *), Bash(awk *), Bash(grep *), Bash(wc *), Bash(ls *), Bash(stat *), Bash(mktemp *), Bash(rm *), Read, Write, Edit, Grep, Glob\ncreated: 2026-05-03\nmodified: 2026-11-09\nreviewed: 2026-05-03\n---\n\n# LaunchServices Health (macOS)\n\n## When to Use This Skill\n\n| Use this skill when... | Use something else when... |\n|------------------------|----------------------------|\n| `launchservicesd` is at sustained high CPU | General process forensics — use `ps`\u002F`top` directly |\n| GUI feels sluggish after weeks of uptime | The machine actually hung — see `macos-incident-postmortem` |\n| Quantifying LS DB bloat (size, bundle count, claim count) | Checking app launch failures — use `system_profiler SPApplicationsDataType` |\n| Deciding whether `lsregister` rebuild is warranted | First-time install setup — use `configure-plugin` |\n\n## Platform Guard\n\nThis skill is **macOS-only**. The `lsregister` binary, `launchservicesd` daemon, and the LaunchServices database are Darwin-specific. Refuse to act if `uname -s` is not `Darwin`.\n\n```bash\ntest \"$(uname -s)\" = \"Darwin\" || { echo \"macos-plugin: not Darwin, refusing\"; exit 1; }\n```\n\n## Core Expertise\n\nLaunchServices is the macOS subsystem that maps documents and URL schemes to applications. State is held by `launchservicesd` and persisted to a binary database. Two failure modes matter:\n\n1. **DB bloat** — over months of uptime and app churn (Homebrew updates, Xcode reinstalls, Wine\u002FCrossOver bottle creation, Electron app upgrades), the DB accumulates stale bundle records and duplicate claims. The bigger the DB, the slower `lsregister -dump` runs and the more memory `launchservicesd` holds.\n2. **Daemon wedge** — `launchservicesd` can spin at high CPU when a misbehaving process repeatedly registers\u002Funregisters bundles. WindowServer makes synchronous XPC calls into `launchservicesd` for icon and document-handler lookups; a wedged daemon manifests as a frozen GUI.\n\nThe diagnostic answer is always: **measure first, rebuild only if warranted**. Rebuild (`lsregister -kill -r ...`) takes minutes, makes every app's \"open with\" disappear briefly, and rebuilds the DB from scratch — only do it when the metrics justify it.\n\n### Where the bits live\n\n| Path | Purpose |\n|------|---------|\n| `\u002FSystem\u002FLibrary\u002FFrameworks\u002FCoreServices.framework\u002FFrameworks\u002FLaunchServices.framework\u002FSupport\u002Flsregister` | The `lsregister` CLI — not on `$PATH`, must be invoked by absolute path |\n| `~\u002FLibrary\u002FApplication Support\u002Fcom.apple.PersistentURLTranslator\u002F` | Per-user persisted state |\n| `\u002Fvar\u002Ffolders\u002F*\u002F0\u002Fcom.apple.LaunchServices*` | LS cache directories (varies by macOS version) |\n\n## Quick Snapshot\n\nThe reference script `ls-stats` produces a one-page health snapshot. Install at `~\u002F.local\u002Fbin\u002Fls-stats` (mode 0755):\n\n```bash\n#!\u002Fusr\u002Fbin\u002Fenv bash\n# ls-stats: macOS LaunchServices DB + launchservicesd health snapshot\nset -euo pipefail\n\n[ \"$(uname -s)\" = \"Darwin\" ] || { echo \"not Darwin\" >&2; exit 1; }\n\nLSREG=\u002FSystem\u002FLibrary\u002FFrameworks\u002FCoreServices.framework\u002FFrameworks\u002FLaunchServices.framework\u002FSupport\u002Flsregister\nPID=$(pgrep -x launchservicesd) || { echo \"launchservicesd not running\" >&2; exit 1; }\n\nDUMP=$(mktemp); trap 'rm -f \"$DUMP\"' EXIT\n\"$LSREG\" -dump >\"$DUMP\" 2>\u002Fdev\u002Fnull\n\necho \"=== launchservicesd ===\"\nps -o pid,rss,etime,command -p \"$PID\" | sed 's\u002F^\u002F  \u002F'\n\necho\necho \"=== LaunchServices DB ===\"\nwc -c \u003C\"$DUMP\" | awk '{printf \"  size:    %d bytes (%.1f MB)\\n\", $1, $1\u002F1048576}'\nprintf \"  bundles: %d\\n\" \"$(grep -c '^bundle id:' \"$DUMP\")\"\nprintf \"  claims:  %d\\n\" \"$(grep -c '^claim '    \"$DUMP\")\"\nprintf \"  records: %d\\n\" \"$(grep -c '^----'      \"$DUMP\")\"\n\necho\nprintf \"=== Diagnostic reports ===\\n  launchservicesd CPU events: %d\\n\" \\\n  \"$(ls \u002FLibrary\u002FLogs\u002FDiagnosticReports\u002F 2>\u002Fdev\u002Fnull | grep -c launchservicesd)\"\n\necho\necho \"=== Uptime ===\"\nuptime | awk '{print \"  \" $0}'\n```\n\nThe script prints four blocks: daemon process state (RSS, etime), DB size and counts, recent CPU diagnostic-report count, and current uptime. All numbers are absolute — interpret them against the baseline thresholds below.\n\n## Interpreting the Snapshot\n\n### launchservicesd RSS\n\n| RSS (KB) | Meaning |\n|----------|---------|\n| \u003C 50 000 (~50 MB) | Healthy |\n| 50 000 – 150 000 | Normal for active use |\n| 150 000 – 400 000 | Bloated; consider rebuild |\n| > 400 000 (~400 MB) | Pathological; rebuild warranted |\n\n### Daemon `etime` (elapsed time since launch)\n\n`launchservicesd` is launched once per boot and lives until reboot. `etime` close to `uptime` is normal. `etime` significantly less than `uptime` means the daemon was relaunched mid-session — usually after a crash; check Diagnostic Reports.\n\n### DB size\n\n| Size | Meaning |\n|------|---------|\n| \u003C 5 MB | Normal |\n| 5 – 20 MB | Healthy heavy-app workstation |\n| 20 – 50 MB | Bloated; rebuild improves things |\n| > 50 MB | Pathological |\n\n### Bundle \u002F claim \u002F record counts\n\nThere is no absolute threshold — these matter relative to the **expected** number of installed apps. Useful sanity check:\n\n```bash\nls \u002FApplications \u002FApplications\u002FUtilities ~\u002FApplications 2>\u002Fdev\u002Fnull | wc -l\n```\n\nIf `bundle id:` count is 5x or more above the visible-`.app` count, the DB has stale records.\n\n### Diagnostic-report CPU events\n\n`\u002FLibrary\u002FLogs\u002FDiagnosticReports\u002Flaunchservicesd-*.cpu_resource.diag` files indicate the daemon hit a CPU threshold (typically 80% sustained for 90s). Each file is one event. Recent volume:\n\n```bash\nfind \u002FLibrary\u002FLogs\u002FDiagnosticReports -name 'launchservicesd*.cpu_resource.diag' -mtime -7 | wc -l\n```\n\n| Count (last 7 days) | Meaning |\n|---------------------|---------|\n| 0 | Normal |\n| 1 – 3 | Notable; monitor |\n| 4+ | Pattern; likely a misbehaving registrar — investigate |\n\n## Rebuild Procedure\n\nRebuild **only** when the snapshot shows multiple red flags. The rebuild takes 1–10 minutes depending on app count.\n\n```bash\n# Rebuild the LaunchServices database\n\u002FSystem\u002FLibrary\u002FFrameworks\u002FCoreServices.framework\u002FFrameworks\u002FLaunchServices.framework\u002FSupport\u002Flsregister \\\n  -kill -r -domain local -domain system -domain user\n```\n\nWhat the flags do:\n\n| Flag | Effect |\n|------|--------|\n| `-kill` | Reset the existing database first |\n| `-r` | Recursively scan for bundles to register |\n| `-domain local` | `\u002FApplications` |\n| `-domain system` | `\u002FSystem\u002FApplications`, `\u002FSystem\u002FLibrary` |\n| `-domain user` | `~\u002FApplications`, `~\u002FLibrary\u002FApplication Support` |\n\nSide effects:\n\n- \"Open With\" submenus regenerate (a few seconds of \"no apps available\")\n- Default-app preferences are preserved (stored separately)\n- The Dock badge and icon caches are NOT affected\n- A new `launchservicesd` process is spawned; PID changes\n\n### After rebuild\n\nRe-run `ls-stats` to confirm RSS, DB size, and counts dropped.\n\n## Common Patterns\n\n### Snapshot before\u002Fafter a rebuild\n\n```bash\nls-stats > \u002Ftmp\u002Fls-before.txt\n\"$LSREG\" -kill -r -domain local -domain system -domain user\nls-stats > \u002Ftmp\u002Fls-after.txt\ndiff -u \u002Ftmp\u002Fls-before.txt \u002Ftmp\u002Fls-after.txt\n```\n\n### Track DB growth across boots\n\nAppend a snapshot to a logbook on each session:\n\n```bash\n{ date -Iseconds; ls-stats; echo \"---\"; } >> ~\u002F.local\u002Fstate\u002Flaunchservices.log\n```\n\nPlot or grep over time to see whether DB size is monotonically growing.\n\n### Identify the registrar driving CPU\n\nWhen `launchservicesd` is hot and you suspect a specific app:\n\n```bash\nlog stream --predicate 'process == \"launchservicesd\"' --style syslog | head -200\n```\n\nLook for repeated `bundle id` or `path` strings — that's the offender.\n\n### Check for bottle-creation amplification\n\nWine\u002FCrossOver bottle creation registers hundreds of `.exe`-as-bundle entries. Count them:\n\n```bash\n\"$LSREG\" -dump 2>\u002Fdev\u002Fnull | grep -c -i 'wineprefix\\|bottle'\n```\n\nA 4-digit answer is the smoking gun.\n\n## Justfile Recipe\n\n```just\n[doc('Quantify LaunchServices DB and launchservicesd state (macOS)')]\n[macos]\nls-stats:\n    @~\u002F.local\u002Fbin\u002Fls-stats\n```\n\nThe `[macos]` attribute (just 1.34+) skips the recipe on non-Darwin. On older just versions, drop the attribute and let the script's `uname -s` check do the gating.\n\n## Agentic Optimizations\n\n| Context | Command |\n|---------|---------|\n| One-line size | `$LSREG -dump 2>\u002Fdev\u002Fnull \\| wc -c \\| awk '{printf \"%.1f MB\\n\", $1\u002F1048576}'` |\n| RSS only | `ps -o rss= -p \"$(pgrep -x launchservicesd)\"` |\n| Bundle count | `$LSREG -dump 2>\u002Fdev\u002Fnull \\| grep -c '^bundle id:'` |\n| Recent CPU events | `find \u002FLibrary\u002FLogs\u002FDiagnosticReports -name 'launchservicesd*.cpu_resource.diag' -mtime -7 \\| wc -l` |\n| Daemon uptime vs system uptime | `ps -o etime= -p \"$(pgrep -x launchservicesd)\"; uptime` |\n\n## Quick Reference\n\n### Key paths\n\n| Path | Purpose |\n|------|---------|\n| `\u002FSystem\u002F...\u002FSupport\u002Flsregister` | The CLI |\n| `\u002FLibrary\u002FLogs\u002FDiagnosticReports\u002F` | CPU and crash diag files |\n| `~\u002FLibrary\u002FApplication Support\u002Fcom.apple.PersistentURLTranslator\u002F` | Per-user state |\n\n### Useful flags\n\n| Flag | Description |\n|------|-------------|\n| `-dump` | Print the entire DB to stdout |\n| `-kill -r -domain ...` | Rebuild |\n| `-h` | List all flags (undocumented elsewhere) |\n| `-f \u003Cbundle>` | Force-register a single bundle |\n| `-u \u003Cbundle>` | Unregister a bundle |\n\n### Indicator thresholds (rough)\n\n| Metric | Healthy | Bloated | Rebuild |\n|--------|---------|---------|---------|\n| DB size | \u003C 5 MB | 20–50 MB | > 50 MB |\n| Daemon RSS | \u003C 50 MB | 150–400 MB | > 400 MB |\n| Bundle count vs visible apps | 1–2x | 3–5x | > 5x |\n| CPU diag events \u002F 7 days | 0 | 1–3 | 4+ |\n\n## Error Handling\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| `lsregister: command not found` | Not on `$PATH` by design | Use the full `\u002FSystem\u002F...\u002FSupport\u002Flsregister` path |\n| `lsregister -dump` exits non-zero with stderr | Permissions or DB corruption | Capture stderr separately; rebuild may resolve it |\n| `pgrep -x launchservicesd` returns nothing | Daemon crashed and not yet relaunched | Check Diagnostic Reports; force a relaunch with `lsregister -kill -r ...` |\n| Rebuild appears to hang | Indexing many app bundles is genuinely slow | Wait — typical 1–10 min depending on app count |\n| Sudden RSS jump after Homebrew upgrade | Many bundles re-registered at once | Expected; will settle within minutes |\n\n## Related Skills\n\n- `macos-incident-postmortem` — when LaunchServices CPU caused a GUI hang, parse Diagnostic Reports there\n- `kitty-plugin:kitty-session-persistence` — recover terminal sessions lost when WindowServer wedged on an LS XPC call\n","# LaunchServices Health (macOS)\n\n## When to Use This Skill\n\n| Use this skill when... | Use something else when... |\n|------------------------|----------------------------|\n| `launchservicesd` is at sustained high CPU | General process forensics — use `ps`\u002F`top` directly |\n| GUI feels sluggish after weeks of uptime | The machine actually hung — see `macos-incident-postmortem` |\n| Quantifying LS DB bloat (size, bundle count, claim count) | Checking app launch failures — use `system_profiler SPApplicationsDataType` |\n| Deciding whether `lsregister` rebuild is warranted | First-time install setup — use `configure-plugin` |\n\n## Platform Guard\n\nThis skill is **macOS-only**. The `lsregister` binary, `launchservicesd` daemon, and the LaunchServices database are Darwin-specific. Refuse to act if `uname -s` is not `Darwin`.\n\n```bash\ntest \"$(uname -s)\" = \"Darwin\" || { echo \"macos-plugin: not Darwin, refusing\"; exit 1; }\n```\n\n## Core Expertise\n\nLaunchServices is the macOS subsystem that maps documents and URL schemes to applications. State is held by `launchservicesd` and persisted to a binary database. Two failure modes matter:\n\n1. **DB bloat** — over months of uptime and app churn (Homebrew updates, Xcode reinstalls, Wine\u002FCrossOver bottle creation, Electron app upgrades), the DB accumulates stale bundle records and duplicate claims. The bigger the DB, the slower `lsregister -dump` runs and the more memory `launchservicesd` holds.\n2. **Daemon wedge** — `launchservicesd` can spin at high CPU when a misbehaving process repeatedly registers\u002Funregisters bundles. WindowServer makes synchronous XPC calls into `launchservicesd` for icon and document-handler lookups; a wedged daemon manifests as a frozen GUI.\n\nThe diagnostic answer is always: **measure first, rebuild only if warranted**. Rebuild (`lsregister -kill -r ...`) takes minutes, makes every app's \"open with\" disappear briefly, and rebuilds the DB from scratch — only do it when the metrics justify it.\n\n### Where the bits live\n\n| Path | Purpose |\n|------|---------|\n| `\u002FSystem\u002FLibrary\u002FFrameworks\u002FCoreServices.framework\u002FFrameworks\u002FLaunchServices.framework\u002FSupport\u002Flsregister` | The `lsregister` CLI — not on `$PATH`, must be invoked by absolute path |\n| `~\u002FLibrary\u002FApplication Support\u002Fcom.apple.PersistentURLTranslator\u002F` | Per-user persisted state |\n| `\u002Fvar\u002Ffolders\u002F*\u002F0\u002Fcom.apple.LaunchServices*` | LS cache directories (varies by macOS version) |\n\n## Quick Snapshot\n\nThe reference script `ls-stats` produces a one-page health snapshot. Install at `~\u002F.local\u002Fbin\u002Fls-stats` (mode 0755):\n\n```bash\n#!\u002Fusr\u002Fbin\u002Fenv bash\n# ls-stats: macOS LaunchServices DB + launchservicesd health snapshot\nset -euo pipefail\n\n[ \"$(uname -s)\" = \"Darwin\" ] || { echo \"not Darwin\" >&2; exit 1; }\n\nLSREG=\u002FSystem\u002FLibrary\u002FFrameworks\u002FCoreServices.framework\u002FFrameworks\u002FLaunchServices.framework\u002FSupport\u002Flsregister\nPID=$(pgrep -x launchservicesd) || { echo \"launchservicesd not running\" >&2; exit 1; }\n\nDUMP=$(mktemp); trap 'rm -f \"$DUMP\"' EXIT\n\"$LSREG\" -dump >\"$DUMP\" 2>\u002Fdev\u002Fnull\n\necho \"=== launchservicesd ===\"\nps -o pid,rss,etime,command -p \"$PID\" | sed 's\u002F^\u002F  \u002F'\n\necho\necho \"=== LaunchServices DB ===\"\nwc -c \u003C\"$DUMP\" | awk '{printf \"  size:    %d bytes (%.1f MB)\\n\", $1, $1\u002F1048576}'\nprintf \"  bundles: %d\\n\" \"$(grep -c '^bundle id:' \"$DUMP\")\"\nprintf \"  claims:  %d\\n\" \"$(grep -c '^claim '    \"$DUMP\")\"\nprintf \"  records: %d\\n\" \"$(grep -c '^----'      \"$DUMP\")\"\n\necho\nprintf \"=== Diagnostic reports ===\\n  launchservicesd CPU events: %d\\n\" \\\n  \"$(ls \u002FLibrary\u002FLogs\u002FDiagnosticReports\u002F 2>\u002Fdev\u002Fnull | grep -c launchservicesd)\"\n\necho\necho \"=== Uptime ===\"\nuptime | awk '{print \"  \" $0}'\n```\n\nThe script prints four blocks: daemon process state (RSS, etime), DB size and counts, recent CPU diagnostic-report count, and current uptime. All numbers are absolute — interpret them against the baseline thresholds below.\n\n## Interpreting the Snapshot\n\n### launchservicesd RSS\n\n| RSS (KB) | Meaning |\n|----------|---------|\n| \u003C 50 000 (~50 MB) | Healthy |\n| 50 000 – 150 000 | Normal for active use |\n| 150 000 – 400 000 | Bloated; consider rebuild |\n| > 400 000 (~400 MB) | Pathological; rebuild warranted |\n\n### Daemon `etime` (elapsed time since launch)\n\n`launchservicesd` is launched once per boot and lives until reboot. `etime` close to `uptime` is normal. `etime` significantly less than `uptime` means the daemon was relaunched mid-session — usually after a crash; check Diagnostic Reports.\n\n### DB size\n\n| Size | Meaning |\n|------|---------|\n| \u003C 5 MB | Normal |\n| 5 – 20 MB | Healthy heavy-app workstation |\n| 20 – 50 MB | Bloated; rebuild improves things |\n| > 50 MB | Pathological |\n\n### Bundle \u002F claim \u002F record counts\n\nThere is no absolute threshold — these matter relative to the **expected** number of installed apps. Useful sanity check:\n\n```bash\nls \u002FApplications \u002FApplications\u002FUtilities ~\u002FApplications 2>\u002Fdev\u002Fnull | wc -l\n```\n\nIf `bundle id:` count is 5x or more above the visible-`.app` count, the DB has stale records.\n\n### Diagnostic-report CPU events\n\n`\u002FLibrary\u002FLogs\u002FDiagnosticReports\u002Flaunchservicesd-*.cpu_resource.diag` files indicate the daemon hit a CPU threshold (typically 80% sustained for 90s). Each file is one event. Recent volume:\n\n```bash\nfind \u002FLibrary\u002FLogs\u002FDiagnosticReports -name 'launchservicesd*.cpu_resource.diag' -mtime -7 | wc -l\n```\n\n| Count (last 7 days) | Meaning |\n|---------------------|---------|\n| 0 | Normal |\n| 1 – 3 | Notable; monitor |\n| 4+ | Pattern; likely a misbehaving registrar — investigate |\n\n## Rebuild Procedure\n\nRebuild **only** when the snapshot shows multiple red flags. The rebuild takes 1–10 minutes depending on app count.\n\n```bash\n# Rebuild the LaunchServices database\n\u002FSystem\u002FLibrary\u002FFrameworks\u002FCoreServices.framework\u002FFrameworks\u002FLaunchServices.framework\u002FSupport\u002Flsregister \\\n  -kill -r -domain local -domain system -domain user\n```\n\nWhat the flags do:\n\n| Flag | Effect |\n|------|--------|\n| `-kill` | Reset the existing database first |\n| `-r` | Recursively scan for bundles to register |\n| `-domain local` | `\u002FApplications` |\n| `-domain system` | `\u002FSystem\u002FApplications`, `\u002FSystem\u002FLibrary` |\n| `-domain user` | `~\u002FApplications`, `~\u002FLibrary\u002FApplication Support` |\n\nSide effects:\n\n- \"Open With\" submenus regenerate (a few seconds of \"no apps available\")\n- Default-app preferences are preserved (stored separately)\n- The Dock badge and icon caches are NOT affected\n- A new `launchservicesd` process is spawned; PID changes\n\n### After rebuild\n\nRe-run `ls-stats` to confirm RSS, DB size, and counts dropped.\n\n## Common Patterns\n\n### Snapshot before\u002Fafter a rebuild\n\n```bash\nls-stats > \u002Ftmp\u002Fls-before.txt\n\"$LSREG\" -kill -r -domain local -domain system -domain user\nls-stats > \u002Ftmp\u002Fls-after.txt\ndiff -u \u002Ftmp\u002Fls-before.txt \u002Ftmp\u002Fls-after.txt\n```\n\n### Track DB growth across boots\n\nAppend a snapshot to a logbook on each session:\n\n```bash\n{ date -Iseconds; ls-stats; echo \"---\"; } >> ~\u002F.local\u002Fstate\u002Flaunchservices.log\n```\n\nPlot or grep over time to see whether DB size is monotonically growing.\n\n### Identify the registrar driving CPU\n\nWhen `launchservicesd` is hot and you suspect a specific app:\n\n```bash\nlog stream --predicate 'process == \"launchservicesd\"' --style syslog | head -200\n```\n\nLook for repeated `bundle id` or `path` strings — that's the offender.\n\n### Check for bottle-creation amplification\n\nWine\u002FCrossOver bottle creation registers hundreds of `.exe`-as-bundle entries. Count them:\n\n```bash\n\"$LSREG\" -dump 2>\u002Fdev\u002Fnull | grep -c -i 'wineprefix\\|bottle'\n```\n\nA 4-digit answer is the smoking gun.\n\n## Justfile Recipe\n\n```just\n[doc('Quantify LaunchServices DB and launchservicesd state (macOS)')]\n[macos]\nls-stats:\n    @~\u002F.local\u002Fbin\u002Fls-stats\n```\n\nThe `[macos]` attribute (just 1.34+) skips the recipe on non-Darwin. On older just versions, drop the attribute and let the script's `uname -s` check do the gating.\n\n## Agentic Optimizations\n\n| Context | Command |\n|---------|---------|\n| One-line size | `$LSREG -dump 2>\u002Fdev\u002Fnull \\| wc -c \\| awk '{printf \"%.1f MB\\n\", $1\u002F1048576}'` |\n| RSS only | `ps -o rss= -p \"$(pgrep -x launchservicesd)\"` |\n| Bundle count | `$LSREG -dump 2>\u002Fdev\u002Fnull \\| grep -c '^bundle id:'` |\n| Recent CPU events | `find \u002FLibrary\u002FLogs\u002FDiagnosticReports -name 'launchservicesd*.cpu_resource.diag' -mtime -7 \\| wc -l` |\n| Daemon uptime vs system uptime | `ps -o etime= -p \"$(pgrep -x launchservicesd)\"; uptime` |\n\n## Quick Reference\n\n### Key paths\n\n| Path | Purpose |\n|------|---------|\n| `\u002FSystem\u002F...\u002FSupport\u002Flsregister` | The CLI |\n| `\u002FLibrary\u002FLogs\u002FDiagnosticReports\u002F` | CPU and crash diag files |\n| `~\u002FLibrary\u002FApplication Support\u002Fcom.apple.PersistentURLTranslator\u002F` | Per-user state |\n\n### Useful flags\n\n| Flag | Description |\n|------|-------------|\n| `-dump` | Print the entire DB to stdout |\n| `-kill -r -domain ...` | Rebuild |\n| `-h` | List all flags (undocumented elsewhere) |\n| `-f \u003Cbundle>` | Force-register a single bundle |\n| `-u \u003Cbundle>` | Unregister a bundle |\n\n### Indicator thresholds (rough)\n\n| Metric | Healthy | Bloated | Rebuild |\n|--------|---------|---------|---------|\n| DB size | \u003C 5 MB | 20–50 MB | > 50 MB |\n| Daemon RSS | \u003C 50 MB | 150–400 MB | > 400 MB |\n| Bundle count vs visible apps | 1–2x | 3–5x | > 5x |\n| CPU diag events \u002F 7 days | 0 | 1–3 | 4+ |\n\n## Error Handling\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| `lsregister: command not found` | Not on `$PATH` by design | Use the full `\u002FSystem\u002F...\u002FSupport\u002Flsregister` path |\n| `lsregister -dump` exits non-zero with stderr | Permissions or DB corruption | Capture stderr separately; rebuild may resolve it |\n| `pgrep -x launchservicesd` returns nothing | Daemon crashed and not yet relaunched | Check Diagnostic Reports; force a relaunch with `lsregister -kill -r ...` |\n| Rebuild appears to hang | Indexing many app bundles is genuinely slow | Wait — typical 1–10 min depending on app count |\n| Sudden RSS jump after Homebrew upgrade | Many bundles re-registered at once | Expected; will settle within minutes |\n\n## Related Skills\n\n- `macos-incident-postmortem` — when LaunchServices CPU caused a GUI hang, parse Diagnostic Reports there\n- `kitty-plugin:kitty-session-persistence` — recover terminal sessions lost when WindowServer wedged on an LS XPC call\n",{"name":5,"created":47,"modified":48,"reviewed":47,"description":7,"allowed-tools":49,"user-invocable":43},1777766400000,1794182400000,"Bash(uname *), Bash(ps *), Bash(pgrep *), Bash(uptime *), Bash(awk *), Bash(grep *), Bash(wc *), Bash(ls *), Bash(stat *), Bash(mktemp *), Bash(rm *), Read, Write, Edit, Grep, Glob","main","4ce428979f89281ce915e0c022270791a6fa5b08","macos-plugin\u002Fskills\u002Flaunchservices-health",6,"https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins","https:\u002F\u002Fgithub.com\u002Flaurigates","Linux enthusiast, cloud engineer, neovim addict, electronics hobbyist.","2026-11-12 03:43:32",{"source":8,"skillName":5,"commands":59,"prompt":69,"zipAvailable":70},[60,63,66],{"tool":61,"command":62},"npx","npx skills add laurigates\u002Fclaude-plugins --skill launchservices-health",{"tool":64,"command":65},"bunx","bunx skills add laurigates\u002Fclaude-plugins --skill launchservices-health",{"tool":67,"command":68},"pnpm","pnpm dlx skills add laurigates\u002Fclaude-plugins --skill launchservices-health","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fmacos-plugin\u002Fskills\u002Flaunchservices-health\u002FSKILL.md",true,[],[73,99,115,131,154,184],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":84,"publishedAt":42},"01M70PFHMH9ADY0CRE6047Y4B2","kitty-show-image","Show the user an image with a note on what to judge, via a file send or a labelled kitty tab. Use when the user must see an image, or icat fails with no \u002Fdev\u002Ftty.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fkitty-plugin\u002Fskills\u002Fkitty-show-image\u002FSKILL.md",[79],{"categoryNo":80,"categoryName":81,"taxonomyType":82,"taxonomyTypeDesc":83},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[85,86,87,88,89,28,90,91,92,93,33,23,39,94,95,96,97,98,21,36],"show","kitty show image","image","kitty","show image","get","send","open","dev","file","text","with","xdg","via",{"skillNo":100,"name":101,"nameZh":6,"description":102,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":42},"01M70PFEN18HKQ4RCQ1VPGMPTB","kitty-session-persistence","Snapshot and restore kitty terminal sessions on macOS. Use when surviving WindowServer hangs without losing tabs, configuring snapshots, or restoring after a force-reboot.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fkitty-plugin\u002Fskills\u002Fkitty-session-persistence\u002FSKILL.md",[],[88,106,107,108,30,109,23,39,26,110,111,21,36,35,34,112,22,113,114,33],"kitty session persistence","session","persistence","snapshots","reboot","terminal","snapshot","sessions","restore",{"skillNo":116,"name":117,"nameZh":6,"description":118,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":119,"categories":120,"keywords":121,"publishedAt":42},"01M70PFC77XGXCVQ1543VGZHYR","kitty-remote-control","Safe kitty remote control from an agent — read panes with kitty @ ls\u002Fget-text, notify, and never mutate the live terminal unasked. Use when running inside kitty.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fkitty-plugin\u002Fskills\u002Fkitty-remote-control\u002FSKILL.md",[],[122,123,88,124,125,28,126,127,90,128,129,33,23,130,39,95,96,111,21,36],"kitty remote control","remote","control","remote control","running","never","panes","notify","query",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":135,"categories":136,"keywords":137,"publishedAt":42},"01M70P6WVMCT5JG4SACTM69AF9","docs-reference-check","Dangling doc-reference gate: flag markdown naming repo paths or relative links that no longer exist. Use when docs cite moved\u002Fdeleted files, or wiring a doc-drift lint.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fdocumentation-plugin\u002Fskills\u002Fdocs-reference-check\u002FSKILL.md",[],[138,139,140,141,142,143,144,145,146,147,33,23,39,148,94,149,150,151,152,153],"docs reference check","check","reference check","reference","docs","links","python3","repo","files","auto","drift","lint","wiring","chezmoi","references","cp",{"skillNo":155,"name":156,"nameZh":6,"description":157,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":158,"categories":159,"keywords":169,"publishedAt":42},"01M6C6NDE7DAQGNWSF22J5CJ0Z","youtube-upload","Upload a video to YouTube via the Data API v3 and edit its title, description, tags or thumbnail afterwards. Use when publishing or retitling a YouTube video.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fyoutube-plugin\u002Fskills\u002Fyoutube-upload\u002FSKILL.md",[160,163,164],{"categoryNo":161,"categoryName":162,"taxonomyType":82,"taxonomyTypeDesc":83},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":80,"categoryName":81,"taxonomyType":82,"taxonomyTypeDesc":83},{"categoryNo":165,"categoryName":166,"taxonomyType":167,"taxonomyTypeDesc":168},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[170,171,172,173,144,174,36,175,34,176,177,178,33,39,94,179,180,23,181,182,183,98,21],"youtube upload","upload","youtube","Video","run","uv run","publishing","data","uv","api","v3","tags","id","title",{"skillNo":185,"name":186,"nameZh":6,"description":187,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":188,"categories":189,"keywords":193,"publishedAt":42},"01M6C6NABWW1X58KJJM4F6GQMQ","youtube-studio-share","Share a private YouTube video with a whole Google Workspace organization by scripting YouTube Studio in the browser. Use when a video must be org-only.","https:\u002F\u002Fgithub.com\u002Flaurigates\u002Fclaude-plugins\u002Fblob\u002Fmain\u002Fyoutube-plugin\u002Fskills\u002Fyoutube-studio-share\u002FSKILL.md",[190],{"categoryNo":191,"categoryName":192,"taxonomyType":82,"taxonomyTypeDesc":83},"01JBSEEDCAT000000000000023","Skill与智能体开发",[194,195,196,197,172,173,198,199,200,201,202,36,203,204,205,206,33,207,23,96,208,21],"youtube studio share","share","youtube studio","studio","browser","javascript","scripting","google workspace","workspace","tool","google","only","MCP","chrome","organization"]