skills/mac-cleanup/SKILL.md
Interactive macOS system cleanup for any dev machine. Frees disk space by pruning caches, package managers, unused apps, stale dev artifacts, and more. Discovers what's installed rather than assuming a specific setup. Always consults the user before deleting anything. Use when the user asks to: clean up their Mac, free disk space, remove unused apps, prune caches, clean developer artifacts, or any disk space maintenance task.
npx skillsauth add jwa91/agentskills mac-cleanupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
An interactive, discovery-based macOS cleanup skill. Works on any Mac dev machine — detects installed tools, package managers, browsers, and dev directories rather than assuming a fixed setup.
These rules are non-negotiable. Follow them at all times:
rm -rf app bundles. Use Finder via osascript to move apps to Trash:
osascript -e 'tell application "Finder" to delete POSIX file "/Applications/App.app"'.git directories. Only clean merged branches (via git branch -d), never remove .git itself./System, /Library (root level), /usr, /bin, /sbin are off-limits.sudo unless the user explicitly asks for elevated privileges and understands why.rm -rf ~/Downloads/* without showing item count and total size.Before scanning, gather context about the system:
uname -m to detect architecture (Apple Silicon vs Intel — determines Homebrew prefix)/opt/homebrew (Apple Silicon) or /usr/local (Intel)which brew npm pnpm yarn bun uv pip3 cargo go pyenv/Applications/ for installed browsers~/developer, ~/Developer, ~/dev, ~/projects, ~/Projects, ~/src, ~/code, ~/workspace, ~/reposNote: The scan script's tool detection (shutil.which()) is authoritative — it may find tools that the shell's which misses due to PATH differences.
Run the scan script with the discovered configuration:
uv run .agents/skills/mac-cleanup/scripts/scan.py \
--dev-dirs <discovered_dirs> \
--stale-days <threshold> \
--skip <protected_paths>
If uv is not available, fall back to python3.
The script runs all checks in parallel and outputs a JSON report to stdout. Read the full JSON output to understand what's on the system.
If the scan script is unavailable or fails, fall back to manual commands:
df -h / — overall disk usagedu -sh ~/Library/Caches ~/Library/Logs ~/.cache ~/.npm ~/.Trash ~/Downloads — quick size surveyreferences/cleanup-catalog.md)Show the user a summary table grouped by category. Include:
| Category | Item | Size | Risk | Status | |----------|------|------|------|--------| | Package caches | Homebrew | 3.2 GB | safe | 12 stale items | | System caches | ~/Library/Caches | 8.1 GB | moderate | Top: Xcode (4 GB) | | Dev artifacts | node_modules (5 stale) | 2.3 GB | safe | >90 days old | | Docker | Images + containers | 15 GB | moderate | 8 unused images | | Trash | ~/.Trash | 1.2 GB | moderate | | | Downloads | ~/Downloads | 4.5 GB | high | 127 items |
Sort by size (largest first). Flag risk levels:
Before starting, ask the user if there are paths that should be protected/skipped during cleanup.
Walk through categories from safest to riskiest. For each:
Consult references/cleanup-catalog.md for the correct detection, cleanup command, and dry-run command for each category.
Order of operations (safest first):
~/Library/Logs)__pycache__, .pytest_cache, etc.)~/Library/Caches — per-subdirectory, with breakdown)docker system df, ask about aggressiveness level)| App | Size | Description | using brew info --json for descriptions and sizes, ask which are unused)App uninstall procedure:
mdls -name kMDItemCFBundleIdentifier /Applications/AppName.apposascript -e 'tell application "Finder" to delete POSIX file "/Applications/AppName.app"'~/Library/Application Support/<AppName>~/Library/Caches/<bundleid>~/Library/Preferences/<bundleid>.plist~/Library/HTTPStorages/<bundleid>~/Library/Logs/<AppName>~/Library/Containers/<bundleid>~/Library/Group Containers/<bundleid>~/Library/Saved Application State/<bundleid>.savedState~/Library/WebKit/<bundleid>After all cleanup actions are complete, show:
open -a Docker, wait for daemon readiness (poll docker info up to 30s).
If no: flag prominently in report: "Docker skipped (not running) — restart and re-run to check."/usr/local for Homebrew prefix. All other commands work the same.du/df commands as described in Step 2.~/.cache/huggingface or similar can be huge. Flag these specifically and warn about re-download costs.Do NOT do any of the following:
rm -rf / or any variation targeting the root filesystem.git directories — only clean merged branchessudo by default — only when the user explicitly requests it and for a specific reason~/Library/Application Support — this contains critical app data. Only remove entries for apps the user has confirmed they uninstalled.~/Library/Application Support or ~/Library/Containers — these can be enormous and slow. Only check specific subdirectories.data-ai
Release the current project to the personal Homebrew tap from repo-local release config. Use when the user says "release", "ship", "cut a version", "publish", "make a new tag", or asks how to make a new version available via jwa91/tap.
tools
Use the `jwa-harden` CLI for secret-safe command execution, env-template discovery, and signing/notarization preflight checks. Trigger when a command needs secrets, when `.env.template` or 1Password references are involved, or before signed release flows.
documentation
Modify or extend the `jwa-tobrew` scaffolding system — the templates that `init` writes into target projects. Trigger when the user says "add a new scaffold kind", "change what init writes", "update the templates", or asks how the embedded templates are wired.
development
Detect and fix drift between a project and the conventions encoded in `jwa-tobrew`, prek, and the tap ADRs. Trigger when the user says "align", "any drift", "verify conventions", or asks why a particular file/symlink/script is required.