Kache: a content-addressed Rust and C/C++ cache that spends hardlinks instead of disk
Zero-copy, content-addressed Rust build cache for Rust, C/C++ and more. No copies, no wasted disk — just hardlinks locally and S3 for sharing.
At a glance
- What is it?
- Kache is a local-first compiler cache from Kunobi that stores build outputs by content and reuses them across worktrees. The design bet is zero-copy: hardlinks and reflinks locally, S3-compatible or filesystem remotes for sharing.
- Who is it for?
- Adopt Kache if you keep several worktrees of the same Rust or C/C++ repository on one machine, or if CI restores large target directories and you want to stop paying for duplicate bytes. Do not adopt it if your builds are dominated by unsupported invocations, if you need a public cache service rather than a bucket you run, or if you cannot accept a compiler wrapper in the build path.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Kache targets: the same bytes, copied again and again
A compiler cache usually earns its keep by skipping work. Kache's README frames the benefit differently: it is about what the cache leaves on disk. The repository's own storage chart compares a second Firefox worktree on APFS, where Kache adds about 3 GB of new data by reflinking the other 13.5 GB, against sccache, which the README says writes an independent copy of roughly 16.7 GB. Those numbers come from a Firefox 151 benchmark run with Kache 0.7.0 on macOS/APFS, and the README points to a separate methodology page rather than presenting them as universal.
The audience is narrow but real. If you keep multiple git worktrees of one large Rust repository, or you check out a revision twice to compare behaviour, each worktree normally gets its own target directory and its own copy of every artifact. The same applies to C and C++ trees that rebuild object files into per-build directories. Kache's content-addressed store is meant to make the second copy nearly free, because the store already holds the bytes and can link to them instead of writing them out again.
That framing also sets the bar. A cache that saves disk but misses often is worse than no cache, so the project ships kache why-miss, kache stats and kache monitor to make hit and miss behaviour inspectable rather than assumed.
How the content-addressed store and the wrapper fit together
Kache sits between the build system and the compiler. For Rust, it is wired in as a rustc wrapper, either by setting RUSTC_WRAPPER=kache directly or by letting kache init write the setting into Cargo's configuration. For C and C++, the mechanism differs: on Unix you install compiler-name shims, put that directory first in PATH, and tools that invoke gcc or g++ by name pass through Kache without any CC= edit. The README notes that Kache inspects the real compiler invocation and that unsupported or unsafe invocations pass through untouched, which is the honest way to handle a wrapper that cannot understand every flag combination.
Outputs land in a content-addressed store, with garbage collection built in. The Cargo.toml lists blake3 as a dependency, and the crate keywords include blake3 and rustc-wrapper, so content addressing by hash is the store's organising principle rather than a marketing phrase. The workspace is split into crates for the core, format, filesystem, store and service layers, which suggests the store and the daemon are separable pieces rather than one monolith.
The zero-copy claim is about how entries are materialised into a target directory. Locally the store links rather than copies. The README's worktree diagram describes four Firefox worktrees sharing cached build outputs through reflinks, and the storage chart is explicitly about reflinking on APFS. Reflinks are a filesystem feature, so the size of the win depends on where the store lives relative to the target directory; on a filesystem without reflink support the fallback is presumably a hardlink or a copy, and the README does not spell out that fallback behaviour.
For sharing, Kache supports S3-compatible remotes (the README names AWS S3, MinIO and Cloudflare R2) and filesystem remotes for shared disks and CI volumes. The v0.17.0 release notes mention volume shards, and v0.19.0 is titled bounded memory for remote restores, which is a useful signal: pulling large entries back from a remote is a memory-sensitive path the project has had to tune.
Installing Kache and getting a first cache hit
The README's install path is Cargo. Installing the binary and letting init inspect the proposed configuration before applying it is the whole setup:
cargo install kache
kache init --check # print the proposed changes
kache init # apply themThe README states that kache init sets rustc-wrapper in Cargo's config and, on Unix, adds the [env] keys for build-script C and C++. Your existing cargo commands do not change. If you want persistent Cargo configuration without an OS service, the README offers kache init --no-service.
To see reuse rather than trust it, build the same revision in two temporary worktrees. Each gets its own target directory, so your existing build outputs stay in place, and the report is where you check hits and investigate misses:
kache monitor
kache stats
kache doctorkache monitor is the live view of build and cache activity, kache stats is the non-interactive summary, and kache doctor runs setup and integrity checks. When something you expected to hit does not, kache why-miss <crate> explains the latest miss for that crate.
For C and C++, the README's route is shims rather than an environment variable. Install the farm and put it first on PATH:
kache install-shims
export PATH="$HOME/.local/lib/kache/shims:$PATH"The README notes that kache init can create the user farm but does not change PATH, that makepkg users should put the same assignment in ~/.makepkg.conf, and that names already on PATH can be wrapped with kache install-shims --from-path.
Remote storage is configured in TOML, either through kache config or by editing the file. A minimal S3-compatible remote, as given in the README:
[cache.remote]
type = "s3"
bucket = "my-build-cache"
region = "us-east-1"Credentials come from the standard AWS environment variables or credential chain. The default local cache locations are $XDG_CACHE_HOME/kache or ~/.cache/kache on Linux, ~/Library/Caches/kache on macOS, and %LOCALAPPDATA%\kache on Windows. For CI, the official action is kunobi-ninja/kache-action@v1, used before a normal cargo build --locked.
Where Kache is the wrong tool
The README's own support table is the first boundary. Rust libraries and build scripts are supported, C and C++ object files are supported, but Rust executables are supported only on Linux and macOS and are disabled by default on Windows. If your workload is Windows Rust binaries, the cache is not covering you out of the box.
The second boundary is the wrapper itself. Kache inspects compiler invocations and passes through anything unsupported or unsafe. That is the correct design, but it means a build system that generates unusual command lines, or a toolchain that does not go through gcc/g++/rustc by name, will silently bypass the cache. Silent bypass is the failure mode to watch for: builds still succeed, and the only evidence is a lower hit rate in kache stats or a kache why-miss explanation.
Third, the zero-copy story is filesystem-dependent. Reflinks are the mechanism the README highlights, and the benchmark that supports the disk claim is explicitly APFS. On a filesystem without reflink support, or when the store and the target directory live on different volumes, the linking advantage shrinks. The README does not document what happens in that case, so it is a question to settle on your own hardware before you plan around the disk savings.
Fourth, Kache is a cache, not a hermetic build system. It does not make a non-reproducible build reproducible. If your cache keys are wrong because the build depends on something Kache cannot see, the cache will confidently return the wrong artifact. The project's answer to this is introspection (why-miss, stats, doctor) rather than a guarantee, and that is a trade-off worth naming.
Finally, the remote is a bucket or a shared filesystem that you run. There is no hosted service in the README. Teams that want a managed cache without operating storage should look elsewhere first.
Kache against sccache, and against doing nothing
The README links a dedicated comparison page, so the project invites the sccache question. The difference the README draws is in storage behaviour rather than in which compiler invocations are cached: the Firefox worktree chart contrasts Kache reflinking existing data with sccache writing an independent copy for the second worktree. That is a claim about disk, not about compile time, and the README points to a measurements page rather than asserting a speed win in the chart itself.
The other alternative is no cache at all. For a single small crate built once, Kache adds a wrapper, a store, potentially a background service and some configuration, and returns very little. The calculus changes when the same dependency graph is rebuilt across several worktrees or when CI restores a target directory from scratch on every run. Those are the cases the design is aimed at.
There is also a middle option the README itself describes: a trial without persistent Cargo configuration, which enables the Rust wrapper only. That is a sensible way to measure whether the Rust side alone justifies the setup before you commit to the C/C++ shim farm and remote storage.
Maintenance, releases and the Apache-2.0 licence
The repository is not archived and the last push was on 2026-09-09, so it is current. The release cadence visible in the repository is fast: v0.17.0 added volume shards, C/C++ cache support and predicted rustc keys on 2026-09-06, v0.18.0 added per-build cache miss understanding on 2026-09-07, and v0.19.0 addressed bounded memory for remote restores on 2026-09-09. Three minor releases in four days is a project moving quickly, which cuts both ways: fixes arrive fast, and the surface you configure may shift between minor versions. Note that Cargo.toml declares version 0.22.0 while the newest release listed is v0.19.0, so the manifest is ahead of the release list.
The repository also carries unusually heavy verification infrastructure for a cache: a scheduled benchmark workflow that the README says builds Firefox, LLVM, Substrate, SurrealDB, Lance, OpenDAL and eza, compares Firefox against sccache, exercises Firefox on Windows, and measures how much of a Firefox build survives a source update. The README is careful about how to read it, stating that timing or hit-rate numbers should be treated as evidence only when the individual job succeeds and its benchmark verdict is ok. That is a more disciplined framing than most projects offer.
Licensing is Apache-2.0, declared in Cargo.toml and present as a LICENSE file at the repository root. Apache-2.0 is permissive and includes an explicit patent grant. It is not legal advice to say that Apache-2.0 is generally compatible with commercial use, but if you redistribute Kache or bundle it into a product, read the NOTICE and attribution requirements yourself. The README does not discuss licence implications for the remotes you configure, which are your own storage accounts.
Editorial conclusion
Adopt Kache if you keep several worktrees of the same Rust or C/C++ repository on one machine, or if CI restores large target directories and you want to stop paying for duplicate bytes. Do not adopt it if your builds are dominated by unsupported invocations, if you need a public cache service rather than a bucket you run, or if you cannot accept a compiler wrapper in the build path. Before rolling it out, run kache doctor on one machine, confirm kache init --check prints the changes you expect, and verify with kache why-miss why a crate you expected to hit actually missed.
Frequently asked questions
What is Kache and what does it cache?
Kache is a local-first compiler cache for Rust and C/C++. According to the README, it caches Rust libraries and build scripts, Rust executables on Linux and macOS, and C and C++ object files, storing outputs in a content-addressed local store with optional S3-compatible or filesystem remotes.
How do I install Kache?
The README gives cargo install kache, followed by kache init --check to print the proposed changes and kache init to apply them. On Unix, init also adds the environment keys for build-script C and C++, and kache init --no-service skips the OS service.
Does Kache work with C and C++ builds like Make and CMake?
Yes, via compiler-name shims. The README states that kache install-shims installs a shim directory that you put first in PATH, after which Make, CMake, autotools and Arch PKGBUILDs calling gcc by name go through Kache with no CC= edit.
Where does Kache store its local cache?
The README lists $XDG_CACHE_HOME/kache or ~/.cache/kache on Linux, ~/Library/Caches/kache on macOS, and %LOCALAPPDATA%\kache on Windows. You can open the configuration editor with kache config or edit the TOML file directly.
How does Kache compare to sccache?
The README links a dedicated comparison page and a Firefox worktree storage chart, where Kache reflinks existing outputs while sccache writes an independent copy. The chart is about disk usage rather than compile time, and the README points to a separate methodology page for the measurements.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kunobi-ninja-kache)