Skip to main content

crozier

An ultra-fast, memory-efficient OpenAPI-to-SDK code generator written in Rust + minijinja. crozier reproduces Fern's generated SDKs byte-for-byte (with generator-identifying comments aside), driven by nothing but an OpenAPI document and a couple of naming flags — no per-project config, no generators written in the target language.

Python is the only target today; more will follow.

Status: early. crozier generates the Python type layer (pydantic models, enums, unions/aliases) plus version.py/py.typed, and byte-matches Fern's output for those files. See docs/matching.md for exactly what is matched and the roadmap.

See it in action

One OpenAPI document in, a complete typed Python SDK out — crozier generate writes the whole package in one shot, then you can read the code it produced:

Animated demo: typing crozier generate --spec petstore.yml --output sdk, crozier reporting it wrote 35 files, then cat-ing the generated PetStatus enum as it streams in with syntax highlighting

The output is byte-for-byte Fern's. Here is the Pet model crozier emitted from a handful of lines of schema — a real generated file, not a hand-written sample:

The generated types/pet.py: a pydantic Pet(UniversalBaseModel) with Optional id, name, status and owner fields and the pydantic v1/v2 config block

crozier generate python takes the document and a couple of naming flags and writes the SDK — the models, enums, the per-endpoint client, and Fern's core/ runtime — into --output:

Terminal: crozier generate python --spec petstore.yml --output sdk --package-name petstore, the generated 35 files into sdk summary, and a tree of the written package showing src/petstore with core, types, list_pets, client.py and pyproject.toml

Or drive one — or several — named generators from a crozier.yml instead of flags. crozier config shows the effective settings for every generator and the layer each value resolved from (CLI flag > CROZIER_* env > file > default):

Terminal: crozier config against a crozier.yml with shared defaults and two generators (python and admin), each field shown with its resolved value and source layer — shared, generator, or default

crozier init drops a starter crozier.yml carrying a JSON Schema modeline, so editors complete and validate it against crozier's own config schema:

Terminal: crozier init writing crozier.yml, then cat-ing it — a yaml-language-server $schema modeline, shared spec, and a generators block with the built-in python generator

The full command surface (crozier --help and crozier generate --help)

crozier --help: the top-level usage listing the generate, init, config and schema subcommands

crozier generate --help: every flag — spec, output, package-name, project-name, client-class-name, audience, audience-strict and extra-fields

A malformed document is rejected at the boundary with an actionable message and a non-zero exit — never a panic:

crozier rejecting broken.yml with the message: invalid OpenAPI document broken.yml, missing openapi version field, is this an OpenAPI document?

These are real captures of the CLI, rendered from its actual output by just screenshots and gated by screencomp — change what a command prints and the committed image (and its digest) changes with it.

Install

From PyPI (fastest — a prebuilt binary, no Rust toolchain): crozier ships as platform wheels that wrap the compiled binary and expose it as a console script, so any Python installer puts it on your PATH in seconds:

pip install crozier      # or: pipx install crozier
uvx crozier --help       # run once without installing

Platforms without a prebuilt wheel fall back to the source distribution, which builds from Rust (a toolchain is needed there).

From crates.io:

cargo install crozier --locked

From the install script (prebuilt binary from GitHub Releases, verified):

curl -fsSL https://raw.githubusercontent.com/nickderobertis/crozier/main/scripts/install.sh | sh

It detects your platform, downloads the matching archive, and verifies it against a trust root independent of where it was downloaded — a Sigstore build-provenance attestation when a verifier (cosign, pip install sigstore, or gh) is present, else the canonical SHA-256 checksum. Pin a version or install location with sh -s -- --version v0.1.0 --to ~/.local/bin.

From source (latest main):

cargo install --git https://github.com/nickderobertis/crozier --locked

From a release archive (manual): each release publishes per-platform archives named crozier-<tag>-<target>.tar.gz with a matching .sha256 and a .sigstore.json provenance bundle, for targets x86_64/aarch64 Linux, x86_64/aarch64 macOS, and x86_64 Windows. Download the archive for your platform from the Releases page, verify the checksum (or the attestation), and put the crozier binary on your PATH.

Usage

The fastest path needs no config file — the built-in python generator runs straight from flags:

crozier generate python \
  --spec path/to/openapi.yml \
  --output ./generated \
  --package-name my_api \
  --project-name my-api
  • --spec — the OpenAPI 3.x document (.yml, .yaml, or .json).
  • --output — directory to write the SDK into.
  • --package-name — the Python import package (the directory under src/). Defaults to a snake_case of the API title.
  • --project-name — the distribution name recorded in version.py. Defaults to the package name.
  • --client-class-name — the name of the generated root client class (Fern's client_class_name). Defaults to {PascalCase(package_name)}Api.
  • --audience (repeatable) / --audience-strict — prune generation to x-crozier-audiences.

crozier exits 0 on success (with a one-line summary on stderr) and 1 on any error, printing the exact problem and a suggested fix.

Configuration

crozier runs one or more named generators. You can drive them purely from flags (above), from a crozier.yml, or any mix — every setting resolves per field as:

CLI flag  >  CROZIER_* env var  >  crozier.yml (generator over shared)  >  built-in default

Run crozier init to drop a starter crozier.yml in the working directory. It leads with a JSON Schema modeline —

# yaml-language-server: $schema=https://raw.githubusercontent.com/nickderobertis/crozier/main/assets/crozier.schema.json

— so editors with the YAML language server give field completion and validation against the published schema (derived from crozier's own config types, so it never drifts). Run crozier config to print the effective settings and the layer each value came from.

A crozier.yml in the working directory is picked up automatically. Top-level keys are shared defaults; each entry under generators: is one SDK to emit:

# Shared across every generator
spec: ./openapi.yml
audiences: [public]

generators:
  python:              # overrides the built-in `python` generator
    output: ./sdks/python
    package-name: my_api
    project-name: my-api
  admin:               # a second generator (also Python for now)
    type: python
    spec: ./admin-openapi.yml
    output: ./sdks/admin
    package-name: admin_api
  • crozier or crozier generate — run every configured generator (or the built-in python when nothing is configured).
  • crozier generate <name> — run one generator by name (python always works, even with no config file).
  • crozier init — write a starter crozier.yml (--output, --force).
  • crozier config [<name>] — show the effective config and each value's source.
  • crozier schema — print the config JSON Schema to stdout.
  • --config <path> (repeatable, later wins) selects config files instead of auto-discovery; --no-config ignores config files entirely; CROZIER_CONFIG names a file via the environment.

Per-generation flags (--spec, --output, …) apply to a single generator, so they are rejected when more than one would run — name one, or set the values in crozier.yml. See docs/configuration.md for the full reference.

Development

The command surface is a small set of just recipes:

just bootstrap   # set up from a clean clone (toolchain + dev tools)
just check       # full gate: fmt, clippy -D warnings, tests + e2e + coverage, deny, machete, doc
just test        # fast tests with coverage enforced (95%)
just test-e2e    # drive the compiled binary and byte-compare against fixtures
just format      # rustfmt in place
just upgrade     # cargo update, then re-run the gate

See AGENTS.md for the durable contributor guide and docs/matching.md for the byte-matching strategy.

License and attribution

crozier is licensed under Apache-2.0. It is an independent, clean-room implementation — it reproduces Fern's generated output format (the project's explicit goal) and does not copy Fern's generator source.

The test fixtures under tests/fixtures/ are Fern's own output and OpenAPI test specs, used under Apache-2.0 with attribution and a statement of changes; see NOTICE and licenses/fern-APACHE-2.0.txt.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

crozier-0.0.22.tar.gz (145.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

crozier-0.0.22-py3-none-win_amd64.whl (1.2 MB view details)

Uploaded Python 3Windows x86-64

crozier-0.0.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

crozier-0.0.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

crozier-0.0.22-py3-none-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

crozier-0.0.22-py3-none-macosx_10_12_x86_64.whl (1.3 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file crozier-0.0.22.tar.gz.

File metadata

  • Download URL: crozier-0.0.22.tar.gz
  • Upload date:
  • Size: 145.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for crozier-0.0.22.tar.gz
Algorithm Hash digest
SHA256 c4f3069760658ca97f76406e0172bafb44daf0ef82b3fa6f9b714b4358bd0d97
MD5 100d949902f56cdfe2896497edb08f63
BLAKE2b-256 9f2c2d1b41a14ac75f8c1a370b3685ca3c853509503e1d4141a8cbaf139dc8a5

See more details on using hashes here.

File details

Details for the file crozier-0.0.22-py3-none-win_amd64.whl.

File metadata

  • Download URL: crozier-0.0.22-py3-none-win_amd64.whl
  • Upload date:
  • Size: 1.2 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for crozier-0.0.22-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 a12e06fe9d1f0b7e5ef343f3af89230de8b300523822af1ea0438c6941e9876f
MD5 3ad7168c8475eb748c4350789e2586a4
BLAKE2b-256 76311e135592fc39d459d6471e5098dcf580f7c7cc4c149b210334a64169c6e3

See more details on using hashes here.

File details

Details for the file crozier-0.0.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for crozier-0.0.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7a0f00fb68a37f891ecadd7c06106a1997a6998671336109fe2fd4dfe958145c
MD5 2063afb4e3e536e987196f20897a4d5b
BLAKE2b-256 237ad33f34057132899e7b1d55fcdffe093aba9aebf0573aa4c1e940f632e334

See more details on using hashes here.

File details

Details for the file crozier-0.0.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for crozier-0.0.22-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fdc76c374f632419eff9fac81529424cd016654374fd409b24e33c02d3905750
MD5 8dcd22abcf12e34626a621b99e8db039
BLAKE2b-256 c03e86c6ef73ab0271c961626f610e4699f7fd174f8a8e22d2b0932b789dfc2f

See more details on using hashes here.

File details

Details for the file crozier-0.0.22-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for crozier-0.0.22-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c8114ccb4f497d3e87ac8e1eeaa1eecb7111e78102c8dbd7119aef86d5072c0e
MD5 91b72e342f6a3d0474192601d81648f3
BLAKE2b-256 3e89426c5410b0c957760f5d00e2a1586346184869b182f8cee287bc58eeb93d

See more details on using hashes here.

File details

Details for the file crozier-0.0.22-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for crozier-0.0.22-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b246b13ed4eacdf5d852d4d1808af8564c33fe1fa9af031a91d343bde8798f00
MD5 f5ef781c6e680f49f70a71211d783f39
BLAKE2b-256 75d6ca8f549c0c9fa3c6d3872d2a9f744126a0b2d1f3108a36dc066aa6c6c075

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.31

6 files

0.0.30

6 files

0.0.29

6 files

0.0.28

6 files

0.0.27

6 files

0.0.26

6 files

0.0.25

6 files

0.0.24

6 files

0.0.23

6 files

This release

0.0.22 This release

6 files

0.0.21

6 files

0.0.20

6 files

0.0.19

6 files

0.0.18

6 files

0.0.17

6 files

0.0.16

6 files

0.0.15

6 files

0.0.14

6 files

0.0.13

6 files

0.0.12

6 files

0.0.11

6 files

0.0.10

6 files

0.0.9

6 files

0.0.8

6 files

0.0.7

6 files

0.0.6

6 files

0.0.5

6 files

0.0.4

6 files

0.0.3

6 files

0.0.2

6 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page