# How the dotnet‑upgrade Plugin Facilitates .NET Framework Migration

> Automate .NET Framework migration with the dotnet-upgrade plugin. It guides API replacements, project updates, and validation via markdown manifests, ensuring a smooth transition.

- Repository: [.NET Platform/skills](https://github.com/dotnet/skills)
- Tags: how-to-guide
- Published: 2026-07-06

---

**The dotnet‑upgrade plugin automates .NET Framework migration through modular skills defined in markdown manifests, guiding agents through systematic API replacements, project file updates, and validation checks with commit‑after‑each‑pattern workflows.**

The dotnet‑upgrade plugin in the `dotnet/skills` repository transforms complex .NET Framework migration into a repeatable, auditable process. By encapsulating migration logic into discrete skills—each defined by a [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md) file and executed by the Instagit runtime—the plugin enables both automated agents and developers to perform systematic upgrades with built‑in validation and rollback safety.

## Understanding the dotnet‑upgrade Plugin Architecture

The plugin follows a self‑contained architecture that separates declaration from execution. At its core, the system consists of four components that work together to deliver guided migrations.

**Plugin declaration** resides in [[`plugins/dotnet-upgrade/plugin.json`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-upgrade/plugin.json)](https://github.com/dotnet/skills/blob/main/plugins/dotnet-upgrade/plugin.json). This JSON file declares the plugin name and version, and points the Instagit runtime to the `./skills/` directory containing individual migration scenarios.

**Skill definitions** are markdown manifests named [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md) that reside in subfolders such as [`plugins/dotnet-upgrade/skills/thread-abort-migration/`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-upgrade/skills/thread-abort-migration/SKILL.md) or [`migrate-nullable-references/`](https://github.com/dotnet/skills/blob/main/plugins/dotnet-upgrade/skills/migrate-nullable-references/SKILL.md). Each manifest describes a specific migration scenario, listing required inputs, step‑by‑step workflows, validation checkpoints, and common pitfalls.

**Reference materials** provide authoritative documentation for APIs being migrated. For example, the Thread‑Abort skill links to the official breaking‑change documentation, while the nullable‑references skill includes local attribute tables in [`references/nullable-attributes.md`](https://github.com/dotnet/skills/blob/main/references/nullable-attributes.md).

**Testing assets** in the form of [`eval.vally.yaml`](https://github.com/dotnet/skills/blob/main/eval.vally.yaml) files allow the Skill‑Validator to execute the skill against sample codebases. These files live in [[`tests/dotnet-upgrade/thread-abort-migration/eval.vally.yaml`](https://github.com/dotnet/skills/blob/main/tests/dotnet-upgrade/thread-abort-migration/eval.vally.yaml)](https://github.com/dotnet/skills/blob/main/tests/dotnet-upgrade/thread-abort-migration/eval.vally.yaml) and verify that transformations produce expected results.

## How the Migration Workflow Works

The dotnet‑upgrade plugin operates through a standardized six‑phase workflow that ensures consistent, reviewable migrations from .NET Framework to modern .NET.

### Discovery and Registration

The Instagit runtime discovers the plugin via the [`plugin.json`](https://github.com/dotnet/skills/blob/main/plugin.json) entry point. Upon loading, the runtime registers each skill found in the `skills/` directory by parsing the `name:` header in the corresponding [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md) file.

### Input Handling and Validation

Each skill declares required inputs—such as project paths, target frameworks, and optional build commands—within its manifest. The runtime prompts users (or upstream orchestrators) for these values and validates them before execution begins.

### Step-by-Step Execution

The `Workflow` section of each [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md) parses into discrete, actionable steps. For the **Thread‑Abort migration** skill, for example, the workflow includes:

1. Inventorying all `Thread.Abort` related APIs
2. Classifying each usage pattern
3. Applying cooperative‑cancellation replacements
4. Cleaning up removed APIs
5. Verifying the migration through build and test execution

This systematic approach prevents “half‑migrated” code by ensuring each transformation completes before proceeding.

### Commit Strategy and Safety

Every skill implements a *commit‑after‑each‑pattern* policy. By committing after each logical change—such as converting a work‑loop to use `CancellationToken`—the migration remains bisectable. Reviewers can examine the exact impact of each transformation through the git history.

### Validation and Testing

The `Validation` checklist at the end of each skill ensures completeness: zero remaining `Thread.Abort` calls, no compile warnings, and passing tests. The accompanying [`eval.vally.yaml`](https://github.com/dotnet/skills/blob/main/eval.vally.yaml) files enable automated regression testing, allowing the Skill‑Validator to catch issues before they reach production codebases.

## Executing Migrations via Command Line

You invoke the dotnet‑upgrade plugin through the Instagit CLI, specifying the skill name and required parameters. The runtime loads the appropriate [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md), executes the workflow, and manages commits automatically.

Replace deprecated threading APIs using the thread‑abort skill:

```bash
instagit run dotnet-upgrade/thread-abort-migration \
      --project src/LegacyApp/LegacyApp.csproj \
      --target-framework net8.0

```

Enable nullable reference types across a library:

```bash
instagit run dotnet-upgrade/migrate-nullable-references \
      --project src/UtilityLib/UtilityLib.csproj \
      --strategy project-wide

```

Upgrade between modern .NET versions:

```bash
instagit run dotnet-upgrade/migrate-dotnet8-to-dotnet9 \
      --project src/ModernApp/ModernApp.csproj \
      --target-framework net9.0

```

Each command loads the skill definition, prompts for missing inputs, executes the step‑by‑step workflow with intermediate commits, and runs the built‑in validation checklist.

## Integrating the Plugin Programmatically

For custom orchestrators or CI pipelines, the Instagit SDK exposes a `SkillRunner` class that executes skills directly from C# code.

```csharp
using Instagit;

// Create a runner and point it at the dotnet‑upgrade plugin folder
var runner = new SkillRunner(@"../plugins/dotnet-upgrade");

// Execute the nullable‑reference skill
await runner.ExecuteAsync(
    skillName: "migrate-nullable-references",
    inputs: new Dictionary<string, string>
    {
        ["ProjectOrSolution"] = "src/UtilityLib/UtilityLib.csproj",
        ["Strategy"] = "project-wide"
    });

```

The SDK parses the [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md) file, performs the migration steps, and returns a `SkillResult` containing validation errors or success confirmation. This approach allows you to embed .NET Framework migration capabilities directly into existing automation tools.

## Summary

- The dotnet‑upgrade plugin uses modular **SKILL.md** manifests to define specific migration scenarios such as Thread‑Abort replacement and nullable reference enablement.
- **Instagit runtime** discovers skills via [`plugin.json`](https://github.com/dotnet/skills/blob/main/plugin.json) and executes workflows with automatic input validation and commit management.
- **Commit‑after‑each‑pattern** strategy ensures migrations remain bisectable and reviewable throughout the process.
- **Validation checkpoints** and [`eval.vally.yaml`](https://github.com/dotnet/skills/blob/main/eval.vally.yaml) test files guarantee that migrations complete successfully with no breaking changes remaining.
- The plugin supports both **CLI execution** via `instagit run` and **programmatic integration** through the `SkillRunner` SDK.

## Frequently Asked Questions

### What is the dotnet‑upgrade plugin?

The dotnet‑upgrade plugin is a collection of migration skills hosted in the `dotnet/skills` repository. It transforms .NET Framework migration from a manual, error‑prone process into an automated workflow by encapsulating best practices for API replacement, project file updates, and validation into executable markdown manifests.

### How does the plugin handle breaking changes during migration?

Each skill includes a detailed `Workflow` section that inventories deprecated APIs, classifies usage patterns, and applies specific replacements. For example, the thread‑abort‑migration skill replaces `Thread.Abort` calls with cooperative cancellation patterns using `CancellationToken`, while validation steps ensure no legacy calls remain before marking the migration complete.

### Can I extend the plugin with custom migration skills?

Yes. The architecture supports extensibility by design. Adding a new migration scenario requires creating a new folder in `plugins/dotnet-upgrade/skills/` containing a [`SKILL.md`](https://github.com/dotnet/skills/blob/main/SKILL.md) file that defines inputs, workflow steps, and validation rules. The Instagit runtime automatically discovers new skills from the `skills/` directory referenced in [`plugin.json`](https://github.com/dotnet/skills/blob/main/plugin.json).

### What validation does the plugin perform after migration?

Each skill defines a `Validation` checklist that typically includes verifying zero compiler warnings, ensuring no deprecated API calls remain, and confirming all unit tests pass. Additionally, [`eval.vally.yaml`](https://github.com/dotnet/skills/blob/main/eval.vally.yaml) files in the `tests/dotnet-upgrade/` directory provide automated test cases that the Skill‑Validator runs against sample repositories to detect regressions.