
Changesets
- 100 installs
- 14 repo stars
- Updated March 2, 2026
- oakoss/agent-skills
Helps with ai & agent building tasks during AI-assisted development.
About
changesets is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- changesets
- AI & Agent Building
- AI-coding skill
Changesets by the numbers
- 100 all-time installs (skills.sh)
- +2 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #4,357 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/oakoss/agent-skills --skill changesetsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 100 |
|---|---|
| repo stars | ★ 14 |
| Last updated | March 2, 2026 |
| Repository | oakoss/agent-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Changesets
Overview
Changesets is a versioning and changelog management tool focused on multi-package repositories. Contributors declare the semver impact of each change (major/minor/patch) via changeset files, then Changesets aggregates them to bump versions, update changelogs, and publish packages in a single coordinated release.
When to use: Monorepo versioning, automated changelog generation, coordinated multi-package releases, CI-driven publishing, prerelease/snapshot workflows.
When NOT to use: Single-file projects with no npm publishing, projects using commit-message-based versioning (semantic-release), manual version management without an npm registry, projects where a single maintainer controls all releases without PR collaboration.
How It Works
1. A contributor adds a changeset file declaring affected packages, bump types, and a summary 2. The changeset file is committed alongside the code change in the PR 3. When ready to release, changeset version consumes all pending changesets and updates versions and changelogs 4. changeset publish publishes the updated packages to npm and creates git tags 5. In CI, the official GitHub Action automates steps 3-4 via an auto-maintained "Version Packages" PR
Key Concepts
- Changeset file — A markdown file in
.changeset/declaring which packages are affected, their bump type (major/minor/patch), and a human-readable summary that appears in the changelog - Version command — Consumes all pending changeset files, calculates final version bumps, updates
package.jsonversions, generatesCHANGELOG.mdentries, and bumps internal dependency ranges - Publish command — Publishes updated packages to npm and creates git tags; must run immediately after
versionwith no commits in between - Linked packages — Packages that share the highest bump type within a release but maintain independent version numbers
- Fixed packages — Packages that always share the exact same version number across the group
- Prerelease mode — A mode where
versionproduces prerelease versions (e.g.,1.0.0-beta.0) for testing before stable release - Snapshot releases — Temporary
0.0.0-timestampversions for ad-hoc testing without affecting the main release line
Configuration Quick Reference
| Option | Default | Description |
|---|---|---|
changelog | "@changesets/cli/changelog" | Changelog generator package or false to disable |
commit | false | Auto-commit on version and add commands |
access | "restricted" | npm publish access; set "public" for public scoped packages |
baseBranch | "main" | Branch used for change detection |
linked | [] | Groups of packages that share highest bump type |
fixed | [] | Groups of packages that share exact version |
ignore | [] | Packages excluded from changeset versioning |
updateInternalDependencies | "patch" | When to bump dependents: "patch" or "minor" |
privatePackages | { version: true, tag: false } | Version/tag behavior for "private": true packages |
Quick Reference
| Pattern | Command / Config | Key Points |
|---|---|---|
| Initialize | npx @changesets/cli init | Creates .changeset/ folder with config |
| Add changeset | npx @changesets/cli add | Interactive prompt for packages and bump type |
| Add empty changeset | npx @changesets/cli add --empty | Declares no packages need versioning (satisfies CI) |
| Version packages | npx @changesets/cli version | Consumes changesets, bumps versions, updates changelogs |
| Publish packages | npx @changesets/cli publish | Publishes to npm, creates git tags |
| Check status | npx @changesets/cli status | Lists pending changesets; exits 1 if changes lack changesets |
| Status since branch | npx @changesets/cli status --since=main | Only checks changes since diverging from main |
| Enter prerelease | npx @changesets/cli pre enter <tag> | Enables prerelease mode (beta, alpha, rc, next) |
| Exit prerelease | npx @changesets/cli pre exit | Returns to normal versioning mode |
| Snapshot version | npx @changesets/cli version --snapshot | Creates 0.0.0-timestamp versions for testing |
| Snapshot publish | npx @changesets/cli publish --tag canary --no-git-tag | Publishes snapshot without overwriting latest dist-tag |
| Link packages | "linked": [["pkg-a", "pkg-b"]] in config | Packages share the highest version bump type |
| Fix packages | "fixed": [["pkg-*"]] in config | Packages share the exact same version number |
| Ignore packages | "ignore": ["pkg-internal"] in config | Excludes packages from changeset versioning |
| Public access | "access": "public" in config | Required for publishing public scoped packages |
| GitHub changelog | "changelog": ["@changesets/changelog-github", ...] | Adds PR links and contributor attribution |
| Auto-commit | "commit": true in config | Version and add commands auto-commit changes |
| Internal deps | "updateInternalDependencies": "patch" in config | Controls when internal dependents get bumped |
Common Mistakes
| Mistake | Correct Pattern |
|---|---|
Committing between version and publish | Run publish immediately after version with no commits in between |
Forgetting --empty for PRs with no package changes | Use npx @changesets/cli add --empty to satisfy CI checks |
Using linked when packages must share exact versions | Use fixed for identical versions; linked only shares bump magnitude |
Setting access: "restricted" for public packages | Set access: "public" in config for public npm packages |
Not including fetch-depth: 0 in CI checkout | Full git history is needed for changeset detection |
Running publish without building first | Always run build step before changeset publish |
| Entering prerelease mode on main branch | Use a dedicated branch for prereleases to avoid blocking normal releases |
| Ignoring packages that others depend on | Ignored packages skip bumps, breaking dependents — use sparingly |
| Publishing snapshots with default tag | Always use --tag flag to avoid overwriting latest dist-tag |
Not setting NPM_TOKEN in CI environment | Both GITHUB_TOKEN and NPM_TOKEN are required for automated publishing |
Using changeset publish in CI without the action | The official changesets/action handles the two-mode workflow correctly |
Manually editing generated CHANGELOG.md | Edit changeset files instead; changelogs are regenerated on version |
Delegation
- CI pipeline debugging: Use
Exploreagent for repository-specific workflow discovery - npm publishing issues: Use
Taskagent for debugging publish and registry authentication failures
If the turborepo skill is available, delegate build orchestration, task caching, and CI optimization to it.If the pnpm-workspace skill is available, delegate workspace setup, dependency linking, catalogs, and Docker deployment to it. See its monorepo integration reference for the end-to-end release pipeline.References
- Basic workflow: adding changesets, versioning, publishing, CI integration
- Monorepo setup: configuration, linked packages, fixed versioning, ignore patterns
- CI automation: GitHub Actions, automated PRs, snapshot releases, prerelease channels
Basic Workflow
Initialization
Set up Changesets in a project:
npx @changesets/cli initThis creates a .changeset/ directory containing:
config.json— configuration optionsREADME.md— instructions for contributors
Adding a Changeset
When making a change that affects package versions, add a changeset:
npx @changesets/cli addThe interactive prompt asks:
1. Which packages are affected 2. What semver bump type (major, minor, patch) 3. A summary of the change
This creates a markdown file in .changeset/:
---
'@scope/my-package': minor
'@scope/other-package': patch
---
Add new authentication provider and fix token refresh logicEach changeset file can reference multiple packages with different bump types.
Empty Changesets
For PRs that do not require version bumps (documentation, CI config, tests):
npx @changesets/cli add --emptyThis creates a changeset with no package bumps, satisfying CI status checks.
Versioning
When ready to release, consume all pending changesets:
npx @changesets/cli versionThis command:
- Reads all changeset files in
.changeset/ - Calculates the final version bump per package (highest bump wins)
- Updates
package.jsonversion fields - Updates or creates
CHANGELOG.mdfor each affected package - Bumps internal dependency ranges in dependent packages
- Deletes consumed changeset files
Review the changes, then commit:
git add .
git commit -m "chore: version packages"Publishing
After versioning, publish all updated packages to npm:
npx @changesets/cli publishThis command:
- Publishes each package with an updated version
- Creates git tags for each published package (e.g.,
@scope/pkg@1.2.0) - Skips packages marked as
private: true
Push tags to remote after publishing:
git push --follow-tagsBuild before publishing. The publish command does not run build scripts. Ensure packages are built before running publish:
npm run build
npx @changesets/cli publishChecking Status
View pending changesets and their projected version bumps:
npx @changesets/cli statusUse --verbose for detailed per-package breakdown:
npx @changesets/cli status --verboseThe status command exits with code 1 if there are changed packages without changesets. Use this in CI to enforce changeset requirements:
npx @changesets/cli status --since=mainChangelog Configuration
The default changelog generator is @changesets/cli/changelog. For richer changelogs with GitHub links, use @changesets/changelog-github:
npm install -D @changesets/changelog-githubUpdate .changeset/config.json:
{
"changelog": ["@changesets/changelog-github", { "repo": "owner/repo-name" }]
}This adds commit links, PR references, and contributor attribution to changelogs.
Package.json Scripts
Define convenience scripts for the release workflow:
{
"scripts": {
"changeset": "changeset",
"version-packages": "changeset version",
"release": "npm run build && changeset publish"
}
}Changeset File Format
Each changeset is a markdown file with YAML frontmatter:
---
'package-a': major
'package-b': minor
---
Description of the change. This text appears in CHANGELOG.md.
Supports **markdown** formatting for rich changelogs.Valid bump types follow semver:
- major — breaking changes (1.x.x -> 2.0.0)
- minor — new features, backward compatible (1.1.x -> 1.2.0)
- patch — bug fixes, backward compatible (1.1.1 -> 1.1.2)
Complete Release Workflow
A typical release cycle:
# 1. Developer adds changeset during feature work
npx @changesets/cli add
# 2. Commit changeset with the PR
git add .changeset/
git commit -m "feat: add new feature"
# 3. When ready to release, consume changesets
npx @changesets/cli version
# 4. Review version bumps and changelogs
git diff
# 5. Commit version changes
git add .
git commit -m "chore: version packages"
# 6. Build and publish
npm run build
npx @changesets/cli publish
# 7. Push commits and tags
git push --follow-tagsCI Automation
GitHub Actions Release Workflow
The official changesets/action automates the release process. It operates in two modes:
1. When changesets exist: Opens a "Version Packages" PR that consumes all changesets 2. When the Version Packages PR is merged: Publishes packages to npm
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build packages
run: npm run build
- name: Create Release Pull Request or Publish
uses: changesets/action@v1
with:
version: npm run version-packages
publish: npm run release
commit: 'chore: version packages'
title: 'chore: version packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}Required package.json scripts:
{
"scripts": {
"version-packages": "changeset version",
"release": "npm run build && changeset publish"
}
}Action Configuration Options
| Option | Default | Description |
|---|---|---|
version | changeset version | Command to run for versioning |
publish | changeset publish | Command to run for publishing |
commit | "Version Packages" | Commit message for version changes |
title | "Version Packages" | PR title for the version PR |
setupGitUser | true | Configures git user as github-actions[bot] |
createGithubReleases | true | Creates GitHub Releases after publish |
commitMode | "git-cli" | Use "github-api" for GPG-signed commits |
pnpm Monorepo Workflow
For pnpm-based monorepos, adjust the workflow:
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpm run build
- name: Create Release Pull Request or Publish
uses: changesets/action@v1
with:
version: pnpm run version-packages
publish: pnpm run release
commit: 'chore: version packages'
title: 'chore: version packages'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}Changeset Status Check in CI
Enforce that PRs include changesets for package changes:
name: Changeset Check
on:
pull_request:
branches:
- main
jobs:
changeset-check:
name: Changeset Check
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Check for changesets
run: npx @changesets/cli status --since=origin/mainAlternatively, install the Changeset Bot GitHub App. It comments on PRs indicating whether a changeset is present, without failing the build.
Snapshot Releases
Snapshot releases create temporary versions for testing without affecting the main release line. They produce versions like 0.0.0-20240115120000.
Manual Snapshot Workflow
npx @changesets/cli version --snapshot
npx @changesets/cli publish --tag canary --no-git-tagThe --tag canary flag publishes under a dist-tag other than latest, preventing users from accidentally installing snapshot versions.
Snapshot CI Workflow
Automate snapshot releases on PRs for testing:
name: Snapshot Release
on:
issue_comment:
types: [created]
jobs:
snapshot:
name: Snapshot Release
if: github.event.comment.body == '/snapshot'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: refs/pull/${{ github.event.issue.number }}/head
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Build packages
run: npm run build
- name: Create snapshot versions
run: npx @changesets/cli version --snapshot pr${{ github.event.issue.number }}
- name: Publish snapshot
run: npx @changesets/cli publish --tag pr${{ github.event.issue.number }} --no-git-tag
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}Install a snapshot release for testing:
npm install @scope/package@pr123Prerelease Channels
Prereleases allow publishing beta, alpha, or RC versions before a stable release.
Entering Prerelease Mode
npx @changesets/cli pre enter betaThis creates a .changeset/pre.json file that tracks prerelease state. While in prerelease mode:
changeset versionproduces versions like1.0.0-beta.0,1.0.0-beta.1- Each
versioncall increments the prerelease number - New changesets continue to accumulate
Prerelease Workflow
# 1. Enter prerelease mode on a dedicated branch
git checkout -b release/next
npx @changesets/cli pre enter beta
# 2. Version and publish prerelease
npx @changesets/cli version
git add .
git commit -m "chore: version packages (beta)"
npm run build
npx @changesets/cli publish
git push --follow-tags
# 3. Continue adding changesets and versioning
npx @changesets/cli add
npx @changesets/cli version
git add .
git commit -m "chore: version packages (beta)"
npm run build
npx @changesets/cli publish
git push --follow-tags
# 4. Exit prerelease mode for stable release
npx @changesets/cli pre exit
npx @changesets/cli version
git add .
git commit -m "chore: version packages"
npm run build
npx @changesets/cli publish
git push --follow-tagsPrerelease Tags
Common prerelease tags and their conventions:
| Tag | Use Case | Example Version |
|---|---|---|
alpha | Early development, unstable | 2.0.0-alpha.0 |
beta | Feature complete, testing | 2.0.0-beta.3 |
rc | Release candidate, final testing | 2.0.0-rc.1 |
next | Upcoming major version | 2.0.0-next.5 |
Prerelease Branch Strategy
Use a dedicated branch for prereleases to avoid blocking normal releases on main:
main (stable releases)
└── release/next (prerelease channel)The changesets/action can be configured to handle prerelease branches by adding the branch to the workflow trigger:
on:
push:
branches:
- main
- 'release/**'npm Authentication in CI
Configure npm authentication for automated publishing:
- name: Create .npmrc
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > .npmrcFor scoped packages on a private registry:
- name: Create .npmrc
run: |
echo "@scope:registry=https://npm.pkg.github.com" > .npmrc
echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> .npmrcHandling Version PR Conflicts
The automated Version Packages PR can develop merge conflicts when multiple PRs with changesets merge in sequence. The changesets/action automatically updates the PR on each push to main, resolving most conflicts. If manual intervention is needed:
git checkout changeset-release/main
git merge main
npx @changesets/cli version
git add .
git commit -m "chore: resolve version conflicts"
git pushMonorepo Setup
Configuration File
All Changesets configuration lives in .changeset/config.json. The full default configuration:
{
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "restricted",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}Configuration Options
changelog
Controls changelog generation. Can be a string (package name) or a tuple with options:
{
"changelog": "@changesets/cli/changelog"
}With GitHub integration for PR links and author attribution:
{
"changelog": ["@changesets/changelog-github", { "repo": "owner/repo-name" }]
}Set to false to disable changelog generation entirely:
{
"changelog": false
}commit
When true, changeset version and changeset add automatically create git commits:
{
"commit": true
}access
Controls npm publish access. Set to "public" for public scoped packages:
{
"access": "public"
}Use "restricted" (default) for private registry or scoped private packages.
baseBranch
The branch that Changesets compares against for detecting changes:
{
"baseBranch": "main"
}updateInternalDependencies
Controls how internal dependency ranges are updated when a dependency is bumped:
{
"updateInternalDependencies": "patch"
}"patch"(default) — always update the dependency range"minor"— only update when the bump is minor or major
Linked Packages
Linked packages always share the highest bump type within a release. If one package gets a major bump, all linked packages get a major bump. Each package may have a different version number.
Explicit package list:
{
"linked": [["@scope/components", "@scope/theme", "@scope/tokens"]]
}Using glob patterns (micromatch format, matches against package names):
{
"linked": [["@scope/ui-*"]]
}Multiple independent link groups:
{
"linked": [["@scope/react-*"], ["@scope/vue-*"]]
}How Linked Packages Work
Given packages A (1.0.0) and B (1.0.0) in the same linked group:
- A changeset bumps A as
minorand B aspatch - Both get a
minorbump (highest wins) - A becomes 1.1.0, B becomes 1.1.0
Linked packages share bump magnitude but not version numbers. Use fixed if packages must have identical versions.
Fixed Packages
Fixed packages always share the exact same version. When any package in the group is bumped, all packages get the same version.
{
"fixed": [["@scope/core", "@scope/react", "@scope/vue"]]
}Using glob patterns:
{
"fixed": [["@scope/sdk-*"]]
}How Fixed Packages Work
Given packages A (1.0.0) and B (1.0.0) in the same fixed group:
- A changeset bumps only A as
minor - Both A and B become 1.1.0
- All packages in the group always have the same version
Dependencies between packages in a fixed group are not considered for additional version bumping since they always move together.
Linked vs Fixed Comparison
| Behavior | Linked | Fixed |
|---|---|---|
| Bump type | Shared (highest wins) | Shared (highest wins) |
| Version number | Independent per package | Identical across group |
| Use case | Related packages that evolve independently | Packages that must always be in sync |
| Example | Design system components | SDK core + framework bindings |
Private Packages
Control how private packages (those with "private": true in package.json) are handled during versioning:
{
"privatePackages": {
"version": true,
"tag": true
}
}| Sub-option | Default | Description |
|---|---|---|
version | true | Update version and changelog |
tag | false | Create git tags for private packages |
Set to false to completely skip private packages:
{
"privatePackages": false
}This is useful for managing application versions and non-npm packages within a monorepo. Applications with "private": true can still get versioned changelogs and git tags without being published to npm.
Ignore Patterns
Exclude packages from Changesets versioning entirely:
{
"ignore": ["@scope/internal-tool", "@scope/dev-scripts"]
}Using glob patterns:
{
"ignore": ["@scope/internal-*"]
}Restrictions on ignore:
- Cannot ignore a package that is depended on by a non-ignored package
- Ignored packages skip version bumps entirely, including internal dependency updates
- Use sparingly — ignored packages with dependents can leave the repo in a broken state
Monorepo Directory Structure
A typical monorepo layout with Changesets:
monorepo/
├── .changeset/
│ ├── config.json
│ └── README.md
├── packages/
│ ├── core/
│ │ ├── package.json
│ │ ├── CHANGELOG.md
│ │ └── src/
│ ├── react/
│ │ ├── package.json
│ │ ├── CHANGELOG.md
│ │ └── src/
│ └── utils/
│ ├── package.json
│ ├── CHANGELOG.md
│ └── src/
└── package.jsonEach package gets its own CHANGELOG.md, generated and maintained by changeset version.
Internal Dependencies
When a package is bumped, Changesets automatically updates dependent packages within the monorepo.
Given this dependency graph:
@scope/react depends on @scope/core
@scope/vue depends on @scope/coreA minor bump to @scope/core triggers:
@scope/coreversion bump (minor)@scope/reactdependency range update (patch bump by default)@scope/vuedependency range update (patch bump by default)
Control this behavior with updateInternalDependencies:
{
"updateInternalDependencies": "minor"
}With "minor", dependents only get bumped if the dependency bump is minor or higher. Patch bumps to dependencies do not cascade.
Public Monorepo Configuration Example
A complete config for a public monorepo with GitHub changelogs:
{
"changelog": ["@changesets/changelog-github", { "repo": "owner/repo-name" }],
"commit": false,
"fixed": [],
"linked": [["@scope/react-*"]],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@scope/internal-docs"]
}