author-migration

Author or scope a first-party Nx migration. Use whenever code removes, renames, or deprecates an option/flag/executor/generator-schema field, changes a default, or bumps a dependency, and someone asks whether existing workspaces need a migration so they don't break on `nx migrate`/upgrade. Covers writing the colocated update-VER/NAME.{ts,spec.ts,md} set, the migrations.json entry (version, requires, implementation, prompt, documentation) or packageJsonUpdates group, and the AI-agent prompt/runbook .md for prompt-only or hybrid (generator + prompt) migrations. Also covers porting an upstream framework's own migrations into Nx. Invoke BEFORE writing, fixing, or editing any migration, migration prompt/runbook, or packageJsonUpdates group, and before concluding a breaking change needs no migration at all.

Install
npx skills add 'https://github.com/nrwl/nx/tree/master/.claude/skills/author-migration'
Download bundle ↓
master · 646e806Scanned 2026-09-17

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗
View on GitHub
← Back to SKILL.md

migrations.json entry templates

The JSON blocks are examples: entry keys, version values, and package names are illustrative; the key sets and path shapes are the contract. Migration entries go under the file's top-level generators section, packageJsonUpdates groups under packageJsonUpdates (full file shape at the bottom). Version values follow the target-train rule from SKILL.md section 2. Paths are dist-prefixed because they resolve against the installed package. The examples below use ./dist/src/migrations/..., the shape for packages whose tsconfig.lib.json has rootDir: "." (the dominant shape); packages that set rootDir: "src" publish without the src segment (./dist/migrations/..., e.g. dotnet and maven). Copy the shape from a sibling entry, or for a package's first entry derive it from rootDir. The migration-markdown-assets conformance rule maps each published path back through the build's rootDir/outDir and fails on a wrong shape (./dist/src/... in a rootDir: "src" package); a package whose tsconfig declares no rootDir/outDir pair is left unchecked there, so confirm its paths against the built dist/ by hand.

Generator-only

"update-23-2-0-remove-foo-option": {
  "version": "23.2.0-beta.3",
  "description": "Removes the deprecated `foo` option from the @nx/bar:build executor options",
  "implementation": "./dist/src/migrations/update-23-2-0/remove-foo-option",
  "documentation": "./dist/src/migrations/update-23-2-0/remove-foo-option.md"
}

Add requires when the migration only applies past an upstream major:

"requires": { "bar": ">=4.0.0" }

Prompt-only

"update-23-2-0-migrate-bar-config-format": {
  "version": "23.2.0-beta.3",
  "requires": { "bar": ">=4.0.0" },
  "description": "AI-assisted migration: rewrites bar config files to the v4 format, whose options do not map 1:1, so it is driven by an AI prompt rather than a deterministic generator",
  "prompt": "./dist/src/migrations/update-23-2-0/migrate-bar-config-format.md",
  "documentation": "./dist/src/migrations/update-23-2-0/upgrade-to-bar-v4.md"
}

Hybrid (deterministic pre-pass plus AI half)

One entry, both keys. The prompt filename must differ from the implementation basename (the documentation .md owns that name; SKILL.md section 4).

"update-23-2-0-convert-bar-config": {
  "version": "23.2.0-beta.3",
  "requires": { "bar": ">=4.0.0" },
  "description": "Converts bar configuration to the v4 format; mechanically safe conversions are applied by a generator and the remainder is completed by an AI prompt",
  "implementation": "./dist/src/migrations/update-23-2-0/convert-bar-config",
  "prompt": "./dist/src/migrations/update-23-2-0/finish-bar-config-conversion.md",
  "documentation": "./dist/src/migrations/update-23-2-0/convert-bar-config.md"
}

packageJsonUpdates

Plain bump for the target train:

"23.2.0": {
  "version": "23.2.0-beta.3",
  "packages": {
    "bar": { "version": "^4.1.0", "alwaysAddToPackageJson": false }
  }
}

alwaysAddToPackageJson: false bumps the package only where it is already installed, the norm for managed deps; true (or "dependencies"/"devDependencies") also adds it when missing.

Cross-major bump gated on the source major (one group per supported source major, ordered oldest first):

"23.2.0-bar-v4": {
  "version": "23.2.0-beta.3",
  "requires": { "bar": ">=3.0.0 <4.0.0" },
  "packages": {
    "bar": { "version": "^4.1.0", "alwaysAddToPackageJson": false }
  }
}

Bumping a package that ships its own migrations, without triggering them:

"packages": {
  "some-cli": {
    "version": "~5.0.0",
    "alwaysAddToPackageJson": false,
    "ignorePackageGroup": true,
    "ignoreMigrations": true
  }
}

First migration in a plugin: package.json wiring

"nx-migrations": {
  "migrations": "./migrations.json",
  "supportsOptionalMigrations": true
}

And a new migrations.json has this shape:

{
  "$schema": "../../node_modules/nx/schemas/migrations-schema.json",
  "generators": {},
  "packageJsonUpdates": {}
}
Referenced from SKILL.md