pkgrank ranks nodes in a Cargo dependency graph using centrality metrics.
This repo is currently publish = false (not on crates.io). Install from source:
git clone https://github.com/arclabs561/pkgrank
cd pkgrank
cargo install --path .
pkgrank --help# Rank local crates by importance (PageRank)
cargo run -- -n 10
# Rank by "who consumes this?" (Consumer PageRank)
cargo run -- --metric consumers-pagerank -n 10- Nodes are Cargo packages (from
cargo metadata). - Directed edges are
$A \to B$ iff crate A depends on crate B.
- PageRank on the depends-on graph tends to surface shared dependencies / “substrate” crates.
- To surface top-level orchestrators / consumers, use the “consumer PageRank” (PageRank on the reversed graph).
Analyze the current directory (finds Cargo.toml if present):
cargo run -- -n 25Pick the “top-level orchestrators” view:
cargo run -- --metric consumers-pagerank -n 25Bound JSON output explicitly:
cargo run -- analyze --format json --json-limit 200Write per-repo artifacts under evals/pkgrank/ (super-workspace mode):
cargo run -- sweep-local --root . --out evals/pkgrank --mode workspace-slice -n 10Triage (artifact-backed summary, same payload as MCP pkgrank_triage):
cargo run -- triage --root . --out evals/pkgrankFor commands that support --format json, the JSON is wrapped for forwards-compatible parsing:
{
"schema_version": 1,
"ok": true,
"command": "analyze|modules|modules-sweep|cratesio",
"rows": [ /* ... */ ]
}pkgrank analyze --format json also includes explicit bounding metadata:
rows_total: total rows computedrows_returned: rows included inrowstruncated: whetherrowswas truncatedjson_limit: the applied limit (if any)
pkgrank modules shells out to cargo-modules and parses its DOT output.
Install once:
cargo install cargo-modulesDefaults are tuned for a “fast, actionable hotspot scan”:
- aggregate by file
- include types + traits
- hide functions / externs / sysroot
- show a few strongest edges
- cache
cargo-modulesDOT output
Note on CLI vs MCP defaults:
- The CLI
pkgrank modulesdefaults include types + traits (and hide functions). - The MCP
pkgrank_modulestool is more conservative by default (hides fns/types/traits unless you opt in viapresetorinclude_*), because MCP payloads are easy to blow up accidentally.- If you want the CLI-like view from MCP, pass a
presetlikefile-apiorfile-full.
- If you want the CLI-like view from MCP, pass a
File-level hotspots (explicit, but these are now close to the defaults):
cargo run -- modules --manifest-path ../Cargo.toml -p walk --lib -n 25Workspace sweep (summary-only):
cargo run -- modules-sweep --manifest-path ../Cargo.toml -p walk -p innr --libUse presets when you want a different “view” quickly:
# Item-level view, more verbose
cargo run -- modules --manifest-path ../Cargo.toml -p walk --lib --preset node-full -n 25Failure semantics:
- Default: continue on error and report which packages failed.
--fail-fast: stop on first failure.--continue-on-error=false: equivalent explicit form.
Caching:
modules/modules-sweepcachecargo modules dependenciesDOT output underevals/pkgrank/modules_cache/.- Use
--cache-refreshto force regeneration.
pkgrank mcp-stdio runs an MCP server over stdio. Stdout is reserved for JSON-RPC frames.
Run:
cargo run -- mcp-stdioToolset selection (optional):
- Default: slim (small tool surface; “just works” for Cursor)
- Opt-in:
PKGRANK_MCP_TOOLSET=fullto expose advanced tools (e.g. module/type graph centrality)PKGRANK_MCP_TOOLSET=debugto also expose internal artifact-inspection tools
Environment (optional):
PKGRANK_ROOT: default root directory for artifact-backed toolsPKGRANK_OUT: default artifacts directory (defaultevals/pkgrank)
Tools (high level):
- Default (Cursor MCP):
pkgrank_view,pkgrank_triage,pkgrank_analyze,pkgrank_repo_detail,pkgrank_crate_detail,pkgrank_snapshot,pkgrank_compare_runs - Advanced (opt-in:
PKGRANK_MCP_TOOLSET=full):pkgrank_status,pkgrank_modules,pkgrank_modules_sweep - Debug (opt-in:
PKGRANK_MCP_TOOLSET=debug): internal artifact-inspection tools (e.g. TLC tables, invariants list, PPR summaries)
- Default test suite is offline/deterministic and uses local real targets (the dev super-workspace itself).
- URL-backed tests (crates.io crawl) are opt-in:
- set
PKGRANK_E2E_NETWORK=1before running tests.
- set
- Edge meaning:
$A \to B$ means “A depends on B”. - Dependency kind gating:
--dev/--buildcontrol whether those edges exist. - Workspace restriction: “workspace-only” means nodes/edges restricted to the current Cargo workspace members.
These are the “real” workflows this tool is meant to serve.
- Onboarding / orientation: “What are the most central crates in this workspace? Who are the orchestrators?”
- Use:
pkgrank analyze(metricpagerankvsconsumers-pagerank) andpkgrank triage.
- Use:
- Dependency slimming / graph sanity: “Why is this crate so central / so sticky? What depends on it?”
- Use:
pkgrank analyze --metric consumers-pagerank+ drill into origins and degrees; optionally generate artifacts viapkgrank view.
- Use:
- Refactor hotspots inside a crate: “Which files/modules/items are the coupling hotspots?”
- Use:
pkgrank moduleswith--aggregate file(hot files) or--aggregate node(hot items).
- Use:
- Workspace sweep: “Run that hotspot scan across a bunch of crates and summarize failures/results.”
- Use:
pkgrank modules-sweep(summary-only by default).
- Use:
- Shareable artifacts: “Write an HTML snapshot I can point people at.”
- Use:
pkgrank view/pkgrank sweep-local.
- Use:
Evidence pointers (qualitative):
- Community demand for “internal dependency graph visualization” (rust-analyzer crate graph is commonly suggested):
https://www.reddit.com/r/rust/comments/x04zko/visualizing_internal_dependencies_as_a_graph/ - Cursor’s framing of MCP: “connect to external tools and data sources” (so MCP tends to be used for “triage + drilldown”):
https://cursor.com/docs/context/mcp - Cargo’s own
cargo treedocs emphasize dependency display, reverse-deps (--invert), and “duplicates” as a common pain point:https://doc.rust-lang.org/cargo/commands/cargo-tree.html
pkgrankincludes its centrality algorithms internally (PageRank / PPR / betweenness / reachability), to stay buildable as a standalone repo (no cross-repo path deps).