# Compiled code

When a Rust check runs, hushrun can also skip compiling the crates it already compiled from the same inputs: on your machine, and through your organization's shared store, on every machine that builds the repository. This page explains how, whose code each machine reuses, and what never leaves the machine. To set it up, see [Share compiled code](https://hushrun.com/docs/shared-store.md).

## Terms

- **Build reuse:** inside `hushrun run`, hushrun stands between cargo and the compiler. It keeps each crate it compiles in a store on the machine, and a compile with the same inputs as one it kept takes the kept crate instead of compiling.
- **Block:** one compiled crate as hushrun stores it. The lines hushrun prints say *blocks* where these pages say crates.
- **Shared store:** your organization's store of compiled code on hushrun's server, behind each machine's own. An admin turns it on.
- **Trusted branch:** a branch an admin listed for a repository. Its CI writes the code that every machine building that repository reuses.
- **Trusted code:** what a repository's trusted branches' CI compiled. The lines hushrun prints call it the repository's *trusted blocks*, or its *trusted copy*.
- **Your own machines:** every machine signed in to this organization as you.
- **Hints:** the list of files each crate's compile read, which tells the next machine what to hash. They are sealed, and hold no code.
- **Suspended:** a crate whose two trusted builds disagreed. Its stored copy is deleted, and every machine of that repository compiles it instead of reusing it, for 7 days or until an admin clears it.
- **Allowance:** how much compiled code your plan lets the shared store hold.

## On your machine

On a person's machine, build reuse is off until you turn it on, once per machine. In CI it's on whenever the organization shares. In an agent's sandbox it's on by default whenever the organization shares, and `hushrun build off` there wins.

```bash
hushrun build on
```

From then on, every Rust compile that `hushrun run` starts goes through hushrun, in both forms: `hushrun run NAME -- COMMAND` and the checks of `hushrun.yaml` (`hushrun run CHECK`). Only the first form also uses your organization's [shared store](#shared-store). A compile counts as the same when the compiler, its flags, every file it read and the variables it was told about are the same. The worktree, the folder and the commit aren't part of it, so a second worktree or a fresh clone reuses what the first one compiled.

After the command, the run says what its compiles came to:

```text
hushrun: build: 319 of 360 crates reused, 41 built, saving about 3m 39s
```

- It's free and needs no account. Nothing leaves the machine unless your organization shares and your machine takes part.
- A crate nobody used for 15 days is deleted. There is no size limit, but nothing is kept while the disk has less than 10 GB free.
- A plain `cargo` outside `hushrun run` is untouched, and so is cargo's configuration.
- It stays out of the way where another wrapper is set (`RUSTC_WRAPPER`, as sccache uses), on Windows, and for a check `hushrun run --isolated` runs in a container.
- `hushrun build observe` compiles everything as usual and says what would have been reused, if you'd rather watch first.

Every command and setting: [hushrun build](https://hushrun.com/docs/reference/cli.md#hushrun-build).

## Across machines

With the shared store on, a compile inside `hushrun run NAME -- COMMAND` that finds nothing on the machine asks the shared store. Once an admin has chosen **Start reusing**, and the crate is there, hushrun downloads it, checks it and reuses it as if it had been built here. Before that, while the organization is watching, machines only compare. A crate the machine builds goes up for the next machine.

- **Sealed.** Each crate is encrypted with a key that comes from its own inputs, so only someone who has the same source, flags and compiler can open it. hushrun's server and its storage provider can't, and an org member without the repository's source can't either.
- **Checked like your own.** A download's files must match what the server recorded when it was stored, and it is reused through the same checks as a crate built here. One library reuse in fifty compiles anyway and compares the result byte for byte; on a person's machine, a library that was downloaded is compared one time in ten on its first reuse.
- **At most half a compile slower, usually faster.** hushrun measures your link during the run, and starts a download only when it should arrive within half the time the crate takes to compile. Otherwise the compiler runs. So a wrong guess costs at most half of that crate's compile time. On a person's machine, cargo never waits for the network to start.
- **Withdrawn code stops being reused.** At its next run, a machine that reaches hushrun's server asks again about every crate it downloaded whose last word from the server is over a day old. So on such a machine, code an admin withdraws stops being reused within a day. Once the server says it no longer serves a crate, that copy is never reused again, even offline. When the server answers too slowly, the crate compiles. A machine with no network hears of no withdrawal until it's back online: meanwhile it reuses a crate it downloaded only where its own earlier compiles lead to that crate. A sandbox's [saved fetch](https://hushrun.com/docs/shared-store.md#offline-sandbox) is reused for the rest of its 24 hours without being told.
- **Off means off for downloads.** A run that isn't sharing, because the organization turned sharing off, the person ran `hushrun build share off`, or nobody is signed in, reuses nothing it only downloaded: it compiles those crates once, and they are then its own. So the first build after sharing goes off compiles what had been downloaded. Only a run that can't reach the network reuses an older download.
- **Offline builds stay offline.** A machine that can't reach hushrun builds and reuses from its own store as usual, says nothing about sharing, and keeps what it builds: nothing built offline is uploaded later. The next machine that builds it online uploads it.

The run's line says how many reuses came from the shared store:

```text
hushrun: build: 226 of 360 crates reused (226 from the shared store), 134 built, saving about 2m 3s
```

## Whose code a machine reuses

Compiled code ends up in what you ship, and nothing in a crate proves it came from an honest compile. So one rule decides: a machine never reuses code written by something less trusted than itself.

| Machine | Reuses | Writes |
|---|---|---|
| CI on a [trusted branch](#trusted-branches) | The repository's trusted code, and nothing else | The repository's trusted code |
| CI on a pull request, or on a branch that was never listed | The repository's trusted code, then what earlier runs of the same pull request built (for a push, of the same branch) | Code for that pull request or branch alone, kept 7 days after its last use |
| A release: CI on a tag, or a job with an `environment:` key | The repository's trusted code, and nothing else | Nothing |
| Your machine | The trusted code of the repository you're in, then what your own machines built | Code only your own machines reuse, or the team's pool with **One for the team** |
| An agent's sandbox | Its repository's trusted code, and, if its token may write, what that token stored | Nothing, unless an admin lets its agent token write: then code that token reuses, or the team's pool with **One for the team** |
| CI with an agent token, outside GitHub Actions | The repository's trusted code alone, whatever that token may do elsewhere | Nothing |
| A GitHub Actions job without an ID token, or any CI job with only a person's sign-in | Nothing, whatever other token it holds | Nothing |
| A pull request from a fork | Nothing | Nothing |

What follows from it:

- What a repository ships holds only code its own trusted CI built, and code the release job built itself.
- Without **One for the team**, a laptop or a sandbox that goes wrong can spoil only what it alone reuses.
- A pull request starts warm from main's code and can't change it.
- Trusted code stays in its repository. Another repository of your organization builds its own, even of the same crate.
- A teammate's unmerged work isn't shared with you.

Reuse runs one way: CI's trusted code reaches laptops, sandboxes and other jobs, and a laptop's code never reaches CI.

An admin can widen one thing, under **Sharing** on the Shared store page, in the row **People's and agents' code**: **Switch to one for the team…** makes people's machines, and agent tokens that may write, share one pool. Then every member's laptop feeds every other's, and one that goes wrong spoils the pool for all. Trusted CI never reads it. Switching deletes what each person and token stored on their own, and switching back deletes the pool. The dialog says how much first.

## Trusted branches

An admin lists each repository's trusted branches on the repository's page in the dashboard, by their exact names, such as `main`. Only a branch whose CI has already run hushrun can be listed. A CI job writes trusted code only when all of these hold:

- its branch is listed;
- its event is a push or a schedule, or a manual run (`workflow_dispatch`) where an admin allowed those;
- it runs on GitHub's own runners, unless the repository opted its self-hosted runners in;
- it has no `environment:` key, the mark of a job that deploys;
- it builds the commit its token names, with no file git tracks changed before the build;
- the repository is the one an admin confirmed, with the same owner on GitHub;
- its run started after the branch was listed.

A job on a listed branch that misses one of these reads the trusted code and writes nothing, and its run says why.

Branches are listed one by one: no patterns, and never a tag. Anyone with write access can usually create a branch that would match a pattern, or push a tag, and GitHub's rules don't stop that by default. Listing a branch trusts everyone who can push to it, so the dashboard warns beside a branch GitHub doesn't protect.

Withdrawing a branch puts its code out of reach at once, and listing it again doesn't bring that code back.

Four settings hold only while the admin who gave them is an admin or owner of the organization: a trusted branch, the allowance for manual runs, the opt-in for self-hosted runners, and an agent token's writing. When that admin leaves or loses the role, each holds 14 days more and then ends, unless another admin chooses **Confirm** on it. A repository's confirmation, the switch and the pool don't lapse.

## When it helps

The shared store pays off where a machine starts with nothing compiled:

- a new sandbox, a CI runner, a second laptop or a fresh clone;
- a pull request's CI, after main's CI built the code it starts from.

A download wins when the link brings code in faster than the machine could compile it. On hushrun's own two Rust repositories, built on a 10-core Mac, one second of compiling on one core made 2 to 3 MB of compressed compiled code. At that rate a 2-core CI runner is matched by a link of 35 to 50 Mbit/s, and a 10-core laptop needs 170 to 250 Mbit/s.

## When it doesn't

- **A fast laptop on a slow link.** hushrun doesn't start a download it expects to lose, so the compiler runs. Your machine's own store answers most compiles anyway.
- **A Mac and Linux never share,** and neither do two compiler versions or two targets. A Mac gets nothing from Linux CI. Pin one toolchain, with `rust-toolchain.toml`, on laptops and CI.
- **Only libraries are shared.** Programs, tests, proc macros and build scripts are compiled on each machine. Your machine's own store still reuses them.
- **A compiler wrapper already set,** such as sccache through `RUSTC_WRAPPER`, turns hushrun's build reuse off for that run. Where your organization shares, the run says so in one line.
- **The checks of `hushrun.yaml`,** run as `hushrun run CHECK`, reuse only what the machine compiled itself, never a crate it only downloaded, and nothing in CI. Where your organization shares, such a run that compiled Rust says once that it didn't use the shared store. Run a Rust build as `hushrun run NAME -- COMMAND` to share it.
- **New code** compiles once, wherever it's first built.
- **GitLab CI** doesn't take part yet: a GitLab repository has no trusted code, and its CI builds as it would without the store. Laptops and sandboxes in it still share as anywhere else: each person's machines reuse what that person's other machines built, or the team's pool does with **One for the team**.
- **Not covered:** Windows, clippy, rustdoc, coverage builds, and cargo outside `hushrun run`.

## What stays on your machine

These are never uploaded, whatever the settings:

- a crate whose compiled files hold one of your machine's folders, such as your home folder or cargo's. These are compiled on each machine, and there's nothing to do;
- a crate whose compiled files hold the value, 8 bytes or more, of an environment variable its inputs don't include. Only the exact variables a CI system documents as its own, and a few the build tools and the shell set, are left out of this search, and a variable whose name looks like a secret never is. The run names the variable, never its value;
- a crate compiled with `-C target-cpu=native`, since no other machine can tell what that meant here;
- programs, proc macros and build scripts, as above;
- anything from a machine whose sharing is off, anything built with no network, and anything built outside `hushrun run NAME -- COMMAND`.

What goes up is compiled libraries, sealed. A compiled library holds its string literals, text taken in with `include_str!` or `include_bytes!`, and the compiled form of its generic code: much of its source. Sealing is why only someone who has that source can open it. What sealing doesn't cover, and what hushrun's server knows about each crate: [Security and data](https://hushrun.com/docs/security.md#compiled-code).

A build script or a proc macro can read a variable without telling the compiler. Name such variables under `build: env:` in `hushrun.yaml`, so every machine's compiles are keyed by them: see [Name the variables your build reads](https://hushrun.com/docs/shared-store.md#build-env).

## Next

- [Share compiled code](https://hushrun.com/docs/shared-store.md): turn the shared store on, step by step.
- [Security and data](https://hushrun.com/docs/security.md#compiled-code): sealing, and what it doesn't cover.
- [Plans and limits](https://hushrun.com/docs/plans.md#shared-store): how much each plan includes.
