Fast local CI and task runner for Rust workspaces. Define your pipeline once, run it the same way locally and in CI.
Scope note: rx has been refocused from a "unified toolchain manager" to a fast local-CI and task runner for Rust workspaces. See PRODUCT.md for the product definition and explicit non-goals. The ~40 out-of-scope commands (toolchain management, release automation, SBOM, telemetry, plugins, daemon, and other satellites) were removed for 0.2 — use the dedicated tools (rustup, cargo-release, cargo-audit, sccache, …) directly, or invoke them from a configured rx task.
CI failures you could have caught locally waste round-trips, and every project reinvents the same fmt/clippy/test/build pipeline in shell scripts and YAML. rx gives a Rust workspace one task definition that runs identically on your machine and in CI, understands which packages are affected by a change, and delegates compilation to Cargo and Cargo-compatible tools.
rx offers:
- One-command CI —
rx ciruns your full pipeline locally (fmt, clippy, test, build) - Task runner — define tasks once in
[tasks]withdepends-onpipelines; run them withrx run <task>locally and in CI, independent tasks run concurrently - Affected-only execution —
--affectedon test/ci/run selects changed packages plus their dependents, passed to one Cargo invocation via repeated-p - Workspace orchestration — dependency-aware task execution; compilation scheduling stays with Cargo
- Unified commands —
rx testuses nextest when available,rx lintruns clippy with strict defaults,rx fmtruns rustfmt - Fast builds — auto-detects
mold/lldlinkers, caches detection results persistently - CI generation —
rx init --ciwrites a GitHub/GitLab/Circle pipeline that mirrors your local one - Auto-fix everything —
rx fixapplies compiler suggestions, clippy fixes, and formatting in one step - Project config —
rx.tomlwith profiles, tasks, env vars, and config validation - Global artifact cache (opt-in) — content-addressed store with xxHash fingerprinting; disabled by default because its fingerprint does not yet cover all compilation inputs (see PRODUCT.md)
- Build stats —
rx stats showtracks build time trends across sessions - Actionable errors — failures include hints on how to fix them (25+ error codes)
- Context-aware completions — workspace members, installed targets, and tasks
curl -fsSL https://raw.githubusercontent.com/iPeluwa/rx/master/install.sh | shThis downloads a prebuilt binary for your platform (Linux, macOS, Windows/MSYS), or falls back to cargo install from source.
cargo install --path .- uses: iPeluwa/rx@v1
with:
command: ci# Bash (includes dynamic completions for workspace members, targets, tasks)
rx completions bash >> ~/.bashrc
# Zsh
rx completions zsh >> ~/.zshrc
# Fish
rx completions fish > ~/.config/fish/completions/rx.fish
# PowerShell
rx completions powershell >> $PROFILEcd my-rust-project
rx init # generate rx.toml (add --ci for a matching CI workflow)
rx ci # run the full pipeline locally| Command | Description |
|---|---|
rx init |
Generate rx.toml with smart defaults |
rx init --migrate |
Auto-detect project settings from existing tools |
rx init --ci |
Also generate .github/workflows/ci.yml |
rx config |
Show resolved configuration |
rx build |
Build with fast linker |
rx build --target <triple> |
Cross-compile for a target triple |
rx check |
Type-check without building (fast feedback) |
rx test |
Run tests (nextest if available) |
rx test --affected |
Only test packages changed since base ref |
rx fmt |
Format code |
rx lint |
Lint with clippy |
rx fix |
Auto-fix everything (compiler + clippy + fmt) |
rx ci |
Run full CI pipeline locally |
rx graph |
Show the workspace dependency graph |
rx run <task> |
Run a task (built-in or from [tasks]), with its dependencies |
rx run |
List available tasks |
rx ws list/graph/run/exec |
Workspace orchestration |
rx cache status/gc/purge |
Manage the global artifact cache |
rx clean |
Clean build artifacts |
rx doctor |
Check your development environment |
rx stats show/clear |
View or clear build time statistics |
rx completions <shell> |
Generate shell completions |
| Flag | Description |
|---|---|
--quiet / -q |
Suppress non-error output |
--verbose / -v |
Show extra detail (cache paths, timing, etc.) |
--profile <name> |
Use a config profile (e.g. --profile ci) |
All commands support these flags. For example:
rx --quiet build --release # silent build
rx --verbose test # show timing and debug info
rx --profile ci test # use CI profile overridesRun rx init to generate an rx.toml. Smart defaults are applied — a ci task pipeline is defined, and if mold is available it's set as the default linker. Unknown keys in rx.toml produce a warning so typos don't silently fail.
Use rx init --migrate to auto-detect your project's existing tools (linkers, nextest, Makefiles, benchmarks, error handling crates) and generate a tailored config.
[build]
linker = "auto" # "auto", "mold", "lld", or "system"
rustflags = [] # extra RUSTFLAGS
cache = false # opt-in global artifact cache (see PRODUCT.md)
jobs = 0 # parallel jobs (0 = auto)
incremental_link = true # enable incremental linking optimizations
[test]
runner = "auto" # "auto", "nextest", or "cargo"
extra_args = []
[lint]
severity = "deny" # "deny", "warn", or "allow"
extra_lints = [] # e.g. ["clippy::pedantic"]
[fmt]
extra_args = []
[tasks]
bench = "cargo bench"
[tasks.ci]
depends-on = ["fmt", "lint", "test", "build"]
[env]
RUST_BACKTRACE = "1"Override settings per context with [profile.<name>]:
[profile.ci]
build = { cache = false, jobs = 2 }
lint = { severity = "deny" }
test = { runner = "nextest" }
env = { CI = "true" }Use with rx --profile ci build.
Config is resolved by merging ~/.rx/config.toml (global) with the project's rx.toml. Project values override global.
Every pipeline in rx runs through one task executor. A task is a shell command, an rx built-in (fmt, lint, test, build, check), or a group of dependencies:
[tasks]
bench = "cargo bench"
[tasks.docs]
command = "cargo doc --no-deps"
[tasks.ci]
depends-on = ["fmt", "lint", "test", "build"]rx run ci # run the ci task and its dependency graph
rx run bench -- --save # extra args append to the task's command
rx run # list every available task
rx ci # exactly `rx run ci`Independent tasks in the same dependency wave run concurrently (with captured output so they don't interleave). Dependency cycles and unknown task names are rejected with a clear error. As tasks, the built-ins have CI semantics — the fmt task checks formatting rather than rewriting files (the rx fmt command still formats in place). Defining your own task with a built-in's name overrides it. Legacy [scripts] entries still work and are treated as tasks without dependencies.
rx test --affected # test packages changed since HEAD~1
rx ci --affected # run the ci pipeline against affected packages
rx run lint --affected # any task, scoped to affected packages
rx run deploy --affected --base mainChanged files from git diff are mapped to workspace members, then the set is expanded to transitive dependents — a change in core also selects everything that depends on core. Resolution happens once; the result is passed to a single Cargo invocation as repeated -p selections (never one Cargo process per member). If nothing relevant changed, the pipeline is skipped entirely.
Shell tasks see the selection as the RX_AFFECTED_PACKAGES environment variable (space-separated), so custom tasks can scope themselves too.
For Cargo workspaces, rx ws provides dependency-aware execution:
rx ws list # list all workspace members
rx graph # show dependency graph (alias for rx ws graph)
rx ws run build # single `cargo build --workspace` from the root
rx ws run test --release # single `cargo test --workspace --release`
rx ws exec "wc -l src/*.rs" # run a shell command in each member directoryrx ws run issues one Cargo invocation with --workspace — Cargo already schedules independent crates in parallel, so rx does not recreate that with one process per member. rx ws exec runs in each member directory in dependency order (topological sort).
rx keeps an opt-in, content-addressed artifact cache at ~/.rx/cache (build.cache = true to enable). Its fingerprint does not yet cover all compilation inputs — see PRODUCT.md for the exact limits and why it is off by default. For compiler-level caching, use sccache; Cargo owns target/.
rx cache status # show cache size and artifact count
rx cache gc # remove artifacts older than 30 days
rx cache purge # delete the entire cache
rx clean --gc # clean local target/ and GC global cache
rx clean --all # clean all workspace member target/ directoriesrx (single binary, MSRV 1.85.0)
├── cli/ CLI definition (clap derive) with lazy config loading + profiles
├── config/ rx.toml parsing, global/project merge, profiles, validation
├── build/ cargo build with fast linker, cross-compilation, incremental linking
├── cache/ opt-in content-addressed store (xxHash, atomic writes, reflink)
├── cargo_output/ cargo JSON output parser with error hints
├── workspace/ dependency graph via cargo metadata, topo sort (Kahn's)
├── affected/ git-diff-based affected package detection
├── ci/ + ci_gen/ local CI pipeline + CI workflow generation
├── task/ task graph + runner: [tasks], depends-on, concurrency
├── completions/ shell completions + context-aware dynamic completions
├── output/ colored output, timing, verbosity control
├── stats/ build time tracking and statistics
├── hints/ error code hints surfaced next to cargo output
├── migrate/ auto-detection and config generation from existing projects
└── doctor/ development environment checks
Use rx in your CI with the official GitHub Action:
- uses: iPeluwa/rx@v1
with:
version: latest # rx version to install
command: ci # rx command to run
cache: true # cache Cargo artifacts
rust-toolchain: stable # Rust toolchain to installcargo test| Suite | Coverage |
|---|---|
cache_tests |
Fingerprinting, cache hit/miss, store/restore |
cli_tests |
CLI parsing, including rejection of removed commands |
config_tests |
Config loading, merging, profiles, serialization |
integration_tests |
End-to-end: init, build, test, fmt, doctor, flags |
workspace_tests |
Topo sort, cycle detection |
CI runs on every push: check, test (ubuntu + macos), clippy, fmt, and MSRV verification.
MIT — see LICENSE.