arthjean/rust-doctor
GitHub: arthjean/rust-doctor
rust-doctor 是一个 Rust 代码健康检查工具,将多种静态分析与安全审计工具整合为统一的 0–100 评分体系。
Stars: 9 | Forks: 1
# rust-doctor
**仅需一条命令即可完成 Rust 项目的健康检查。** rust-doctor 会扫描安全、性能、正确性、架构和依赖问题,然后将所有内容汇总为一个 0–100 的评分,并提供可执行的诊断信息。
它会在一次运行中执行 `cargo clippy`、`cargo-audit`、`cargo-deny`、`cargo-geiger` 以及 34 条自定义 AST 规则,并以 CLI、库 crate、[MCP](https://modelcontextprotocol.io/) server、npm 包和 GitHub Action 的形式发布,因此它可以在你的终端、CI 以及 Claude Code、Cursor 或任何 MCP agent 中运行。
```
$ 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
```
## 快速开始
```
npx rust-doctor # scan the current directory and print the score
```
更喜欢使用 cargo?可以使用 `cargo install rust-doctor`。想在你的 AI agent 中使用它?运行 `npx rust-doctor setup`。其他安装格式请参阅[安装说明](#installation)。
### 查看实际运行效果 →
https://github.com/user-attachments/assets/6766a5d8-9a47-4eb8-892e-76c1a23eb122
## 适用场景
Rust 已经拥有出色的单一功能工具。rust-doctor 将它们整合在一起,添加了它们未涵盖的规则,并将结果转化为一个你可以随时间追踪的数字。
| 你正在使用的 | 它为你提供的功能 | rust-doctor 额外带来的优势 |
|---|---|---|
| `cargo clippy` | 700+ 内置 lint | 类别与严重程度映射、34 条自定义 AST 规则(涵盖安全、async、框架、架构)以及单一的 0–100 评分 |
| `cargo audit` / `cargo deny` | CVE 和供应链检查 | 一次运行即可同时执行 clippy、geiger 和 machete —— 如果未安装某个工具,则会优雅地跳过 |
| 分离的 CI 步骤 | 每个工具各自的输出 | 一条命令支持 `--json`、`--sarif`、`--diff`、`--score` 以及 PR 评论 |
| Claude Code / Cursor | 代码生成 | MCP server 和 slash-command skill,让 agent 在编写代码时即可进行扫描、评分和修复 |
## 功能
- **700+ clippy lints**,带有明确的严重性覆盖和类别映射
- **34 条自定义 AST 规则**(通过 [syn](https://crates.io/crates/syn) 实现):错误处理、性能、安全、async、架构和框架反模式
- **Async 反模式检测**:在 async 上下文中检测阻塞调用和 `block_on`
- **感知框架的规则**:tokio、axum、actix-web —— 仅在存在相应依赖时运行
- **供应链审计**:通过 `cargo-audit` 检查 CVE,通过 `cargo-deny` 检查禁用/许可证问题,通过 `cargo-geiger` 检查 unsafe,通过 `cargo-machete` 检测未使用的依赖
- **0–100 健康评分**,涵盖五个加权维度,并配有一个会对结果做出反应的 ASCII 医生
- **MCP server**:提供 4 个只读工具 + 2 个专家审计提示词,适用于 Claude Code、Cursor、Windsurf 或任何 MCP 客户端
- **Diff 模式**:`--diff` 仅扫描更改过的文件,以实现快速的 CI 反馈
- **类别扫描**:选择一个或多个类别,跳过不相关的步骤,并获得针对该选择的范围评分
- **Workspace 支持**:扫描每个 crate 或选择特定的成员
- **行内抑制**:`// rust-doctor-disable-next-line `
- **输出模式**:终端、`--json`、`--score`(用于 CI 的纯整数)、`--sarif`(GitHub 代码扫描)
- **`--fix`**:将机器可应用的修复直接应用到源文件
- **设置向导**:`rust-doctor setup` 会自动检测 Claude Code、Cursor 和 Windsurf,并通过一条命令配置好 MCP 或安装 skill
- **全面分发**:提供 CLI 二进制文件、库 crate、MCP server、npm 包和 GitHub Action
## 安装说明
### npm / npx(推荐 MCP 用户使用)
```
npx rust-doctor --mcp
```
或者全局安装:
```
npm install -g rust-doctor
```
### cargo install(通过源码)
```
cargo install rust-doctor
```
### cargo binstall(预编译二进制文件)
```
cargo binstall rust-doctor
```
### Shell 安装程序(Linux/macOS)
```
curl -fsSL https://github.com/arthjean/rust-doctor/releases/latest/download/install.sh | bash
```
### PowerShell 安装程序(Windows)
```
irm https://github.com/arthjean/rust-doctor/releases/latest/download/install.ps1 | iex
```
### GitHub Releases
从 [GitHub Releases](https://github.com/arthjean/rust-doctor/releases) 下载预编译的二进制文件。
可用平台:
- `x86_64-unknown-linux-gnu`
- `aarch64-unknown-linux-gnu`
- `x86_64-apple-darwin`
- `aarch64-apple-darwin`
- `x86_64-pc-windows-msvc`
## 用法
```
# 扫描当前目录
rust-doctor
# 扫描特定目录
rust-doctor /path/to/project
# 获取用于 CI 的基础分数
rust-doctor --score
# JSON 输出(pretty、compact 或 atomic file)
rust-doctor --json
rust-doctor --json-compact
rust-doctor --json-out report.json
# 用于 code-scanning 消费者的 SARIF
rust-doctor --sarif
# 仅扫描已更改的文件,包括未跟踪的文件
rust-doctor --scope changed --include-untracked
# 针对特定分支进行扫描
rust-doctor --scope changed --base main
# 在出现错误时使 CI 失败
rust-doctor --blocking error
# 要求每个强制 analyzer 完成
rust-doctor --require-complete
# 扫描特定 workspace 成员
rust-doctor --project core,api
# 带有 file:line 详情的详细输出
rust-doctor --verbose
# 仅扫描安全和性能发现
rust-doctor --category security,performance
# 在终端输出中隐藏警告详情并限制 workspace 并发
rust-doctor --warnings hide --jobs 4
# 审计被内联 rust-doctor directives 隐藏的发现
rust-doctor --no-respect-inline-disables
# 安装缺失的外部工具(cargo-deny、cargo-audit 等)
rust-doctor --install-deps
# 作为 MCP server 运行
rust-doctor --mcp
# 设置向导 —— 自动配置 AI agents
rust-doctor setup
# 检查有效规则或解释某个源码位置
rust-doctor rules list --category security
rust-doctor why src/lib.rs:42
# 报告 binary、toolchain、target 和 OS 版本,无需构建项目
rust-doctor version
```
### 输出约定
终端诊断信息会写入 stderr,而评分框会写入 stdout。`--score` 会向 stdout 写入一个纯整数。`--json`、`--json-compact` 和 `--sarif` 会向 stdout 写入机器可读的输出;而 `--json-out` 则会以原子操作方式将 JSON 写入到选定的文件中。
`--score`、`--sarif`、`--json` 和 `--json-compact` 是互斥的。`--json-out` 可以与 `--json` 或 `--json-compact` 组合使用,但与 `--score` 和 `--sarif` 冲突。`--color` 和 `--no-color` 仅影响终端渲染,如果两者同时显式指定则会发生冲突。
### 类别扫描
`--category` 接受以逗号分隔的选项,可选自 `error-handling`、
`performance`、`security`、`correctness`、`architecture`、`dependencies`、
`async`、`framework`、`cargo` 和 `style`。
```
rust-doctor --category security
rust-doctor --category security,dependencies --score
```
类别扫描会在分析前过滤自定义规则,并跳过
无法生成所选类别的外部执行步骤。Clippy 仍会运行,因为其
lint 注册表涵盖了多个类别。诊断信息、包评分、整体
评分以及终端评分卡都会被限制在所选类别中。
当选择了多个评分维度时,它们的标准权重
会被保留,未选择的维度将被排除在
平均值之外。
## 退出代码
rust-doctor 会返回特定的退出代码,以便 CI pipeline 能够区分
质量门失败与程序崩溃:
| 代码 | 含义 |
|------|---------|
| `0` | 成功:扫描完成,且所有质量门均已通过 |
| `1` | 设置错误:MCP server、安装程序或 `--install-deps` 失败 |
| `2` | 扫描错误:项目发现、分析或输出渲染失败 |
| `3` | 质量门失败:得分低于 `[score] fail_below` 或达到 `--blocking` 阈值 |
| `4` | 在启用了 `--require-complete` 的情况下,所需的分析未完成 |
将构建置于质量失败的限制之下,同时不掩盖崩溃:
```
rust-doctor --blocking error
if [ $? -eq 3 ]; then
echo "Quality gate failed"
exit 1
fi
```
## AI Agent 设置(推荐)
将 rust-doctor 与你的 AI 编程 agent 集成的最快方法:
```
npx rust-doctor@latest setup
```
向导会自动检测已安装的 agent(Claude Code、Cursor、Windsurf),并让你选择:
- **CLI + Skills**(默认)—— 安装一个 `SKILL.md`,教会你的 agent 使用 rust-doctor CLI 并具备深度分析能力
- **MCP Server** —— 在你的 agent 配置文件中配置 `rust-doctor --mcp` stdio server
向导通过一条命令处理检测、配置和验证。如需手动设置,请参阅以下章节。
## MCP Server
rust-doctor 包含一个内置的 [Model Context Protocol](https://modelcontextprotocol.io/) server,允许 AI 编程助手直接扫描和分析 Rust 项目。
### 工具
| 工具 | 描述 |
|------|-------------|
| `scan` | 扫描 Rust 项目的代码健康问题。返回诊断信息以及一个 0–100 的健康评分。 |
| `score` | 以单个整数的形式获取 Rust 项目的健康评分(0–100)。 |
| `explain_rule` | 获取规则的详细说明:它检查的内容、重要性以及如何修复违规。 |
| `list_rules` | 列出所有可用的规则及其类别和严重程度。 |
所有工具均为只读(`readOnlyHint: true`)。
### 提示词
| 提示词 | 描述 |
|--------|-------------|
| `deep-audit` | 全面的 6 阶段专家审计:代码库探索、静态分析、深度代码审查(51 项清单)、最佳实践研究、综合报告和补救方案选择(全部实施 / 生成 PRD / 手动处理)。 |
| `health-check` | 快速扫描 + 优先补救计划(P0–P3)+ 修复工作流。 |
### Claude Code
**自动设置(推荐):**
```
rust-doctor setup # detects Claude Code and configures MCP or installs skill
```
**或者使用一键 MCP 安装命令:**
```
claude mcp add --transport stdio rust-doctor -- npx -y rust-doctor --mcp
```
**或者通过 Claude Code 插件:**
```
/plugin install rust-doctor@arthjean/rust-doctor
```
**或者手动添加**到你的 `~/.claude/settings.json`:
```
{
"mcpServers": {
"rust-doctor": {
"command": "rust-doctor",
"args": ["--mcp"]
}
}
}
```
**或者通过项目根目录(提交到 git)的 `.mcp.json` 与你的团队共享:**
```
{
"mcpServers": {
"rust-doctor": {
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
```
### Cursor
添加到你的 `.cursor/mcp.json`:
```
{
"mcpServers": {
"rust-doctor": {
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
```
### VS Code
添加到你的 `.vscode/settings.json`:
```
{
"mcp": {
"servers": {
"rust-doctor": {
"type": "stdio",
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
}
```
### Windsurf
添加到你的 `~/.codeium/windsurf/mcp_config.json`:
```
{
"mcpServers": {
"rust-doctor": {
"command": "npx",
"args": ["-y", "rust-doctor", "--mcp"]
}
}
}
```
### 其他 MCP 客户端
rust-doctor 使用 stdio 传输。任何支持 stdio 的 MCP 客户端都可以通过运行 `rust-doctor --mcp` 进行连接。
基于 [rmcp](https://crates.io/crates/rmcp) v1.x(官方 Rust MCP SDK)构建。
## Claude Code Skill(无需 MCP)
如果你比起 MCP server 更喜欢 slash 命令,rust-doctor 提供了一个 Claude Code skill。
**自动安装(推荐):**
```
rust-doctor setup # choose "CLI + Skills", select Claude Code
```
**或者通过 npx:**
```
npx skills add https://github.com/arthjean/rust-doctor --skill rust-doctor
```
**或者手动复制:**
```
cp -r skills/rust-doctor/ ~/.claude/skills/rust-doctor/
```
**用法:**
```
/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
```
该 skill 在底层运行 `rust-doctor` CLI,解析输出,按优先级对发现进行分类,并提供带有修改前后代码对比的可执行修复指导。
## 编辑器诊断
构建二进制文件时启用编辑器 server:
```
cargo install rust-doctor --features lsp
```
VS Code 和 Cursor 扩展位于 `editors/vscode`;Zed 扩展位于 `editors/zed`。两者都会启动 `rust-doctor --lsp`,默认使用 300 毫秒的文件本地分析,公开悬停元数据和安全的抑制操作,并保持项目范围的保存时检查为可选。有关二进制文件路径和打包说明,请参阅各自的编辑器目录。
## 托管 CI
安装或预览最小权限的 GitHub 工作流:
```
rust-doctor ci install --scope baseline --blocking warning
rust-doctor ci install --dry-run
rust-doctor ci config --review-comments=true --commit-status=true
rust-doctor ci upgrade --version v1
```
`ci config` 和 `ci upgrade` 仅改变由标记拥有者管理的工作流块。`ci install --pr` 仅在本地 Git 和提供商验证成功后创建分支和 pull request。GitLab 作为仅限门控的脚手架受支持,可通过 `rust-doctor ci install --provider gitlab` 使用;评论、状态和 SARIF 依然是仅限 GitHub 的渠道。
该 Action 也可以直接配置:
```
- uses: arthjean/rust-doctor@v1
with:
scope: baseline
blocking: warning
require-complete: true
comment: true
commit-status: true
sarif: true
token: ${{ secrets.GITHUB_TOKEN }}
```
Pull requests 会在本地解析其基础,然后仅在历史记录不可用时才使用分页的 GitHub API。报告渠道独立降级:被拒绝的评论、状态或 SARIF 权限不会替代配置好的扫描门。
## 配置
在你的项目根目录下创建一个 `rust-doctor.toml`,或者在 `Cargo.toml` 中添加 `[package.metadata.rust-doctor]`:
```
# rust-doctor.toml
verbose = false
fail_on = "none"
[rules.unwrap-in-production]
severity = "error"
surfaces = ["terminal", "score", "ci-failure", "pr-comment", "sarif", "mcp"]
[categories.performance]
severity = "info"
[[path_overrides]]
pattern = "tests/**"
severity = "off"
[ignore]
files = ["**/generated/**"]
```
CLI 参数会覆盖配置文件中的值。
## 行内抑制
```
// rust-doctor-disable-next-line unwrap-in-production
let value = some_option.unwrap();
let x = risky_call(); // rust-doctor-disable-line
```
## 规则
### 自定义 AST 规则(34 条规则) - 启发式
这些规则仅分析语法树(通过 `syn`):没有类型解析,没有宏
展开。它们运行得很快且支持离线,但发出的是**启发式**信号,而不是
经过类型检查的判定结果。规范的目录是直接从 34 条规则
实现和 Clippy 注册表构建而来的。MCP 的 `list_rules` 和 `explain_rule`
会渲染该目录,并且测试会断言这些计数,因此添加规则不需要
维护第二个文档表。
#### 已知的启发式限制 (⚠)
由于缺乏类型信息,这些规则存在文档记录的盲区。它们仍然
值得展示,但产生发现只代表需要去查看,而不是确认的缺陷:
- `unwrap-in-production` —— 在语法上匹配 `.unwrap()`/`.expect()`;无法区分绝对可靠的 unwrap 与危险的 unwrap。
- `large-enum-variant` —— 计算变体的字段数量,而不是其字节大小;几个宽类型字段可能会比许多小字段带来的影响更大- `blocking-in-async` —— 在 async 函数内部按名称标记已知的阻塞调用;无法追踪到其他函数的调用或解析别名导入。
- `sql-injection-risk` —— 启发式地标记字符串构建的查询;无法确认被插值插入的值确实是不可信的输入。
### Clippy Lints(74 条带有覆盖配置) - 类型感知
rust-doctor 运行带有 pedantic、nursery 和 cargo lint 组的 `cargo clippy`。确切的 74 条 lints 被显式分配了类别和严重性覆盖,涵盖:错误处理、性能、安全、正确性、架构、Cargo、Async、风格。与上面的自定义规则不同,Clippy 会根据编译器解析类型,因此它的发现更具权威性。
### 外部工具(可选,自动检测)
这些工具是可选的 —— 如果缺少任何工具,rust-doctor 都会优雅地跳过,并显示哪些步骤被跳过了。运行 `rust-doctor --install-deps` 即可一次性安装它们。
| 工具 | 安装命令 | 作用 |
|------|---------|-------------|
| clippy | `rustup component add clippy` | 700+ 项 lint 检查 |
| cargo-deny | `cargo install cargo-deny` | 供应链检查(安全公告、许可证、禁用项) |
| cargo-audit | `cargo install cargo-audit` | CVE 漏洞扫描 |
| cargo-geiger | `cargo install cargo-geiger` | 跨依赖树的 unsafe 代码审计 |
| cargo-machete | `cargo install cargo-machete` | 未使用依赖检测 |
| cargo-semver-checks | `cargo install cargo-semver-checks` | Semver 违规检测 |
## 库用法
rust-doctor 也可作为库 crate 使用:
```
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);
```
完整的 API 文档可在 [docs.rs/rust-doctor](https://docs.rs/rust-doctor) 上找到。
## 评分计算
**请将 0–100 的得分看作一个指南针,而不是温度计。** 它为你指明
最薄弱的维度;它不是一个精确的测量值。各个维度的
评分(显示在终端框中和 `--json` 中)包含真正的信号 —— 它们会告诉你
该*在何处*采取行动。
### 它是如何计算的
该得分是 5 个维度的加权平均值:
| 维度 | 权重 | 涵盖范围 |
|-----------|--------|--------|
| 安全 | ×2.0 | 安全规则(硬编码密钥、unsafe、SQL 注入) |
| 可靠性 | ×1.5 | 正确性、错误处理、async、框架 |
| 可维护性 | ×1.0 | 架构、风格 |
| 性能 | ×1.0 | 性能 |
| 依赖 | ×1.0 | Cargo、依赖、安全公告发现(RUSTSEC / cargo-deny) |
每个维度初始分为 100,每违反一条**唯一规则**都会根据严重程度扣分:
`dimension = 100 − (unique_error_rules × 1.5) − (unique_warning_rules × 0.75) − (unique_info_rules × 0.25)`
维度得分会被限制在 `[0, 100]` 之间,整体得分是这五个维度的加权
平均值,同样也被限制在 `[0, 100]` 之间。
使用 `--category` 时,只有由所选类别代表的维度才会计入
加权平均值。从同一维度选择多个类别(
例如 `correctness` 和 `error-handling`)会将它们在该维度内违反的
唯一规则合并计算。
该得分计算的是唯一规则,而不是出现次数 —— 修复一个 `.unwrap()` 不会改变它,但移除最后一个 `.unwrap()` 会完全消除惩罚。
| 得分 | 标签 | 医生 |
|-------|-------|--------|
| 75–100 | 优秀 | ◠ ◠ |
| 50–74 | 需要改进 | • • |
| 0–49 | 严重 | x x |
### 已知局限性
- **维度饱和。** 惩罚是线性的,且下限为 0,因此一旦
某个维度累计了约 67 条不同的 Error 严重性规则(`100 ÷ 1.5`),它就会
保持在 0,该维度中进一步出现的不同规则将不再改变这个数字 —— 在那之后它是
指示性的,而非成比例的。
- **启发式输入。** 自定义 AST 规则仅基于 `syn`(无类型、无宏
展开),因此计入得分的一部分是启发式信号 —— 请参阅
[规则](#rules)。Clippy 和外部工具的发现是类型感知的。该得分
目前没有对启发式和类型感知的发现进行不同的加权。
- **手动调整的权重。** 维度权重和严重性惩罚是
深思熟虑的设计,但并未经过经验校准;请谨慎对待跨项目的得分
比较。
- **空项目。** 一个不包含 Rust 源文件的目录得分为 100,并会发出
`No Rust source files found` 的提示 —— 这是符合预期的,并不代表健康状况良好。
## 许可证
根据以下任一许可证授权
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) 或
)
- MIT license ([LICENSE-MIT](LICENSE-MIT) 或 )
由你选择。
除非你明确声明,否则根据 Apache-2.0 许可证的定义,你有意提交包含在该作品中的任何贡献,均应按上述方式获得双重许可,不附加任何额外的条款或条件。
标签:Rust, SOC Prime, 云安全监控, 依赖审查, 可视化界面, 开发工具, 网络流量审计, 通知系统, 静态分析