Skip to main content
Article complete

Get one like this every Tuesday at 7 PM IST.

codewithmukesh
Back to blog
claude 16 min read Lesson 13/29 New

How I Use dotnet-claude-kit: Making Claude Code Write Senior-Level .NET

Install and use dotnet-claude-kit: 47 skills, 10 agents, 16 commands, and 20 Roslyn MCP tools that make Claude Code write production-ready .NET 10 code.

Install and use dotnet-claude-kit: 47 skills, 10 agents, 16 commands, and 20 Roslyn MCP tools that make Claude Code write production-ready .NET 10 code.

claude

claude-code dotnet-claude-kit claude-code-plugin ai-coding-assistant dotnet-10 csharp-14 aspnet-core roslyn mcp-server minimal-api ef-core vertical-slice-architecture clean-architecture code-review scaffolding testcontainers claude-md developer-productivity ai-workflow open-source

Mukesh Murugan
Mukesh Murugan
Solutions Architect · Microsoft MVP
Chapter 13 of 29
View course

Claude Code for .NET Developers

From dotnet new to docker push - REST, EF Core 10, auth, caching, Clean Architecture, observability. 29 hands-on lessons, source on GitHub.

dotnet-claude-kit is a free, MIT-licensed Claude Code plugin that makes Claude write .NET 10 code the way a senior engineer would: 47 skills, 10 specialist agents, 16 slash commands, and 20 Roslyn-powered MCP tools. You install it with two commands and one dotnet tool. This guide shows exactly how I use it day to day.

I built this kit, so this is not a neutral review. It is the opposite: a tour from the person who made every design decision in it, including the ones I got wrong the first time. I will show you what Claude Code gets wrong on .NET out of the box, how the kit fixes each failure, and which parts I would adopt first if I were starting today.

Everything here is on GitHub at codewithmukesh/dotnet-claude-kit, and the .NET Claude Kit resource page tracks every release. Current version as I write this: v0.11.0.

Let’s get into it.

Read next

Claude Code for Beginners

New to Claude Code itself? Start with the terminal basics, then come back here to specialize it for .NET.

Why Does Claude Code Write Bad .NET Code Out of the Box?

Claude Code is a general-purpose coding agent. It has no opinion about your architecture, your conventions, or your token budget until you give it one. On .NET projects, that shows up as four specific failures I kept hitting in my own sessions.

1. Legacy patterns from training data. Ask vanilla Claude for an order service and you get DateTime.Now instead of TimeProvider, new HttpClient() instead of IHttpClientFactory, and a repository interface wrapped around EF Core for no reason. None of it is wrong enough to fail review loudly. All of it is the kind of code you spend the next hour correcting.

2. Architecture roulette. Tell Claude to “set up a new API” and it picks an architecture for you, usually a generic Clean Architecture layout, without asking a single question about your domain complexity, team size, or how long the project needs to live. A CRUD-heavy internal tool and a rich-domain payment system get the same folder structure.

3. Token bonfires. Claude explores a codebase by reading files. A single .cs file costs roughly 500 to 2,000 tokens, and answering “who calls this method” means opening a lot of them. The compiler already knows the answer. Claude just has no way to ask it.

4. No quality gates. Out of the box there is no verification loop. Claude writes code, tells you it is done, and the first honest feedback comes from your build server or your reviewer.

Each of these is fixable with enough prompting per session. I got tired of re-typing the fixes, so I packaged them.

What Is dotnet-claude-kit?

dotnet-claude-kit is a knowledge and action layer that sits between Claude Code and your .NET project. The knowledge layer teaches Claude current .NET 10 and C# 14 patterns through 47 skills. The action layer enforces those patterns through 16 slash commands, 10 specialist agents, and a 20-tool Roslyn MCP server.

That two-layer split is the core design decision. Knowledge alone is not enough: Claude can know that DateTime.Now is wrong and still generate it under pressure. So the kit pairs every convention with something that actively applies or checks it:

LayerWhat shipsWhat it does
Knowledge31 reference skillsTeach patterns: minimal APIs, EF Core, resilience, caching, testing, observability
Workflow16 slash-command skillsOrchestrate: init, spec, plan, scaffold, verify, review, migrate, clean up
Agents10 specialistsRoute work: architect, API designer, EF Core specialist, security auditor, and more
Analysis20 Roslyn MCP toolsQuery the compiler instead of reading files
Guardrails10 rules + 3 hooksAlways-on conventions, auto-format on edit, destructive-command guard
Templates5 CLAUDE.md startersWeb API, modular monolith, Blazor, worker service, class library

Every skill is capped at 400 lines with BAD/GOOD comparisons and a decision guide. When I audited the full skill set with token estimates in March 2026, all 47 skills at the time weighed in around 92,000 tokens combined, and the highest-value ones were consistently those covering post-training-data APIs: .NET 10’s built-in OpenAPI, Polly v8, HybridCache, Wolverine. That audit shaped the kit’s rule of thumb: a skill earns its tokens when it covers what Claude’s training data does not.

Read next

Skills in Claude Code

How the skill system works under the hood: SKILL.md files, triggers, and on-demand loading.

How Do You Install dotnet-claude-kit?

Installation is three steps and takes about two minutes. You need the .NET 10 SDK, Claude Code, and optionally Docker if you want the Testcontainers-based integration testing workflow. Node.js only matters if you add npx-based MCP servers on top; the kit’s own server is a dotnet tool.

First, install the Roslyn MCP server as a global tool from your terminal:

Terminal window
dotnet tool install -g CWM.RoslynNavigator

Then, inside a Claude Code session, add the marketplace and install the plugin:

/plugin marketplace add codewithmukesh/dotnet-claude-kit
/plugin install dotnet-claude-kit

That is the whole install. All 47 skills, 10 agents, hooks, and the MCP configuration activate globally through the Claude Code plugin system. The 10 rules ship in the repo for you to copy into your project’s .claude/rules/ folder when you want them always-loaded.

On macOS or Linux, if the MCP server fails with “No .NET SDKs were found”, set DOTNET_ROOT to your .NET installation root, for example /usr/local/share/dotnet. That is the single most common install issue people report.

Read next

Anatomy of the .claude Folder

Where plugins, rules, settings, and MCP config live in a project, and how Claude Code loads each one.

How Do You Update dotnet-claude-kit?

The kit is two moving parts that version independently: the Claude Code plugin (skills, agents, commands, hooks, rules) and the Roslyn MCP server (the dotnet tool). A plugin release may or may not bump the MCP server, so when you update, run both.

Update the plugin. Refresh the marketplace so it pulls the newest release from GitHub, then reload:

/plugin marketplace update dotnet-claude-kit
/reload-plugins

/reload-plugins activates the new version without restarting Claude Code; a full restart works too. If you would rather not do this by hand, open /plugin, go to the Marketplaces tab, select dotnet-claude-kit, and turn on Enable auto-update. Third-party marketplaces ship with auto-update off by default, so this is opt-in. Once on, Claude Code refreshes the plugin in the background after startup and prompts you to reload.

Update the Roslyn MCP server. This is a standard global tool update:

Terminal window
dotnet tool update -g CWM.RoslynNavigator

To confirm where you landed, check the MCP server with cwm-roslyn-navigator --version and the plugin version in the /plugin Installed tab. If a new tool or command from the changelog is not showing up, you almost always just need the piece you forgot: reload the plugin for skills and commands, update the dotnet tool for new MCP tools.

What Happens in Your First Session?

Once the plugin is installed, go to your project and run one command:

/dotnet-init

On an existing project, /dotnet-init reads the codebase before it asks you anything. It finds your .slnx or .sln, scans each .csproj to infer the project type from its SDK (Microsoft.NET.Sdk.Web means a Web API or Blazor app, Microsoft.NET.Sdk.Worker a worker service, inter-module references a modular monolith), and picks up your tech stack from configuration: PostgreSQL or SQL Server from the connection string, JWT or OIDC from appsettings. It then runs the convention-learner over your code so the questionnaire is informed by patterns you already follow, not a blank slate. The CLAUDE.md it generates describes the project you actually have, which is the whole point: a generic template teaches Claude nothing your code has not already decided.

On an empty folder, it flips into greenfield mode: it asks what you are building, scaffolds the full solution structure with dotnet new sln, projects, Directory.Build.props, and src/ plus tests/ folders, then writes the CLAUDE.md to match.

If you already have a CLAUDE.md, /dotnet-init will not clobber it. It detects the existing file, reads it, and stops to ask how to proceed:

  • Merge (the recommended path) keeps your hand-written sections (deployment notes, team conventions, domain rules) and refreshes only the kit’s architecture, tech-stack, and convention sections in place.
  • Overwrite replaces the file entirely with the freshly generated one.
  • Keep leaves your file untouched and just prints the generated content so you can copy across whatever you want by hand.

Merge and overwrite both back the original up to CLAUDE.md.bak first, so nothing you wrote is ever lost. On a codebase you have already tuned by hand, merge is the safe default: you get the kit’s current .NET 10 conventions without giving up the project knowledge only you know.

The architecture questions are the part I refuse to compromise on. The kit’s advisor asks about domain complexity, team size, and project lifetime before recommending Vertical Slice, Clean Architecture, DDD, or Modular Monolith. The default answer to “which architecture?” is a question, not a template. That single rule kills the architecture-roulette problem: an AI that recommends Clean Architecture for everything is just autocomplete with confidence.

After init, I always run one more command to see where the project actually stands:

/health-check

This produces a graded report card, A through F, across build health, code quality, architecture, test coverage, dead code, API surface, security posture, and documentation. It is driven by the MCP tools, so it checks facts from the compiler rather than vibes: detect_antipatterns for code smells, get_project_graph plus detect_circular_dependencies for architecture, get_test_coverage_map for coverage, find_dead_code for the stuff nobody deleted. On a brownfield project this is the fastest honest answer you will get to “how bad is it?”

Read next

CLAUDE.md Mastery for .NET Developers

What belongs in a CLAUDE.md, what does not, and how to keep it from rotting.

What Does the Everyday Feature Workflow Look Like?

My daily loop with the kit is four commands: /spec, /plan, /scaffold, /verify. Each one exists because skipping it cost me real time at some point.

Step 1: /spec - agree before you build

/spec runs a questioning loop until the human and the AI agree on a written spec, persisted to docs/specs/. It is deliberately annoying. It keeps asking until edge cases, validation rules, and failure behavior are pinned down. The output feeds /plan and /tdd, which means the expensive ambiguity gets resolved in text, before any code exists.

Step 2: /plan - architecture-aware planning

/plan consumes the approved spec and produces an implementation plan filtered through your declared architecture. A plan for a Vertical Slice project proposes feature folders; the same request in a Modular Monolith proposes module-local changes and integration events. Plan mode is the highest-ROI habit in all of Claude Code, and the kit just makes it .NET-aware.

Read next

Plan Mode in Claude Code

Why planning before writing code is the single biggest quality lever, and how to use plan mode well.

Step 3: /scaffold - the complete feature, not the happy path

This is where the before/after difference is most visible. Ask vanilla Claude for a create-order feature and you typically get something like this:

// Vanilla Claude Code output
public class OrderService
{
private readonly IOrderRepository _repo; // abstraction over EF Core for no reason
public async Task<Order> CreateOrder(CreateOrderDto dto)
{
var order = new Order();
order.CreatedAt = DateTime.Now; // not testable, wrong offset handling
order.Items = dto.Items.ToList();
await _repo.AddAsync(order);
return order; // leaks the domain entity to the API
}
}

With the kit installed, /scaffold generates the feature against a 9-point checklist: endpoint, handler, DTOs, EF configuration, Result pattern, FluentValidation wired through an endpoint filter, OpenAPI metadata, CancellationToken on every async path, and integration tests. Supporting infrastructure like bounded pagination gets scaffolded once if it is missing. The same feature comes out like this:

// dotnet-claude-kit output
public static class CreateOrder
{
public record Command(string CustomerId, List<OrderItemDto> Items) : IRequest<Result<Response>>;
public record Response(Guid Id, decimal Total, DateTimeOffset CreatedAt);
internal sealed class Handler(AppDbContext db, TimeProvider clock)
: IRequestHandler<Command, Result<Response>>
{
public async Task<Result<Response>> Handle(Command request, CancellationToken ct)
{
var order = Order.Create(request.CustomerId, request.Items, clock.GetUtcNow());
db.Orders.Add(order);
await db.SaveChangesAsync(ct);
return Result.Success(new Response(order.Id, order.Total, order.CreatedAt));
}
}
}
// Endpoint auto-discovered via IEndpointGroup - Program.cs never changes
public sealed class OrderEndpoints : IEndpointGroup
{
public void Map(IEndpointRouteBuilder app)
{
var group = app.MapGroup("/api/orders").WithTags("Orders");
group.MapPost("/", CreateOrderHandler)
.WithName("CreateOrder").Produces<CreateOrder.Response>(201)
.ProducesValidationProblem()
.AddEndpointFilter<ValidationFilter<CreateOrder.Command>>();
}
}

Every pattern in that output is a deliberate decision documented in the kit’s ADRs. Result over exceptions, because exceptions are for exceptional cases. Direct DbContext over a repository wrapper, because EF Core already is the repository. TimeProvider over DateTime.Now, because time you cannot fake is time you cannot test. Sealed handlers, primary constructors, records: modern C# 14, not 2019-era C#.

Step 4: /verify - the quality gate

/verify runs a 7-phase pipeline: build, analyzers, anti-pattern scan, tests, security check, formatting, and a diff review against the base branch. Each phase reports PASS or FAIL with actionable output, and the pipeline short-circuits on critical failures. I run it before every commit that matters. It is the difference between “Claude says it is done” and “the toolchain agrees”.

The anti-pattern phase alone catches the classics: async void, sync-over-async, new HttpClient(), DateTime.Now, broad catch blocks, string interpolation in log templates, missing CancellationToken, and EF queries without AsNoTracking.

Read next

My Claude Code Prompts for .NET Work

The copy-paste prompts I use for everyday .NET tasks, which pair well with the kit's commands.

How Does the Roslyn MCP Server Save Tokens?

The CWM.RoslynNavigator MCP server lets Claude query the C# compiler instead of reading source files. A semantic query costs 30 to 150 tokens; reading the file it replaces costs 500 to 2,000. Across a session of codebase exploration, that is roughly a 10x reduction, and in my own measurements typically 60 to 80% fewer tokens overall.

Roslyn is the compiler platform behind C#. It already holds a complete semantic model of your solution: every type, every reference, every call chain. The Model Context Protocol makes that model callable as tools. The kit ships 20 of them, and every response is bounded: list results are capped and report the total found, and source reads are truncated at a character limit, so no single call can blow up your context window.

The six I use constantly:

ToolQuestion it answersWhat it replaces
find_symbolWhere is this type or method defined?Grep across every .cs file
find_referencesWho uses this symbol?Grep plus manually opening files
get_file_outlineWhat is in this file?Reading the file to find out
get_symbol_sourceShow me this ONE method bodyReading the whole file for one method
get_endpoint_mapEvery route with its auth postureGrepping Map* calls and controllers
get_di_registrationsEvery registration, lifetime, and captive-dependency riskReading Program.cs and all extensions

get_endpoint_map deserves a special mention. It inventories every route in the solution and labels each one authorized, anonymous, or unmarked in a single token-cheap call. The /security-scan command starts every auth audit there, because an unmarked endpoint is a finding by itself.

The server starts automatically through the plugin’s MCP configuration. There is nothing to run manually; it discovers your .sln or .slnx and loads the solution on first use.

Read next

Advanced Claude Code Tips

The workflow habits that pair with the MCP server: context discipline, subagents, and parallel sessions.

Which Commands Keep the Codebase Healthy?

Beyond the feature loop, five commands cover the maintenance work that usually gets skipped:

  1. /code-review - MCP-powered review that prioritizes by blast radius: data access, security, concurrency, and integration boundaries get reviewed before style nits. The code-reviewer agent behind it is tool-enforced read-only, so it can never “fix” things mid-review, and it carries project memory, so it learns your conventions across sessions instead of rediscovering them.
  2. /build-fix - a bounded autonomous loop: parse compiler errors, categorize, apply known fix patterns, rebuild, repeat until green or the iteration cap hits (5 by default, hard cap of 10). Bounded is the important word. An unbounded fix loop on a confused model is how you turn 3 errors into 40.
  3. /de-sloppify - the systematic cleanup pass nobody volunteers for: formatting, unused usings, analyzer warnings, dead code removal, sealing classes, CancellationToken propagation. Seven ordered steps, tests between phases, and the refactor-cleaner agent behind it works in an isolated git worktree so a bad cleanup never touches your branch.
  4. /outdated - dependency health with a twist: alongside stale packages and CVEs, it flags commercial-license traps. MediatR 13+, MassTransit 9+, FluentAssertions 8+, and AutoMapper 15+ all changed licensing terms, and an innocent update-all can change your legal position before your code.
  5. /arch-check - verifies the code still matches its declared architecture: dependency direction, layer violations, module leaks, and cycles, reported with file and line evidence. Architectures do not fail in one commit; they erode over fifty. This is the erosion detector.

My Take: What Should You Adopt First?

If you take one thing from the kit, take the Roslyn MCP server. If you take two, add /dotnet-init. Everything else compounds from there. Token-efficient exploration changes what Claude can do on a real codebase, and a generated, accurate CLAUDE.md changes the quality of everything Claude writes afterward.

Here is how I would sequence adoption depending on where you are:

Your situationStart withThen addSkip for now
Solo dev, greenfield API/dotnet-init + /scaffold/verify before commitsInstinct system, /wrap-up
Team, existing codebaseMCP server + /health-check/code-review, /arch-check in PR flowGreenfield scaffolding
Inherited legacy solutionMCP server + /health-check/de-sloppify, /outdated/spec until the fires are out
Evaluating Claude Code itselfPlugin install + one /scaffoldThe full spec-plan-verify loopRules and hooks customization
Read next

Building a .NET Architecture Skill for Claude Code

How I built the kit's first scaffolding skill, and what designing a skill teaches you about Claude's failure modes.

And the honest part, because a kit built by me deserves harder scrutiny than a kit built by a stranger. What it will not do:

  • It will not replace judgment. The architecture advisor recommends; you decide. If you accept every recommendation without reading the rationale, you have automated your thinking, not improved it.
  • It is opinionated, and you may disagree. Result pattern over exceptions and no-repository-over-EF-Core are documented positions with ADRs, not universal truths. If your team standard differs, edit the rules; they are markdown files, not a framework.
  • The first MCP load on a huge solution is not instant. The server builds a full semantic model. On a 50-project solution, expect a short wait on first query while it loads, then fast responses after.
  • Skills cost tokens too. The knowledge layer is on-demand, but it is not free. That is exactly why the March audit exists and why every skill fights for its line count.

Key Takeaways

  • Claude Code fails on .NET in four repeatable ways: legacy patterns, architecture roulette, token-expensive file reading, and no quality gates. dotnet-claude-kit packages a fix for each.
  • Install is two commands plus one dotnet tool; /dotnet-init then generates a project-specific CLAUDE.md for existing or greenfield projects.
  • The everyday loop is /spec, /plan, /scaffold, /verify: agree, plan, generate against a 9-point checklist, then gate with a 7-phase pipeline.
  • The Roslyn MCP server is the highest-value single piece: 30-150 tokens per semantic query versus 500-2,000 per file read, roughly 10x cheaper exploration.
  • The kit is opinionated on purpose. Every default has an ADR explaining why, and every rule is editable markdown.

Frequently Asked Questions

What is dotnet-claude-kit?

dotnet-claude-kit is a free, open-source Claude Code plugin that makes Claude write modern .NET 10 and C# 14 code. It ships 47 skills, 10 specialist agents, 16 slash commands, 10 rules, 5 project templates, and a 20-tool Roslyn MCP server for token-efficient codebase analysis.

Is dotnet-claude-kit free?

Yes. The entire kit is MIT-licensed and free, including the CWM.RoslynNavigator MCP server. There is no paid tier, no signup, and no telemetry.

How do I install dotnet-claude-kit?

Install the MCP server with dotnet tool install -g CWM.RoslynNavigator, then inside Claude Code run /plugin marketplace add codewithmukesh/dotnet-claude-kit followed by /plugin install dotnet-claude-kit. Finally run /dotnet-init in your project to generate a customized CLAUDE.md.

Does dotnet-claude-kit work on existing brownfield projects?

Yes. /dotnet-init detects your solution, scans project SDKs, reads your tech stack, and generates a CLAUDE.md that matches what already exists. The /health-check command then grades the codebase across eight dimensions so you know exactly where it stands.

Do I need the Roslyn MCP server for the kit to work?

No, the skills, agents, commands, and rules work without it. But the MCP server is the highest-value piece: it lets Claude query the compiler for 30 to 150 tokens instead of reading whole files for 500 to 2,000 tokens, which is what makes the kit practical on large solutions.

Which architectures does dotnet-claude-kit support?

Four: Vertical Slice Architecture, Clean Architecture, Domain-Driven Design, and Modular Monolith. The architecture advisor asks about your domain complexity, team size, and project lifetime before recommending one, and /scaffold generates features correctly for whichever you choose.

Does dotnet-claude-kit work with Cursor or other AI coding tools?

Partially. The repo ships compatibility configs for Cursor, Codex CLI, and OpenCode, including consolidated rules and the Roslyn MCP server registration. The full experience with skills, agents, hooks, and slash commands is Claude Code only.

How is this different from writing my own CLAUDE.md?

A CLAUDE.md holds static instructions. The kit adds an action layer on top: slash commands that orchestrate workflows, agents that route work to specialists, hooks that format and guard automatically, and MCP tools that query the compiler. Instructions tell Claude what good looks like; the action layer enforces it.

Troubleshooting

MCP tools are not available. Verify the install with cwm-roslyn-navigator --version, and confirm a .sln or .slnx file exists; the server discovers it by searching up to 3 directory levels. On macOS/Linux, set DOTNET_ROOT if you see “No .NET SDKs were found”.

Slash commands do not show up. Run /plugin inside Claude Code and confirm dotnet-claude-kit is installed and enabled. If you loaded it with --plugin-dir for local testing, remember that flag only applies to that session.

First MCP query returns a loading status. Normal on large solutions. The server builds the full semantic model on first use; give it a moment and query again.

/build-fix hits the iteration limit. Check whether errors are decreasing each round. If not, look for circular dependencies with detect_circular_dependencies and confirm packages restore cleanly; some architecture-level errors need a human.

Testcontainers tests fail. Confirm Docker is running with docker info and has enough memory allocated. Integration tests in the kit’s testing workflow use real databases via Testcontainers, so Docker is a hard requirement for that part.

Summary

Claude Code out of the box is a strong generalist that writes mediocre .NET. dotnet-claude-kit turns it into a specialist: current C# 14 patterns from the knowledge skills, enforced quality from the command pipeline, and compiler-accurate codebase answers from the Roslyn MCP server, all installed in about two minutes.

Start small. Install the plugin, run /dotnet-init, and run /health-check on a project you know well. If the report card tells you things about your own codebase you did not know, the rest of the kit will earn its place quickly.

The kit is MIT-licensed and open to contributions: github.com/codewithmukesh/dotnet-claude-kit. If something generates code you disagree with, open an issue and tell me why. The ADRs exist to be argued with.

Happy Coding :)

Source code Open on GitHub

Grab the source code.

Get the full implementation. Drop your email for instant access, or skip straight to GitHub.

Skip - go straight to GitHub
View all articles

What's your take?

Push back, share a war story, or ask the obvious question someone else is wondering. I read every comment.

View on GitHub

Weekly .NET tips · free

Newsletter

stay ahead in .NET

One email every Tuesday at 7 PM IST. One topic, deep. The week's articles. No filler.

Tutorials Architecture DevOps AI
Join 9,735 developers · Delivered every Tuesday
Privacy notice 30s read

Cookies, but only the useful ones.

I use cookies to understand which articles get read and which CTAs actually work. No third-party advertising trackers, ever. Read the privacy policy →