Migrate from @nx-dotnet/core to @nx/dotnet

Last updated: July 8, 2026

This guide provides a streamlined migration path from the community @nx-dotnet/core plugin to Nx official @nx/dotnet plugin.

Plugin Status

The @nx-dotnet/core plugin is deprecated in favor of the official @nx/dotnet plugin (available in Nx 22+), which is maintained by the Nx team and integrated directly into the Nx repository.

Why migrate?

The official @nx/dotnet plugin represents a natural evolution, building on lessons learned from the community plugin while embracing native .NET workflows:

  • Project inference: Automatic detection of .NET projects without configuration with Nx inferred targets
  • MSBuild integration: Direct use of Microsoft's APIs for accurate dependency analysis
  • Native CLI first: Uses dotnet commands directly instead of custom wrappers
  • Minimal abstraction: Simpler implementation with fewer dependencies

This results in a faster, and more reliable .NET plugin.

Prerequisites

Before starting the migration:

  • [ ] Upgrade to .NET SDK 8.0 or later (required)
  • [ ] Locate your current @nx-dotnet/core configuration (see below)
  • [ ] Review any custom generators and executors you're using
  • [ ] Ensure your projects build successfully with current setup

Locating your configuration

The @nx-dotnet/core plugin configuration can be in one of two places:

nx.json

{
  "plugins": [
    {
      "plugin": "@nx-dotnet/core",
      "options": {
        "inferredTargets": { ... },
        "solutionFile": "...",
        // ... other options
      }
    }
  ]
}

.nx-dotnet.rc.json

{
  "inferredTargets": { ... },
  "solutionFile": "...",
  // ... other options
}

No Configuration?

If you don't have custom configuration in either location, that's fine! The plugin works with defaults, and migration will be even simpler.

Migration steps

1. Install @nx/dotnet

nx add @nx/dotnet

This automatically:

  • Adds @nx/dotnet as a dependency
  • Registers the plugin in nx.json
  • Configures target inputs
  • Updates .gitignore

2. Remove @nx-dotnet/core

npm uninstall @nx-dotnet/core @nx-dotnet/utils @nx-dotnet/dotnet

Clean up the relevant workspace configurations:

  • Remove @nx-dotnet/core from the plugins array in nx.json (if present)
  • Delete .nx-dotnet.rc.json (if it exists)

3. Migrate plugin configuration

Move any customized target configurations from your @nx-dotnet/core config to the new @nx/dotnet plugin options.

Before (in nx.json or .nx-dotnet.rc.json):

{
  "inferredTargets": {
    "build": "build",
    "test": {
      "targetName": "test:dotnet",
      "cache": false
    }
  }
}

After (in nx.json):

// nx.json
{
  "plugins": [
    {
      "plugin": "@nx/dotnet",
      "options": {
        "build": {
          "targetName": "build"
        },
        "test": {
          "targetName": "test:dotnet"
        }
      }
    }
  ]
}

4. clear cache and verify

nx reset
nx graph

The nx graph command should show all your .NET projects with their dependencies correctly detected. If you encounter any issues, see the Troubleshooting section below.

Key workflow changes

Here's what changes in your day-to-day usage with the new @nx/dotnet plugin:

TaskOld (@nx-dotnet/core)New (@nx/dotnet)
Create applicationnx g @nx-dotnet/core:app my-apidotnet new webapi -n MyApi
Create librarynx g @nx-dotnet/core:lib my-libdotnet new classlib -n MyLib
Add project referencenx g @nx-dotnet/core:project-reference --source A --target Bdotnet add reference ../B/B.csproj
Add NuGet packagenx g @nx-dotnet/core:nuget-referencedotnet add package PackageName
Build projectnx build my-apinx build my-api ✅ (same)
Run testsnx test my-apinx test my-api ✅ (same)
Serve/watchnx serve my-apidotnet watch run (or configure custom target)

Default targets generated

The plugin automatically creates these targets for .NET projects:

TargetWhen CreatedCommand
buildAll projectsdotnet build --no-restore --no-dependencies
testTest projects onlydotnet test --no-build --no-restore
restoreAll projectsdotnet restore
cleanAll projectsdotnet clean
publishExecutable projectsdotnet publish
packLibrary projectsdotnet pack

Adding back missing targets

The serve and format targets are not automatically created. serve defaults to a target named watch now. To run it, you'd need to run nx run my-api:watch run. To configure the watch target to act like serve, you could set the following in nx.json:

// nx.json
{
  "plugins": [
    {
      "plugin": "@nx/dotnet",
      "options": {
        "watch": {
          "targetName": "serve",
          "args": ["run"]
        }
      }
    }
  ]
}

The format target is not present by default. You should add it as a custom target if desired.

Advanced migration scenarios

Migrating from explicit executor configurations

If you have project.json files that explicitly configure @nx-dotnet/core executors, you'll need to update them to use command targets.

Before (project.json):

// project.json
{
  "name": "my-api",
  "targets": {
    "build": {
      "executor": "@nx-dotnet/core:build",
      "options": {
        "configuration": "Release",
        "noDependencies": true
      }
    },
    "test": {
      "executor": "@nx-dotnet/core:test",
      "options": {
        "testProject": "MyApi.Tests.csproj"
      }
    },
    "serve": {
      "executor": "@nx-dotnet/core:serve",
      "options": {
        "project": "MyApi.csproj"
      }
    }
  }
}

After (project.json):

// project.json
{
  "name": "my-api",
  "targets": {
    "build": {
      "command": "dotnet build",
      "options": {
        "cwd": "{projectRoot}",
        "args": ["--configuration", "Release", "--no-dependencies"]
      }
    },
    "test": {
      "command": "dotnet test MyApi.Tests.csproj",
      "options": {
        "cwd": "{projectRoot}"
      }
    },
    "serve": {
      "command": "dotnet watch run",
      "options": {
        "cwd": "{projectRoot}"
      }
    }
  }
}

Automatic Target Inference

In most cases, you can delete these project.json files entirely. The @nx/dotnet plugin will automatically infer the correct targets based on your .csproj files. Only keep custom project.json configurations if you need non-standard options.

Migrating from inferProjects: false

If you previously set inferProjects: false in your @nx-dotnet/core config, this option no longer exists in @nx/dotnet. The new plugin always infers projects automatically.

Why this changed:

  • Project inference is a core feature of how Nx plugins work
  • Manual project management doesn't align with Nx preferred automatic detection model
  • Maintaining explicit project configurations is error-prone

Migration path:

  1. If you disabled inference to exclude certain projects:

    • Use the exclude property in the plugin configuration:
      // nx.json
      {
        "plugins": [
          {
            "plugin": "@nx/dotnet",
            "exclude": ["legacy-projects/**", "temp-projects/**"]
          }
        ]
      }
      
  2. If you disabled inference to use explicit project.json files:

    • The new plugin will still detect your projects via .csproj files
    • You can keep project.json files to customize targets, but they're optional
    • Consider removing them to use the automatically inferred targets

Configuration changes

Module boundaries → Nx conformance

If you used moduleBoundaries in your @nx-dotnet/core config, you may want to migrate to Nx Conformance rules

The script used to evaluate module boundaries is missing several features from the eslint and conformance implementations, and is not present in the new plugin. If you wish to continue using it, you'll need to inline the implementation in your repository and update the path in Directory.build.targets. Otherwise, you should remove the target from Directory.build.targets.

NuGet package management

Replace the sync generator with MSBuild's Central Package Management.

Create Directory.Packages.props at workspace root:

// Directory.Packages.props
<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>
  <ItemGroup>
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.0" />
  </ItemGroup>
</Project>

Update project files to remove version attributes:

- <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+ <PackageReference Include="Newtonsoft.Json" />

Testing the migration

Run these commands to verify everything works:

# Clear cache
nx reset

# Verify project detection
nx show projects

# Test builds
nx run-many -t build

# Test affected builds
nx affected -t build

# Run tests
nx run-many -t test

Troubleshooting

Projects not detected after migration

Symptom: Some .NET projects don't appear in nx show projects

Solution:

  • Ensure project files have .csproj, .fsproj, or .vbproj extensions
  • Check that the plugin is registered in nx.json
  • Run nx reset to clear the cache

"Could not find project reference" build error

Symptom: Build fails with "Could not find project reference"

Solution:

  • Verify the referenced project exists in the workspace
  • Ensure build targets have "dependsOn": ["^build"] (plugin adds this automatically)
  • Check that project references in .csproj files use correct relative paths
  • Run nx reset to clear stale cache

Missing Targets (test, pack, publish)

Symptom: Expected targets like test or pack don't show up

Solution:

  • test: Only created for projects with IsTestProject property or Microsoft.NET.Test.Sdk package
  • pack: Only created for library projects (not executables)
  • publish: Only created for executable projects (OutputType="Exe")
  • Use nx show project my-project to see all available targets

Project name mismatch after migration

Symptom: Project names don't match expectations

Solution: Add a Name property to your .csproj file under the Nx property group:

<PropertyGroup>
  <Nx>
    <Name>my-custom-name</Name>
  </Nx>
</PropertyGroup>

Next steps

After completing the migration:

  • Review the incremental builds guide to understand how --no-dependencies optimizes builds
  • Configure Nx Cloud for improved repo experience for your team and CI
  • Set up custom targets for serve, lint, or other specialized tasks as needed
  • Update CI/CD pipelines to ensure .NET SDK 8.0+ is installed

Additional resources