Reclaim disk space from dev junk — without the black box.
CleanMahMac is a macOS CLI that cleans regenerable development caches and abandoned dependencies.
The command is cmm, not CleanMahMac.
- Dry-run by default — nothing is deleted unless you pass
--force - Confirmation prompts — destructive actions ask before proceeding
- Allowlist validation — only known-safe paths can be removed
- Protected paths — home, system dirs, and source roots are blocked
- No blind
rm -rf— targeted removal with path checks - Never deletes source code — only caches, build artifacts, and
node_modules - No telemetry — your disk shame stays local (lol)
git clone https://github.com/Sabique-Islam/CleanMahMac.git
cd CleanMahMac
./install.shinstall.sh runs chmod +x on all scripts automatically. If you clone without installing and get "Permission denied", run:
cmm fix-permissions
# or manually:
chmod +x cmm install.sh uninstall.sh
find . -type f \( -name '*.sh' -o -name cmm \) ! -path './tests/fixtures/*' -exec chmod +x {} +When a script is not executable, cmm prints the exact fix command and asks whether to repair permissions automatically.
Ensure ~/.local/bin is on your PATH:
export PATH="$HOME/.local/bin:$PATH"Uninstall:
./uninstall.sh# Scan everything (safe, no deletes)
cmm scan
# Readable report grouped by module
cmm report
# Detect disk hogs and anomalies
cmm doctor
# Configure which folders to scan (arrow-key picker — include ~/Downloads if you use it)
cmm configure
# Fix script permissions if needed
cmm fix-permissions
# Preview cleanup for a module (dry-run)
cmm clean xcode
cmm clean docker
cmm clean abandoned-node-modules
# Actually delete (with confirmation)
cmm clean xcode --force
cmm clean abandoned-node-modules --force
# Skip prompts (CI / power users)
cmm clean node --force --yes
# Clean everything
cmm clean all --force| Module | What it cleans |
|---|---|
xcode |
DerivedData, Archives, DeviceSupport, CoreSimulator, SwiftPM caches |
docker |
Build cache, dangling images, stopped containers; optional volumes with --volumes |
android |
Android Studio caches, AVDs, Gradle caches, SDK temp files |
flutter |
Pub cache, build/ artifacts in dev folders |
node |
npm, pnpm, and Yarn caches |
python |
pip, uv, and Poetry caches |
rust |
Cargo registry and git cache |
go |
Go build and module cache |
java |
Gradle and Maven caches |
homebrew |
Old downloads, cleanup, autoremove |
abandoned-node-modules |
Stale node_modules in idle projects (see below) |
You choose which folders to scan — nothing is assumed. Run cmm configure to pick from every dev folder found on your Mac (including ~/Downloads if it exists and contains projects):
cmm configureThe picker shows all discovered folders. Use ↑/↓ to move, Space to toggle (x), Enter to confirm, then confirm again before saving. Settings are saved to ~/.config/cleanmahmac/scan-roots.txt.
It finds Node projects (via package.json or lockfiles), and if:
- The project has a
node_modulesdirectory, and - The project hasn't been accessed or modified in 15+ days (configurable in
configs/rules.json)
…it marks that node_modules as reclaimable.
Safety: ~/Downloads and other user folders are protected from wholesale deletion — only node_modules inside projects you opted into can be removed, and only after confirmation.
Example output:
Found abandoned projects
~/Projects/chat-app
Last active: 48 days ago
node_modules: 1.8 GB
~/Projects/old-dashboard
Last active: 92 days ago
node_modules: 3.4 GB
Total reclaimable: 5.2 GB
Run npm install (or your package manager) anytime to restore dependencies. Your source code is never touched.
cmm doctor detects anomalies without deleting anything:
- Non-executable repo scripts (run
cmm fix-permissions) - Huge
Docker.rawVM disks - Excessive iOS simulators
- Abandoned
node_modules - Giant log files (>500 MB)
- Duplicate Android SDK versions
- Oversized caches (Xcode, Gradle, npm, Homebrew)
- Orphaned Docker volumes
- Large forgotten Xcode archives
Typical results on a well-used dev Mac (your mileage will vary):
| Target | Typical savings |
|---|---|
| Xcode DerivedData | 5–30 GB |
| Abandoned node_modules | 2–15 GB |
| Docker system prune | 1–20 GB |
| npm + Homebrew caches | 500 MB–5 GB |
| Android Gradle cache | 1–10 GB |
Run cmm scan to see your actual numbers before deleting anything.
configs/rules.json— thresholds, scan roots, module listconfigs/safe-paths.txt— paths allowed for deletionconfigs/protected-paths.txt— paths never touched
- Create
scripts/dev/my-tool.shwith two functions:cmm_scan_my_tool()— populate results viacmm_add_scan_resultcmm_clean_my_tool()— scan, show totals, confirm, callcmm_safe_remove
- Add
"my-tool"toconfigs/rules.json→modules - Add safe paths to
configs/safe-paths.txt - Run
cmm scanto verify
See scripts/dev/node.sh for a minimal example.
# Run tests
./tests/run-tests.sh
# Lint
shellcheck -x cmm scripts/**/*.sh