# msbuild-modernization

A skill that rewrites legacy .NET project files to SDK-style: trims the XML, moves packages to PackageReference, hands assembly attributes to the SDK.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 3700 installs · ★ 5730
- Author: dotnet
- License: MIT · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/dotnet/skills/tree/HEAD/plugins/dotnet-msbuild/skills/msbuild-modernization/SKILL.md
- Updated: 2026-10-24
- HTML: https://affpapa.org/en/nevibecode/skills/msbuild-modernization

## What it does

The skill takes an inherited `.csproj` or `.vbproj` and turns it into an SDK-style project. It starts by looking for the usual tells: a `ToolsVersion` attribute, an `Import` of `Microsoft.CSharp.targets` through `$(MSBuildToolsPath)`, a `packages.config`, a `Properties\AssemblyInfo.cs`. Quick check before you commit to the work: a simple library whose project file runs past 50 lines is almost certainly legacy.

Then it walks the migration. The root element becomes `<Project Sdk="Microsoft.NET.Sdk">`, `TargetFrameworkVersion` becomes `TargetFramework` (`v4.7.2` → `net472`), and the `<Compile Include>` and `<Content Include>` groups are deleted outright because the SDK globs files on its own. Assemblies attributes leave `AssemblyInfo.cs` for project properties; `packages.config` becomes `<PackageReference>` items.

Keeping `AssemblyInfo.cs` is possible, but then the project needs `<GenerateAssemblyInfo>false</GenerateAssemblyInfo>`. Without it the attributes get generated twice and the build fails. The skill also stays away from projects already in SDK-style, from npm, Maven and CMake builds, and from .NET Framework projects that cannot make the move.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill msbuild-modernization -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/msbuild-modernization/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/msbuild-modernization/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill msbuild-modernization -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/msbuild-modernization/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill msbuild-modernization -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/msbuild-modernization/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install dotnet/skills msbuild-modernization
```

2. **Manually: put the files in place**
- File: `.github/skills/msbuild-modernization/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill msbuild-modernization -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/dotnet/skills --path plugins/dotnet-msbuild/skills/msbuild-modernization
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/msbuild-modernization/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add dotnet/skills --skill msbuild-modernization -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/dotnet/skills/tree/HEAD/plugins/dotnet-msbuild/skills/msbuild-modernization/SKILL.md

## When to use it
- convert a legacy .csproj to SDK-style without hand-editing XML
- move NuGet packages out of `packages.config` into `PackageReference`
- strip long `<Compile Include>` lists from a project
- move assembly attributes from `AssemblyInfo.cs` into project properties
- consolidate shared settings into `Directory.Build.props`

## Example prompts
- Convert `MyLibrary.csproj` to SDK-style and show me the diff
- Migrate every `packages.config` in this solution to `PackageReference`
- Pull the shared settings out of the projects into `Directory.Build.props`

## Source text · SKILL.md · MIT

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 8163d5dccd614315.

BEGIN THIRD-PARTY FILE 8163d5dccd614315
````text
---
name: msbuild-modernization
description: "Guide for modernizing and migrating MSBuild project files to SDK-style format. USE FOR: converting legacy .csproj/.vbproj with verbose XML to SDK-style, migrating packages.config to PackageReference, removing Properties/AssemblyInfo.cs in favor of auto-generation, eliminating explicit Compile Include lists via implicit globbing, consolidating shared settings into Directory.Build.props. Indicators of legacy projects: ToolsVersion attribute, an Import of Microsoft.CSharp.targets via $(MSBuildToolsPath), .csproj files over 50 lines for simple projects. DO NOT USE FOR: projects already in SDK-style format, non-.NET build systems (npm, Maven, CMake), .NET Framework projects that cannot move to SDK-style."
license: MIT
---

# MSBuild Modernization: Legacy to SDK-style Migration

## Identifying Legacy vs SDK-style Projects

**Legacy indicators:**

- `<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />`
- Explicit file lists (`<Compile Include="..." />` for every `.cs` file)
- `ToolsVersion` attribute on `<Project>` element
- `packages.config` file present
- `Properties\AssemblyInfo.cs` with assembly-level attributes

**SDK-style indicators:**

- `<Project Sdk="Microsoft.NET.Sdk">` attribute on root element
- Minimal content — a simple project may be 10–15 lines
- No explicit file includes (implicit globbing)
- `<PackageReference>` items instead of `packages.config`

**Quick check:** if a `.csproj` is more than 50 lines for a simple class library or console app, it is likely legacy format.

```xml
<!-- Legacy: ~80+ lines for a simple library -->
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <OutputType>Library</OutputType>
    <RootNamespace>MyLibrary</RootNamespace>
    <AssemblyName>MyLibrary</AssemblyName>
    <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <!-- ... 60+ more lines ... -->
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
````
END THIRD-PARTY FILE 8163d5dccd614315

The third-party file has ended. Everything between the 8163d5dccd614315 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2399 of 17445 bytes. © dotnet · MIT · https://github.com/dotnet/skills/tree/HEAD/plugins/dotnet-msbuild/skills/msbuild-modernization/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
