cargo-bless
A Cargo subcommand that checks your dependencies against blessed.rs recommendations and suggests modern alternatives.

Powered by blessed.rs curated paths · optional crates.io + GitHub intel · optional Cargo.toml‑only autofix
On crates.io: cargo-bless · Generated API docs: docs.rs/cargo-bless · Changelog: changelog.md · Repo docs: docs/
cargo-bless checks whether your Rust dependency tree is modern, boring, and defensible.
At a glance

flowchart LR
A["Cargo.toml + lock"] --> B["cargo metadata\nresolved features"]
B --> C["Built-in rules\n(blessed.rs lineage)"]
C --> D["Suggestions\n+ trust metadata"]
D --> E["TTY report or JSON"]
E --> F{{"Extras"}}
F --> G["Live intel\ncrates.io / GitHub"]
F --> H["--fix\nCargo.toml only"]
F --> I["--audit-code\nstatic scan"]
Which command should I run?
flowchart TD
Start([You are here]) --> Q{Need machine output?}
Q -->|yes| J["cargo bless --json\n(+ --fail-on=… in CI)"]
Q -->|no| R{Paste into GitHub issue?}
R -->|yes| F["cargo bless --feedback\n(root crate)"]
R -->|no| S{Want a one-screen roll-up?}
S -->|yes| Sm["cargo bless --summary"]
S -->|no| D["cargo bless\n(default full report)"]
Release framing (semver)
| Version | What it represented |
|---|---|
| 0.1.0 | Birth |
| 0.1.1–0.1.3 | Rapid hardening |
| 0.1.4 | First “people might actually try this” slice — think how does a stranger feel after running this once? |
| 0.1.7 | Rule merges fixed (embedded suggestions win over blessed cache/tooling); selective blessed cherry-picks; CI --feedback smoke |
| 0.1.8 | Blessed.rs ingest: tightened migration cues, HTML-stripped notes, regression tests aligned with upstream crates.json wording |
| 0.2.0 | --workspace / --package, --summary, --fail-on, JSON grouped per package, virtual-workspace-safe metadata parsing, clearer --fix messaging (Cargo.toml-only) |
Likely near-term forks:
- 0.2.x —
bless.toml/ severity gates refinement,--all-targets, cache-first polish.
What it does
- Scans your
Cargo.tomldependency tree (direct + transitive, with features) - Matches against a built-in rule database sourced from blessed.rs
- Detects single-crate replacements and combo optimizations (e.g. dropping
serde_jsonwhenreqwesthas thejsonfeature) - Optionally runs a built-in bullshit detector code audit for suspicious Rust complexity patterns
- Fetches live metadata from crates.io (latest version, downloads) and GitHub (last push, archived status)
- Optionally applies safe fixes to your
Cargo.tomlwith--fix(preview first with--dry-run)
What cargo-bless is not
- It is not a replacement for
cargo audit,cargo deny, or license/security policy tooling. - It is not automatic truth. Recommendations include confidence, migration risk, autofix safety, and evidence source.
- It is not a source rewriter.
--fixonly applies rules marked as safe Cargo.toml-only edits. - It is not a command to blindly run in production without reading the report.
Installation
From crates.io:
From source:
First run (copy-paste)
If the report looks sane, drop --offline to light up crates.io / GitHub intel on the colorful default run.
Usage
Multi-crate workspaces
flowchart TB
W["Workspace Cargo.toml<br/>[workspace] members"]
W --> P1["crates/foo"]
W --> P2["crates/bar"]
subgraph scan ["One cargo metadata resolve"]
P1 --> R["Per-member suggestions"]
P2 --> R
R --> F["Optional --fix per Cargo.toml"]
end
$ cargo bless --workspace --offline
🔥 cargo-bless v0.2.0
📋 Scanning dependencies…
• api v0.3.0 — 11 direct, 189 total (crates/api/Cargo.toml)
• worker v0.1.0 — 6 direct, 155 total (crates/worker/Cargo.toml)
Workspace: 2 members · 17 direct deps (sum) · 344 resolved rows (sum).
📦 api v0.3.0 (crates/api/Cargo.toml)
• [HIGH] lazy_static → std::sync::LazyLock
…
📦 worker v0.1.0 (crates/worker/Cargo.toml)
• [MED] log → tracing
…
CLI Flags
| Flag | Description |
|---|---|
--fix |
Apply Cargo.toml-only autofixes (*.toml.bak on write); never edits Rust sources |
--dry-run |
With --fix, prints the unified diff/plan — no files written, no cargo update |
--audit-code |
Bullshit detector pass merged across selected packages (sums files + alerts) |
--diff |
With cargo bless bs, audit only changed lines from git diff HEAD |
--verbose |
Show every code-audit finding instead of the trimmed summary |
--json |
Machine JSON (cargo_bless_version, workspace_scan, packages[], code_audit) |
--offline |
Skip crates.io/GitHub intel; rules + embedded data still apply |
--policy=PATH |
Use custom bless.toml policy file |
--update-rules |
Fetch latest blessed-derived rules into the cache |
--manifest-path=PATH |
Workspace or package Cargo.toml (defaults to current directory) |
--feedback |
Issue/discord block: aggregates + hotspots; root crate only (no --workspace/--package) |
--summary |
Short dep summary + pattern bullets; skips live intel; mutually exclusive with --json/--fix/--feedback/--audit-code |
--fail-on=l,m,h,c |
Fail CI when any suggestion’s impact matches (comma-separated; critical aliases high for deps today) |
--workspace |
Analyze all [workspace].members with one cargo metadata call |
--package=NAMES |
Member filter (comma-separated names) |
Picking an output mode
| Mode | Best for |
|---|---|
Default cargo bless |
Full dependency report + optional crates.io/GitHub intel |
--feedback |
GitHub issues / Discord — aggregates + code-audit hotspots (root crate only) |
--summary |
Quick roll-up — counts + deduped “crate → suggestion” lines without fetching live intel |
--json |
CI / automation — stable JSON with packages[].dependency_suggestions and nullable code_audit |
--feedback, --summary, and --json are mutually exclusive. --feedback also rejects --workspace / --package.
Pasteable feedback (--feedback)
Tried cargo-bless on a non-trivial tree? Paste cargo bless --feedback into an issue. It prints aggregate counts plus coarsely-ranked source locations (path::fn); it does not print your dependency crate list or full suggestion text. No network (skips live intel); still runs the local code audit. --manifest-path and --policy work as usual.
Example shape:
cargo-bless feedback block
version: 0.2.0
direct_deps: 46
total_deps: 624
suggestions: 2
high_impact: 1
code_audit_findings: 401
top_hotspots:
- src/main.rs::run_simulation
- src/main.rs:apply_forces
Policy File (bless.toml)
Drop a bless.toml next to your Cargo.toml to customize behavior:
# Ignore specific packages
= ["internal-crate"]
# Per-package overrides
[]
= true
= "We use lazy_static for cross-crate compatibility"
# Global settings
[]
= true
= 10
[]
= ["src/generated", "tests/fixtures"]
= ["UnwrapAbuse"]
Or pass a custom path: cargo bless --policy=custom-bless.toml
Examples & terminal gallery
Synthetic screenshots below are trimmed for readability; your tree will differ.
cargo bless --summary (paste-friendly roll-up)
🔥 cargo-bless v0.2.0
📊 Summary — scanned 1 workspace member
• my-crate — 42 direct deps, 580 total in resolve
Suggestions after policy: 7
By impact — high: 3, medium: 3, low: 1
Top patterns:
• serde_derive → serde with "derive" feature
• tracing-subscriber+parking_lot → tracing-subscriber without parking_lot
…
`--fix` changes Cargo.toml entries only — never Rust source.
Default run + --audit-code (color in a real terminal)
$ cargo bless --audit-code
🔥 cargo-bless v0.2.0
📋 Scanning dependencies...
📦 Direct dependencies (16)
• reqwest 0.12.28 [json, default-tls, ...]
• serde_json 1.0.149 [default, ...]
...
Found 16 direct deps, 317 total.
🌐 Fetching live intelligence...
🚀 Modernization report for my-project v0.1.0
• [LOW] reqwest+serde_json → reqwest with "json" feature
[HIGH confidence] [LOW risk] [autofix: Cargo.toml-only] evidence: crate docs
…
latest: v0.13.2, 64.6M recent downloads
(This sample shows only a `[LOW]` impact row — real trees often surface `[HIGH]` items too.)
🧨 Bullshit detector code audit
Scanned 8 Rust files.
🚨 Bullshit detected: 2 findings
• unwrap abuse src/main.rs:14:35
Fix: Propagate the error with ?, add context, or handle the failure explicitly.
--fix --dry-run (diff only — no writes)
$ cargo bless --fix --dry-run
🔍 Dry-run — previewing Cargo.toml edits only (no writes, no cargo update)
🔍 Dry-run: the following changes would be made:
- serde_json = "1"
Changes that would be applied:
✓ Removed `serde_json`, enabled `json` feature on `reqwest`
--json (CI shape, v0.2+ — truncated)
GitHub Actions: fail builds on high-impact suggestions
jobs:
bless:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install cargo-bless
run: cargo install cargo-bless
- name: Lint dependency choices
run: cargo bless --offline --fail-on=high
Combine with --json in a dedicated job if you want to upload artifacts rather than stare at ANSI colors.
Before / after Cargo.toml (autofix pattern)
Before
[]
= { = "0.12", = ["json"] }
= "1"
After (conceptual — cargo bless --fix)
[]
= { = "0.12", = ["json"] }
# serde_json dropped — responses use reqwest's json path
Built-in rules
Each rule carries trust metadata:
impact: how important the dependency choice may be.confidence: how strong the recommendation is.migration_risk: how likely the change is to require careful review.autofix_safety: whethercargo bless --fixmay editCargo.toml.evidence_source: where the recommendation is grounded.
| Pattern | Suggestion | Impact | Confidence | Risk | Autofix |
|---|---|---|---|---|---|
lazy_static |
std::sync::LazyLock |
High | High | Low | Manual |
once_cell |
std::sync::LazyLock / OnceLock |
High | High | Low | Manual |
memmap |
memmap2 |
High | High | Medium | Manual |
failure |
anyhow + thiserror |
High | High | Medium | Manual |
iron |
axum |
High | High | High | Manual |
structopt |
clap v4 (derive) |
Medium | High | Medium | Manual |
log |
tracing |
Medium | Medium | Medium | Manual |
chrono |
consider time |
Medium | Low | Medium | Manual |
reqwest + serde_json |
reqwest with json feature |
Low | High | Low | Cargo.toml-only |
serde_derive |
serde with derive feature |
Low | High | Low | Cargo.toml-only |
clap + clap_derive |
clap with derive feature |
Low | High | Low | Cargo.toml-only |
Rules are embedded at compile time from data/suggestions.json. PRs to add more are welcome.
How --fix works
Only suggestions marked autofix_safety = "CargoTomlOnly" are auto-fixable.
StdReplacement, Unmaintained, ModernAlternative, and ComboWin are reported but not auto-fixed by default, since they usually require source code changes or architectural judgment.
Code-audit findings are advisory in this release. --fix only edits dependency declarations in Cargo.toml; it never rewrites Rust source files.
Before any write, --fix creates a Cargo.toml.bak backup and runs cargo update afterward.
How it works
cargo_metadataparses the full resolved dependency tree with features- Rules from
data/suggestions.jsonare matched against direct deps (single-crate and combo patterns) crates_io_api::SyncClientfetches live metadata (cached to~/.cache/cargo-bless/with 1-hour TTL)reqwestchecks GitHub forpushed_at,archived, and star count- With
--audit-codeorcargo bless bs, the bullshit detector scans Rust files undersrc,tests,examples, andbenchesfor static complexity patterns toml_editapplies fixes while preserving comments and formatting
Network calls are non-fatal — if you're offline, the rule-based report still works.
Extended documentation
These files also live under docs/ in the repository (links work from GitHub and crates.io):
- Documentation index —
docs/README.md - Architecture — module map and pipeline
- CLI reference — flags and subcommands
- Contributing — build, test, release checklist
License
MIT -- see LICENSE-MIT.