Content
# rust-doctor
<p align="center">
<a href="https://crates.io/crates/rust-doctor"><img alt="Crates.io" src="https://img.shields.io/crates/v/rust-doctor?logo=rust"></a>
<a href="https://www.npmjs.com/package/rust-doctor"><img alt="npm" src="https://img.shields.io/npm/v/rust-doctor?logo=npm"></a>
<a href="https://docs.rs/rust-doctor"><img alt="docs.rs" src="https://img.shields.io/docsrs/rust-doctor?logo=docsdotrs&label=docs.rs"></a>
<a href="https://github.com/ArthurDEV44/rust-doctor/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/ArthurDEV44/rust-doctor/actions/workflows/ci.yml/badge.svg"></a>
<a href="https://crates.io/crates/rust-doctor"><img alt="Downloads" src="https://img.shields.io/crates/d/rust-doctor?label=downloads"></a>
<a href="#license"><img alt="License" src="https://img.shields.io/crates/l/rust-doctor"></a>
<img alt="MSRV" src="https://img.shields.io/badge/MSRV-1.85-blue?logo=rust">
</p>
**The one-command health check for your Rust project.** rust-doctor scans for security, performance, correctness, architecture, and dependency issues, then folds everything into a single 0–100 score with diagnostics you can act on.
It runs `cargo clippy`, `cargo-audit`, `cargo-deny`, `cargo-geiger`, and 19 custom AST rules in one pass, and ships as a CLI, a library crate, an [MCP](https://modelcontextprotocol.io/) server, an npm package, and a GitHub Action — so it works in your terminal, your CI, and inside Claude Code, Cursor, or any MCP agent.
```console
$ rust-doctor # rust-doctor scanning its own codebase
◠ ◠ rust-doctor
▽ 99 / 100 Great
████████████████████████████████████████
Security 99 · Reliability 99 · Maintainability 100 · Performance 99 · Dependencies 99
✓ 0 errors ⚠ 44 warnings ℹ 42 infos · 60 files scanned in 32.9s
```
## Quickstart
No Rust toolchain required — `npx` downloads a pre-built native binary for your platform:
```bash
npx rust-doctor # scan the current directory and print the score
```
Prefer cargo? `cargo install rust-doctor`. Want it in your AI agent? `npx rust-doctor setup`. Other formats are in [Installation](#installation).
### See it in action →
https://github.com/user-attachments/assets/6766a5d8-9a47-4eb8-892e-76c1a23eb122
## Where it fits
Rust already has excellent point tools. rust-doctor runs them together, adds rules they don't cover, and turns the result into one number you can track over time.
| You're using | It gives you | rust-doctor adds |
|---|---|---|
| `cargo clippy` | 700+ built-in lints | Category + severity mapping, 19 custom AST rules (security, async, framework, architecture), and a single 0–100 score |
| `cargo audit` / `cargo deny` | CVE and supply-chain checks | One pass that also runs clippy, geiger, and machete — skipping gracefully when a tool isn't installed |
| Separate CI steps | Each tool's own output | One command with `--json`, `--sarif`, `--diff`, `--score`, and PR comments |
| Claude Code / Cursor | Code generation | An MCP server and a slash-command skill, so the agent scans, scores, and fixes as it writes |
## Features
- **700+ clippy lints** with explicit severity overrides and category mapping
- **19 custom AST rules** via [syn](https://crates.io/crates/syn): error handling, performance, security, async, architecture, and framework anti-patterns
- **Async anti-pattern detection**: blocking calls and `block_on` inside an async context
- **Framework-aware rules**: tokio, axum, actix-web — only run when the dependency is present
- **Supply-chain auditing**: CVEs via `cargo-audit`, bans/licenses via `cargo-deny`, unsafe via `cargo-geiger`, unused deps via `cargo-machete`
- **A 0–100 health score** across five weighted dimensions, with an ASCII doctor that reacts to the result
- **MCP server**: 4 read-only tools + 2 expert audit prompts for Claude Code, Cursor, Windsurf, or any MCP client
- **Diff mode**: `--diff` scans only changed files for fast CI feedback
- **Workspace support**: scan every crate or pick specific members
- **Inline suppression**: `// rust-doctor-disable-next-line <rule>`
- **Output modes**: terminal, `--json`, `--score` (bare integer for CI), `--sarif` (GitHub code scanning)
- **`--fix`**: apply machine-applicable fixes to source files
- **Setup wizard**: `rust-doctor setup` auto-detects Claude Code, Cursor, and Windsurf and wires up MCP or installs the skill in one command
- **Distributed everywhere**: CLI binary, library crate, MCP server, npm package, and GitHub Action
## Installation
### npm / npx (recommended for MCP users)
```bash
npx rust-doctor --mcp
```
Or install globally:
```bash
npm install -g rust-doctor
```
This downloads a pre-built native binary for your platform — no Rust toolchain required.
### cargo install (from source)
```bash
cargo install rust-doctor
```
### cargo binstall (pre-built binary)
```bash
cargo binstall rust-doctor
```
### Shell installer (Linux/macOS)
```bash
curl -fsSL https://github.com/ArthurDEV44/rust-doctor/releases/latest/download/install.sh | bash
```
### PowerShell installer (Windows)
```powershell
irm https://github.com/ArthurDEV44/rust-doctor/releases/latest/download/install.ps1 | iex
```
### GitHub Releases
Download pre-built binaries from [GitHub Releases](https://github.com/ArthurDEV44/rust-doctor/releases).
Available platforms:
- `x86_64-unknown-linux-gnu`
- `aarch64-unknown-linux-gnu`
- `x86_64-apple-darwin`
- `aarch64-apple-darwin`
- `x86_64-pc-windows-msvc`
## Usage
```bash
# Scan current directory
rust-doctor
# Scan a specific directory
rust-doctor /path/to/project
# Get bare score for CI
rust-doctor --score
# JSON output
rust-doctor --json
# Scan only changed files
rust-doctor --diff
# Scan against a specific branch
rust-doctor --diff main
# Fail CI on errors
rust-doctor --fail-on error
# Scan specific workspace members
rust-doctor --project core,api
# Verbose output with file:line details
rust-doctor --verbose
# Install missing external tools (cargo-deny, cargo-audit, etc.)
rust-doctor --install-deps
# Run as MCP server
rust-doctor --mcp
# Setup wizard — configure AI agents automatically
rust-doctor setup
```
## Exit Codes
rust-doctor returns distinct exit codes so CI pipelines can tell a quality-gate
failure apart from a crash:
| Code | Meaning |
|------|---------|
| `0` | Success — scan completed and all quality gates passed |
| `1` | Setup error — MCP server, setup wizard, or `--install-deps` failed |
| `2` | Scan error — project discovery/compile failure or output rendering failed |
| `3` | Quality gate failed — score below `[score] fail_below`, or `--fail-on` threshold reached |
Gate the build on a quality failure without masking a crash:
```bash
rust-doctor --fail-on error
if [ $? -eq 3 ]; then
echo "Quality gate failed"
exit 1
fi
```
## AI Agent Setup (recommended)
The fastest way to integrate rust-doctor with your AI coding agent:
```bash
npx rust-doctor@latest setup
```
The wizard auto-detects installed agents (Claude Code, Cursor, Windsurf) and lets you choose:
- **CLI + Skills** (default) — installs a `SKILL.md` that teaches your agent to use the rust-doctor CLI with deep analysis capabilities
- **MCP Server** — configures the `rust-doctor --mcp` stdio server in your agent's config file
The wizard handles detection, configuration, and verification in one command. For manual setup, see the sections below.
## MCP Server
rust-doctor includes a built-in [Model Context Protocol](https://modelcontextprotocol.io/) server, allowing AI coding assistants to scan and analyze Rust projects directly.
### Tools
| Tool | Description |
|------|-------------|
| `scan` | Scan a Rust project for code health issues. Returns diagnostics with a 0–100 health score. |
| `score` | Get the health score (0–100) of a Rust project as a single integer. |
| `explain_rule` | Get a detailed explanation of a rule: what it checks, why it matters, and how to fix violations. |
| `list_rules` | List all available rules with their categories and severities. |
All tools are read-only (`readOnlyHint: true`).
### Prompts
| Prompt | Description |
|--------|-------------|
| `deep-audit` | Comprehensive 6-phase expert audit: codebase exploration, static analysis, deep code review (51-item checklist), best practices research, synthesis report, and remediation choices (implement all / generate PRD / manual). |
| `health-check` | Quick scan + prioritized remediation plan (P0–P3) + fix workflow. |
### Claude Code
**Automatic setup (recommended):**
```bash
rust-doctor setup # detects Claude Code and configures MCP or installs skill
```
**Or one-command MCP install:**
```bash
claude mcp add --transport stdio rust-doctor -- npx -y rust-doctor --mcp
```
**Or via Claude Code plugin:**
```
/plugin install rust-doctor@ArthurDEV44/rust-doctor
```
**Or add manually** to your `~/.claude/settings.json`:
```json
{
"mcpServers": {
"rust-doctor": {
"command": "rust-doctor",
"args": ["--mcp"]
}
}
}
```
**Or share with your team** via `.mcp.json` in your project root (committed to git):
```json
{
"mcpServers": {
"rust-doctor": {
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
```
### Cursor
Add to your `.cursor/mcp.json`:
```json
{
"mcpServers": {
"rust-doctor": {
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
```
### VS Code
Add to your `.vscode/settings.json`:
```json
{
"mcp": {
"servers": {
"rust-doctor": {
"type": "stdio",
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
}
```
### Windsurf
Add to your `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"rust-doctor": {
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
```
### Other MCP clients
rust-doctor uses stdio transport. Any MCP client that supports stdio can connect by running `rust-doctor --mcp`.
Built with [rmcp](https://crates.io/crates/rmcp) v1.x (official Rust MCP SDK).
## Claude Code Skill (no MCP required)
If you prefer slash commands over MCP servers, rust-doctor ships a Claude Code skill.
**Automatic install (recommended):**
```bash
rust-doctor setup # choose "CLI + Skills", select Claude Code
```
**Or via npx:**
```bash
npx skills add https://github.com/ArthurDEV44/rust-doctor --skill rust-doctor
```
**Or copy manually:**
```bash
cp -r skills/rust-doctor/ ~/.claude/skills/rust-doctor/
```
**Usage:**
```
/rust-doctor # scan current project
/rust-doctor --diff # scan changed files only
/rust-doctor --fix # scan + apply fixes
/rust-doctor --plan # scan + remediation plan
/rust-doctor src/ # scan a specific directory
```
The skill runs the `rust-doctor` CLI under the hood, parses the output, categorizes findings by priority, and provides actionable fix guidance with before/after code.
## GitHub Actions
```yaml
- uses: ArthurDEV44/rust-doctor@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
fail-on: warning
```
The action posts a PR comment with the health score, error/warning counts, and top diagnostics.
## Configuration
Create a `rust-doctor.toml` in your project root, or add `[package.metadata.rust-doctor]` to your `Cargo.toml`:
```toml
# rust-doctor.toml
verbose = false
fail_on = "none"
[ignore]
rules = ["excessive-clone", "string-from-literal"]
files = ["**/generated/**", "tests/**"]
```
CLI flags override config file values.
## Inline Suppression
```rust
// rust-doctor-disable-next-line unwrap-in-production
let value = some_option.unwrap();
let x = risky_call(); // rust-doctor-disable-line
```
## Rules
### Custom AST Rules (19 rules) — heuristic
These rules analyze the syntax tree only (via `syn`): no type resolution, no
macro expansion. They run fast and offline, but emit a **heuristic** signal, not
a type-checked verdict — calibrate confidence accordingly. Findings are tagged
`heuristic` in `--json` and SARIF output, and marked `~heuristic` in the
terminal. Rules flagged ⚠ have known structural blind spots (see below).
| Category | Rule | Severity |
|----------|------|----------|
| Error Handling | `unwrap-in-production` ⚠ | Warning |
| Error Handling | `panic-in-library` | Error |
| Error Handling | `box-dyn-error-in-public-api` | Warning |
| Error Handling | `result-unit-error` | Warning |
| Performance | `excessive-clone` | Warning |
| Performance | `string-from-literal` | Info |
| Performance | `collect-then-iterate` | Warning |
| Performance | `large-enum-variant` ⚠ | Warning |
| Performance | `unnecessary-allocation` | Warning |
| Architecture | `high-cyclomatic-complexity` | Warning |
| Security | `hardcoded-secrets` | Error |
| Security | `unsafe-block-audit` | Warning |
| Security | `sql-injection-risk` ⚠ | Error |
| Async | `blocking-in-async` ⚠ | Error |
| Async | `block-on-in-async` | Error |
| Framework | `tokio-main-missing` | Error |
| Framework | `tokio-spawn-without-move` | Error |
| Framework | `axum-handler-not-async` | Warning |
| Framework | `actix-blocking-handler` | Warning |
#### Known heuristic limitations (⚠)
Without type information these rules have documented blind spots. They're still
worth surfacing, but a finding is a prompt to look, not a confirmed defect:
- `unwrap-in-production` — matches `.unwrap()`/`.expect()` syntactically; cannot tell a provably-infallible unwrap from a risky one.
- `large-enum-variant` — counts a variant's fields, not its byte size; a few wide-type fields can outweigh many small ones.
- `blocking-in-async` — flags known blocking calls by name inside async fns; cannot follow calls into other functions or resolve aliased imports.
- `sql-injection-risk` — flags string-built queries heuristically; cannot confirm the interpolated value is actually untrusted input.
### Clippy Lints (75+ with overrides) — type-aware
rust-doctor runs `cargo clippy` with pedantic, nursery, and cargo lint groups. 75+ lints have explicit category and severity overrides across: Error Handling, Performance, Security, Correctness, Architecture, Cargo, Async, Style. Unlike the custom rules above, clippy resolves types against the compiler, so its findings are more authoritative — they are **not** tagged `heuristic`.
### External Tools (optional, auto-detected)
These tools are optional — rust-doctor gracefully skips any that are missing and shows which passes were skipped. Run `rust-doctor --install-deps` to install them all at once.
| Tool | Install | What it does |
|------|---------|-------------|
| clippy | `rustup component add clippy` | 700+ lint checks |
| cargo-deny | `cargo install cargo-deny` | Supply-chain checking (advisories, licenses, bans) |
| cargo-audit | `cargo install cargo-audit` | CVE vulnerability scanning |
| cargo-geiger | `cargo install cargo-geiger` | Unsafe code auditing across dependency tree |
| cargo-machete | `cargo install cargo-machete` | Unused dependency detection |
| cargo-semver-checks | `cargo install cargo-semver-checks` | Semver violation detection |
## Library Usage
rust-doctor is available as a library crate:
```rust
use std::path::Path;
// Discover the project (finds Cargo.toml, loads config)
let (dir, info, config) = rust_doctor::discovery::bootstrap_project(
Path::new("/path/to/project"), false,
)?;
// Resolve config with defaults
let resolved = rust_doctor::config::resolve_config_defaults(config.as_ref());
// Run the scan
let result = rust_doctor::scan::scan_project(&info, &resolved, false, &[], true)?;
println!("Score: {}/100 ({})", result.score, result.score_label);
```
Full API docs are on [docs.rs/rust-doctor](https://docs.rs/rust-doctor).
## Score Calculation
**Read the 0–100 score as a compass, not a thermometer.** It points you toward
the weakest dimension; it isn't a precision measurement. The per-dimension
scores (shown in the terminal box and in `--json`) carry the real signal — they
tell you *where* to act.
### How it's computed
The score is a weighted average across 5 dimensions:
| Dimension | Weight | Covers |
|-----------|--------|--------|
| Security | ×2.0 | Security rules (hardcoded secrets, unsafe, SQL injection) |
| Reliability | ×1.5 | Correctness, error handling, async, framework |
| Maintainability | ×1.0 | Architecture, style |
| Performance | ×1.0 | Performance |
| Dependencies | ×1.0 | Cargo, dependencies, advisory findings (RUSTSEC / cargo-deny) |
Each dimension starts at 100 and loses points per **unique rule** violated,
weighted by severity:
`dimension = 100 − (unique_error_rules × 1.5) − (unique_warning_rules × 0.75) − (unique_info_rules × 0.25)`
The dimension is clamped to `[0, 100]`, and the overall score is the weighted
average of the five, also clamped to `[0, 100]`.
The score counts unique rules, not occurrences — fixing one `.unwrap()` won't
move it, but removing the last `.unwrap()` drops the penalty entirely.
| Score | Label | Doctor |
|-------|-------|--------|
| 75–100 | Great | ◠ ◠ |
| 50–74 | Needs work | • • |
| 0–49 | Critical | x x |
### Known limits
- **Dimension saturation.** Penalties are linear and the floor is 0, so once a
dimension accumulates ~67 distinct Error-severity rules (`100 ÷ 1.5`), it sits
at 0 and further distinct rules in that dimension stop moving the number — it's
directional past that point, not proportional.
- **Heuristic inputs.** The custom AST rules are `syn`-only (no types, no macro
expansion), so part of what feeds the score is a heuristic signal — see
[Rules](#rules). Clippy and external-tool findings are type-aware. The score
does not currently weight heuristic vs type-aware findings differently.
- **Hand-tuned weights.** The dimension weights and severity penalties are
deliberate but not empirically calibrated; treat cross-project score
comparisons with caution.
- **Empty projects.** A directory with no Rust source files scores 100 and emits
`No Rust source files found` — expected, not a clean bill of health.
## Contributing
Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) for the dev
setup, the CI gates to run before opening a PR (`cargo fmt`, `cargo clippy`,
`cargo test`), and the guide to authoring a new rule. By participating you agree
to the [Code of Conduct](CODE_OF_CONDUCT.md). For security issues, follow the
[Security Policy](SECURITY.md) — please don't open a public issue.
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
<http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available