Advanced (Updated: 6/2/2026)

Safe Changesets Versioning with Claude Code

Use Claude Code with Changesets for SemVer, release notes, monorepos, CI, and safer npm publishing.

Safe Changesets Versioning with Claude Code

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 caseRelease riskWhat Claude Code can review
UI component packageProps, variants, CSS tokens, peer dependenciesWhether the bump matches the public API change
CLI packageFlags, command names, exit codesWhether README, tests, and code still agree
Monorepo package setInternal dependency rangesWhether a dependent package also needs a bump
Private/internal packageAccidental npm publicationprivate, 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.

#Claude Code #Changeset #version management #monorepo #release
Free

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.

Masa

About the Author

Masa

Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.