This is an instructions file. It lives in your repository root. Your AI coding assistant reads it before touching anything.
The name doesn’t matter. CLAUDE.md, AGENTS.md, INSTRUCTIONS.md. The point is getting expectations out of your head and into a file the tool actually reads. You know things about your codebase that the AI won’t guess correctly: where the boundaries are, what’s shared, which abstractions matter. If you don’t write it down, the AI will make reasonable-sounding decisions that violate your architecture in ways that take an hour to untangle.
What follows is a starting template. It’s opinionated. Steal what works, cut what doesn’t, add the things I couldn’t have known about your project.
# 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.
If you're unsure what the boundaries are, ask.
## 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. 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. Present the tradeoff before acting
Example:
"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?"
## 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 blast radius is bigger than you expected, stop and say so.
## Depend on Interfaces
Prefer abstractions over concrete implementations. If you're reaching for a concrete class when an interface exists, pause. Ask yourself why.
If the available interfaces won't let you implement what you need, that's a signal, not a blocker. The interfaces might need to change. The feature might belong in a different layer. The request might not fit this architecture at all. Any of those is worth a conversation before you start routing around the problem.
## 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
Stop and explain: what you're trying to accomplish, what's blocking you, what options you see.
Let the human make the architectural call.
The template above is generic on purpose. Your version should be specific. If your AI keeps creating duplicate utilities, make the “search before creating” section louder. If it keeps reaching across module boundaries, spell out exactly which modules exist and what they’re allowed to depend on.
The best instructions file is the one that prevents yesterday’s mistakes.