A high-performance local compiler cache daemon
Project description
zccache
A blazing fast compiler cache for C/C++ and Rust
Inspired by sccache, but optimized for local-first use with aggressive file metadata caching and filesystem watching.
Quick Install
curl -LsSf https://github.com/zackees/zccache/releases/latest/download/install.sh | sh
powershell -ExecutionPolicy Bypass -c "irm https://github.com/zackees/zccache/releases/latest/download/install.ps1 | iex"
Verify:
zccache --version
Performance
The benchmark images are generated from the latest scheduled run and replace
hand-maintained text stats. Full results, rendered HTML, and machine-readable
JSON are published in the
benchmark-stats branch
and at zackees.github.io/zccache. Run the
same suite locally with ./perf.
Why is zccache so much faster on warm hits?
The difference comes from architecture, not better caching:
| sccache | zccache | |
|---|---|---|
| IPC model | Subprocess per invocation (fork + exec + connect) | Persistent daemon, single IPC message per compile |
| Cache lookup | Client hashes inputs, sends to server, server checks disk | Daemon has inputs in memory (file watcher + metadata cache) |
| On hit | Server reads artifact from disk, sends back via IPC | Daemon hardlinks cached file to output path (1 syscall) |
| Multi-file | Compiles every file (no multi-file cache support) | Parallel per-file cache lookups, only misses go to the compiler |
| Per-hit cost | ~170ms (process spawn + hash + disk I/O + IPC) | ~1ms (in-memory lookup + hardlink) |
Architecture enhancements that make the difference:
- Filesystem watcher — a background
notifywatcher tracks file changes in real time, so the daemon already knows whether inputs are dirty before you even invoke a compile. No redundant stat/hash work on hit. - In-memory metadata cache — file sizes, mtimes, and content hashes live in a lock-free
DashMap. Cache key computation is a memory lookup, not disk I/O. - Single-roundtrip IPC — each compile is one length-prefixed bincode message over a Unix socket (or named pipe on Windows). No subprocess spawning, no repeated handshakes.
- Hardlink delivery — cache hits are served by hardlinking the cached artifact to the output path — a single syscall instead of reading + writing the file contents.
- Multi-file fast path — when a build system passes N source files in one invocation, zccache checks all N against the cache in parallel, serves hits immediately, and batches only the misses into a single compiler process.
Broader tool coverage — zccache supports modes that other compiler caches don't:
| Mode | Description |
|---|---|
| Multi-file compilation | clang++ -c a.cpp b.cpp c.cpp — per-file caching with parallel lookups |
| Response files | Nested .rsp files with hundreds of flags — fully expanded and cached |
| clang-tidy | Static analysis results cached and replayed |
| include-what-you-use | IWYU output cached per translation unit |
| Emscripten (emcc/em++) | WebAssembly compilation cached end-to-end |
| wasm-ld | WebAssembly linking cached |
| rustfmt | Formatting results cached |
| clippy | Lint results cached |
| Rust check & build | cargo check and cargo build with extern crate content hashing |
Link-Time Side Effects
Linker drivers sometimes create more than the named -o output. Windows and
MinGW toolchains may deploy runtime DLLs next to an executable, MSVC links may
emit PDB files, and Emscripten links may create .wasm, .map, or .js
sidecars. If a cache hit restored only the primary binary, those sibling files
could be missing even though the cached binary itself was correct.
For link invocations, zccache snapshots the output directory before running the
real linker, records sibling files created or changed by a successful link, and
stores them with the primary link artifact. Later cache hits restore the full
artifact set to the output directory, so tools such as clang-tool-chain runtime
deployment work without per-build-system post-link hooks.
Install
curl -LsSf https://github.com/zackees/zccache/releases/latest/download/install.sh | sh
powershell -ExecutionPolicy Bypass -c "irm https://github.com/zackees/zccache/releases/latest/download/install.ps1 | iex"
This installs the standalone native Rust binaries (zccache, zccache-daemon,
and zccache-fp) directly from GitHub Releases.
Default install locations:
- Linux/macOS user install:
~/.local/bin - Linux/macOS global install:
/usr/local/bin - Windows user install:
%USERPROFILE%\.local\bin - Windows global install:
%ProgramFiles%\zccache\bin
Global install examples:
curl -LsSf https://github.com/zackees/zccache/releases/latest/download/install.sh | sudo sh -s -- --global
powershell -ExecutionPolicy Bypass -c "$env:ZCCACHE_INSTALL_MODE='global'; irm https://github.com/zackees/zccache/releases/latest/download/install.ps1 | iex"
Each GitHub release also publishes standalone per-platform archives:
- Linux:
zccache-vX.Y.Z-x86_64-unknown-linux-musl.tar.gz,zccache-vX.Y.Z-aarch64-unknown-linux-musl.tar.gz - macOS:
zccache-vX.Y.Z-x86_64-apple-darwin.tar.gz,zccache-vX.Y.Z-aarch64-apple-darwin.tar.gz - Windows:
zccache-vX.Y.Z-x86_64-pc-windows-msvc.zip,zccache-vX.Y.Z-aarch64-pc-windows-msvc.zip
PyPI remains available if you prefer pip install zccache; those wheels also install
the native binaries directly onto your PATH. Pre-built wheels are available for:
| Platform | Architecture |
|---|---|
| Linux | x86_64, aarch64 |
| macOS | x86_64, Apple Silicon |
| Windows | x86_64 |
Verify the install:
zccache --version
Rust crates are also published on crates.io. The main installable/runtime crates are:
zccache-clizccache-daemonzccache-corezccache-hashzccache-protocolzccache-fscachezccache-artifact
Use it as a drop-in replacement for sccache — just substitute zccache:
Integration Summary
RUSTC_WRAPPER=zccache cargo build
export CC="zccache clang"
export CXX="zccache clang++"
- Rust: set
RUSTC_WRAPPER=zccacheor addrustc-wrapper = "zccache"to.cargo/config.toml. - Bash: export
RUSTC_WRAPPER,CC, andCXXonce in your shell or CI environment. - Python: pass
RUSTC_WRAPPER,CC, andCXXthroughsubprocessenv when invokingcargoorclang. - First commands to check:
zccache --version,zccache start,zccache status.
Rust zccache integration
Use zccache as Cargo's compiler wrapper:
# one-off invocation
RUSTC_WRAPPER=zccache cargo build
RUSTC_WRAPPER=zccache cargo check
# optional: start the daemon explicitly
zccache start
Add to .cargo/config.toml for automatic use:
[build]
rustc-wrapper = "zccache"
Recommended project-local config:
[build]
rustc-wrapper = "zccache"
[env]
ZCCACHE_CACHE_DIR = { value = "/tmp/.zccache", force = false }
Supports --emit=metadata (cargo check), --emit=dep-info,metadata,link (cargo build),
extern crate content hashing, and cacheable crate types such as lib, rlib,
and staticlib. Proc-macro and binary crates are passed through without caching,
matching the usual sccache behavior.
Useful Rust workflow commands:
# inspect status
zccache status
# clear local cache
zccache clear
# validate wrapper is active
RUSTC_WRAPPER=zccache cargo clean
RUSTC_WRAPPER=zccache cargo check
zccache status
Cache root override
Set ZCCACHE_CACHE_DIR to isolate every zccache cache and state path under a
specific root:
export ZCCACHE_CACHE_DIR="$HOME/.soldr/cache/zccache"
zccache start
zccache status
When set and non-empty, the override is used for artifacts/, tmp/,
depgraph/, index.redb, crashes/, logs/, daemon lock files, download
daemon state, and the default daemon endpoint. Separate cache roots therefore
use separate daemon instances unless ZCCACHE_ENDPOINT is explicitly set.
Relative override paths are normalized against the current working directory.
Worktree cache sharing
zccache can share cache entries across sibling Git worktrees when the compile is equivalent. This targets multi-agent workflows where several checkouts of the same repository build the same Rust crates under different absolute paths. The daemon detects the enclosing Git root for each compile request, normalizes project-local source, dependency, cwd, and safe path arguments relative to that root, and writes cache hits back to the output paths requested by the current worktree.
For C/C++ projects, enable compiler path remapping so path-sensitive outputs
such as __FILE__, debug/source paths, and compatible link search paths can
share cache entries across equivalent Git roots:
export ZCCACHE_PATH_REMAP=auto
In auto mode, zccache discovers the enclosing Git root and internally adds
root/cwd -ffile-prefix-map=...=. arguments for GCC/Clang-family compile
misses. The original build files do not need to inject those flags themselves.
For link requests, zccache normalizes proven workspace-local input/search paths
for cache identity while preserving physical output and runtime-facing paths.
Set ZCCACHE_WORKTREE_ROOT when automatic Git-root detection is not reliable
or when a wrapper/test needs to define the normalization root explicitly:
export ZCCACHE_WORKTREE_ROOT="$PWD"
RUSTC_WRAPPER=zccache cargo build
For Rust projects, use the same path-remap directive:
export ZCCACHE_PATH_REMAP=auto
RUSTC_WRAPPER=zccache cargo build
In auto mode, zccache discovers the Git worktree root automatically on macOS,
Linux, and Windows, then adds a root-covering rustc --remap-path-prefix=...=.
when needed. Set ZCCACHE_WORKTREE_ROOT only as an advanced override for
non-Git checkouts or unusual build layouts where automatic root detection is
not reliable.
ZCCACHE_PATH_REMAP=auto tells zccache to apply compiler-specific path remaps
when it can prove they are safe, such as C/C++ -ffile-prefix-map, Rust
--remap-path-prefix, and platform equivalents. The goal is to make emitted
source paths, debug paths, and macro paths stable across equivalent worktrees
without requiring every build generator to spell those flags correctly. Physical
paths that build tools need for dependency tracking, such as Ninja depfiles,
must remain usable for the current checkout.
The override should point at the logical project root shared by equivalent worktrees. Paths under that root may be normalized for cache identity. Paths outside that root remain absolute unless zccache has a specific safe rule for them, so toolchain files, sysroots, generated files outside the checkout, and other external inputs do not accidentally become shared.
Worktree sharing is intentionally conservative. If zccache cannot prove that a compile is root-equivalent, it falls back to the existing path-specific cache key or records a miss. Diagnostics and session logs distinguish normal same-root hits from worktree-equivalent hits and report conservative reasons such as:
git_root_unavailable- no Git root and no explicitZCCACHE_WORKTREE_ROOT.path_outside_root- an input path is outside the detected/overridden root.path_sensitive_arg- flags such as--remap-path-prefix, debug path flags, or unknown absolute path-bearing options could affect emitted output.content_hash_mismatch- root-relative paths match but file contents differ.toolchain_mismatch- the compiler or relevant toolchain inputs differ.unsupported_language- the invocation is not covered by the worktree-aware normalization rules.
The supported worktree-equivalent paths are Rust rustc compilation, including
dependency artifacts used through --extern, and C/C++ compilation through the
existing depgraph context/artifact keys. The request-level fast path only serves
cross-root hits after validating the current worktree's recorded input hashes;
otherwise zccache falls back to the normal depgraph check or a path-specific
miss.
Sub-agent / parallel-worktree recipe
The typical multi-agent workflow runs one sub-agent per git worktree, all
checked out from the same repository under sibling paths. Without remap, every
worktree has different absolute compile inputs, so each agent pays full compile
cost even when source contents are identical. With ZCCACHE_PATH_REMAP=auto
exported once at the orchestrator level, every sub-agent's compile in every
worktree shares the same logical cache.
-
Create the worktrees. Anything
git worktree addproduces (or a siblinggit clone) works — zccache auto-detects each enclosing Git root:git worktree add ../agent-a -b agent-a main git worktree add ../agent-b -b agent-b main git worktree add ../agent-c -b agent-c main
-
Export the remap directive once, before launching the agents. Every sub-process inherits it; no per-worktree configuration is required:
export ZCCACHE_PATH_REMAP=auto
Then wire zccache into the build the same way you would for a single checkout. For Rust:
export RUSTC_WRAPPER=zccache
For C/C++, use the launcher pattern your build system already supports (Make and Ninja pick
CC/CXXup automatically):# Make / Ninja / plain shell export CC="zccache clang" export CXX="zccache clang++"
# CMake — set once, applies to every target set(CMAKE_C_COMPILER_LAUNCHER zccache) set(CMAKE_CXX_COMPILER_LAUNCHER zccache)
For Emscripten, swap in
emcc/em++:export CC="zccache emcc" export CXX="zccache em++"
The
ZCCACHE_PATH_REMAP=autoexport is what unlocks cross-worktree sharing for whichever language the agent compiles; the wrapper choice is just the normal single-checkout setup. -
Launch sub-agents in their own worktrees in parallel. The first agent to compile a unit populates the cache; the others get worktree-equivalent hits even though their absolute paths differ:
(cd ../agent-a && agent-runner ...) & (cd ../agent-b && agent-runner ...) & (cd ../agent-c && agent-runner ...) & wait
-
Verify it is working.
zccache statusreports worktree-equivalent hits separately from same-root hits, and per-session logs include the gate reason if a request fell back (path_outside_root,content_hash_mismatch,toolchain_mismatch, etc. — see the list above).
A few things worth knowing:
- One daemon, one cache. All worktrees share the same zccache daemon and
artifact store by default — do not set
ZCCACHE_CACHE_DIRper worktree, or you defeat the sharing. - Auto-detection requires a Git checkout. The daemon walks ancestors of the
compile cwd looking for
.git(file or directory), so plaingit cloneandgit worktree addcheckouts both work, but raw source trees (tarball extracts, archive payloads, custom build layouts with no.git) do not. For those, setZCCACHE_WORKTREE_ROOT="$PWD"(or any absolute path) to the logical project root you want cache keys normalized against. Without either a detected Git root or an explicit override,ZCCACHE_PATH_REMAP=autois a no-op and the session log reportsgit_root_unavailable. - User-supplied remap flags take precedence. If your build already passes
-ffile-prefix-map=<root>=...(C/C++/Emscripten) or--remap-path-prefix=<root>=...(Rust) where<root>is the auto-detected worktree root, zccache uses your flag as-is and does not inject a duplicate. The check is per-flag and per-path: only-ffile-prefix-map/--remap-path-prefixmatching the worktree root suppress auto-injection; related flags like-fdebug-prefix-map,-fmacro-prefix-map,-fcoverage-prefix-map, and-fprofile-prefix-mapdo not. If cwd differs from the detected root and you have not supplied a matching-ffile-prefix-map=<cwd>=., zccache may still inject one for that path. Auto-injected remaps are fallback remaps placed before user-supplied remaps, so a narrower overlapping user remap remains the later, winning rule. - Same-content guarantee. Cross-worktree hits validate content hashes for every input. If two worktrees have diverged on a file, the second compile misses and recompiles — the cache cannot be poisoned across siblings (the invariant fixed in #197).
- Measured win. The
perf_cpp_sibling_remap_warm/perf_rustc_sibling_remap_warmbenchmarks (introduced in #238) confirm warm-state hits across sibling worktrees run an order of magnitude faster than bare compiles and sccache even though sccache cannot share across sibling roots at all.
Strict path validation
Use --strict-paths or ZCCACHE_STRICT_PATHS to fail fast when compiler path
flags are spelled in ways that can confuse #pragma once on Windows.
zccache --strict-paths=absolute clang++ -c src/main.cpp -IC:/work/project/include
ZCCACHE_STRICT_PATHS=consistent ninja
Modes:
offdisables validation.consistentallows relative or absolute paths, but rejects mixed/and\separators within one path or across checked path flags in the same invocation.absoluterequires checked path flags to be forward-slash absolute paths with no/./or/../components.ZCCACHE_STRICT_PATHS=1maps to this mode.
Checked flags include -I, -isystem, -iquote, -idirafter, -include,
-include-pch, -imacros, -F, -iframework, -imsvc, and MSVC /I.
Response-file arguments are checked after expansion by the daemon.
Compiler child priority
Compiler and linker subprocesses run with ZCCACHE_COMPILE_PRIORITY=auto by
default. Auto mode keeps compiler children at normal priority while total CPU
usage is below 95%, then drops them to low priority when the machine is
saturated. Set the variable on the build command or in the daemon environment to
override it:
| Value | Behavior |
|---|---|
auto |
Default. Use normal below 95% CPU utilization and low at 95-100% utilization. |
low |
Lower compiler priority (nice +10 on Unix/macOS, BELOW_NORMAL_PRIORITY_CLASS on Windows). |
normal |
Preserve the inherited process priority for maximum throughput. |
idle |
More conservative background mode (nice +19 on Unix/macOS, IDLE_PRIORITY_CLASS on Windows). |
high |
Higher-priority mode for real-time benchmarking (nice -5 on Unix/macOS where permitted, HIGH_PRIORITY_CLASS on Windows). |
Unsupported priority changes fail soft with a daemon log message and do not
break compilation. Invalid values warn and fall back to low.
Bash integration
For shell-driven builds, export the wrapper once in your session or CI step:
export RUSTC_WRAPPER=zccache
export CC="zccache clang"
export CXX="zccache clang++"
zccache start
cargo build
ninja
If you want this active in interactive shells, add it to ~/.bashrc:
export RUSTC_WRAPPER=zccache
export PATH="$HOME/.local/bin:$PATH"
For per-build stats in Bash:
eval "$(zccache session-start --stats)"
cargo build
zccache session-end "$ZCCACHE_SESSION_ID"
Python integration
Python projects can use zccache when invoking Rust or C/C++ toolchains through
subprocess, build backends, or extension-module builds.
import os
import subprocess
env = os.environ.copy()
env["RUSTC_WRAPPER"] = "zccache"
env["CC"] = "zccache clang"
env["CXX"] = "zccache clang++"
subprocess.run(["cargo", "build", "--release"], check=True, env=env)
This is useful for:
setuptools-rustmaturinscikit-build-core- custom Python build/test harnesses that shell out to
cargo,clang, orclang++
Example with maturin:
RUSTC_WRAPPER=zccache maturin build
Example with Python driving cargo check:
subprocess.run(["cargo", "check"], check=True, env=env)
GitHub Actions
zccache provides a composite GitHub Action that replaces both mozilla-actions/sccache-action and Swatinem/rust-cache with a single action.
Minimal example
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.94.1
- uses: zackees/zccache@main
with:
shared-key: ${{ runner.os }}
- run: cargo build --release
- run: cargo test
# REQUIRED: always clean up at end of job
- if: always()
uses: zackees/zccache/action/cleanup@main
Multi-platform matrix
name: CI
on: [push, pull_request]
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-24.04, target: x86_64-unknown-linux-gnu }
- { os: ubuntu-24.04-arm, target: aarch64-unknown-linux-gnu }
- { os: macos-15, target: aarch64-apple-darwin }
- { os: macos-14, target: x86_64-apple-darwin }
- { os: windows-2025, target: x86_64-pc-windows-msvc }
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.94.1
targets: ${{ matrix.target }}
# One action replaces sccache + rust-cache
- uses: zackees/zccache@main
with:
shared-key: ${{ matrix.target }}
- run: cargo build --release --target ${{ matrix.target }}
- run: cargo test --target ${{ matrix.target }}
- if: always()
uses: zackees/zccache/action/cleanup@main
What it does
The action provides two default cache layers, plus an opt-in target snapshot layer
and zccache warm for near-instant subsequent builds:
| Layer | What | Replaces | Effect |
|---|---|---|---|
| Compilation cache | Per-unit .o/.rlib files via zccache daemon |
sccache | ~1ms per cache hit vs ~170ms for sccache |
| Cargo registry cache | ~/.cargo/registry/ + ~/.cargo/git/ |
Swatinem/rust-cache | Avoids re-downloading crates |
| Target snapshot cache | target/ tarball excluding incremental/ |
(new) | Cargo sees target outputs and fingerprints together |
zccache warm |
Backfills target/deps/ from compilation cache |
(new) | Restores missing artifacts before cargo runs |
On setup, the action installs zccache, then restores caches through the native
zccache gha-cache backend when the GitHub Actions cache runtime is available.
When that runtime is missing, it falls back to actions/cache. When
cache-target: true is set, it also extracts the target snapshot, runs
zccache warm to backfill cached .rlib/.rmeta files, and touches all
timestamps to a single consistent value.
On cleanup: stops daemon and saves the enabled caches. The native backend saves
the compilation cache, the cargo registry archive, and the optional target
snapshot without requiring manual cache steps in the workflow. When prefix
restore-fallback is enabled, the action still uses actions/cache for that
fallback path. Target snapshots are pruned and size-checked before save.
CI benchmark results
Measured on ubuntu-24.04 building zccache-core (14 crates):
| Scenario | Bare | sccache | zccache |
|---|---|---|---|
| 1st CI run (clean target) | 5,315ms | 3,261ms | 2,194ms |
| 2nd CI run (cached target) | 5,315ms | 3,261ms | ~200ms |
15x faster than sccache on subsequent CI runs. Zero recompilation — cargo sees all fingerprints as fresh and prints Finished immediately.
How it works:
- First run with
cache-target: true: cold build, populates zccache compilation cache and saves a bounded target snapshot. - Second run with
cache-target: true: restores the target snapshot, runszccache warmas a backfill, touches timestamps, thencargo buildfinishes without recompilation.
zccache warm reads the on-disk artifact index (no daemon needed) and filters by Cargo.lock — only restores artifacts matching crates in your lockfile. That is a speed optimization, not a full integrity-verification pass: warmed artifacts are trusted and Cargo is expected to reject or rebuild anything incompatible.
Inputs
| Input | Default | Description |
|---|---|---|
cache-cargo-registry |
true |
Cache cargo registry index + crate files + git deps |
cache-compilation |
true |
Cache compilation units via zccache daemon |
cache-target |
false |
Cache target snapshot + run zccache warm; opt in only for workflows where target snapshots are worth the disk budget |
target-snapshot-mode |
hot |
hot saves Cargo metadata plus target files read or modified during the job; full saves the pruned target tree |
target-snapshot-max-size |
2GiB |
Skip or fail target snapshot save when the pruned snapshot exceeds this size; use 0 for unlimited |
target-snapshot-too-large |
skip |
skip oversized target snapshots or fail cleanup |
target-prune-incremental |
true |
Remove target/**/incremental before creating a snapshot |
target-prune-build-script-out |
false |
Remove target/**/build/*/out before creating a snapshot |
compilation-restore-fallback |
true |
Allow prefix fallback for compilation cache restores |
target-restore-fallback |
false |
Allow prefix fallback for target snapshot restores |
target-dir |
target |
Path to the cargo target directory |
shared-key |
"" |
Extra key for matrix isolation (typically the target triple) |
zccache-version |
latest |
Version to install |
save-cache |
true |
Set false for PR builds (restore-only, saves cache budget) |
Restore policy
The action now treats the two cache layers differently:
- Compilation cache fallback stays enabled by default. That preserves fast incremental reuse across nearby commits while still letting zccache validate cache hits when
rustcactually runs. - Target snapshot fallback is disabled by default. Reusing stale Cargo fingerprints and build-script outputs across different source trees can make a PR merge ref look fresh when it is not.
- Target snapshots are disabled by default because Cargo does not garbage collect
target/. When enabled, the defaulttarget-snapshot-mode: hotsaves Cargo freshness metadata plus target files read or modified during the job instead of archiving the whole tree. Usetarget-snapshot-mode: fullonly for tightly scoped jobs where the target directory is known to stay bounded. - Target snapshot saves prune
target/**/incrementalby default, can optionally prunetarget/**/build/*/out, and skip saving when the pruned snapshot exceedstarget-snapshot-max-size.
If you want the old fastest-possible behavior for developer CI, opt back in explicitly:
- uses: zackees/zccache@main
with:
cache-target: true
compilation-restore-fallback: true
target-restore-fallback: true
If you want a more release-hardened setup, keep target snapshots disabled and prefer exact restores:
- uses: zackees/zccache@main
with:
compilation-restore-fallback: false
This project is optimized for developer speed, not full artifact attestation. zccache warm does not checksum every restored object on every run, and the action does not try to prove cache integrity before building. If you need that level of assurance, disable the speed-focused layers for that workflow.
Outputs
| Output | Description |
|---|---|
cache-hit-compilation |
Whether the zccache compilation cache was restored |
cache-hit-registry |
Whether the cargo registry cache was restored |
cache-hit-target |
Whether the target snapshot cache was restored |
Why two parts?
Composite GitHub Actions don't support post steps (automatic cleanup). The action is split into:
zackees/zccache— setup: install zccache, restore caches through the native GHA cache backend when available, optionally warm target, start daemon, setRUSTC_WRAPPERzackees/zccache/action/cleanup— teardown: print stats, stop daemon, prune and save enabled caches through the same backend
The cleanup action must be called with if: always() to ensure caches are saved even on failure.
Migrating from sccache + rust-cache
Before (two actions):
- uses: mozilla-actions/sccache-action@v0.0.9
- uses: Swatinem/rust-cache@v2
env:
SCCACHE_GHA_ENABLED: "true"
RUSTC_WRAPPER: sccache
After (one action):
- uses: zackees/zccache@main
with:
shared-key: ${{ matrix.target }}
# ... build steps ...
- if: always()
uses: zackees/zccache/action/cleanup@main
No env vars needed — the action sets RUSTC_WRAPPER=zccache automatically.
C/C++ build system integration (ninja, meson, cmake, make)
zccache is a drop-in compiler wrapper. Point your build system's compiler
at zccache <real-compiler> and it handles the rest:
# meson native file
[binaries]
c = ['zccache', '/usr/bin/clang']
cpp = ['zccache', '/usr/bin/clang++']
# CMake
set(CMAKE_C_COMPILER_LAUNCHER zccache)
set(CMAKE_CXX_COMPILER_LAUNCHER zccache)
The first build (cold cache) runs at near-bare speed. Subsequent rebuilds
(ninja -t clean && ninja, or touching source files) serve cached artifacts
via hardlinks in under a second.
Strict path validation: Set ZCCACHE_STRICT_PATHS or pass
--strict-paths=<off|consistent|absolute> before the compiler name to catch
non-normalized include paths before the real compiler runs:
ZCCACHE_STRICT_PATHS=consistent ninja
zccache --strict-paths=absolute clang++ -IC:/project/src -c main.cpp
consistent rejects checked path flags that mix separator styles within one
path or across the same invocation. absolute also requires path flags such as
-I, -isystem, -include, and -include-pch to be forward-slash absolute
paths without /./ or /../ segments. Violations exit non-zero with the
offending flag and full caller command.
Path remap auto mode: Planned C/C++ worktree sharing uses
ZCCACHE_PATH_REMAP=auto to let zccache inject and key compiler path remaps
internally for clang/gcc/emcc builds. This keeps Ninja, Meson, CMake, and Make
commands simple while allowing sibling checkouts to share artifacts when
compiler-visible source/debug paths are equivalent.
Single-roundtrip IPC: In drop-in mode, zccache sends a single
CompileEphemeral message that combines session creation, compilation, and
session teardown — eliminating 2 of 3 IPC roundtrips per invocation.
Session stats: Track hit rates per-build with --stats:
eval $(zccache session-start --stats --log build.log)
export ZCCACHE_SESSION_ID=...
# ... build runs ...
zccache session-stats $ZCCACHE_SESSION_ID # query mid-build
zccache session-end $ZCCACHE_SESSION_ID # final stats
Persistent cache: Artifacts are stored in ~/.zccache/artifacts/
and survive daemon restarts. No need to re-warm the cache after a reboot.
Compile journal (build replay): Every compile and link command is recorded
to ~/.zccache/logs/compile_journal.jsonl as a JSONL file with enough
detail to replay the entire build:
{"ts":"2026-03-17T10:30:00.123Z","outcome":"hit","compiler":"/usr/bin/clang++","args":["-c","foo.cpp","-o","foo.o"],"cwd":"/project/build","env":[["CC","clang"]],"exit_code":0,"session_id":"uuid","latency_ns":1234567}
Fields: ts (ISO 8601 UTC), outcome (hit/miss/error/link_hit/link_miss),
compiler (full path), args (full argument list), cwd, env (omitted when
inheriting daemon env), exit_code, session_id (null for ephemeral),
latency_ns (wall-clock nanoseconds). One JSON object per line — pipe through
jq to filter, or replay builds by extracting compiler + args + cwd.
Per-session compile journal: Pass --journal <path> to session-start to
write a dedicated JSONL log containing only the commands from that session.
The path must end in .jsonl:
result=$(zccache session-start --journal build.jsonl)
session_id=$(echo "$result" | jq -r .session_id)
export ZCCACHE_SESSION_ID=$session_id
# ... build runs ...
# Inspect this session's commands only (no noise from other sessions)
jq . build.jsonl
zccache session-end $session_id
The session journal uses the same JSONL schema as the global journal. Entries
are written to both the global and session journals simultaneously. The session
file handle is released when session-end is called.
Multi-file compilation (fast path)
When a build system passes multiple source files to a single compiler invocation
(e.g. gcc -c a.cpp b.cpp c.cpp -o ...), zccache treats this as a fast path:
- Each source file is checked against the cache in parallel.
- Cache hits are served immediately — their
.ofiles are written from the cache. - Remaining cache misses are batched into a single compiler process, preserving the compiler's own process-reuse and memory-sharing benefits.
- The outputs of the batched compilation are cached individually for future hits.
This hybrid approach means the first build populates the cache per-file, and subsequent builds serve as many files as possible from cache while still letting the compiler handle misses efficiently in bulk.
Recommendation: Configure your build system to pass multiple source files per compiler invocation whenever possible. This gives zccache the best opportunity to parallelize cache lookups and minimize compiler launches.
Concurrency
The daemon uses lock-free concurrent data structures (DashMap) for artifact and metadata lookups, so parallel compilation requests from multiple build workers never serialize on a global lock.
Status
Early development — architecture and scaffolding phase.
Goals
- Extremely fast on local machines (daemon keeps caches warm)
- Portable across Linux, macOS, and Windows
- Correct under heavy parallel compilation (no stale cache hits)
- Simple deployment (single binary)
Tool Compatibility
zccache works as a drop-in wrapper for these compilers and tools:
- Clang Toolchain: clang, clang-tidy, IWYU
- Emscripten / WebAssembly: emcc, wasm-ld
- Rust Toolchain: rustc, rustfmt, clippy
Architecture
See docs/ARCHITECTURE.md for the full system design.
Key components
| Crate | Purpose |
|---|---|
zccache-cli |
Command-line interface (zccache binary) — includes warm, cargo-registry, gha-cache subcommands |
zccache-daemon |
Daemon process (IPC server, orchestration) |
zccache-core |
Shared types, errors, config, path utilities |
zccache-protocol |
IPC message types and serialization |
zccache-ipc |
Transport layer (Unix sockets / named pipes) |
zccache-hash |
blake3 hashing and cache key computation |
zccache-fscache |
In-memory file metadata cache |
zccache-artifact |
Disk-backed artifact store with redb index |
zccache-watcher |
File watcher subsystem: daemon notify pipeline plus Rust-backed Python watcher bindings |
zccache-compiler |
Compiler detection and argument parsing |
zccache-gha |
GitHub Actions Cache API client |
zccache-test-support |
Test utilities and fixtures |
Building
cargo build --workspace
Testing
cargo test --workspace
Documentation
Watcher APIs
zccache exposes watcher-related APIs in three different places, depending on how you want to consume change detection:
- CLI:
zccache fp ...for daemon-backed fingerprint checks in scripts and CI - Python:
zccache.watcherfor cross-platform library-style file watching - Rust:
zccache-watcherfor the daemon-facing watcher pipeline primitives
CLI API
The CLI watcher entrypoint is the fingerprint API. It answers "should I rerun?" by consulting the daemon's in-memory watch state and cached file fingerprints.
zccache fp --cache-file .cache/headers.json check \
--root . \
--include '**/*.cpp' \
--include '**/*.h' \
--exclude build \
--exclude .git
Exit codes:
0: files changed, run the expensive step1: no changes detected, skip the step
After a successful or failed run, update the daemon's watch state:
zccache fp --cache-file .cache/headers.json mark-success
zccache fp --cache-file .cache/headers.json mark-failure
zccache fp --cache-file .cache/headers.json invalidate
The fingerprint API is the best fit for shell scripts, CI jobs, and build steps that only need a yes/no change answer rather than a stream of file events.
Python API
pip install zccache now exposes an importable zccache module in addition to
the native binaries. The Python surface is aimed at the same hot-path features
the CLI already exposes: watcher events, fingerprint decisions, daemon/session
control, downloads, and Arduino .ino conversion.
from zccache.client import ZcCacheClient
from zccache.fingerprint import FingerprintCache
from zccache.ino import convert_ino
from zccache.watcher import watch_files
client = ZcCacheClient()
client.start()
fp = FingerprintCache(".cache/watch.json")
decision = fp.check(
root=".",
include=["**/*.cpp", "**/*.hpp", "**/*.ino"],
exclude=["**/.build/**", "**/fastled_js/**"],
)
if decision.should_run:
convert_ino("Blink.ino", "build/Blink.ino.cpp")
fp.mark_success()
The watcher API remains polling- and callback-friendly, while the backend runs the filesystem scan loop in Rust and only crosses into Python when delivering events.
from zccache.watcher import watch_files
watcher = watch_files(
".",
include_folders=["src", "include"],
include_globs=["src/**/*.cpp", "include/**/*.h"],
exclude_globs=["build", "dist/**", ".git"],
debounce_seconds=0.2,
poll_interval=0.1,
)
event = watcher.poll(timeout=1.0)
if event is not None:
print(event.paths)
watcher.stop()
For explicit lifecycle control, use the class API:
from zccache.watcher import FileWatcher
watcher = FileWatcher(".", include_globs=["**/*.cpp"], autostart=False)
watcher.start()
event = watcher.poll(timeout=1.0)
watcher.stop()
watcher.resume()
watcher.stop()
Python watcher features:
include_foldersto narrow the scan rootsinclude_globsto include only matching filesexclude_globs/excluded_patternsto skip directories or filesdebounce_secondsto coalesce bursts of edits- optional
notification_predicateapplied at Python delivery time - callback API plus polling API
- explicit
start(),stop(),resume(), and context-manager support
Daemon/session control is also available without shelling out per call:
from zccache.client import ZcCacheClient
client = ZcCacheClient()
client.start()
session = client.session_start(cwd=".", track_stats=True)
stats = client.session_stats(session.session_id)
client.session_end(session.session_id)
And fingerprint state can be managed directly from Python:
from zccache.fingerprint import FingerprintCache
fp = FingerprintCache(".cache/lint.json", cache_type="two-layer")
decision = fp.check(root=".", include=["**/*.cpp"], exclude=["**/.build/**"])
if decision.should_run:
fp.mark_success()
Compatibility wrappers used by fastled-wasm are also available:
FileWatcherProcessDebouncedFileWatcherProcesswatch_filesFileWatcher
See crates/zccache-watcher/README.md for the full Python watcher surface.
Rust API
For Rust consumers, the public watcher crate is zccache-watcher.
It now exposes both the daemon-facing watcher pipeline and a library-style
polling watcher API:
-
PollingWatcherConfig -
PollingWatcher -
PollWatchBatch -
PollWatchObserver -
IgnoreFilterfor directory-name-based filtering -
NotifyWatcherfornotify-backed OS watch registration -
SettleBufferandSettledEventfor burst coalescing -
OverflowRecoveryfor overflow-driven rescan scheduling -
WatchEventandWatcherConfigfor event/config plumbing
Example:
use std::time::Duration;
use zccache_watcher::{PollingWatcher, PollingWatcherConfig};
let mut config = PollingWatcherConfig::new(".");
config.include_globs = vec!["**/*.cpp".to_string()];
config.poll_interval = Duration::from_millis(50);
config.debounce = Duration::from_millis(50);
let watcher = PollingWatcher::new(config)?;
watcher.start()?;
let batch = watcher.poll_timeout(Duration::from_secs(1))?;
watcher.stop()?;
Downloader APIs
zccache also exposes the dedicated download subsystem in three places:
- CLI:
zccache download ...on the main binary, plus the standalonezccache-downloadtool - Python:
zccache.downloader.DownloadApi - Rust:
zccache-download-clientfor the client API andzccache-downloadfor shared download types
The downloader daemon is separate from the compiler-cache daemon. It is meant for long-lived artifact downloads, deterministic cache paths, optional unarchiving, and attach/wait/status flows from multiple clients.
Downloader CLI
The main zccache binary includes a simple download subcommand:
zccache download \
https://example.com/toolchain.tar.zst \
--unarchive .cache/toolchain \
--sha256 0123456789abcdef \
--multipart-parts 8
That path blocks until the artifact is ready and prints the resolved cache path, SHA-256, and optional unarchive destination.
For daemon lifecycle control, attach/wait/status operations, JSON output, and explicit archive-format selection, use the standalone downloader CLI:
zccache-download daemon start
zccache-download fetch \
https://example.com/toolchain.tar.zst \
.cache/downloads/toolchain.tar.zst \
--expanded .cache/toolchain \
--archive-format tar.zst \
--max-connections 8
zccache-download exists \
https://example.com/toolchain.tar.zst \
.cache/downloads/toolchain.tar.zst
zccache-download --json daemon status
Additional standalone subcommands:
getto attach to a raw download handlewait,status, andcancelfor handle lifecycle operationsdaemon stopto shut the download daemon down explicitly
Python Downloader API
pip install zccache exposes the downloader as zccache.downloader.
from zccache.downloader import DownloadApi
api = DownloadApi()
api.start()
result = api.download(
source_url="https://example.com/toolchain.tar.zst",
destination=".cache/downloads/toolchain.tar.zst",
expanded=".cache/toolchain",
archive_format="tar.zst",
multipart_parts=8,
)
print(result.status, result.sha256, result.expanded_path)
state = api.exists(
source_url="https://example.com/toolchain.tar.zst",
destination=".cache/downloads/toolchain.tar.zst",
)
print(state.kind, state.reason)
If you need attach/wait/status semantics instead of a blocking fetch call, use
DownloadApi.attach(...) and operate on the returned DownloadHandle:
from zccache.downloader import DownloadApi
api = DownloadApi()
with api.attach(
source_url="https://example.com/toolchain.tar.zst",
destination=".cache/downloads/toolchain.tar.zst",
max_connections=8,
) as handle:
status = handle.wait(timeout_ms=1_000)
print(handle.download_id, status.phase, status.downloaded_bytes)
The Python downloader surface includes:
DownloadApi.start(),stop(), anddaemon_status()DownloadApi.download()/fetch()for blocking or non-blocking fetchesDownloadApi.exists()for cache-state checksDownloadApi.attach()plusDownloadHandle.status(),wait(), andcancel()
Rust Downloader API
For Rust code, use zccache-download-client as the entrypoint and
zccache-download for shared status and option types.
use std::path::PathBuf;
use zccache_download_client::{ArchiveFormat, DownloadClient, FetchRequest, WaitMode};
let client = DownloadClient::new(None);
client.start_daemon()?;
let mut request = FetchRequest::new(
"https://example.com/toolchain.tar.zst",
PathBuf::from(".cache/downloads/toolchain.tar.zst"),
);
request.destination_path_expanded = Some(PathBuf::from(".cache/toolchain"));
request.archive_format = ArchiveFormat::TarZst;
request.multipart_parts = Some(8);
request.wait_mode = WaitMode::Block;
let result = client.fetch(request)?;
println!("{:?} {} {}", result.status, result.sha256, result.cache_path.display());
For handle-based control, use DownloadClient::download(...):
use std::path::Path;
use zccache_download::DownloadOptions;
use zccache_download_client::DownloadClient;
let client = DownloadClient::new(None);
let mut handle = client.download(
"https://example.com/toolchain.tar.zst",
Path::new(".cache/downloads/toolchain.tar.zst"),
DownloadOptions {
force: false,
max_connections: Some(8),
min_segment_size: None,
},
)?;
let status = handle.wait(Some(1_000))?;
println!("{:?} {}", status.phase, status.downloaded_bytes);
The Rust downloader surface includes:
DownloadClient::start_daemon(),stop_daemon(), anddaemon_status()DownloadClient::fetch()andexists()withFetchRequestDownloadClient::download()returning aDownloadHandleArchiveFormat,FetchResult,FetchState,FetchStatus, andWaitModeDownloadOptions,DownloadStatus, andDownloadDaemonStatus
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zccache-1.4.7-py3-none-win_arm64.whl.
File metadata
- Download URL: zccache-1.4.7-py3-none-win_arm64.whl
- Upload date:
- Size: 10.4 MB
- Tags: Python 3, Windows ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
841bf1ff70506f63004fc970fecce3c045bbd519626c4069e7029f815e7f6f1c
|
|
| MD5 |
cde186aa6354e9373307ed18593f06d2
|
|
| BLAKE2b-256 |
775d3fd2bd99d9f7bb39d3ab5a897f758493312f49c912a93bbb2e0ce387cf19
|
Provenance
The following attestation bundles were made for zccache-1.4.7-py3-none-win_arm64.whl:
Publisher:
release-auto.yml on zackees/zccache
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zccache-1.4.7-py3-none-win_arm64.whl -
Subject digest:
841bf1ff70506f63004fc970fecce3c045bbd519626c4069e7029f815e7f6f1c - Sigstore transparency entry: 1537705913
- Sigstore integration time:
-
Permalink:
zackees/zccache@51aae3f0db96314fa65a95be230e60d5e508730d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zackees
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-auto.yml@51aae3f0db96314fa65a95be230e60d5e508730d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file zccache-1.4.7-py3-none-win_amd64.whl.
File metadata
- Download URL: zccache-1.4.7-py3-none-win_amd64.whl
- Upload date:
- Size: 11.2 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b44d5e5e8609c6b0f97ce4259c9661e6b80db1aee6a8a84b3aece931c5edb87
|
|
| MD5 |
59e403dbe97d79925d99d7fef20bb8f8
|
|
| BLAKE2b-256 |
e718d0a721f0358a96f67600ff5669b2b0ca645cac82fca46f3d748e813b29d5
|
Provenance
The following attestation bundles were made for zccache-1.4.7-py3-none-win_amd64.whl:
Publisher:
release-auto.yml on zackees/zccache
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zccache-1.4.7-py3-none-win_amd64.whl -
Subject digest:
3b44d5e5e8609c6b0f97ce4259c9661e6b80db1aee6a8a84b3aece931c5edb87 - Sigstore transparency entry: 1537705806
- Sigstore integration time:
-
Permalink:
zackees/zccache@51aae3f0db96314fa65a95be230e60d5e508730d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zackees
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-auto.yml@51aae3f0db96314fa65a95be230e60d5e508730d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file zccache-1.4.7-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: zccache-1.4.7-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 14.0 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2da88142bee5634e44e5c73ccda63cf8663274163daad5dcecb292e38d9fcf01
|
|
| MD5 |
e7e4f355de2355f185dc30eeefae5a25
|
|
| BLAKE2b-256 |
c930c800410511f0f470b62084949148fda02e6cc10a6c35614dbbecf871ee64
|
Provenance
The following attestation bundles were made for zccache-1.4.7-py3-none-manylinux_2_17_x86_64.whl:
Publisher:
release-auto.yml on zackees/zccache
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zccache-1.4.7-py3-none-manylinux_2_17_x86_64.whl -
Subject digest:
2da88142bee5634e44e5c73ccda63cf8663274163daad5dcecb292e38d9fcf01 - Sigstore transparency entry: 1537706209
- Sigstore integration time:
-
Permalink:
zackees/zccache@51aae3f0db96314fa65a95be230e60d5e508730d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zackees
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-auto.yml@51aae3f0db96314fa65a95be230e60d5e508730d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file zccache-1.4.7-py3-none-manylinux_2_17_aarch64.whl.
File metadata
- Download URL: zccache-1.4.7-py3-none-manylinux_2_17_aarch64.whl
- Upload date:
- Size: 13.7 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3819cf3e852d949b5b51e42b3174de72b3f53345ae6756b42a03d1cc4deb379
|
|
| MD5 |
68e9c005ac441a126d56a88e5b90fc60
|
|
| BLAKE2b-256 |
025e7da3b45df25391d6d8b232db83cc9fd5b924e1a496930eb5324c60f023ad
|
Provenance
The following attestation bundles were made for zccache-1.4.7-py3-none-manylinux_2_17_aarch64.whl:
Publisher:
release-auto.yml on zackees/zccache
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zccache-1.4.7-py3-none-manylinux_2_17_aarch64.whl -
Subject digest:
a3819cf3e852d949b5b51e42b3174de72b3f53345ae6756b42a03d1cc4deb379 - Sigstore transparency entry: 1537705706
- Sigstore integration time:
-
Permalink:
zackees/zccache@51aae3f0db96314fa65a95be230e60d5e508730d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zackees
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-auto.yml@51aae3f0db96314fa65a95be230e60d5e508730d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file zccache-1.4.7-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: zccache-1.4.7-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 11.6 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6faff829779dad79c5f54f8e2a02b8ad25ac79040e57baf8b515a0a94cc7d928
|
|
| MD5 |
96f1a3352499682bbaa755367823455c
|
|
| BLAKE2b-256 |
5f15990a71087c8448e592e87aea4b6ccc19d4e57194ae2c0c94d1f10da42722
|
Provenance
The following attestation bundles were made for zccache-1.4.7-py3-none-macosx_11_0_arm64.whl:
Publisher:
release-auto.yml on zackees/zccache
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zccache-1.4.7-py3-none-macosx_11_0_arm64.whl -
Subject digest:
6faff829779dad79c5f54f8e2a02b8ad25ac79040e57baf8b515a0a94cc7d928 - Sigstore transparency entry: 1537706109
- Sigstore integration time:
-
Permalink:
zackees/zccache@51aae3f0db96314fa65a95be230e60d5e508730d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zackees
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-auto.yml@51aae3f0db96314fa65a95be230e60d5e508730d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file zccache-1.4.7-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: zccache-1.4.7-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 12.1 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d34ee9ccee5aef93609abca43370fca39e27f23f367623653064d6c464dc033
|
|
| MD5 |
d69f92a1d86afab3fbcf64bcf2689f83
|
|
| BLAKE2b-256 |
b94431e058beacb2435dcd51a2db58bcaac5dca03aac6b45b39a83fafa777fe4
|
Provenance
The following attestation bundles were made for zccache-1.4.7-py3-none-macosx_10_12_x86_64.whl:
Publisher:
release-auto.yml on zackees/zccache
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zccache-1.4.7-py3-none-macosx_10_12_x86_64.whl -
Subject digest:
9d34ee9ccee5aef93609abca43370fca39e27f23f367623653064d6c464dc033 - Sigstore transparency entry: 1537706020
- Sigstore integration time:
-
Permalink:
zackees/zccache@51aae3f0db96314fa65a95be230e60d5e508730d -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zackees
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-auto.yml@51aae3f0db96314fa65a95be230e60d5e508730d -
Trigger Event:
workflow_dispatch
-
Statement type: