A Claude Code skill that deeply analyzes a Mac's disk usage and tells you exactly what's safe to delete — without ever deleting anything until you say so.
macOS's own About This Mac → Storage panel is notoriously misleading: its "Documents" and "Applications"/"System Data" categories don't map to the folders they're named after, and the actual weight is usually hiding in dev-tool caches, orphaned app data, and forgotten package-manager stores instead. This skill does its own filesystem-level investigation and gives you a straight answer.
- Orphaned app data — leftover
Application Support/Container/Cachesfolders for apps you already uninstalled, detected by cross-referencing every folder against what's actually still installed (via Spotlight'smdfind). - Regenerable dev-tool caches — npm, pnpm, uv, pip, Homebrew, node-gyp, Go build/module cache, Electron caches, browser HTTP caches — anything that just redownloads or rebuilds automatically.
- Fresh build/dependency artifacts, anywhere under your home directory —
node_modules,.venv,target,build,dist,.next,__pycache__in loose project folders, regardless of how recently you touched them, confirmed against a sibling build manifest before it's ever called safe to delete. - Git repo hygiene, home-wide — pack-file bloat in stale repos, with an unconditional do-not-touch floor for any repo carrying uncommitted changes or stashes.
- System Data — Xcode DerivedData, Time Machine local snapshots, iOS device backups, diagnostic/crash reports, Spotlight index size (informational only), and Docker/VM disk images (checked against whether the daemon/VM is actually running before anything is offered up).
- Mail, Messages, Photos, and iCloud — sized and staleness-checked with a hard floor: this data is never offered as auto-safe, and never bulk-approvable — you always review it row by row.
- Rarely-used apps — surfaced with their actual last-used date and use count (via
mdls), not just a guess. - Large, old files — anything big and untouched for months, excluding noise from dev-tool directories already covered elsewhere.
- Ambiguous/unknown folders — resolved to their real vendor identity via Preferences plists, LaunchAgents, and bundle-ID lookups, and checked against
launchctlto make sure nothing that's actually a live background service gets miscategorized as safe. - Mounted/external volumes — opt-in only, off by default; ask explicitly ("include my external drive") to have it scanned.
- Never deletes anything without your explicit confirmation. You can approve a whole category, cherry-pick specific rows, or ask for more research on anything ambiguous — silence is never treated as approval.
- Never runs
sudoor attempts privilege escalation. Root-owned paths (like parts of/Library/Developer) are reported with the exact command for you to run yourself. - Never touches a sandboxed app Container via shell. macOS blocks this at the OS level (
containermanagerd) even for orphaned apps — those get Finder-based removal steps instead. - Never batches deletions. One path per command, always — smaller blast radius if anything ever goes wrong.
- Never modifies its own instructions without your explicit confirmation. The self-learning loop below can only ever propose an edit to its own files — it never applies one silently.
One synthesized report, every time — a single markdown table:
| Item | Size | Category | Rank | Last-Touched | Purpose | Justification |
|---|---|---|---|---|---|---|
| ... | ... | auto-safe / needs-your-call / do-not-touch | 1-4 or — | ... | ... | ... |
Priority Rank sorts everything reclaimable (auto-safe and needs-your-call) by how easy it is to act on, so you can knock out the easy wins first:
- Rank 1 — instant, zero manual steps
- Rank 2 — safe, but needs one extra step (a
sudocommand or a Finder drag) - Rank 3 — your call, low regret if you're wrong
- Rank 4 — your call, higher stakes (installed software, real personal data, anything touching a registered-but-inactive background service)
do-not-touch rows are never ranked — they're informational only and never counted toward reclaimable space, with a subtotal per category and a grand total, opened and closed with the real free-space number from diskutil info / (not df, which reports confusingly on APFS).
Eight research subagents run in parallel, each covering a distinct slice of the disk:
- Agent A —
~/Librarysweep (Application Support, Caches, Containers, Group Containers) + orphan detection - Agent B — package-manager caches, Homebrew, pipx, nvm, cargo/rustup, Xcode Command Line Tools, CoreSimulator
- Agent C — large/old files elsewhere in the home directory
- Agent D — always-on ambiguity resolver: independently verifies anything unrecognized via LaunchAgents/LaunchDaemons, Preferences plists, and bundle-ID lookups before it can be marked safe
- Agent E — home-wide dev-artifact directories (
node_modules,.venv,target,build,dist,.next,__pycache__) regardless of age, manifest-confirmed before leaning toward removal, plus home-wide git repo discovery - Agent F — System Data: Xcode DerivedData, Time Machine local snapshots, iOS device backups, diagnostic/crash reports, Spotlight index size, Docker/VM disk images
- Agent G — Communications and Cloud: Mail, Messages attachments, Photos Library, iCloud Drive spot-check — best-effort, never produces an auto-safe lean
- Agent H — Applications review, plus opt-in-only mounted/external volume scanning (ask explicitly to include drives)
Their findings are synthesized into one report — backfilling a Last-Touched date and Purpose for any row that doesn't already carry one, and computing each reclaimable row's Priority Rank — gated behind your confirmation, and only then acted on — one path at a time, with automatic handling for read-only cache permissions (chmod before rm) and clear manual instructions for anything that needs your own sudo or Finder. Personal communications data (Mail, Messages, Photos, iOS backups) is never bulk-approvable — even if you approve "everything needs-your-call," those rows still need to be named individually.
Each run reads and writes a small local log, LEARNINGS.local.md, so the skill accumulates history across sessions instead of starting from zero every time:
- What's logged: a one-line summary of each invocation, which agents ran, and — when relevant — one or more coverage gaps or corrections you raise at any point in the session, not just at the final confirmation. That includes naming an uncovered folder before the scan even starts, disputing a category mid-review, or asking afterward to also check an external drive.
- Where it lives:
LEARNINGS.local.mdat the repo root, gitignored. It never leaves this machine — never committed, never referenced in a commit, never shared as part of this skill's own actions. This repo is public on GitHub; a disk-scanning skill's own history will inevitably contain fragments of real personal paths, so it stays local by design. - How it becomes a fix: when the same kind of gap or correction shows up in 2+ separate sessions, the skill proposes a concrete edit to its own reference files — naming the exact file and change — and asks for an explicit yes/no before touching anything. It never applies a self-correction silently, and it will never propose weakening an existing safety floor (the deletion confirmation gate, the Communications-data floor, etc.) no matter how often you push back on one.
- What this doesn't do (yet): aggregate learnings across different machines, installations, or users. This is local history for this one installation only.
git clone https://github.com/SomSamantray/mac-storage-doctor.git ~/.claude/skills/mac-storage-doctorOr copy the folder directly into ~/.claude/skills/.
In Claude Code, just ask naturally:
"What's taking up space on my Mac?" "Help me free up disk space" "Clean up my Mac"
The skill triggers automatically, or invoke it directly if your setup supports named skill invocation.
- macOS (uses
mdfind,mdls,diskutil,launchctl— all Spotlight/macOS-specific) - Claude Code with subagent dispatch support
This skill was built from a real, live cleanup session and encoded the lessons learned the hard way — including a Spotlight-indexing blind spot that could otherwise flip its main safety signal backwards, and several safety floors that keep ambiguous items out of the "safe to delete" bucket by default. See references/playbook.md for the full categorization rules.
MIT