You and your CI use the CLI, and your agent uses the MCP server. Both call the same TypeScript core. The core fetches and caches specs, slices them to your endpoints, and hands generation to Hey API or oapi-codegen. Spec comparison runs in a small Go binary. The results land in your repo.
coding agent ──▶ apiweld mcp ──┐
├──▶ @apiweld/core ──▶ apiweld-engine (Go)
developer / CI ──▶ apiweld CLI ┘ │ │
▼ ▼
apiweld.config.ts ~/.apiweld/
apiweld.lock.json catalog.db
<output>/* specs/<sha256>.jsonCatalog
The catalog is a SQLite database with full-text search over APIs and every one of their endpoints. It answers questions like “which endpoint refunds a payment?” in milliseconds, without loading any specs.
There are three ways to fill it:
catalog add <id> <url>indexes one API. This is the usual way: add the APIs a project uses as you need them.catalog syncdownloads a prebuilt snapshot of the APIs.guru directory. The snapshot is rebuilt weekly by the project’s GitHub Action and checked against a published SHA-256 before use.catalog buildindexes APIs.guru on your machine. It’s slow, but it doesn’t depend on the project’s releases.
Your own specs, from a folder or a list of URLs in ~/.apiweld/settings.json, are indexed next to the public ones and labelled with their source.
Directory entries can go stale. Search results show when each spec last changed, so an agent can prefer maintained APIs. Where the directory records the provider’s original URL (x-origin), Apiweld fetches from the provider. A curated upstreams.json in the Apiweld repo lists verified URLs for widely used APIs.
Spec store
Every fetched spec is normalized and saved as ~/.apiweld/specs/<sha256>.json, named by its hash. The lockfile records that hash, so the exact spec behind your client is always available, both for diffs and for rebuilding offline.
Engine
apiweld-engine is a small Go program built on oasdiff and kin-openapi, the OpenAPI parser oasdiff itself uses, so hashes and diffs agree.
| Command | What it does |
|---|---|
normalize |
Loads a JSON or YAML spec, resolves $refs, upgrades Swagger 2.0 to OpenAPI 3, and writes canonical JSON with sorted keys. |
operations |
Lists each endpoint’s method, path, operation id, summary, tags, deprecation, and auth, for the catalog. |
breaking |
Runs oasdiff’s breaking-change rules between two specs. |
changelog |
Lists every change between two specs, at every level. |
The engine reads one JSON request on stdin and writes one JSON response on stdout. It keeps no state and never opens a network connection. The TypeScript side downloads specs and passes the engine file paths.
The engine compares the full old and new specs. The TypeScript side then drops findings for endpoints you didn’t select. Diffing the whole spec means a change to a shared schema is correctly attributed to every selected endpoint that uses it.
The engine ships as one npm package per platform (@apiweld/engine-darwin-arm64, -darwin-x64, -linux-x64, -linux-arm64, -win32-x64), the same way esbuild ships. npm installs only the one that matches your machine. Binaries are built in GitHub Actions with goreleaser, with published checksums and npm provenance. Set APIWELD_ENGINE_PATH to use your own build.
Slicer
The slicer starts from your selected endpoints and collects everything they reference: parameters, request bodies, responses, and every schema those point to. The hash of that set is sliceHash, a cheap way to answer “did anything I use change?”
Generators
Generators implement one small interface:
interface GeneratorAdapter {
name: string;
version(): Promise<string>;
generate(input: {
specPath: string;
operations: string[];
outDir: string;
options: Record<string, unknown>;
}): Promise<{ files: string[] }>;
}- Hey API (
hey-api, TypeScript) runs@hey-api/openapi-tsin-process. Your selection becomes its operation filter, which also drops schemas nothing uses. Withvalidators: "zod", it adds Zod schemas and the runtime drift helper. Per-APIpatchfunctions are passed to itsparser.patch. - oapi-codegen (
oapi-codegen, Go) generates a Go client for the same selection.
Impact analysis and heal
The impact analyzer regenerates a client in a temporary git worktree and runs the TypeScript compiler over your project. The heal planner matches the compiler errors to the engine’s findings. See the heal loop.
Working on Apiweld itself
The repository is a Bun workspace with these packages: core, cli, mcp, gen-heyapi, gen-oapi, and apiweld, the published package. engine/ is the Go module. catalog/ holds the snapshot job and upstreams.json. fixtures/ holds real spec version pairs for tests. This site lives in site/.
bun install
bun run engine:build
bun run test