How do their APIs compare?
How do their APIs compare?
About astral-sh/ruff · 2 messages · last activity 9/9/2026
I should clarify: ruff and utoipa aren't really comparable on "API" in the same sense, since they serve entirely different purposes and are consumed in different ways. Let me lay out what the retrieved data actually shows for each, rather than force a feature-by-feature comparison.
astral-sh/ruff — CLI/tool surface, not a library API
Ruff is primarily consumed as a command-line tool (linter + formatter), not as a Rust library API for downstream consumers. The retrieved chunks reflect this:
- It's structured as a workspace of internal crates (
ruff_linter,ruff_formatter,ruff_annotate_snippets,ruff_db, etc.), per the import graph in the RepoPilot analysis, with entry points like [crates/ruff_linter/src/checkers/ast/analyze/mod.rs] and [crates/ruff_formatter/src/printer/mod.rs] being the most-depended-on internal modules. - Diagnostics generation from source (e.g., stdin) is exposed internally via functions like the one documented at [crates/ruff/src/diagnostics.rs:L382].
- There isn't a public "API" for embedding Ruff into other Rust programs in the way utoipa is embedded — its primary interface is the CLI (
pyproject.tomlconfig, rule codes,--fix, etc.), per the README's feature list [README.md:L68-L102 region / overview].
So "API" for ruff really means: CLI flags, configuration schema (pyproject.toml/ruff.toml), and the rule/diagnostic model — not a stable Rust crate API for third parties.
juhaku/utoipa — a Rust proc-macro/builder API for OpenAPI generation
Utoipa's API is explicitly designed for library consumption, centered on:
- Derive/attribute macros like
#[utoipa::path(...)]and#[derive(OpenApi)], which developers annotate directly on handler functions to generate OpenAPI docs, as shown in the actix-web and axum examples [utoipa-gen/src/lib.rs:L1517-L1556] and [utoipa-axum/src/lib.rs:L221-L260]. - Builder-style runtime types, e.g.,
OpenApiBuilder, and direct mutation of the generatedOpenApistruct at runtime (doc.info.title = ...), as documented in [utoipa-gen/README.md:L277-L302] and mirrored in [README.md:L277-L302]. - Router integration APIs for frameworks — e.g.,
OpenApiRouter::nest, which wrapsaxum::Router::nestwhile also merging OpenAPI path metadata, seen in [utoipa-axum/src/router.rs:L289-L328]. - A
Modifytrait for runtime OpenAPI post-processing, referenced in the README modify-at-runtime section. - Internally, its proc-macro crate (
utoipa-gen) implements customParseimpls to read macro attribute syntax, e.g.,DeriveToResponseValue::parsefor response attributes [utoipa-gen/src/path/response.rs:L536-L578] and route-method parsing for actix [utoipa-gen/src/ext/actix.rs:L164-L221].
Summary of the contrast
- ruff: an application whose "API" is its CLI + config surface; internal crates are implementation details not meant for external API stability.
- utoipa: a library whose entire value proposition is its API — proc-macro attributes for annotating code, builder types for runtime OpenAPI manipulation, and framework-specific integration crates (
utoipa-axum, actix extras) that extend routing APIs.
If you want, I can dig deeper into either side — e.g., ruff's rule/diagnostic data structures, or utoipa's Modify trait and builder pattern internals.
FOLLOW_UPS:
- How does utoipa's
Modifytrait work internally? - What does ruff's diagnostic data structure look like?
- How does utoipa-axum integrate OpenAPI with routing?
Want to ask your own question?
Open chat for astral-sh/ruffPublic Q&A. Generated by RepoPilot from the actual source of astral-sh/ruff. AI answers can be incomplete or stale — verify before relying on them.