You've probably used Claude or ChatGPT to help you write C# code. You paste in a class, ask it to add a method, copy the result back. That approach works but its not the most optimal.
There's times where it can suggest something that does not match the rest of the codebase, simply because it does not have the full context of the code.
The problem isn't the AI/LLM. The problem is that every conversation starts from zero. Claude/ChatGPT have no idea what your project looks like, what patterns you follow, or what you've already decided. You're giving it a piece of the puzzle and hoping it guesses the rest.
Claude Code fixes this, and in this article, I'll show you how to set it up on an existing .NET project.
What is Claude Code ?
Claude Code is Anthropic's CLI tool for using Claude directly in your terminal, inside your actual codebase. Instead of copying code back and forth in a chat window, Claude reads your files, makes changes, runs commands, and works alongside you in the repo.
The difference from chat isn't the interface, it's the context. Claude Code can see your entire codebase. It can read your files, check your dependencies, understand your folder structure, and make changes directly.
But that only matters if you tell it what to do with all that context.
That's where a CLAUDE.md file comes in.
Claude Code setup/
├── CLAUDE.md # Project context — read every session
├── .claude/
│ ├── commands/ # Slash commands — reusable .NET workflows
│ │ ├── scaffold-endpoint
│ │ ├── add-command
│ │ ├── add-query
│ │ ├── add-migration
│ │ ├── write-tests
│ │ └── add-service
│ └── agents/ # Personas — specialist modes on demand
│ ├── @code-reviewer
│ ├── @architect
│ ├── @test-writer
│ └── @doc-writer
└── integrations/ # MCP configs — external tool connections
├── github/
├── azure-devops/
├── jira/
└── slack/
The CLAUDE.md File
CLAUDE.md is a markdown file you place at the root of your repo. Claude Code reads it automatically at the start of every session. It's the document that tells Claude everything it needs to know to work effectively without you having to repeat yourself.
Think of it like onboarding a new developer. You wouldn't hand them a ticket and walk away. You'd tell them: here's the architecture, here's how we name things, here are the patterns we use, here's what we never do. CLAUDE.md is that conversation, written down once and reused forever.
Contents of a CLAUDE.md
A good CLAUDE.md for a .NET project covers:
Project identity — what the solution is called, where the .sln file lives,
what .NET version you're targeting, and one sentence describing what the system does.
Repository structure — the actual folder tree. Claude should not have to guess where your controllers live or whether you have separate Application and Infrastructure projects.
Architecture — the patterns in use and the rules that come with them. If you're using Clean Architecture, Claude needs to know the layer boundaries. If you're using CQRS with MediatR, it needs to know where Commands and Queries live. If you have a
simpler folder-based structure, it needs to know that too, and what each folder is responsible for.
Coding standards — your actual conventions. Nullable reference types on or off. Whether you use var freely or sparingly. Async method naming. Error handling approach.
The things that make a PR reviewer say "this doesn't look like our code."
Testing — which framework, which mock library, and what the naming convention is. Claude generates a lot of tests. They should look like your tests, not generic ones.
Behaviour rules — explicit "always do" and "never do" instructions. This is where you eliminate the most common AI frustrations. Things like:
- Never put business logic in a controller
- Always use ILogger, never Console.WriteLine
- Never add a NuGet package without flagging it first
- Always generate an EF Core migration when changing the schema
A real example
## Project Overview
**Project name:** SensorIngestApi
**Solution file:** SensorIngestApi.sln
**Target framework:** net8.0
**Description:** High-throughput sensor telemetry API — accepts readings via HTTP,
routes through a channels pipeline, detects anomalies, persists to TimescaleDB,
and streams real-time stats via SignalR.
## Repository Structure
SensorIngestApi/
Controllers/ # API controllers
Services/ # Background workers and core services
Interfaces/ # Service contracts
Models/ # Domain models
Data/ # EF Core DbContext
## Claude Behaviour for This Project
### Always do
- Use ILogger<T> with structured message templates — never Console.WriteLine
- Consider back-pressure on every change to the channel pipeline
- Use existing IThroughputStats, IAggregator, IAlertBus abstractions
### Never do
- Add NuGet packages without explaining why
- Change the database schema without generating an EF Core migration
- Use .Result or .Wait() on async operations
- Use Thread.Sleep — use Task.Delay with CancellationToken
MCP Integrations and Connecting Claude to Your Tools
MCP (Model Context Protocol) is how Claude Code connects to external tools. With the right MCP server configured, Claude can read your GitHub issues, check open PRs, look up Jira tickets, and search Slack threads, all without you leaving the terminal.
For most .NET projects, GitHub is the one to set up first. The config is straightforward:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
}
}
}
Drop this in your Claude Code settings and Claude can do things like:
Can you check if there's already a GitHub issue for the sensor timeout bug?
Commit and push this this implementation to the target branch
Other useful integrations for .NET teams: Azure DevOps (work items and pipelines), Jira (issues and sprints), and Slack (thread summaries).
Slash Commands — Reusable Workflows for .NET
Slash commands are reusable prompt templates stored as markdown files in .claude/commands/.
You invoke them with /command-name and Claude executes the instructions inside.
For .NET projects, the commands that save the most time are the ones you'd otherwise type from scratch every session. Here are a few that have become part of my workflow:
/scaffold-endpoint — scaffolds a Controller action with the right attributes, IMediator injection, CancellationToken, and ProducesResponseType declarations. One command instead of copying and adapting from an existing controller.
/add-command — generates all three files for a CQRS Command in one shot: the command record, the handler, and the FluentValidation validator. All in the right folder, all following the project's naming convention.
/write-tests — reads the actual class, identifies its constructor dependencies, and generates an NUnit + Moq test skeleton with the right mock setup and a baseline set of test scenarios. It won't write the test logic for you, but it eliminates the boilerplate that makes developers avoid writing tests in the first place.
These commands know your project's conventions, and combined with what is in your defined CLAUDE.md file, the generated code
looks like your code, not generic code.
Agent Personas — Modes for Different Tasks
Agent personas are a way to put Claude into a specific mode for a specific task. You activate one by mentioning it by name in your prompt.
The one I reach for most is @code-reviewer:
@code-reviewer review the changes in OrderController.cs
Rather than a generic review, it checks against the specific conventions in your CLAUDE.md like layer boundaries, naming, async patterns, error handling. It labels findings as [VIOLATION] (must fix) or [SUGGESTION] (worth considering) and ends with a clear verdict. It reads like a review from someone who actually knows the codebase.
Other useful personas for .NET work: @architect for design decisions and layer questions, @test-writer for generating full test coverage, and @doc-writer for XML comments, ADRs, and API documentation.
What a Session Actually Looks Like
Before — without proper setup
You: Can you create an Order controller for my .NET API?
Claude: [generates a controller with logic directly in the action methods,
no MediatR, no CancellationToken, wrong folder location,
inconsistent naming with the rest of the project]
You: No, we use MediatR. Here's how our handlers work...
Claude: [tries again, still puts business logic in the wrong place]
You: [spends 10 minutes fixing and reorganising what was generated]
After — with CLAUDE.md, commands, and MCP configured
You: /scaffold-endpoint Order POST api/orders
Claude: [reads CLAUDE.md, generates a thin Controller with IMediator
injection, correct ProducesResponseType attributes,
CancellationToken, points to /api-add-command as next step]
You: /add-command CreateOrder
Claude: [generates CreateOrderCommand record, CreateOrderCommandHandler,
and CreateOrderCommandValidator — all in the correct
Application/Commands/CreateOrder/ folder, following the
project's naming conventions]
You: @code-reviewer review the three new files
Claude: [checks against CLAUDE.md conventions, flags one missing
null check on the command property, approves everything else,
returns verdict: APPROVED WITH SUGGESTIONS]
Getting Started
Setting this up properly takes about an hour on a project you already know well.
The rough steps:
- Install Claude Code:
npm install -g @anthropic-ai/claude-code - Create
CLAUDE.mdat your repo root and start with Project Overview, Repository Structure, and the Behaviour Rules sections. Those three alone make a noticeable difference. - Add a GitHub MCP config so Claude can see your issues and PRs
- Open Claude Code in your repo from the terminal by running
claude
The more honest you are in CLAUDE.md about how the project actually works, the better Claude performs. A CLAUDE.md that says "we use Clean Architecture" when the project is actually a flat folder structure will cause more confusion than no CLAUDE.md at all.
Closing
Claude Code is genuinely useful for .NET development. But like most tools, the difference between this is okay and this has changed how I work is in the setup.
CLAUDE.md is the foundation. Everything else like commands, personas, integrations just build on top of it. Get that right first and every other thing will be seamless.
Happy coding!!!



Top comments (0)