| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A free, open-source macOS utility that helps developers reclaim disk space by scanning and cleaning common cache directories.
Built for developers on space-constrained Macs (especially the 256GB M4 Mac Mini), Cacheout finds and removes caches from Xcode, Docker, npm, Yarn, Homebrew, browsers, and more — typically recovering 20-60GB.
git clone https://github.com/yourusername/cacheout.git
cd cacheout
bash scripts/bundle.sh
open Cacheout.appThis builds the project and creates a proper Cacheout.app bundle you can drag to /Applications.
swift build -c release
.build/release/Cacheoutopen Package.swift
# Build and run from Xcode (⌘R)| Category | Risk | What happens after cleaning |
|---|---|---|
| Xcode DerivedData | ✅ Safe | Xcode rebuilds on next build |
| Xcode Device Support | 🟡 Review | Re-downloads when you connect a device |
| Homebrew Cache | ✅ Safe | Equivalent to brew cleanup |
| npm Cache | ✅ Safe | npm re-downloads on install |
| Yarn Cache | ✅ Safe | Yarn re-downloads on install |
| pnpm Store | ✅ Safe | pnpm re-downloads on install |
| Playwright Browsers | ✅ Safe | npx playwright install to restore |
| CocoaPods Cache | ✅ Safe | pod install re-downloads |
| Swift PM Cache | ✅ Safe | SPM re-resolves on next build |
| Gradle Cache | ✅ Safe | Gradle re-downloads on build |
| Docker Disk Image | 🔴 Caution | Removes all Docker data — run docker system prune -a first |
| Browser Caches | 🟡 Review | Browsers rebuild as you browse |
| VS Code Cache | ✅ Safe | VS Code re-downloads as needed |
| Electron Cache | ✅ Safe | Re-downloads when Electron apps need it |
| pip Cache | ✅ Safe | pip re-downloads on install |
This table is a sample — see docs/v1/CATEGORIES.md for every category with paths, discovery method, and risk level.
Cacheout walks your configured dev roots (by default ~/Documents, ~/Developer, ~/Projects, ~/Code, ~/Sites, ~/Desktop, ~/Dropbox, ~/repos, ~/src, ~/work — editable in Settings) for build-output directories, and reports each one it can PROVE: a target/ beside a Cargo.toml, a node_modules/ beside a package.json, a directory containing a pyvenv.cfg, and the rest of the rule table. A directory with the right name but no marker is never touched.
Each find shows its path, size and how long since the last build; anything untouched for 30+ days gets an age badge, and you can select all stale finds at once or pick individually. Sizes are allocated, sparse-aware bytes — a Rust target/ that looks like 57 GB but occupies 31 GB reports 31 GB, with the apparent size shown separately so the number you budget against is the number you get back.
Release artifacts are protected. Before deleting, Cacheout inspects the directory for .dmg, .pkg, .ipa, .app, .xcarchive and .dSYM payloads. Anything it finds is listed on the confirmation sheet and the delete is refused until you acknowledge exactly what is there — and it re-checks immediately before deleting, so an artifact produced after the scan still stops the deletion.
Headless too: --cli scan lists every find as a scanner_items row, and --cli clean build_artifacts --confirm (or build_artifacts:<item-id> for one) deletes them. See docs/v1/CLI-REFERENCE.md.
/private/tmp and your per-user temp and cache containers collect scratch directories that nothing on modern macOS reliably cleans up — a month-old build sandbox or agent workspace can sit there through reboots. Cacheout lists the stale ones: an entry qualifies when its own timestamp and its newest REGULAR FILE are both older than the age threshold (7 days by default) and it is at least 10 MB, so a directory holding one fresh file deep inside is left alone, and so is anything the current session just wrote.
Those two thresholds decide which MEASURED entries are offered. An entry Cacheout could not measure — a denied read, or a mounted volume it refuses to enter — is listed anyway, as an explicit not-measured row: the size cut never hides one, because a zero it could not verify must not read as "nothing here".
A nested directory's OWN timestamp is deliberately not an input, at scan time or at delete time — only the entry's own timestamp and the mtimes of the REGULAR FILES below it. So a write at the top level of the entry is caught, while one that only re-stamps a directory deeper down is not.
That is a statement about the TIMESTAMP, not about the operations that move it, and the difference matters: a nested change can still trip a gate that is not a timestamp at all. Unlinking a file inside a nested directory can take the entry below the size floor, and creating enough subdirectories inside one can push its contents past the budget the inspection walk is bounded by — either of those both keeps the entry off the list and refuses it at delete time. (Earlier releases of this document claimed the whole class of such changes was invisible on both sides. Two of the five operations it named were not, and there is now a falsifier per operation beside the code.)
Cacheout also skips an entry a process has taken an advisory lock on, but that check only sees a lock on the entry itself — it cannot detect a process merely holding a file open somewhere inside. Age is the real protection, and every gate is re-established from a held descriptor immediately before deletion, so an entry is refused if it was replaced under the same name, its own directory changed, a fresh regular file appeared anywhere inside it, it shrank below the size floor, or its contents could not be fully re-inspected within that budget.
These locations are scanned only when you explicitly press Scan (or run --cli scan) — automatic background refreshes never touch them. Findings are always Review risk and never selected for you, an ordinary temp entry another user owns is skipped rather than listed, and anything Cacheout could not read is reported rather than quietly counted as empty. (The one entry that is listed without its owner being checked is a mounted volume: that arm runs first, deliberately, so a dead or foreign mount is refused and reported without Cacheout ever touching it.)
Cacheout scans known cache directories in your home folder (~/Library/Caches, ~/Library/Developer, ~/.npm, etc.), your configured dev roots, and the ephemeral temp locations above, and calculates actual disk usage using totalFileAllocatedSize (which correctly handles sparse files like Docker's disk image).
You select which caches to clean, confirm the action, and Cacheout either moves them to Trash or permanently deletes them. All cleanup actions are logged.
PRs welcome! To add a new cache category, edit Sources/Cacheout/Scanner/Categories.swift and add a new CacheCategory entry.
MIT — See LICENSE
| Back | FazBrowse Home | New Git URL |