If you only do ONE thing to make Claude Code better, make it a good CLAUDE.md. Pair that with the settings hierarchy, permissions and MCP configuration, and you've got Claude Code set up to fly... for you and for your whole team.
CLAUDE.md: Persistent Project Context
CLAUDE.md is a markdown file that gives Claude lasting context about your project. It gets loaded automatically at the start of every session, so you never have to re-explain the basics.
A client once asked me what happens to their site if I die. Kinda morbid, honestly, but it was the right question, and it's what pushed me to rebuild my whole agency around real written-down systems instead of stuff living in my head. CLAUDE.md is that same idea for your project. Write it down once and nobody (human or AI) has to guess.
The File Hierarchy
Claude Code reads CLAUDE.md files at three levels.
User-level (~/.claude/CLAUDE.md) - Personal preferences across all projects
Project-level (./CLAUDE.md) - Project-specific context shared with the team
Claude Code loads every CLAUDE.md from your working directory and the folders above it when the session starts. They don't override each other, they get stacked into context together (general ones first, closer ones last). So if two files contradict each other, Claude might pick either one. Don't make it guess.
What to Include
Build & Run Commands
Example
## Commands
- `npm run dev` - Start dev server (port 3001 if 3000 is busy)
- `npm run build` - Production build (required before deploy)
- `npm run test:unit` - Run unit tests
- `npm run lint:fix` - Auto-fix lint issues
The non-obvious stuff is where the gold is. Weird flags, environment requirements and the gotchas that bit you last month.
## Conventions
- Use named exports (not default exports)
- Prefer early returns over nested conditionals
- Use `type` keyword for TypeScript types (not `interface`)
- Server Components by default, `'use client'` only when needed
- Max 100 characters per line
- Use absolute imports (@/lib/..., @/components/...)
Known Gotchas
Example
## Gotchas
- The `prisma` client must be imported from `@/lib/db` (not generated directly)
- API routes need auth check: `const { userId } = await auth()`
- Never use `git push --force` on main
- The CI build uses Node 20, not 22
What NOT to Include
Secrets or API keys - Use environment variables and only write down the variable names
File contents Claude can read - Don't paste your package.json in there, Claude can read it directly
Stale documentation - Keep it current, or Claude will happily follow outdated instructions
Entire framework docs - Claude already knows React and Next.js, so just list YOUR conventions
Obvious things - Don't say "use TypeScript" if your project is already TypeScript
Using /init to Bootstrap
The fastest way to get started is this.
Example
claude
Then type /init. Claude looks over your project structure, figures out your stack and writes a starter CLAUDE.md. Read it over, then make it yours.
Directory-Level CLAUDE.md
For big projects, extra CLAUDE.md files in subdirectories add context for specific areas.
Each one only loads when Claude reads files in that directory, which keeps your context lean.
Real Example
Here's a small but effective CLAUDE.md.
Example
# My SaaS App
## Stack
Next.js 14 (App Router), TypeScript, Tailwind, Supabase
## Commands
- `npm run dev` - Dev server on :3000
- `npm run build` - Must pass before merging
- `npm test -- --run` - Tests (Vitest)
## Conventions
- Named exports only
- Server Components by default
- API routes: validate with Zod, auth with Clerk middleware
- Database: use Prisma, never raw SQL
## Structure
- src/app/(auth)/ - Public auth pages
- src/app/(main)/ - Protected app pages
- src/lib/db/ - Prisma client and queries
## Gotchas
- Prisma client is at src/lib/db/index.ts (singleton pattern)
- Environment variables must be in .env.local (not .env)
- The deploy script requires Railway CLI installed
Settings Hierarchy
Settings stack up in layers. For your own files, the more specific layer beats the more general one. Managed settings from your organization are the exception, because they sit on top of everything and can't be overridden.
Example
Managed (highest priority - set by your organization, can't be overridden)
βββ User (~/.claude/settings.json - your personal defaults)
βββ Project (.claude/settings.json - shared with team)
βββ Local (.claude/settings.local.json - your local overrides)
Precedence. Managed > Command line flags > Local > Project > User
Settings File Locations
Level
Path
Committed to Git?
Purpose
Managed
Organization-controlled
N/A
Enterprise policies
User
~/.claude/settings.json
No
Personal preferences
Project
.claude/settings.json
Yes
Team standards
Local
.claude/settings.local.json
No (gitignored)
Personal overrides
Permission Rules
Permissions decide what Claude gets to do without asking you first. The format is Tool(pattern).
Creating or editing any file under src/ (Edit rules cover every file-editing tool)
Read(.env)
Reading any file named .env, at any depth
Permission Priority
Rules get checked in order, deny first, then ask, then allow
If nothing matches, Claude asks you (the default behavior)
In Bash rules * matches any text. File rules like Edit(...) and Read(...) use gitignore-style paths, where * stays inside one folder and ** reaches into subfolders
MCP Servers
MCP (Model Context Protocol) servers are plugins that hook Claude up to outside data and tools.
What MCP Servers Can Do
Connect to databases and query data
Pull information from APIs (Jira, Confluence, Slack)
Get into file storage (S3, R2)
Work with your own internal tools
Add special skills (image processing, PDF generation)
Configuring MCP Servers
Project MCP servers live in a file called .mcp.json at the root of your project.
When Claude Code creates .claude/settings.local.json itself, it adds the file to your global git excludes so it stays out of your commits. If you make the file by hand, add it to .gitignore yourself. Either way, each developer can tweak their own settings without messing with the rest of the team.
Setting Up a New Team Member
When a new developer joins, here's the drill.
They clone the repo (and get .claude/settings.json, skills, hooks and CLAUDE.md for free)
They create a personal ~/.claude/settings.json with their preferences
They optionally create .claude/settings.local.json for local overrides
They set whatever environment variables the MCP servers need
They run claude and everything just works with the team settings
TL;DR
CLAUDE.md loads every session, so put your commands, conventions, architecture and gotchas in it
Keep secrets, pasted file contents and stale docs OUT of CLAUDE.md
Use /init to bootstrap, then customize
Directory-level CLAUDE.md files add detail without bloating the main file
Settings stack as Managed > Command line > Local > Project > User
Permission rules use the Tool(pattern) format, like Bash(npm run *) or Edit(src/**), and deny always wins
MCP servers hook Claude up to outside data and tools
Commit .claude/settings.json, .mcp.json and skills, and gitignore .local.json
New team members get everything from the repo with zero extra setup