Configuring Clippy
clippy.toml (and Cargo.toml [lints.clippy]) tune thresholds, disallowed methods, and third-party macros so Clippy matches your team's standards.
Recipe
# clippy.toml
cognitive-complexity-threshold = 25
disallowed-methods = [
{ path = "std::env::var", reason = "use config crate" },
]When to reach for this: Banning unwrap in apps, raising complexity limits, or documenting disallowed APIs.
Working Example
# clippy.toml at workspace root
avoid-breaking-exported-api = false
too-many-lines-threshold = 120
disallowed-types = [
{ path = "std::sync::Mutex", reason = "use parking_lot::Mutex or tokio::sync::Mutex" },
]# crates/api/Cargo.toml
[lints.clippy]
unwrap_used = "deny"
expect_used = "deny"cargo clippy --workspace -- -D warningsWhat this demonstrates:
- Workspace-root
clippy.tomlapplies to all members - Per-crate
[lints.clippy]for stricter bins vs libs disallowed-methodsfails compile with custom reason- Thresholds reduce false positives on large handlers
Deep Dive
Useful clippy.toml Keys
| Key | Purpose |
|---|---|
cognitive-complexity-threshold | Function complexity cap |
too-many-arguments-threshold | Arity warning level |
disallowed-names | Ban variable names like foo |
msrv | Avoid lints requiring newer Rust than MSRV |
Third-Party Macros
third-party = { yaml = true }- Helps clippy understand DSL macros
- Reduces false positives in
serde,tracingmacros
Gotchas
- clippy.toml in wrong directory - settings ignored. Fix: place at workspace root or crate root Clippy searches upward from package manifest.
- Disallowing too much - blocks legitimate std uses. Fix: narrow paths; allow in tests via
cfg(test). - MSRV mismatch - clippy suggests APIs you cannot use. Fix: set
msrv = "1.97.0"in clippy.toml. - Different thresholds per crate without override - one size fits poorly. Fix: nested
clippy.tomlin member crate. - Relying on defaults after Rust upgrade - new lints appear. Fix: changelog review on toolchain bump.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
Only [lints.clippy] | Simple allow/deny | Need disallowed-methods list |
#[allow] only | One-off exceptions | Org-wide banned APIs |
| Custom rustc lint crate | Extreme policies | Standard app teams |
FAQs
clippy.toml vs rustfmt.toml location?
Same discovery: package dir, then ancestors to workspace root.
How ban unwrap project-wide?
unwrap_used = "deny" in app crate manifests; allow in #[cfg(test)] modules.
disallowed-methods format?
Array of { path = "...", reason = "..." } entries.
Does msrv in clippy.toml enforce MSRV?
It filters suggestions; still set rust-version in Cargo.toml for cargo enforcement.
Complexity threshold for handlers?
Axum handlers may be longer; raise threshold or extract helpers instead of blanket allow.
clippy for tests?
Same config; relax specific lints inside mod tests with inner allows.
Workspace with mixed policies?
Strict clippy.toml at root; per-crate [lints] relax for legacy crate during migration.
How test config change?
Introduce intentional violation; confirm clippy fails with expected lint name.
Third-party yaml for tracing?
Enable in clippy.toml to reduce macro expansion noise.
Update clippy.toml on clippy upgrade?
Review release notes when bumping Rust; new lints may need threshold tweaks.
Related
- Clippy - running clippy
- Lint Levels & Attributes - deny/allow
- Linting in CI - enforcement
- Coding Standards - team standards
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.