Configuring Claude Code for .NET: Settings, Hooks, MCP, and Cloud Agents
Out of the box, Claude Code asks permission for every dotnet build, every file edit, and every git diff. That is the right default for a new user. It is not the right default for a .NET team running a 15-project migration. This guide covers the six configuration files that turn Claude Code into a reliable partner for .NET development, with the full command catalogue, copy-pasteable hooks, and a worked cloud-agents setup.
- Pre-approved permissions are the single highest-leverage configuration step. Eliminate prompt fatigue without giving up safety.
- Hooks give you automated
dotnet formatanddotnet buildafter every file edit, without asking. - AGENTS.md is portable across tools. CLAUDE.md is Claude Code-specific. Invest in both.
- MCP servers bring your work tracker, Azure, and SQL Server schema into the agent’s context.
- Cloud agents let one developer supervise parallel migrations, or kick off analysis from a phone.
The six files that make Claude Code know your .NET stack
Claude Code reads configuration from six locations. Understanding which file does what job prevents duplication and ensures the team shares the right things.
~/
└── .claude/
├── settings.json # Your personal defaults, all projects
└── CLAUDE.md # Your personal instructions, all projects
your-solution/
├── AGENTS.md # Portable instructions (Cursor, Claude Code, any agent)
├── CLAUDE.md # Claude Code-specific instructions for this project
├── .claude/
│ ├── settings.json # Team-shared settings (commit this)
│ ├── settings.local.json # Your personal overrides (gitignored automatically)
│ ├── hooks/ # Hook scripts referenced by settings.json
│ ├── skills/ # Project-level skills
│ └── agents/ # Project-level subagent definitions
└── .mcp.json # MCP server registry (commit this)
| File | Scope | Commit? | Purpose |
|---|---|---|---|
~/.claude/settings.json | All your projects | Not applicable | Personal defaults, global deny rules |
~/.claude/CLAUDE.md | All your projects | Not applicable | Your personal preferences and global instructions |
CLAUDE.md (repo root) | This project, Claude Code | Yes | Project conventions, architecture, doc references |
AGENTS.md (repo root) | This project, all agents | Yes | Portable instructions that work in Cursor, Claude Code, and future tools |
.claude/settings.json | This project, whole team | Yes | Permissions, hooks, env vars, MCP approvals |
.claude/settings.local.json | You, this project only | No | Personal experiments, machine-specific paths |
.mcp.json | This project, whole team | Yes | MCP server registry |
AGENTS.md versus CLAUDE.md
The distinction matters. AGENTS.md is the portable instruction surface defined by the Agent Skills open standard. It works in Cursor, Claude Code, and any other agent that follows the standard. CLAUDE.md is Claude Code-specific and loaded only when Claude Code runs.
Put your target framework, coding conventions, forbidden APIs, and architectural rules in AGENTS.md. Claude Code reads it alongside CLAUDE.md. Put Claude Code-specific workflow instructions (session patterns, /compact triggers, skill invocation reminders) in CLAUDE.md.
Keep CLAUDE.md under 300 lines. Claude Code wraps it in a system reminder at the start of each session. As instruction count grows, the model starts applying all instructions less reliably. Style rules belong in .editorconfig and Directory.Build.props, not CLAUDE.md. Claude Code is an in-context learner: if your codebase follows a pattern, it picks it up from reading your files.
For a worked AGENTS.md and CLAUDE.md example for a .NET 10 project, see the Claude Code for .NET developers guide.
Pre-approved permissions: the highest-leverage configuration
By default, Claude Code prompts for permission before every Bash command and every file edit. On a single-file task that is fine. On a 200-file migration that is hundreds of prompts, it breaks the agent’s flow and trains developers to mash yes without reading.
Pre-approving safe and frequent commands eliminates prompt fatigue without giving up control of dangerous ones.
How allow, ask, and deny work
The permissions object in settings.json contains three lists:
allow: the command runs silently, no prompt.ask: the default for anything not in allow or deny. Claude Code prompts and waits.deny: the command is blocked, the agent is told why, and it cannot proceed.
deny always wins. A command in both allow and deny is denied. This is true across all configuration scopes: a deny in the team-shared .claude/settings.json cannot be overridden by an allow in ~/.claude/settings.json.
You can also cycle permission modes at any time with Shift+Tab: normal (ask for everything), acceptEdits (auto-accept file edits, ask for Bash), plan (read-only, no edits or commands), and auto (the agent decides based on a built-in classifier plus your autoMode rules).
Pass --permission-mode auto to start in auto mode for a long unattended session. Do not use --dangerously-skip-permissions in any project that touches client code or production configuration: it bypasses all permission checks including deny rules.
The .NET command catalogue
Below is the full .claude/settings.json for a .NET team, with every command group annotated. Copy the whole file, remove the comments (JSON does not support them), and adjust to your project.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
// Build, test, format (always safe, run frequently)
"Bash(dotnet build*)",
"Bash(dotnet test*)",
"Bash(dotnet format*)",
"Bash(dotnet restore*)",
"Bash(dotnet watch test*)",
"Bash(dotnet vstest*)",
"Bash(dotnet clean*)",
// EF Core: migrations and scripts are safe; database update only for dev
"Bash(dotnet ef migrations*)",
"Bash(dotnet ef database update*)",
"Bash(dotnet ef dbcontext*)",
"Bash(dotnet ef database update --connection*)",
// Tooling: upgrade-assistant, dotnet-ef, user-secrets read
"Bash(dotnet tool*)",
"Bash(upgrade-assistant*)",
"Bash(dotnet user-secrets list*)",
"Bash(dotnet user-secrets set*)",
// Git: read-only operations are always safe
"Bash(git status)",
"Bash(git diff*)",
"Bash(git log*)",
"Bash(git show*)",
"Bash(git branch*)",
"Bash(git remote*)",
"Bash(git stash list*)",
// NuGet: read-only inspection
"Bash(dotnet list package*)",
"Bash(dotnet list reference*)",
"Bash(dotnet nuget list source*)",
// Solution inspection
"Bash(dotnet sln list*)",
// File reads (deny list below takes precedence)
"Read(**/*)"
],
"ask": [
// Solution and project changes: ask because they modify project structure
"Bash(dotnet sln*)",
"Bash(dotnet new*)",
"Bash(dotnet add package*)",
"Bash(dotnet remove package*)",
"Bash(dotnet add reference*)",
// Publish and pack: produces artefacts that may be shipped
"Bash(dotnet publish*)",
"Bash(dotnet pack*)",
// Git writes: ask before any commit, push, or rebase
"Bash(git commit*)",
"Bash(git push*)",
"Bash(git rebase*)",
"Bash(git merge*)",
"Bash(git cherry-pick*)",
// EF Core drop: ask, do not auto-allow even for dev
"Bash(dotnet ef database drop*)",
// NuGet cache management
"Bash(dotnet nuget locals*)"
],
"deny": [
// Destructive file operations
"Bash(rm -rf bin*)",
"Bash(rm -rf obj*)",
"Bash(rm -rf .git*)",
"Bash(rm -rf src*)",
"Bash(rm -rf **/bin*)",
"Bash(rm -rf **/obj*)",
// Network tools (force IHttpClientFactory discipline in .NET code;
// the agent should not use curl to reach external APIs during development)
"Bash(curl*)",
"Bash(wget*)",
"Bash(Invoke-WebRequest*)",
"Bash(Invoke-RestMethod*)",
// NuGet source changes (prevents silent feed swaps)
"Bash(dotnet nuget add source*)",
"Bash(dotnet nuget remove source*)",
"Bash(dotnet nuget update source*)",
// Destructive EF Core (never allow without explicit human review)
"Bash(dotnet ef database drop --force*)",
// Destructive git (force-push and hard reset must be deliberate)
"Bash(git push --force*)",
"Bash(git push -f *)",
"Bash(git reset --hard*)",
"Bash(git clean -fd*)",
// Secret and environment files (never read by the agent)
"Read(**/.env)",
"Read(**/.env.*)",
"Read(**/appsettings.Production.json)",
"Read(**/appsettings.Staging.json)",
"Read(**/secrets.json)",
"Read(**/ConnectionStrings.config)",
"Read(**/*.pfx)",
"Read(**/*.p12)",
"Read(**/.azure/**)",
"Read(**/.aws/**)",
"Read(**/ServicePrincipal*)"
]
},
"env": {
"DOTNET_NOLOGO": "1",
"DOTNET_CLI_TELEMETRY_OPTOUT": "1",
"NUGET_PACKAGES": "${HOME}/.nuget/packages"
}
}
The $schema line at the top enables autocomplete and inline validation in Visual Studio, VS Code, and Rider. The schema is updated periodically; a validation warning on a recently documented field does not necessarily mean the file is invalid.
Adding auto mode prose rules for .NET
The autoMode block lets you extend the built-in classifier with project-specific prose rules. Useful for long migration sessions where you want the agent to work uninterrupted but still respect domain-specific safety boundaries.
{
"autoMode": {
"hard_deny": [
"$defaults",
"Running any database migration against a connection string that contains 'prod', 'live', or 'production'",
"Modifying any file under src/Generated/ or src/Migrations/ without explicit instruction",
"Adding any NuGet package not already present in the existing solution",
"Running dotnet publish or dotnet pack without an explicit request to do so"
],
"soft_deny": [
"$defaults",
"Making structural changes to the solution file (adding or removing projects)",
"Changing any project target framework without reading CLAUDE.md first"
],
"allow": [
"$defaults",
"Running dotnet build and dotnet test repeatedly",
"Running dotnet format after editing C# files",
"Running dotnet restore after modifying .csproj files",
"Reading any file under src/, test/, or docs/"
]
}
}
The literal string "$defaults" includes the built-in classifier rules at that position. Include it to extend rather than replace the defaults.
Personal versus team scopes
.claude/settings.json is committed to the repository and shared by the whole team. .claude/settings.local.json is gitignored automatically when Claude Code creates it.
The workflow for introducing a new allowed command:
- Add it to your
settings.local.jsonand test it. - If it works safely across a session, propose adding it to the team
settings.jsonin a PR. - The PR review is also a review of the permissions change.
Environment variables with machine-specific paths, personal API keys for experimental MCP servers, and permissions that only make sense on your machine belong in settings.local.json.
Hooks for .NET development
Hooks are shell commands (or HTTP endpoints or LLM prompts) that run automatically at specific points in the Claude Code lifecycle. For .NET development, three hooks do most of the work: format on edit, build on edit, and a session start summary.
All hooks below belong in .claude/settings.json so the team shares them.
Format and build after every C# edit
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"if": "Edit(*.cs)|Write(*.cs)",
"command": "bash",
"args": [
"-c",
"FILE=$(echo '$INPUT' | jq -r '.tool_input.file_path // .tool_input.path // empty'); if [ -n \"$FILE\" ]; then DIR=$(dirname \"$FILE\"); PROJ=$(find \"$DIR\" -maxdepth 3 -name '*.csproj' -print -quit 2>/dev/null); if [ -n \"$PROJ\" ]; then dotnet format \"$PROJ\" --include \"$FILE\" --no-restore 2>&1; dotnet build \"$PROJ\" --no-restore -v minimal 2>&1; fi; fi"
],
"timeout": 30000
}
]
}
]
}
}
This runs dotnet format and dotnet build --no-restore on the nearest project after each C# file edit. The --no-restore flag skips package restore, keeping the hook fast. If the build fails, Claude Code sees the output and can self-correct before moving to the next file.
For simpler setups where you prefer a project-level hook rather than file-level, use a shell script in .claude/hooks/:
#!/bin/bash
# .claude/hooks/after-cs-edit.sh
# Run after any .cs file is written or edited
INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
if [ -z "$FILE" ] || [[ "$FILE" != *.cs ]]; then
exit 0
fi
# Find the nearest .csproj
DIR=$(dirname "$FILE")
PROJ=$(find "$DIR" -maxdepth 4 -name "*.csproj" -print -quit 2>/dev/null)
if [ -z "$PROJ" ]; then
exit 0
fi
dotnet format "$PROJ" --include "$FILE" --no-restore
dotnet build "$PROJ" --no-restore -v minimal
Reference it in settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/after-cs-edit.sh"
}
]
}
]
}
}
Run tests after a test file edit
{
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"if": "Edit(*Tests.cs)|Write(*Tests.cs)|Edit(*Tests/*.cs)|Write(*Tests/*.cs)",
"command": "bash",
"args": ["-c", "PROJ=$(find . -maxdepth 4 -name '*.Tests.csproj' -o -name '*.Test.csproj' | head -1); if [ -n \"$PROJ\" ]; then dotnet test \"$PROJ\" --no-restore -v minimal 2>&1; fi"]
}
]
}
]
}
Block destructive rm commands
{
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm*)",
"command": "bash",
"args": ["-c", "CMD=$(echo \"$INPUT\" | jq -r '.tool_input.command'); if echo \"$CMD\" | grep -qE 'rm -rf (bin|obj|src|.git)'; then echo '{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"Destructive rm on protected directory blocked\"}}'; exit 0; fi"]
}
]
}
]
}
Session start: .NET status summary
{
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "bash",
"args": ["-c", "echo '=== .NET Environment ==='; dotnet --version; echo; echo '=== Solution ==='; dotnet sln list 2>/dev/null || echo 'No .sln found in working directory'; echo; echo '=== Git status ==='; git status -sb 2>/dev/null || echo 'Not a git repository'; echo; echo '=== Uncommitted changes ==='; git diff --stat 2>/dev/null"]
}
]
}
]
}
This prints the .NET SDK version, the projects in the solution, the current branch, and the uncommitted diff summary at the start of every session. The agent reads this output and starts with current state rather than having to ask.
Snapshot progress before compaction
During long migration sessions, the /compact command compresses the conversation context. You can use a PreCompact hook to save migration progress notes to a file so context that matters survives the compaction.
{
"PreCompact": [
{
"hooks": [
{
"type": "command",
"command": "bash",
"args": ["-c", "mkdir -p .claude && echo \"[$(date -u +%Y-%m-%dT%H:%M:%SZ)] Pre-compact snapshot\" >> .claude/migration-progress.log; git diff --stat >> .claude/migration-progress.log 2>/dev/null; echo '---' >> .claude/migration-progress.log"]
}
]
}
]
}
MCP servers for a .NET shop
MCP (Model Context Protocol) servers extend Claude Code with external data and tools. They are configured in .mcp.json at the project root. The team shares this file.
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"azure": {
"command": "npx",
"args": ["-y", "@azure/mcp"],
"env": {
"AZURE_SUBSCRIPTION_ID": "${AZURE_SUBSCRIPTION_ID}"
}
}
}
}
Recommended MCP servers for .NET teams
GitHub MCP: issues, PRs, and code review. The agent can open a PR, read review comments, and fix them without leaving the session. Essential for teams using GitHub Actions for CI.
Azure MCP: resource inspection during platform modernisation. The agent can check App Service configurations, Container Apps revisions, and Key Vault secrets (read-only) during migration planning. Set to read-only in the autoMode deny list.
SQL Server or custom schema MCP: for EF Core migrations, an MCP that can diff the current schema against a baseline lets the agent verify that its migration scripts match the actual database. There is no official SQL Server MCP as of May 2026. A lightweight custom server calling sqlpackage /action:DeployReport works well.
Work items MCP: connecting Claude Code to your issue tracker (Linear, Jira, Azure DevOps) lets the agent read acceptance criteria and update task status. In our Q1 2026 AI Velocity Report this was one of the six live MCP integrations: replacing manual context switching for work items.
Security note: credentials for MCP servers belong in environment variables, not in .mcp.json. Use ${ENV_VAR} substitution as shown above, and store the actual values in .claude/settings.local.json under env or in a .env file excluded by .gitignore. We evaluated OpenClaw (a self-managed credential sharing service for remote agents) and skipped it on security grounds: the self-managed install, credentials shared with remote agents, and the fast-moving open-source codebase did not meet our ISO 27001 bar.
Skills for .NET development
Skills extend what Claude Code can do. A SKILL.md file gives Claude detailed instructions for a specific workflow. The agent invokes skills automatically when the description matches, or you invoke them explicitly with /skill-name.
Skills live in .claude/skills/<name>/SKILL.md for project-level, or ~/.claude/skills/<name>/SKILL.md for personal.
Migrate a .NET project
.claude/skills/migrate-dotnet-project/SKILL.md
---
description: Migrate a single .NET Framework project to .NET 10. Use when the user asks to migrate a project, asks to start migration of a component, or provides a project path for migration.
---
## Instructions
1. Read CLAUDE.md and AGENTS.md to load the migration rules for this solution.
2. Read the target .csproj file and identify the current target framework.
3. Run `dotnet ef migrations list` if the project has an EF context to capture the current migration history.
4. Produce a migration plan listing:
- All .NET Framework APIs in use that need replacing
- All NuGet packages that need updating or replacing
- The recommended order of file changes
5. Wait for confirmation before proceeding.
6. Migrate one file at a time. After each file, run `dotnet build <project> --no-restore` and show the result.
7. Fix any build failures before moving to the next file.
8. After all files are migrated, run `dotnet test <test-project> --no-restore` and fix any migration-related test failures.
9. Produce a summary of all changes made.
Write xUnit tests
.claude/skills/write-xunit-tests/SKILL.md
---
description: Write xUnit tests for a .NET class or method. Use when the user asks to write tests, add test coverage, or generate tests for a specific file or method.
---
## Instructions
1. Read the target file to understand the class and its dependencies.
2. Read AGENTS.md for the project's test naming conventions.
3. Write tests using xUnit, NSubstitute for mocks, and FluentAssertions for assertions.
4. Follow the naming convention: {ClassName}Tests and {MethodName}_{Scenario}_{ExpectedResult}.
5. Cover: happy path, validation failures, edge cases, and any async cancellation paths.
6. Use constructor injection for the class under test. Do not use static factories or service locators in tests.
7. Run `dotnet test` on the test project and fix any failures before presenting the output.
Add an EF Core entity
.claude/skills/add-ef-core-entity/SKILL.md
---
description: Add a new EF Core entity following the project's data access conventions. Use when the user asks to add a new domain entity, data model, or database table.
---
## Instructions
1. Read AGENTS.md for the project's EF Core conventions (fluent API or data annotations, naming, inheritance patterns).
2. Read an existing entity and its configuration class to understand the established pattern.
3. Create the entity class with appropriate properties.
4. Create an IEntityTypeConfiguration<T> implementation using fluent API.
5. Register the configuration in the DbContext.
6. Generate a migration: `dotnet ef migrations add Add{EntityName}`.
7. Run `dotnet build` and `dotnet test` to confirm nothing is broken.
8. Do not use data annotations if the project uses fluent API exclusively, and vice versa.
Author a Roslyn analyser
.claude/skills/roslyn-analyser/SKILL.md
---
description: Create a Roslyn DiagnosticAnalyzer to enforce a coding convention deterministically. Use when the user wants to turn a prose rule into a build-time check.
---
## Instructions
1. Identify the pattern to detect (the violation) and the pattern to suggest (the fix).
2. Create a DiagnosticAnalyzer class in a separate analyser project.
3. Register a DiagnosticDescriptor with a unique ID, category, and message.
4. Implement the analysis logic using the Roslyn syntax/semantic model.
5. Write xUnit tests using Microsoft.CodeAnalysis.Testing.
6. Register the analyser in Directory.Build.props as an analyzer package reference so it applies to the whole solution.
7. Reference the harness engineering guide (/guides/ai-and-code/harness-engineering-coding-agents/) for the rationale: every prose rule worth keeping should aspire to become a deterministic check.
Subagents for .NET workflows
Subagents are Claude Code agents with specialised system prompts, tool restrictions, and model assignments. They live in .claude/agents/ (project-level) or ~/.claude/agents/ (personal).
Code reviewer
.claude/agents/code-reviewer.md
---
name: code-reviewer
description: Reviews .NET code changes for correctness, conventions, and security. Grounded in build and test output before offering opinions.
model: claude-sonnet-4-7
tools: [Read, Bash]
---
You are a senior .NET developer reviewing a code change. Before commenting on any issue, run the available computational sensors and ground your findings in their output.
Required steps before any review comment:
1. Run `dotnet build --no-restore` and read the output.
2. Run `dotnet test --no-restore` and read the output.
3. Run `dotnet format --verify-no-changes` and note any formatting drift.
Only raise issues that the sensors did not catch if you have high confidence they are real. Do not speculate. Do not raise style issues the formatter would fix automatically.
When reviewing a migration, additionally check:
- EF Core lazy loading usage (any virtual navigation properties without explicit .Include())
- DateTime.Now usage (should use TimeProvider)
- HttpClient instantiation outside IHttpClientFactory
- ConfigurationManager usage (should use IConfiguration)
- Thread.Sleep usage (should use await Task.Delay)
Migration analyser
.claude/agents/migration-analyser.md
---
name: migration-analyser
description: Read-only analysis agent for .NET Framework to .NET 10 migration planning. Does not modify files.
model: claude-sonnet-4-7
tools: [Read, Bash]
---
You are a read-only migration analyst. You do not modify files. Your job is to produce a structured migration plan.
For a given project path:
1. Read all .cs files and the .csproj file.
2. Identify every .NET Framework API that needs replacing on .NET 10.
3. Identify every NuGet package that needs updating or replacing.
4. Identify any Windows-specific APIs requiring Microsoft.Windows.Compatibility.
5. Identify any EF6 patterns with no direct EF Core equivalent (lazy loading, ObjectContext, complex inheritance).
6. Produce a structured report: file path, line number, current API, recommended replacement.
7. Estimate effort in developer-hours, broken into automated (Claude Code) and manual (human decision required).
Do not suggest architectural changes. Focus on mechanical translation readiness.
Cloud agents and multitasking
Claude Code is not just a terminal tool. The same agent, with the same configuration, runs on four surfaces: the terminal CLI, the web app at claude.ai/code, the desktop app, and mobile via the web. Your account, your MCP servers, and your skills follow you between them.
Background agents for long-running .NET work
You can run a task as a background agent while you keep working in Visual Studio or VS Code. Start a background session with claude --bg:
# Kick off a migration analysis while you keep working
claude --bg "Read src/OrderManagement.Infrastructure/ and produce a migration plan following CLAUDE.md. List every .NET Framework API, its location, and the .NET 10 replacement. Write the plan to .claude/migration-plan-infrastructure.md"
The agent runs in the background. Claude Code notifies you when it completes. You review the plan file at your desk, or from your phone via the web UI.
Parallel agents with worktrees
Each agent gets its own git worktree so multiple migrations can run side by side:
# Start two parallel migrations on separate branches
claude --worktree migrate-domain "Migrate src/OrderManagement.Domain/ to .NET 10 following CLAUDE.md"
claude --worktree migrate-infrastructure "Migrate src/OrderManagement.Infrastructure/ to .NET 10 following CLAUDE.md"
The result is two branches. Each agent works in its own directory. The original working tree stays buildable while the migrations run.
For a 15-project solution, the practical pattern is: migrate projects in dependency order, but start the next leaf the moment its dependency is done. One developer can supervise three or four parallel migrations at once.
Practical note: worktrees double NuGet restore time on first run because each worktree has its own restore cache. Set NUGET_PACKAGES in settings.json to a shared path to warm the cache once.
Exploring ideas on the go
The web UI and mobile browser access the same Claude Code account. Useful patterns:
- Kick off a refactor proposal from your phone on the commute: “Will the WCF service in OrderManagement.Messaging translate cleanly to gRPC? Produce a brief comparison and flag any patterns with no direct equivalent.”
- Review the resulting plan during a meeting, annotate it in the chat, and the next session at your desk picks up where you left off.
- Background agents started from the terminal are visible and resumable from the web UI. Start a long analysis before leaving the office, check the result from anywhere.
Managed Agents environments for .NET
Anthropic’s Managed Agents API lets you provision a cloud container with .NET pre-installed, then spawn many sessions against it. Useful for long migration runs, CI integration, or sandboxed analysis away from a developer laptop.
A worked .NET 10 environment definition:
{
"name": "dotnet10-migration",
"config": {
"type": "cloud",
"packages": {
"apt": ["dotnet-sdk-10.0", "git", "jq"]
},
"networking": {
"type": "limited",
"allowed_hosts": [
"api.nuget.org",
"pkgs.dev.azure.com",
"api.anthropic.com"
],
"allow_package_managers": true,
"allow_mcp_servers": true
}
}
}
After the environment is created, post-install the global tools in a SessionStart hook or as part of the agent’s initial instructions:
dotnet tool install -g upgrade-assistant
dotnet tool install -g dotnet-ef
This environment is reused across sessions. The same definition works in CI (GitHub Actions calling the Managed Agents API), from the web UI during exploration, and from the desktop app for longer sessions. Behaviour is consistent because the container is the same.
All Managed Agents API requests require the managed-agents-2026-04-01 beta header. The Anthropic SDK sets it automatically.
One developer, three agents: a worked example
The pattern that consistently compresses migration timelines:
Developer at desk (Visual Studio) Background Agent 1 Background Agent 2
Working on Domain project Migrating Infrastructure Analysing Services
- Reviews Domain migration diff - PostToolUse hook runs - Producing migration plan
- Merges approved changes - dotnet build on each file - Writing to .claude/plan-svc.md
- Starts next review - Reports when done - Reports when done
The developer’s job shifts from writing migration code to reviewing agent output. The agents handle the mechanical translation. The developer handles architectural decisions and review.
CI integration for .NET
GitHub Actions
A basic GitHub Actions job for PR-time migration sweeps:
name: Claude Code migration sweep
on:
pull_request:
paths:
- 'src/**/*.cs'
- '**/*.csproj'
jobs:
migration-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Install tools
run: |
dotnet tool install -g upgrade-assistant
dotnet tool install -g dotnet-ef
- name: Run Claude Code migration analysis
uses: anthropics/claude-code-action@v1
with:
prompt: |
Read the changed files in this PR and check for:
1. Any remaining .NET Framework APIs that were not migrated
2. Any EF6 patterns that should be EF Core equivalents
3. Any DateTime.Now usage that should use TimeProvider
4. Any HttpClient instantiation outside IHttpClientFactory
Run dotnet build and dotnet test and include their output.
Post a summary as a PR comment.
allowed_tools: "Bash,Read"
permission_mode: "plan"
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
The permission_mode: "plan" setting means the agent reads and analyses but does not modify files. It posts a PR comment with findings. A developer reviews the comment and decides which findings to act on.
For a fully automated sweep that makes fixes (use with caution and on feature branches only):
- name: Run Claude Code migration fix
uses: anthropics/claude-code-action@v1
with:
prompt: "Fix any remaining .NET Framework APIs in the changed files following CLAUDE.md migration rules. Run dotnet build and dotnet test after each fix. Do not change business logic."
allowed_tools: "Bash,Read,Edit,Write"
permission_mode: "auto"
Velocity Report: this is the configuration TTD ships .NET with
The Q1 2026 AI Velocity Report records 84% AI-authored code across active projects, 40-50% faster delivery, and six live MCP integrations. The configuration in this guide is the outer harness behind those numbers: pre-approved permissions, PostToolUse hooks, MCP servers for work items and CI, and skills for recurring .NET workflows.
For the full stack, tools, and methodology behind the numbers, see the Q1 2026 AI Velocity Report.
Next steps
For the getting-started guide covering installation, CLAUDE.md setup, and practical workflows, see Claude Code for .NET Developers.
For the migration-specific playbook covering the .NET Upgrade Assistant, EF6 migration, and project-by-project workflow, see .NET Framework to .NET 10 Migration with Claude Code.
For the deeper framing of computational sensors versus inferential checks, and why every prose rule should aspire to become a deterministic check, see Harness Engineering for Coding Agents.
For the model-driven template pattern and how to turn a Skill into a conflict-free code generator, see Harness Templates for AI Coding Agents.
For the broader .NET modernisation strategy, see the .NET Modernisation Playbook.
Frequently asked questions
What is the difference between user, project, and local settings in Claude Code?
Do hooks slow Claude Code down?
Can hooks block destructive commands?
How do I share hooks with the team safely?
What is autoMode and when should I use it for .NET work?
How do I run Claude Code in CI for .NET projects?
Related guides
Claude Code for .NET Developers: A Practical Getting Started Guide
Getting started with Claude Code for C# and .NET. Installation, IDE integration, pre-approved command setup, cloud agents, and practical .NET workflows.
The GDS Service Standard for Private-Sector Delivery Teams
A practical guide to what the UK Government's GDS Service Standard offers private-sector delivery teams, which practices transfer directly, which need adapting, and which are genuinely public-sector specific.
In-House DevOps vs DevOps-as-a-Service: A Cost and Capability Comparison
Should you hire a DevOps engineer or work with a DevOps-as-a-Service partner? A practical comparison of cost, coverage, risk, and how AI-augmented delivery changes the economics.