Skip to main content

CacheFerret

CacheFerret

CI public installs crates.io clispec

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

# Inspect Docker-managed storage without pruning anything
cacheferret docker

# Preview the bounded Docker build-cache cleanup
cacheferret docker clean --dry-run

# Confirm Docker build-cache cleanup from a script or agent
cacheferret docker clean --yes

# 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. Docker build cache participates in the same selection model and always asks for confirmation. Docker images, containers, and volumes remain inspection-only. Docker inspection runs in the background with a 60-second limit. The TUI shows “Checking Docker storage…” while you continue browsing and deleting filesystem caches; if the inspection times out, press r to retry.

After a successful TUI scan, CacheFerret keeps a small private snapshot of known cache paths. Later launches show those paths immediately with approximate prior sizes while fresh measurements run in the background; stale rows cannot be selected or deleted. Set CACHEFERRET_NO_CACHE=1 to disable this warm-start accelerator.

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)'

cacheferret docker --fields kind,reclaimable_bytes |
  jq '.items[] | select(.reclaimable_bytes > 1073741824)'

Safety model

  • Bare cacheferret opens the TUI on a terminal and emits a read-only JSON scan when piped. cacheferret scan never mutates the filesystem.
  • The TUI supports both focused and batch deletion: press Space to build a selection, then d; when nothing is selected, d acts on the focused cache.
  • Measured caches can be selected and deleted while the rest of the scan runs. Pressing d uses the displayed size and age without repeating the tree walk. A risky batch gets one confirmation, and every target receives an identity and ownership check immediately before removal. Temporary trees requiring quiescence still receive a fingerprint check. Sizes remain scan-time estimates.
  • clean defaults to project caches; shared global caches require an explicit --scope global or --scope all.
  • The batch clean command protects caches modified in the last seven days unless --include-recent is passed. Change the window with --protect-days.
  • A non-interactive clean refuses to run without --yes and exits with the declared confirmation_required error.
  • 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 individual Space selection 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-run follows the same discovery and eligibility policy without deleting anything, and lists every selected path with its apparent size, allocated-block estimate, and restore requirements.
  • Docker storage is inspected through a bounded native command. Only ordinary build cache is selectable. Cleanup refreshes the estimate before confirmation and again before mutation, then runs exactly docker builder prune --force. CacheFerret never adds --all, never runs docker system prune, and never prunes images, containers, or volumes.

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.

Docker-managed storage is reported separately using Docker's native total and reclaimable estimates. These values are not filesystem-path measurements and are never folded into apparent, allocated, or observed-free-space totals.

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, and each installed rustup toolchain that is not the default, an override or RUSTUP_TOOLCHAIN (removed with rustup toolchain uninstall)
Python virtualenvs, bytecode, pytest, mypy, Ruff, tox, nox pip, uv, and pre-commit/prek
JavaScript node_modules npm, pnpm, Bun, Deno, and Playwright
Go — compiler and module caches
JVM/Android Gradle output and project cache, Maven target/ Gradle and Plugin Verifier; 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
Xcode — iOS, watchOS, tvOS, and visionOS DeviceSupport symbols, one entry per device and OS build; shut-down simulator devices that have installed apps (removed with xcrun simctl delete); simulator runtimes that simctl reports as deletable and no booted device uses (removed with xcrun simctl runtime delete)
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. cacheferret docker uses docker system df to report images, containers, volumes, and build cache as distinct native resources. The TUI shows the same daemon-scoped rows when global storage is in scope. Ordinary build cache alone can be selected and pruned; every prune gets a fresh preview and explicit confirmation. The bounded adapter contract and native cleanup opportunities for other package managers are documented in docs/native-cleanup.md.

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, exact Go build-cache metadata, and Xcode DerivedData structures are cleanable. Valid CACHEDIR.TAG roots nested inside any owned temporary tree are measured and protected by their own activity, independently of the parent; they take precedence in that scan to avoid double-counting their bytes. Large workspaces without a recognized nested cache are reported as scan-only diagnostic findings. Global cleanup remains opt-in, and recent cache 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 docker Inspect Docker storage with pagination and field controls
cacheferret docker clean Preview or confirm bounded ordinary build-cache pruning
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 json and automatic JSON when piped;
  • data on stdout and diagnostics on stderr;
  • structured error envelopes as the last stderr line in JSON mode;
  • offline schema introspection with effects, cardinality, pagination, output fields, confirmation gates, and stable exit codes;
  • offset pagination and --fields for unbounded scan and Docker results;
  • honest read_only and idempotent effect declarations.
cacheferret schema
cacheferret schema clean
cacheferret schema docker
cacheferret schema docker 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
7 native_unavailable A native tool, daemon, or operation is unavailable; retryable
8 native_protocol Native output could not be interpreted safely

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

Metadata

Release files for cacheferret 0.5.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cacheferret 0.5.4
File Size Uploaded Provenance Actions
cacheferret-0.5.4.tar.gz 1.7 MB Without provenance Details for cacheferret-0.5.4.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for cacheferret 0.5.4
File Actions
cacheferret-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details for cacheferret-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
cacheferret-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details for cacheferret-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
cacheferret-0.5.4-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for cacheferret-0.5.4-py3-none-macosx_11_0_arm64.whl
cacheferret-0.5.4-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details for cacheferret-0.5.4-py3-none-macosx_10_12_x86_64.whl

Total release size: 6.3 MB

Release files / cacheferret-0.5.4.tar.gz

Download URL cacheferret-0.5.4.tar.gz
Size 1.7 MB
Tags Source
SHA-256 checksum
How to use checksums
9c1f0f59e9ea5855c0f1d0f20cb953334c4465e4b764d3943ccc254c2b11f6f9
BLAKE2b-256 checksum
How to use checksums
2a4f131b3f33c7a4b11f8ec2b0dc730dae59eb2f6e0f5bd1b56263d63d826075
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / cacheferret-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL cacheferret-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.2 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
f029cf5429e20918084e1b83cca7a9473d120bcd99234648ebf56787be8a6cbe
BLAKE2b-256 checksum
How to use checksums
6863b7ae444e4f72f74369a348d26f6df330605389567af42c7cc92af89c209a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / cacheferret-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL cacheferret-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.1 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
19a438d8fdc6510f05cd1851a52e50bbd1dc6835f78dc95cd47a1a7a38c31e68
BLAKE2b-256 checksum
How to use checksums
8805a423a8d31441d107c2cf5997343b13ea3848f01b9d007f24123cdd605ec4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / cacheferret-0.5.4-py3-none-macosx_11_0_arm64.whl

Download URL cacheferret-0.5.4-py3-none-macosx_11_0_arm64.whl
Size 1.1 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
4d0f1f6b9c08cba09f9b6dfa2908dd0b81f63828cc3c122339a1bdd2fdfff005
BLAKE2b-256 checksum
How to use checksums
202f7d0601395b2f0b956b454cd490b97b199b12d23d048717802bb68d26c7f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Release files / cacheferret-0.5.4-py3-none-macosx_10_12_x86_64.whl

Download URL cacheferret-0.5.4-py3-none-macosx_10_12_x86_64.whl
Size 1.2 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
5fc3a97da21dd85d72ace2c32af30d1b24ba973e9b2a6709709048a45e28373d
BLAKE2b-256 checksum
How to use checksums
c57744959e5138bca04ea3697b4bd196b24a343b72d3dc1d4832556e932b3aa1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.15.0

Security for cacheferret 0.5.4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page