Changelog
v5.0.0-beta.74 — Jun 23, 2026
@kubb/core
Features
- Let
ctx.addGeneratorregister several generators in one call. Pass them as separate arguments (ctx.addGenerator(schemaGenerator, operationGenerator)) or hand it an existing list (ctx.addGenerator(selectedGenerators)), and the arrays are flattened for you. A single generator still works as before, so there is no need to loop over each one. (#3663,c21d008)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.73 — Jun 22, 2026
@kubb/adapter-oas
Bug Fixes
Close tuples when
prefixItemsis paired withitems: false.A
prefixItemsschema withitems: falseis the canonical closed-tuple pattern in JSON Schema 2020-12 / OpenAPI 3.1: the prefix defines the positions anditems: falseforbids any extra elements. The boolean was being read as a falsy rest schema, so the tuple gained a stray...any[]tail ([number, number, ...any[]]) that both allowed extra elements and widened them toany. The rest element is now omitted, producing a closed[number, number]. An absentitemsstill widens the tail toany, anditems: truekeeps the unconstrained rest. (#3651,7bbc0f6)
@kubb/cli
Bug Fixes
kubb initnow scaffolds and lists@kubb/plugin-axiosand@kubb/plugin-fetchinstead of the removed@kubb/plugin-client. (#3650,7577c64)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.72 — Jun 20, 2026
@kubb/ast
Breaking Changes
- Remove the TypeScript function-parameter model from
@kubb/ast. The function-parameter nodes and factories (createFunctionParameter,createFunctionParameters,createTypeLiteral,createIndexedAccessType,createObjectBindingPattern), thecreateOperationParamsbuilder, thecaseParamshelper, and theOperationParamsResolvertype are no longer part of@kubb/ast. These are language-specific code generation, so they now live in@kubb/plugin-ts(the node model andcreateOperationParams) and the shared plugin internals (caseParams,OperationParamsResolver).@kubb/astkeeps the spec-agnostic node tree. (#3647,1fd1136)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.71 — Jun 20, 2026
@kubb/ast
Bug Fixes
Let
createFunctionParameteraccept a pre-builtObjectBindingPatternNodeas itsname.The
name-form input now takesstring | ObjectBindingPatternNode, so a destructured group that is typed from a single reference (or carries no type) can go through the factory instead of a hand-built{ kind: 'FunctionParameter' }literal, for examplecreateFunctionParameter({ name: createObjectBindingPattern({ elements: [{ name: 'path' }] }), type: "Omit<Config, 'url'>", default: '{}' }). TheFunctionParameterNodeshape is unchanged. (#3643,711d1f2)Stop re-exporting unused internal helpers from
@kubb/ast/utils.resolveRefName,resolveGroupType,buildGroupParam,buildTypeLiteral, andresolveParamType, plus theMappedProperty,MappedSchema,SchemaTransform,BuildGroupArgs, andParamGroupTypetypes, were exported from the@kubb/ast/utilsbarrel but nothing consumed them through it. They stay available to the package internally. Keep importing the public helpers (caseParams,createOperationParams,mapSchemaItems,syncSchemaRef, and the rest) as before. (#3640,02fc0f6)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.70 — Jun 19, 2026
@kubb/core
Bug Fixes
Simplify the generate phase: schema and operation nodes now run through each plugin's generators in a single ordered pass instead of parallel batches.
The generators run synchronously, so the old
Promise.allbatching never overlapped any work. It only marked where queued writes flushed. The pass now walks nodes in order and flushes everyGENERATE_FLUSH_EVERYnodes (the renamedSCHEMA_PARALLEL), keeping the generation/write overlap that speeds up large specs on disk while dropping theforBatcheshelper. (#3638,3055bca)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.69 — Jun 18, 2026
@kubb/adapter-oas
Breaking Changes
@kubb/adapter-oasno longer deduplicates schemas, and thededupeoption is removed. Every named schema in the spec becomes its own type, and inline shapes stay inline.Earlier versions collapsed structurally identical schemas into one shared definition and hoisted repeated inline shapes under an invented name. That hoisting could collide with a generated operation type (a shared
{ error?: string }400 response becamePostV1WorkoutsStatus400, the same name the response-status type uses), producing a self-referentialexport type X = Xand duplicate exports. Output is now faithful to the spec: to share a shape, name it as a component and$refit.@kubb/ast: the dialectdedupeseam is removed —defineDialectno longer accepts adedupemember and theDedupetype is gone. ThesignatureOfandisSchemaEqualhelpers are removed too, since deduplication was their only consumer. (#3632,8addaf3)
Features
Add an
enumsoption toadapterOasthat controls where inline enums live. The default'inline'keeps each enum on the property that declares it.'root'lifts every inline enum to a reusable top-level schema named after its context (e.g.PetStatusEnum) and references it wherever it appears, so types, zod, and faker all share one definition. (#3632,8addaf3)Group the server options and rename the discriminator modes.
Breaking changes
Server options
serverIndexandserverVariablesare replaced by a singleserverobject.ts// Before adapterOas({ serverIndex: 0, serverVariables: { env: 'prod' } }) // After adapterOas({ server: { index: 0, variables: { env: 'prod' } } })resolveBaseUrlnow takes{ document, server }instead of{ document, serverIndex, serverVariables }.Discriminator modes
The
discriminatorvalues are renamed for clarity.'strict'becomes'preserve'and'inherit'becomes'propagate'. The default is now'preserve'.ts// Before adapterOas({ discriminator: 'inherit' }) // After adapterOas({ discriminator: 'propagate' }) ``` ([#3634](https://github.com/kubb-labs/kubb/pull/3634), [`9f6b051`](https://github.com/kubb-labs/kubb/commit/9f6b05150a6f5002f7b0ccaa204448b524a05e98))
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.68 — Jun 17, 2026
@kubb/adapter-oas
Bug Fixes
- Reframe each package description and its keywords around Kubb. Only the
kubbmeta-package calls itself the meta framework for code generation, and only@kubb/adapter-oasstill names OpenAPI and Swagger, since that is the package that parses them. The READMEs use the same wording. (#3625,420c8d4)
@kubb/ast
Features
Add a
copyfield to the file model so plugins can emit a real on-disk file into the generated folder verbatim. Setcopyto an absolute path on aUserFileNode(viainjectFile/upsertFileorcreateFile), or passcopyto the JSX<File copy={…} />component, and Kubb writes that file's content unchanged, applying onlybanner/footerand bypassing the language parser. This lets a plugin ship a hand-authored template as a real.tsfile and drop it into the output without inlining its source as a string.Remove the unused
output.overrideboolean from the config and plugin output options. It was documented as overwriting or skipping existing files, but nothing in the write path read it (fsStoragealready skips writes only when content is byte-identical), so it had no effect. (#3627,bf1a3a8)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.67 — Jun 17, 2026
@kubb/ast
Breaking Changes
Rename
definePrintertocreatePrinterand drop thecreatePrinterFactoryexport.createPrinteris the single helper for building a schema printer. The genericcreatePrinterFactorythat sat behind it is now inlined, since the only consumer that keyed a printer by a field other thannode.type(@kubb/plugin-ts's function printer) no longer needs it. ReplacedefinePrinter(...)withcreatePrinter(...); the builder shape, options, andPrinterresult are unchanged. (#3622,e2caa72)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.66 — Jun 17, 2026
@kubb/adapter-oas
Bug Fixes
Keep generating a request body schema for
application/octet-streambodies.The 3.0 -> 3.1 upgrade drops the schema from an
application/octet-streamrequest body, leaving an empty media type object.getRequestSchemanow recognizes a binary media type and synthesizes the{ type: 'string', contentMediaType: 'application/octet-stream' }schema, so operations likeuploadFilestill emit a binary request body type (for example the ZoduploadFileDataSchema). (#3621,f6d1256)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.65 — Jun 17, 2026
@kubb/adapter-oas
Features
Normalize every input to OpenAPI 3.1 and drop the 3.0 type union.
parseDocumentupgrades documents to 3.1 (upgrade(document, '3.1')), so Swagger 2.0 and OpenAPI 3.0 inputs keep working, they just upgrade further. The exportedDocument,SchemaObject,OperationObject,ResponseObjectand related types are now 3.1 only (OpenAPIV3_1). That is breaking for code importing them expecting 3.0 shapes such asnullableon a schema.The AST schema node now carries an
examplesarray, populated from the OAS 3.1examples, instead of a singularexample.parseDocumentalso loses itscanBundleoption. A string is always a file path or URL to bundle, an object is an already-parsed document. (#3619,30ec0b4)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.64 — Jun 17, 2026
@kubb/adapter-oas
Bug Fixes
Convert Swagger 2.0 specs with
@scalar/openapi-upgraderinstead ofswagger2openapi.The old converter pulled in the legacy oas-kit and node-fetch dependency tree (around 1.5 MB) for a single
convertObjcall.@scalar/openapi-upgraderis a focused ESM package that does the same 2.0 to 3.0 transform, cutting install size to roughly 480 KB. The upgrader runs on every parsed document and only rewrites Swagger 2.0 input (it checks forswagger: '2.0'internally), so OpenAPI 3.0 and 3.1 documents pass through untouched. The internalisOpenApiV2Documentguard is gone as a result. (#3611,8bd4085)
@kubb/ast
Bug Fixes
Stop publishing
src/in the package tarballs.The shipped sourcemaps already embed their sources and no declaration maps point at
src/, so source-level debugging and go-to-definition are unaffected while each tarball drops by roughly a third. (#3611,8bd4085)Expose every
@kubb/astexport under a singleastnamespace and make the package tree-shakable.import { ast } from '@kubb/ast'(or from@kubb/core) now reaches the whole surface the way the TypeScript compiler exposests.factory, for exampleast.factory.createSchema(...). The namespace is a compile-time re-export and the package is marked side-effect-free, so a bundler keeps only the factories you actually use. Flat named imports such asimport { factory, defineNode } from '@kubb/ast'keep working. (#3611,8bd4085)
@kubb/cli
Bug Fixes
Load the Kubb config with
unconfigand accept only JavaScript and TypeScript module configs.Discovery now matches
kubb.config.{ts,mts,cts,js,mjs,cjs}and the matching.kubbrc.*variants (also under.config/andconfigs/). YAML, JSON, and thepackage.jsonkubbkey are no longer read, since a Kubb config is defined withdefineConfigand plugin function calls that those formats cannot express. This replacescosmiconfigand its YAML and JSON loader chain, reducing install size. TypeScript and JSX configs keep loading through the existing jiti loader. (#3611,8bd4085)
@kubb/core
Bug Fixes
Lead terminal diagnostics with the code and rename the help/docs labels.
A diagnostic now prints as
[CODE] plugin: messagewith the code tinted by severity, followed by indentedat:,fix:, andsee:rows. Thehelp:anddocs:labels are renamed tofix:andsee:, matching the diagnostics docs pages, and the standalone×/⚠/ℹglyph is dropped. The--reporter jsonoutput and theSerializedDiagnosticfields (help,docsUrl) are unchanged. (#3606,799c660)
@kubb/mcp
Bug Fixes
Serve the MCP server over stdio only and drop the HTTP transport.
Every local MCP client (Claude, Copilot, editors) launches the server as a subprocess and talks to it over stdio, so the HTTP transport and its
--portand--hostflags are removed along with the@remix-run/node-fetch-serverand@tmcp/transport-httpdependencies.startServer()no longer takesportorhostoptions. (#3611,8bd4085)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.63 — Jun 16, 2026
@kubb/adapter-oas
Bug Fixes
- Consolidate the OAS dedupe pass behind a single
Planobject.plan()now returns one object that owns its rewriting:applyfor operations and nested schemas,applyTopLevelfor top-level schemas, andisAliasto skip a duplicate top-level name. The internalDedupePlan,DedupeLookups, andDedupeTargettypes and the standaloneapplyfunction are gone, and the@kubb/astDedupeseam drops itsapplymember because the plan carries that behavior. Generated output is unchanged. (39e4f79) - Review JSDoc and code comments across these packages so the shipped docs match the current code. The pass corrects stale claims (a
PluginDriverreference that is nowKubbDriver, a reversed formatter-detection order, a--debugflag that no longer exists, lowercase HTTP methods that are actually uppercase) and removes unverifiable assertions. Comments only, no code or generated output changes. (39e4f79)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.62 — Jun 16, 2026
@kubb/ast
Bug Fixes
- Colocate the node builders with their definitions.
createFilenow lives innodes/file.tsalongside the othercreateXhelpers, the per-node factory tests sit next to each node module, and thenode.ts/printer.tsmodules are renamed todefineNode.ts/definePrinter.tsto match their exports. Public API and generated output are unchanged. (73f6e86)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.61 — Jun 15, 2026
@kubb/adapter-oas
Bug Fixes
- Consolidate the OAS parser's per-site macro calls behind
applyShallowand anameEnumshelper. Output is unchanged; the parser test suite stays byte-identical. (#3600,ec32ab9)
@kubb/ast
Breaking Changes
Add macros, a named and composable way to rewrite the AST, and make them the single transform layer.
defineMacro,composeMacros, andapplyMacroslive on the@kubb/astroot and turn an anonymous transform into a named unit with an optionalenforceorder and awhengate. Macros follow themacro<Name>convention, mirroring plugins (pluginTs). The built-in presets live on the new@kubb/ast/macrossubpath, one file per macro. Plugins register macros through the newaddMacroandsetMacrossetup-context methods in@kubb/core, replacing the oldsetTransformer.The plugin
transformer?: Visitorfield is gone, andcreateMockedPluginfrom@kubb/core/mockstakesmacrosinstead of atransformervisitor.The schema rewriters are retired into macros.
setDiscriminatorEnum,simplifyUnion, andsetEnumNameare removed from@kubb/astand replaced bymacroDiscriminatorEnum,macroSimplifyUnion, andmacroEnumNameon@kubb/ast/macros.mergeAdjacentObjectsandsyncSchemaRefmove to the@kubb/ast/utilssubpath.@kubb/adapter-oasnormalizes through these macros. (#3600,f5b4db2)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.60 — Jun 15, 2026
@kubb/ast
Features
- Add shared schema-traversal helpers to
@kubb/ast/utilsfor printers to build on.mapSchemaProperties,mapSchemaMembers, andmapSchemaItemswalk an object's properties, a union or intersection's members, and an array or tuple's items, pairing each child with its transformed output. They are generic over the output type, so a printer can returnstringorts.TypeNode.lazyGetteremits theget key() { return body }form for circular-ref positions, andresolveRefNameis now exported from the subpath as the shared ref-name resolver. Pure addition, no behavior change. (#3596,67bb92c)
Bug Fixes
Fix the CJS build dropping re-export-only
@kubb/ast/utilshelpers.With
"sideEffects": false, rolldown tree-shook the modules that theutilssubpath only re-exports (schemaGraph,operationParams,codegen,strings, and friends) out of the multi-entry CJS bundle, while still emitting their export getters. Requiring@kubb/ast/utilsfrom a CommonJS context then threwfindCircularSchemas is not defined(and the same forcreateOperationParams,containsCircularRef,caseParams,buildJSDoc, and the rest). The ESM build was unaffected, so this only surfaced for CJS consumers such as akubb.config.cjs. Dropping thesideEffectsdeclaration keeps those modules in the CJS output. (#3598,3c3f03d)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.59 — Jun 15, 2026
@kubb/adapter-oas
Bug Fixes
- Tighten the JSDoc prose across the core packages so the published types read naturally. This cuts rule-of-three filler,
-ing-participle clauses, clause-joining semicolons, marketing words, and sentences that only restate the TypeScript type. The change is comment-only, so no API or behavior changes. (#3593,1f71069)
@kubb/ast
Features
Reduce the files you touch to add a node.
types.tsnow derives its node-type exports from the node barrel (export type * from './nodes/index.ts') instead of a hand-maintained list, so adding a node no longer editstypes.ts. This also surfaces five node types the old list had drifted from:BreakNode,ContentNode,GenericOperationNode,RequestBodyNode, andScalarSchemaNode.The
@kubb/astbarrel now sources its node defs from the registry (export * from './registry.ts'), so adding a node no longer edits the barrel either. This surfacesnodeDefson the barrel. The visitor tables it derives stay internal tovisitor.ts.A new test fails when a node def has no matching
factory.create*, so missing wiring is caught in CI. The package README documents the remaining touch-points. (#3595,4dcfe98)Clarify the
@kubb/astabstraction boundaries. No runtime behavior changes.dedupe.tsandutils/fileMerge.tseach gained a header that explains the split.dedupe.tscollapses duplicate schema shapes by structural signature, whilefileMerge.tsmerges one file's imports, exports, and sources.syncSchemaRefnow lives intransformers.tsnext to the otherSchemaNodetransforms. It is still exported from@kubb/ast/utils, so its import path is unchanged.createOperationParamsis no longer surfaced through thefactorynamespace. It is a high-level builder, not ats.factoryprimitive, so import it from@kubb/ast/utilsinstead ofast.factory.The OpenAPI discriminator helpers
createDiscriminantNodeandfindDiscriminatormoved out of@kubb/astinto@kubb/adapter-oas, since the OAS adapter was their only consumer. This keeps@kubb/astspec-agnostic. (#3594,25b7936)
Bug Fixes
- Reorganize the
@kubb/astutils layer into concern-based modules. The grab-bagutils/ast.tsandutils/index.tsfiles now split intostrings.ts,codegen.ts,refs.ts,schemaGraph.ts,operationParams.ts, andfileMerge.ts, each with its tests alongside it.utils/index.tsstays a thin barrel, so@kubb/ast,@kubb/ast/factory,@kubb/ast/types, and@kubb/ast/utilsexport the same names with the same behavior. No public API changes. (#3591,c069f04)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.58 — Jun 14, 2026
@kubb/ast
Breaking Changes
Reshape the
@kubb/astfactory surface around anast.factorynamespace that mirrorsts.factory.createX.The flat
createXnode constructors leave the@kubb/astroot barrel. Reach them through thefactorynamespace asast.factory.createSchema(...), or import them from the new@kubb/ast/factorysubpath. MigratecreateSchema(...)andast.createSchema(...)calls toast.factory.createSchema(...).The node and AST helpers
buildGroupParam,buildTypeLiteral,caseParams,collectUsedSchemaNames,containsCircularRef,findCircularSchemas,isStringType,resolveParamType, andsyncSchemaRefmove off the root barrel onto the@kubb/ast/utilssubpath. Import them from@kubb/ast/utilsrather than@kubb/astor theastnamespace.createStreamInputfolds intocreateInput. Passstream: truefor the streaming variant:createInput({ stream: true, schemas, operations, meta })returns the streamingInputNode<true>withAsyncIterablesources, whilecreateInput({ schemas, operations })still returns the eagerInputNode.The function-parameter printer key type
FunctionNodeTypebecomesFunctionParamKind, derived fromFunctionParamNode['kind']so its values match the PascalCase nodekinddiscriminants.@kubb/corere-exports@kubb/astas theastnamespace, soimport { ast } from '@kubb/core'reaches node definitions asast.schemaDef, guards and helpers asast.narrowSchema, and constructors asast.factory.createSchema(...). (#3570,3553f14)
Features
Split the operation-parameter helpers across
@kubb/astby what they return. The node buildersresolveParamType,buildGroupParam, andbuildTypeLiteralstay on the main@kubb/astentry. The helpers that return plain values move to the@kubb/ast/utilssubpath:resolveGroupType(aParamGroupTypedescriptor) andextractStringsFromNodes(a string), along with theParamGroupTypeandBuildGroupArgstypes.extractStringsFromNodesis no longer re-exported from the main@kubb/astbarrel or theastnamespace re-exported by@kubb/core. Import it from@kubb/ast/utilsinstead. The plugins migration (Phase 2) builds query, header, and path parameter groups from these helpers instead of redefining them. (#3570,f213bed)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.57 — Jun 14, 2026
@kubb/ast
Breaking Changes
Reshape function parameter and type nodes onto the
ts.factorymodel.A type reference is now a plain
string. TheParamsTypenode (with itsreference,struct, andmembervariants) and the separateParameterGroupnode are gone. Three new nodes replace them:TypeLiteralfor an inline object type ({ petId: string; name?: string }),IndexedAccessTypefor a single field read from a named type (PathParams['petId']), andObjectBindingPatternfor a destructured binding ({ id, name }).createFunctionParameternow takes either anameor a flatpropertieslist. Passingpropertiesbuilds one destructured parameter, anObjectBindingPatternname paired with aTypeLiteraltype, so a whole group is a single parameter instead of its own node type.Migration:
createParamsType({ variant: 'reference', name: 'string' })becomes the string'string'.createParamsType({ variant: 'member', base, key })becomescreateIndexedAccessType({ objectType: base, indexType: key }).createParamsType({ variant: 'struct', properties })becomescreateTypeLiteral({ members }).createParameterGroup({ properties })becomescreateFunctionParameter({ properties }).
The 24 standalone
isXxxNodeguards that were deprecated in the previous release are also removed. Use each node'sDef.isinstead, for exampleschemaDef.is(node)overisSchemaNode(node).narrowSchemaandisHttpOperationNodestay. (#3569,1388155)
Features
Introduce
defineNodeas the single source-of-truth for AST nodes.Each node is now defined once in its
nodes/*.tsfile withdefineNode, which derives itscreatebuilder, itsis*guard, and the visitor traversal tables (VISITOR_KEYS,VISITOR_KEY_BY_KIND,nodeFinalizers) from that one definition. The public API is re-exported fromindex.tsstraight from each node file, the hand-maintained visitor tables moved to a generatedregistry.ts, and the node-shapeascasts are gone.factory.tsnow holds onlycreateFileandupdate.This is non-breaking: every existing export keeps its shape and behavior, and the generated output is unchanged. It also adds an
is*guard for every node kind (24 in total), soisContentNode,isPropertyNode,isFileNode,isTextNode, and the rest are now available alongside the existing guards.The per-node definitions (
schemaDef,propertyDef, …) anddefineNodeare now exported. The standaloneis*guards are deprecated in favor of each node's<node>Def.is(for exampleschemaDef.isoverisSchemaNode), which keeps the guard next to the node it belongs to.The param and type helpers that Phase 1 (#3563) reshapes are marked
@deprecatedwith their migration paths:createParamsType(pass the type name as a plain string),createParameterGroup(usecreateFunctionParameter({ properties: [...] })), and theParamsTypeNode/ParameterGroupNodetypes. (#3567,218b365)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.56 — Jun 13, 2026
@kubb/core
Bug Fixes
- Expose Url (
f333037)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.55 — Jun 13, 2026
@kubb/adapter-oas
Bug Fixes
Drop the
oasandoas-normalizedependencies in favor of built-in logic.Operation iteration (paths, methods,
operationId, tags, request/response bodies, content type) now runs through a small internalOperationwrapper instead of theoaspackage, and the OpenAPI type aliases come straight fromopenapi-typesand@types/json-schema. Document loading parses inline YAML/JSON with theyamlpackage, andkubb validatevalidates with@readme/openapi-parserdirectly. Generated output and validation behavior are unchanged, while the dependency tree is considerably smaller. (#3557,330ea5b)
@kubb/core
Breaking Changes
Remove the incremental build cache.
The
cacheconfig option, thecreateCachefactory, thefsCachebackend, and theCache,CachedSnapshot, andFsCacheOptionstypes are gone from@kubb/core.defineConfigno longer enablesfsCache()by default, and thekubb generate --no-cacheflag is removed from the CLI. Every run now regenerates straight from the spec. (#3558,b504cf0)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.54 — Jun 12, 2026
@kubb/adapter-oas
Bug Fixes
Repoint refs at duplicate top-level schemas to the first schema with the same content.
When a spec defines a schema and also references an external copy of it (for example
$ref: 'https://petstore3.swagger.io/api/v3/openapi.json#/components/schemas/Category'next to a localCategory), the ref bundler hoists the copy under a numeric suffix (Category1) and rewrites the ref sites to it, so generators typed properties againstCategory1instead ofCategory.buildDedupePlannow records every later top-level schema whose content matches an earlier one in a newaliasNamesmap,applyDeduperepoints any ref targeting such a duplicate at the first schema with that content, and the adapter stream no longer emits the duplicate at all. The decision is purely content-based (structural signature), not name-based:Pet.categoryis typedCategoryagain, no deadCategory1model is generated, and a schema with a different shape keeps its own type. This also applies to hand-written schemas that share one content (aDogidentical toCatcollapses intoCat).applyDedupenow takes the plan lookups ({ canonicalBySignature, aliasNames }) instead of the bare signature map, and@kubb/astexports theDedupeCanonicalandDedupeLookupstypes. (#3551,d8d1aef)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.53 — Jun 12, 2026
@kubb/adapter-oas
Bug Fixes
Bundle external
$refs withapi-ref-bundlerinstead of@apidevtools/json-schema-ref-parser.$RefParser.bundle()remaps external file refs to the JSON pointer of their first occurrence (for example#/components/schemas/AppState/properties/currentUser), so multi-file specs lost their named schemas and generators inlined types instead of emitting named types with imports.api-ref-bundlerhoists external file schemas into namedcomponents.schemasentries (./schemas/User.yamlbecomes#/components/schemas/User), matching the earlier Redocly behavior while staying lightweight, and adds a foundation for AsyncAPI support later on.The new bundler resolves local YAML and JSON files and HTTP(S) URLs, including
./and../relative refs and pointer fragments into external files. (#3549,3c013ef)Stop shipping
extension.yamlin the npm packages and drop theschemas/extension.jsonschema. Extension metadata now lives in the platform repo (kubb-labs/platform,apps/kubb.dev/extensions/) and the options are documented on each extension's kubb.dev page. (#3547,2944481)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.52 — Jun 11, 2026
@kubb/adapter-oas
Bug Fixes
Remove more unused code flagged by knip. None of the removed symbols are part of any package's
exports, and all were unused across the kubb and plugins repos. Runtime behavior is unchanged.@kubb/parser-ts: delete the deadcreateImportandcreateExportAST builders, superseded by the string-basedprintImport/printExport.@kubb/adapter-oas: drop the unusedHttpMethodslookup and the redundantopenapi-typesre-export.@kubb/ast: drop the unusedbuildFixturemock helper.@kubb/cli: drop the unusedSUMMARY_SEPARATORconstant.@kubb/core: drop the orphanedmocks/noopfixtures.- Several internal-only symbols (
createContent,createRequestBody,SCALAR_PRIMITIVE_TYPES,INDENT_SIZE,defaultResolveOptions,buildDefaultBanner,ReportTiming,printFrontmatter,SchemaWithMetadata) drop their redundantexport. (#3544,5ce2414)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.51 — Jun 11, 2026
@kubb/adapter-oas
Features
Drop dead exports and lazy-load heavy deps.
Remove
mergeDocuments,ValidateDocumentOptions, andHttpMethodsfrom the public API (src/index.ts). These symbols had no consumers across the kubb, plugins, or platform repos. They remain in their source files for internal use.Replace
@redocly/openapi-core(8–10 MB) with@apidevtools/json-schema-ref-parser(~100 KB) for external$refbundling. The library was already a transitive dependency and exposes the samebundle()behavior.@redocly/openapi-coreis removed fromdependencies.Lazy-load
swagger2openapiwith a dynamicimport()so it only loads when the input is a Swagger 2.0 document. (#3538,4afab7a)
@kubb/core
Breaking Changes
Replace
middlewarewith post-enforced plugins.defineMiddlewareand theMiddlewaretype are removed from@kubb/core. UsedefinePluginwithenforce: 'post'instead — a post-enforced plugin registers after all normal plugins and fires in that order, giving the same guarantee.Config.middlewareandUserConfig.middlewareare removed. Barrel generation now runs through the new@kubb/plugin-barrelpackage, which is a standard plugin withenforce: 'post'. It is added topluginsautomatically bydefineConfigwhen no barrel plugin is already present.@kubb/middleware-barrelis removed. Migrate to@kubb/plugin-barrel. (#3537,af0c0cf)
Features
- Move
Telemetry,defineLogger, Logger types (Logger,LoggerContext,LoggerOptions,UserLogger), andselectReportersfrom@kubb/coreto@kubb/cli. These exports were only ever used by the CLI.logLevelremains exported from@kubb/core. Programmatic users ofcreateKubbare unaffected. (#3536,d3c29bd)
Bug Fixes
- Split the type definitions out of
createKubb.tsinto thetypes.tsbarrel, foldManifestintocaches/fsCache.ts, and replace the internalHookRegistrywith inline listener tracking onKubbDriver. Also drop the unusedtinyexecdependency. These are internal cleanups with no change to the public API. (#3541,159aa57) - Remove the unused
kubb:config:startandkubb:config:endlifecycle events fromKubbHooksand delete theKubbConfigEndContexttype. The CLI already emitskubb:infoandkubb:success"Config loaded" messages for the same output, so nothing visible changes. (#3534,e388248) - Resolve config in the
Kubbconstructor instead ofsetup().configis now a plain readonly property available right aftercreateKubb, so the getter no longer throws beforesetup().setup()keeps the async work: sizing the hooks ceiling, theoutput.cleanstorage clear, anddriver.setup(). The deadkubb.config ?? userConfigfallback inunplugin-kubbis removed. (#3540,2c05045)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.50 — Jun 10, 2026
@kubb/cli
Features
- Remove the
kubb agentcommand and drop@kubb/agentas a peer dependency of@kubb/cliandkubb. The HTTP agent server has moved out of this repository and is now deployed as thekubblabs/kubb-agentDocker image. To run the agent, use the published Docker image instead of the CLI. (#3524,94ac5b8)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.49 — Jun 10, 2026
@kubb/cli
Features
Add a
--no-cacheflag tokubb generatethat turns off the incremental build cache for a single run, forcing a full regeneration without editing the config.The flag overrides whatever cache the config resolved to (
fsCache()by default), so it works for every config shape.CLIOptionsnow carriesnoCache, letting adefineConfigfunction read it too. (#3520,e6987cb)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.48 — Jun 10, 2026
@kubb/core
Breaking Changes
Remove the
'group'output mode.output.modenow accepts'directory' | 'file'.'directory'(the default) writes one file per operation or schema, and'file'writes everything into a single file. The per-group consolidation mode is gone.The
groupoption stays and keeps organizing'directory'output into per-tag or per-path subdirectories. It remains invalid with'file', and pairing the two now fails the build with aKUBB_INVALID_PLUGIN_OPTIONSdiagnostic.Migrate any plugin set to
output.mode: 'group'to'directory'(keep thegroupoption for subdirectories) or'file'(drop thegroupoption for a single file). (#3517,49ffe04)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.47 — Jun 10, 2026
@kubb/ast
Bug Fixes
Drop self-imports of locally-defined symbols in consolidated output (
mode: 'group'/mode: 'file').A grouped file that defines a type (e.g.
Pet) no longer also imports that same type. In group mode the import for a referenced schema resolves to the per-schema path while the file lives at the group path, so the existing path-based filter could not match.createFilenow also drops any import whose binding is defined locally by one of the file's own sources. The local definition stays in place. (#3515,ebb0921)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.46 — Jun 10, 2026
@kubb/ast
Breaking Changes
- Strip self-imports in
createFile. An import whose resolved path equals the containing file is now dropped, so consolidated output (output.mode: 'group'andoutput.mode: 'file') no longer emits an import that points at the file itself. Bare module specifiers and genuine cross-file imports are unaffected. (#3513,d90c0ea)
@kubb/core
Breaking Changes
Add an explicit
output.modeoption and remove the implicit single-file detection.A plugin's
outputnow takesmode: 'directory' | 'group' | 'file':'directory'(default) writes one file per operation or schema, the previous default behavior.'group'writes one file per resolved group and requires the plugin'sgroupoption.'file'writes everything into a single file. Whenpathhas no extension the default.tsis appended ('types'becomes'types.ts').
Kubb no longer guesses the mode from the
output.pathextension. Setoutput.mode: 'file'to get a single file where you previously relied on apathending in.ts.Removed
getMode, theKubbDriver.getModestatic, the generator contextctx.getMode, and thepathModefield onResolverPathParams. Added theOutputModeandOutputOptionstypes, whereOutputOptionscouplesoutput.mode: 'group'with a requiredgroupoption at the type level. A plugin configured withoutput.mode: 'group'but nogroupnow fails the build with aKUBB_INVALID_PLUGIN_OPTIONSdiagnostic. (#3513,d90c0ea)
@kubb/middleware-barrel
Breaking Changes
- Make barrel generation aware of
output.mode. A plugin withoutput.mode: 'file'gets no per-plugin barrel, since its output is a single file, and the root barrel re-exports that file directly. A plugin withoutput.mode: 'group'writes one file per group, which the per-plugin barrel re-exports like any other flat layout. (#3513,d90c0ea)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.45 — Jun 10, 2026
@kubb/adapter-oas
Bug Fixes
- Sync option docs with the actual v5 defaults and APIs. The
integerTypedocs in@kubb/adapter-oas(extension.yaml) and@kubb/ast(JSDoc) now state the real default'bigint'instead of'number'. The@kubb/coreJSDoc for build diagnostics names the per-plugin timing kindperformanceinstead of the removedtiming. The@kubb/renderer-jsxREADME drops the removedcreateRendererandrenderer.unmount()APIs in favor ofjsxRenderer()withrender,files, andstream, and lists the markdown components (Callout,Frontmatter,Heading,List,Paragraph). (#3504,84326c1)
@kubb/ast
Bug Fixes
- Trim type exports that no package in the kubb or plugins ecosystem consumes. The public barrel no
longer re-exports node and helper types that were never imported, two unused node aliases are
removed, and several internal-only types drop their
export. Runtime behavior is unchanged. (#3502,a83c3ea)
@kubb/core
Features
Default the
taggroup folder name to the plain camelCased tag instead of${tag}Controller.With
group: { type: 'tag' }, files now land inpet/rather thanpetController/. TheControllersuffix was a leftover convention nothing else in the output referenced. To keep the old layout, setgroup: { type: 'tag', name: ({ group }) => \${group}Controller` }. ([#3509](https://github.com/kubb-labs/kubb/pull/3509), [d63c266`](https://github.com/kubb-labs/kubb/commit/d63c266777c107ae9732f6f63e82bae50d27bbff))
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.44 — Jun 9, 2026
@kubb/ast
Breaking Changes
Add a
@kubb/ast/utilssubpath for spec-agnostic helpers that produce or format generated source, so the main@kubb/astbarrel stays focused on the AST node tree and every adapter can share one implementation. The subpath exportsstringify,trimQuotes,jsStringEscape,toRegExpString,stringifyObject,getNestedAccessor,buildJSDoc,isValidVarName, and a newensureValidVarName.It also moves the pure (non-node) helpers
objectKey,buildObject,buildList,childName,enumPropName,extractRefName, andfindDiscriminatorfrom the main barrel to@kubb/ast/utils. This is breaking: import them from@kubb/ast/utilsinstead of@kubb/ast(they are also no longer part of theastnamespace re-exported by@kubb/core). (#3498,8ba18f7)
@kubb/core
Bug Fixes
Cut memory use and duplicated work in the build hot path, and name the requiring plugin in missing-dependency errors.
Rendered sources are no longer retained in memory for the whole build when caching is disabled, and the file write pipeline streams each file to storage as soon as it is parsed instead of materializing the entire batch first. Cache-hit restores now write files in parallel batches instead of one at a time. Per-node transformer results are memoized per plugin, so a plugin with a batch
operations()generator no longer transforms and re-resolves every operation twice.requirePluginerrors raised from a generator context now say which plugin declared the missing dependency, e.g.Plugin "plugin-zod" is required by "plugin-ts" but not found. (#3499,8b611cb)
@kubb/parser-ts
Features
- Tighten generated-output formatting so it reads cleanly without a formatter.
objectKeynow quotes a key only when it is not valid identifier syntax (reserved words and globals likenameandclassstay bare) and uses single quotes when it must quote.@kubb/parser-tstreats a<br/>break as a blank-line separator between statements, so consecutive or edge breaks fold into a single blank line instead of stacking. A sharedsingleQuotehelper backs the single-quote output. (#3498,8ba18f7)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.43 — Jun 9, 2026
@kubb/core
Bug Fixes
- Trim the
Renderercontract to what the build driver actually uses. Theunmountanddisposemethods were never called, since the driver disposes throughusing instance = renderer(), which runs[Symbol.dispose]. Both are removed from theRenderertype, so a custom renderer now implementsrender,files, an optionalstream, and[Symbol.dispose]only. (#3488,626b261)
@kubb/parser-ts
Features
- Normalize the indentation of generated declarations so the output reads cleanly before any formatter runs. Raw text and JSX nodes are now dedented to a column-zero baseline when printed, which removes the source indentation that template literals bake into multi-line
const,type,function, and arrow-function bodies and stops it from compounding under the structural indent. Top-level declarations in a source are separated by a blank line, and an explicit<br/>no longer doubles that gap. Adedenthelper sits next toindentLinesfor this. (#3494,04e75af) - Emit imports and exports in the repo style so generated files read cleanly before any formatter runs.
@kubb/parser-tsnow printsimport/exportstatements with single quotes and no semicolons through newprintImport/printExportbuilders instead of the TypeScript compiler printer.@kubb/astgains shared string builders (buildObject,buildList,objectKey) so plugins can assemble multi-line object and array literals with correct, cumulative indentation, a closing bracket at column zero, and trailing commas. (#3496,8ea4500)
@kubb/renderer-jsx
Breaking Changes
Remove React entirely, runtime and types, while keeping JSX as the authoring style. The async fiber runtime,
react-reconciler,scheduler, and thereactdependency are all gone. Rendering runs through the synchronous walker over a tiny built-in JSX runtime (@kubb/renderer-jsx/jsx-runtime). The JSX namespace is now self-contained and declares only thekubb-*code hosts plusbr, so@types/reactis dropped as well and consumers no longer need it for type support. The gzipped bundle drops from a 510 KiB budget to ~8 KiB.There is now one renderer, exported as
jsxRenderer. The separatejsxRendererSyncname is gone, and so is the unusedRooterror-boundary component. This release also clears the scaffolding left from the virtual-DOM era: the internal DOM module with itsDOMElementandDOMNodetypes, the unusedCodeBlockcomponent, thecreateContext,inject,provide, andunprovidere-exports, and the renderer's no-opdisposeandunmountmethods. (#3488,2bd32fd)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.42 — Jun 5, 2026
@kubb/core
Features
Add an opt-in incremental build cache.
Kubb now fingerprints the inputs that shape generated code (the spec content, the resolved config, every plugin's options, and the running version) and, when nothing changed, restores the previous output instead of regenerating it. A second run becomes near-instant, the same idea behind Nx's computation cache.
defineConfigturns this on by default withfsCache()(local disk undernode_modules/.cache/kubb). Setcache: falseto turn it off, or pass another backend through the newcacheoption, which mirrors the existingstorageoption.@kubb/coreships thefsCache()backend, plus theCachetype andcreateCachefactory for custom ones. A barecreateKubbleaves caching off unless a cache is passed.tsimport { defineConfig } from 'kubb' export default defineConfig({ input: { path: './petStore.yaml' }, output: { path: './src/gen' }, // cache: fsCache() is applied by default; set `cache: false` to turn it off. }) ``` ([#3469](https://github.com/kubb-labs/kubb/pull/3469), [`eeab54b`](https://github.com/kubb-labs/kubb/commit/eeab54b2823a5e591c9ec2b05cb31abf32f37cb2))Run Kubb natively on Bun while keeping full Node support.
Runtime detection is now centralized, so the filesystem helpers reach for
Bun.fileandBun.writeunder Bun and fall back tonode:fseverywhere else. The defaultfsStoragescans the output directory withBun.Globunder Bun instead of a recursivereaddirwalk. Thekubb agentcommand launches its server with the same runtime that started the CLI (viaprocess.execPath) instead of always shelling out tonode, so a Bun-only environment no longer needs anodebinary on the PATH. Anonymous telemetry also records which runtime ran the generation (bun,deno, ornode) alongside its version. (#3470,1ca92f6)
Bug Fixes
- Adopt native Node 22 / ES2024 features: order plugins through
Set-based dependency lookups inKubbDriver, and replacePromiseresolver boilerplate withPromise.withResolvers(). The shared TypeScript config moves to an ES2024 target with the ES2025 collection and iterator libraries to match the Node 22 baseline. (#3473,50615f4)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.41 — Jun 3, 2026
@kubb/cli
Bug Fixes
- Remove the GitHub Actions logger. The CLI now picks the clack or plain logger based on whether a TTY is available, regardless of the CI environment. (#3463,
7798632)
@kubb/core
Features
Route hook subprocess output through events instead of a sink-factory callback.
Hook output (formatter, linter, and
donehooks) now reaches loggers over the event emitter: a newkubb:hook:lineevent carries each streamed stdout line while a hook runs, andkubb:hook:endgained optionalstdout/stderrfields holding a failed hook's captured output. The CLI'smakeSink/HookSinkFactorychannel and its threading are removed, so loggers are pure event subscribers and the runner decides whether to stream from thekubb:hook:linelistener count. Behavior is unchanged: clack still streams live dimmed lines, the plain logger still prints failure output, and a failed hook's output still surfaces at the silent log level. (#3467,333aea7)
Bug Fixes
- Restore progressive
Plugins N/Mprogress in the CLI. The driver now runs each plugin's generator pass sequentially, sokubb:plugin:endfires as each plugin finishes instead of once the whole batch pass is over. The CLI counter advances 2/9, 3/9, ..., 9/9 again rather than jumping from 1/9 straight to 9/9 at the end of the run. (#3465,be22e6d)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.40 — Jun 3, 2026
@kubb/core
Bug Fixes
- add urlpath back (
68638b7)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.39 — Jun 3, 2026
@kubb/core
Features
Fold the diagnostic error helpers into the
Diagnosticsnamespace:DiagnosticErroris nowDiagnostics.Errorand the structural check is exposed asDiagnostics.isError.The standalone
DiagnosticErrorexport from@kubb/coreis removed. Replacenew DiagnosticError(...)withnew Diagnostics.Error(...), and importDiagnosticsinstead. The thrown error keeps itsnameof'DiagnosticError', so structural checks across duplicated@kubb/corecopies still match. (#3458,ec9a92c)Remove the public
FileProcessorexport from@kubb/coreand move thematchFilessnapshot helper into@kubb/core/mocks.matchFiles(files, { parsers, format, pre })takes its parsers and formatter as options, so it renders generator output to file snapshots without@kubb/corepulling in a parser or prettier. (#3458,1b19a0c)Remove the exported
isInputPathtype guard from@kubb/core. It had a single internal caller, where the check is now an inline'path' in config.inputthat narrows theInputPath | InputDataunion on its own. (#3458,ec69a5c)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.38 — Jun 3, 2026
@kubb/core
Bug Fixes
Fix diagnostic reporting regressions found in review.
resolveRefnow throws aDiagnosticErrorwhen a$refcannot be resolved outside a build scope, instead of silently returningnull. Inside a build it still collects the diagnostic and keeps parsing.- Plugin-reported problems (
ctx.error/ctx.warn/ctx.info) and formatter/linter/done-hook failures no longer render twice. The generator context only collects diagnostics now, and the host renders each once after the build. schemaDiagnosticsbuilds correct RFC 6901 pointers: property names are escaped (~→~0,/→~1), and tuple items andoneOf/anyOf/allOfmembers are indexed, so distinct advisory diagnostics are no longer dropped by the dedupe.kubb generate --reporter jsonemits one top-level JSON array for the whole run (aggregated onkubb:lifecycle:end), so multi-config runs stay valid JSON.config.reportersfromkubb.config.tsis honored again:--reporterno longer defaults tocli, so it only overrides the config when passed.- The agent forwards
diagnostics,status,hrStart, andfilesCreatedonkubb:generation:end, so the generation summary reaches connected clients again. - The OAS adapter caches its parsed document, schemas, and prescan per source and per document instead of once per instance. Reusing one
adapterOas()instance across adefineConfigarray (configs that spread a sharedbaseConfig) now parses each config's spec instead of replaying the first, so every config generates its own files and reports its own file count. (50d5f1e)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.37 — Jun 3, 2026
@kubb/adapter-oas
Features
Give every error a stable code, and hand structured diagnostics to the MCP tools.
Failures that used to throw a plain
Errornow throw aDiagnosticErrorwith a code, aconfiglocation, and a help line: a missinginput.pathreportsKUBB_INPUT_NOT_FOUND(the OAS adapter checks the file before reading it), an adapter configured without input reportsKUBB_INPUT_REQUIRED, and merging an empty set of OAS documents reportsKUBB_INPUT_REQUIRED. They surface in the run summary and--reporter jsoninstead of as an opaqueKUBB_UNKNOWN.Diagnostics.fromnow recognizes aDiagnosticErrorstructurally, so a code still survives when the error crosses a duplicated@kubb/corecopy bundled into an adapter or plugin.@kubb/coreexposesDiagnostics.docsUrl(code)andDiagnostics.serialize(diagnostic), the JSON-safe shape (now including adocsUrl) shared by the JSON reporter and the MCP tools.The MCP
generateandvalidatetools now return structured diagnostics, each with its code, source pointer, help, and docs link, as a readable block plus a JSON payload, so an assistant can act on the exact problem rather than parsing a message string.@kubb/adapter-oasgains an opt-indiagnosticsoption that reports two advisory diagnostics against their JSON pointers as it parses:KUBB_UNSUPPORTED_FORMAT(a warning when a schema'sformatfalls back to the base type) andKUBB_DEPRECATED(info for a schema markeddeprecated). The checks reuse the nodes the parser already produces, so they add no extra traversal of the document. Both default to off, so existing output is unchanged unless you setadapterOas({ diagnostics: { unsupportedFormat: true, deprecated: true } }). (#3449,b4f1e18)Extend diagnostics so more failures are coded and visible.
Coded errors that used to surface as
KUBB_UNKNOWN: a missing Studio adapter (KUBB_ADAPTER_REQUIRED), a non-objectdevtoolsconfig (KUBB_DEVTOOLS_INVALID), and a resolved path escaping the output directory (KUBB_PATH_TRAVERSAL). The OAS adapter checks the input file before reading it in both generation andvalidate, so a missing spec reportsKUBB_INPUT_NOT_FOUND(the MCPvalidatetool returns the coded diagnostic too).The formatter, linter, and post-generate hooks now report failures as diagnostics (
KUBB_FORMAT_FAILED,KUBB_LINT_FAILED,KUBB_HOOK_FAILED). They appear in the run summary andkubb generate --reporter json, and a failure marks the run as failed instead of being swallowed.@kubb/coreaddsdiagnosticCatalog(a title, cause, and fix for every code) andDiagnostics.explain(code), the source the kubb.dev diagnostics pages mirror. (#3449,b4f1e18)Replace the debug logger with selectable reporters.
The
kubb:debughook, thecreateDebuggerhelper, thedebuglog level, and the--debugflag are gone. To write a log file you now pick thefilereporter.Reporters work like Vitest. List them on the CLI with
--reporter(comma separated, for example--reporter cli,file) or in the config withreporters: ['cli', 'file'], where the CLI flag overrides the config. Three are built in:cliwrites the end-of-run summary to the terminal and is the default,jsonwrites a machine-readable report to stdout for CI, andfilewrites a log to.kubb/<name>-<timestamp>.log. The--reporter humanname and the--report <file>flag are removed, so use--reporter jsonfor CI output.The OAS adapter's advisory diagnostics (
KUBB_UNSUPPORTED_FORMATandKUBB_DEPRECATED) always run now. TheadapterOas({ diagnostics })option that gated them is removed.The
kubb:generation:summaryhook is removed. The end-of-run summary theclireporter prints is now built from the run's diagnostics, carried onkubb:generation:end(which gains optionaldiagnostics,status,hrStart, andfilesCreatedfields). (#3449,b4f1e18)
@kubb/cli
Bug Fixes
Fix the clack logger rendering plugins side by side during generation.
Plugins run concurrently, but the logger started a separate
clack.progress()bar per plugin. clack renders one progress UI per line, so the bars collided onto a single line, printed blank gutter rows, and piled upkeypresslisteners until Node warned about an EventEmitter leak. The plugin phase now shares one progress bar that lists the plugins currently generating and advances as each finishes. Thekubb:infoline also no longer prints a trailing space when no extra info is attached. (#3449,b4f1e18)
@kubb/core
Features
Add a structured diagnostics model.
Build failures are collected as structured
Diagnostics instead of raw errors. Each has a stablecode, aseverity, an optional sourcelocation(a JSON pointer), and thepluginthat produced it.BuildOutputnow exposes a singlediagnosticsarray (the formererror,failedPlugins, andpluginTimingsfields are gone), and the build emits each problem on the newkubb:diagnostichook. Per-plugin timings are carried astimingdiagnostics in the same array.@kubb/coreexportshasBuildErrorandgetFailedPluginNamesto read them. Three throw sites carry codes:KUBB_REF_NOT_FOUND,KUBB_INVALID_SERVER_VARIABLE, andKUBB_PLUGIN_NOT_FOUND. (#3449,b4f1e18)Round out diagnostic reporting toward tsc/oxlint/nx parity.
Report without throwing. The diagnostics helpers are now a
Diagnosticsclass.Diagnostics.report(diagnostic)collects into the active run instead of aborting, available on the generator context and, via a singleAsyncLocalStoragein the core bundle, to deep code (adapter parse, lazily consumed streams).Diagnostics.scopeactivates a run, andDiagnostics.dedupecollapses repeats by code + pointer + plugin. (Diagnostics.from/timing/hasError/failedPlugins/countreplace the former standalone functions.)Report every problem in one run. The OAS adapter now reports each unresolved
$refand keeps parsing, so a spec with several bad refs surfaces them all in a singlekubb generate(it still throws when called outside a build).Aggregate count. The end-of-run summary box gains an
Issues: N errors, M warningsrow, so parse-time errors that aren't tied to a failed plugin still show.Machine-readable output.
kubb generate --reporter jsonprints a stable report ({ status, summary: { errors, warnings, files, durationMs }, diagnostics }) to stdout. Exit code is unchanged (non-zero on any error).New codes
KUBB_UNSUPPORTED_FORMAT(warning) andKUBB_DEPRECATED(info) are emitted by the OAS adapter. The renderer, counts, and json report handle every severity. (#3449,b4f1e18)Render build diagnostics in the oxlint style and add a suggested fix.
Diagnosticgains ahelpfield with a suggested fix. The three converted throw sites set it, and the CLI renders a diagnostic as:× @kubb/plugin-zod(KUBB_REF_NOT_FOUND): Could not find a definition for Pet. at #/components/schemas/Pet help: Add the schema under components.schemas, or fix the $ref. docs: https://kubb.dev/docs/5.x/reference/diagnostics/kubb-ref-not-foundThe
docs:link is derived from the code and points at the diagnostics reference on kubb.dev. A failed run also prints anEnvironment:row (Node version, Kubb version, platform, cwd) in the summary box.getDiagnosticInfois exported from@kubb/core. (#3449,b4f1e18)Resolve the renderer from the generator only. The
rendererresolution chain dropped the plugin and config fallbacks, sogenerator.rendereris now the single source.Removed the
rendereroption fromdefineConfig, therendererfield from the normalized plugin, and thesetRenderermethod from the plugin setup context. Setrendereron each generator instead (renderer: jsxRenderer), or leave it unset /renderer: nullto opt out of rendering. (#3447,61ca887)Route the generator context's
warn/error/infothrough the diagnostics layer so plugin-reported problems are collected like every other diagnostic.Until now these methods only emitted
kubb:warn/kubb:error/kubb:infoevents, so a plugin callingctx.error(...)logged a line but the build still succeeded, and the message never reached the run summary or--reporter json. They now report into the active run viaDiagnostics.report(attributed to the plugin) while still emitting their hook event:ctx.errorreports anerrordiagnostic (KUBB_PLUGIN_FAILED), which now fails the build. When passed anError, it is kept as the diagnosticcause.ctx.warnreports awarning(KUBB_PLUGIN_WARNING), andctx.inforeports aninfo(KUBB_PLUGIN_INFO). Neither fails the build.
For a structured diagnostic with a stable
codeand a sourcelocation, callDiagnostics.report(...)or throw aDiagnosticErrordirectly. TheDiagnostic,DiagnosticSeverity,DiagnosticLocation, andDiagnosticKindtypes are now exported so you can build one. (#3449,b4f1e18)Collapse the driver's two listener trackers (
#hookListenersand#middlewareListeners) into one typedHookRegistrythat wrapsAsyncEventEmitter. Listeners attached directly viakubb.hooks.on(...)survivedispose(). Only listeners the driver itself registered are removed. Internal refactor: every(...args: Array<never>)cast insideKubbDriveris gone, and the publicdefinePlugin,KubbHooks, andkubb.hookssurfaces are unchanged. (#3445,bd7e026)
Bug Fixes
Lift the per-plugin transform step into a
Transformregistry that the driver consults during dispatch, so transforms have one home and one contract instead of being inlined inKubbDriver.#runGenerators. The driver keeps the parse and generate logic as private methods (#parseInput,#runGenerators) and exposes the renderer-or-file dispatch as aKubbDriver.applyResultstatic so both the registered generators and@kubb/core/mocksroute through one entry point.Bug fix:
gen.operations(nodes, ctx)and thekubb:generate:operationshook now receive the transformed nodes, matching whatgen.operation(node, ctx)already received per-node. Before this fix the aggregated callback saw the original adapter nodes, so a renaming-transformer would feed grouped or barrel generators a different shape than the per-operation hook saw.The flush-after-batch logic that used to live as a closure inside
KubbDriver.runmoved into a newFileWriteQueueclass. The class also makes the flush non-blocking: the next round of generator dispatch can run while the previous round's source rendering and storage writes are still in flight. For large specs (Stripe-sized OpenAPI documents, thousands of generated files) the pipelined flush keeps peak heap roughly the same and lets CPU work overlap with IO instead of running behind it.The public surface (
setTransformer,KubbHooks, theKubbDriverclass, the@kubb/core/mocksentry) is unchanged. (#3447,61ca887)Stop the hooks emitter from tripping Node's EventEmitter leak warning.
Each generator a plugin registers adds a listener to the shared
kubb:generate:*events, so a config with several multi-generator plugins pushed past the emitter's hardcoded ceiling of 10 and printedMaxListenersExceededWarning: 11 kubb:generate:operation listeners added.Kubb.setup()now sizes the ceiling to the plugin count (max(10, plugins.length * 4)), which keeps leak detection for genuine runaway listeners while leaving room for the generators a normal plugin set registers. (#3449,b4f1e18)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.36 — Jun 1, 2026
@kubb/cli
Bug Fixes
- Update @clack/prompts (
6e39543)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.35 — May 30, 2026
@kubb/core
Bug Fixes
- Tighten internal type safety by removing
anyand unnecessary casts. TheParsertype now defaultsTMetatoobjectinstead ofany,getContextreturns an honestOmit<GeneratorContext, 'options'>rather than laundering a missing field throughas unknown as, and a couple ofas nevercasts are replaced with proper optional types. No runtime behavior or public API change. (#3420,e74cb57)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.34 — May 29, 2026
@kubb/ast
Features
- Export the
isInputNodeandisOutputNodetype guards from the@kubb/astentry point. Both guards were defined and documented inguards.tsbut missing from the barrel, so they could not be imported alongsideisOperationNodeandisSchemaNode. (#3416,e3dd3c6)
kubb
Bug Fixes
- Add a Kubb Claude Code plugin and marketplace. It brings Kubb, a meta framework for code generation, into Claude Code so you can turn an OpenAPI spec into TypeScript types, Zod schemas, Axios clients, React Query hooks and more. The plugin ships
/kubb:init,/kubb:generateand/kubb:validatecommands that run thekubbCLI, aconfigskill and akubb-expertagent, and the@kubb/mcpserver (kubb mcp) for conversational generation. Addkubb-labs/kubbas a plugin marketplace to install it. (#3411,31ad94f)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.33 — May 29, 2026
@kubb/ast
Breaking Changes
Trim the
@kubb/astpublic API to shrink the maintained surface.Removed exports that were unused across both the core monorepo and the plugins, and that duplicated or backed a public counterpart:
- Deleted (dead code):
nodeKindsandmediaTypesconstants (no references anywhere), theRefMaptype, and theInferSchematype alias (useInferSchemaNode). - No longer exported (now internal):
collectLazy— use the eagercollectcreateContent/createRequestBody— content is normalized for you bycreateResponse/createOperationmergeAdjacentObjects— usemergeAdjacentObjectsLazy([...mergeAdjacentObjectsLazy(members)])isSchemaEqual— compareschemaSignature(a) === schemaSignature(b)isScalarPrimitive,resolveRefName,collectReferencedSchemaNames,isInputNode,isOutputNode
The README's
Refsexample also referenced helpers that never existed (buildRefMap,resolveRef); it now documents the realextractRefName. (#3402,ecbde80)- Deleted (dead code):
Bug Fixes
Ship the documented
@kubb/ast/typessubpath and makewalk()traverse concurrently.@kubb/ast/typesis now a real export, so the README'simport type { Node } from '@kubb/ast/types'resolves instead of failing — consumers can pull in node interfaces and visitor types without loading any runtime.walk()now visits sibling nodes concurrently up to itsconcurrencylimit. Previously each child was awaited one at a time, so the documentedconcurrencyoption had no effect and async visitor callbacks always ran serially. (#3402,09563b4)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.32 — May 28, 2026
@kubb/adapter-oas
Bug Fixes
Remove internal dead code flagged by knip in production mode. No public API changes — every removed symbol was unexported (not part of any package's
exports) and unused across the workspace and the plugins repo.@kubb/adapter-oas: drop the orphanedapplyDiscriminatorInheritanceandgetMediaTypehelpers (the streaming path already usesbuildDiscriminatorChildMap/patchDiscriminatorNodedirectly).@kubb/core: drop the unuseddecodeAstdevtools helper.@kubb/ast: drop the unusedbuildRefMap,resolveRef,refMapToObjecthelpers and the unused node guards (isPropertyNode,isParameterNode,isResponseNode,isFunctionParameterNode,isParameterGroupNode,isFunctionParametersNode). The publicRefMaptype andextractRefNameare kept. (#3401,e515a1c)
@kubb/ast
Bug Fixes
Performance: persist schema signatures in a process-wide
WeakMapsignatureOfnow memoizes node → digest in a module-levelWeakMapkeyed by node identity, instead of a freshMapperschemaSignature/buildDedupePlan/applyDedupecall. During streaming, each top-level schema tree was hashed twice — once byschemaSignatureand again byapplyDedupe— so a node is no longer re-hashed once it has been seen. Entries are released when the node is garbage-collected, and reuse is sound because signatures depend only on a node's (immutable) content. (#3396,830896b)refactor(ast): replace describeShape switch with SHAPE_KEYS registry
Internal refactor only — no public API changes. Replaces the 12-case switch statement in
describeShapewith a declarativeSHAPE_KEYSregistry (same pattern asVISITOR_KEYSin visitor.ts). Output is byte-for-byte identical. (#3392,3fe64a8)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.31 — May 26, 2026
@kubb/adapter-oas
Features
Add a
dedupeoption toadapterOasthat collapses structurally identical schemas and enums into a single shared definition.OpenAPI specs frequently repeat the same shape — most often an inline enum (e.g.
['active', 'inactive']) duplicated across many properties, or an identical object reused across schemas and operations. Each unique shape is now emitted once: duplicated inline shapes are hoisted into a named schema, and every other occurrence — including a structurally identical top-level component — becomes arefto it. Equality is shape-only, so differences in documentation such asdescriptionorexampledo not block deduplication. Deduplication is enabled by default; setadapterOas({ dedupe: false })to keep every occurrence inline and reproduce the previous output.@kubb/astgains the spec-agnostic primitives that power this:schemaSignature(a content hash of a schema's shape),isSchemaEqual,buildDedupePlan, andapplyDedupe. (#3387,0ee883f)
Bug Fixes
Treat an enum whose only value is
null(drf-spectacular'sNullEnum,{ enum: [null] }) as anullschema instead of an empty enum.Previously the
nullvalue was stripped, leaving an enum with no values that rendered asnever(@kubb/plugin-ts) or an invalidz.enum([])(@kubb/plugin-zod), silently dropping nullability. The common drf-spectacularoneOf: [StatusEnum, BlankEnum, NullEnum]pattern now generates valid output (e.g.Status | "" | null). (#3384,cf72a72)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.30 — May 25, 2026
@kubb/adapter-oas
Bug Fixes
- Isolate the OpenAPI-specific schema decisions (nullability,
$refdetection and resolution, discriminator, binary) behind a singleSchemaDialectpassed intocreateSchemaParser. The converter pipeline and dispatch rules are now dialect-driven with the OAS dialect as the default, so the spec-specific surface lives in one documented place — the seam a future adapter (e.g. AsyncAPI) targets. No change to generated output. (#3377,287a42a)
@kubb/ast
Features
Add a generic
dispatchhelper andDispatchRuletype to@kubb/ast: an ordered match/convert table that maps source-spec shapes onto Kubb AST nodes.@kubb/adapter-oasnow builds its OAS schema parser on top of it, replacing the longparseSchemaif/else chain with a declarativeschemaRulestable. The mechanism is spec-agnostic, so future adapters (e.g. AsyncAPI) can reuse the same traversal by defining their own context type and rules. No change to generated output. (#3377,f657504)Promote the schema dialect to
@kubb/astas a first-class, spec-agnostic contract: add a generic, guard-preservingSchemaDialect<TSchema, TRef, TDiscriminated, TDocument>type and adefineSchemaDialecthelper, alongsidedispatch.@kubb/adapter-oasnow buildsoasDialectwithast.defineSchemaDialect, so the JSON-Schema-family seam (nullability,$ref, discriminator, binary, ref resolution) is shared across adapters — an AsyncAPI adapter supplies its own dialect and reuses the converter pipeline and dispatch rules. No change to generated output. (#3377,829a8ef)Make the AST node vocabulary spec-neutral so adapters for non-OpenAPI specs (AsyncAPI, GraphQL, Prisma, Arazzo) map onto built-in nodes — the model stays closed and fully typed, no adapter-defined kinds.
OperationNodeis now a discriminated union keyed onprotocol.HttpOperationNode(protocol: 'http') guarantees non-nullablemethodandpath;GenericOperationNodeomits them for non-HTTP transports. New exports:HttpOperationNode,GenericOperationNode,OperationNodeBase, and theisHttpOperationNodeguard.createOperationis overloaded: passingmethod+pathreturns anHttpOperationNodeand auto-setsprotocol: 'http'; otherwise it returns aGenericOperationNode.@kubb/adapter-oassetsprotocol: 'http', so OpenAPI output is unchanged.
Breaking (types): read
method/pathonly after narrowing withisHttpOperationNode(node)ornode.protocol === 'http'.createOperation({ protocol: 'http' })withoutmethod/pathis no longer valid — provide both, or omit all three for a generic operation. (#3380,d06344b)Adopt a Babel-style traversal architecture in
@kubb/ast, keeping the node model uniform and minimal.- Request-body and response content entries are now first-class nodes (
ContentNode), and the request body is aRequestBodyNode, so every child slot in the tree is a node rather than an anonymous wrapper object. - A single
VISITOR_KEYS-style child-field registry now drives bothwalk/collecttraversal and the immutabletransform, replacing the per-kind hand-written tree-shape logic that previously lived in two places. - Adds builders
createContentandcreateRequestBody;createOperation/createResponseapply them automatically, so adapters and existing call sites need no changes.
Note: a schema reached through a request/response body now reports its
parentas the enclosingContentNode(previously theOperationNode/ResponseNode). (#3375,c5f5227)- Request-body and response content entries are now first-class nodes (
transformnow preserves identity (structural sharing): when a pass leaves a node and all its descendants unchanged it returns the same reference instead of reallocating the subtree. No-op rewrites become free and callers can detect "nothing changed" by reference, which keeps caches valid and cuts allocations on large specs. Adds anupdate(node, changes)factory — an identity-preserving shallow update, the analogue of the TypeScript compiler'sfactory.updateX. (#3377,29b83a8)
Bug Fixes
Reduce internal complexity in the AST, core, and CLI packages to make them easier to work with and debug. No public API or generated output changes.
@kubb/ast:walk,transform, andcollectLazynow share a single node-kind dispatch helper instead of three duplicatedswitchstatements, andcombineExports/combineImportsshare a name-merge helper.@kubb/core: the schema and operation generator passes inKubbDriverare unified into one dispatch function.@kubb/cli: the clack, GitHub Actions, and plain loggers share progress-counter and hook-timing helpers. (#3375,de7a15c)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.29 — May 23, 2026
@kubb/ast
Features
Add multiple response content type support to the AST and OpenAPI parser.
ResponseNodenow mirrorsrequestBody: the response body schemas live exclusively inside acontentarray (one entry per content type), instead of a single root-levelschema/mediaType. This removes the duplicated schema that previously sat both on the node root and insidecontent. The OpenAPI parser populates every content type declared for a status code; body-less responses keep a singlecontententry whose schema is the empty/voidplaceholder. When the adaptercontentTypeoption is set, only that content type is kept.For convenience
createResponsestill accepts a singleschema(with optionalmediaType), normalizing it into onecontententry, so existing callers keep working. (#3373,d70b887)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.28 — May 23, 2026
@kubb/ast
Bug Fixes
Keep a default import when a used named import from the same module path is retained.
Previously, when operations were grouped into a single file, a used default import (such as a generated
clientruntime) could be dropped during the merge because its binding was not found in the reconstructed source string, producing references to an undefined value.combineImportsnow retains a default import whenever a used named/type import from the same path survives. (#3367,a15e7f7)
@kubb/core
Features
Give
output.banner/output.footerper-file context so a directive like'use server'can be skipped on re-export files.A
banner/footerfunction now receives aBannerMeta— the documentInputMetaextended with the file it is rendered into:filePath,baseName,isBarrel(anindex.tsbarrel), andisAggregation(a group[dir]/[dir].tsfile). Existing(meta) => ...functions keep working sinceBannerMetaextendsInputMeta.tspluginClient({ output: { banner: (meta) => (meta.isBarrel || meta.isAggregation ? '' : "'use server'"), }, })Barrel
index.tsfiles are now also banner-controllable: when a plugin configuresoutput.banner/footer, the barrel middleware applies it (flaggedisBarrel: true). Barrels stay banner-free by default and never inherit the implicit "Generated by Kubb" notice. (#3371,699f924)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.27 — May 23, 2026
@kubb/adapter-oas
Bug Fixes
parseSchemanow propagates the parent name through every call site that previously dropped it: array items (convertArray),allOfmembers (single, multi, and synthetic required-key + outer-properties),oneOf/anyOfmember schemas, union members, operation responses ({operationId}Status{statusCode}), request bodies ({operationId}Request), and parameters ({operationId}{ParamName}).- Operation response schemas now use
Status<code>(matching plugin-ts'sresolveResponseStatusNameconvention) so qualified enum names don't collide with top-level component schemas named<operation><statusCode>(e.g.GetMaintenance200). - Two test expectations updated to reflect the new contracts:
- Parameter top-level enums now carry a parser-level name (qualified with operation + param name) so plugin-generated downstream identifiers stay collision-free.
- The synthetic injected-required-key member inside an
allOfis now named so its nested enums qualify correctly; it consequently shows up as a separate intersection member instead of being adjacent-merged. (#3363,2cb22fe)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.26 — May 22, 2026
@kubb/adapter-oas
Bug Fixes
- Enforce
Array<T>syntax (overT[]) via the oxlinttypescript/array-typerule. Internal-only change; no runtime or API impact. (#3360,ab0abb1)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.25 — May 22, 2026
@kubb/parser-md
Features
Add
@kubb/parser-mdfor emitting.mdand.markdownfiles. The parser exposesparserMd.printfor serialising frontmatter objects to YAML envelopes and readsfile.meta.frontmatterto prepend frontmatter automatically.Add markdown components to
@kubb/renderer-jsx—Frontmatter,Heading,Paragraph,CodeBlock,List,Callout— for authoring.mdfiles declaratively in JSX.Calloutemits GitHub-style alert syntax (> [!TIP]) portable across GitHub, GitLab, VitePress, Obsidian, and MDX. (#3358,8154649)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.24 — May 21, 2026
@kubb/core
Features
Expose
printonparserTsandparserTsx, slim@kubb/parser-tspublic API to just those two parsers.Parser(from@kubb/core) now requires aprint(...nodes): stringmethod that renders compiler AST nodes for the parser's language. The TypeScript and TSX parsers implement it viaparserTs.print(...)/parserTsx.print(...).@kubb/parser-tsno longer re-exports the standalone helpersprint,safePrint,createImport,createExport, orvalidateNodes. Plugins that depended onprint/safePrintshould callparserTs.print(...)instead. Custom parsers built withdefineParserneed to add aprintimplementation matching their AST node shape. (#3356,69e8c5a)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.23 — May 21, 2026
@kubb/agent
Features
Forward additional Kubb lifecycle events to Studio for full event parity with
@kubb/core.The agent now relays
kubb:lifecycle:start,kubb:lifecycle:end,kubb:build:start,kubb:build:end,kubb:format:start,kubb:format:end,kubb:lint:start,kubb:lint:end, andkubb:generation:summaryover the Studio WebSocket. Studio can now render a complete build timeline (per-config build span, format/lint phases) and final generation summary (duration, file count, failed plugins). (#3344,4476049)
@kubb/cli
Bug Fixes
Pass the full CLI options to user-defined config functions.
defineConfig(({ watch, logLevel, config }) => ...)now actually receiveswatch,logLevel, andconfigat runtime. Previously the CLI runner cast{ input }toCLIOptions, so the other fields were silentlyundefinedeven though the type promised otherwise.CLIOptions.inputis now a documented field (so the cast disappears) andCLIOptions.logLeveladds the missing'verbose'value to match the CLI's--logLevelflag.ts// Now works as expected export default defineConfig(({ watch }) => ({ input: { path: './petStore.yaml' }, output: { path: './src/gen', clean: !watch }, })) ``` ([#3346](https://github.com/kubb-labs/kubb/pull/3346), [`aa8aad3`](https://github.com/kubb-labs/kubb/commit/aa8aad31bf902dc83acf2f2e316d1a4e0b3c8d8c))
kubb
Bug Fixes
- Correct the JSDoc on
defineConfig:output.formatandoutput.lintdefault tofalse, not'auto'. The code already appliesfalsewhen the user does not set either option; only the comment was wrong. (#3346,aa8aad3) defineConfignow defaultsroottoprocess.cwd()when omitted. This fixesThe "paths[0]" argument must be of type string. Received undefinedthrown after successful generation whenkubb.config.tsdid not defineroot(the CLI then calledpath.resolve(config.root, …)on the un-normalized config).@kubb/core's internalresolveConfigalready defaultedrootfor the driver, so generation itself succeeded — the error fired in the CLI's post-generationoutputPathresolution. (#3352,49a60c8)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.22 — May 20, 2026
@kubb/core
Bug Fixes
- Make sure we can exclude/include operations (
fa572bb)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.21 — May 20, 2026
@kubb/ast
Features
Standardize
nullvsundefinedacross the codebase: Kubb-controlled "absent" or "skip" states now usenullexplicitly;undefinedis reserved for optional TypeScript properties and external/user-supplied values.Breaking changes
@kubb/astnarrowSchemanow returnsT | nullinstead ofT | undefinedwhen the node type does not match.ts// Before const objectNode = narrowSchema(node, 'object') // ObjectSchemaNode | undefined // After const objectNode = narrowSchema(node, 'object') // ObjectSchemaNode | nullcollectImportsresolvecallback must returnTImport | null(instead ofTImport | undefined) to skip an import.ts// Before collectImports({ node, nameMapping, resolve: (name) => undefined }) // After collectImports({ node, nameMapping, resolve: (name) => null })CollectVisitor<T>callbacks may now returnT | null | undefined; bothnullandundefinedare treated as "skip this node".RefSchemaNode.schemais nowSchemaNode | null | undefined—nullmeans the ref was resolved but circular or unresolvable;undefinedmeans resolution was not attempted.keysToOmitonRequestBodyContentandResponseNodenow acceptsArray<string> | null.InputMeta.baseURLis nowstring | null.@kubb/coreFileManager.setOnUpsertnow acceptsnullto detach the callback (previouslyundefined).@kubb/adapter-oasresolveBaseUrlnow returnsstring | null(previouslystring | undefined) whenserverIndexis omitted or out of range. (#3334,2164a73)
@kubb/core
Features
Performance improvements and event API cleanup in
KubbDriverandFileManager.Breaking changes
kubb:file:processing:update(singular, fired once per file) is replaced bykubb:files:processing:update(plural, fired once per flush chunk with afilesarray). Update any listener from:tshooks.on('kubb:file:processing:update', ({ file, source, processed, total, percentage, config }) => { // handle one file })to:
tshooks.on('kubb:files:processing:update', ({ files }) => { for (const { file, source, processed, total, percentage, config } of files) { // handle each file } })KubbFileProcessingUpdateContextis renamed toKubbFileProcessingUpdate(the per-item type). A newKubbFilesProcessingUpdateContextwrapsfiles: Array<KubbFileProcessingUpdate>.Performance improvements
FileManagersorts lazily: the sorted view is rebuilt from#cacheonly whenfilesis read, not on everyadd/upsert. Upserts are now O(1) with a singlenullassignment to mark the view stale.FileManager.#storefast-paths single-file calls (the common case) — skips the intermediate deduplicationMap.mergeFileavoids unnecessary array allocations when one side'ssources/imports/exportsis empty — returns the non-empty reference directly.createFile(SHA-256 + import/export combining) is skipped for new files that don't require merging with an existing cache entry.kubb:generate:schemaandkubb:generate:operationare gated onlistenerCount— for builds with no listeners on these channels the per-node emit overhead is eliminated entirely.FileProcessoris a long-lived class field onKubbDriverrather than a per-run()scoped resource.dispose()methods added toFileProcessor,Kubb, andRendererimplementations, with[Symbol.dispose]()delegating to them consistently across the codebase. (#3334,2164a73)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.20 — May 20, 2026
@kubb/adapter-oas
Features
All OpenAPI specs now go through the streaming path, removing the size-based threshold that previously switched between eager and lazy parsing.
The adapter's internal streaming logic is extracted into a dedicated
stream.tsmodule (preScan,createInputStream,resolveBaseUrl) so it can be tested in isolation without going through the full adapter pipeline.preScanand the other internalensure*helpers each run at most once per adapter instance. Concurrent callers (e.g.stream()andparse()called simultaneously) share the same in-flight work and cannot trigger duplicate parses or validation passes. (#3331,fd3a585)
@kubb/ast
Features
InputMetagains two pre-computed fields that plugins previously had to derive themselves by iterating the full schema list.circularNames— names of schemas that participate in a circular reference chain. Replaces callingast.findCircularSchemas(inputNode.schemas)inside each plugin.enumNames— names of every enum schema in the document. Replaces filtering the schema stream by type.
Both fields are plain
readonly string[]arrays, keepingInputMetafully JSON-serializable.GeneratorContextnow exposesmeta: InputMetainstead ofinputNode: InputNode. Plugins that previously destructuredinputNodeto access circular or enum information should switch toctx.meta.circularNamesandctx.meta.enumNames. (#3331,fd3a585)
@kubb/core
Features
KubbDriverandcreateKubbare cleaned up around the always-stream architecture.STREAM_SCHEMA_THRESHOLDconstant is removed. All builds now go through the streaming code path regardless of spec size.- Studio-related state (
source,isOpen,inputNode) is consolidated into a single#studioobject onKubbDriverinstead of three separate private fields. runAstPluginis removed fromcreateKubb.runPluginsis the only plugin runner now.- Plugin lifecycle events (
kubb:plugin:start,kubb:plugin:end) fire for every plugin, including those without an adapter configured. middlewareListeners,#eventGeneratorPlugins, andhasEventGeneratorsreplace the previous publicmiddlewareListeners,#pluginsWithEventGenerators, andhasRegisteredGeneratorsfor naming consistency.forBatchesno longer accepts aflushIntervaloption. Theflushcallback now runs after every batch; callers that need coalescing should do so inside their ownflushimplementation. (#3331,fd3a585)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.19 — May 19, 2026
@kubb/core
Bug Fixes
Significantly reduce per-file overhead in the code-generation pipeline.
@kubb/parser-tsparseis now synchronous — returnsstringdirectly instead ofPromise<string> | string.FileProcessor.streamis a plainGeneratorinstead ofAsyncGenerator, removing a microtask per file. TheemitImport/emitExportstring-emit helpers have been removed; import and export statements are generated through the TypeScript compiler API as before.@kubb/coreRenderer.streamnow returnsIterable<FileNode>only —AsyncIterablesupport has been dropped.Parser.parseis typed asstring(synchronous). Adapter initialisation consolidates the streaming / non-streaming branches, removing a duplicate debug-log path.flushPendingFilesremoves a deadsnapshotparameter.@kubb/adapter-oascaches the underlyingBaseOasinstance and the schema parser at adapter scope so the schemas and operations iterables share one instance instead of rebuilding indexes per pass.@kubb/renderer-jsxjsxRendererSyncreturns a synchronousGeneratorfromstream, letting consumers skip the per-file microtask. (#3327,014004f)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.18 — May 18, 2026
@kubb/adapter-oas
Bug Fixes
@kubb/core
Bug Fixes
- Add
Symbol.disposesupport:FileManagerandPluginDriverimplement[Symbol.dispose]().safeBuild()usesusinginstead oftry/finally. Fix resource leaks: chokidar watcher closes onSIGINT/SIGTERM; Studio WebSocketmessagelistener removed incleanup(); MCP HTTP server closes gracefully on signal. (#3321,03ad8ce)
@kubb/renderer-jsx
Bug Fixes
- Add
jsxRendererSync— a React-free recursive renderer 2–4× faster thanjsxRenderer. Addstream()for incremental file processing. Node attributes use plain objects instead ofMap.jsxRendereris unchanged; all new APIs are additive. (#3319,6ab3a5e)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.17 — May 18, 2026
kubb
Features
- Add
@kubb/mcpas a direct dependency sokubb mcpworks out of the box without a separate install step. (#3317,4066e7a)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.16 — May 18, 2026
@kubb/core
Features
- Add
FileProcessor.stream()— an async generator that yields oneParsedFileat a time.run()now delegates tostream()internally, removing themode: 'sequential' | 'parallel'option and thep-limitdependency.safeBuild()now flushes files after each plugin rather than all at once. (#3310,7dffff1)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.15 — May 17, 2026
@kubb/ast
Features
- Performance improvements for large OpenAPI specs: add
mergeAdjacentObjectsLazyfor lazy stateful merging of adjacent allOf schemas; memoizecollectReferencedSchemaNameswith aWeakMap. (#3305,62f72dd)
@kubb/adapter-oas
Bug Fixes
- Replace
flatMapcontent-type loop withfor/push(7× faster for typical 2–4 content types). (#3305,62f72dd)
@kubb/core
Features
- Parallelize per-node generator dispatch with
Promise.all. ConvertfsStoragedirectory walk to an async generator for streaming traversal. (#3305,62f72dd)
@kubb/cli
Bug Fixes
- Show live progress for formatter, linter, and custom hooks in the CLI. The clack logger now renders a live
taskLogper hook that streams subprocess output while it runs. (#3306,dfa488a)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.14 — May 16, 2026
@kubb/ast
Features
- Export
collectLazy()— a generator version ofcollect()that yields results one at a time without materializing an intermediate array.getChildren()andcollectRefs()are now generators internally.containsCircularRef()exits at the first match. (#3301,647207f)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.13 — May 16, 2026
@kubb/cli
Bug Fixes
- Fix multiple configs in
defineConfigarray stopping after the first failure. Each config is now processed independently; the process exits with code 1 after all configs complete if any failed. Middleware listeners are tracked and removed viaSetupResult.dispose()between runs to prevent duplicate output. (#3297,d66969f)
@kubb/middleware-barrel
Features
getBarrelFilesnow returns aGenerator<FileNode>instead ofArray<FileNode>. Iterate withfor...ofor spread with[...getBarrelFiles({ ... })]. (#3294,164881b)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.12 — May 15, 2026
@kubb/adapter-oas
Bug Fixes
- Memoize
$refresolution withinparse()so each$refis resolved at most once. Stripe (~1 400 schemas) went from OOM at 8 GB to ~840 ms / ~15 MB. (#3293,3f5504b)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.11 — May 14, 2026
@kubb/ast
Features
- Reduce peak memory by leaning on the existing
Storageabstraction.BuildOutput.sourcesis replaced byBuildOutput.storage— a read-throughStorageview backed byconfig.storage.FileProcessornow exposes a typedeventsproperty withstart,update, andendevents; the previousonStart,onUpdate, andonEndcallback options are removed.Kubb.driverandKubb.confignow throw if accessed beforesetup()instead of returningundefined. (#3285,ec10ea8)
@kubb/core
Bug Fixes
- Further reduce peak memory: files are written after each plugin completes and already-written files are skipped via a
writtenPathsset.PluginDriver.dispose()clears#resolversand#defaultResolvers.createSourcesView.getKeysiterates theSetdirectly instead of materialising the full key array. (#3285,0752d86)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.10 — May 12, 2026
@kubb/ast
Bug Fixes
- Fix
ThisTypeaugmentation in AST resolver type. (7a6ba31)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.9 — May 12, 2026
@kubb/core
Bug Fixes
- Add
ThisTypeto core resolver type. (54e54b4)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.8 — May 12, 2026
@kubb/parser-ts
Bug Fixes
- Extract utility functions from
parserTs.tsinto a dedicatedutils.tsmodule for improved testability. No public API changes. (0558297)
@kubb/renderer-jsx
Breaking Changes
- Remove
createRendererexport. UsejsxRenderer()directly to obtain a renderer instance.jsxRendereris now a plain factory function with no dependency on@kubb/core, resolving the circular package dependency. (0558297)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.7 — May 12, 2026
@kubb/cli
Bug Fixes
- Refactor CLI runners into per-command folders (
runners/generate/,runners/validate/, etc.), each with a dedicatedrun.tsandutils.ts. Fixesimport.meta.resolvebuild warning and a faulty path-traversal guard inhasPackageJson. (#3268,5030b03)
@kubb/middleware-barrel
Bug Fixes
- Align unplugin generation defaults with the main Kubb config flow and declare the middleware barrel AST runtime dependency. (
2bf409c)
unplugin-kubb
Bug Fixes
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.6 — May 9, 2026
@kubb/adapter-oas
Breaking Changes
- Remove
parseDocument,parseFromConfig, andvalidateDocumentfrom the public API. Useadapter.validate(input, options?)instead. (#3249,8a666d7)
@kubb/agent
Bug Fixes
- Fix agent Docker build: copy full jiti package so
dist/babel.cjsis available at runtime. (62fb218)
@kubb/cli
Bug Fixes
- Make
@kubb/adapter-oasan optional peer dependency for thekubb validatecommand — lazy-loaded only when validation runs. (#3247,38f92e9) - Add
--port(-p) and--hostoptions to themcpcommand for HTTP MCP server mode. (#3254,5fa651a)
@kubb/core
Features
- Add required
validatemethod to theAdapter<T>type so all adapters must implement validation support. (#3249,8a666d7)
@kubb/mcp
Features
- Replace
@modelcontextprotocol/sdkwithtmcpfor full TypeScript inference from Zod schemas. AddvalidateandinitMCP tools. ExportcreateMcpServer. Add HTTP transport support via--portflag. (#3254,5fa651a)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.5 — May 6, 2026
@kubb/agent
Bug Fixes
- Add
@kubb/parser-tsto the defaultKUBB_PACKAGESbuild ARG in the agent Dockerfile. (#3233,23d60be) - Fix Docker build failure on distroless image by replacing
RUN chownwith--chownflags onCOPYinstructions. (#3231,2fe62b5) - Replace
unrunwithjitifor loading TypeScript config files at runtime — pure JavaScript, no native binaries. (ea3233b)
@kubb/cli
Bug Fixes
- Replace
unrunwithjitifor loading TypeScript config files at runtime. (ea3233b)
@kubb/mcp
Bug Fixes
- Replace
unrunwithjitifor loading TypeScript config files at runtime. (ea3233b)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.4 — May 3, 2026
@kubb/adapter-oas
Features
- Ship an
extension.yamlmanifest (kind: adapter) describing the package's options, examples, and resources. References the sharedextension.jsonschema for IDE validation. (#3224,0542031)
@kubb/core
Features
- Make
adapterandinputoptional inConfigto support plugin-only mode. Whenadapteris omitted, Kubb skips the spec parse phase and runs using only its file-management layer. (#3226,81fbfae)
@kubb/middleware-barrel
Features
@kubb/parser-ts
Features
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.3 — Apr 30, 2026
@kubb/ast
Bug Fixes
- Fix
combineImportsproducing duplicate object-named import specifiers.Set-based deduplication failed for object import names because objects are compared by reference; the fix memoizes(propertyName, name)pairs so identical specifiers reuse the same object reference. (#3217,4759c9c)
@kubb/cli
Bug Fixes
- Move
@kubb/agentand@kubb/mcpto optionalpeerDependenciesto reduce default install size. (#3215,9ecce54)
kubb
Bug Fixes
- Move
@kubb/agentand@kubb/mcpto optionalpeerDependenciesto reduce default install size. (#3215,9ecce54)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.2 — Apr 30, 2026
@kubb/adapter-oas
Features
- Change the default value of
integerTypefrom'number'to'bigint'.int64fields are now mapped tobigintby default; setintegerType: 'number'to preserve the previous behaviour. (#3209,9e90cbb)
@kubb/ast
Features
- Fix
includefilter not preventing generation of component schemas from excluded operations. Only schemas transitively referenced by included operations are now generated. New export:collectUsedSchemaNames(operations, schemas). (#3208,3cd3a09)
Bug Fixes
- Fix
combineImportsincorrectly tree-shaking aliased named imports — the used-check now tests the alias rather than the original export name. (#3212,0e5bfaa)
@kubb/core
Bug Fixes
- Fix
includefilter scoping: only schemas reachable from included operations are generated. (#3208,3cd3a09)
@kubb/middleware-barrel
Breaking Changes
- Replace string-based
barrelTypewith an object-basedbarrelconfiguration. Root config:barrel?: { type: 'all' | 'named' } | false. Plugin level:barrel?: { type: 'all' | 'named', nested?: boolean } | false.barrelType: 'propagate'becomesbarrel: { type: 'all' | 'named', nested: true }. (#3200,3519370)
Contributors
Thanks to everyone who contributed to this release:
v5.0.0-beta.1 — Apr 29, 2026
kubb
Bug Fixes
- Update packages (
c17c092)
Contributors
Thanks to everyone who contributed to this release: