Introduction
Rust has earned its reputation as one of the most powerful languages for systems-level programming — memory-safe, blazingly fast, and built with concurrency in mind from day one. That combination makes it a natural fit for command-line tools, where you want the control of a low-level language without constantly worrying about segfaults or data races.
In this guide, we'll build a simple but functional CLI application in Rust — one that starts instantly and runs efficiently, the kind of snappy performance that feels almost as satisfying as flipping on a neon sign and watching it light up immediately, no delay, no flicker.
Why Rust for CLI Applications?
A few reasons Rust keeps showing up in the CLI tooling space:
- Performance — Rust compiles to native machine code and consistently benchmarks close to C/C++, with none of the runtime overhead you get from interpreted languages.
- Memory Safety — The ownership and borrowing system catches memory issues at compile time, so there's no garbage collector pausing your program mid-execution.
- Fearless Concurrency — Rust's type system prevents data races at compile time, which makes writing multi-threaded CLI tools far less error-prone than in most languages.
- Excellent Tooling — Cargo handles dependency management, building, testing, and publishing in one coherent workflow, which makes the whole development experience feel refreshingly modern.
Getting Started
1. Install Rust
The recommended way to install Rust is through rustup, which also manages toolchain updates:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Confirm it installed correctly:
rustc --version
2. Create a New Project
Cargo scaffolds new projects with sensible defaults:
cargo new my_cli_app
cd my_cli_app
This gives you a ready-to-build project with a Cargo.toml manifest and a src/main.rs entry point.
3. Write a Minimal CLI
Open src/main.rs and start simple:
fn main() {
println!("Hello, Rust CLI!");
}
Run it with:
cargo run
Nothing fancy yet — but notice how fast that comes back. No interpreter warming up, no import resolution. It just runs.
4. Parsing Command-Line Arguments
Real CLI tools need arguments, flags, and options. Rather than hand-rolling a parser, the community has largely standardized on clap — it's well-maintained, ergonomic, and supports a clean derive-macro syntax.
Add it to Cargo.toml:
[dependencies]
clap = { version = "4.0", features = ["derive"] }
Update main.rs:
use clap::Parser;
#[derive(Parser)]
#[command(name = "my_cli_app", about = "A simple Rust CLI example")]
struct Args {
/// Name to greet
#[arg(short, long)]
name: String,
}
fn main() {
let args = Args::parse();
println!("Hello, {}!", args.name);
}
Run it:
cargo run -- --name John
Clap also gives you --help output automatically, generated from your struct definitions — a small thing, but it makes your tool feel finished rather than half-built.
5. Building for Release
Debug builds prioritize compile speed over runtime speed. For actual usage, always build in release mode:
cargo build --release
The optimized binary lands in target/release/. It's worth comparing debug vs. release builds on a larger workload — the difference in execution speed is often dramatic, and the release binary starts up just as instantly as a sign flipping on in a dark room — no lag, no waiting.
Where to Go From Here
This is intentionally a minimal starting point. A few natural next steps if you want to take it further:
-
Subcommands — clap supports nested subcommands (
myapp scan,myapp report, etc.) for tools with multiple modes of operation. -
Config files — crates like
serde+tomllet you load persistent settings instead of requiring every flag on every run. -
Concurrency — for I/O-heavy or CPU-bound CLI tools,
rayon(data parallelism) ortokio(async I/O) can meaningfully cut execution time. -
Better error messages —
anyhowormietteturn raw Rust errors into readable, user-friendly output.
Conclusion
You've now got a working CLI application in Rust, backed by clap for argument parsing and Cargo for building a release-optimized binary. It's a small example, but it demonstrates the core loop you'll use in almost every Rust CLI project you build going forward.
What made Rust worth learning for me wasn't just the raw speed — it's that speed paired with safety. You get performance that feels effortless once compiled, the way a well-made neon sign just glows steadily without a second thought — but you get there through a compiler that actually catches your mistakes before your users do.
Happy coding.
Top comments (0)