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. Focus a cache and press d to delete it;
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, d to delete the focused
cache, / to filter, and Tab to cycle scopes. Risky deletes use a compact
y/n prompt. Press ? for the complete shortcut guide. Catalog entries
marked scan-only cannot be deleted.
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 uses focused-item deletion: move to a cache and press
d. It confirms recent, large, shared, unknown-age, and download-backed caches. - Pressing
dremeasures the focused cache before deciding whether confirmation is required; confirming triggers another identity and ownership check. 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 even with
--include-recent --yes. --dry-runfollows the same discovery and eligibility policy without deleting anything, and lists every selected path with its size and restore requirements.
Reclaimed bytes are an estimate based on the freshly measured directory size; filesystem free-space deltas can differ because of snapshots, compression, hard links, or concurrent writes.
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) |
| 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.
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 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.2.0.tar.gz.
File metadata
- Download URL: cacheferret-0.2.0.tar.gz
- Upload date:
- Size: 1.6 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f4334444e33aa3af9b98cf6508b7e193209f1772d3728f287a28885fe6146090
|
|
| MD5 |
8f1e672212b969f46f68fb634ac68688
|
|
| BLAKE2b-256 |
c59395981a828758bfcb99ac8b1698b8a6e58f86e77af7978f456d8b23772f0c
|
File details
Details for the file cacheferret-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: cacheferret-0.2.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 842.0 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65b7a515d9f54b19d201369ddc340d81fb7be77cc15c8d028f2640e49b35487d
|
|
| MD5 |
05bd74f6147363e295ff7ac1a738e3df
|
|
| BLAKE2b-256 |
64d7d796834cc1300b042f00c7857d3017719fab63ca4ae19c3cfeffa42ff4ad
|
File details
Details for the file cacheferret-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: cacheferret-0.2.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 784.3 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34669c17f7cf1187f497b035bb5adf61e8b1d6905866ec9b53f70755ee46bc5a
|
|
| MD5 |
a76a19b20c163ccbc518345b54ea9c3d
|
|
| BLAKE2b-256 |
c17bb0b1e526e8b361f79574c2ac84c9beffd528c65fe155ed773f4555038c0f
|
File details
Details for the file cacheferret-0.2.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: cacheferret-0.2.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 740.4 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21a780f6b65b77de6c69c655ebef9bc51aef8632858438ac764be23415aeffce
|
|
| MD5 |
e0eccfd4239dac6c29eb94637af131c2
|
|
| BLAKE2b-256 |
34d4fd1ea306433a751d48fb05da793f06c34f5e1dc57c7c879242b743092cdd
|
File details
Details for the file cacheferret-0.2.0-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: cacheferret-0.2.0-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 797.7 kB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37a336f5bebc5282cb56dff48d05f041a8934b5f9a47632d6905c2951ce2980b
|
|
| MD5 |
ba46140544a27e015d0c0f641f655e9f
|
|
| BLAKE2b-256 |
b965b7fd8b4f679eb521fedba6a849e0ed8ad599c263fedb56cd069672c5227c
|