CLAUDE.md: Project Governance
Every codebase has rules. Naming conventions, testing requirements, forbidden patterns, preferred libraries. Usually these live in a wiki nobody reads or a PR comment nobody remembers.
CLAUDE.md changes that. It is documentation that actively enforces itself - Claude reads it on every session start and follows it as binding instruction.
The Hierarchy
CLAUDE.md files follow a strict precedence order. Higher levels override lower levels:
| Level | Location | Scope | Shared? |
|---|---|---|---|
| Managed Policy | Set by org admin | Organization-wide | Org-managed |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md | This repository | Yes (committed to git) |
| User | ~/.claude/CLAUDE.md | All your projects | No (personal) |
When Claude starts a session, it loads all three levels and merges them. Managed policy always wins, then project, then user.
Unlike READMEs or wikis, CLAUDE.md is read by Claude at the start of every session. Rules you write here are not suggestions - they are constraints that shape every tool call, every file edit, every commit message.
What Belongs in CLAUDE.md
Keep it under ~200 lines. Focus on what Claude needs to know to work correctly in your codebase.
Good content for CLAUDE.md
# Project: Acme API
## Tech Stack
- TypeScript, Node.js 22, Express
- PostgreSQL with Drizzle ORM
- Vitest for testing
## Coding Standards
- Use `type` over `interface` unless extending
- All API routes must have Zod validation
- Never use `any` - use `unknown` and narrow
## Testing
- Every new function needs a test
- Run `npm test` before suggesting completion
- Integration tests go in `__tests__/integration/`
## Naming
- Files: kebab-case (e.g., `user-service.ts`)
- Database tables: snake_case
- TypeScript: camelCase for variables, PascalCase for typesWhat does NOT belong
- Entire API documentation (use @-imports instead)
- Long lists of every file in the project
- Information that changes frequently
- Secrets or credentials
@-Imports: Pulling in Context
For larger projects, split context across files and reference them:
## Architecture
See @docs/architecture.md
## API Reference
See @docs/api-reference.md
## Database Schema
See @prisma/schema.prismaClaude will read the referenced files when it needs that context. This keeps your root CLAUDE.md lean while making deep documentation accessible.
Path-Specific Rules
Sometimes rules only apply to certain files. A test file has different standards than a migration script. Use .claude/rules/*.md with paths: frontmatter:
---
paths:
- "**/*.test.ts"
- "**/*.spec.ts"
- "__tests__/**"
---
# Test File Rules
- Use `describe` blocks grouped by function name
- Each test needs a clear assertion message
- Use `vi.mock()` for external dependencies, never mock internal modules
- Always test error cases, not just happy paths
- Use factories from `test/factories/` instead of inline fixtures---
paths:
- "drizzle/**"
- "migrations/**"
---
# Migration Rules
- Never modify existing migration files
- Always generate migrations with `npm run db:generate`
- Include both up and down migrations
- Test migrations against a fresh database before committingThese rules activate automatically when Claude edits matching files. No manual prompting required.
Settings: Shared vs Personal
Claude Code has two settings files:
| File | Committed? | Use for |
|---|---|---|
| .claude/settings.json | Yes - shared with team | Tool permissions, hooks, team defaults |
| .claude/settings.local.json | No - gitignored | Personal preferences, local paths |
{
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(npx prettier --write *)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force*)"
]
}
}The shared settings file is powerful for teams - everyone gets the same permissions, the same hooks, the same guardrails, committed right alongside the code.
You do not need a perfect CLAUDE.md on day one. Start with your tech stack and top 3 rules. Add more as you notice Claude making mistakes - each mistake is a rule you have not written yet.
Exercises
Create a CLAUDE.md for your project
Pick a real project you work on. Create a CLAUDE.md that covers:
- Tech stack (language, framework, database, testing)
- At least 3 coding standards specific to your project
- Naming conventions for files, variables, and database entities
- One @-import reference to existing documentation
# Project: Invoice API
## Tech Stack
- Python 3.12, FastAPI, SQLAlchemy
- PostgreSQL 16
- pytest with pytest-asyncio
## Coding Standards
- All endpoints return Pydantic models, never raw dicts
- Use dependency injection for database sessions
- Raise HTTPException with specific status codes, never return error dicts
- Use `Decimal` for all monetary values, never `float`
## Naming
- Files: snake_case (e.g., `invoice_service.py`)
- Database tables: plural snake_case (e.g., `invoice_items`)
- API routes: plural kebab-case (e.g., `/api/invoice-items`)
## Architecture
See @docs/architecture.mdCreate a path-specific rule for test files
Create a .claude/rules/tests.md file that enforces test conventions only when editing test files.
paths: frontmatter with glob patterns that match your test file naming convention.---
paths:
- "**/*.test.ts"
- "**/*.test.tsx"
- "**/__tests__/**"
---
# Test Conventions
- Group tests with `describe` blocks matching the module under test
- Use `it("should ...")` for test names, not `test()`
- One assertion per test unless testing a sequence
- Mock external services in `beforeEach`, restore in `afterEach`
- Never import from `node_modules` directly in tests - use the project's re-exportsStudents often write overly long CLAUDE.md files. Emphasize the ~200 line limit. If they need more, that is a sign to use @-imports or path-specific rules. Also remind them that CLAUDE.md is NOT a README - it is instructions for the AI, not documentation for humans.