Flintstack › Project summary
A build cache that sits in front of your compiler
Flintstack keeps compiler output in a content-addressed store and hands it back when the same inputs show up again - on the same machine, or on any other machine that can reach the shared store. One static binary, one config file, no scheduler.
Quick start
Three commands, under a minute on a box that already has a toolchain:
# 1. unpack the static binary (11 MB, no runtime deps)
tar -xf flintstack-0.11.3-linux-x86_64.tar.zst -C /usr/local
# 2. start the daemon with its store on a fast disk
flintd --root /var/lib/flint
# 3. put the wrapper in front of the compiler
CC="flint wrap -- cc" CXX="flint wrap -- c++" make -j8
The second build of the same tree is the interesting one. Ask the daemon how it went:
$ flint stats
entries 18402
store 21.4 GiB / 80 GiB
hits 94.1 % (rolling 7 days)
misses 1087
evicted 312 (lru)
uptime 11d 4h
No daemon, no cache. The wrapper talks to flintd over
a unix socket at /run/flint/flintd.sock. If nothing is listening, flint
wrap execs the real compiler and returns its exit status unchanged, so a dead cache
never breaks a build - it only makes it slow.
What it does
For every compiler invocation the wrapper builds a cache key out of four things: the toolchain identity, the normalized argument vector, the digests of every input file after preprocessing, and the values of a small allowlist of environment variables. Those are hashed with SHA-256, and the first 128 bits of that digest name the entry.
On a hit, the daemon writes the stored object to the output path and the compiler is never started. On a miss, the compiler runs, the result is captured, and the entry is stored under the key that was computed before the run - so the miss costs one extra stat of each input, not a second compile.
Three storage backends can be stacked, nearest first:
| Backend | What it is | Typical place |
|---|---|---|
| fs | a directory on local disk | always on, the first tier |
| objs | object storage over signed HTTP | shared between CI runners |
| peer | another flintd over TCP port 7914 | a cache box on the same rack |
What it is not
- Not a build system. It has no dependency graph, no targets and no scheduler; your existing tool keeps deciding what to build and in what order.
- Not a distributed compiler. Work is never farmed out to other machines - only results are shared.
- Not a package registry. Entries are keyed by inputs, not by name and version, and they expire.
- Not a sandbox. If a build reads a file nobody declared, Flintstack will happily cache the wrong answer. That is the single sharpest edge in the whole design, and the design notes are blunt about it.
- Not portable to Windows. The code assumes POSIX file semantics in places where the fix would be a rewrite rather than a port.
Numbers
Measured on a corpus of 2310 compile targets: 708 s with an empty store, 69 s with a full one. The full method, the incremental case and the honest caveats live on the benchmark page - including the part where the shared backend adds latency instead of removing it.
Where to go next
- Install - tarball with checksums, or build from source.
- CLI reference - every command and flag, with exit codes.
- Configuration - the
flint.tomlkeys and defaults. - Security - tokens, mTLS and what the threat model excludes.
- FAQ - the questions that arrive by mail most often.
Patches go to dev@flintstack.dev as plain
git format-patch output. The source tree is self-hosted:
git clone https://code.flintstack.dev/flint.git
Last updated: 2026-09-29