Contributing · 1. Build from source

Four commands get you a running daemon, and you do not need protoc despite four documents in the repository telling you that you do. This chapter gives the exact sequence, the measured cost in time and disk, and the failure modes you will hit.

Follow it top to bottom the first time. It is a tutorial: one path, no choices.

1.1 Prerequisites

RequirementStatusWhere it is pinned
Rust 1.88.0Requiredrust-toolchain.toml:2, channel = "1.88.0", profile = "minimal", components = ["rustfmt", "clippy"]
A C toolchain and linker (cc)RequiredCI fails hard without it at ci.yml:117
gitRecommended, not requiredThree build scripts shell out to git rev-parse --short HEAD; they fall back to "unknown"
jq and curlOnly for the shell gatesscripts/demo-receipt-tamper.sh, scripts/assert-context-custody.sh, scripts/assert-no-phone-home.sh
strace or unshare plus ipOnly for the no-phone-home assertionassert-no-phone-home.sh exits 2 (skip) if neither is present
protocNOT requiredSee below
Disk50 GB minimum, 150 GB if you run coverageSee section 1.5

rustup reads rust-toolchain.toml automatically on your first cargo invocation inside the tree and installs 1.88.0 if you do not have it. The same version is declared as the MSRV at Cargo.toml:47 and gated by a required CI job named MSRV (1.88.0).

On Debian or Ubuntu, the C toolchain is one package:

sudo apt install build-essential

You do not need protoc

Four documents in the repository say you do. They are wrong.

crates/corecrux-proto/build.rs:9 resolves a vendored compiler and sets the PROTOC environment variable itself, before tonic_prost_build runs:

fn main() -> anyhow::Result<()> {
    let protoc = protoc_bin_vendored::protoc_bin_path()?;
    std::env::set_var("PROTOC", protoc);

The dependency is protoc-bin-vendored = "3.2.0" at crates/corecrux-proto/Cargo.toml:16. This was verified during the 2026-07-27 audit on a machine with no protoc anywhere on PATH: the workspace builds.

The four documents that claim otherwise:

DocumentLineClaim
CONTRIBUTING.md18"protoc (Protocol Buffers compiler), required by corecrux-proto"
README.md89"From source (Rust 1.88+, protobuf-compiler)"
README.md386Same, in the Operations reference table
docs/getting-started.md98"Rust 1.88+, protobuf-compiler"

Installing protobuf-compiler does no harm, the build script overrides PROTOC regardless, but nothing in the workspace consults a system protoc. Fixing these four lines is good first contribution number 5.

The four build scripts

The workspace has exactly four build.rs files, and knowing this saves you diagnosis time when one of them is the thing that failed:

Build scriptDoes
crates/corecrux-proto/build.rsCompiles the two protobuf packages using the vendored protoc
crates/corecrux-types/build.rsEmbeds the short git SHA
crates/corecruxctl/build.rsEmbeds the short git SHA
crates/corecruxd/build.rsEmbeds the short git SHA; falls back to "unknown"

A tarball checkout with no .git builds fine. --version will report unknown for the SHA.

1.2 Clone to a running binary

Verbatim. Nothing here needs substituting.

git clone https://github.com/CueCrux/Crux.git
cd Crux
cargo build --release
CORECRUXD_AUTH_MODE=dev_scopes CORECRUXD_DATA_DIR=./data ./target/release/corecruxd

Two binaries land in target/release/: corecruxd (the daemon) and corecruxctl (the CLI).

The daemon opens three listeners on loopback: HTTP on 14800, MCP on 14801, gRPC on 4007. Confirm it is alive from a second terminal:

curl -sf http://127.0.0.1:14800/readyz && echo OK
curl -s http://127.0.0.1:14800/v1/version | jq .

CORECRUXD_AUTH_MODE is mandatory and has no default. The daemon refuses to start without it and refuses to start on an unrecognised value; this is deliberate fail-closed behaviour, tracked at config.rs:876 and documented at config.example.env:12. See 3.3 Auth modes for what each value means.

1.3 Build the way CI builds

For any build whose result you intend to push, add --locked. CI uses it everywhere, and it stops a stray Cargo.lock bump from sneaking into your diff:

cargo build --locked --workspace

AGENTS.md:58 states the same, and every cargo invocation in .github/workflows/ci.yml goes through scripts/ci-cargo-with-fallback.sh with --locked.

For iteration, use the debug profile. Everything except the smoke and performance gates works against target/debug/:

cargo build --locked --workspace          # debug: much faster
cargo build --locked --release            # release: slow, see 1.4

1.4 What the build actually costs

The release profile is deliberately slow. Cargo.toml:185:

[profile.release]
opt-level = 3
lto = "thin"
codegen-units = 1
strip = "symbols"

codegen-units = 1 plus thin LTO makes --release substantially slower than a stock release build. The debug profile is opt-level = 0 (Cargo.toml:182).

Measured 2026-07-27 on a 16-core machine with 30 GB RAM and a warm target/:

MeasurementResult
Resolved dependency graph525 packages, 28 of them workspace members
cargo test -p corecrux-frame (leaf crate, 6 tests)2.04 s wall
cargo build --workspace --offline, all 497 third-party deps already compiled, 28 workspace crates rebuilding, debug90.75 s wall
Cold cargo build --release on typical developer hardwareRealistically 20 to 45 minutes
Full test suite on a warm CI runnerAbout 10 minutes

So: the 28 workspace crates alone are a roughly 90-second debug rebuild on 16 cores. Scale down accordingly for fewer cores.

docs/troubleshooting.md:162 claims "First Rust build downloads and compiles all dependencies (~5 minutes)." That is not plausible for 525 packages at codegen-units = 1 with thin LTO, and it will set your expectations wrong. Treat the measured range above as authoritative.

1.5 Disk: the 178 GB number

A tree that has built debug, release and cargo llvm-cov reaches 178 GB in target/ (du -sh target, measured 2026-07-27). target/llvm-cov-target/ and target/doc/ are separate trees stacked on top of debug and release.

WorkflowBudget
Debug only50 GB or more
Debug plus release100 GB or more
Anything that runs coverage150 GB or more

If your home partition cannot take that, redirect the build output before your first cargo command:

export CARGO_TARGET_DIR=/mnt/big-volume/crux-target

Reclaim space at any time with cargo clean, which is safe and only costs you a rebuild.

This is stated up front because a contributor whose disk fills mid-build, with no warning, does not come back.

1.6 First-build failures and their fixes

SymptomCauseFix
error: linker 'cc' not foundNo C toolchainsudo apt install build-essential
error: failed to run custom build command for proc-macro2The same absent or broken C toolchainsudo apt install build-essential
FATAL: CORECRUXD_AUTH_MODE is requiredThe daemon was started with no auth modeexport CORECRUXD_AUTH_MODE=dev_scopes
address already in use14800, 14801 or 4007 is already boundStop the other daemon, or override CORECRUXD_HTTP_PORT / CORECRUXD_MCP_PORT / CORECRUXD_GRPC_PORT for this run only
Disk fills partway through the buildtarget/ growth, section 1.5cargo clean, or set CARGO_TARGET_DIR onto a larger volume
Stack overflow in a corecruxctl test threadRUST_MIN_STACK unset because you ran the test binary directly rather than through cargoexport RUST_MIN_STACK=8388608

The last one deserves explanation. .cargo/config.toml sets:

[env]
RUST_MIN_STACK = "8388608"

The comment there records why: corecruxctl's clap command tree is large enough that the debug-build parser overflows the default 2 MiB test-thread stack. That setting applies only to cargo-spawned processes. If you invoke a compiled test binary directly, export it yourself.

1.7 Documents in the repo that are wrong

Fixing any of these is a legitimate, self-contained first pull request. All are verified against main at 93b41a7.

DocumentLineClaimTruth
CONTRIBUTING.md18protoc is requiredIt is not. Section 1.1
README.md89 and 386protobuf-compiler is requiredIt is not. Section 1.1
docs/getting-started.md98protobuf-compiler is requiredIt is not. Section 1.1
docs/getting-started.md99Links [README Quickstart](../README.md#quickstart)Broken anchor. The README heading is "Up and running in 60 seconds" at README.md:58, so the anchor is #up-and-running-in-60-seconds
docs/troubleshooting.md162First build takes about 5 minutesSection 1.4

1.8 What to do next

NextChapter
Understand what you just built2. Repository tour
Run it with a useful configuration3. Running locally
Run the tests4. Testing
Verify the trust claims rather than believing them4.9 Verifying the claims yourself

Sources