How to Write Effective CLAUDE.md Files
A practical guide to writing CLAUDE.md files that supercharge your Claude Code experience. Covers project instructions, conventions, and workflow optimization.
What Is CLAUDE.md and Why It Matters
If you have been using Claude Code for any length of time, you have probably noticed that it sometimes needs reminding about your project structure, coding conventions, or preferred workflows. That is exactly the problem that CLAUDE.md solves. It is a special markdown file placed in the root of your project that Claude Code reads automatically at the start of every session. Think of it as a persistent instruction set that gives Claude the context it needs to work effectively in your specific codebase from the very first message.
Without a CLAUDE.md, you end up repeating yourself constantly: "We use tabs not spaces," "Our API routes are in src/routes/," "Always use TypeScript strict mode." With a well-written CLAUDE.md, all of that context is loaded automatically. The result is a dramatically more productive experience where Claude understands your project from the start, follows your conventions without being asked, and produces code that fits seamlessly into your existing patterns.
Basic Structure
A good CLAUDE.md starts with three foundational sections: a project overview, your conventions, and a map of key files. Here is a minimal but effective starting template:
# Project: MyApp
## Overview
A Next.js 14 e-commerce platform using App Router,
TypeScript, Tailwind CSS, and Prisma with PostgreSQL.
## Conventions
- Use TypeScript strict mode for all files
- Prefer named exports over default exports
- Use server components by default; add "use client"
only when client interactivity is needed
- Follow the existing error handling pattern using
Result types (see src/lib/result.ts)
- Write tests using Vitest, colocated with source files
## Key Files and Directories
- src/app/ - Next.js App Router pages and layouts
- src/components/ - Shared React components
- src/lib/ - Utility functions and shared logic
- src/server/ - Server-side business logic
- prisma/schema.prisma - Database schema
- .env.example - Required environment variables
Even this minimal version saves you significant repetition. Claude now knows your tech stack, your file organization, and your basic coding standards before you type a single prompt.
Advanced Patterns
Once you are comfortable with the basics, you can add more sophisticated instructions that dramatically improve the quality of Claude's output. Here are some powerful patterns to consider.
Conditional instructions let you specify different behavior depending on context:
CLAUDE.md## Workflow Rules
- When creating new API routes, always include:
- Input validation with Zod schemas
- Error handling that returns proper HTTP status codes
- Rate limiting middleware
- OpenAPI JSDoc comments for documentation
- When modifying existing components, always:
- Check for existing tests and update them
- Preserve backward compatibility of props
- Update the component's Storybook story if one exists
Tool preferences tell Claude which tools to reach for in different situations:
CLAUDE.md## Tool Preferences
- Use the Grep tool instead of bash grep for searching
- Prefer editing existing files over creating new ones
- Run TypeScript compiler (npx tsc --noEmit) after
making type changes to verify correctness
- Use Vitest (npx vitest run) to run tests, not Jest
Code style rules ensure consistency with your existing codebase:
CLAUDE.md## Code Style
- Use functional components with arrow functions
- Prefer const assertions for literal types
- Use early returns to reduce nesting
- Maximum function length: 40 lines
- Name boolean variables with is/has/should prefixes
- Use descriptive variable names; avoid abbreviations
Real Example: A React Project
Here is a comprehensive CLAUDE.md from a production React application that demonstrates how all these patterns come together:
# Project: TaskFlow
## Overview
TaskFlow is a project management SPA built with React 18,
TypeScript, Zustand for state, React Query for data
fetching, and Tailwind CSS. The API is a separate
service; this repo is frontend only.
## Architecture
- src/features/ - Feature-based modules (each has
components/, hooks/, api/, types/)
- src/shared/ - Shared components, hooks, and utilities
- src/app/ - App shell, routing, providers
- All API calls go through React Query hooks in
each feature's api/ directory
## Conventions
- Functional components only, arrow function style
- Co-locate tests: Component.test.tsx next to Component.tsx
- Use Zustand slices pattern for global state
- CSS: Tailwind utility classes only, no custom CSS
- Imports: absolute paths using @/ alias
## Testing
- Unit tests: Vitest + React Testing Library
- Run: npx vitest run
- Minimum coverage: 80% for new features
- Mock API calls using MSW (see src/test/mocks/)
## Do NOT
- Do not use class components
- Do not add new dependencies without noting why
- Do not use inline styles; use Tailwind classes
- Do not modify shared/ui components without checking
all usage sites first
Real Example: A Python API
Here is another example for a different technology stack, a Python FastAPI backend:
CLAUDE.md (Python API Project)# Project: DataPipeline API
## Overview
FastAPI backend for a data processing pipeline.
Python 3.12, SQLAlchemy 2.0 with async, PostgreSQL,
Redis for caching, Celery for background tasks.
## Structure
- app/api/v1/ - API route handlers
- app/models/ - SQLAlchemy ORM models
- app/schemas/ - Pydantic request/response schemas
- app/services/ - Business logic layer
- app/tasks/ - Celery background tasks
- tests/ - Pytest test suite (mirrors app/ structure)
## Conventions
- Type hints on all function signatures
- Use async/await for all database operations
- Pydantic schemas for ALL request/response validation
- Services layer between routes and models (no direct
ORM queries in route handlers)
- Use dependency injection for database sessions
## Commands
- Run tests: pytest -xvs
- Run linter: ruff check .
- Run formatter: ruff format .
- Start dev server: uvicorn app.main:app --reload
## Error Handling
- Use app/exceptions.py for custom exception classes
- All API errors return structured JSON with
"detail" and "error_code" fields
- Log errors using structlog (see app/logging.py)
Common Mistakes to Avoid
- Being too vague: "Write good code" tells Claude nothing. Be specific: "Use early returns, keep functions under 40 lines, prefer composition over inheritance."
- Overloading with information: Claude Code reads the entire
CLAUDE.mdevery session. If it is 2,000 lines long, you are wasting context window on instructions that may not be relevant. Keep it focused and concise, ideally under 200 lines. - Forgetting to update it: Your
CLAUDE.mdshould evolve with your project. If you switch from Jest to Vitest, update the file. Stale instructions actively hurt productivity. - Duplicating what is obvious: You do not need to explain what React is. Focus on what is specific to your project that Claude would not otherwise know.
- Not including a "Do NOT" section: Telling Claude what to avoid is just as valuable as telling it what to do. If you have learned the hard way that certain patterns cause problems in your codebase, document them.
Checklist for a Great CLAUDE.md
- Project name and one-sentence description
- Tech stack with specific versions
- Directory structure with explanations
- Coding conventions (naming, style, patterns)
- Key commands (test, lint, build, run)
- Error handling patterns
- Testing requirements and tools
- A "Do NOT" section with known pitfalls
- Tool preferences for Claude Code
- File kept under 200 lines and actively maintained
A well-crafted CLAUDE.md is one of the highest-leverage investments you can make in your Claude Code workflow. Spend thirty minutes writing one today and you will save hours of repeated instructions over the coming weeks. Start with the basic template, iterate as you discover what Claude needs to know about your project, and watch your productivity compound over time.