A CLAUDE.md file is instructions for your AI coding assistant. Put one at the root of your repository and Claude Code reads it automatically. Other tools have equivalents: Cursor uses .cursorrules, GitHub Copilot uses .github/copilot-instructions.md.

This is my template. Copy what’s useful. Delete what isn’t.


The Template

# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

---

## Project Overview

<!-- Describe what this project is and its purpose -->

## Directory Structure

<!-- Include a tree of key directories and what they contain -->

```
project/
├── src/                    # Source code
├── tests/                  # Test files
├── docs/                   # Documentation
└── ...
```

## Common Commands

<!-- List the commands developers need to run frequently -->

**Development:**
```bash
# Start development server
# Run tests
# Build for production
```

---

# AI Coding Instructions

## Context Awareness

Before writing code, establish your working context:

- What module or layer am I working in?
- What are this module's dependencies?
- What interfaces does this module expose?
- What interfaces can this module consume?

Do not reach outside your working context without acknowledging the boundary crossing. If you need functionality from another module, say so. Don't just import it and hope for the best.

If you're unsure what the boundaries are, ask. "I need to call into the authentication module from here. Is that an expected dependency, or am I crossing a boundary that shouldn't be crossed?"

## Before You Create, Search

Before creating a new utility, helper, or abstraction:

1. Search for existing implementations
2. Check if something similar exists under a different name
3. Ask: "Am I about to write something that already exists in slightly different form?"

If you find something similar, prefer extending or reusing it over creating a new one. Duplication is sometimes fine. Accidental duplication rarely is.

## Modification Requires Justification

When you want to change existing code (especially shared code, interfaces, or utilities):

1. Explain why the change is necessary
2. Identify who else depends on what you're changing
3. Consider whether extension would work instead of modification
4. Surface the decision before making it

Here's the kind of surfacing that works well:

> "I need user data with orders. The current interface has `GetUser()` and `GetOrders()` separately. I could:
> 1. Add `GetUserWithOrders()` (quick, but there are already 3 similar methods)
> 2. Compose the existing methods at the call site
> 3. Refactor to a more flexible query pattern
>
> Which approach fits the codebase better?"

Now you're making the architectural decision. The AI is doing the analysis and implementation. That's the right division of labor.

## Impact Awareness

When modifying shared code:

- Identify all callers and implementations
- Verify your changes work for existing uses
- Update all affected code in the same change
- Do not leave the codebase inconsistent

If the impact is larger than expected, stop and surface it. "This change affects 12 files across 4 modules. Should I proceed, or should we discuss the scope?"

## Depend on Interfaces

Prefer depending on abstractions over concrete implementations. If you're reaching for a concrete class when an interface exists, pause. Ask yourself why.

If you can't implement a feature through available interfaces, that's information worth surfacing. Maybe the interfaces need to evolve. Maybe the feature belongs somewhere else. Maybe the request doesn't fit the architecture.

## When Stuck, Stop

If you hit a wall:

- Don't route around the architecture
- Don't create workarounds that bypass existing patterns
- Don't modify unrelated code to make your path easier

Instead, stop and explain:
- What you're trying to accomplish
- What's blocking you
- What options you see

Let the human make the architectural call. That's the division of labor.

## Considered Over Expedient

Every change should answer:

- Where does this belong?
- How does it relate to what exists?
- What's the impact of adding it?
- Is this the right solution, or just the fastest one?

Prefer changes that *belong* over changes that merely *work*.

---

# Prompt & Instruction Hygiene

When writing instructions, comments, or documentation:

- **State desired behavior directly** - don't negate or correct earlier statements
- **Avoid negative priming** - mentioning something to reject it still adds it to context and influences output
- **Start neutral, refine iteratively** - leading with constraints or failure modes can bias outputs before reasoning starts

This applies to code comments too. "Instead of X we do Y" or "We used to do X but now Y" still introduces X. Just describe Y.

Negation doesn't erase concepts; it weights them differently while keeping them active. If you want to avoid X, state Y directly as if X never existed.

---

# Working in This Codebase

## Reading Code Before Modifying

Never propose changes to code you haven't read. If asked to modify a file, read it first. Understand existing code before suggesting modifications.

## Minimal Changes

Avoid over-engineering. Only make changes that are directly requested or clearly necessary. Keep solutions simple and focused.

- Don't add features, refactor code, or make "improvements" beyond what was asked
- A bug fix doesn't need surrounding code cleaned up
- A simple feature doesn't need extra configurability
- Don't add docstrings, comments, or type annotations to code you didn't change
- Only add comments where the logic isn't self-evident

## Avoid Unnecessary Scaffolding

- Don't add error handling, fallbacks, or validation for scenarios that can't happen
- Trust internal code and framework guarantees
- Only validate at system boundaries (user input, external APIs)
- Don't use feature flags or backwards-compatibility shims when you can just change the code

## Delete Over Deprecate

- Don't create helpers, utilities, or abstractions for one-time operations
- Don't design for hypothetical future requirements
- If something is unused, delete it completely
- Avoid backwards-compatibility hacks like renaming unused `_vars`, re-exporting types, adding `// removed` comments
- Three similar lines of code is better than a premature abstraction

---

# Workflow Guidelines

## Atomic Commits

Make a commit after every logical change. Each commit should represent a single, complete unit of work:

- After adding a new feature - commit
- After fixing a bug - commit
- After updating styles - commit
- After modifying configuration - commit
- After refactoring - commit

Keep commits focused and atomic rather than bundling multiple unrelated changes together.

Given a prompt that mixes concerns, fix issues separately and commit each one.

Prefer succinct commit messages.

## Build and Verify After Changes

Always build and test after making changes to verify they work:

- Run the build command appropriate for the project
- Run tests if available
- Verify the application still works as expected

## Use Parallel Agents

Use as many agents as makes sense to speed up development:

- When tasks are independent, run them in parallel
- Examples: searching multiple codebases, exploring different parts of the architecture, running tests while implementing
- This significantly improves efficiency and reduces overall task completion time

## Look Up Documentation

Always look up official documentation when working with unfamiliar libraries or frameworks:

- Before implementing features, verify correct API usage
- Check package documentation on official websites
- Don't rely solely on general knowledge - verify with current documentation
- Especially important for: routing, state management, authentication, third-party integrations

---

# Documentation Guidelines

## Writing Tone

When writing documentation, comments, or user-facing text:

- Write in present tense stating facts, not changes
- Avoid temporal markers like "now", "new", "updated", "changed to"
- Say "Tasks have AllowedAgents" not "Tasks now have AllowedAgents"

## Documentation Style

- File headers should be short and concise
- Use clear, descriptive comments
- Explain the "why" not just the "what"
- Use progressive disclosure (simple explanation first, complex details later)

---

# Architecture Notes

<!-- Document key architectural decisions and patterns -->

---

# Optional Sections

The following sections contain additional guidelines that may be useful depending on project needs. Review and keep what applies.

---

## Decision Surfacing Framework

When approaching complex changes, use this framework:

1. **Evaluate**: Does the current design support what I need? If not, is this a design gap or a design smell?

2. **Decide**: Should I add something new, or refactor what exists? Surface this decision explicitly.

3. **Act**: If modifying, understand the impact radius. Update all callers. Leave the codebase consistent.

Example of good surfacing:

> "I need to add `GetUserWithOrderHistory()` to `IUserRepository`.
>
> Before I do, I notice there are already 3 similar methods. These feel like combinatorial explosion.
>
> **Options:**
> 1. Add another method (quick, but worsens sprawl)
> 2. Refactor to composable design (better long-term, affects 4 call sites)
>
> Which approach would you prefer?"

---

## Security Considerations

- Never commit secrets, API keys, or credentials
- Don't add error handling that leaks internal details to users
- Validate all user input at system boundaries
- Be cautious with file operations and user-provided paths
- Review generated code for common vulnerabilities (injection, XSS, etc.)

---

## Testing Philosophy

- Tests should verify behavior, not implementation
- Prefer integration tests that test real flows over unit tests that mock everything
- Mock external dependencies (APIs, databases) but not internal code
- Test the public interface, not private methods
- If something is hard to test, consider whether the design needs improvement

---

## Error Handling Patterns

- Handle errors at the appropriate level - not too early, not too late
- Use specific error types over generic exceptions
- Keep try/catch blocks minimal - process data after the catch
- Only catch exceptions you can handle meaningfully
- Don't swallow errors silently - log or propagate them

### Exception Hierarchy

Use inheritance to group related errors. Catch at the appropriate level of specificity:

```csharp
// Define a hierarchy
public class DomainException : Exception { }
public class ValidationException : DomainException { }
public class EntityNotFoundException : DomainException { }
public class ConflictException : DomainException { }

// Catch the base type when you want to handle all domain errors
try
{
    await service.ProcessAsync(request);
}
catch (DomainException ex)
{
    // Handles ValidationException, EntityNotFoundException, etc.
    logger.LogError(ex, "Domain error occurred");
    return Problem(ex.Message);
}

// Catch specific types when you need different handling
try
{
    await service.ProcessAsync(request);
}
catch (EntityNotFoundException)
{
    return NotFound();
}
catch (ValidationException ex)
{
    return BadRequest(ex.Message);
}
```

### Keep Try Blocks Minimal

Good pattern:
```csharp
Data data;
try
{
    data = await client.GetDataAsync();  // Can throw
}
catch (ClientException ex)
{
    logger.LogError(ex, "Failed to get data");
    return;
}

// Process data outside try block
var result = Transform(data);
```

Bad pattern:
```csharp
try
{
    var data = await client.GetDataAsync();  // Can throw
    // Don't process data inside try block
    var result = Transform(data);
    await Save(result);
}
catch (ClientException)
{
    logger.LogError("Failed");
}
```

---

## API Design Guidelines

- Be consistent with naming conventions across the codebase
- Use descriptive names that reveal intent
- Keep interfaces small and focused
- Prefer composition over inheritance
- Design for the common case, accommodate the edge cases

---

## Async/Concurrent Programming

- All external I/O operations should be async when available
- Avoid blocking calls in async contexts
- Use appropriate concurrency primitives (don't reinvent locks)
- Be careful with shared state across concurrent operations
- Prefer immutable data structures where practical

---

## Database/State Management

- Keep database operations in dedicated layers/modules
- Use transactions for operations that must be atomic
- Validate data before storing, not after retrieving
- Consider migration strategies for schema changes
- Don't store computed values that can be derived

---

## Logging Guidelines

- Log at appropriate levels (debug for development, info for operations, error for problems)
- Include context in log messages (what failed, with what inputs)
- Don't log sensitive data (passwords, tokens, PII)
- Use structured logging when available
- Log once per event - avoid duplicate logging

---

## Code Review Checklist

When reviewing code (or self-reviewing before commit):

- [ ] Does this change do what was requested?
- [ ] Is the code in the right place architecturally?
- [ ] Are there existing utilities/patterns being duplicated?
- [ ] Is the change minimal - no unnecessary additions?
- [ ] Are edge cases handled appropriately?
- [ ] Would a future developer understand this code?
- [ ] Are there any security concerns?
- [ ] Does this break any existing functionality?

---

## Refactoring Guidelines

When refactoring:

- Have a clear goal for the refactoring
- Make behavior-preserving changes only
- Refactor in small, verifiable steps
- Commit frequently during refactoring
- Don't mix refactoring with feature changes
- Verify behavior is preserved after each step

---

## Dependency Management

- Prefer well-maintained, widely-used libraries
- Pin dependency versions for reproducibility
- Review security advisories for dependencies
- Don't add dependencies for trivial functionality
- Keep dependencies up to date (but test after updates)

---

## Configuration Management

- Keep configuration separate from code
- Use environment variables for deployment-specific values
- Provide sensible defaults where appropriate
- Document all configuration options
- Validate configuration at startup, fail fast

---

## Feature Development Workflow

1. **Understand**: Read existing code, understand the context
2. **Plan**: Identify what needs to change, surface decisions
3. **Implement**: Make minimal, focused changes
4. **Verify**: Build, test, manually verify if needed
5. **Commit**: Atomic commit with clear message
6. **Review**: Self-review the diff before considering it done

---

## Bug Fixing Workflow

1. **Reproduce**: Confirm you can reproduce the bug
2. **Understand**: Identify the root cause, not just symptoms
3. **Fix**: Make the minimal change that fixes the issue
4. **Verify**: Confirm the fix works and doesn't break other things
5. **Prevent**: Consider if a test should prevent regression
6. **Commit**: Reference the bug/issue in the commit message

---

## Communication Style

When explaining decisions or asking questions:

- Be direct and specific
- Provide context for why you're asking
- Offer options when seeking decisions
- Explain trade-offs clearly
- Don't bury the lead - state the important thing first

---

## Clean Architecture Principles

If the project follows layered architecture:

- Dependencies point inward (outer layers depend on inner)
- Inner layers have no knowledge of outer layers
- Domain logic is pure (no external dependencies)
- Use interfaces to define boundaries between layers
- Keep framework-specific code at the edges

---

## Entity/Model Guidelines

- Entities should encapsulate their own validation
- Use strongly-typed identifiers when helpful
- Keep entities focused on their domain responsibility
- Prefer value objects for concepts without identity
- Don't let persistence concerns leak into domain models

---

## UI/UX Development

- Follow established design patterns in the project
- Maintain consistency with existing components
- Consider accessibility from the start
- Test on multiple viewport sizes if responsive
- Keep user-facing text clear and helpful

---

## API Integration Guidelines

- Handle all error cases (network, auth, rate limits, etc.)
- Implement appropriate retry logic with backoff
- Respect rate limits and quotas
- Log API interactions for debugging
- Use appropriate timeouts

---

## Documentation Requirements

For features/changes that warrant documentation:

- Update relevant README files
- Add inline comments for non-obvious logic
- Document public APIs and their parameters
- Include examples where helpful
- Keep documentation close to the code it describes

---

## Accessibility Guidelines

- Use semantic HTML elements
- Provide alt text for images
- Ensure sufficient color contrast
- Support keyboard navigation
- Test with screen readers when possible

---

## Metrics and Observability

- Add appropriate logging for operational visibility
- Consider what metrics would help diagnose issues
- Include correlation IDs for tracing requests
- Log timing for slow operations
- Balance verbosity with signal-to-noise ratio

---

## Data Validation Patterns

- Validate at system boundaries (API inputs, user forms, external data)
- Trust data within the system after validation
- Fail fast with clear error messages
- Distinguish between validation errors (user fixable) and system errors
- Don't validate the same data multiple times

---

## Naming Conventions

- Use consistent naming patterns across the codebase
- Names should be descriptive and reveal intent
- Avoid abbreviations unless universally understood
- Match the domain language when naming business concepts
- Prefer longer descriptive names over short cryptic ones

---

## File Organization

- Keep related files close together
- Prefer feature-based organization over type-based (components/auth vs components/buttons)
- Index files should only re-export, not contain logic
- Keep file sizes reasonable - split when they become unwieldy
- Name files consistently with their primary export

---

## Comments Philosophy

- Code should be self-documenting where possible
- Comment the "why", not the "what"
- Keep comments up to date with code changes
- Delete commented-out code - use version control instead
- Use TODO comments sparingly and with context

---

## Version Control Practices

- Write meaningful commit messages
- Keep commits atomic and focused
- Don't commit generated files (unless necessary)
- Use branches for features/experiments
- Review diffs before committing

---

## Dependency Injection

- Inject dependencies rather than creating them internally
- Define interfaces for external dependencies
- Keep constructors simple - just store dependencies
- Use DI containers when the project supports them
- Avoid service locator patterns

---

## State Management

- Keep state minimal and derived where possible
- Single source of truth for each piece of data
- Make state changes explicit and traceable
- Consider immutability for shared state
- Avoid global mutable state

---

## Rate Limiting and Throttling

- Implement rate limiting for public APIs
- Respect external API rate limits
- Use exponential backoff for retries
- Provide meaningful feedback when limits are hit
- Consider queue-based approaches for high load

---

## Background Jobs

- Make jobs idempotent when possible
- Implement proper error handling and retry logic
- Log job execution for debugging
- Consider job prioritization
- Monitor job queues and execution times

That’s the full template. Most projects won’t need all of this. Start with the skeleton, add sections as you encounter the problems they solve.