CLI tool
smithy-lang/smithy-rs avatar
smithy-lang/smithy-rs

smithy-rs: Smithy models compiled into Rust clients and servers

Code generation for the AWS SDK for Rust, as well as server and generic smithy client generation.

685 stars282 forksRustApache-2.0

At a glance

What is it?
smithy-rs is the code generator behind the AWS SDK for Rust, and it also produces generic Smithy clients and servers from any Smithy model. It is a Kotlin and Gradle project that emits Rust, so the work is done through Gradle targets rather than a library you call, and the README states plainly that all interfaces are unstable and may change without notice.
Who is it for?
smithy-rs fits a team that already writes Smithy models and wants a Rust client or server without hand writing the protocol, and it does not fit a team that wants a small hand written client or needs a stable public interface from the generator itself, which the README says may change without notice. Before adopting it, generate one service with the assemble target, compile the output, and check the MSRV of the crates you plan to pin against your toolchain.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One generator, the AWS SDK and everything else Smithy describes

smithy-rs is described as Smithy code generators for Rust that generate clients, servers and the entire AWS SDK. That second clause is the one that matters for most people who meet the project: the AWS SDK for Rust is a product of this generator, and the README points to the aws-sdk-rust/next branch for the latest unreleased SDK build.

Smithy is a modelling language for describing a service interface, and the point of code generation from it is that the protocol details are written once and then compiled into the shapes a language expects. In this repository the generator is Kotlin, driven by Gradle, and the output is Rust. The tree shows the pieces: codegen-core for the generation logic common to clients and servers, codegen-client and codegen-server for the two directions, plus codegen-serde and codegen-traits, and the aws directory for AWS specific code generation such as signing, endpoints and customizations.

The audience is two different groups. One is the AWS SDK team and the people who contribute to the SDK itself, working on the signing logic, the endpoint resolution and the per service customizations. The other is any team with a Smithy model and a Rust service or client to build, which is what the codegen-server and codegen-client modules plus the examples directory are for.

For the second group the honest framing is that this is a compiler, not a library. You do not add it to a Cargo.toml. You run a Gradle task, it produces a Rust crate, and that crate is what your project depends on.

Setup is a Gradle wrapper and JDK 17

The setup section is short because the toolchain does the work. Running ./gradlew will set up Gradle for you, and JDK 17 is required. Running the tests requires a working Rust installation, with the README linking the Rust documentation for platform specific instructions.

So there are two toolchains in play before you generate anything: a JDK for the generator and a Rust toolchain for the code it produces, plus whatever the generated code itself needs at build time.

For development the project leans on pre-commit hooks to pass the automated linting when a pull request is opened.

bash
brew install pre-commit # (or appropriate for your platform: https://pre-commit.com/)
pre-commit install

The pre-commit configuration and the hooks directory sit at the top of the tree, alongside a .pre-commit-config.yaml, which is a common shape for a project where formatting and lint failures are cheap to fix locally and expensive to fix in review.

Two other directories hint at the engineering standards applied here: a clippy-root.toml for lint configuration at the repository root, and a .cargo-deny-config.toml, which is the file cargo-deny uses to control which dependencies and licences are allowed into the build. A project that generates a published SDK has to be strict about what lands in it, and those two files are where that strictness is expressed.

Component order decides which tests you run

The README is candid that running all of smithy-rs's tests can take a very long time, and that it is better to know which parts to test based on the changes being made and to let continuous integration find other issues when posting a pull request.

What follows is the dependency order, and it is the most useful thing in the README for a newcomer. The components affect each other in this order, with earlier affecting later: rust-runtime first, then codegen and codegen-server, then aws/rust-runtime, and finally aws/codegen-aws-sdk. Some components such as codegen-client-test and codegen-server-test exist purely to test other components.

Reading that list as a workflow: a change to the runtime only needs the runtime tests, a change to a generator needs the generator tests plus the runtime, and a change to the AWS customizations needs nearly everything. The generated SDK sits at the end of the chain, which is why an AWS specific change is the expensive one to validate.

The runtime crates have their own commands, and the manifest path form lets you run them from the repository root without changing directory.

bash
cargo test --manifest-path=rust-runtime/Cargo.toml
cargo clippy --manifest-path=rust-runtime/Cargo.toml

The AWS runtime is tested the same way with the aws/rust-runtime manifest path. Some runtime crates also carry an additional-ci script, which the README says often needs cargo-hack and cargo-udeps installed, since those tools check every feature combination and unused dependencies respectively.

SDK generation runs through Gradle targets, not a CLI

The AWS specific targets are listed with a note that the aws/sdk/ readme carries more information, because those targets can be configured to generate more or fewer AWS service clients. That configurability is the point: a full SDK generation run is enormous, and the common case during development is generating a slice of it.

The core targets are these.

bash
# Generate an SDK, but do not attempt to compile / run tests. Useful for inspecting generated code
./gradlew :aws:sdk:assemble
# Run all the tests
./gradlew :aws:sdk:sdkTest

There is also a set of targets that delegate to cargo for the generated code: cargoCheck to validate that the generated code compiles, cargoClippy to validate that it passes Clippy, and cargoDocs for the generated documentation, alongside cargoTest for running the generated tests. The SDK output lands in aws/sdk/build/aws-sdk.

One dependency is easy to miss. The sdkTest target, which generates and runs all the tests, requires Go to be installed for FIP support to compile properly, so a full SDK test run needs a third language toolchain that has nothing to do with Rust.

For a team that only wants the SDK, none of this is theirs to run: the published AWS SDK crates are the output of this pipeline, and the aws-sdk-rust repository is what you depend on. The generator earns its keep for anyone building a non-AWS Smithy service.

Codegen tests compile Rust to prove the Kotlin works

The generator tests are Kotlin tasks, and the interesting part is what they do rather than what they assert.

bash
# Run Kotlin codegen unit tests
./gradlew codegen-core:check
./gradlew codegen-client:check
./gradlew codegen-server:check

The protocol test suites run alongside them, with codegen-client-test and codegen-server-test tasks for the whitelabel client and server code, and the README explains the failure mode: several Kotlin unit tests generate Rust projects and compile them, and when they fail they typically output links to the location of the generated code so that it can be inspected.

That is a sensible design for a compiler, and it explains the directory layout. The generated output is not thrown away, it is kept under a projections directory, and the README names the paths to look at when a suite fails, for example codegen-client-test/build/smithyprojections/codegen-client-test for the client suite and the matching path under codegen-server-test for the server suite.

So a failure in this repository is usually a diff in generated Rust rather than a stack trace in Kotlin. For a contributor that means the fastest debugging loop is to read the generated code, and the second is to reproduce it with a single service model rather than a whole SDK.

An MSRV policy of stable minus two, bumped as a minor release

The project publishes its minimum supported Rust version policy in detail, which is unusual and useful. The MSRV is stable-2, meaning the current stable Rust version and the prior two versions. Older versions may work, and in rare circumstances the MSRV may exceed stable-2 for security purposes, for example when a dependency update for a security fix requires an MSRV bump.

The versioning consequence is spelled out. Increasing the MSRV is treated as a minor change rather than a major breaking one, following Cargo's SemVer guidance, and the MSRV is not increased automatically. When it does increase, each affected published crate is versioned accordingly: a 1.x crate takes a minor release, for example 1.4.2 becoming 1.5.0, and a 0.x crate takes a patch release, for example 0.62.1 becoming 0.62.2.

That is a clear contract for anyone pinning versions. The crates move forward without a major bump, so a dependency update can require a newer compiler, and the signal to watch is the minor version of a 1.x crate rather than a major version. For a service that compiles the SDK on a pinned toolchain, this is the rule to encode in your dependency policy.

The releases follow a date based naming scheme, with release-2026-10-19 and release-2026-09-30.2 among the most recent, and the last push was on 2026-10-20 with the repository not archived. The licence is Apache-2.0, with both LICENSE and NOTICE files at the top of the tree, and the README states that all internal and external interfaces are considered unstable and subject to change without notice, which is the sentence to keep in mind when planning to depend on the generator's own crates.

Generated code, or a hand written client

The alternative to generating a Rust client from a Smithy model is to write the client by hand, with an HTTP library such as reqwest and a serialisation layer, and to implement the protocol from the service documentation. The difference in approach is what gets automated and what stays yours.

Generation puts the protocol in the compiler. The shape of the request, the serialisation of the data model, the error taxonomy, the pagination rules and the retry behaviour all come out of the model, and they come out consistently across every operation in the service rather than per endpoint by per engineer. When the service adds an operation, regenerating produces the client code for it, and the diff in your repository is the review artefact.

A hand written client gives you exactly the shape you want and nothing else. It is smaller, it has no codegen step in the build, and it can do things a generator would not produce, such as a request shape that deliberately differs from the published model. The cost is that every protocol detail is a decision someone has to make and then maintain, and in a service with forty operations that is a real cost rather than a rounding error.

The examples directory shows the shape of the generated world, with a pokemon-service that has separate crates for the common model, the client usage, a Lambda variant, a TLS variant and a plain service, plus a Python example and a legacy folder. That layout is the argument for generation in miniature: the model is shared, the transports differ, and the differences are package boundaries rather than forked code.

Editorial conclusion

smithy-rs fits a team that already writes Smithy models and wants a Rust client or server without hand writing the protocol, and it does not fit a team that wants a small hand written client or needs a stable public interface from the generator itself, which the README says may change without notice. Before adopting it, generate one service with the assemble target, compile the output, and check the MSRV of the crates you plan to pin against your toolchain.

Frequently asked questions

What does smithy-rs generate and who uses it?

It generates Rust clients and servers from Smithy models, and it is the generator behind the AWS SDK for Rust, where the AWS specific code covers signing, endpoints and customizations. The latest unreleased SDK build is published in the aws-sdk-rust/next branch.

What do I need to build smithy-rs?

JDK 17 is required, and running the tests also needs a working Rust installation. Running the gradle wrapper sets up Gradle for you, and the aws sdk test target additionally requires Go to be installed so that FIP support compiles.

How long do the smithy-rs tests take and which ones should I run?

The README says running all tests can take a very long time, and it lists the order in which components affect each other: rust-runtime, then codegen and codegen-server, then aws/rust-runtime, and finally aws/codegen-aws-sdk. It suggests testing what your change affects and letting continuous integration find the rest.

What is the MSRV policy for the crates smithy-rs publishes?

The policy is stable-2, the current stable Rust version and the prior two. Raising the MSRV is treated as a minor change, so 1.x crates get a minor release and 0.x crates get a patch release, and the README notes it can exceed stable-2 for security fixes.

How do I generate an AWS SDK build with smithy-rs?

Run ./gradlew :aws:sdk:assemble to generate the SDK without compiling or testing it, and ./gradlew :aws:sdk:sdkTest to generate and run all the tests. The output is placed in aws/sdk/build/aws-sdk, and the aws/sdk/ readme explains how the targets are configured to generate more or fewer service clients.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. README
  4. Releases
  5. smithy-lang/smithy-rs on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/smithy-lang-smithy-rs.svg)](https://hysenlabs.com/projects/smithy-lang-smithy-rs)

Was this useful?