← ClaudeAtlas

rust-api-designlisted

Design a Rust public API — trait design, generics versus dyn, sealed traits, what is exported, and which changes break semver. Use when designing or reviewing a crate public surface, when choosing between a generic parameter and a trait object, when adding a trait method or enum variant to a released crate, or when the user asks whether a change is a breaking change.
rewrite-rs/skills · ★ 2 · API & Backend · score 73
Install: claude install-skill rewrite-rs/skills
# Rust API Design Everything `pub` from the crate root is a promise to every downstream caller. This skill governs *what callers can see and rely on* — the exported surface, the shape of its traits and generics, and which changes break the promise. ## The surface is the contract Default to private and export deliberately: a type `pub` only because a `pub fn` returns it is still part of the API, impls and public fields included. Make `pub(crate)` the habit; re-export the surface from `lib.rs`, module paths private: ```rust,ignore // lib.rs pub use crate::internal::parser::Parser; // the surface mod internal; // the tree stays private ``` `Parser` is reachable by one path only: renaming the module, moving the file, splitting the crate — none of it is a breaking change, because none of it is visible. The surface refuses three shapes: an item public at two paths; an `Arc`, `Rc`, `Box` or `RefCell` in a public signature; and a dependency type in a signature, making that dependency part of the semver contract. The depth is in `SURFACE.md`. ## Getting a dependency in The ladder, lowest rung first: a concrete type — pass the thing; a wrapper struct — swap the inside without touching a signature; a generic parameter — static dispatch, but it infects every type that holds it; `dyn Trait` — the infection stops, at the price of object safety. Climb only when the current rung cannot express the requirement, never for a test-only need — ADR 0006 belongs t