# Converting To Sdk Style

> Converts legacy non-SDK-style .NET project files (.csproj, .vbproj, .fsproj) to modern SDK-style format while preserving target frameworks, dependencies, and build behavior. Use when converting old-format .NET projects, migrating from packages.config to PackageReference, or modernizing project files. Also triggers for "convert to SDK style", "modernize csproj", "update project format", "legacy project migration", and "SDK-style conversion".

- Skill: `microsoft/converting-to-sdk-style` (Agent Skill)
- Install (CLI): `npx skillmds@latest add microsoft/converting-to-sdk-style`
- Raw SKILL.md: https://api.skillmd.com/api/skills/microsoft/converting-to-sdk-style/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: Microsoft (https://skillmd.com/u/microsoft)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/microsoft/converting-to-sdk-style

---


# SDK Style Conversion

## Overview

Guide the step-by-step conversion of legacy (non SDK-style) project files to SDK-style while preserving existing target frameworks, behavior, and build output. This is a structural-only conversion — no target framework changes or functional refactors.

## Hard Constraints

- Do not change, add, remove, or upgrade TargetFramework/TargetFrameworks values — this conversion is format-only, not an upgrade
- Do not introduce new package versions unrelated to conversion — package drift causes subtle runtime issues
- Only convert the project format using the provided tools and fix build issues directly caused by the conversion

## Available Tools

- **Project ordering tool**: Use a tool capability to obtain the topological (dependency) order. Do not hand-compute and stop if unsuccessful
- **SDK style conversion tool**: Use the dedicated conversion tool for each project. Do not manually rewrite XML and stop if unsuccessful

## Workflow

### Execution

Use appropriate tools (not direct file reads) to gather project information. For each project in topological order, convert **one project at a time** — never invoke the conversion tool for multiple projects in parallel (the underlying MSBuild engine uses shared global state that is not safe for concurrent access):

1. Invoke the SDK style conversion tool and **wait for it to complete**
2. Build the converted project directly (not the solution) — solution-level builds introduce noise from unconverted downstream projects. If build fails, see "Common Issues" below. If warnings/errors exceed context window capacity, process them in chunks
3. If failures persist and cannot be resolved without violating constraints, mark Status = Blocked, record the blocker in the plan file, and stop — do not proceed past a blocked dependency since downstream projects depend on it
4. If the project does not build after fix attempts, stop and let the user resolve it
5. Verify the `packages.config` file is removed from the project
6. Commit or checkpoint changes after each successful project (atomic progression)

### Per-Project Checklist

```
- [ ] Used ordering tool output (not manual guess)
- [ ] Conversion tool executed (not a hand rewrite)
- [ ] No TargetFramework/TargetFrameworks modifications
- [ ] Project builds successfully
- [ ] Directly related tests pass
- [ ] Plan file status updated
- [ ] Minimal diff (only removed redundant legacy metadata now implicit in SDK style)
```

## Common Issues

### ItemGroup with removed items that shouldn't be included with globbing

The conversion tool adds a special label to ItemGroups tracking files excluded from globbing. After a successful build, check for this condition unless told to ignore it. If found, list the files for the user and get confirmation before removing them. If declined, leave as-is and continue.

### Missing packages

If the converted project is missing packages, identify and restore them. Keep all package versions identical — version changes are out of scope for format conversion.

### Property-indirected DLL references

The conversion engine detects `<Reference>` elements whose `<HintPath>` uses MSBuild property indirection (e.g., `$(NuGetPath_Foo)\lib\net472\Foo.dll`). It resolves the properties via the evaluated MSBuild project and converts matched references to `<PackageReference>`. References that use property indirection but cannot be resolved to a NuGet package layout are flagged with a warning for manual review — check the conversion output for these warnings and address them.

### Package consumption semantics

The conversion engine automatically preserves key package consumption semantics:

- **`developmentDependency="true"`** → emits `PrivateAssets="All"` (suppresses downstream propagation).
- **`<Private>false</Private>` on all package-backed references** → emits `ExcludeAssets="runtime"` (preserves "don't copy to output" behavior).
- **Mixed `<Private>` metadata** (some references Private=false, others true) → emits a structured warning without auto-applying attributes. Present the warning to the user.
- **Selective assembly inclusion** (project referenced fewer assemblies than the package provides) → emits a structured warning. Present the warning to the user.

**After running the conversion tool**, check the conversion output for warnings. Present any warnings to the user with the package name and recommended action. The engine surfaces these as log messages during conversion.

**Transitivity change (not auto-detected):** In `packages.config`, dependencies are not transitive — downstream projects do not automatically see a project's package dependencies. `PackageReference` makes all dependencies transitive by default. Inform the user about this behavioral change. If packages should remain private to the project, `PrivateAssets="All"` may be needed on those PackageReferences.

When flagging these cases, present the finding with the package name, the original metadata, and the recommended `PackageReference` attribute so the user can make an informed decision.

## Handling Blockers

When a project fails to build after reasonable, minimal fixes:

1. Revert any speculative edits unrelated to conversion
2. Capture error messages in the plan file's Notes column
3. Mark Status = Blocked and stop — escalate or request user input before proceeding to dependent projects
4. When uncertain, ask the user for guidance

## Success Criteria

- All projects converted from legacy to SDK-style format
- All projects build successfully with no target framework changes
- Plan file shows all projects as "Done" or has documented blockers
- All packages.config files removed from converted projects

Follow these instructions exactly. Ask for guidance if an action would require modifying target frameworks or performing broader upgrades.

