CacheFerret
CacheFerret finds rebuildable developer caches across macOS and Linux, shows where the disk space went, and removes the caches you choose. Run it in a terminal for a fast, keyboard-first workspace; pipe it for structured JSON.
Opening the TUI starts with a scan. Press Space to select caches quickly, then
d to delete the batch; with no selection, d deletes the focused cache.
Recent, large, shared, unknown-age, and download-backed caches ask first.
Install
# Homebrew on macOS or Linux
brew install rvben/tap/cacheferret
# Cargo
cargo install cacheferret
# PyPI / pipx
pipx install cacheferret
Release archives include checksums, documentation, and completions for Bash, Zsh, Fish, PowerShell, and Elvish on Intel and ARM Linux and macOS.
Quick start
# Open the interactive cache workspace
cacheferret
# Open the workspace for one source tree
cacheferret tui --root ~/Projects --scope project
# Produce plain or structured scan output without opening the TUI
cacheferret scan --root ~/Projects --scope project
# Preview old project caches that are eligible for cleanup
cacheferret clean --root ~/Projects --dry-run
# Clean after an interactive confirmation
cacheferret clean --root ~/Projects
# Confirm from a script or agent
cacheferret clean --root ~/Projects --yes
# Shared caches are never part of the default clean scope
cacheferret clean --scope global --include-recent --dry-run
cacheferret clean --scope global --include-recent --yes
Inside the TUI, use the arrow keys or j/k to move, Space to select and
advance, a to toggle all visible caches, and d to delete the selection or
focused cache. Use / to filter and Tab to cycle scopes. Risky batches use a
single compact y/n prompt. Press ? for the complete shortcut guide.
Catalog entries marked scan-only are excluded from focused deletion, a batch
selection, and CLI cleanup. Select one individually with Space to request a
manual override; d then requires confirmation and repeats the safety checks.
CacheFerret adapts automatically to truecolor, 256-color, basic ANSI, no-color, and
non-UTF-8 terminals. Set NO_COLOR=1 for an uncolored interface,
CACHEFERRET_ASCII=1 for ASCII-only glyphs, or
CACHEFERRET_REDUCE_MOTION=1 for static progress indicators.
Output is human-readable on a terminal and JSON when piped:
cacheferret scan --limit 20 --fields kind,path,bytes |
jq '.items[] | select(.bytes > 1073741824)'
Safety model
- Bare
cacheferretopens the TUI on a terminal and emits a read-only JSON scan when piped.cacheferret scannever mutates the filesystem. - The TUI supports both focused and batch deletion: press
Spaceto build a selection, thend; when nothing is selected,dacts on the focused cache. - Pressing
dremeasures every target before deciding whether confirmation is required. A risky batch gets one confirmation, and every target receives another identity and ownership check immediately before removal. cleandefaults to project caches; shared global caches require an explicit--scope globalor--scope all.- The batch
cleancommand protects caches modified in the last seven days unless--include-recentis passed. Change the window with--protect-days. - A non-interactive clean refuses to run without
--yesand exits with the declaredconfirmation_requirederror. - Cache roots must match a closed catalog and their project ownership markers.
- Symlinks are never followed.
- Immediately before each deletion, CacheFerret checks the path, filesystem identity, scan-root containment, kind, and ownership markers again.
- Targets that need package downloads to restore are identified in scan and clean output.
- Shared stores that can contain or back irreplaceable project state are
scan-only and remain excluded from CLI cleanup even with
--include-recent --yes. The TUI permits deletion only after individualSpaceselection and an explicit override confirmation. - On macOS, CacheFerret recognizes Chrome code-signing clones and strongly identified build caches in system temporary storage. Large temporary project workspaces are visible but scan-only because they may contain unique work; they require the same individual TUI override.
- Temporary caches must remain unchanged between their final measurement and deletion. Active writers cause cleanup to stop with a conflict.
--dry-runfollows the same discovery and eligibility policy without deleting anything, and lists every selected path with its apparent size, allocated-block estimate, and restore requirements.
CacheFerret reports storage in three deliberately separate layers:
- Apparent bytes are the logical file lengths, with hard links counted once.
- Allocated bytes are the filesystem blocks attributed to the tree before deletion. This is still only an upper-bound estimate on APFS because cloned files can share those blocks with files outside the deleted tree.
- Observed disk-free change is sampled immediately before and after a real cleanup. It is the strongest available answer to “what did this cleanup free?” but remains a net filesystem measurement, so concurrent writes, snapshots, delayed reclamation, compression, and shared clone blocks can make it differ from both size estimates—or even make it negative.
JSON exposes the explicit apparent_bytes_*, allocated_bytes_*, and
filesystem_deltas fields. Free-space deltas remain per filesystem and are not
summed across volumes, because APFS volumes may share one underlying storage
pool. The older bytes_selected and bytes_reclaimed_estimate fields remain as
apparent-byte compatibility aliases.
Supported caches
cacheferret catalog returns the complete machine-readable catalog. The first
release covers:
| ecosystem | project caches | shared caches |
|---|---|---|
| Rust | Cargo target/ |
Cargo registry and git checkouts |
| Python | virtualenvs, bytecode, pytest, mypy, Ruff, tox, nox | pip and uv |
| JavaScript | node_modules |
npm, pnpm, Bun, Deno |
| Go | — | compiler and module caches |
| JVM/Android | Gradle output and project cache, Maven target/ |
Gradle; Maven repository (scan-only) |
| .NET | bin/, obj/ |
NuGet packages |
| Ruby/PHP | Bundler and Composer dependencies | RubyGems and Composer caches |
| Swift | SwiftPM .build/ |
SwiftPM caches and Xcode DerivedData |
| C/C++ | verified CMake build trees | ccache |
| Zig/Dart/Elixir | project build and dependency state | Zig, pub, and Hex caches |
| Haskell | Stack and Cabal project output | Stack and Cabal stores |
| Terraform/R | modules, providers, renv project libraries | configured provider; renv cache (scan-only) |
| macOS | — | Chrome signing clones, temporary build caches, and large temporary workspaces (scan-only) |
| Other | any directory with a valid CACHEDIR.TAG |
— |
Docker build data is intentionally not treated as a directory cache. It needs a
separate native docker builder prune integration with Docker-aware sizing and
is planned as a follow-up.
The Maven local repository is scan-only because it may contain unpublished locally installed artifacts. The shared renv cache is scan-only because project libraries may link packages from it.
Temporary-storage discovery is deliberately narrow. CacheFerret only considers
directories owned by the current user, never follows symlinks, and does not
treat arbitrary /private/tmp contents as deletable. Recognizable build/cache
names are cleanable; large directories with project markers are reported as
scan-only diagnostic findings. Global cleanup remains opt-in, and recent
temporary entries remain protected unless --include-recent is supplied.
Commands
| command | behavior |
|---|---|
cacheferret |
Open the TUI on a terminal; scan as JSON when piped |
cacheferret tui |
Open the interactive browser with optional discovery filters |
cacheferret scan |
Scan with root, scope, kind, pagination, and field controls |
cacheferret clean |
Preview or clean eligible caches |
cacheferret catalog |
List supported cache kinds with pagination and field controls |
cacheferret schema [path] |
Print or narrow the clispec.dev v0.3 contract |
cacheferret completions <shell> |
Generate shell completions |
Use cacheferret <command> --help for every option.
Agent contract
CacheFerret follows clispec.dev v0.3:
- explicit JSON via
--output jsonand automatic JSON when piped; - data on stdout and diagnostics on stderr;
- structured error envelopes as the last stderr line in JSON mode;
- offline
schemaintrospection with effects, cardinality, pagination, output fields, confirmation gates, and stable exit codes; - offset pagination and
--fieldsfor the unbounded scan result; - honest
read_onlyandidempotenteffect declarations.
cacheferret schema
cacheferret schema clean
| exit | kind | meaning |
|---|---|---|
0 |
— | Success, including a no-op clean |
2 |
invalid_input |
Invalid root, cache kind, field, or value |
3 |
usage |
Invalid command-line invocation |
4 |
io |
Filesystem or process operation failed |
5 |
conflict |
Every target changed or became unsafe before deletion |
6 |
confirmation_required |
A non-TTY clean omitted --yes |
Development
make check # format, clippy, and tests
make conformance # build and score the CLI against clispec.dev
See docs/releasing.md for the release checklist and docs/product.md for the durable product direction. See SECURITY.md for private vulnerability reporting.
The generated mascot and wordmark in assets/ are initial brand concepts. A
future design pass can trace the chosen mark into deterministic SVG assets.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cacheferret-0.4.2.tar.gz.
File metadata
- Download URL: cacheferret-0.4.2.tar.gz
- Upload date:
- Size: 1.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.15.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bca9e35eca16265fe5f0fee45ef8d09e6c75686c41bab51377110eb1ceef5bd
|
|
| MD5 |
63fa0b6b5c61f3af3a67350e09dcb85c
|
|
| BLAKE2b-256 |
55a90ae92aef54e80f9fdeb95985f16eeac3b8d637c9984f315fd5928ef198a6
|
File details
Details for the file cacheferret-0.4.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: cacheferret-0.4.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 893.8 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.15.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2ece18a570f84b68eea9cd75d46a5455170cf5b2f055caed11a199748a625405
|
|
| MD5 |
b88edc90b81e4f09a532529bda9608de
|
|
| BLAKE2b-256 |
14b0f7c51bbff5510eb9e91d289974d84f185779e3095ec692e3731ab041faab
|
File details
Details for the file cacheferret-0.4.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: cacheferret-0.4.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 844.1 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.15.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cf98a1c53884d6372ec354f4781db3e4278b1d2e4dff9cf91192f0c3f3d9be87
|
|
| MD5 |
0a9df5070ee0070a68027b7b44a1a742
|
|
| BLAKE2b-256 |
f38f94a57aa89046e8a87296273797b3ab86f10b38df66ce348a882391972749
|
File details
Details for the file cacheferret-0.4.2-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: cacheferret-0.4.2-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 818.4 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.15.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
46192332a4e279b48bf00e8db8cba0f67f5b508e53b0c7fa12641f23506c0fb8
|
|
| MD5 |
0235dcebffe4efee706ef214054aa3ee
|
|
| BLAKE2b-256 |
f86776a9cf9e223c9aa97b57af7ba3acfd040b55ef76bf5d686c93d8f49ce0de
|
File details
Details for the file cacheferret-0.4.2-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: cacheferret-0.4.2-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 863.9 kB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
maturin/1.15.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3fbea716fc18693d53f06159ac11fcb95faf87aa087ab25e0b3678e193f2335e
|
|
| MD5 |
b5f134ab04d450505a67b8f356bc907b
|
|
| BLAKE2b-256 |
87e850047db4c5aa60bed009a43eb68778f58811c218482bbbe7a91283a0200e
|