---
name: churro
description: Sets up, checks and troubleshoots Churro, a cache of precompiled Rust dependencies that plugs into Cargo as its RUSTC_WRAPPER, so dependencies are downloaded instead of compiled. Use when the user wants faster clean Rust builds or CI builds, mentions Churro, churro.sh, RUSTC_WRAPPER=churro or `churro stats`, asks whether a crate is in the Churro cache, or a Rust build misbehaves with Churro turned on.
license: MIT OR Apache-2.0
---

# Churro

Churro's builders compile popular crates.io crates in sandboxes with no network, and publish a result only when independent builders produce byte-identical output. Each result is signed. On the user's machine, Churro runs as Cargo's `RUSTC_WRAPPER`: when a dependency's result in the cache was built from exactly the same inputs, it downloads that and checks it; otherwise it runs `rustc` as usual. The worst case is a normal build.

It never edits code, `Cargo.toml` or `Cargo.lock`, and never uploads anything. Only crates.io dependencies come from the cache; workspace, path and git crates always compile locally.

## Setting it up

Follow https://churro.sh/setup.md step by step: it's kept current with the client. In short:

```sh
cargo install --locked --git https://github.com/usechurro/churro churro-client
churro config
RUSTC_WRAPPER=churro CHURRO_HOST_ARTIFACTS=1 CARGO_TARGET_DIR="$(mktemp -d)" cargo build
churro stats
```

- To keep it on, `export RUSTC_WRAPPER=churro CHURRO_HOST_ARTIFACTS=1` in the user's shell profile or CI environment. Ask before editing shell profiles or `~/.cargo/config.toml`.
- Never set `rustc-wrapper` in a project's committed `.cargo/config.toml`: builds fail for anyone without Churro.
- Churro replaces another `RUSTC_WRAPPER` such as sccache; they don't chain. Ask before replacing one.

## Commands

| command | what it does |
|---|---|
| `churro config` | the endpoint, cache directory and trusted keys in effect, and where each came from |
| `churro stats` | every compile Churro has seen on this machine, by outcome, and the local cache size |
| `churro explain KEY` | what went into a cache key (for a key in the local cache) |
| `churro clean` | delete the local cache |
| `churro daemon start --profile dev` | start fetching a project's dependencies before the build asks for them (useful early in CI) |
| `churro help` | every command and variable |

`churro stats` outcomes: `hit-remote` downloaded from the shared cache; `hit-local` reused from this machine's cache; `miss` compiled here and kept locally; `pass` handed straight to `rustc`, with the reason (your own crates always are).

## Configuration

Environment variables override `~/.config/churro/config.toml` (or the file at `CHURRO_CONFIG`).

| variable | meaning |
|---|---|
| `RUSTC_WRAPPER=churro` | turns Churro on (a Cargo variable) |
| `CHURRO_HOST_ARTIFACTS=1` | also cache proc macros and build scripts (experimental) |
| `CHURRO_DISABLE=1` | run `rustc` untouched |
| `CHURRO_OFFLINE=1` | never contact the cache server |
| `CHURRO_ENDPOINT` | cache server URL, for a self-hosted cache |
| `CHURRO_TRUST_ROOTS` | root public keys that cache's builders are certified by (base64, comma-separated) |
| `CHURRO_CACHE_DIR` | local cache (default `~/.cache/churro`) |

Config file for a self-hosted cache (`cargo ops client-config` prints it):

```toml
endpoint = "https://cache.example.com"
[trust]
roots = ["<base64 ed25519 public key>"]
```

An endpoint without a root key is never used, since nothing it sends could be verified.

## Is a crate in the cache?

Ask the public API (read-only JSON, no key):

- `https://cache.churro.sh/v1/crates?q=QUERY` searches cached crates by name.
- `https://cache.churro.sh/v1/crates/NAME` lists every cached build: version, target, Rust release, profile, mode, kind, features.

As Markdown: `https://churro.sh/catalog.md?crate=NAME`. A result is only used when all of these match the user's build, so a listed crate isn't a promise that every build of it hits.

## Troubleshooting

- **`could not execute process 'churro'`**: `~/.cargo/bin` isn't on `PATH`. Fix `PATH`, or unset `RUSTC_WRAPPER`.
- **No `hit-remote`**: run `churro config`. `endpoint: (none ...)` means no shared cache is configured in this client, and `(not used: no root key)` means it can't be verified. The shared cache is compiled for Linux, so macOS and other systems only get local hits.
- **One dependency never hits**: a different crate version, Rust release, target, profile, feature set, flags or environment makes a different build. Compare with the catalog.
- **A build fails only with Churro**: confirm with `CHURRO_DISABLE=1 cargo build`, then report it at https://github.com/usechurro/churro/issues with the error output.
- **CI install step fails**: set `RUSTC_WRAPPER: ""` on the `cargo install` step, since `churro` doesn't exist until it finishes.

## Turning it off

`CHURRO_DISABLE=1` for one build. For good: remove the `RUSTC_WRAPPER` line that was added, `churro clean`, `cargo uninstall churro-client`.
