Context Files for AI Coding Tools: CLAUDE.md, Copilot Instructions, and AGENTS.md

Context Files for AI Coding Tools: CLAUDE.md, Copilot Instructions, and AGENTS.md
Photo by Franz Harvin Aceituna / Unsplash

Your AI Tools Are Flying Blind Without These Files

Every AI coding assistant defaults to generic patterns unless you tell it otherwise. Claude Code reaches for controllers. Copilot suggests IActionResult. Cursor writes synchronous LINQ. The output compiles fine but is architecturally wrong for your project. Every. Single. Time.

The fix isn't better prompting. It's a set of committed files that define your conventions once and apply them to every AI session, every developer, every tool. The ecosystem has matured fast: we now have CLAUDE.md, copilot-instructions.md, prompt files, custom agents, and AGENTS.md, each solving a different piece of the context problem.

I've written previously about setting up Claude Code for .NET and GitHub Copilot for .NET individually. This post pulls it all together. One repo, all the context files, every tool covered.


The Landscape: What Files Exist and Who Reads Them

Here's the full picture as of mid-2026:

File / Path Tool Scope Auto-loaded?
CLAUDE.md (root) Claude Code Whole project Yes
subfolder/CLAUDE.md Claude Code That directory tree Yes (hierarchical)
.github/copilot-instructions.md GitHub Copilot Whole repo Yes
.github/instructions/*.instructions.md GitHub Copilot File-type or path-specific Yes (when applyTo matches)
.github/prompts/*.prompt.md GitHub Copilot On-demand templates No (invoked manually)
.github/agents/*.yaml GitHub Copilot Custom agent personas Yes (when agent invoked)
copilot-setup-steps.yml Copilot Coding Agent Cloud agent environment Yes
AGENTS.md Cross-tool convention Documentation layer Varies by tool

Here's what matters: these files are not mutually exclusive. You commit all of them. Each tool reads what it understands and ignores the rest. The cost is a handful of markdown files. The payoff is every AI tool in your pipeline operating with full project awareness.


AGENTS.md: The Cross-Tool Standard

AGENTS.md is the newest addition here and the most interesting one. No single vendor owns it. The convention is emerging across Claude Code, Copilot, Cursor, Windsurf, and other AI coding tools as a universal way to document how agents should behave in your repository.

Where CLAUDE.md is Claude-specific and copilot-instructions.md is Copilot-specific, AGENTS.md describes your project's AI interaction model in a tool-agnostic way. Think of it as the README for your AI assistants.

What goes in it:

  • Agent roles and capabilities available in the repo
  • Which tools or MCPs agents have access to
  • Workflow descriptions (how to run tests, how to deploy)
  • Architecture decisions that any AI tool should respect
  • Cross-references to tool-specific files

Here's an AGENTS.md for our example project:

# AGENTS.md - AI Agent Configuration

## Project Overview
ASP.NET Core 10 minimal API using clean architecture (Domain, Application,
Infrastructure, API layers). CQRS via MediatR, EF Core with PostgreSQL,
FluentValidation, Result pattern, Serilog, JWT auth.

## Architecture Rules (All Agents)
- No controllers. Minimal APIs only with endpoint route groups.
- No exception throwing for business logic. Use Result<T> pattern.
- Every async method takes CancellationToken as final parameter.
- All validation through FluentValidation pipeline behavior, not data annotations.

## Available Workflows
- `dotnet build src/CleanApi.sln` - build everything
- `dotnet test tests/` - run all tests
- `dotnet ef migrations add <Name> -p src/Infrastructure -s src/Api` - add migration

## Agent Roles
- **Code Generator**: Scaffolds new endpoints, entities, handlers following conventions
- **Code Reviewer**: Checks PRs against architecture rules above
- **Test Writer**: Generates integration and unit tests using the project's patterns

## Tool-Specific Files
- Claude Code: see `CLAUDE.md` at project root
- GitHub Copilot: see `.github/copilot-instructions.md` and `.github/instructions/`

This file doesn't replace the tool-specific ones. It complements them by providing a single source of truth that any AI (or any new developer) can read to understand the project's AI-assisted workflow.


Full Context Setup for a .NET Minimal API Project

Let me walk through every file I commit for a clean architecture ASP.NET Core 10 project. The stack: MediatR for CQRS, EF Core with PostgreSQL, FluentValidation, Result pattern, Serilog, JWT auth, minimal APIs with endpoint route groups.

.github/copilot-instructions.md - Repo-Wide Copilot Context

# Copilot Instructions - CleanApi

## Architecture
- ASP.NET Core 10 minimal APIs. No controllers. No [ApiController].
- Clean architecture: Api/, Application/, Domain/, Infrastructure/ projects.
- Endpoints registered via IEndpointRouteBuilder extension methods in route groups.
- CQRS through MediatR. Commands and Queries live in Application/Features/{Entity}/.

## Patterns
- Result<T> for all Application layer returns. Never throw for business logic.
- FluentValidation via MediatR pipeline behavior (ValidationBehavior<TRequest, TResponse>).
- Repository interfaces in Domain/. Implementations in Infrastructure/Persistence/.
- Entity configurations via IEntityTypeConfiguration<T>, applied with ApplyConfigurationsFromAssembly.

## Conventions
- Async methods suffixed with Async. CancellationToken as last parameter always.
- Records for DTOs and Commands/Queries. Classes for entities.
- Serilog structured logging. Never string interpolation in log templates.
- JWT auth via AddAuthentication().AddJwtBearer(). Policies defined per endpoint group.

## Testing
- Unit tests: xUnit + NSubstitute + FluentAssertions.
- Integration tests: WebApplicationFactory<Program> with Testcontainers for PostgreSQL.
- Test naming: MethodName_Scenario_ExpectedResult.

## Forbidden Patterns
- X Controllers, ControllerBase, IActionResult, ActionResult<T>
- X Data Annotations for validation ([Required], [MaxLength], etc.)
- X .Result, .Wait(), .GetAwaiter().GetResult()
- X DbContext injected directly into endpoints (use repositories or MediatR)
- X Exception throwing for not-found, validation failure, or authorization failure

.github/instructions/csharp.instructions.md - C# File-Specific Rules

---
applyTo: "**/*.cs"
---

# C# Code Conventions

When generating or modifying C# files:

- Use file-scoped namespaces (one per file).
- Use primary constructors where the class has simple DI dependencies.
- Prefer collection expressions (`[1, 2, 3]`) over `new List<int> { 1, 2, 3 }`.
- Use `required` keyword on properties that must be set at initialization.
- Pattern matching over type checking: prefer `is` and `switch` expressions.
- Seal classes that are not designed for inheritance.
- Use `sealed record` for DTOs and value objects.
- `var` for obvious types only. Explicit types for non-obvious assignments.
- Use `TimeProvider` for time-dependent code, never `DateTime.Now` or `DateTime.UtcNow`.

.github/instructions/tests.instructions.md - Test-Specific Rules

---
applyTo: "tests/**/*.cs"
---

# Test Code Conventions

When generating or modifying test files:

- Use xUnit with [Fact] and [Theory] attributes.
- Use NSubstitute for mocking. Never Moq.
- Use FluentAssertions for all assertions (`.Should().Be()`, not `Assert.Equal()`).
- Test naming: `MethodName_Scenario_ExpectedResult` (e.g., `CreateOrder_WhenInvalidCustomer_ReturnsValidationError`).
- Arrange-Act-Assert structure. Separate each section with a blank line.
- Integration tests inherit from `IntegrationTestBase` which provides WebApplicationFactory and database.
- Use Testcontainers for PostgreSQL in integration tests. Never an in-memory provider.
- One test class per handler or endpoint. File name matches: `CreateOrderHandlerTests.cs`.

CLAUDE.md - Claude Code Project Brain

# CLAUDE.md - CleanApi Project

## Project Structure

src/ Api/ - Minimal API endpoints, middleware, Program.cs Application/ - MediatR handlers, DTOs, validators, pipeline behaviors Domain/ - Entities, value objects, repository interfaces, domain events Infrastructure/ - EF Core DbContext, repositories, migrations, external services tests/ Unit/ - Handler and service unit tests Integration/ - WebApplicationFactory + Testcontainers tests CleanApi.sln


## Tech Stack
- Runtime: .NET 10, C# 13
- ORM: EF Core 10 with Npgsql (PostgreSQL)
- Mediator: MediatR 12 (CQRS)
- Validation: FluentValidation 11
- Logging: Serilog with structured logging
- Auth: JWT via Microsoft.AspNetCore.Authentication.JwtBearer
- Testing: xUnit, NSubstitute, FluentAssertions, Testcontainers

## Architecture Rules
- Minimal APIs only. No controllers, no ControllerBase, no [ApiController].
- Endpoints are static extension methods on IEndpointRouteBuilder, grouped by entity.
- CQRS: Commands mutate state. Queries read state. Never mix.
- Result<T> pattern for all domain/application returns. No exception throwing for business logic.
- FluentValidation via MediatR ValidationBehavior pipeline. No data annotations.
- Repository pattern: interfaces in Domain/, implementations in Infrastructure/.
- Entity configuration: IEntityTypeConfiguration<T> in Infrastructure/Persistence/Configurations/.

## Coding Conventions
- File-scoped namespaces. One type per file.
- Async suffix on all async methods. CancellationToken as last parameter.
- Records for DTOs, Commands, Queries. Classes for entities.
- Primary constructors for DI in handlers and services.
- Serilog: use message templates, never string interpolation.
- Seal all classes not designed for inheritance.
- TimeProvider for time, never DateTime.Now.

## Build & Test
- Build: `dotnet build CleanApi.sln`
- Test: `dotnet test tests/ --no-build`
- Migrations: `dotnet ef migrations add <Name> -p src/Infrastructure -s src/Api`
- Run: `dotnet run --project src/Api`

## Forbidden
- X Controllers, IActionResult, ActionResult<T>
- X Data Annotations ([Required], [MaxLength])
- X .Result, .Wait(), .GetAwaiter().GetResult()
- X DbContext in endpoints directly
- X Exception-based flow control for business errors
- X In-memory database provider for tests

.github/prompts/new-endpoint.prompt.md - Reusable Prompt Template

# New Endpoint

Create a complete minimal API endpoint for the entity: {{entity}}

## Generate These Files

1. `src/Application/Features/{{entity}}/Commands/Create{{entity}}Command.cs`
   - sealed record with required properties
   - MediatR IRequest<Result<{{entity}}Dto>>

2. `src/Application/Features/{{entity}}/Commands/Create{{entity}}Handler.cs`
   - sealed class with primary constructor
   - Inject I{{entity}}Repository and IValidator<Create{{entity}}Command>
   - Return Result<T> (success or validation/domain error)

3. `src/Application/Features/{{entity}}/Queries/Get{{entity}}ByIdQuery.cs`
   - sealed record with Id property
   - MediatR IRequest<Result<{{entity}}Dto>>

4. `src/Application/Features/{{entity}}/Queries/Get{{entity}}ByIdHandler.cs`
   - sealed class, inject I{{entity}}Repository
   - Return Result<T> with NotFound error if missing

5. `src/Application/Features/{{entity}}/{{entity}}Dto.cs`
   - sealed record mapping from domain entity

6. `src/Application/Features/{{entity}}/Create{{entity}}Validator.cs`
   - FluentValidation AbstractValidator<Create{{entity}}Command>

7. `src/Api/Endpoints/{{entity}}Endpoints.cs`
   - Static class with Map{{entity}}Endpoints extension method
   - POST and GET /{entity}s routes
   - RequireAuthorization() on mutation endpoints
   - Map Result<T> to TypedResults.Ok / TypedResults.Problem / TypedResults.NotFound

8. `src/Domain/Entities/{{entity}}.cs`
   - Entity class with Id (Guid), audit fields (CreatedAt, UpdatedAt via TimeProvider)

9. `src/Domain/Repositories/I{{entity}}Repository.cs`
   - Interface with CreateAsync, GetByIdAsync (both with CancellationToken)

10. `src/Infrastructure/Persistence/Repositories/{{entity}}Repository.cs`
    - EF Core implementation of the interface

11. `src/Infrastructure/Persistence/Configurations/{{entity}}Configuration.cs`
    - IEntityTypeConfiguration<{{entity}}> with proper column mappings

## Constraints
- Follow all conventions in copilot-instructions.md and CLAUDE.md
- All methods async with CancellationToken
- No exceptions for business errors
- Use Result<T> throughout

This prompt template is invoked in Copilot Chat with /new-endpoint and lets you scaffold an entire feature vertical in one shot. The {{entity}} placeholders get filled when you use it.


Hierarchical Context: Monorepo Sub-Projects

Claude Code supports hierarchical CLAUDE.md files. A CLAUDE.md in a subfolder extends and overrides the root one for that directory tree. This matters a lot for monorepos.

Say your repo has a shared frontend alongside the API:

/CLAUDE.md                    ← root: general rules
/src/Api/CLAUDE.md            ← API-specific overrides
/src/Frontend/CLAUDE.md       ← Angular/React specific rules

The API-specific file might look like:

# CLAUDE.md - API Layer Overrides

## Context
This is the ASP.NET Core 10 API project. When working in this directory,
prioritize the following over root-level instructions:

## Endpoint Pattern
Every new endpoint file follows this exact structure:

```csharp
namespace CleanApi.Api.Endpoints;

public static class {Entity}Endpoints
{
    public static IEndpointRouteBuilder Map{Entity}Endpoints(
        this IEndpointRouteBuilder app)
    {
        var group = app.MapGroup("/api/{entities}")
            .WithTags("{Entity}")
            .RequireAuthorization();

        group.MapGet("/{id:guid}", GetById);
        group.MapPost("/", Create);

        return app;
    }

    private static async Task<IResult> GetById(
        Guid id,
        ISender sender,
        CancellationToken ct)
    {
        var result = await sender.Send(new Get{Entity}ByIdQuery(id), ct);
        return result.Match(
            success => TypedResults.Ok(success),
            error => TypedResults.NotFound());
    }
}

Dependencies Available

  • MediatR (ISender) for dispatching commands/queries
  • TypedResults for response mapping
  • Do not inject repositories directly into endpoints

Claude Code resolves the full context by merging root + subfolder. When you're working in `src/Api/`, it knows both the global rules and the API-specific patterns. When you switch to `src/Frontend/`, it picks up the frontend rules instead. Zero manual context switching.

---

## `copilot-setup-steps.yml` - Cloud Agent Environment

If you use GitHub's **Copilot Coding Agent** (the one that creates PRs autonomously), it needs to know how to build your project in its cloud container. That's what `copilot-setup-steps.yml` handles:

```yaml
# .github/copilot-setup-steps.yml
steps:
  - name: Setup .NET
    uses: actions/setup-dotnet@v4
    with:
      dotnet-version: '10.0.x'

  - name: Restore dependencies
    run: dotnet restore CleanApi.sln

  - name: Build solution
    run: dotnet build CleanApi.sln --no-restore

  - name: Install EF Core tools
    run: dotnet tool install --global dotnet-ef

Without this file, the Copilot Coding Agent can't verify that its generated code actually compiles. With it, every autonomous PR from the agent is build-verified before it hits your review queue.


The Payoff: What Actually Changes

Let me be direct about what happens in practice once you commit this full context setup:

Copilot inline suggestions stop suggesting controllers. They match your endpoint pattern, use your Result type, pass CancellationToken, and structure files the way your team expects.

Claude Code sessions start productive immediately. No "let me explain the architecture" preamble. Claude already knows. You say "add an Order entity" and get 11 files that compile and follow every convention.

New team members get a documented architecture that the AI enforces. The AGENTS.md and instruction files serve double duty as living documentation and AI configuration.

Code review gets faster. When every AI tool generates code to spec, the gap between "generated" and "mergeable" shrinks. In my experience, what used to take 3-4 correction cycles now merges in one.

The total setup cost is maybe 2 hours. The ongoing return is every AI interaction in your repo producing output that matches your team's standards without manual correction. That's the 75% easier threshold I keep coming back to. Not a marginal improvement, but a fundamental shift in how much rework you're doing.


Get Started in 15 Minutes

You don't need all of these files on day one. Here's the priority order:

  1. CLAUDE.md or .github/copilot-instructions.md - whichever tool you use most, set up its context file first. Copy the examples above, adjust for your stack.
  2. .github/instructions/csharp.instructions.md - the file-type specific rules catch patterns the repo-wide file misses.
  3. AGENTS.md - document the full picture for cross-tool compatibility.
  4. .github/prompts/ - build prompt templates for your most common scaffolding tasks.
  5. copilot-setup-steps.yml - add once you start using Copilot Coding Agent for autonomous PRs.

Every file you add compounds. The AI gets smarter about your project, your team gets faster, and the gap between "generated" and "ready to merge" closes.

Commit the context. Let the machines read it. Ship faster.