원클릭으로
rmc-imports-exports
Audit Rust cross-crate imports and exports.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Audit Rust cross-crate imports and exports.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Preview a Rust symbol rename — exact reference set & refactor probe.
Audit a Rust crate's public API.
Enforce Rust crate-edge rules.
Audit Rust attributes and doc-comments.
Rust fn-level call graphs.
Task-conditioned workspace subgraph — nodes, edges, hierarchy.
| name | rmc-imports-exports |
| description | Audit Rust cross-crate imports and exports. |
| argument-hint | [crate-name] [workspace-path] |
| allowed-tools | Read, Bash, mcp__rust-code-mcp__* |
Audit a Rust workspace's import/export structure: who exports what, who
consumes what, where the public surface is over- or under-broad, and which
pub items are dead.
Two scopes:
For naming-collision hygiene (type overlaps, module shadows), use
rmc-type-overlaps. For per-symbol forensics on a hot symbol, use
rmc-symbol-forensics. For sortable per-crate Martin metrics in isolation,
use rmc-dependency-metric.
build_hypergraph(directory=<absolute-path>)
If the schema bumped or sources changed, this rebuilds. Otherwise reuse is sub-second.
Pull these three together — they're independent reads:
workspace_stats(directory=...) → counts (nodes, items by kind, visibility)
crate_edges(directory=...) → full consumer→producer matrix
dead_pub_report(directory=...) → workspace-wide dead-pub findings
From crate_edges, sort consumer→producer edges by
total_refs_via_imports + total_refs_via_usages:
domain, core, model).main fn or [[bin]] target).Aggregate the matrix into per-producer fan-in and per-consumer fan-out totals. The shape tells you whether your crates form a clean DAG or a coupled mesh.
For each producer crate X:
get_declared_reexports(directory=..., module=X) → declared `pub use` at root
Cross-check against dead_pub_report:
dead_pub_report AND in declared_reexports → dead facade:
re-exports that nothing imports. Drop the pub use lines, demote the
source types.dead_pub_report NOT in declared_reexports → dead canonical
pubs: declared pub at home, never imported. Demote to pub(crate).dead_pub_report → live facade:
doing its job. Keep.Optional, when visibility filtering matters:
get_exports(directory=..., module=X, consumer=Y) → what consumer Y actually sees
Filter crate_edges rows by consumer_crate=Y:
unique_symbols field per edge says how broad each dependency is.total_refs_via_usages field says how heavy the dependency is.High unique_symbols on one producer = wide coupling (uses many parts).
High total_refs_via_usages on a single symbol = narrow but heavy coupling
(one type drives everything).
For symbols with the highest import_count + usage_count in any edge:
who_uses_summary(directory=..., target=<qualified_name>)
Returns rows grouped by consumer module with Test/Other category breakdown:
#[cfg(test)] or factoring
into dev-deps.crate_edges)crate_dependency_metric(directory=..., sort_by="instability", top_n=10)
Returns per-local-crate Ca (afferent), Ce (efferent),
instability = Ce / (Ce + Ca), abstractness. sort_by accepts
instability / item_count / afferent / efferent / abstractness.
module_tree(directory=..., krate=X, depth=2) → top-level module structure
get_declared_reexports(directory=..., module=X) → declared `pub use` at root
get_imports(directory=..., module=X) → what's imported at the root
dead_pub_in_crate(directory=..., krate=X) → pub items with no cross-crate consumer
Cross-tabulate three sets at the crate root:
In module_tree (visibility=pub) | In get_declared_reexports | In dead_pub_in_crate | Meaning |
|---|---|---|---|
| ✓ | – | – | canonical pub, live |
| – | ✓ | – | re-export, live (facade) |
| – | ✓ | ✓ | dead re-export — drop the pub use |
| ✓ | – | ✓ | dead canonical pub — demote to pub(crate) |
| ✓ | ✓ | – | re-exported AND canonical (rare) |
Look at pub(in crate_name) items at the root level — these are
crate-internal coordination helpers. A healthy crate has discipline:
external API as pub, internal API as pub(in crate), hidden as
default-private.
If you have workspace crate_edges cached, filter:
consumer_crate=X → outgoing dependencies (what X consumes)producer_crate=X → incoming dependencies (who consumes X)Otherwise call crate_edges(directory=...) and filter client-side.
A crate with one consumer is single-purpose; multiple consumers means it's a shared library. Single producer dependency means strong coupling to one upstream.
For each non-dead pub item at the crate root:
who_uses_summary(directory=..., target=X::Type)
The category breakdown distinguishes:
#[cfg(test)].who_imports).Identify entry-point functions (often run, start, main_loop). Run
who_uses_summary on each:
main or genuinely dead.For key types, walk their methods from module_tree and check fan-in:
who_uses_summary(directory=..., target=X::Type::method)
Methods with empty who_uses are dead-method candidates. Pre-Layer-4
these queries returned empty; post-Layer-4 they return real results, so
this step is now meaningful.
| Finding | Action |
|---|---|
Item in dead_pub_report not used by anyone | Demote to pub(crate) or delete |
Re-export in get_declared_reexports whose target is also dead | Drop the pub use, demote the source |
| Producer X with multiple consumers using overlapping symbols | Candidate for shared interface extraction |
| Consumer Y pulling deeply from producer X (high unique_symbols + total_refs) | Tight coupling — consider merging or introducing a smaller interface |
| Crate X re-exports many items from crate Y (facade pattern) | Verify intent — may be over-broad if Y is also imported directly |
Edge with total_refs_via_usages >> total_refs_via_imports | Heavy use through trait dispatch / methods (Layer 4-aware) |
| Single-consumer crate with broad API | Suspicious — consumer probably doesn't need all of it |
Methods with empty who_uses | Verify (may be dispatched via trait); demote if unused |
| Signal | Pattern |
|---|---|
| Producer fan-in skewed to 1-2 type crates | Healthy DAG with universal types |
| Producers and consumers nearly symmetric | Coupled mesh |
| One crate with high fan-in AND high fan-out | Hourglass; bottleneck |
Many pub use from one submodule | That submodule is the de-facto crate API |
dead_pub_in_crate ∩ get_declared_reexports non-empty | Dead facade re-exports |
pub(in <crate>) items in module_tree | Healthy internal-API discipline |
Severity-ranked findings table:
🔴 High — broken or contradictory state (e.g., type duplicated across
crates with same consumer, dead canonical pub still referenced
by a stale pub use)
🟡 Medium — wasted surface or namespace overload
🟢 Low — naming clarity, mechanical refactors
⚪ Info — confirms healthy structure
A clean output is a markdown table per finding with: severity, location (qualified name + file:span where available), what's wrong, recommended action.
coding-agent-bad17 crates, 1441 fan-in on domain (universal types), agent re-exports
11 permissions::* types as a facade even though direct imports of
permissions work (over-broad facade), tools has 13 dead-pub *Tool
types likely dispatched via a trait registry. Top severity finding:
half-finished migration around AgentConfig with the type duplicated in
both agent and config crates.
tui in coding-agent-bad15 submodules, single entry point tui::run (one caller in
coding-agent::interactive), 7 dead pubs of which 3 are dead re-exports
at the crate root, sensible pub(in tui) discipline for crate-internal
helpers. Cleanup is small: drop dead re-exports, demote source types.
crate_edges excludes method calls / trait dispatch from usage counts
(Layer 4 hooks them in for who_uses queries, but not in edge totals).dead_pub_in_crate is computed from cross-crate consumers only —
within-crate usage in tests/examples still flags as dead.who_uses on a popular trait can return thousands of rows; no
pagination cursor today.