Rust builds that never do the same work twice.
A fast, Cargo-compatible build system and package manager for Rust. Drop it into any Cargo project — no changes, no lock-in.
$ curl -fsSL https://www.runepm.com/install.sh | shYour Cargo project, as it is.
Rune builds existing Cargo projects with rustc directly. The commands, flags and manifests are Cargo's — and the project keeps working with plain cargo.
Nothing to migrate
Rune writes a Cargo-format Cargo.lock, reads .cargo/config.toml, and changes nothing else.
Your plugins come along
Every cargo-<name> on your PATH works as a Rune subcommand.
Fast where it matters.
Finding out nothing changed, switching branches, starting on a fresh machine: the moments a build tool is waited on most. Rune against Cargo, measured with rune-bench.
- fresh checkout
- 108×
- switching back to a branch
- 34×
- running the tests
- 9×
- faster overall, 32 measurements
- 2.8×
On a generated 25-crate workspace. Cold builds and rebuilds after an edit are on par: both run the same compiler. Run it on your own project with rune-bench run --project path/to/it.
Nothing is compiled twice.
Every compiled crate goes into a content-addressable store shared by all your projects, branches, profiles and machines. Same inputs, same artifact — reused in milliseconds instead of compiled again.
UnitKey = hash( package + source identity + target kind, crate types, edition, features + compiler, RUSTC_WRAPPER, rustflags, linker + the unit's effective profile + every dependency's own key + the outside inputs it read)
check after build is free
Type-checking reuses what a build already compiled. On Rune's own workspace, check right after build compiles nothing.
Correct before fast
Store objects are immutable, published atomically and verified on every hit. A false rebuild is acceptable; a wrong artifact is not.
Several builds at once
An editor's background check next to a terminal build: no lock on the target directory, and a unit another process is building is waited for, not built twice.
A store that stays small
Capped at a tenth of its disk, compressed when idle for a week, cleaned after a month. rune cas pin keeps what a workspace needs.
A test runner you can trust.
Testing starts while the build is still running — the first test binary runs the moment it links — with a live view of what runs, how many tests passed and how long each binary takes.
Stable by default
Test binaries run one at a time, as with Cargo, so tests that share a port or a database don't fail at random. Opt into parallel binaries with --test-jobs.
Re-run what failed
rune test --failed builds and runs only the tests that failed last time — again and again, until none are left.
Flaky tests, named
Retries with flaky-test detection, timeouts for hung tests and JUnit reports, so a bad test can't hang a CI job.
Cached results
--cached skips the binaries that passed with identical inputs: 8 s down to 0.26 s when nothing changed.
Scheduled across binaries
nextest-style scheduling of tests across binaries, with a live line for what is running and for how long.
Coverage, built in
rune coverage writes a summary, LCOV, Cobertura or HTML report, and fails the run under a threshold.
One cache for every machine.
Share the store between laptops and CI through a directory or Cairn, Rune's companion cache server. A developer with an empty store restores a whole workspace in under a second.
- to restore Rune's own 182 units from a cache server. Building them takes about 30 s.
- 0.65 s
- added to a CI build for publishing its results, in the background.
- ~1%
rune cas import ci.tar.gz || true # a missing bundle is finerune build && rune test --retries 2 --junit report.xmlrune cas export -o ci.tar.gz --for build --for test
Bundles that don't grow
rune cas export saves exactly the store entries a run needs — unlike a cached target/, it never grows with every run.
Selective CI
rune affected --since origin/main lists the packages a change can influence, and splits them across machines.
Build scripts stay in their sandbox.
With build.sandbox = true, build scripts and proc-macros run with no network and nothing writable outside the build. A script that reaches for ~/.bashrc or phones home fails instead — at no measurable cost.
rune auditEvery dependency against the RustSec database, with the path that brings it in and the fix.
rune sbomA CycloneDX 1.5 or SPDX 2.3 bill of materials for what the workspace ships.
rune tree --exec-surfaceEvery crate that runs code at build time, and who brings it in.
resolve.min-release-ageKeeps brand-new releases out of the lockfile until they have aged.
Everything else, in the same binary.
rune outdatednewer releases than the lockfile allows
rune upgraderaise requirements, keeping their style
rune unused --fixdrop dependencies the compiler says are unused
rune watch -x testre-run on every change
rune script hello.rssingle-file scripts with dependencies
rune explainwhich units the next build compiles, and why
rune doctorwhat slows your build down, with the fix
rune build --timingsa timeline with the chain that sets the pace
rune installprograms from crates.io, git or a path
rune publishpackage and upload a crate
rune vendorevery dependency into vendor/
rune nextest runany cargo-<name> plugin you already have
Works with what you have.
Tested against real-world workspaces — ripgrep, serde, regex — and a corpus of popular crates whose own test suites must pass under Rune as they do under Cargo.
- workspaces
- features
- build scripts
- proc-macros
- cc · bindgen · cxx · pyo3
- git & path dependencies
- alternative registries & mirrors
- [patch]
- cross-compilation
- custom profiles
- rust-toolchain files
- RUSTC_WRAPPER
- rust-analyzer
Linux and macOS are Rune's home; Windows builds are new and less tested. What's supported, and the known limits
Try it on your project.
Nothing to migrate and nothing to undo: your project keeps working with plain cargo.
$ curl -fsSL https://www.runepm.com/install.sh | sh