Quick start
The fastest path is kache init. It edits ~/.cargo/config.toml to set rustc-wrapper = "kache", installs the background daemon as a login service, and starts it. The whole flow takes a few seconds and is idempotent — re-run it any time to repair configuration.
# interactive setup
kache init
# or accept all defaults non-interactively
kache init -y
# skip the login service if you'd rather start the daemon manually
kache init --no-service
# check what init would do without changing anything
kache init --check
After kache init, your next cargo build is already cached. The first run is a normal cold compile; the second run restores everything from kache's store with zero-copy reflinks (copy-on-write) where the filesystem supports it, and hardlink or copy otherwise.

Verify the setup
kache doctor
doctor checks for a working RUSTC_WRAPPER, conflicting wrappers (e.g. sccache), config file problems, and daemon connectivity. Add --fix to apply automatic repairs. For store integrity, --verify walks the store and checks entries, blobs, and metadata; add --checksums to also recompute and verify blob content hashes (slower); --repair removes corrupted entries.
Manual setup (without kache init)
If you'd rather wire things up yourself:
Set the wrapper for your current shell session
export RUSTC_WRAPPER=kacheOr persist it in ~/.cargo/config.toml so it applies to every project:
[build]
rustc-wrapper = "kache"The ~/.cargo/config.toml approach is more convenient for daily use. The env var is handy for CI or when you want to test kache on a single project without changing global config.
Run a build
cargo buildThe first build runs normally — kache compiles each crate and stores the result. You'll see normal cargo output.
Run the build again
cargo clean && cargo buildThis time, kache restores every crate from the cache with zero-copy reflinks (hardlink or copy where the filesystem has no copy-on-write). Cargo should complete in seconds for a project with no source changes.
Open the monitor
kache monitorThe TUI monitor opens and shows the Build tab with the events from the last run — each crate listed as a local hit or miss with timing. Press q to quit. (Running bare kache prints help; use kache monitor to open the dashboard.)
How to tell it's working
kache can print a one-line summary to stderr per crate, off by default. Enable it with KACHE_PROGRESS=1 (or hits) to show hits, or KACHE_PROGRESS=verbose (or all) to also show dups and misses:
[kache] serde: local hit (2ms, 1.2 MB)
[kache] tokio: local hit (3ms, 4.8 MB)
[kache] myapp: miss (1.4s, 892 KB)
The miss line only appears at KACHE_PROGRESS=verbose; at KACHE_PROGRESS=1/hits only hit lines are shown. For a live view, open the monitor instead with kache monitor.
Verbose progress also prints still compiling heartbeats for misses that outlive the configured heartbeat cadence. They stay off by default because Cargo caches compiler-wrapper stderr and can replay old progress on later builds.
After upgrading from kache 0.12, already-cached heartbeat lines can keep replaying until the affected crates rebuild. Clean the project's Cargo target directory if they must be removed immediately.
You can also check the cache state directly:
kache list # all cached crates, sorted by name
kache list serde # details for a specific crate
kache stats # one-shot summary (no UI)
What kache does not cache
On Linux, kache caches user-facing executables (bin crates and --test harnesses) by default: DWARF lives inside the binary, so a restored executable debugs exactly like a freshly linked one. On macOS and Windows it skips them by default, because their debug info is referenced from outside the binary (macOS N_OSO records point at per-build object files; a Windows .exe records its .pdb path), so a restored binary would lose source-level debugging — see #319. Dynamic libraries (dylib, cdylib) and proc-macros stay cached everywhere regardless. Override either way with KACHE_CACHE_EXECUTABLES=1/=0 or cache_executables in the config file.
Incremental compilation is automatically disabled when kache is active — kache strips the -C incremental=... flag from each rustc invocation (setting CARGO_INCREMENTAL=0 would be too late, since cargo injects the flag before the wrapper runs). kache's artifact caching makes incremental redundant, and on macOS, APFS-related corruption can occur when both are active simultaneously.
C/C++ object compiles
kache can also wrap C/C++ compilers for local object-compile caching:
export CC="kache cc"
export CXX="kache c++"
This is separate from RUSTC_WRAPPER: supported single-source -c compiles are cached, while link steps and unmodeled compiler shapes pass through. See C/C++ caching.
Disabling kache temporarily
KACHE_DISABLED=1 cargo build
Even when disabled, kache strips incremental flags to avoid the APFS issue on macOS.