Inspecting and cleaning the Zig build cache
On this page 5
Zig writes all build output into two repository-local directories:
| Path | Contents |
|---|---|
.zig-cache/ | compiled objects (o/), scratch (tmp/), hashes (h/, z/) |
zig-out/ | installed artifacts (zig build install step outputs) |
Everything in both directories is reproducible — deleting them only forces the next build to recompile. Neither ever contains source or user-owned files.
Why it grows without bound
Each distinct build configuration produces a distinct cache key and a fresh copy of the artifact. Target, optimization, sanitizer, and source changes legitimately produce new artifacts. Test-name filters are runtime selectors, so commands such as
zig build test -Dtest-filter=vm # then ...=jit, ...=compiler, ...
reuse the same linked root test binary. Historical compile-time filtering could leave dozens of multi-hundred-MB artifacts behind; the runtime runner removes that source of cache growth. Clearing the reproducible cache remains safe when artifacts from genuinely different build configurations accumulate.
Use the small production-module roots for repeated focused work:
zig build test-jit -Dtest-filter='integer provenance'
zig build test-vm -Dtest-filter='numeric loop'
zig build test-concurrency -Dtest-filter='atomic increments'
They use the same target, optimization mode, ThreadSanitizer option, external
dependencies, and production source modules as zig build test, but do not
link the unrelated C-API/corpus tests. test-jit is a low-level root.
The VM/concurrency steps are small semantic executables because importing the
production interpreter through zig test recursively discovers the entire
inline integration suite; their filter is a runtime selector, so distinct VM or
concurrency filters reuse one linked artifact. Run zig build test once after a
batch as the authoritative full-suite gate.
Measured focused-build bound
On July 16, 2026, Zig 0.17.0-dev.956+2dca73595 on an Apple M3 Pro produced
the following repository-local cache growth from a fully cold prune:
| Invocations | Mode | Final .zig-cache | Documented bound |
|---|---|---|---|
4 distinct test-jit filters + 3 distinct test-vm filters + 3 distinct test-concurrency filters | Debug | 121 MiB | at most 256 MiB |
The four JIT filters were Tier claims, native entry, integer provenance,
and guarded unsigned. The VM filters were numeric loop, packed array, and
property loop; the concurrency filters were atomic increments, distinct property, and join chain. All ten selected and passed real cases. The cache
contained one 55 MiB production semantic executable, four roughly 5–13 MiB JIT
test artifacts, and 27 MiB of Zig metadata—rather than ten monolithic root test
images. Repeat this measurement after materially changing the focused roots;
Debug is the development-loop bound, while ReleaseFast/full-suite validation is
batched separately.
Inspect
home-tool run tools/zig-cache-tool.ts report # sizes, per-subdir breakdown,
# largest o/ artifacts, reclaimable total
Clean
home-tool run tools/zig-cache-tool.ts prune --dry-run # preview removal
home-tool run tools/zig-cache-tool.ts prune # remove caches
prune removes the repository-local cache as one coherent unit. Zig 0.17's
c/, h/, and z/ metadata retains references to compiled o/ artifacts, so
keeping that metadata while deleting only the apparent bulk can make the next
build fail with CacheCheckFailed. A fully cold cache is both reproducible and
reliable.
Safety
The tool is deliberately conservative and is the recommended way to clean the cache:
- It accepts no path arguments — both targets are fixed repository-relative
directories (
.zig-cacheandzig-out), so there is no way to point it at anything else. - Before each removal it resolves the target parent and refuses to proceed
unless the fixed target is
<repo>/.zig-cacheor<repo>/zig-out.rmdoes not traverse a final-component symlink, so a symlinked cache is unlinked rather than deleting its outside target. - It locates the repository from its own location via
git rev-parse, so it never acts on an unrelated directory even if run from elsewhere.
The manual equivalent is rm -rf .zig-cache zig-out from the repo root, but the
tool adds reporting and the outside-the-repo guard.