cargo-compatible 0.2.0

Cargo subcommand for auditing and resolving dependency graphs against a target Rust version or MSRV
Documentation

cargo-compatible

CI crates.io docs.rs MSRV License: MIT

Audit your workspace's dependency graph against any Rust version. Fix what's blocking, safely.

cargo-compatible is a Cargo subcommand that answers "does my resolved dependency graph fit the Rust version I care about?" It scans your lockfile, classifies every package as compatible, incompatible, or unknown, and offers a safe, incremental path to fix blockers — lockfile changes first, manifest edits only when necessary.

Status: v0.1 core is implemented and published on crates.io. The command surface (scan, resolve, apply-lock, suggest-manifest, explain) ships today, and the active work is performance realism, release polish, and operator trust for v0.2. See BUILD.md for the full execution plan.

Why cargo-compatible?

Managing MSRV across a workspace with dozens of dependencies is painful. You bump a dependency, CI breaks on your MSRV target, and now you're spelunking through cargo tree output to figure out which transitive dependency dragged in a newer rust-version requirement.

cargo-compatible solves this by:

  1. Scanning your current graph and classifying every resolved package as compatible, incompatible, or unknown
  2. Resolving a candidate lockfile in a sandboxed temp workspace to see if Cargo can find a better solution
  3. Explaining exactly why specific packages are blockers, with full dependency paths from your workspace members
  4. Suggesting conservative manifest changes only when a lockfile-only fix isn't enough

The lockfile-first workflow matters: changing Cargo.lock is low-risk and reversible. Changing Cargo.toml version requirements is a commitment. This tool tries the safe thing first.

Feature cargo-compatible cargo-msrv manual cargo tree
Lockfile-first workflow Yes No N/A
Sandbox resolution Yes (temp copy) No N/A
Dependency path reporting Yes No Manual
Manifest suggestions Conservative, registry-only Version bisection Manual
Mixed-workspace support Yes (per-member analysis) Limited Manual
JSON output Yes Yes No
Safety model Non-mutating by default Modifies toolchain Read-only

Install

Prerequisites

  • Rust toolchain (stable)

From crates.io

cargo install cargo-compatible

After installation, use it as cargo compatible.

From source

git clone https://github.com/dunamismax/cargo-compatible.git
cd cargo-compatible
cargo install --path .

Quick start

# See where you stand
cargo compatible scan --workspace

# Try to resolve a better lockfile
cargo compatible resolve --workspace --write-candidate .cargo-compatible/candidate/Cargo.lock

# Understand a specific blocker
cargo compatible explain serde

# If lockfile-only isn't enough, get manifest suggestions
cargo compatible suggest-manifest --package my-crate

# Apply the candidate lockfile when you're satisfied
cargo compatible apply-lock --candidate-lockfile .cargo-compatible/candidate/Cargo.lock

Commands

cargo compatible scan

Analyze the current workspace state. This is your starting point — it reads the existing lockfile and classifies resolved packages without changing anything.

cargo compatible scan --workspace
cargo compatible scan --package app --format json
cargo compatible scan --rust-version 1.70

cargo compatible resolve

Build a candidate lockfile in a temporary workspace copy. Your real workspace is never modified. Optionally save the candidate and a rendered report.

cargo compatible resolve --workspace
cargo compatible resolve --workspace --write-candidate .cargo-compatible/candidate/Cargo.lock
cargo compatible resolve --workspace --write-report report.md --format markdown

cargo compatible apply-lock

Apply a previously saved candidate lockfile to the real workspace. Requires an explicit path — no implicit lockfile rewrites.

cargo compatible apply-lock --candidate-lockfile .cargo-compatible/candidate/Cargo.lock

cargo compatible suggest-manifest

Suggest direct dependency requirement changes when lockfile-only resolution isn't enough. Dry-run by default.

cargo compatible suggest-manifest --package app
cargo compatible suggest-manifest --package app --write-manifests
cargo compatible suggest-manifest --package app --allow-major

cargo compatible explain

Explain why a specific package is present and whether it's a compatibility blocker. Shows dependency paths from your workspace members to the queried package.

cargo compatible explain serde
cargo compatible explain "serde@1.0.218"

Safety model

This tool is designed to be safe to run in any context:

  • scan never mutates user files
  • resolve runs in a temp workspace copy by default — your checkout stays untouched
  • apply-lock requires an explicit candidate lockfile path — no surprise rewrites
  • suggest-manifest is dry-run by default; --write-manifests stages and validates all edits before persisting
  • Missing rust-version metadata is treated as unknown, never silently assumed compatible
  • Path and git dependencies are analyzed and explained but never receive fabricated crates.io downgrade suggestions

Output formats

All commands support --format {human|json|markdown}:

  • human (default): readable terminal output with source labels and dependency paths
  • json: machine-readable, suitable for CI integration and downstream tooling
  • markdown: report-ready format for PRs, issues, or documentation

Architecture

┌──────────────────────────────────────────────────────────────┐
│                     cargo compatible CLI                      │
│          (clap: scan/resolve/apply-lock/suggest/explain)      │
└──────┬──────────┬──────────┬──────────┬──────────┬───────────┘
       │          │          │          │          │
  ┌────▼───┐ ┌───▼────┐ ┌───▼───┐ ┌───▼────┐ ┌───▼─────┐
  │Metadata│ │ Compat │ │Resolve│ │Manifest│ │ Explain │
  │        │ │        │ │       │ │  Edit  │ │         │
  │ cargo  │ │ graph  │ │ temp  │ │ sparse │ │ blocker │
  │metadata│ │analysis│ │sandbox│ │ index  │ │ paths   │
  └───┬────┘ └───┬────┘ └───┬───┘ └───┬────┘ └───┬─────┘
      │          │          │          │          │
      └──────────┴──────────▼──────────┴──────────┘
                      ┌──────────┐
                      │ Identity │
                      │ + Report │
                      │          │
                      │ human    │
                      │ json     │
                      │ markdown │
                      └──────────┘
  • Metadata — runs cargo metadata, identifies workspace/package scope, determines target Rust version
  • Compat — analyzes the resolved graph, classifies packages, captures dependency paths
  • Resolve — creates an isolated temp workspace, generates candidate lockfiles, diffs against current state
  • Manifest Edit — inspects sparse-index or local-registry metadata, produces conservative direct-dependency suggestions
  • Explain — assembles per-package reasoning with blocker classification and dependency-path context
  • Identity + Report — renders results in human, JSON, or Markdown form with source-aware labeling

Repository Layout

.
├── BUILD.md                          # execution manual, phase tracking, verification ledger
├── README.md                         # public-facing project description, honest status
├── AGENTS.md                         # concise repo memory for agents and contributors
├── CONTRIBUTING.md                   # development setup, coding standards, PR process
├── CHANGELOG.md                      # user-facing change history
├── SECURITY.md                       # security policy
├── LICENSE                           # MIT
├── Cargo.toml                        # single-crate package definition
├── Cargo.lock                        # repo lockfile
├── deny.toml                         # dependency-policy checks
├── .editorconfig                     # editor consistency settings
├── .github/
│   └── workflows/ci.yml              # CI gate
├── src/
│   ├── main.rs                       # binary entrypoint + opt-in tracing
│   ├── lib.rs                        # command dispatch and orchestration
│   ├── cli.rs                        # clap command surface and examples
│   ├── model.rs                      # serializable shared analysis types
│   ├── metadata.rs                   # cargo metadata loading, scope selection
│   ├── compat.rs                     # compatibility analysis and dep-path capture
│   ├── resolution.rs                 # candidate lockfile generation and diffing
│   ├── temp_workspace.rs             # temp-copy support for safe resolution
│   ├── index.rs                      # crates.io sparse-index / local-registry lookup
│   ├── manifest_edit.rs              # conservative manifest suggestion and TOML edits
│   ├── explain.rs                    # per-package explanation and blocker classification
│   ├── identity.rs                   # stable package identity labeling
│   └── report.rs                     # human, JSON, and Markdown rendering
├── tests/
│   ├── integration_cli.rs            # snapshot-backed CLI integration coverage
│   ├── version_selection.rs          # focused selection-rule coverage
│   └── fixtures/                     # deterministic sample workspaces
│       ├── missing-rust-version/
│       ├── mixed-workspace/
│       ├── path-too-new/
│       ├── virtual-workspace/
│       └── local-registry-manifest-blocker/
└── benches/
    └── large_workspace_resolver.rs   # Criterion benchmark for synthetic workspace

Current limitations

  • Manifest suggestions focus on normal direct crates.io dependencies and require locally available sparse-index or local-registry metadata
  • Feature validation does not fully reimplement Cargo feature resolution semantics
  • resolve favors correctness and safety over speed (full temp workspace copy)
  • Resolver guidance for mixed or virtual workspaces is explanatory only — no auto-edit of workspace.resolver
  • Path and git dependencies are analyzed but don't receive downgrade suggestions

Roadmap

Phase Name Status
0 Repo charter and verification baseline Done
1 Core command surface and analysis engine Done
2 Safe resolution and manifest-suggestion workflow Done
3 Reporting, fixtures, CI, and benchmark baseline Done
4 Correctness hardening (selection, explain, report) Done
5 Write-path and mutating-flow coverage Done
6 Performance realism and benchmark expansion Next
7 Release polish and operator trust cleanup Planned
8 CI/CD hardening and release automation Planned
9 Ecosystem integration and interoperability Planned
10 Advanced analysis and resolution intelligence Planned
11 Documentation, examples, and onboarding Planned
12 Community readiness and 1.0 roadmap Planned

See BUILD.md for the full phase breakdown with goals, exit criteria, risks, and decisions.

Design principles

  1. Lockfile first, manifests second. Changing Cargo.lock is low-risk and reversible. Changing Cargo.toml is a commitment. The tool always tries the safe thing first.
  2. Non-mutating by default. Read commands never write. Write commands require explicit flags. No surprises.
  3. Conservative over clever. If the tool can't prove something, it says "unknown" instead of guessing. No suggestion is better than a bogus one.
  4. Sandbox everything. Resolution experiments run in isolated temp workspaces. Your checkout is never modified by analysis.
  5. Explain, don't just report. Blockers come with full dependency paths and reasoning. Users should understand why, not just what.
  6. Local-first. All analysis uses locally available metadata. No network calls, no accounts, no cloud dependencies in the core path.
  7. Truthful status. Docs, CLI output, and code must agree. If they don't, the next change reconciles all three.

Development And Verification

cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
cargo nextest run
cargo deny check
cargo bench --bench large_workspace_resolver --no-run

Tracing is opt-in:

RUST_LOG=cargo_compatible=debug cargo compatible scan --workspace

See BUILD.md for the full development manual, phase tracking, and verification ledger. See CONTRIBUTING.md for development setup and PR guidelines.

Contributing

cargo-compatible is actively moving from correctness hardening into performance and release-polish work. Contributions are welcome — see CONTRIBUTING.md for development setup, coding standards, and PR guidelines. Design feedback and bug reports are always valuable — open an issue.

License

MIT — see LICENSE.