Clippy tells you what's wrong with your code. pedant tells you what your code can do.
pedant is a Rust static analyzer that combines style enforcement, capability detection, and security rules. It answers three questions about any crate: Does the code follow your style rules? What system resources does it access? Are those access patterns expected?
Style checks catch what Clippy considers too subjective — nesting depth, forbidden patterns, naming conventions. Capability detection maps every import, string literal, and attribute to concrete capabilities: network, filesystem, crypto, process exec. Gate rules evaluate capability profiles against known-suspicious patterns. An MCP server exposes all of this to AI agents as structured, queryable data.
Proof
Given this file:
$ pedant -d 2 example.rs
example.rs:3:9: match-in-if: match inside if, consider restructuring
example.rs:5:17: if-in-match: if inside match arm, consider match guard
example.rs:5:17: max-depth: nesting depth 3 exceeds limit of 2
Found 3 violation(s)
All three pass cargo check and cargo clippy.
Installation
When to Use What
pedant has several access paths. Each serves a different workflow:
| When you want to... | Use | Why |
|---|---|---|
| Block bad code as it's written | Post-hook (pedant-check.sh) |
Runs on every Edit/Write, catches violations before they enter the project |
| Check a file or crate manually | CLI (pedant src/*.rs) |
One-shot style check with immediate feedback |
| Audit what a crate can do | CLI (pedant --capabilities) |
Lists network, filesystem, crypto, etc. capabilities with evidence |
| Check for supply chain risks | CLI (pedant --gate) |
Evaluates 22 rules against capability combinations and data flows |
| Get a reproducible security snapshot | CLI (pedant --attestation) |
Capability profile + source hash + crate identity |
| Compare before/after a dependency change | CLI (pedant --diff old.json new.json) |
Shows added/removed capabilities |
| Let an AI agent query capabilities | MCP server (pedant-mcp) |
Persistent service — AI agents ask questions, get structured answers |
| Quick scan of changed files | Skill (/pedant) |
Runs capabilities + gate + style on your recent changes |
| Resolve types through aliases | --semantic flag |
Enriches any of the above with rust-analyzer type resolution |
The post-hook is enforcement (automatic, per-file). The CLI is investigation (manual, targeted). The MCP server is intelligence (persistent, queryable). See examples/ for skill and hook setup.
Usage
Linting
# Check files
# Custom depth limit
# Pipe generated code
|
Exit codes: 0 clean, 1 violations, 2 error.
To run pedant as a Claude Code hook that blocks AI-generated code on every edit:
Capability Detection
# Scan for capabilities (network, filesystem, unsafe, FFI, crypto, etc.)
# Attestation (adds source hash and crate identity for reproducibility)
# Diff two profiles or attestations
Build scripts (build.rs) are automatically discovered and analyzed. Findings from build scripts are tagged with "build_script": true in the JSON output, distinguishing compile-time capabilities from runtime capabilities.
Exit codes for --diff: 0 no changes, 1 differences found, 2 error.
Gate Rules
# Evaluate security rules against capability profile
# Combine with attestation
Gate rules flag suspicious capability combinations and data flow patterns — build scripts with network access, environment variables flowing to network sinks, lock guards held across await points. 22 built-in rules across security, quality, performance, and concurrency categories.
Exit codes: 0 clean or warn-only, 1 deny-level verdict fired, 2 error.
Configure in .pedant.toml:
[]
# Disable a rule
= false
# Override severity (deny/warn/info)
= "warn"
MCP Server
pedant-mcp is a standard MCP stdio server. The .mcp.json config works with any MCP client (Claude Code, Cursor, Zed, etc.).
Configure in Claude Code (user-scope, works in all projects):
Or project-scope via .mcp.json in the project root:
Restart Claude Code after adding. The server auto-discovers the Cargo workspace from CWD, indexes all crates, and watches for file changes. Tools:
query_capabilities— list capability findings for a crate, file, or workspacequery_gate_verdicts— evaluate gate rules for a crate or workspacequery_violations— list style violations with optional filteringsearch_by_capability— find crates matching a capability pattern (e.g., "network + crypto")explain_finding— get rationale for a specific checkaudit_crate— full security summary: capabilities, verdicts, violationsfind_structural_duplicates— detect structurally similar functions across files
See the capability detection guide for output format, supported capabilities, attestation details, and diffing.
Configuration
pedant loads config from two locations, in priority order:
- Project —
.pedant.tomlin the current directory - Global —
~/.config/pedant/config.toml(or$XDG_CONFIG_HOME/pedant/config.toml)
Project config wins. If neither exists, built-in defaults apply. Use -c <path> to specify an explicit config file.
A minimal config that catches common AI-generated patterns:
= 2
= true
= true
= true
= true
[]
= true
[]
= true
= [".unwrap()", ".expect(*)"]
[]
= true
= ["panic!", "todo!", "dbg!", "println!"]
# Relax rules for tests
[]
= 5
[]
= false
[]
= false
Scalar keys must appear before [table] sections — TOML assigns bare keys after a header to that table.
See examples/ for a full global config and a project-level override.
Checks
23 style checks across five categories. Nesting checks run by default. Everything else requires a config file.
| Category | Checks |
|---|---|
| Nesting | max-depth, nested-if, if-in-match, nested-match, match-in-if, else-chain |
| Forbidden patterns | forbidden-attribute, forbidden-type, forbidden-call, forbidden-macro, forbidden-else, forbidden-unsafe |
| Performance & dispatch | dyn-return, dyn-param, vec-box-dyn, dyn-field, clone-in-loop, default-hasher |
| Structure | mixed-concerns, inline-tests, let-underscore-result, high-param-count |
| Naming | generic-naming |
Run pedant --list-checks to see all checks, or pedant --explain <check> for detailed rationale and fix guidance.
Semantic Analysis
With the semantic feature enabled, pedant resolves types through aliases using rust-analyzer's analysis engine (ra_ap_ide). This eliminates false positives in clone-in-loop, refcounted detection, and type classification checks. It also enables data flow analysis: taint tracking (environment variables flowing to network sinks), quality checks (dead stores, discarded results), performance checks (unnecessary clones, allocation in loops), and concurrency checks (lock guards across await points).
# Build with semantic support
# Run with type resolution (requires Cargo workspace)
# Combine with gate rules for full analysis
When --semantic is active, the attestation's analysis_tier escalates from "syntactic" to "semantic" or "data_flow" depending on whether data flow findings are detected.
License
MIT or Apache-2.0, at your option.