Skip to main content
Technology & EngineeringMonorepo198 lines

Lerna

Multi-package repository management with Lerna for versioning, publishing, and task orchestration

Quick Summary18 lines
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 lines
Paste into your CLAUDE.md or agent config

Lerna — 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

  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.

Common Pitfalls

  • Using Lerna's legacy bootstraplerna 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.
  • Forgetting --no-private — By default, lerna publish skips private packages, but lerna version still bumps them. Use --no-private to 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

Get CLI access →