How to use Cargo aliases

Define custom command shortcuts in the [alias] section of your .cargo/config.toml file.

When the command line gets heavy

You're building a CLI tool. Every time you want to test the release build, you type cargo build --release --features "json,logging" --target x86_64-unknown-linux-gnu. You do this ten times a day. Your fingers start to cramp. You miss a flag. The build fails. You curse the terminal. There has to be a better way. There is. Cargo lets you define aliases. You turn that monster command into cargo br.

What an alias actually is

Cargo aliases are shortcuts you define in a configuration file. You map a short name to a longer command sequence. When you run cargo <alias>, Cargo expands it and runs the full command. It's not magic. It's just text substitution before Cargo parses the subcommand.

The alias lives in .cargo/config.toml. This file sits in your project root. Cargo reads it automatically. You add an [alias] section and list your shortcuts. The left side is the name you type. The right side is the command Cargo runs.

# .cargo/config.toml
[alias]
# Map 'br' to 'build --release'.
# Cargo sees 'cargo br' and runs 'cargo build --release'.
br = "build --release"

# Map 'ca' to 'check --all-targets'.
# Useful for CI or pre-commit checks to catch errors in tests and benches.
ca = "check --all-targets"

Run cargo br in your terminal. Cargo expands the alias and compiles your project in release mode. Run cargo ca and Cargo checks all targets, including tests and benchmarks, without building them.

How Cargo processes aliases

Cargo handles aliases before it looks for subcommands. When you type cargo foo, Cargo checks if foo is a built-in subcommand like build or test. If not, it checks for an external subcommand binary named cargo-foo. If that also fails, Cargo checks the [alias] table in .cargo/config.toml.

If Cargo finds a match, it replaces the alias with the value and re-parses the command line. This expansion happens once. You cannot chain aliases. If you define a = "b" and b = "build", running cargo a fails because b is not a subcommand and aliases are not recursive.

The expansion preserves arguments. If you run cargo br --verbose, Cargo expands it to cargo build --release --verbose. The extra arguments append to the expanded command. This makes aliases flexible. You can define the base command and pass modifiers on the fly.

Convention aside: The Rust community has standardized on a few alias names. b for build, br for build --release, c for check, ca for check --all-targets, r for run, t for test. Using these names makes your project feel familiar to anyone who has touched Rust before. Deviating from these conventions adds cognitive load for contributors. Stick to the standard names. Your team will thank you.

Realistic project setup

Real projects have more complexity. You might have a workspace with multiple crates. You want to check all targets, including tests and benchmarks. Or you have a specific feature set you always enable. Aliases encode these patterns so you don't have to memorize them.

# .cargo/config.toml
[alias]
# Check everything: lib, bin, tests, benches, examples.
# Runs faster than build because it skips code generation.
ca = "check --all-targets"

# Build release with specific features.
# The quotes handle the comma-separated feature list.
# This ensures every release build includes JSON support and logging.
br = "build --release --features json,logging"

# Run clippy with strict linting.
# The '--' passes arguments to clippy itself, not cargo.
# '-D warnings' turns all warnings into errors.
cl = "clippy --all-targets -- -D warnings"

# Run a specific example in release mode.
# Useful for demos or performance testing of examples.
demo = "run --example demo --release"

Run cargo cl to lint your entire workspace. If any warning exists, the build fails. This enforces code quality. Run cargo demo to execute your example in release mode. The alias captures the exact flags you need.

Scope and sharing

Aliases live in .cargo/config.toml. This file can be in your project root or your home directory at ~/.cargo/config.toml. Project aliases only work inside that project. Global aliases work everywhere.

Project aliases are the right choice for workflows specific to the codebase. If an alias depends on project features, workspace structure, or linting rules, put it in the repo. Share it with your team. Global aliases are for personal preferences that apply to every project, like cargo t = "test".

If you rely on global aliases for project-specific workflows, you break reproducibility. A new contributor clones the repo and runs cargo br. It fails because they don't have your global alias. The build command is hidden. Put the alias in .cargo/config.toml. Commit the file. Now everyone gets the shortcut.

Convention aside: Some teams exclude .cargo/config.toml from version control. This is a mistake. The file contains build configuration. It belongs in the repo. If you have sensitive data, use environment variables or a separate secrets file. Aliases are safe to commit. They are just command strings.

Pitfalls and gotchas

Aliases are simple, but they have limits. You cannot alias a built-in subcommand. If you try to define build = "build --release", Cargo ignores the alias. Built-in subcommands always win. You can only alias names that don't conflict with existing subcommands.

Typos cause silent failures. If you type cargo bre instead of cargo br, Cargo reports error: no such subcommand. The error message doesn't mention aliases. You have to check the spelling. This is why standard names help. br is short and hard to mistype.

Quotes matter in TOML. If your alias value contains spaces, commas, or special characters, wrap it in quotes. br = build --release fails to parse. br = "build --release" works. TOML requires quotes for strings with spaces.

Aliases cannot contain logic. They are static text. You cannot write conditional aliases. You cannot check environment variables. You cannot loop. If you need dynamic behavior, you need a shell script or a Makefile. Aliases are for repetition, not logic.

Section closer: An alias is a contract. If the underlying command changes, update the alias or break the workflow. Keep the config in sync with the project.

When to use aliases versus alternatives

Cargo aliases solve a specific problem: repetitive command sequences. They are not a replacement for build systems or shell scripting. Choose the right tool based on complexity.

Use Cargo aliases for repetitive command sequences you run multiple times a day. Use Cargo aliases to encode project-specific conventions, like a standard set of features or linting flags. Use Cargo aliases to share build shortcuts with your team via version control.

Reach for shell aliases for commands that involve external tools or complex shell logic that Cargo cannot handle. Shell aliases live in your shell config and can use shell features like pipes and redirection. They are personal and not shared with the project.

Pick a Makefile or justfile for multi-step workflows that require state, loops, or conditional logic beyond simple argument passing. These tools can run multiple commands, check file timestamps, and handle dependencies. They are better for complex build orchestration.

Reach for Cargo subcommands (custom binaries named cargo-foo) when the logic requires Rust code, dynamic behavior, or integration with the Cargo API. Subcommands are full programs. They can parse arguments, read the manifest, and perform complex operations. They are overkill for simple shortcuts.

Section closer: Don't hide complexity in shell scripts. Put the alias in the repo. If the workflow is part of the project, the configuration should be too.

Where to go next