Skip to main content

macos-disk-usage

macOS disk-usage forensics and space recovery on APFS. Use when df reports a disk near-full, hunting what's eating space, reclaiming OrbStack/Docker, or pruning caches and local snapshots.

来源信息

仓库
laurigates/claude-plugins
最近来源活动
2026年10月18日 06:17
检测到的 SKILL.md 语言
英语
星标
59
Forks
6

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
9 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
macos-disk-usage
description
macOS disk-usage forensics and space recovery on APFS. Use when df reports a disk near-full, hunting what's eating space, reclaiming OrbStack/Docker, or pruning caches and local snapshots.
user-invocable
false
allowed-tools
Bash(bash *), Bash(uname *), Bash(df *), Bash(du *), Bash(find *), Bash(diskutil *), Bash(tmutil *), Bash(docker *), Bash(brew *), Bash(go *), Bash(pip *), Bash(uv *), Bash(dust *), Bash(dua *), Bash(gdu *), Bash(ncdu *), Bash(mise *), Bash(git *), Read, Grep, Glob, TodoWrite
created
2026-06-21T00:00:00.000Z
modified
2026-10-13T00:00:00.000Z
reviewed
2026-08-04T00:00:00.000Z
# macOS Disk Usage & Space Recovery ## When to Use This Skill | Use this skill when... | Use something else when... | |------------------------|----------------------------| | `df` reports a volume near-full and you need the honest figure | The root disk on Linux is full — use the Linux-focused `disk-full-recovery` rule | | Hunting "what's eating my disk" on macOS | General process forensics — use `ps`/`top` directly | | Reclaiming space from OrbStack/Docker, caches, or local snapshots | A GUI hang/freeze occurred — see `macos-incident-postmortem` | | `du` totals and free space disagree (purgeable snapshots, or CoW clones) | `launchservicesd` DB bloat specifically — see `launchservices-health` | | Deleting a big tree freed far less than `du` promised | — | ## Platform Guard This skill is **macOS-only**. APFS containers, `diskutil apfs`, `tmutil` local snapshots, and BSD `du` block-counting are Darwin-specific. Refuse to act if `uname -s` is not `Darwin`. ```bash test "$(uname -s)" = "Darwin" || { echo "macos-plugin: not Darwin, refusing"; exit 1; } ``` This skill **cross-references, does not duplicate**, the Linux-focused `disk-full-recovery` rule (root partition, `~/.cache`, apt/journalctl). The APFS / Time Machine / OrbStack angle below is the macOS-specific complement. ## Core Expertise The single most-important macOS fact: **APFS shares free space across every volume in a container.** A per-volume `Capacity %` is therefore misleading — the sealed system snapshot volume routinely reads **99%** while the container has tens of GB free. Trust the `Avail` column (or `diskutil apfs list`), never the `Capacity %`, or the investigation goes down the wrong path before it starts. The second fact: **`du` lies about reclaimable space.** `tmutil` local snapshots hold purgeable space that `du` never counts, so `du` totals and reported free space can disagree by tens of GB. Check snapshots first when the numbers don't reconcile. The third fact: **`du` also over-counts in the other direction — copy-on-write clones.** APFS reports a cloned file at *full* `st_blocks` even though its blocks are shared and cost nothing, so a `du` total can far exceed what deleting the tree would actually free. This is not fixable by switching tools: `dust`, `gdu`, and `ncdu` all read `st_blocks` and double-count identically. See [CoW clones](references/cow-clones.md). ## Step 1: Measure honestly (built-in CLI) ```bash # Trust Avail, NOT Capacity % — APFS shares free space container-wide df -h / # The container's real free space, per-volume roles, and snapshot count diskutil apfs list # Top-level consumers, one level deep, staying on one filesystem (-x) du -hx -d1 / 2>/dev/null | sort -h du -hx -d1 ~ 2>/dev/null | sort -h ``` BSD `du` counts **allocated blocks**, so it reports the real on-disk size of sparse files (e.g. OrbStack's `data.img.raw` reads its true 33 GB, not its apparent size). Trust the number *for sparse files* — but not as a general rule: allocated blocks are also what makes `du` over-count clones (below), and they never include purgeable snapshot space. When a size gates a decision ("how much will this free?"), or `df` barely moves after a delete, open [references/cow-clones.md](references/cow-clones.md) for the measured clone over-count, the per-package-manager table, and the `df`-delta recipe. ### Purgeable snapshot space (the thing `du` hides) When `du` totals and `df` free space disagree, local Time Machine snapshots are the usual cause: ```bash # List local snapshots holding purgeable space tmutil listlocalsnapshots / # Thin them (reclaims purgeable space invisible to du); needs sudo sudo tmutil thinlocalsnapshots / 999999999999 4 ``` ## Step 1.5: Fast-path — the usual-suspects scan Step 1 gives the honest *total*; this gives *where it went* without re-deriving the hunt by hand each time. `scripts/scan-suspects.sh` reads a public catalog of known reclaim targets (`scripts/suspects.tsv` — dev caches, build-artifact dirs, VM images), `du`s the ones that exist on this machine, and emits a ranked rollup with the **cleanup command and safety tier already attached**: ```bash # Whole home (thorough; slower — du walks every tree) bash "${CLAUDE_SKILL_DIR}/scripts/scan-suspects.sh" --home-dir "$HOME" --root "$HOME" # Bound the build-artifact search to where projects live, raise the noise floor bash "${CLAUDE_SKILL_DIR}/scripts/scan-suspects.sh" --root ~/repos --min-mb 1000 ``` Output follows the structured `SUSPECT id=… tier=… size_kb=… cmd="…"` convention, plus a ranked human table and per-tier totals (`TIER_SAFE_KB=…`, `RECLAIMABLE_SAFE=…`). Work the tiers exactly as Step 4 — exhaust `safe` before `decision`, never blind-delete `userdata`. ⚠️ Those totals are `du` sums, so they are an **upper bound** wherever CoW clones apply, e.g. the `node_modules` / `.venv` suspects, which `uv` and `bun` clone from a global cache. Treat `RECLAIMABLE_*` as "at most this much"; confirm with a `df` delta. See [CoW clones](references/cow-clones.md). **This augments Step 1, it does not replace it.** The scan only measures. The agent still reads `Avail` rather than `Capacity %`, checks snapshots when `du` and `df` disagree, and decides *which* `decision`/`userdata` items to remove. **The `UNKNOWN` lines are the feedback loop.** Any big directory *not* in the catalog is surfaced as `UNKNOWN size_kb=… path=…`. When one recurs, add it to `suspects.tsv` **as a pattern** (never a machine-specific path — this repo is public) and open a PR; the catalog grows from real findings. Catalog columns and placeholders (`{dir}`, `{parent}`) are documented in the file's header. An `UNKNOWN` inside a git repo is usually a git-ignored build artifact; size and trace it with [references/repo-artifacts.md](references/repo-artifacts.md). Two operational notes: - **Runtime scales with disk size** — `du` walks every tree, so a full disk can take a minute or two. Bound with `--root <project-dir>` and `--min-mb`; or use `dust` (Step 3) for a parallel walk. - **The catalog is the shared artifact; the scan *output* is machine-specific** — keep it in scratch, never commit it. ## Step 2: The OrbStack / Docker recovery play OrbStack/Docker is frequently the dominant consumer (100+ GB seen). The VM image (`data.img.raw`) grows but **never shrinks on its own**. The recovery is: prune **inside** the VM, then OrbStack **auto-shrinks** the host image (unlike Docker Desktop, which needs manual reclaim). ```bash # See what's reclaimable before pruning docker system df # Prune unused images + build cache (NOT volumes — see warning below) docker system prune -a -f ``` A real session reclaimed **85 GB** this way (159 images / 57 GB reclaimable, 42 GB build cache), after which OrbStack auto-shrank the host image **103 GB → 33 GB**. ### Never blind-prune named volumes `docker volume ls -f dangling=true` lists named volumes (`olmap_postgres_data`, `docker_neo4j_data`, …) that are "unused" **only because no container is currently running** — they hold live project databases. A blind `docker volume prune` would wipe them. ```bash # Inspect first — named volumes are project data, anonymous-hash ones are scratch docker volume ls -f dangling=true ``` Prune **only anonymous-hash volumes** (long hex names), never the human-named ones, and only after confirming with the user. ## Step 3: Third-party tooling For a faster or interactive scan (`dust`, `dua`, `gdu`/`ncdu`, `diskonaut`) and their mise `aqua:` installs, open [references/third-party-tools.md](references/third-party-tools.md). ## Step 4: Tiered cleanup Work top-down — exhaust the safe tier before touching anything that needs a decision. | Tier | What | How | Notes | |------|------|-----|-------| | **Safe / regenerable** | Homebrew downloads | `brew cleanup -s` | Rebuilds on next install | | | Go module cache | `go clean -modcache` | Re-downloads on next build | | | pip cache | `pip cache purge` | | | | uv cache | `uv cache clean` | **Blocks on the lock** while any `uvx`/`uv run` process (e.g. an MCP server) runs — read [troubleshooting](references/troubleshooting.md) before `--force` | | | Playwright / Yarn / node-gyp caches | `rm -rf ~/Library/Caches/{ms-playwright,Yarn,node-gyp}` | Regenerable | | **Needs a decision** | Docker images + build cache | `docker system prune -a -f` | OrbStack auto-shrinks host image after | | | Local Time Machine snapshots | `sudo tmutil thinlocalsnapshots /` | Loses local restore points | | **User data** | Named Docker volumes | confirm each | Live project databases — never blind-prune | | | Anything in `~/Documents`, `~/Downloads` | user confirms | Irreplaceable | ## Quick Reference One-line commands per step (suspect scan, honest free space, container truth, snapshots, Docker reclaim, machine-readable `dust` sizes): [references/command-reference.md](references/command-reference.md). ## Error Handling When a number does not reconcile or a cleanup command fails, open the symptom → cause → fix table in [references/troubleshooting.md](references/troubleshooting.md). ## Related Skills - `launchservices-health` — when `launchservicesd` DB bloat (not disk usage) is the concern - `macos-incident-postmortem` — when a freeze/panic, not a full disk, is the symptom - `disk-full-recovery` (user-global rule) — the Linux-focused complement to this APFS-specific skill
在 GitHub 查看