with one click
rmc-api-surface
Audit a Rust crate's public API.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
Audit a Rust crate's public API.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Preview a Rust symbol rename — exact reference set & refactor probe.
Enforce Rust crate-edge rules.
Audit Rust attributes and doc-comments.
Rust fn-level call graphs.
Task-conditioned workspace subgraph — nodes, edges, hierarchy.
Rust complexity hotspots by blast radius.
| name | rmc-api-surface |
| description | Audit a Rust crate's public API. |
| argument-hint | <crate-name> |
| allowed-tools | Read, mcp__rust-code-mcp__* |
Catch over-broad facades, accidental internals exposure, and dead public surface. Scope: single crate.
For workspace-wide imports/exports, use rmc-imports-exports. For
refactor-specific recipes (drop facade, demote pub), use rmc-refactor-plan.
build_hypergraph(directory=<absolute-path>)
get_declared_reexports(directory=..., module=<crate_root>)
get_exports(directory=..., module=<crate_root>, consumer=<external_crate>)
module_tree(directory=..., krate=<crate>) → filter to pub items
dead_pub_in_crate(directory=..., krate=<crate>)
| Source | Meaning |
|---|---|
module_tree (visibility=pub) | What's pub at canonical site |
get_declared_reexports | What's re-exported via pub use at the crate root |
get_exports(consumer=<other>) | What's actually visible from outside (visibility-filtered) |
dead_pub_in_crate | Pub items with no cross-crate consumer |
For each declared re-export, look up canonical-path traffic:
who_imports(directory=..., target=<canonical_path>)
Most importers reaching for the canonical path means the facade isn't being used. Drop it.
Items in get_declared_reexports that the team thought were pub(crate).
These usually slip in via pub use submodule::* patterns.
If a pub use chain can become pub(crate) use, the source can be
pub(crate). dead_pub_in_crate already finds these.
| Empty result | Means |
|---|---|
get_declared_reexports([]) | Crate has no facade — everything at canonical paths. Intentional design. |
dead_pub_in_crate([]) | No dead pubs — disciplined. |
overlaps.common_fn_names([]) | No init / run proliferation — good hygiene. |
| Finding | Action |
|---|---|
Re-export declared at root, target dead in dead_pub_in_crate | Drop pub use, demote source |
Pub item at canonical site, dead in dead_pub_in_crate | Demote to pub(crate) |
Item in get_declared_reexports that looks crate-internal | Probably accidentally exposed; demote |
| Re-export AND canonical declaration of same item | Pick one path; drop the other |
get_exports(consumer=X) smaller than get_declared_reexports | Visibility filter is trimming pub(crate) / pub(in <crate>) items (intentional discipline) |
| Signal | Means |
|---|---|
pub use foo::* at crate root | Likely over-broad facade; audit each item |
Crate's get_declared_reexports ⊆ dead_pub_in_crate | Entire facade is dead — drop wholesale |
get_exports(consumer=X) smaller than get_declared_reexports | Visibility filter trimming pub(crate) / pub(in <crate>) items |
Every facade item has who_imports only on the facade path | Facade is earning its keep |
Every facade item has who_imports only on canonical path | Facade is dead weight |
Crate: <crate>
Declared re-exports: <n>
Effective exports to <consumer>: <m>
Dead pubs: <k>
Dead facade re-exports (intersection): <j>
Recommended:
- Drop pub use for: <list>
- Demote to pub(crate): <list>
- Already healthy: <list of items earning their pub keyword>
Severity-ranked findings:
🔴 High — Crate-internal type accidentally exposed via pub use
🟡 Medium — Dead facade re-export
🟡 Medium — Dead canonical pub
🟢 Low — Over-broad pub use glob (audit each item)
⚪ Info — Healthy facade; intentional no-facade design
tui in coding-agent-bad15 submodules. 7 dead pubs of which 3 are dead re-exports at the crate
root (RunState, InvalidTransition, RunnerWakeError — all
re-exported AND dead). Sensible pub(in tui) discipline for
crate-internal helpers. Cleanup: drop three pub use lines, demote
source types to pub(crate).
get_exports(consumer=X) requires X to be a valid crate name in the
workspace. Pass a non-existent name and you get an empty result, not
an error.pub use submodule::* glob re-exports surface as one row per
re-exported item, not one row per glob — verify by reading source if
the glob is the actual smell.dead_pub_in_crate counts cross-crate consumers only; within-crate
test usage still flags as dead.