aspnet-core
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging,…
Safely refactors C#/.NET code without changing behavior. USE FOR any request to refactor, rename, move, extract, inline, merge, consolidate, deduplicate, split, or modernize C# code, including partial/generated declarations, wrappers, public APIs,
Claude Code
$ npx -y skills add managedcode/dotnet-skills --skill csharp-refactoring --agent claude-code
Codex
$ npx skills add managedcode/dotnet-skills --skill csharp-refactoring -a codex -y
Cursor
$ npx skills add managedcode/dotnet-skills --skill csharp-refactoring -a cursor -y
Gemini CLI
$ npx skills add managedcode/dotnet-skills --skill csharp-refactoring -a gemini-cli -y
GitHub Copilot
$ npx skills add managedcode/dotnet-skills --skill csharp-refactoring -a github-copilot -y
OpenCode
$ npx skills add managedcode/dotnet-skills --skill csharp-refactoring -a opencode -y
Windsurf
$ npx skills add managedcode/dotnet-skills --skill csharp-refactoring -a windsurf -y
name: csharp-refactoring description: "Safely refactors C#/.NET code without changing behavior. USE FOR any request to refactor, rename, move, extract, inline, merge, consolidate, deduplicate, split, or modernize C# code, even a small extract, inline, or rename, or merging near-identical types; green builds miss drift in #if branches, generated partials, and reflection/config names. When a changed member is visible outside the assembly (PublicAPI.*.txt, InternalsVisibleTo, shipped package), also invoke dotnet-breaking-changes; local/private renames do not need it. Also use when a request calls a feature, bug fix, package/framework upgrade, or public nullability change a refactor and the behavior-changing part must be separated or declined. DO NOT USE FOR ordinary feature or bug fixes not presented as refactoring; standalone upgrades after reclassification (use dotnet-upgrade); adding tests; or formatting-only work." license: MIT
A refactor changes **structure**, never observable **behavior**. Do the edit with binding-aware tools, then confirm behavior held with a build + the relevant tests. Keep the effort proportional to the change: a one-line local rename does not need the ceremony a public multi-targeted change does.
Read only enough repository context to classify **each requested operation**. Do this before restoring, building, or making an edit. Classification precedence is:
that structural work and defer only the behavior-changing or contract-changing operations. Do not invent or infer structural work to avoid the stop response.
response and state why they are inseparable.
behavior-preserving refactoring.
For a whole request that is outside behavior-preserving refactoring:
1. State: `Not a behavior-preserving refactor: <specific reason>.` 2. State: `No files changed.` 3. State: `Next workflow: <workflow>.` Then stop. Do not add manual implementation steps, alternatives, an offer to proceed without the workflow, or a follow-up question — even when that workflow is unavailable.
| Requested as a "refactor" | Classification and action | |---|---| | Framework or NuGet version change | **Upgrade.** Do not edit or validate the upgrade here; hand off to `dotnet-upgrade`. | | New capability, flag, endpoint, tier, or behavior | **Feature.** Do not implement it here; hand off to the repository's feature workflow. | | Threshold, rate, output, or bug-result change | **Behavior change.** Defer it and hand off to the repository's bug-fix or behavior-change workflow; still complete any clearly separable structural operation. | | Tighten or loosen a shipped/public nullable annotation | **Source-contract change.** Leave the declaration and API record unchanged; hand off to the `dotnet-breaking-changes` skill. |
For a mixed request, never stop after classification. Perform the separable structural operation, explicitly defer the behavior/contract change, and never state `No files changed.` after completing structural work. Never modify tests to make an unauthorized behavior change appear preserved.
Use the current agent workspace as the boundary. If it is a Git checkout, resolve its repository root (`git rev-parse --show-toplevel`) and stay inside it. If Git metadata is absent, treat the current working directory and its subdirectories as the boundary, and use a solution or project named in the request inside it; Git is not a prerequisite for a refactor. Resolve prompt-provided relative paths inside that boundary.
Search and edit only that workspace. Never use filesystem-wide search or select a similarly named clone, another worktree, build output, or unrelated temporary directory because a file also exists there. If a named path is absent, stop and report the mismatch instead of guessing another workspace. If a tool rejects an in-workspace path for a mechanical reason such as path form or unsupported tool root, retry through another in-workspace mechanism. If the rejection is a permission or policy denial, report it instead of working around it. Never search outside the boundary.
The #1 way a "rename" silently corrupts code is editing textual matches (comments, strings, unrelated overloads) instead of real **bindings**. Find every binding reference first, then edit semantically. Use the strongest tool available: an IDE/Roslyn workspace refactoring, then the C# LSP the [`dotnet` plugin declares](https://github.com/dotnet/skills/blob/main/plugins/dotnet/lsp.json) (`findReferences`, `goToDefinition`, `incomingCalls`, `rename` code action), then analyzer code-fixes / Roslynator, then compiler-validated edits (edit the true bindings, rebuild, let the compiler flag misses). Plain find/replace only when scope is provably tiny and every hit is verified. Include **every** `partial` declaration, and edit the generator input, never generated (`*.g.cs`) output.
For the operation → Roslyn-provider mapping and representative PRs, see [references/operation-catalog.md](references/operation-catalog.md).
When de-duplicating, preserve the ownership direction stated by the code or request. If `B` duplicates an implementation already owned by `A`, keep `A` canonical and make `B` delegate to it; do not invert the dependency merely because either direction compiles. Preserve public compatibility wrappers when the duplicate surface is shipped, and migrate only in-repo callers that are safe to move.
Use the first matching row instead of applyi
Stop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Build, debug, modernize, or review ASP.NET Core applications with correct hosting, middleware, security, configuration, logging,…
Build, upgrade, and operate Aspire 13.5.x C# or TypeScript application hosts with the current CLI, AppHost, ServiceDefaults,…
Build and debug Avalonia 11/12 .NET applications with XAML, compiled bindings, MVVM, custom controls, desktop lifetimes, and…
Build, review, or migrate Azure Functions in .NET with correct execution model, isolated worker setup, bindings, DI, and Durable…
Build and review Blazor applications across server, WebAssembly, web app, and hybrid scenarios with correct component design,…
Maintain or migrate EF6-based applications with realistic guidance on what to keep, what to modernize, and when EF Core is or is…
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
Ask which skill or flow fits your situation. A router over the skills in this repo.