A full cleanup pass — scan, read the report, handle the two big "why didn't my free space change?" traps (Docker's VM disk and Time Machine local snapshots), preview a cleanup, then run the safe tier. Written from a real session on a Mac that went from 14 GB to 70 GB free. Nothing below deletes anything until step 6.
devdoctor scan --json > /tmp/dd_report.json
scan is read-only: it never deletes, moves, or modifies anything. --json emits the structured report (see the CLI reference for the full contract). Summarize it:
total_reclaimable_bytes — the headline: estimated reclaimable space.per_provider — bytes per provider, biggest first. This tells you where to look.entries — one item per cleanable thing, each with provider, label, path, size_bytes, risk (safe / reclaimable / dangerous), and the actions DevDoctor would take.diagnostics — paths that could not be read (e.g. permission denied). Entries you cannot see cannot be counted; re-run with Full Disk Access or sudo if the total looks too small.Prefer --json whenever output is piped or captured: the Rich table that devdoctor scan prints to a terminal truncates wide rows.
devdoctor scan --min-size 100M --risk safe,reclaimable
devdoctor scan --provider docker
devdoctor providers # everything registered, with availability
| Risk | Meaning | clean behavior |
|---|---|---|
safe | Regenerable caches (package-manager downloads, build caches) | Offered; --yes-safe auto-approves |
reclaimable | Rebuildable but costs time/bandwidth (containers, models, worktrees) | Offered; always prompted per entry |
dangerous | May hold durable user data (~/Downloads, named Docker volumes, large files) | Skipped unless --allow-dangerous |
Dangerous entries are usually advice-only: DevDoctor prints what you could do instead of running anything. See the safety model and the provider catalogue.
On Docker Desktop (macOS), containers and images live inside a Linux VM whose disk is a file on your Mac (Docker.raw). DevDoctor's docker provider prunes inside the VM; unused volumes are reviewed one by one — named volumes are dangerous, anonymous ones reclaimable.
The trap: after a big prune, Finder's free space may barely move. The VM disk file compacts later, not instantly. Give it time, restart Docker Desktop if you are in a hurry, and judge the prune by docker system df, not by the menu-bar number in the first minute. See the FAQ.
On macOS, hourly Time Machine local snapshots pin disk blocks: other cleanups can delete files yet the space stays allocated until the snapshots age out. If a cleanup reports success but free space is flat, check here first:
devdoctor scan --provider time-machine-local-snapshots
The provider lists each snapshot plus one bundle entry that deletes all but the newest restore point (newest first), so you always keep a restore point. macOS system-update snapshots (com.apple.os.update-*) are never touched, and deleting local snapshots never touches the external backup drive. In the session this tutorial is based on, thinning snapshots was the step that finally released the space other cleanups had already freed. (Linux has no equivalent provider — skip this step there.)
devdoctor clean
devdoctor recipe -o /tmp/cleanup.sh # everything commented out; you pick
clean with no flags prints the report table and stops. Zero prompts, zero shell calls.
devdoctor clean --execute --yes-safe
What happens, in order: the plan prints first (path, risk, estimated reclaim, exact command per entry); you confirm once; each entry runs with a per-entry line (✓ done, ✗ failed with the error, - skipped, · advice-only); the summary states estimated reclaimed vs. planned plus the measured free-space change; every run is recorded (devdoctor history, devdoctor history 1 for the newest in detail).
devdoctor clean --execute --risk safe --provider uv-cache # one safe cache
devdoctor clean --execute --yes-safe # all safe entries
devdoctor clean --execute --provider docker # reclaimable, prompted
devdoctor clean --execute --provider time-machine-local-snapshots
Unattended runs add --yes (plan still prints, final confirmation skipped); without a terminal, --execute refuses unless --yes is passed. --allow-dangerous stays a separate, explicit opt-in — never bundle it into a routine command.
devdoctor snapshot --note "before cleanup"
# ... clean ...
devdoctor diff --to live # last snapshot vs. now
Prefer a GUI? devdoctor serve (needs the web extra) opens the local dashboard with the same engine. See the Web UI guide.
Next: CLI reference · Provider catalogue · Safety model · FAQ · Docs for agents