arthjean/rust-doctor

GitHub: arthjean/rust-doctor

rust-doctor 是一个 Rust 代码健康检查工具,将多种静态分析与安全审计工具整合为统一的 0–100 评分体系。

Stars: 9 | Forks: 1

# rust-doctor

Crates.io npm docs.rs CI Downloads License MSRV

**仅需一条命令即可完成 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, 云安全监控, 依赖审查, 可视化界面, 开发工具, 网络流量审计, 通知系统, 静态分析