mac-cleanup
macOS Cleanup
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.
Safety Rules
These rules are non-negotiable. Follow them at all times:
- Never delete without approval. Always show what will be deleted, its size, and get explicit user confirmation before executing any destructive command.
- Never
rm -rfapp bundles. Use Finder via osascript to move apps to Trash:osascript -e 'tell application "Finder" to delete POSIX file "/Applications/App.app"' - Never clear browser profile data (cookies, history, passwords in ~/Library/Application Support/). OS-level browser caches in ~/Library/Caches/ are safe to remove like any app cache.
- Honor protected paths. Ask the user for any paths that should be skipped, and never touch them.
- Never touch
.gitdirectories. Only clean merged branches (viagit branch -d), never remove.gititself. - Never touch system directories.
/System,/Library(root level),/usr,/bin,/sbinare off-limits. - Never use
sudounless the user explicitly asks for elevated privileges and understands why. - Keep a running tally. Track and display cumulative space freed after each action.
- Default stale threshold: 90 days. Dev artifacts not modified in 90+ days are flagged as stale. The user can override this.
- Confirm before bulk operations. Never run commands like
rm -rf ~/Downloads/*without showing item count and total size.
Workflow
1. Discover & Configure
Before scanning, gather context about the system:
- Run
uname -mto detect architecture (Apple Silicon vs Intel — determines Homebrew prefix) - Detect the Homebrew prefix:
/opt/homebrew(Apple Silicon) or/usr/local(Intel) - Check which package managers are installed:
which brew npm pnpm yarn bun uv pip3 cargo go pyenv - Scan
/Applications/for installed browsers - Identify dev directories — check common locations:
~/developer,~/Developer,~/dev,~/projects,~/Projects,~/src,~/code,~/workspace,~/repos - Ask the user:
- Are there additional dev directories to scan?
- Should the stale threshold be something other than 90 days?
Note: The scan script's tool detection (shutil.which()) is authoritative — it may find tools that the shell's which misses due to PATH differences.
2. Scan
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 survey- Check package manager caches individually (see
references/cleanup-catalog.md)
3. Present Findings
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:
- safe — always reclaimable, rebuilds automatically
- moderate — reclaimable but may need re-download or rebuild time
- high — potential data loss, needs careful review
4. Clean Up Interactively
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:
- Show exactly what will be deleted and its size
- Show the command that will run
- Get user approval
- Execute the command
- Report space freed
Consult references/cleanup-catalog.md for the correct detection, cleanup command, and dry-run command for each category.
Order of operations (safest first):
- Package manager caches (brew, npm, pnpm, yarn, bun, uv, pip, cargo, go)
- System logs (
~/Library/Logs) - Stale dev artifacts (node_modules, .venv, build dirs older than threshold)
- Python bytecode caches (
__pycache__,.pytest_cache, etc.) - Merged git branches
- System caches (
~/Library/Caches— per-subdirectory, with breakdown) - Docker (show
docker system df, ask about aggressiveness level) - Homebrew — unused formulae/casks (list installed as a table with
| App | Size | Description |usingbrew info --jsonfor descriptions and sizes, ask which are unused) - Trash
- Downloads (show largest files, never bulk-delete without review)
- Application uninstall (if user wants — quit first, use Finder, clean support files)
App uninstall procedure:
- Get bundle ID:
mdls -name kMDItemCFBundleIdentifier /Applications/AppName.app - Quit the app if running
- Move to Trash via Finder:
osascript -e 'tell application "Finder" to delete POSIX file "/Applications/AppName.app"' - Clean support files in these locations (use the bundle ID):
~/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>
5. Report
After all cleanup actions are complete, show:
- Before/after disk comparison: free space before vs after
- Actions taken: list every action with space freed
- Total space freed: cumulative sum
- Declined items: what was skipped and why, with suggestions for future cleanup
- Maintenance tips: suggest scheduling periodic cleanup for categories that grow back
Edge Cases
- Docker not running: Docker images/containers can use 10+ GB. Ask the user:
"Docker is installed but not running. Want to start Docker Desktop to check for reclaimable space?"
If yes:
open -a Docker, wait for daemon readiness (polldocker infoup to 30s). If no: flag prominently in report: "Docker skipped (not running) — restart and re-run to check." - No dev directories found: Skip dev artifact scan. Ask the user if they have dev work in a non-standard location.
- Intel Mac: Use
/usr/localfor Homebrew prefix. All other commands work the same. - Command failures: Log the error, skip that category, continue with the rest. Report all errors at the end.
- Nothing to clean: Report that the system is already in good shape. Show current disk usage.
- Scan script missing: Fall back to manual
du/dfcommands as described in Step 2. - Large ML caches:
~/.cache/huggingfaceor similar can be huge. Flag these specifically and warn about re-download costs.
Anti-Patterns
Do NOT do any of the following:
rm -rf /or any variation targeting the root filesystem- Delete
.gitdirectories — only clean merged branches - Use
sudoby default — only when the user explicitly requests it and for a specific reason - Bulk-delete
~/Library/Application Support— this contains critical app data. Only remove entries for apps the user has confirmed they uninstalled. - Run recursive finds on huge system directories like
~/Library/Application Supportor~/Library/Containers— these can be enormous and slow. Only check specific subdirectories. - Delete Xcode derived data without warning — it can be very large but takes time to rebuild. Always flag the size and rebuild cost.
- Clear browser caches programmatically — this can corrupt browser state. Always direct users to browser settings.
- Force-prune Docker volumes — these may contain database data. Always show volume names and get explicit approval.
More from jwa91/agentskills
interactive-learner
Personal AI tutoring skill that deeply researches any topic, then creates rich, interactive HTML courses with quizzes, simulators, debug challenges, explain-back exercises, real-world missions, and more. Tracks per-concept mastery across sessions with spaced repetition. Use when: (1) the user wants to learn a new topic, (2) the user says 'teach me X' or 'I want to learn X', (3) the user asks for an interactive lesson or course, (4) the user wants to study or review a subject. Works for any topic: technical, conceptual, creative, math, languages.
15spec
Interviews the user about a product idea or feature using structured questions, then generates a detailed spec document (SPEC.md). Use when the user wants to flesh out an idea, plan a feature, or create a buildable specification.
5personal-commit-review
Create a personal GitHub coding retrospective from a date range and turn it into a short Markdown review. Research commit activity across accessible public and private repositories through the authenticated gh CLI, understand what the relevant repositories and subsystems are for, and write a prose retrospective with stats and highlights. Use when the user asks for a commit review, coding recap, engineering retrospective, GitHub activity story, weekly/monthly/yearly highlights, or a written summary of what their commits achieved.
3env-inspector
Safely inspect .env files by showing key names and clearly non-sensitive values while redacting anything that looks like a secret. Best-effort heuristic redaction (keyword block + token-pattern blocklist + Shannon-entropy check + value allowlist) — not a cryptographic guarantee. Use when you need to understand a project's environment configuration without exposing credentials.
2vps-dependency-overview
Generate an offline-first dependency overview across services in a Docker-compose monorepo. Reports image tags & pinning quality, Dockerfile base images, runtime hints (Node/Python via .nvmrc, .python-version, package.json engines, pyproject.toml), and lockfile presence. Use when you want a single report of "what am I running and where are my update surfaces?" — no network calls, no pulls.
2vps-service-status
Quick health checks for a Dockerized VPS. Use to verify services are running, check container status, view logs, or get a system overview (disk, memory, CPU). Read-only by design — anything that would change state is routed through the clipboard for the user to paste.
2