New Rust Project
Use this workflow when creating or configuring a new Rust crate, workspace, CLI, library, service, or application.
Guideline Routing
Always load the pages for house style, code classification, edition and MSRV, rustfmt, lints, Cargo, testing, CI tooling, and unsafe policy.
For a greenfield multi-crate application, also load application workspace architecture. Load async, logging, public API, and error pages only when those surfaces apply.
Workflow
- Identify the project shape: library, application, CLI, service, test support crate, or mixed workspace.
- Make the sync-vs-async posture explicit before adding async dependencies; async projects use Tokio.
- Prefer a workspace when multiple crates share version, edition, dependencies, lints, or profiles.
- Set Rust 2024 and
rust-version = "1.85"unless the project already has different constraints. - Add pinned rustfmt configuration and use
nightly-2026-04-14for formatting. - Add curated workspace lints and tailor project-specific
clippy.tomlguardrails before copying async/blocking disallow rules. - Place tests according to behavior and risk: focused unit tests near local logic and integration tests around public workflows.
- Use
cargo nextest run --workspace --all-targets --all-featuresas the normal workspace test runner. - Skip doctests unless the project explicitly opts into maintaining rustdoc examples.
- Add dependencies only for an identified need.
- Verify the project with the configured commands before handing it off.
Cargo Baseline
Use a workspace when multiple crates share package, lint, dependency, or profile policy:
[workspace]
members = ["crates/*"]
resolver = "3"
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
[workspace.lints.rust]
unsafe_code = "deny"
unreachable_pub = "warn"
[workspace.lints.clippy]
pedantic = { level = "warn", priority = -2 }
allow_attributes_without_reason = "warn"
implicit_hasher = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
module_name_repetitions = "allow"
must_use_candidate = "allow"
similar_names = "allow"
struct_excessive_bools = "allow"
too_many_arguments = "allow"
too_many_lines = "allow"
cast_precision_loss = "allow"
doc_markdown = "allow"
print_stdout = "warn"
print_stderr = "warn"
dbg_macro = "warn"
empty_drop = "warn"
empty_structs_with_brackets = "warn"
disallowed_methods = "deny"
exit = "warn"
get_unwrap = "warn"
unwrap_used = "deny"
rc_buffer = "warn"
rc_mutex = "warn"
rest_pat_in_fully_bound_structs = "warn"
use_self = "warn"
wildcard_imports = "warn"
absolute_paths = "warn"
Workspace lint inheritance is opt-in per member crate: every member crate must set [lints] workspace = true in its own Cargo.toml, or the workspace lint tables do nothing.
[package]
name = "example-crate"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
[lints]
workspace = true
For a single crate, put the same package fields and lint tables in the crate’s Cargo.toml instead of a workspace root, renaming the tables to [lints.rust] and [lints.clippy]; copied [workspace.lints.*] tables do nothing in a standalone manifest.
For async projects, add Tokio deliberately to the package or workspace dependencies:
tokio = { version = "1", features = ["full"] }
rustfmt Baseline
Use this rustfmt.toml at the project root:
edition = "2024"
style_edition = "2024"
max_width = 100
comment_width = 80
group_imports = "StdExternalCrate"
imports_granularity = "Module"
use_field_init_shorthand = true
merge_derives = true
overflow_delimited_expr = true
format_code_in_doc_comments = true
format_macro_matchers = true
normalize_doc_attributes = true
wrap_comments = true
struct_field_align_threshold = 20
enum_discrim_align_threshold = 20
Install the pinned formatter, the MSRV toolchain, and the test runner used by the verification commands:
rustup toolchain install nightly-2026-04-14 --profile minimal --component rustfmt
rustup toolchain install 1.85.0 --profile minimal
cargo install cargo-nextest --locked
Optional Clippy Guardrails
Use clippy.toml for project-specific architectural guardrails. For async projects, review rules like these before copying them:
allow-unwrap-in-tests = true
allow-unwrap-types = ["std::sync::LockResult"]
disallowed-methods = [
{ path = "std::thread::sleep", reason = "Prefer tokio::time::sleep on Tokio paths; document intentional blocking sleeps with #[expect(clippy::disallowed_methods, reason = \"...\")]", replacement = "tokio::time::sleep" },
{ path = "std::thread::spawn", reason = "Prefer Tokio task APIs on async paths; document intentional dedicated OS threads with #[expect(clippy::disallowed_methods, reason = \"...\")]" },
{ path = "std::process::Command::new", reason = "Prefer tokio::process::Command on Tokio paths; document intentional synchronous subprocesses with #[expect(clippy::disallowed_methods, reason = \"...\")]" },
]
disallowed-types = [
{ path = "std::io::Read", reason = "Blocking trait; prefer tokio::io::AsyncReadExt on Tokio paths. Document intentional sync I/O with #[expect(clippy::disallowed_types, reason = \"...\")]" },
{ path = "std::net::TcpStream", reason = "Blocking socket; prefer tokio::net::TcpStream on Tokio paths. Document intentional sync networking with #[expect(clippy::disallowed_types, reason = \"...\")]" },
]
Verification Commands
Use these commands as the default new-project validation set:
cargo +nightly-2026-04-14 fmt --check --all
cargo clippy --locked --workspace --all-targets --all-features -- -D warnings
cargo nextest run --workspace --all-targets --all-features
cargo +1.85.0 check --workspace --all-targets --all-features
If the project intentionally maintains doctests, add:
cargo test --doc --workspace --all-features
Avoid
- Do not add async casually; document the project posture first.
- Do not add every standard dependency to every project by default.
- Do not copy Tokio-specific Clippy guardrails into sync projects.
- Do not create broad preludes, public facades, or feature flags before the project needs them.
- Do not lower
unsafe_code = "deny"unless the new crate’s purpose requires unsafe code. - Do not impose test placement quotas by source file; test behavior at the level where it is observable.