Remote caching
A remote cache lets a team (or your CI) share build results. Because zut is content-addressed, sharing is safe by construction: an action’s key is the hash of its inputs, so a result computed on one machine is valid on any other.
Enable it with --remote-cache=<spec> (or remote-cache = <spec> in
.zutrc):
$ zut build //:app --remote-cache=s3://my-bucket?region=eu-west-3
...
remote cache (read_write): 7 hit, 2 miss, 2 uploaded, 0 error
The remote cache is a tier on top of the local store: reads are read-through (miss locally → fetch from remote → populate local), writes are write-through. A misconfigured or unreachable remote degrades gracefully to local-only rather than failing the build, and every blob read back from the remote is digest-verified before use.
Modes
--remote-cache-mode=read-write(default) — read from and upload to the remote.--remote-cache-mode=read— read only (typical for untrusted CI or developer machines that should consume, not publish).
Backends
The scheme in the spec selects the backend:
fs:// — a shared directory
fs:///mnt/nfs/zut-cache
A plain directory (NFS mount, local path). Great for a LAN or for testing.
s3:// — native S3 (and S3-compatible)
s3://my-bucket?region=eu-west-3
s3://my-bucket?region=us-east-1&endpoint=https://minio.local:9000
Speaks the S3 REST protocol directly with hand-rolled AWS SigV4 signing — no AWS
SDK or CLI required. Works against AWS, MinIO, Cloudflare R2, and other
S3-compatible stores via endpoint=.
Credentials follow the standard AWS provider chain:
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN~/.aws/credentialsand~/.aws/config(honoringAWS_PROFILE)
Region comes from the ?region= query param, else AWS_REGION /
AWS_DEFAULT_REGION.
gs:// — native Google Cloud Storage
gs://my-bucket
gcs://my-bucket
Speaks the GCS XML API with an OAuth2 bearer token from GOOGLE_OAUTH_TOKEN
(e.g. export GOOGLE_OAUTH_TOKEN=$(gcloud auth print-access-token)).
cmd: — bring your own store
cmd:/usr/local/bin/my-cache-helper
zut shells out to your helper with get|put|has <key>, streaming blobs over
stdin/stdout. This is the plug-and-play escape hatch: back the cache with
Redis, a database, an internal artifact service — anything — by writing a small
script. No zut changes required.
On the wire
Blobs are wrapped in a small self-describing envelope (objframe) — a magic
tag, flags, optional metadata, and the payload — with transparent deflate
compression above a size threshold. The envelope lives on zut’s side; backends
only ever move opaque bytes, which keeps the S3/GCS clients general-purpose.
For the tiering semantics, the envelope format, and the SDK boundary, see
docs/design/remote-cache.md.