This guide helps teams move from semantic-release or changesets to ReleaseKit. Both migrations follow the same broad pattern: install, create a config, swap the workflow step, dry-run, then remove the old tool.
| If you want... | semantic-release | changesets | releasekit |
|---|---|---|---|
| Convention-driven bumps from commits | yes | partial (via plugins) | yes |
| Per-PR explicit bump intent (changeset files) | no | yes | partial (label-driven) |
| Standing release PR you can review before publish | no | yes | yes |
| LLM-enhanced changelogs | no | no | yes |
| Rust/Cargo support | no | no | yes |
| Mixed npm + cargo monorepo | no | no | yes |
| Zero-install PR previews via GitHub Action | no | no | yes |
| semantic-release concept | releasekit equivalent |
|---|---|
release.config.js plugins array |
Built-in stages; releasekit.config.json sections |
@semantic-release/commit-analyzer |
Built-in (conventional commits, configurable preset) |
@semantic-release/release-notes-generator |
@releasekit/notes stage |
@semantic-release/npm |
publish.npm config |
@semantic-release/github |
publish.githubRelease config |
branches config |
Release branch via git.branch; prerelease channels via the channel:prerelease label |
SEMANTIC_RELEASE_PACKAGE env var |
--target flag or version.packages config |
.releaserc / release.config.js |
releasekit.config.json |
There is no plugin system to reason about. Each stage (version, notes, publish) is built in and enabled or disabled via config keys. You gain Rust/Cargo support, LLM-enhanced notes, and a first-class monorepo model without installing additional packages.
-
Install ReleaseKit.
npm install -g @releasekit/release # or pnpm add -g @releasekit/release -
Scaffold a config. Run
releasekit initto generatereleasekit.config.jsonin your project root, then port your semantic-release options into it. The init command detects monorepo layouts automatically. -
Note the key differences from semantic-release:
- No plugin packages to install — all behaviour is configured in
releasekit.config.json. - npm provenance is on by default.
- OIDC is the default npm auth method in CI; no
NPM_TOKENsecret is required when you use trusted publishing. See CI setup for details. - The commit preset defaults to
conventional. If you were usingangularin@semantic-release/commit-analyzer, set"version": { "preset": "angular" }to preserve your existing changelog groupings.
- No plugin packages to install — all behaviour is configured in
-
Replace the workflow step. Remove the semantic-release step from your GitHub Actions workflow and add
releasekit releasein its place. A minimal replacement:- run: pnpm exec releasekit release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
See CI setup for complete workflow examples including OIDC publishing and label-based triggers.
-
Dry-run before committing.
releasekit release --dry-run
This runs the full pipeline — version analysis, changelog generation, publish simulation — without writing files, creating tags, or publishing packages.
-
Remove semantic-release once you have a clean release cycle through ReleaseKit.
A common semantic-release setup and its releasekit.config.json equivalent:
{
"$schema": "https://goosewobbler.github.io/releasekit/schema.json",
"version": {
"preset": "angular",
"packages": ["./"]
},
"notes": {
"changelog": { "mode": "root" }
},
"publish": {
"npm": { "enabled": true },
"githubRelease": { "enabled": true }
}
}For a monorepo, change changelog.mode to "packages" and list your packages in
version.packages. See the configuration reference for all available keys.
| changesets concept | releasekit equivalent |
|---|---|
.changeset/*.md files |
Conventional commits across feeder PRs (default) |
pnpm changeset (create changeset) |
Write conventional commit messages (feat:, fix:); the standing PR's bump is computed from the union of commits |
| Override the bump on the upcoming release | Add bump:major (or other) on the standing PR itself |
pnpm changeset version |
releasekit standing-pr update (runs automatically) |
| "Version Packages" PR | Standing release PR (ci.releaseStrategy: "standing-pr") |
pnpm changeset publish |
Merge the standing PR (publish runs automatically) |
| Ship one PR urgently without queueing | Add release:immediate to the feeder PR |
| Retry a publish that failed partway | Add release:retry to the merged standing PR |
.changeset/config.json |
releasekit.config.json |
fixed packages (move together) |
version.sync: true |
linked packages |
Not directly supported; use version.sync |
ignore packages |
version.skip array |
The main conceptual shift is that bump intent moves from committed markdown files to the
standing PR itself. Conventional commits across feeder PRs are aggregated into the standing
PR's bump; if you need to override the magnitude (e.g. escalate from minor to major), add a
bump:* label directly to the standing release PR. Feeder-PR labels are advisory only —
they're shown in the preview but don't drive behavior. This keeps your repository history
clean (no .changeset/ files), avoids merge conflicts on changesets in active monorepos, and
gives you one canonical place to see and adjust what's about to release.
Changesets users are used to reviewing a "Version Packages" PR before publishing. The
standing-pr strategy is the direct analogue: ReleaseKit maintains a PR that accumulates
releasable changes, shows what will be released, and publishes when you merge it.
Optional guardrails mirror changesets' workflow:
ci.standingPr.minAge— hold the PR open for a minimum duration (e.g."6h") before the status check turns green, giving the team time to review.ci.standingPr.minPackages— require at least N packages with releasable changes before a PR is created.
-
Install ReleaseKit.
npm install -g @releasekit/release # or pnpm add -g @releasekit/release -
Create
releasekit.config.jsonwith the standing-PR strategy:{ "$schema": "https://goosewobbler.github.io/releasekit/schema.json", "ci": { "releaseStrategy": "standing-pr" }, "publish": { "npm": { "enabled": true } } } -
Pick a release trigger (in standing-pr mode, this only affects the
release:immediatebypass path — see step 6; the standing PR itself is always commit-driven regardless of trigger)."releaseTrigger": "commit"— for the immediate-release path, every merged PR withrelease:immediateships using conventional commits to determine the bump."releaseTrigger": "label"— for the immediate-release path, the merged PR must also carrybump:patch/minor/majorto specify the magnitude.
-
Add the standing-PR workflow. Copy the template from
templates/workflows/standing-pr.ymlinto.github/workflows/. See CI setup for the full workflow YAML, required secrets, and lifecycle details. -
Enable Actions write access. Go to your repository Settings > Actions > General and enable "Allow GitHub Actions to create and approve pull requests". This is required for the bot to manage the release PR.
-
Remove changeset files. Delete
.changeset/*.mdand.changeset/config.json. Existing changelog text should be retained — see the stumbling blocks section below. -
Dry-run the update.
releasekit release --dry-run
You can run ReleaseKit alongside the old tool for a few releases before fully switching over:
- Use
version.tagTemplateto give ReleaseKit a distinct tag prefix, preventing it from picking up tags created by semantic-release or changesets during the overlap period. - In a monorepo, use
--targetto point ReleaseKit at a subset of packages while the old tool continues to manage the rest.
Remove the old tool only after at least one clean release cycle has completed through ReleaseKit.
"My CHANGELOG.md format looks different."
ReleaseKit uses a template-based renderer (Handlebars/Liquid/EJS). Refer to the
@releasekit/notes configuration docs for template customisation options. The default format
follows Keep a Changelog conventions.
"Tags now have a prefix I did not have before."
Set version.versionPrefix: "" to strip the v prefix, or "v" to make it explicit. Use
version.tagTemplate for a fully custom format (e.g. ${packageName}/${prefix}${version} for
monorepos).
"I lost my changeset / semantic-release history."
Copy your existing CHANGELOG.md content into the file before the first ReleaseKit run.
Subsequent releases prepend new entries; existing content is left intact.
"My prerelease workflow is broken."
ReleaseKit uses the --prerelease <id> CLI flag or the channel:prerelease PR label combined
with a bump:* label. See CI setup for the label
combination table and prerelease workflow examples.
"Nothing is being released."
Check that your commits follow Conventional Commits
format. If you are using label-based triggers, confirm the merged PR has a bump:patch,
bump:minor, or bump:major label. Run releasekit release --dry-run --verbose for
diagnostic output.
- Getting started — installation and first release
- Configuration reference — all
releasekit.config.jsonkeys - CI setup — complete GitHub Actions workflow recipes
- @releasekit/release README — CLI flags and programmatic API