Rust Tooling
A Rust project sits in the pit lane of a Formula 1 race. The car is your code, and every two seconds a different crew member runs at it with one job and only that job. The jack lifts. The gunner spins the wheel nut. The chief engineer reads telemetry over your shoulder and yells about the line you took into turn three. Five people, one car, twenty seconds of work, and the car leaves faster than it came in. Rust ships with the same kind of crew — five separate programs, each with one job, each interchangeable. The crew is rustup, cargo, clippy, rustfmt, and rust-analyzer. Once you know which one is which, every Rust project you ever touch feels like the same pit stop.

The crew chief is rustup. The chief decides which engine the car runs on this weekend, and Rust has three engines to choose from. Stable, the one used at every race, updates every six weeks and never breaks code that worked yesterday. Beta is next week's stable, sitting in the garage so teams can shake it down. Nightly is the wild prototype, rebuilt every twenty-four hours, packed with features the rules committee has not approved yet. Brian Anderson at Mozilla wrote rustup in 2015 after watching every Rust developer juggle three compilers by hand and lose. Before rustup the tool was called multirust, and before multirust there was no tool at all — you compiled the compiler yourself from source and prayed your coworker did the same. The chief replaced all that with one command: rustup default stable, and the right engine drops in.

The pit lane runner is cargo. The runner does the actual work — every other tool is something the runner hands off to. Yehuda Katz and Carl Lerche shipped cargo in 2014, eight months before Rust hit version 1.0, because the team realized a language without a build tool was a car without wheels. Cargo is a Swiss-army-knife with the subcommands sticking out. cargo new lays out a fresh project. cargo build compiles it. cargo run builds and runs. cargo test finds every function tagged with #[test] and runs them all. cargo check is the fast cousin of cargo build that does the type checking but skips the slow code-generation step, which is what your editor runs in the background while you type. cargo add serde reaches out to crates.io, downloads the library, and writes it into Cargo.toml. You will type cargo ten times today and a thousand times by the end of the month. Every other tool in the crew is something you reach through cargo.

Open a terminal and ask each crew member who they are. The point of this exercise is not the answer — it is to see that every one of them is its own program, installed on your machine, willing to introduce itself.
println!("$ rustup show active-toolchain");
println!("stable-aarch64-apple-darwin (default)");
println!("rustc 1.92.0 (a1b2c3d4e 2026-04-15)");
println!();
println!("$ cargo --version");
println!("cargo 1.92.0 (a1b2c3d4e 2026-04-12)");
println!();
println!("$ cargo clippy --version");
println!("clippy 0.1.92 (a1b2c3d4e 2026-04-12)");
println!();
println!("$ cargo fmt --version");
println!("rustfmt 1.8.0-stable (a1b2c3d4e 2026-04-12)");
println!();
println!("$ rust-analyzer --version");
println!("rust-analyzer 1.92.0 (a1b2c3d4e 2026-04-12)");Run the binary the same way you ran the last lesson's, and you will see the kind of report you would get if you typed all five --version commands by hand. The version numbers are made up — your real machine will print whatever the latest stable shipped this week — but the shape of it is what matters. Five tools, five separate programs, one toolchain.
The third crew member is clippy, the chief engineer with the radio in one hand. Where cargo build says "your code compiles," clippy says "your code compiles and you are about to do something you will regret." Clippy is a linter — a program that reads source code and shouts about patterns it has seen go wrong before. It ships with roughly 400 of those patterns built in, organized into groups called correctness, suspicious, style, complexity, perf, and pedantic. The project started in 2014 as a side experiment by a German student named Manish Goregaokar and lived on nightly-only for years, the way every wild prototype does. Clippy graduated to stable Rust in 2018, which is when it stopped being optional in serious codebases. Run it once and watch it spot something the compiler ignored.
The fourth crew member is rustfmt, the formatter. Rustfmt does one thing: read your source file, throw out all your whitespace, and rewrite it according to one fixed style book. Four spaces for indentation. Open braces on the same line. A blank line between functions. No options worth arguing about. The reason no options matter is the bug the Rust team watched destroy every C++ project: humans spend hours arguing about where the brace goes, and the arguments produce nothing the user can see. Rustfmt ends the argument by making the style not yours. The whole company writes Rust that looks like the same person wrote it, because the same program did the typing of the spaces. Run cargo fmt once after every save and you will never think about braces again.
println!();
println!("$ cargo check");
println!(" Checking hello_world v0.1.0");
println!(" Finished `dev` profile in 0.18s");
println!();
println!("$ cargo clippy");
println!(" Checking hello_world v0.1.0");
println!("warning: this `let` binding is unused");
println!(" --> src/main.rs:2:9");
println!(" |");
println!("2 | let x = 5;");
println!(" | ^ help: if this is intentional, prefix it with an underscore: `_x`");
println!();
println!("$ cargo fmt");
println!("Diff in src/main.rs at line 1:");
println!("-fn main(){{println!(\"hi\");}}");
println!("+fn main() {{");
println!("+ println!(\"hi\");");
println!("+}}");Watch the three of them line up. cargo check is the runner asking "does this compile" and getting back yes in under a second. cargo clippy is the chief engineer pointing at the unused variable — your code compiles, but you forgot why you wrote that line. cargo fmt is the formatter rewriting the cramped one-line function into the canonical four-line shape. That sequence — check, clippy, fmt — is the loop every Rust developer runs dozens of times a day, and the loop your editor runs for you in the background. Here is the actual report your terminal would print.
$ rustup show active-toolchain
stable-aarch64-apple-darwin (default)
rustc 1.92.0 (a1b2c3d4e 2026-04-15)
$ cargo --version
cargo 1.92.0 (a1b2c3d4e 2026-04-12)
$ cargo clippy --version
clippy 0.1.92 (a1b2c3d4e 2026-04-12)
$ cargo fmt --version
rustfmt 1.8.0-stable (a1b2c3d4e 2026-04-12)
$ rust-analyzer --version
rust-analyzer 1.92.0 (a1b2c3d4e 2026-04-12)
$ cargo check
Checking hello_world v0.1.0
Finished `dev` profile in 0.18s
$ cargo clippy
Checking hello_world v0.1.0
warning: this `let` binding is unused
--> src/main.rs:2:9
|
2 | let x = 5;
| ^ help: if this is intentional, prefix it with an underscore: `_x`
$ cargo fmt
Diff in src/main.rs at line 1:
-fn main(){println!("hi");}
+fn main() {
+ println!("hi");
+}The fifth crew member is the one you never call by name. rust-analyzer is the language server — a program that sits inside your editor, parses your code the moment you stop typing, and answers the editor's questions about what type each variable is, where each function is defined, and what the error message at line 14 actually means. Aleksey Kladov started rust-analyzer in 2018 as a clean rewrite of the original Rust Language Server, called RLS, which was slow enough that most people gave up on it and went back to running cargo check by hand. The rewrite holds the whole crate in memory and answers most questions in a few milliseconds, which is fast enough that you forget it is there. Every modern Rust editor uses it — VS Code, Neovim, Zed, JetBrains RustRover. The reason you never type rust-analyzer at the command line is the editor types it for you, ten times a second, while you are looking at the code.
A question. If the editor already runs cargo check for you in the background through rust-analyzer, why does cargo check still exist as a separate command? The answer is that not every place that compiles your code is an editor. Continuous integration servers, pre-commit hooks, the script you wrote that builds a docker image — none of them load a language server. They shell out to cargo check, get the exit code, and move on. The five tools cover the five places code gets read: the chief swaps the engine, the runner does the work, the engineer flags the mistakes, the formatter standardizes the look, and the analyzer feeds the editor. Pull any one of them out and the crew is short-handed.
The crew is in place. The next bottleneck is the runner itself — what cargo build actually does between the moment you press enter and the moment a binary appears, and why the build pipeline is what makes or breaks every Rust project past a hundred files.