Module 1.1
CLAUDE.md Deep Dive
What CLAUDE.md Actually Is
Every time you start a Claude Code session, Claude reads CLAUDE.md and injects its contents directly into the system prompt. That's the mechanism. It's not magic - it's just a file that becomes part of Claude's instructions before you type anything.
This means whatever you write in CLAUDE.md shapes Claude's behavior for that entire session, automatically, every time.
The File Hierarchy
Claude doesn't just read one CLAUDE.md. It reads multiple, in this order:
~/.claude/CLAUDE.md ← 1. Global (applies to every project)
~/projects/CLAUDE.md ← 2. Parent directory (if it exists)
~/projects/my-app/CLAUDE.md ← 3. Project-level (most specific)
~/projects/my-app/src/CLAUDE.md ← 4. Subdirectory (most local)
All of them get loaded and merged. More specific files don't override global ones - they stack on top. So your global CLAUDE.md might say "always use British English" and your project CLAUDE.md might say "this is a FastAPI project" - Claude sees both.
Practical implication: Put universal preferences (coding style, communication preferences, tools you always use) in the global file. Put project-specific context (tech stack, commands, file structure, team conventions) in the project file.
The 200-Line Rule
Claude Code truncates CLAUDE.md after ~200 lines. Everything after line 200 gets cut off silently.
This forces discipline. You can't dump everything in one file. The fix is the @import syntax:
# My Project
@import docs/architecture.md
@import docs/conventions.md
@import docs/commands.mdEach @import pulls in another file's contents. Keep the main CLAUDE.md as a lean index that points to topic files.
What to Put In It
A well-structured project CLAUDE.md has four sections:
1. Project context - what this codebase is, the tech stack, key architectural decisions
## Project
FastAPI backend, PostgreSQL, deployed on Railway.
Auth uses JWT tokens stored in httpOnly cookies.2. Commands - the exact commands to run tests, start the server, lint, etc.
## Commands
- Run tests: `pytest tests/ -v`
- Start dev server: `uvicorn main:app --reload`
- Lint: `ruff check .`3. Conventions - coding style, naming patterns, what to avoid
## Conventions
- Use async functions for all route handlers
- Never use `print()` - use the logger
- All new endpoints need a test4. Constraints - things Claude should never do in this project
## Constraints
- Never modify migration files directly
- Don't install new packages without asking firstGlobal vs Project: What Goes Where
Global ~/.claude/CLAUDE.md | Project ./CLAUDE.md |
|---|---|
| Preferred coding style | Tech stack & architecture |
| Communication preferences | Run/test/lint commands |
| Tools you always want available | File structure overview |
| How you like responses formatted | Team conventions |
| Personal workflow rules | What not to touch |
Common Mistakes
| Mistake | Problem | Fix |
|---|---|---|
| Writing it like a README | Too much prose, not actionable | Write imperatives: "Always...", "Never...", "Use..." |
| Putting everything in one file | Hits 200-line truncation | Use @import to split into topic files |
| Outdated commands | Claude runs wrong commands | Treat it like code - update it when things change |
| No constraints section | Claude makes risky changes | Explicitly list what it shouldn't do |
| Vague instructions | Ignored or misinterpreted | Be specific, same rules as prompt engineering |
A Real Example
# my-saas-app
## Project
Next.js 14 (App Router) + Supabase + Stripe.
Multi-tenant SaaS. Each tenant has isolated data via RLS policies.
## Commands
- Dev: `npm run dev`
- Tests: `npm test`
- Type check: `npx tsc --noEmit`
- Lint: `npm run lint`
## Structure
- `app/` - Next.js routes
- `components/` - shared UI
- `lib/supabase/` - all database logic lives here
- `lib/stripe/` - all billing logic lives here
## Conventions
- Server components by default. Use `"use client"` only when needed.
- All DB queries go through `lib/supabase/` - never query directly in components
- Use Zod for all form validation
## Constraints
- Never modify `supabase/migrations/` - always create new migration files
- Don't add new npm packages without flagging it first
- RLS policies must be tested before any schema change ships
@import .claude/architecture.md