These are the short paths for the adapter commands BoringCache ships today.
The pattern is simple:
boringcache onboard.boringcache.tomlboringcache <tool>cache-registry only when the repo already has a checked-in local endpoint setup or another process should keep the proxy alivecache-registry is the proxy.
boringcache <tool> and boringcache run --proxy temporarily start that same proxy for one command, wait until it is ready, then hand traffic to the wrapped tool.
cache-registry itself is warm by default. Use --on-demand only for advanced shared-proxy setups that prefer immediate startup over warmed first reads.
The snippets below are intended to be copy-pasteable .boringcache.toml
starting points. They work for local CLI runs and for boringcache/one
because the action asks the CLI for the same repo plan.
Shared defaults for the examples:
[proxy].metadata-hints[adapters.<tool>].metadata-hintsno-platform and no-git unset unless the cache is genuinely portableread-only = true only on restore-only lanesworkspace = "my-org/my-project"
[proxy]
metadata-hints = ["project=app"]
[adapters.docker]
tag = "docker-cache"
command = ["docker", "buildx", "build", "."]
metadata-hints = ["tool=oci", "lane=ci"]
boringcache docker
boringcache docker --tag docker-cache -- docker buildx build .
boringcache docker injects --cache-from and --cache-to for you.
Do not pass those flags yourself.
Use --cache-mode only when you need to change the BuildKit export mode.
Direct BuildKit runs use the same OCI cache plan:
[adapters.buildkit]
tag = "docker-cache"
command = ["buildctl", "build", "--frontend", "dockerfile.v0"]
metadata-hints = ["tool=oci", "lane=ci"]
boringcache buildkit
boringcache buildkit --tag docker-cache -- buildctl build --frontend dockerfile.v0
boringcache buildkit injects --import-cache and --export-cache for buildctl build.
Keep builder installation, daemon lifecycle, QEMU/binfmt, and Docker container networking in the caller’s runtime setup.
Docker has one BoringCache tag concept:
--tag docker-cache selects the resolved human cache tag, and the CLI uses that same tag for the BuildKit registry ref and backend cache entry.In GitHub Actions or another CI environment that provides BoringCache CI metadata, the adapter applies the shared branch/default/PR restore ordering as human tags. It injects the planned human-tag imports and exports the resolved write tag:
--cache-from .../cache:docker-cache-pr-3208-ubuntu-24-x86_64
--cache-from .../cache:docker-cache-main-ubuntu-24-x86_64
--cache-to .../cache:docker-cache-pr-3208-ubuntu-24-x86_64
BoringCache backs the BuildKit registry cache through the Docker and direct BuildKit adapters. By default the Docker path warms the selected OCI manifest, blob URLs, and blob bodies before BuildKit starts. That keeps the normal path simple: a warm BuildKit run should read cache bodies through the local proxy instead of discovering remote body reads after the manifest hit.
If the builder runs in another container, set endpoint-host = "host.docker.internal" in .boringcache.toml or pass --endpoint-host host.docker.internal.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
docker buildx build \
--cache-from type=registry,ref=127.0.0.1:5000/my-cache:main \
--cache-to type=registry,ref=127.0.0.1:5000/my-cache:main,mode=max \
.
[adapters.nx]
tag = "build-cache"
command = ["nx", "run-many", "--target=build"]
boringcache nx
Nx gets the local endpoint and access token automatically.
If nx.json is still connected to Nx Cloud with nxCloudId, nxCloudAccessToken,
or an nx-cloud task runner, Nx may select its private cloud runner before the
self-hosted cache endpoint. Remove that Nx Cloud binding from the workspace
config before using the BoringCache Nx proxy, or use a prepared disposable
checkout for benchmarks. Do not use NX_NO_CLOUD as the BoringCache setup path;
Nx treats it as remote-cache disablement in current releases.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
NX_SELF_HOSTED_REMOTE_CACHE_SERVER=http://127.0.0.1:5000 \
NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN=boringcache \
nx run-many --target=build
workspace = "my-org/my-project"
[proxy]
metadata-hints = ["project=web"]
[adapters.turbo]
tag = "turbo-cache"
command = ["pnpm", "turbo", "run", "build"]
metadata-hints = ["tool=turborepo", "lane=ci"]
boringcache turbo
Turborepo gets TURBO_API, TURBO_TOKEN, and TURBO_TEAM automatically.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
TURBO_API=http://127.0.0.1:5000 \
TURBO_TOKEN=boringcache \
TURBO_TEAM=boringcache \
turbo run build
workspace = "my-org/my-project"
[proxy]
metadata-hints = ["project=backend"]
[adapters.bazel]
tag = "bazel-cache"
command = ["bazel", "build", "//..."]
metadata-hints = ["tool=bazel", "lane=ci"]
boringcache bazel
boringcache bazel starts the proxy and runs Bazel.
It injects --remote_cache=http://127.0.0.1:5000 automatically and keeps upload enabled unless you run the adapter in read-only mode.
If the repo already has Bazel cache flags in .bazelrc, those stay in effect and explicit user flags still win.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
bazel build --remote_cache=http://127.0.0.1:5000 //...
workspace = "my-org/my-project"
[proxy]
metadata-hints = ["project=backend"]
[adapters.gradle]
tag = "gradle-cache"
command = ["./gradlew", "build", "--no-daemon"]
metadata-hints = ["tool=gradle", "lane=ci"]
boringcache gradle
boringcache gradle starts the proxy and runs Gradle.
It injects --build-cache and a generated init script that points Gradle remote cache traffic at http://127.0.0.1:5000/cache/.
The adapter keeps push enabled unless you run it in read-only mode.
If the repo already has build cache config in settings.gradle(.kts), that still works. The adapter-owned init script just makes the local proxy turnkey for one command.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
./gradlew build --build-cache --no-daemon
[adapters.maven]
tag = "maven-cache"
command = ["mvn", "install", "-DskipTests", "--batch-mode", "-ntp"]
boringcache maven
boringcache maven starts the proxy and runs Maven.
It injects the maven.build.cache.remote.url and maven.build.cache.remote.save.enabled properties automatically.
If the repo does not already use the Maven build cache extension, add that first. The adapter owns the endpoint and save mode, but it does not bootstrap the extension itself.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
mvn install -DskipTests --batch-mode -ntp -Dmaven.build.cache.remote.save.enabled=true
workspace = "my-org/my-project"
[proxy]
metadata-hints = ["project=rust"]
[adapters.sccache]
tag = "rust-cache"
command = ["cargo", "build", "--release"]
metadata-hints = ["tool=sccache", "lane=ci"]
# Optional: keep sccache objects under a WebDAV sub-root.
sccache-key-prefix = "rust/ci"
boringcache sccache
The adapter sets RUSTC_WRAPPER=sccache, SCCACHE_WEBDAV_ENDPOINT, SCCACHE_WEBDAV_KEY_PREFIX, and CARGO_INCREMENTAL=0 when the caller has not set it.
After the wrapped command exits, it reads sccache --show-stats, prints a concise hit/miss summary, and records normalized native tool evidence with the run/session diagnostics when sccache reports stats.
For a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
RUSTC_WRAPPER=sccache \
SCCACHE_WEBDAV_ENDPOINT=http://127.0.0.1:5000/ \
SCCACHE_WEBDAV_KEY_PREFIX=rust/ci \
cargo build --release
[adapters.go]
tag = "go-cache"
command = ["go", "build", "./..."]
boringcache go
Use boringcache go for normal Go cache integration. The adapter sets GOCACHEPROG automatically for Go 1.24+.
Advanced: manual GOCACHEPROG wiring for a long-lived endpoint:
boringcache cache-registry my-org/app registry-cache --port 5000
GOCACHEPROG="boringcache go-cacheprog --endpoint http://127.0.0.1:5000" \
go build ./...