Skip to content
Eight Effect-native API SDKs are live.Explore the catalog
Distilled
Esc
navigateopen⌘Jpreview
On this page

Generate an SDK

A practical path from authoritative API input to an Effect-native package.

Before you begin

Choose the source strategy before writing generator code. The authority and shape of the upstream input determines whether you need a spec repository at all.

Pin the authoritative input

Mirror a maintained OpenAPI document or add the official typed SDK as a submodule. Pin an exact commit.

Document semantic patches

Keep unavoidable RFC 6902 transformations small, named, and reviewable. Never silently mutate the source.

Generate operations

Emit Effect schemas, HTTP traits, categories, and yieldable operations through the shared generator.

Add provider behavior

Implement credentials, client wiring, error mapping, retry policy, and any pagination conventions in the provider repository.

Prove determinism

Regenerate and fail when committed operations or coverage.json drift. Review method totals and unsupported operations, and test generator adaptations with focused request-shape fixtures.

Publish independently

Release the provider package from its own trusted GitHub workflow.

OpenAPI generator

import { generateFromOpenAPI } from "@kevinmichaelchen/distilled/openapi/generate";

generateFromOpenAPI({
  specPath: "specs/provider/specs/openapi.json",
  patchDir: "patches",
  outputDir: "src/operations",
});

The exact provider configuration is documented by the source type:

PropType
specPathstring

Path to the OpenAPI spec file

Typestring
patchDirstring

Directory containing *.patch.json files (can be same as spec dir or separate)

Typestring
outputDirstring

Output directory for generated files

Typestring
importPrefixstring

Import prefix for relative imports (e.g., ".." for operations/ -> src/)

Typestring
clientImport?string

Client import path (e.g., "../client")

Typestring
traitsImport?string

Traits import path (e.g., "../traits" or "@distilled.cloud/core/traits")

Typestring
sensitiveImport?string

Sensitive import path

Typestring
errorsImport?string

Errors import path (for operation-specific error imports)

Typestring
includeOperationErrors?boolean

Whether to include operation-specific error imports (default: true for Swagger, false for OAS 3.x)

Typeboolean
statusToErrorClass?Record<string, string>

Status codes to error class name mapping (only used when includeOperationErrors=true)

TypeRecord<string, string>
defaultErrorStatuses?Set<string>

Default error status codes to exclude from operation-specific errors

TypeSet<string>
skipDeprecated?boolean

Whether to skip deprecated operations (default: true)

Typeboolean
apiVersion?string

Default `api-version` for versioned APIs (e.g. Azure ARM). When set, the generator bakes `apiVersion` into each operation's `T.Http` trait (so the client injects `?api-version=<value>` automatically) and omits the `api-version` query parameter from the generated input schema.

Typestring

Agent handoff

Ask a coding agent to evaluate a new provider source.

Why are generated files committed?

Because source and generator changes should produce reviewable diffs. Consumers also receive a complete source package without needing generation at install time.

Why not one monorepo?

Independent repositories keep source history, provider cadence, package ownership, and release permissions explicit.

When should I create distilled-spec-*?

When a compact, authoritative artifact benefits from immutable mirroring or extraction. Skip it when the official source repository is already the right-sized authoritative input.

Last updated on July 16, 2026

Was this page helpful?