Lerna
Multi-package repository management with Lerna for versioning, publishing, and task orchestration
You are an expert in Lerna for managing multi-package JavaScript and TypeScript monorepos, including versioning, publishing, and task running. ## Key Points - **Fixed mode** (`"version": "1.0.0"`) — All packages share one version. A change in any package bumps the version for all. - **Independent mode** (`"version": "independent"`) — Each package has its own version. Only changed packages are bumped. 1. **Use independent versioning** — Unless packages are truly inseparable, independent mode avoids unnecessary version bumps. 2. **Enable conventional commits** — Automate version bumps and changelog generation based on commit messages. 3. **Use `--since` for CI** — Run only affected tests and builds with `--since=main` to cut CI time. 4. **Leverage Nx caching** — Lerna v6+ uses Nx's task runner; configure `nx.json` for full caching support. 5. **Set `allowBranch`** — Restrict versioning and publishing to specific branches to prevent accidental releases. 6. **Use `ignoreChanges`** — Exclude test files, docs, and config changes from triggering version bumps. 7. **Prefer `from-git` publishing** — Separate versioning from publishing so you can review version bumps before they reach npm. - **Using Lerna's legacy bootstrap** — `lerna bootstrap` is deprecated. Use your package manager's workspace support (pnpm workspaces, npm workspaces) instead. - **Confusing fixed and independent mode** — Switching modes mid-project requires careful migration. Decide early. - **Not using workspaces** — Lerna without `"useWorkspaces": true` misses out on native package manager linking and hoisting.
skilldb get monorepo-skills/LernaFull skill: 198 linesLerna — Monorepo Management
You are an expert in Lerna for managing multi-package JavaScript and TypeScript monorepos, including versioning, publishing, and task running.
Core Philosophy
Overview
Lerna is one of the original monorepo management tools for JavaScript. Since being adopted by Nx (v6+), Lerna now integrates Nx's task runner for caching and task orchestration while retaining its strengths in versioning and publishing. Lerna manages the lifecycle of multiple packages: bootstrapping, running scripts, versioning, and publishing to npm.
Setup & Configuration
Installation
# Initialize a new Lerna repo
npx lerna init
# Or add to an existing repo
npm install -D lerna
npx lerna init
lerna.json Configuration
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "independent",
"npmClient": "pnpm",
"useWorkspaces": true,
"command": {
"version": {
"conventionalCommits": true,
"message": "chore(release): publish %s",
"allowBranch": ["main", "release/*"]
},
"publish": {
"conventionalCommits": true,
"yes": true
},
"run": {
"stream": true
}
},
"ignoreChanges": [
"**/__tests__/**",
"**/*.md"
]
}
Version Modes
- Fixed mode (
"version": "1.0.0") — All packages share one version. A change in any package bumps the version for all. - Independent mode (
"version": "independent") — Each package has its own version. Only changed packages are bumped.
Package Structure
my-monorepo/
packages/
core/
package.json # @myorg/core
cli/
package.json # @myorg/cli
utils/
package.json # @myorg/utils
lerna.json
package.json
Core Patterns
Running Scripts
# Run build in all packages (topological order with caching via Nx)
npx lerna run build
# Run tests in specific packages
npx lerna run test --scope=@myorg/core
# Run in all packages except one
npx lerna run lint --ignore=@myorg/docs
# Run only in changed packages since last release
npx lerna run test --since=main
# Stream output in real time
npx lerna run dev --stream --parallel
Versioning
# Version with conventional commits (auto-determines bump)
npx lerna version --conventional-commits
# Version with explicit bump
npx lerna version patch
# Preview without making changes
npx lerna version --no-push --no-git-tag-version
# Version only changed packages (independent mode)
npx lerna version --no-private
Publishing
# Version and publish in one step
npx lerna publish
# Publish packages that were versioned in a previous step
npx lerna publish from-package
# Publish from the latest git tag
npx lerna publish from-git
# Publish canary versions from CI
npx lerna publish --canary --preid=beta
Listing and Diffing
# List all packages
npx lerna list
# List changed packages since last tag
npx lerna changed
# Show diff since last release
npx lerna diff
Using Nx Integration
Lerna v6+ uses Nx under the hood. Add nx.json for caching:
{
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"cache": true,
"outputs": ["{projectRoot}/dist"]
},
"test": {
"cache": true,
"inputs": [
"default",
"^default"
]
}
},
"namedInputs": {
"default": ["{projectRoot}/**/*"]
}
}
Best Practices
- Use independent versioning — Unless packages are truly inseparable, independent mode avoids unnecessary version bumps.
- Enable conventional commits — Automate version bumps and changelog generation based on commit messages.
- Use
--sincefor CI — Run only affected tests and builds with--since=mainto cut CI time. - Leverage Nx caching — Lerna v6+ uses Nx's task runner; configure
nx.jsonfor full caching support. - Set
allowBranch— Restrict versioning and publishing to specific branches to prevent accidental releases. - Use
ignoreChanges— Exclude test files, docs, and config changes from triggering version bumps. - Prefer
from-gitpublishing — Separate versioning from publishing so you can review version bumps before they reach npm.
Common Pitfalls
- Using Lerna's legacy bootstrap —
lerna bootstrapis deprecated. Use your package manager's workspace support (pnpm workspaces, npm workspaces) instead. - Confusing fixed and independent mode — Switching modes mid-project requires careful migration. Decide early.
- Not using workspaces — Lerna without
"useWorkspaces": truemisses out on native package manager linking and hoisting. - Forgetting
--no-private— By default,lerna publishskips private packages, butlerna versionstill bumps them. Use--no-privateto skip them entirely. - Conventional commit format errors — If commit messages don't follow the convention (
feat:,fix:,BREAKING CHANGE:), automatic version bumps will be wrong or skipped entirely.
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add monorepo-skills
Related Skills
Changesets
Versioning and changelog management with Changesets for coordinated monorepo package releases
CI Optimization
CI/CD optimization for monorepos including affected detection, caching strategies, and parallel execution
Dependency Management
Managing internal package dependencies, versioning strategies, and dependency graph health in monorepos
Nx
Monorepo development with Nx including project graph, generators, executors, and computation caching
Pnpm Workspaces
Managing monorepo packages with pnpm workspaces including linking, filtering, and dependency hoisting
Shared Configs
Sharing ESLint, TypeScript, Prettier, and other tool configurations across monorepo packages