beachball
  • v3 prerelease
  • v2 stable
GitHub
  • v3 prerelease
  • v2 stable
GitHub
  • Overview

    • Getting started
    • Installation
    • Configuration
    • V3 migration guide
  • Concepts

    • Bump algorithm
    • Change files
    • Change types
    • Groups
    • CI integration
      • Auth helper
    • AI integration
    • Optimizing performance in large repos
  • CLI commands

    • Common options
    • bump
    • change
    • check
    • config
    • migrate
    • publish
    • sync
This documentation applies to beachball v3 prerelease (beachball@next). View the beachball v2 documentation or read the v3 migration guide.

V3 migration guide

This page describes how to migrate from beachball v2 to v3.

Overview and installation

As of writing, beachball v3 is in alpha under the next tag. You can see the latest version via npm show beachball@next version.

It's currently recommended to pin a specific version: the prerelease has some significant benefits (not easily backported) for secure publishing, and most of the true breaking changes have already been implemented, but there may still be some changes to dependent bumping behavior which may require further verification.

This release mainly focuses on:

  • Supporting secure publishing: better approaches for passing git and npm tokens, help with generating a GitHub App token, and (planned) better support for separate bump/publish steps
  • Fixing longstanding oddities (most of the option behavior changes)
  • Reducing dependency tree size (yargs-parser => commander, execa => nano-spawn, minimatch => path.matchesGlob)
  • Improving npm performance (planned) and reducing git history bloat (no CHANGELOG.json by default)

The remaining planned changes will likely focus on:

  • Further npm improvements: respect registry and credentials from npm config, and don't use CLI for registry read operations
  • Better support for separate bump/publish steps
  • Possibly: dependent bumping behavior coherency improvements (this is the main reason for keeping the version pinned)

Running the migrate command

beachball v3 includes a migrate command that checks your config and logs any updates needed for v3:

beachball migrate

If your config is already compatible, you will see:

No config updates are needed for v3.

Otherwise, the command will list specific config updates that are needed. The command does NOT attempt to make updates directly due to the variety of locations and file types where the config can be specified.

Breaking changes

Many of the config-related changes below are detected by beachball migrate or automatic validation.

Require Node.js 22.18+

beachball v3 requires Node.js 22.18.0 or newer, and its published output uses ES2024 syntax. This also allows support for TypeScript or ESM config files.

CLI option parsing changes

CLI parsing moved from yargs-parser to commander. Most behavior is preserved, but a few things changed:

  • Unknown options now cause an error instead of being silently passed through. This should have no impact unless you were passing extra BeachballOptions values on the command line that aren't actually specified in CliOptions. (If there's some other value you need as a CLI option, please open an issue or PR.)
  • Repeated non-array options use the last value instead of throwing an error.
  • String boolean values are no longer supported: Specifying boolean values like --push false or --push=false won't work. Use --push / --no-push (or similar) instead.
  • If you're using --camelCase flags, it's recommended to switch to --kebab-case. camelCase is not supported by default by commander, and beachball's workarounds for this may be removed in a future major version.

CHANGELOG.json generation disabled by default

generateChangelog now defaults to 'md', meaning CHANGELOG.json files are no longer generated by default. This is because most repos don't use CHANGELOG.json, and those files add substantial git history bloat in a large/busy repo. (CHANGELOG.md is still generated.)

  • If you rely on CHANGELOG.json, set generateChangelog: true in your config.
  • If you don't, delete any existing CHANGELOG.json files (beachball migrate won't do this automatically).

registry and access respect npm settings

In v2, Beachball defaulted registry to https://registry.npmjs.org/ and access to restricted.

In v3, Beachball no longer sets its own defaults for either option:

  • registry now uses whatever registry npm is configured to use.
    • Temporary exception: Due to unfinished features, if you're explicitly providing BEACHBALL_NPM_TOKEN or --token, you must explicitly provide registry.
  • access now uses npm's default publish behavior. Since scoped packages default to restricted, you should almost always set this to public (as most repos with scoped packages already do).

Fix group exclude negation behavior

Remove the requirement for groups[*].exclude and changelog.groups[*].exclude patterns to be negated (leading !).

To migrate, simply remove the leading ! from all exclude patterns.

Stricter comparison remote/branch resolution

The logic for determining the comparison remote and branch is stricter: beachball now throws if no remotes are defined, or if the root package.json specifies a repository field but no matching remote is found. If your branch option contains a /, beachball checks whether the leading segment matches a configured remote name, and falls back to the default remote otherwise.

Custom changelog rendering changes

Only relevant for custom changelog renderers (or if reading CHANGELOG.json later): PackageChangelog.tag and ChangelogJsonEntry.tag are now undefined when the package had no associated git tag (previously a value was always present).

ChangelogEntry.commit will be undefined if the package did not have an associated commit.

Stop writing placeholder commit hashes in changelog

In v2, Beachball could write "not available" to the commit field in CHANGELOG.json when a commit hash was unavailable.

In v3, Beachball omits the commit field entirely in those cases instead, including dependent bump entries that do not have a real commit hash yet.

Stop writing default dependentChangeType in change files

Beachball no longer writes the default dependentChangeType values to generated change files. The same defaults as before are applied at bump time (none when the change type is none, or patch otherwise). Existing change files which specify dependentChangeType are still supported, and --dependent-change-type continues to write an explicit override.

Custom tools that read change files should allow dependentChangeType to be missing and apply the same defaults. Tools that create change files should omit the field unless non-default dependent bump behavior is intended.

Fix fallback behavior for disallowed change types

Fallback behavior for disallowed change types now keeps stable and prerelease types separate. Stable types fall back from major -> minor -> patch -> none; prerelease types fall back from premajor -> preminor -> prepatch -> prerelease -> none. (Previously, the combined ordering could cause a disallowed stable type to fall back to a prerelease type, such as minor becoming preminor rather than patch.)

This is technically a breaking change, but really it's more of a bug fix, since the behavior was probably not intentional and is almost never desirable.

shouldPublish behavior change

Note: you should almost never need this option - in most scenarios, just set private: true in package.json instead. Only use this if the package should not be published to npm, but you do want beachball to manage its version and changelog.

In v2, the beachball.shouldPublish: false package option was handled inconsistently: packages didn't get change files or direct version bumps, but if a shouldPublish: false package was a dependent of a bumped package, it was silently bumped and published anyway.

In v3, shouldPublish: false packages are full participants in all steps of the workflow except npm publish:

  • Change files are generated and required
  • Version bumps, git tags, and changelogs are produced (same as published packages)
  • The final npm publish (or pack) step is skipped
  • If a published package has a shouldPublish: false package in its production dependencies, Beachball will exit with an error (same as with private: true deps)
  • Since shouldPublish: false is redundant with private: true, beachball migrate reports this as an error

BeachballConfig and other type updates

  • Rename changelog.groups[*].masterPackageName to mainPackageName.
  • Removed rarely-used options:
    • new: This option was never needed if PR builds run beachball check (a new package without a change file already causes an error), and it had a significant performance cost because it checked the registry for all unmodified packages.
    • packStyle: packing always uses the layered style now.
  • hooks.prebump no longer receives packageInfos. This was never in the signature, and trying to modify it may lead to unexpected behavior. Please open an issue if you were using this and we can find an alternative.
  • tag and defaultNpmTag updates:
    • tag may not be null. This was already ignored in the previous version, but now it's removed from the types.
      • Note that tag: '' means fall back to defaultNpmTag or 'latest' (npm doesn't allow publishing a new version without a dist-tag).
      • To disable git tags for a package, set gitTags: false.
    • defaultNpmTag should not be '' for reasons above.
  • Package-level-only options have been removed from BeachballConfig.

Config loading changes

Beachball v3 replaces cosmiconfig with custom logic which supports most previous config file names but removes support for YAML config files. TypeScript config files are now supported and will be run natively in Node.

The config file is now only resolved at the project root. Support for searching up from the project root (into parent directories) has been removed.

Other potentially-breaking changes

  • Use Node's path.matchesGlob instead of minimatch. Behavior should stay the same, but if not, please open an issue.
  • If you're deep importing beachball's internal helpers, some deprecated signatures have been removed. Use the new signatures (which pre-calculate and share context) instead.

Other changes

New options

  • Add getGitTag option, a function used to generate per-package git tags.
  • Add commitMessage option, a function used to generate the commit message for the change and publish commands (overridden by --message for publish).
  • Support authenticating with a git token from BEACHBALL_GIT_TOKEN.

New commands

  • Add experimental beachball publish-helpers update-lock-registry command

Patches

  • In the change prompt, add a link to the change type help page.
  • Use p-graph v3 for both concurrent and non-concurrent publishing, and for generating graph layers when packing.
  • Replace execa with nano-spawn.
  • Use --no-tags option with git fetch.
  • Update the layer logic to only consider the set of published packages when building its graph.
  • Use node: prefix on built-in imports.
Last Updated: 8/13/26, 3:07 AM
Prev
Configuration