Safe Changesets Versioning with Claude Code
Use Claude Code with Changesets for SemVer, release notes, monorepos, CI, and safer npm publishing.
Claude Code can make release work faster, but package versions are the wrong place to be casual. A patch that should have been a minor release can hide a new API. A breaking change shipped as a patch can break downstream builds. A private workspace package accidentally published to npm can leave a permanent mess.
This guide shows a practical workflow for using Changesets with Claude Code. The goal is not to let AI choose versions blindly. The goal is to make humans define the release policy, then use Claude Code to inspect diffs, draft changesets, check changelog quality, and catch risky publish settings. Keep the SemVer specification, the Changesets documentation, the npm publishing docs, and the GitHub Actions docs open while adapting this to your repository.
For adjacent ClaudeCodeLab material, pair this with CLAUDE.md best practices, CI/CD setup, and monorepo management.
What Changesets Controls
Changesets records release intent in .changeset/*.md files. Those files later drive package versions, changelogs, release pull requests, and publishing. That is different from simply asking an assistant to edit package.json.
SemVer means semantic versioning: major.minor.patch. A patch release fixes bugs without changing the public contract. A minor release adds backward-compatible functionality. A major release may require users to change their code. Explain that rule to Claude Code in the prompt, because an AI model can otherwise over-focus on file size or wording and miss the actual public API impact.
Use cases where this setup pays off:
| Use case | Release risk | What Claude Code can review |
|---|---|---|
| UI component package | Props, variants, CSS tokens, peer dependencies | Whether the bump matches the public API change |
| CLI package | Flags, command names, exit codes | Whether README, tests, and code still agree |
| Monorepo package set | Internal dependency ranges | Whether a dependent package also needs a bump |
| Private/internal package | Accidental npm publication | private, ignore, registry, and token settings |
Initial Setup
Install Changesets and initialize the .changeset directory.
npm install -D @changesets/cli @changesets/changelog-github
npx changeset init
A solid starting .changeset/config.json looks like this:
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": [
"@changesets/changelog-github",
{
"repo": "your-org/your-repo"
}
],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
fixed keeps packages on the same version. linked bumps related packages together while preserving their own version numbers. updateInternalDependencies controls how workspace dependency ranges move when an internal package is released. This is important in monorepos because the repo can build locally even when the published dependency range would fail for external users.
Add explicit scripts so Claude Code and CI use the same commands:
{
"scripts": {
"changeset": "changeset",
"changeset:status": "changeset status --since=origin/main",
"version": "changeset version",
"release": "changeset publish",
"build": "tsc -p tsconfig.json",
"test": "vitest run"
}
}
Write the Changeset
Run the interactive command for each PR that changes a public package contract.
npx changeset
Example changeset file:
---
"@myapp/ui": minor
"@myapp/utils": patch
---
Add the `outline` variant to Button and keep the existing `solid` and `ghost` variants compatible.
Fix `formatCurrency` so it handles zero-decimal currencies without rounding errors.
Here @myapp/ui gets a minor release because a new backward-compatible option was added. @myapp/utils gets a patch release because an existing function was fixed without changing its contract. If a prop was removed, a CLI flag was renamed, or a default behavior changed in a way that can break users, treat it as a major candidate.
Use a review prompt like this instead of asking “bump the version”:
Read the current PR diff and draft a Changesets changeset.
Rules:
- Follow SemVer: major for breaking changes, minor for backward-compatible features, patch for fixes.
- Do not edit package.json versions directly.
- Do not run npm publish.
- Do not include packages with private: true in the publish plan.
Return:
- changed packages
- recommended bump for each package
- reasoning for the bump
- proposed .changeset/*.md content
- any uncertain points that need human review
Monorepos and Internal Packages
Many real repositories contain both publishable packages and apps that should never be published. For example, @myapp/ui may go to npm while @myapp/app is only deployed as a web app. Mark private packages clearly:
{
"name": "@myapp/app",
"private": true,
"version": "0.0.0",
"scripts": {
"build": "next build"
},
"dependencies": {
"@myapp/ui": "workspace:*"
}
}
Then keep them out of release calculations where appropriate:
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": [
"@changesets/changelog-github",
{
"repo": "your-org/your-repo"
}
],
"commit": false,
"fixed": [
["@myapp/core", "@myapp/cli"]
],
"linked": [
["@myapp/ui", "@myapp/theme"]
],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@myapp/app", "@myapp/docs"]
}
For internal registries, make the target registry explicit and separate the CI token from the public npm token.
{
"name": "@my-company/internal-kit",
"version": "1.8.0",
"publishConfig": {
"registry": "https://npm.pkg.github.com",
"access": "restricted"
}
}
Release CI
The official changesets/action can create a version PR and publish after that PR is merged. Keep permissions narrow and run tests before publish.
name: Release
on:
push:
branches:
- main
concurrency: release-${{ github.ref }}
permissions:
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm test
- run: npm run build
- name: Create release PR or publish to npm
uses: changesets/action@v1
with:
version: npm run version
publish: npm run release
title: "chore: version packages"
commit: "chore: version packages"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Add a PR check so feature work cannot merge without release intent.
name: Changeset Check
on:
pull_request:
branches:
- main
permissions:
contents: read
jobs:
changeset:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx changeset status --since=origin/main
Documentation-only and test-only PRs may not need a changeset. If your team supports a skip label, make that rule explicit in the workflow. Do not let Claude Code invent skip conditions during a release fix.
Changelog Quality
Generated changelogs often become vague unless you review them. A weak entry says:
---
"@myapp/ui": minor
---
Update Button.
A useful entry tells users what changed and whether they need to act:
---
"@myapp/ui": minor
---
Add `variant="outline"` to `Button`.
Existing `solid` and `ghost` variants keep the same props and class names. Teams using a custom theme should add `--button-outline-border` only if they want to override the default border color.
Use Claude Code as a critic:
Review this changeset as public release-note copy.
Check:
- Can users understand the impact?
- Does the text match the proposed SemVer bump?
- Are migration steps present when needed?
- Are vague words like "updated" or "improved" replacing real details?
- Do package names, function names, and prop names exist in the repo?
List suspicious points as questions. Do not silently rewrite them.
Common Failure Modes
The first failure is asking Claude Code to “update the version.” It may edit package.json directly and leave no changeset. Ask for a changeset draft, then let the release PR run changeset version.
The second failure is shipping a breaking change as a minor. Type-only changes can still break consumers if their build fails. Removed exports, renamed props, changed CLI flags, and default behavior changes deserve special review.
The third failure is accidental publication. Check private: true, ignore, publishConfig.registry, npm token scope, and package tarball contents together. Publishing is much harder to undo than it is to prevent.
The fourth failure is missing an internal dependency bump. If @myapp/core changes and @myapp/cli depends on it, the release should not leave consumers with an impossible or stale range.
Local Verification
Before a release, run:
npm run changeset:status
npm test
npm run build
npm run version -- --snapshot canary
git diff -- package.json package-lock.json pnpm-lock.yaml yarn.lock CHANGELOG.md
npm pack --dry-run
The snapshot version checks version calculation and changelog output without publishing. npm pack --dry-run shows the files that would go into the tarball. Ask Claude Code to review that output for secrets, bulky fixtures, internal docs, or missing build artifacts.
Monetization and Team Rollout
Release discipline is part of revenue. A stable UI kit, CLI, SDK, or template package can support paid templates, training, internal platform work, and consulting. A broken version bump or useless changelog damages trust quickly.
ClaudeCodeLab can help teams turn this into a repeatable workflow through Claude Code training and consultation: Changesets configuration, CLAUDE.md rules, GitHub Actions, npm token boundaries, changelog review prompts, and monorepo package policy.
Hands-On Result
I validated this article against a small npm workspace flow: initialize Changesets, create a changeset, run changeset status, design the release PR workflow, and inspect the publish guardrails. Claude Code is strong at drafting release notes from a diff, but it is less reliable when deciding SemVer alone. The best prompt asks it to explain why a change is not breaking; that exposes questionable minor and patch bumps before they reach npm.
Free PDF: Claude Code Cheatsheet
Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.
We handle your data with care and never send spam.
Level up your Claude Code workflow
Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.
About the Author
Masa
Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.
Related Posts
Claude Code Permission Receipt Pattern: Record Scope, Proof, and Rollback
A permission receipt pattern for Claude Code: allowed actions, approval boundaries, proof commands, rollback, and revenue CTA checks.
Safe Agent Harness Design for Claude Code and Codex: Permissions, Checks, and Rollback
Build a practical agent harness for Claude Code and Codex with policy, planning, verification, and recovery layers.
Claude Code Subagents: A Practical Guide to Safe Agent Delegation
Claude Code subagent guide for safe parallel article and code work: delegation rules, prompts, pitfalls, and checks.
Related Products
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.