Package Version Management#
Kubb's package ecosystem spans two GitHub repositories — kubb-labs/kubb (the CLI and core framework) and kubb-labs/plugins (official plugins). This split creates two distinct version-skew surfaces that each have dedicated mitigations: dist-tag pinning at scaffolding time and pnpm catalog pinning at development/publish time.
1. Dist-Tag Pinning in kubb init#
When a user runs kubb init, the CLI collects plugin selections and installs packages pinned to the same release channel as the running CLI binary. This is implemented in withDistTag:
- The function extracts the prerelease identifier from the CLI's version string via
/-([a-z]+)/(e.g.,betafrom5.0.0-beta.105). - Each package is installed as
<name>@<tag>— so a beta CLI installskubb@beta,@kubb/plugin-ts@beta, etc. - A stable CLI version (no prerelease segment) installs everything
@latest.
The tag is applied in run.ts to the full install list — kubb plus every selected plugin's packageName — before invoking the package manager. The available plugins and their packageName values are defined in availablePlugins.
Why this matters: Without dist-tag pinning, npm install kubb @kubb/plugin-ts on a beta-user machine would silently pull @latest (the older stable major), producing a plugin/CLI version mismatch. The test suite for withDistTag explicitly covers beta, arbitrary prerelease, and stable scenarios .
2. pnpm Catalog Pinning in the Plugins Repo#
The kubb-labs/plugins monorepo uses pnpm's native catalog feature to centralize all @kubb/* and kubb version pins in one place: pnpm-workspace.yaml.
Key entries in the catalog (as of 5.0.0-beta.104):
| Package | Catalog pin |
|---|---|
kubb | 5.0.0-beta.104 |
@kubb/adapter-oas | 5.0.0-beta.104 |
@kubb/core | 5.0.0-beta.104 |
@kubb/plugin-barrel | 5.0.0-beta.104 |
@kubb/parser-ts | 5.0.0-beta.104 |
Every plugin's package.json references these with "kubb": "catalog:" in both peerDependencies and devDependencies . The catalog: specifier is resolved by pnpm both during local development (pnpm install) and at publish time — no custom pre-publish script is needed.
Why this matters: Without catalog centralization, bumping kubb from beta.104 to beta.105 would require touching every plugin's package.json individually. Instead, a single edit to pnpm-workspace.yaml propagates the new pin across all 11+ plugin packages.
The commented-out overrides block in pnpm-workspace.yaml provides a ready-made pattern for swapping all catalog pins to local link: references during cross-repo development, useful when testing core changes against plugins before publishing.
3. Changesets and Peer Dependency Release Coordination#
The plugins repo uses Changesets for releases. The configuration at .changeset/config.json includes two notable settings:
updateInternalDependencies: patch— automatically bumps inter-plugin dependencies on each release, preventing stale workspace refs.onlyUpdatePeerDependentsWhenOutOfRange: true— limits cascading peer-dep version bumps to only when the new version actually falls outside the declared range .
@internals/* packages and example apps (*-pet-store) are excluded from versioning, keeping changelogs clean .
Key Files#
| File | Purpose |
|---|---|
internals/shared/src/init.ts | withDistTag — dist-tag resolution logic |
packages/cli/src/runners/init/run.ts | kubb init wizard, calls withDistTag at install time |
internals/shared/src/constants.ts | availablePlugins — plugin registry with package names |
pnpm-workspace.yaml (plugins repo) | Catalog version pins for all @kubb/* packages |
plugin-react-query/package.json | Example of catalog: peer dependency reference |
.changeset/config.json | Changesets release config with peer dep cascade rules |