Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Rust Api Design

ASecurity

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.

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentrustgobashexpresstestingapi

Works with

cliapi

Security Analysis

A100/100

Pro scans all 5 files and shows the line behind each finding

Scanned 9/19/2026

$npx -y skills add rewrite-rs/skills --skill rust-api-design --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rust Api Design?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Rust Api Design
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/rewrite-rs-rust-api-design/badge)](https://www.skillsdirectory.com/skills/rewrite-rs-rust-api-design)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: rust-api-design
description: 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.
---

# 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 to `/rust-testing`. The
cost of each rung is in `DEPENDENCY-INJECTION.md`.

## Generics or `dyn`

| Want | Choose | Cost |
|---|---|---|
| Monomorphized speed, inlining, no vtable | `impl Trait` / `<T: Trait>` | Code bloat; every call site instantiates |
| Heterogeneous collection, plugin registry, smaller binary | `dyn Trait` | Vtable dispatch; the trait must be object-safe |
| Argument position, caller convenience | `impl Trait` argument | The caller cannot turbofish |
| Return position in a public API | named type or `impl Trait` | `impl Trait` hides the type — a deliberate choice, not a shortcut |

Object safety usually settles it: generic methods, methods returning `Self` by
value, or associated constants used through the object rule out `dyn`; a
heterogeneous registry cannot be generic without an enum or a trait object.

## Trait design

A trait is shared behaviour callers write generic code against, not a namespace
for grouping related functions. Keep the required methods small and default the
rest — every required method is a promise to every future implementer. Use an
associated type for the one sensible choice per implementer (`Iterator::Item`), a
generic parameter for several (`From<T>`). Watch blanket impls — `impl<T: Foo> Bar
for T` closes the door on any later `impl Bar for SomeType` that does not satisfy
`Foo`; the trap fires when the second impl is written, not when the blanket is.

## Sealed traits

A sealed trait exists to let the crate add methods without breaking downstream
implementers: the supertrait lives in a private module, so only this crate can
implement it, though downstream code can still name the trait as a bound.
Readers reproduce the pattern wrong from memory, so here it is:

```rust
struct Widget;

mod sealed {
    pub trait Sealed {}
}

pub trait WidgetBuilder: sealed::Sealed {
    fn new() -> Self;
}

impl sealed::Sealed for Widget {}

impl WidgetBuilder for Widget {
    fn new() -> Self {
        Widget
    }
}
```

## What breaks and what does not

The headline cases: adding a variant to a public enum breaks exhaustive matches
(unless the enum is `#[non_exhaustive]`); adding a required trait method breaks
implementers, a default body does not; adding a field to a public struct that is
not `#[non_exhaustive]` breaks literal construction; narrowing an argument type
breaks callers; widening a return type breaks callers who programmed against
the old one. The full table, including the non-obvious ones, is in `SEMVER.md`.

## Deferrals

The shape of the error type this API returns is `/rust-errors`. Whether an argument
type should be a newtype carrying an invariant is `/type-driven-design`. Whether a
public function should be `async`, and what that commits the crate to, is
`/async-rust`. Whether a `pub unsafe fn` is justified and how its contract is
documented is `/unsafe-rust`.

## Verification

```bash
cargo doc --no-deps          # every public item documented and the links resolve
cargo clippy --all-targets   # add -- -D warnings only if the repo has no lint config
cargo test
```

Run clippy at the lint level configured in the repo — never force `missing_docs` or
another lint on to make the surface check pass; propose it instead. When the crate
is published or has downstream consumers, the semver check the agent runs and reads:

```bash
cargo semver-checks check-release   # requires cargo-semver-checks; skip with a note if unavailable
```

Do not install tooling into the user environment as a side effect. If
`cargo-semver-checks` is not present, say so and fall back to the `SEMVER.md` table.

Attribution

rewrite-rsrewrite-rs
View sourceSee grades on GitHubMore from rewrite-rs →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Clean Code

Pragmatic coding standards - concise, direct, no over-engineering, no unnecessary comments

304955 votes

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

285172 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2222 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

10311 votes
View all in development →