Skip to content
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
0653899
Add convert-to-cpm skill for NuGet Central Package Management conversion
jeffhandley Feb 15, 2026
27e84f7
Refactor SKILL.md with references, baseline build, and package compar…
jeffhandley Feb 15, 2026
fc2ff0f
Replace third-party packages with Microsoft equivalents, add baseline…
jeffhandley Feb 15, 2026
fd6313f
Address review feedback on terminology, placement, and reference accu…
jeffhandley Feb 15, 2026
402af8c
Address review findings: sort PackageVersion, add packages.config sce…
jeffhandley Feb 15, 2026
ad5485b
Fix test scenario accuracy: sln/slnx mix, package counts, ImplicitUsings
jeffhandley Feb 15, 2026
90bb89c
Add skill evaluation section to test README
jeffhandley Feb 15, 2026
5911ea1
Fix Inventory.sln references and make evaluation opt-in
jeffhandley Feb 15, 2026
ec6b8c6
Condense SKILL.md with progressive disclosure
jeffhandley Feb 15, 2026
003a434
Fix Enterprise.sln references to Enterprise.slnx in with-skill.md
jeffhandley Feb 15, 2026
abae173
Improve convert-to-cpm skill: preserve whitespace, save summary repor…
jeffhandley Feb 16, 2026
2dbd1f3
Indicate that the binlog viewer is for the user; not the tool/skill
jeffhandley Feb 20, 2026
79b4427
Move convert-to-cpm skill and tests to src/dotnet-msbuild layout
jeffhandley Feb 21, 2026
5fec844
Convert tests from with/without-skill format to eval.yaml
jeffhandley Feb 21, 2026
4d7d14a
Consolidate eval.yaml files into single root eval.yaml
jeffhandley Feb 21, 2026
d3270b4
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 2, 2026
a899154
Reorganize convert-to-cpm into plugins/tests folders
jeffhandley Mar 3, 2026
76dd717
Add post-conversion reporting rubrics to CPM eval scenarios
jeffhandley Mar 4, 2026
56dd1d5
Improve post-conversion reporting, conflict resolution, and skill act…
jeffhandley Mar 4, 2026
12a5dee
Address PR feedback from kartheekp-ms
jeffhandley Mar 4, 2026
d2914be
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 4, 2026
636ce91
Improve convert-to-cpm skill activation, artifact preservation, and e…
jeffhandley Mar 5, 2026
f006833
Extend timeouts and add CODEOWNERS entry
jeffhandley Mar 6, 2026
f6a9b95
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 6, 2026
a5f4d3c
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 7, 2026
9c9bc1f
Move convert-to-cpm skill into a new dotnet-nuget plugin
jeffhandley Mar 7, 2026
dab18d4
Fix erroneous plugin msbuild/nuget plugin split change. Add dotnet-nu…
jeffhandley Mar 9, 2026
bb07e7a
Merge branch 'main' into jeffhandley/convert-to-cpm
ViktorHofer Mar 9, 2026
b46dba1
Add NuGet package management skills to README
ViktorHofer Mar 9, 2026
338e1e1
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 12, 2026
5324fb7
Merge branch 'jeffhandley/convert-to-cpm' of https://github.com/dotne…
jeffhandley Mar 12, 2026
49c19ea
Address PR feedback: clarify CPM sub-folder semantics, remove securit…
jeffhandley Mar 12, 2026
c0f6e48
Extend eval timeouts for scenarios hitting time limits
jeffhandley Mar 12, 2026
110e2b8
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 12, 2026
8c71103
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 17, 2026
d76e394
Add missing CODEOWNERS for dotnet-nuget plugin. Reorder convert-to-cp…
jeffhandley Mar 18, 2026
0e93231
Remove containing skill mentions from reference files; fix ordering
jeffhandley Mar 18, 2026
c050835
Replace output_matches with deterministic file assertions in eval.yaml
jeffhandley Mar 18, 2026
fe1ad3b
Reorganize skill description with USE FOR / DO NOT USE FOR markers
jeffhandley Mar 18, 2026
341d7c6
Fix issues for external link references
jeffhandley Mar 18, 2026
1b5e61f
Increase timeouts
jeffhandley Mar 18, 2026
a919a64
Handle packages.config non-activation in convert-to-cpm skill
jeffhandley Mar 18, 2026
65a663d
Remove leading blank lines from .sln test files
jeffhandley Mar 18, 2026
c2fe3c8
Use imperative 'Read' instead of 'See' for reference file links
jeffhandley Mar 18, 2026
286772e
Merge branch 'main' into jeffhandley/convert-to-cpm
jeffhandley Mar 18, 2026
3c6d391
Simplify dotnet-nuget CODEOWNERS
jeffhandley Mar 18, 2026
1351841
Simplify packages.config guard
jeffhandley Mar 18, 2026
b5dc93d
Add minimal Program.cs entrypoints to Web/Worker test fixtures
jeffhandley Mar 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
"source": "./plugins/dotnet-msbuild",
"description": "Comprehensive MSBuild and .NET build skills: failure diagnosis, performance optimization, code quality, and modernization."
},
{
"name": "dotnet-nuget",
"source": "./plugins/dotnet-nuget",
"description": "NuGet and .NET package management: dependency management and modernization."
},
{
"name": "dotnet-upgrade",
"source": "./plugins/dotnet-upgrade",
Expand Down
7 changes: 7 additions & 0 deletions .github/CODEOWNERS
Comment thread
jeffhandley marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,10 @@
# dotnet-maui
/plugins/dotnet-maui/ @Redth @jfversluis
/tests/dotnet-maui/ @Redth @jfversluis

# dotnet-nuget (package and dependency management)
Comment thread
jeffhandley marked this conversation as resolved.
/plugins/dotnet-nuget/ @dotnet/area-infrastructure-libraries @kartheekp-ms
/tests/dotnet-nuget/ @dotnet/area-infrastructure-libraries @kartheekp-ms

/plugins/dotnet-nuget/skills/convert-to-cpm/ @dotnet/area-infrastructure-libraries
/tests/dotnet-nuget/convert-to-cpm/ @dotnet/area-infrastructure-libraries
Comment thread
jeffhandley marked this conversation as resolved.
Outdated
5 changes: 5 additions & 0 deletions .github/plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
"source": "./plugins/dotnet-msbuild",
"description": "Comprehensive MSBuild and .NET build skills: failure diagnosis, performance optimization, code quality, and modernization."
},
{
"name": "dotnet-nuget",
"source": "./plugins/dotnet-nuget",
"description": "NuGet and .NET package management: dependency management and modernization."
},
{
Comment thread
jeffhandley marked this conversation as resolved.
"name": "dotnet-upgrade",
"source": "./plugins/dotnet-upgrade",
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This repository contains the .NET team's curated set of core skills and custom a
| [dotnet-data](plugins/dotnet-data/) | Skills for .NET data access and Entity Framework related tasks. |
| [dotnet-diag](plugins/dotnet-diag/) | Skills for .NET performance investigations, debugging, and incident analysis. |
| [dotnet-msbuild](plugins/dotnet-msbuild/) | Comprehensive MSBuild and .NET build skills: failure diagnosis, performance optimization, code quality, and modernization. |
| [dotnet-nuget](plugins/dotnet-nuget/) | NuGet and .NET package management: dependency management and modernization. |
| [dotnet-upgrade](plugins/dotnet-upgrade/) | Skills for migrating and upgrading .NET projects across framework versions, language features, and compatibility targets. |
| [dotnet-maui](plugins/dotnet-maui/) | Skills for .NET MAUI development: environment setup, diagnostics, and troubleshooting. |
| [dotnet-ai](plugins/dotnet-ai/) | AI and ML skills for .NET: technology selection, LLM integration, agentic workflows, RAG pipelines, MCP, and classic ML with ML.NET. |
Expand Down
2 changes: 2 additions & 0 deletions eng/reference-scanner/known-domains.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ github.com/dotnet/dotnet-api-docs
github.com/dotnet/dotnet-docker
github.com/dotnet/efcore
github.com/dotnet/maui
github.com/dotnet/msbuild
github.com/dotnet/roslyn
github.com/dotnet/runtime
github.com/dotnet/sdk
Expand All @@ -50,6 +51,7 @@ github.com/microsoft/openjdk
github.com/microsoft/perfview
github.com/microsoftdocs/visualstudio-docs
github.com/modelcontextprotocol/csharp-sdk
github.com/NuGet/docs.microsoft.com-nuget
Comment thread
jeffhandley marked this conversation as resolved.

# Community
ollama.com
Expand Down
6 changes: 6 additions & 0 deletions plugins/dotnet-nuget/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "dotnet-nuget",
"version": "0.1.0",
"description": "NuGet and .NET package management skills: dependency management and modernization.",
"skills": "./skills/"
}
168 changes: 168 additions & 0 deletions plugins/dotnet-nuget/skills/convert-to-cpm/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
---
name: convert-to-cpm
description: >
Convert .NET projects and solutions (.sln, .slnx) to NuGet Central Package Management
(CPM) using Directory.Packages.props. USE FOR: converting to CPM, centralizing or
aligning NuGet package versions across multiple projects, inlining MSBuild version
properties from Directory.Build.props into Directory.Packages.props, resolving version
conflicts or mismatches across a solution or repository, updating or bumping or syncing
package versions across projects. Also activate when packages are out of sync, drifting,
or inconsistent — even without the user mentioning CPM. Provides baseline build capture,
version conflict resolution, build validation with binlog comparison, and a structured
post-conversion report. DO NOT USE FOR: packages.config projects (must migrate to
PackageReference first) or repositories that already have CPM fully enabled.
---

# Convert to Central Package Management

Migrate .NET projects from per-project package versioning to NuGet Central Package Management (CPM). CPM centralizes all package versions into a single `Directory.Packages.props` file, making version governance and upgrades easier across multi-project repositories.

## When to Use

- The user wants to adopt Central Package Management for a .NET repository, solution, or project
- Package versions are scattered across many `.csproj`, `.fsproj`, or `.vbproj` files and the user wants a single source of truth
- The user mentions `Directory.Packages.props`, CPM, or centralizing NuGet versions
- The user wants to update, bump, upgrade, align, or sync a NuGet package version across multiple projects — CPM is the recommended approach for managing shared package versions, so suggest converting to CPM as part of the update if the projects use `PackageReference` and CPM is not already enabled
- Package versions are out of sync, conflicting, or mismatched across projects and the user wants to resolve or unify them

## When Not to Use

- The repository already has CPM fully enabled for all in-scope projects
- The user is working with `packages.config`-based projects (must first migrate to `PackageReference`)
- The user wants to manage versions via a custom MSBuild property file without using CPM

## Inputs

| Input | Required | Description |
|-------|----------|-------------|
| Scope | Yes | A project file, solution file, or directory containing .NET projects to convert |
| Version conflict strategy | No | How to resolve cases where the same package has different versions across projects. When conflicts are detected, do not assume a default strategy — ask the user which strategy to use or explicitly confirm a proposed strategy before proceeding. |

## Workflow

### Step 1: Determine scope

- **Single project**: User specifies a `.csproj`, `.fsproj`, or `.vbproj`.
- **Solution**: User specifies a `.sln` or `.slnx`. List projects with `dotnet sln list`.
- **Repository/directory**: No specific file given. Find all project files recursively from the first common ancestor directory of all .NET projects in scope.

If the scope is unclear, ask the user.

**Guard: Check for packages.config projects.** Before proceeding, check whether any project in scope uses `packages.config` instead of `PackageReference`. Look for `packages.config` files alongside project files, and check whether the project files use legacy non-SDK format (e.g., `<Project ToolsVersion="..." xmlns="...">` instead of `<Project Sdk="...">`). If any `packages.config` usage is detected, **stop and do not proceed with the conversion**. Inform the user that CPM requires SDK-style projects with `PackageReference` format and that they must first migrate from `packages.config` to `PackageReference` (e.g., using Visual Studio's built-in migration or the `dotnet migrate` tooling). This skill cannot perform that migration.
Comment thread
jeffhandley marked this conversation as resolved.
Outdated

### Step 2: Establish baseline build

Before making any changes, verify the scope builds successfully and capture a baseline binlog and package list. Run `dotnet clean`, then `dotnet build -bl:baseline.binlog`, then `dotnet package list --format json > baseline-packages.json`. Read [baseline-comparison.md](references/baseline-comparison.md) for the full procedure and fallback options. If the baseline build fails, stop and inform the user — the scope must build cleanly before conversion. Do not delete `baseline.binlog` or `baseline-packages.json` — they are needed for the post-conversion comparison and report.

Comment thread
jeffhandley marked this conversation as resolved.
### Step 3: Check for existing CPM

Search for any existing `Directory.Packages.props` in scope or ancestor directories. If CPM is already fully enabled, inform the user and stop. If a `Directory.Packages.props` exists without CPM enabled, ask whether to add the property to the existing file or create a new one.

### Step 4: Audit package references
Comment thread
jeffhandley marked this conversation as resolved.

Run `dotnet package list --format json` to get the resolved package references across all in-scope projects. Also scan `<Import>` elements to discover shared `.props`/`.targets` files containing package references.

Check for complexities: version conflicts, MSBuild property-based versions, conditional references, security advisories, and existing `VersionOverride` usage. Read [audit-complexities.md](references/audit-complexities.md) for the full checklist.

Present audit results to the user before proceeding, including:
- A table of each package, its version(s), and which projects use it
- Any version conflicts, security advisories, or complexities requiring decisions

When version conflicts exist, present each one individually with the affected projects, the distinct versions found, and the resolution options (align to highest, use `VersionOverride`, etc.) with their trade-offs. Do not upgrade any package beyond the highest version already in use across the scope — this avoids introducing version incompatibilities or breaking changes that are unrelated to the CPM conversion itself. Note any known security advisories or other upgrade opportunities as follow-up items for the user to address after the conversion is complete. Ask the user to decide on each conflict before proceeding. Read [audit-complexities.md § Same package with different versions](references/audit-complexities.md) for the resolution workflow and presentation format.

### Step 5: Create or update Directory.Packages.props

Create the file with `dotnet new packagesprops` (.NET 8+) or manually. Add a `<PackageVersion>` entry for each unique package sorted alphabetically. For conditional versions or `VersionOverride` patterns, read [directory-packages-props.md](references/directory-packages-props.md).

### Step 6: Update project files

Remove the `Version` attribute from every `<PackageReference>` that now has a corresponding `<PackageVersion>`. Also update any shared `.props`/`.targets` files identified in step 4.

- Preserve all other attributes (`PrivateAssets`, `IncludeAssets`, `ExcludeAssets`, `GeneratePathProperty`, `Aliases`)
- Preserve conditional `<ItemGroup>` elements — only remove the `Version` attribute within them
- Retain each file's existing indentation style (spaces vs. tabs, indentation depth) and blank lines — do not reformat or reorganize unchanged lines
- Use `VersionOverride` (with user confirmation) when a project needs a different version than the central one

### Step 7: Handle MSBuild version properties

For `PackageReference` items that used MSBuild properties for versions, determine whether to inline the resolved value or keep the property reference in `Directory.Packages.props`. After validation succeeds in step 8, remove inlined version properties from `Directory.Build.props` or other files, verifying they have no remaining references. Read [msbuild-property-handling.md](references/msbuild-property-handling.md) for the decision workflow, import order requirements, and cleanup procedure.

### Step 8: Restore and validate

Run a clean restore and build, capturing a post-conversion binlog and package list. Run `dotnet clean`, then `dotnet build -bl:after-cpm.binlog`, then `dotnet package list --format json > after-cpm-packages.json`. Read [baseline-comparison.md](references/baseline-comparison.md) for the full procedure. If errors occur, read [validation-and-errors.md](references/validation-and-errors.md) for NuGet error codes and multi-TFM guidance.

**Do not delete or clean up any artifacts** (`baseline.binlog`, `after-cpm.binlog`, `baseline-packages.json`, `after-cpm-packages.json`). These files must be preserved for the user to inspect after the conversion. They are deliverables, not temporary files.

### Step 9: Post-conversion report

**You must create a `convert-to-cpm.md` file** alongside the binlog and JSON artifacts. Do not skip this step or substitute inline chat output for the file — the user needs a persistent, shareable document. This file should be self-contained and shareable — suitable for a pull request description, a team review, or a record of what was done. Structure the report with the following sections:

#### Section 1: Conversion overview

Summarize what was converted: the scope (project, solution, or repository), number of projects converted, total packages centralized, any projects or packages that were skipped, and any MSBuild properties that were inlined or removed. This gives the reader immediate context.

#### Section 2: Version conflict resolutions

If any version conflicts were encountered, list each one with:

- The package name and all versions that were found across projects
- Which projects used each version
- What the user decided (aligned to highest, used `VersionOverride`, etc.)
- The practical impact: which projects now resolve a different version than before, and which are unchanged

If no conflicts were found, state that all packages had consistent versions across projects — this is a positive signal worth noting.

#### Section 3: Package comparison — baseline vs. result

Compare `baseline-packages.json` and `after-cpm-packages.json` per project. See [baseline-comparison.md](references/baseline-comparison.md) for the comparison procedure. Present two tables:

- **Changes table**: Packages where the resolved version changed, a `VersionOverride` was introduced, or a package was added/removed. Include a status column explaining what changed and why (e.g., "VersionOverride — project retains pinned version", "Aligned to highest version").
- **Unchanged table**: All other packages, confirming they resolve identically to baseline.

If there are no changes at all, state that the conversion is fully version-neutral — this is the ideal outcome and provides reassurance.

#### Section 4: Risk assessment

Provide a clear confidence statement:

- **✅ Low risk** — Conversion is version-neutral; all packages resolve to the same versions as baseline. The build and restore succeeded. Recommend running `dotnet test` as a final check.
- **⚠️ Moderate risk** — Some packages changed versions (e.g., minor/patch alignment). List the affected packages and projects. Recommend reviewing the changes table and running `dotnet test` to verify no regressions.
- **🔴 High risk** — Major version changes were applied, or packages were added/removed unexpectedly. Recommend careful review, running `dotnet test`, and comparing binlogs before merging.

Call out any specific warnings: `VersionOverride` usage that partially undermines centralization, or MSBuild property removal that could affect other build logic.

#### Section 5: Follow-up items

List any items identified during the conversion that the user should address separately after the CPM conversion is complete. These are intentionally out of scope for the conversion itself but important for the user to act on. Common follow-up items include:

- **Security advisories**: If any package versions are known to have security vulnerabilities (detected via `dotnet package list --vulnerable` or noted during the audit), list each advisory with the package name, current version, affected projects, and the minimum patched version. These upgrades are out of scope for the CPM conversion to avoid introducing version incompatibilities or breaking changes.
- **Deprecated packages**: If any packages are deprecated, note the recommended replacement.
- **Version alignment opportunities**: If `VersionOverride` was used to preserve differing versions, note that the user may want to align these in the future once the affected projects can be validated against the central version.
- **Test validation**: Recommend running `dotnet test` to validate runtime behavior beyond build success, especially if any version conflicts were resolved by aligning to the highest version.

Present follow-up items as a numbered checklist so the user can track them.

#### Section 6: Artifacts and how to use them

List the artifacts produced during conversion and explain how to use them:

- **`baseline.binlog`** and **`after-cpm.binlog`** — MSBuild binary logs captured before and after conversion. These are available for manual validation and troubleshooting if needed.
- **`baseline-packages.json`** and **`after-cpm-packages.json`** — Machine-readable snapshots of resolved package versions per project, used to produce the comparison tables above.
- **`convert-to-cpm.md`** — This report file, suitable for use as a pull request description or team review artifact.

Recommend the user run `dotnet test` to validate runtime behavior beyond build success. If any version conflicts were resolved by aligning to the highest version, recommend reviewing the release notes for the affected packages.

## Validation

- [ ] Baseline build succeeded before any changes were made
- [ ] `Directory.Packages.props` exists with `ManagePackageVersionsCentrally` set to `true`
- [ ] Every in-scope `PackageReference` either has no `Version` attribute or uses `VersionOverride`
- [ ] Every referenced package has a corresponding `PackageVersion` entry
- [ ] `dotnet restore` and `dotnet build` complete without errors from a clean state
- [ ] Package list comparison shows no unexpected version changes
- [ ] No orphaned version properties remain (unless intentionally kept)

## More Info

- [Central Package Management documentation](https://github.com/NuGet/docs.microsoft.com-nuget/blob/main/docs/consume-packages/Central-Package-Management.md)
- [Validation and common errors](references/validation-and-errors.md)
Loading
Loading