nx Migrations
For an overview of the plugin and setup instructions, see the @nx/nx introduction.
The @nx/nx plugin provides various migrations to help you migrate to newer versions of nx projects within your Nx workspace. Below is a complete reference for all available migrations.
24.0.x
Section titled “24.0.x”24-0-0-move-custom-hashers-to-inputs
Section titled “24-0-0-move-custom-hashers-to-inputs”Version: 24.0.0-beta.0
Finds local executors that declare a custom hasher, which is deprecated and will be removed in Nx 25. Rewriting a hasher as target inputs means reading what its code hashes, so the rewrite is driven by an AI prompt; the generator only reports each hasher.
Move custom executor hashers to target inputs
Section titled “Move custom executor hashers to target inputs”Custom hashers are deprecated in Nx 24 and will be removed in Nx 25.
A custom hasher is the hasher property of an executor in executors.json, pointing at a module that computes the task hash in code.
Target inputs replace them.
This migration finds every local plugin in the workspace whose executors.json (or builders.json) declares a hasher.
It doesn’t edit any files.
When it finds one, it lists the executor, the hasher module, and the executors.json file in the migration’s next steps.
It also lists files and executor entries it can’t read, so you can check those by hand.
Under nx migrate with an AI agent, the agent reads each hasher and writes inputs that hash the same things.
A target that declares its own inputs doesn’t inherit them from targetDefaults, so the agent checks every target that uses the executor and adds the inputs where they’re missing.
It removes the hasher only once every one of those targets is covered.
If something the hasher hashes can’t be expressed as an input, the agent leaves the hasher in place and tells you why.
Packages installed in node_modules aren’t scanned.
If a third-party plugin you use declares a hasher, Nx warns about it when it hashes one of its tasks.
Sample code changes
Section titled “Sample code changes”Given a local plugin whose echo executor hashes the project, its dependencies, and the API_URL environment variable:
Before
Section titled “Before”{ "executors": { "echo": { "implementation": "./src/executors/echo/executor", "hasher": "./src/executors/echo/hasher", "schema": "./src/executors/echo/schema.json" } }}{ "targetDefaults": { "@acme/my-plugin:echo": { "inputs": ["default", "^default", { "env": "API_URL" }] } }}{ "executors": { "echo": { "implementation": "./src/executors/echo/executor", "schema": "./src/executors/echo/schema.json" } }}Reference
Section titled “Reference”24-0-0-enable-legacy-affected
Section titled “24-0-0-enable-legacy-affected”Version: 24.0.0-beta.3
Sets affected.legacy to true in nx.json so nx affected keeps selecting whole projects. Nx 24 selects individual affected tasks by default.
Keep legacy nx affected selection
Section titled “Keep legacy nx affected selection”In Nx 24, nx affected -t selects only the tasks whose inputs a change reaches, instead of every task of each affected project.
This migration sets affected.legacy to true in nx.json, so existing workspaces keep selecting whole projects after upgrading.
To switch to task selection, remove the setting or set it to false.
The NX_LEGACY_AFFECTED environment variable overrides the setting for a single run: false selects tasks and true selects projects.
The migration skips workspaces that already set affected.legacy.
Sample code changes
Section titled “Sample code changes”Before
Section titled “Before”{ "defaultBase": "main"}{ "defaultBase": "main", "affected": { "legacy": true }}24-0-0-rename-ultracache-ignore-options
Section titled “24-0-0-rename-ultracache-ignore-options”Version: 24.0.0-beta.3
Renames the ultracache target options “ignoredReads” and “ignoredWrites” to “ignoreReads” and “ignoreWrites”, and renames .nx/workflows/sandboxing-config.yaml to ultracache-config.yaml with its “exclude-reads” and “exclude-writes” keys renamed to “ignore-reads” and “ignore-writes”.
Rename ultracache ignore options
Section titled “Rename ultracache ignore options”Nx 24 renames the ultracache target options ignoredReads and ignoredWrites to ignoreReads and ignoreWrites.
The workspace-wide exclusions file moves from .nx/workflows/sandboxing-config.yaml to .nx/workflows/ultracache-config.yaml, and its exclude-reads and exclude-writes keys become ignore-reads and ignore-writes.
This migration renames the options in every target in project.json files, in the nx block of package.json files, and in targetDefaults in nx.json.
When a target sets both the old and the new option, it combines their patterns under the new one.
It renames .nx/workflows/sandboxing-config.yaml (or .yml) and the keys inside it, including those in task-exclusions entries.
It also updates any inputs or namedInputs entry that points at the old file.
If .nx/workflows/ultracache-config.yaml already exists, the migration leaves both files in place and lists them in its next steps so you can merge them by hand.
It does the same when the file writes those keys in a form it can’t rewrite, such as an inline { } map.
Sample code changes
Section titled “Sample code changes”Before
Section titled “Before”{ "targets": { "build": { "ultracache": { "ignoredReads": ["tmp/**"], "ignoredWrites": ["**/.cache/**"] } } }}exclude-reads: - 'dist/**'task-exclusions: - target: lint exclude-writes: - .eslintcache/**{ "targets": { "build": { "ultracache": { "ignoreReads": ["tmp/**"], "ignoreWrites": ["**/.cache/**"] } } }}ignore-reads: - 'dist/**'task-exclusions: - target: lint ignore-writes: - .eslintcache/**23.2.x
Section titled “23.2.x”23-2-0-set-cache-on-executor-target-defaults
Section titled “23-2-0-set-cache-on-executor-target-defaults”Version: 23.2.0-beta.8
Sets “cache” on some executor-based target defaults whose caching was previously enabled by a target name default, maintaining compatibility with how cacheability resolved before Nx 23. Keys the migration cannot decide are left alone, and the targets resolving through them need “cache” set by hand.
Set cache on executor-based target defaults
Section titled “Set cache on executor-based target defaults”Maintains compatibility with how cacheability was resolved before Nx 23.
Target defaults resolve to a single key rather than merging them. When a target matches both a target name key and an executor key, the executor key is the one that applies, and the target name key is not read at all. Earlier versions of Nx also derived cacheability from target names, so "cache": true on the target name key still took effect even when an executor key applied. Nx 23 reads cacheability from the resolved target only.
This migration copies cache onto each executor key that applies to a target whose target name key enables it, so those targets remain cacheable.
An executor key applies to every target that resolves through it, so the migration updates a key only when it can establish that caching is right for all of them. It leaves the key unchanged when the key already declares cache, when it declares continuous: true, when every entry on the key is filtered so none of them always applies, when a target through it is continuous or is a long-running target such as serve, dev, or start, when the executor’s own schema marks its targets continuous, or when a target through it has no target name key enabling cache. It never updates the nx:run-commands or nx:run-script keys, because targets written with command and targets derived from package.json scripts resolve through those keys without naming them.
Where the migration makes no change, the targets resolving through that key are not cached. Nx 24 reads cache from the key that wins resolution and nothing else, so cache on a target name key has no effect once an executor key applies. That leaves the keys the migration skips, the keys whose only cache declaration is filtered, the targets passed over because a sibling target through the same key does not opt in, and the targets reaching the nx:run-commands and nx:run-script keys. Set cache on the key those targets resolve through, or on the targets themselves.
Targets are read from each project’s project.json and from the nx.targets block of its package.json. Targets inferred by a plugin, and targets derived from package.json scripts, are not visible to the migration — the latter is why the nx:run-script key is never updated. A key that looks safe here may still serve an inferred target. Set cache on the executor key by hand only after checking that no target reaching it is continuous; Nx rejects a target that is both cacheable and continuous.
Sample code changes
Section titled “Sample code changes”Given a project with a build target that uses the @nx/angular:webpack-browser executor:
Before
Section titled “Before”{ "targetDefaults": { "build": { "cache": true, "dependsOn": ["^build"] }, "@nx/angular:webpack-browser": { "inputs": ["production", "^production"] } }}{ "targetDefaults": { "build": { "cache": true, "dependsOn": ["^build"] }, "@nx/angular:webpack-browser": { "inputs": ["production", "^production"], "cache": true } }}23.0.x
Section titled “23.0.x”23-0-0-add-migrate-runs-to-git-ignore
Section titled “23-0-0-add-migrate-runs-to-git-ignore”Version: 23.0.0-beta.18
Adds .nx/migrate-runs to .gitignore
22.7.x
Section titled “22.7.x”22-7-0-add-polygraph-to-git-ignore
Section titled “22-7-0-add-polygraph-to-git-ignore”Version: 22.7.0-beta.0
Adds .nx/polygraph to .gitignore
22-7-0-add-self-healing-to-gitignore
Section titled “22-7-0-add-self-healing-to-gitignore”Version: 22.7.0-beta.0
Adds .nx/self-healing to .gitignore
Add Self-Healing Directory to Git Ignore
Section titled “Add Self-Healing Directory to Git Ignore”Add gitignore entry for the .nx/self-healing directory, which stores local fix context generated by Nx’s self-healing CI feature.
Sample Code Changes
Section titled “Sample Code Changes”Adds the following entry to the .gitignore file.
.nx/self-healing22.6.x
Section titled “22.6.x”22-6-1-add-claude-worktrees-to-git-ignore
Section titled “22-6-1-add-claude-worktrees-to-git-ignore”Version: 22.6.0-beta.10
Adds .claude/worktrees to .gitignore
22-6-0-add-claude-settings-local-to-git-ignore
Section titled “22-6-0-add-claude-settings-local-to-git-ignore”Version: 22.6.0-rc.0
Adds .claude/settings.local.json to .gitignore
22-6-0-enable-analytics-prompt
Section titled “22-6-0-enable-analytics-prompt”Version: 22.6.0-beta.11
Prompts to enable usage analytics
22.1.x
Section titled “22.1.x”22-1-0-update-nx-wrapper
Section titled “22-1-0-update-nx-wrapper”Version: 22.1.0-beta.5
Updates the nx wrapper.
22.0.x
Section titled “22.0.x”22-0-0-release-version-config-changes
Section titled “22-0-0-release-version-config-changes”Version: 22.0.0-beta.1
Updates release version config based on the breaking changes in Nx v22
22-0-0-consolidate-release-tag-config
Section titled “22-0-0-consolidate-release-tag-config”Version: 22.0.0-beta.2
Consolidates releaseTag* options into nested releaseTag object structure
21.0.x
Section titled “21.0.x”remove-legacy-cache
Section titled “remove-legacy-cache”Version: 21.0.0-beta.8
Removes the legacy cache configuration from nx.json
Use Legacy Cache
Section titled “Use Legacy Cache”Removes useLegacyCache from nx.json as it is no longer functional in Nx 21
Sample Code Changes
Section titled “Sample Code Changes”Before
Section titled “Before”{ "targetDefaults": {}, "useLegacyCache": true}{ "targetDefaults": {}}remove-custom-tasks-runner
Section titled “remove-custom-tasks-runner”Version: 21.0.0-beta.8
Removes the legacy cache configuration from nx.json
Remove Custom Tasks Runners
Section titled “Remove Custom Tasks Runners”Removes tasksRunnerOptions entries from nx.json that contain custom tasks runners. In Nx 21, custom tasks runners are no longer functional. See /deprecated/custom-tasks-runner for more information.
Sample Code Changes
Section titled “Sample Code Changes”Removes custom task runner configuration from nx.json.
Before
Section titled “Before”{ "targetDefaults": {}, "tasksRunnerOptions": { "default": { "runner": "custom-task-runner" } }}{ "targetDefaults": {}}release-version-config-changes
Section titled “release-version-config-changes”Version: 21.0.0-beta.11
Updates release version config based on the breaking changes in Nx v21
Nx Release Version Config Changes
Section titled “Nx Release Version Config Changes”In Nx v21, the implementation details of versioning were rewritten to massively enhance flexibility and lay the groundwork for future features.
As part of this, some elements of the release configuration were updated. During the lifecycle of Nx v21, you can still opt into the old versioning by setting release.version.useLegacyVersioning to true, in which case the release configuration should remain unchanged.
In Nx v22, the legacy versioning implementation will be removed entirely and the configuration will have to be updated to match what this migration does for you.
Sample Code Changes
Section titled “Sample Code Changes”“generatorOptions” is longer exists and most non-ecosystem specific options have moved to the top level of “version” and are therefore fully documented on the JSON schema as a core option.
“packageRoot: string” has been replaced by the more flexible concept of “manifestRootsToUpdate: string[]”, allowing for multiple manifest files (such as package.json in the JS/TS ecosystem)
to be updated in a single versioning run.
Ecosystem specific options, such as “skipLockFileUpdate”, which is specific to the JS/TS ecosystem, are available via the new “versionActionsOptions” object, which is so named because of the new VersionActions abstraction introduced in Nx v21,
which allows for different ecosystems and use-cases to be supported via very minimal implementation effort.
“preserveLocalDependencyProtocols” changed from false by default to true by default in Nx v21, so it can simply be removed from the configuration when set to true.
The migration will also update release groups version configuration, as well as project.json and package.json version configuration, if applicable.
Before
Section titled “Before”{ "release": { "version": { "generatorOptions": { "packageRoot": "build/packages/{projectName}", "currentVersionResolver": "registry", "skipLockFileUpdate": true, "preserveLocalDependencyProtocols": true } } }}{ "release": { "version": { "manifestRootsToUpdate": ["build/packages/{projectName}"], "currentVersionResolver": "registry", "versionActionsOptions": { "skipLockFileUpdate": true } } }}release-changelog-config-changes
Section titled “release-changelog-config-changes”Version: 21.0.0-beta.11
Updates release changelog config based on the breaking changes in Nx v21
Nx Release Changelog Config Changes
Section titled “Nx Release Changelog Config Changes”In Nx v21, the mapAuthorsToGitHubUsernames changelog “renderOption” for the default changelog renderer was renamed to applyUsernameToAuthors to reflect the fact that it is no longer specific to GitHub. Most people were not setting this option directly, but if you were, it will be automatically migrated by this migration.
The migration will also update release groups changelog configuration, if applicable.
Sample Code Changes
Section titled “Sample Code Changes”Before
Section titled “Before”{ "release": { "changelog": { "workspaceChangelog": { "renderOptions": { "mapAuthorsToGitHubUsernames": true } }, "projectChangelogs": { "renderOptions": { "mapAuthorsToGitHubUsernames": false } } } }}{ "release": { "changelog": { "workspaceChangelog": { "renderOptions": { "applyUsernameToAuthors": true } }, "projectChangelogs": { "renderOptions": { "applyUsernameToAuthors": false } } } }}20.0.x
Section titled “20.0.x”move-use-daemon-process
Section titled “move-use-daemon-process”Version: 20.0.0-beta.7
Migration for v20.0.0-beta.7
Move useDaemonProcess
Section titled “Move useDaemonProcess”Move the useDaemonProcess to the root of nx.json
Sample Code Changes
Section titled “Sample Code Changes”Before
Section titled “Before”{ "tasksRunnerOptions": { "default": { "options": { "useDaemonProcess": false } } }}{ "useDaemonProcess": false}use-legacy-cache
Section titled “use-legacy-cache”Version: 20.0.1
Set useLegacyCache to true for migrating workspaces
Use Legacy Cache
Section titled “Use Legacy Cache”Set useLegacyCache to true for migrating workspaces
Sample Code Changes
Section titled “Sample Code Changes”Add useLegacyCache to nx.json unless enableDbCache was set to true.
Before
Section titled “Before”{ "targetDefaults": {}}{ "targetDefaults": {}, "useLegacyCache": true}19.2.x
Section titled “19.2.x”19-2-0-move-graph-cache-directory
Section titled “19-2-0-move-graph-cache-directory”Version: 19.2.0-beta.2
Updates the default workspace data directory to .nx/workspace-data
19-2-2-update-nx-wrapper
Section titled “19-2-2-update-nx-wrapper”Version: 19.2.2-beta.0
Updates the nx wrapper.
19-2-4-set-project-name
Section titled “19-2-4-set-project-name”Version: 19.2.4-beta.0
Set project name in nx.json explicitly
18.1.x
Section titled “18.1.x”move-default-base-to-nx-json-root
Section titled “move-default-base-to-nx-json-root”Version: 18.1.0-beta.3
Moves affected.defaultBase to defaultBase in nx.json
18.0.x
Section titled “18.0.x”18.0.0-disable-adding-plugins-for-existing-workspaces
Section titled “18.0.0-disable-adding-plugins-for-existing-workspaces”Version: 18.0.0-beta.2
Updates nx.json to disabled adding plugins when generating projects in an existing Nx workspace
17.3.x
Section titled “17.3.x”17.3.0-update-nx-wrapper
Section titled “17.3.0-update-nx-wrapper”Version: 17.3.0-beta.6
Updates the nx wrapper.
17.0.x
Section titled “17.0.x”17.0.0-move-cache-directory
Section titled “17.0.0-move-cache-directory”Version: 17.0.0-beta.1
Updates the default cache directory to .nx/cache
Sample Code Changes
Section titled “Sample Code Changes”Add .nx/cache to the .gitignore file.
Before
Section titled “Before”node_modulesnode_modules.nx/cacheAdd .nx/cache to the .prettierignore file.
Before
Section titled “Before”/dist/dist.nx/cache17.0.0-use-minimal-config-for-tasks-runner-options
Section titled “17.0.0-use-minimal-config-for-tasks-runner-options”Version: 17.0.0-beta.3
Use minimal config for tasksRunnerOptions
rm-default-collection-npm-scope
Section titled “rm-default-collection-npm-scope”Version: 17.0.0-rc.1
Migration for v17.0.0-rc.1
16.8.x
Section titled “16.8.x”16.8.0-escape-dollar-sign-env
Section titled “16.8.0-escape-dollar-sign-env”Version: 16.8.0-beta.3
Escape $ in env variables
16.6.x
Section titled “16.6.x”16.6.0-prefix-outputs
Section titled “16.6.0-prefix-outputs”Version: 16.6.0-beta.6
Prefix outputs with {workspaceRoot}/{projectRoot} if needed
16.2.x
Section titled “16.2.x”16.2.0-remove-output-path-from-run-commands
Section titled “16.2.0-remove-output-path-from-run-commands”Version: 16.2.0-beta.0
Remove outputPath from run commands
16.0.x
Section titled “16.0.x”16.0.0-remove-nrwl-cli
Section titled “16.0.0-remove-nrwl-cli”Version: 16.0.0-beta.0
Remove @nrwl/cli.
16.0.0-tokens-for-depends-on
Section titled “16.0.0-tokens-for-depends-on”Version: 16.0.0-beta.9
Replace dependsOn.projects and inputs definitions with new configuration format.
16.0.0-update-nx-cloud-runner
Section titled “16.0.0-update-nx-cloud-runner”Version: 16.0.0-beta.0
Replace @nrwl/nx-cloud with nx-cloud