TechLead
Lesson 4 of 25
9 min read
AI-Native Engineering

Writing Effective CLAUDE.md Files

Master the art of writing CLAUDE.md files that transform AI output quality by giving Claude deep context about your project architecture, conventions, and requirements

What is CLAUDE.md?

CLAUDE.md is a markdown file that provides persistent instructions to Claude Code across all sessions in a project. Think of it as your project's onboarding document — but specifically designed for an AI collaborator. A well-written CLAUDE.md is the single highest-leverage thing you can do to improve Claude Code's output quality.

Without a CLAUDE.md, Claude reads your code and makes reasonable guesses about conventions and architecture. With a great CLAUDE.md, Claude knows your conventions, understands your architecture, and produces code that looks like your team wrote it.

Where CLAUDE.md Files Live

  • Project Root (CLAUDE.md): Committed to git, shared with the whole team. Contains project-wide instructions.
  • .claude/CLAUDE.md: Can be gitignored for personal preferences (your specific workflow, editor settings).
  • ~/.claude/CLAUDE.md: Global instructions that apply to ALL projects (your general coding style preferences).
  • Subdirectory CLAUDE.md: Place in any subdirectory for context-specific instructions (e.g., packages/api/CLAUDE.md).

What to Include in CLAUDE.md

A great CLAUDE.md has five sections. Not all are required, but the more context you provide, the better the output.

1. Project Overview

What is this project? What does it do? What is the tech stack? This orients Claude immediately instead of making it guess from file structure.

2. Architecture and Structure

Where do things live? What are the key directories? How does data flow? What are the naming conventions for files?

3. Coding Conventions

How does your team write code? What patterns do you use? What should Claude avoid? This is the section that most dramatically improves output consistency.

4. Common Commands

How to run the dev server, tests, linter, build, deploy. Claude uses these to verify its changes work.

5. Known Pitfalls

What are the gotchas in this codebase? Things that are not obvious from reading the code. Environment-specific issues. Legacy decisions that look wrong but exist for a reason.

Complete CLAUDE.md Template: Next.js Project

# CLAUDE.md

## Project Overview
E-commerce platform built with Next.js 14 (App Router).
Static export deployed to Vercel. ~50 pages, ~200 components.
Revenue: $2M ARR. Any downtime or bugs directly impact revenue.

## Tech Stack
- Next.js 14 with App Router and static export (output: "export")
- TypeScript in strict mode — never use 'any' type
- Tailwind CSS — no CSS modules, no styled-components
- Supabase for database and auth
- Stripe for payments
- Vercel for hosting

## Directory Structure
- app/ — Next.js app router pages
- app/components/ — shared React components
- app/lib/ — utility functions and data files
- app/hooks/ — custom React hooks
- public/ — static assets
- supabase/ — database migrations and seed files

## Coding Conventions
- Functional components only, no class components
- Named exports, not default exports
- "use client" only when component needs browser APIs or state
- Components: PascalCase (UserCard.tsx)
- Utilities: camelCase (formatPrice.ts)
- Types: defined in the same file unless shared, then in app/types/
- Prefer composition over inheritance
- No barrel files (index.ts re-exports)
- Error boundaries around every page-level component

## State Management
- Server state: React Server Components (default)
- Client state: useState/useReducer for local, Zustand for global
- No Redux, no Context API for state (only for dependency injection)

## Testing
- Framework: Vitest + React Testing Library
- Run all tests: npm test
- Run single file: npx vitest path/to/file.test.ts
- Coverage: npm run test:coverage
- Every component needs a test. Every utility function needs a test.
- Test file location: co-located (Button.tsx + Button.test.tsx)

## Common Commands
- Dev: npm run dev (port 3000)
- Build: npm run build
- Lint: npm run lint
- Type check: npx tsc --noEmit
- Format: npx prettier --write .

## Important: Known Pitfalls
- The pricing logic in app/lib/pricing.ts has tax rules that vary
  by state. Do NOT simplify or refactor without understanding the
  tax implications.
- The Supabase RLS policies are critical for security. Never
  bypass them with service_role key in client-side code.
- Image optimization is disabled because we use static export.
  Use regular img tags with width/height, not next/image.
- The checkout flow has a specific order of operations that Stripe
  requires. Do not reorder the steps in CheckoutWizard.tsx.

Complete CLAUDE.md Template: Python API

# CLAUDE.md

## Project Overview
REST API for a healthcare scheduling platform.
Built with FastAPI + PostgreSQL. Handles PHI (Protected Health
Information) — security and HIPAA compliance are critical.

## Tech Stack
- Python 3.12 with FastAPI
- PostgreSQL 16 with SQLAlchemy ORM (async)
- Alembic for migrations
- Redis for caching and rate limiting
- Celery for background tasks
- Docker for local development and deployment

## Directory Structure
- app/ — main application code
- app/api/ — route handlers organized by domain
- app/models/ — SQLAlchemy models
- app/schemas/ — Pydantic request/response schemas
- app/services/ — business logic layer
- app/core/ — config, security, database setup
- tests/ — mirrors app/ structure
- migrations/ — Alembic migration files

## Coding Conventions
- Type hints on ALL functions (params and return types)
- Async functions for all database operations
- Business logic in services/, not in route handlers
- Route handlers only: parse request, call service, return response
- Use dependency injection for database sessions
- Pydantic models for ALL request/response validation
- Never expose internal IDs — use UUIDs in API responses

## Security Rules (CRITICAL)
- All PHI fields must be encrypted at rest (use app/core/encryption.py)
- Never log patient names, SSNs, or medical record numbers
- All endpoints require authentication except /health and /docs
- Use parameterized queries only — no string concatenation for SQL
- Rate limit all endpoints (configured in app/core/rate_limit.py)

## Testing
- Run tests: pytest
- Run with coverage: pytest --cov=app
- Fixtures in tests/conftest.py
- Use factory_boy for test data generation
- Integration tests use a real test database (Docker)

## Common Commands
- Dev server: uvicorn app.main:app --reload
- Run migrations: alembic upgrade head
- Create migration: alembic revision --autogenerate -m "description"
- Docker: docker-compose up -d
- Lint: ruff check . && ruff format --check .

Complete CLAUDE.md Template: Monorepo

# CLAUDE.md

## Project Overview
Monorepo for the Acme platform. Contains web app, mobile app,
shared component library, and backend API.

## Structure
- apps/web — Next.js web application
- apps/mobile — React Native mobile app
- apps/api — Node.js Express API
- packages/ui — shared component library (used by web and mobile)
- packages/shared — shared types, utils, and constants
- packages/config — shared ESLint, TypeScript, and Prettier configs

## Package Manager
- pnpm workspaces (DO NOT use npm or yarn)
- Install: pnpm install (from root)
- Add dependency: pnpm add -w package (root) or pnpm add package --filter @acme/web

## Cross-Package Rules
- packages/shared — NO React dependencies, pure TypeScript only
- packages/ui — React components, but no Next.js or React Native specifics
- When adding types used by multiple packages, put them in packages/shared/types/
- All packages use the shared tsconfig from packages/config

## Working in Specific Apps
- When working in apps/web, read apps/web/CLAUDE.md for web-specific conventions
- When working in apps/api, read apps/api/CLAUDE.md for API conventions
- Always check if a change affects shared packages

## Common Commands
- Dev all: pnpm dev (runs all apps concurrently)
- Dev web only: pnpm dev --filter @acme/web
- Build all: pnpm build
- Test all: pnpm test
- Lint: pnpm lint
- Type check: pnpm typecheck

What NOT to Include

A CLAUDE.md should contain things Claude cannot easily derive from the code itself. Do not include:

  • A full file tree listing: Claude can read the directory structure itself
  • Copies of your code: Claude will read the actual files
  • Generic best practices: Claude already knows TypeScript best practices
  • Overly long documents: Keep it under 500 lines. Focused and relevant.
  • Outdated information: Maintain it like code. If it is wrong, it actively hurts.

Before and After: The Impact

Scenario Without CLAUDE.md With CLAUDE.md
New componentDefault export, CSS modules, generic styleNamed export, Tailwind, matches team patterns exactly
Add API routeRandom structure, missing auth middlewareFollows existing route patterns, includes auth and validation
Write testsUses Jest (wrong framework), wrong file locationUses Vitest, co-located test file, uses team fixtures
Database queryRaw SQL string concatenationUses ORM, parameterized, follows service layer pattern
Error handlingGeneric try/catch with console.logUses custom error classes, structured logging, error boundaries

The 80/20 Rule for CLAUDE.md

You get 80% of the benefit from just these four things: (1) tech stack and key libraries, (2) directory structure with what goes where, (3) three to five coding conventions that matter most, and (4) how to run tests. Start there. You can always add more as you discover gaps in Claude's output.

Maintaining Your CLAUDE.md

Treat CLAUDE.md like living documentation. Review it monthly. When you notice Claude Code making the same mistake twice, add a note to CLAUDE.md. When your team adopts a new convention, update CLAUDE.md. When you deprecate a library, update CLAUDE.md.

# Pro tip: Ask Claude to help maintain its own instructions
> Review our CLAUDE.md and suggest improvements based on the current
  state of the codebase. Are there any conventions mentioned that we
  no longer follow? Any patterns in the code that should be documented
  but are not?

# Claude will compare the CLAUDE.md against actual code and suggest updates

Team Tip: Make CLAUDE.md Part of Code Review

When someone introduces a new convention or pattern, part of their PR should include updating the CLAUDE.md. This creates a virtuous cycle: the more your team maintains the CLAUDE.md, the better Claude's output becomes, the more the team trusts and uses Claude, and the more motivated they are to maintain the CLAUDE.md.

Summary

CLAUDE.md is the most underrated feature of Claude Code. It takes 30 minutes to write a good one and saves hours of correcting Claude's output every week. Start with the basics — tech stack, directory structure, conventions, and commands — then evolve it as you discover what Claude needs to know. Commit it to your repo so the whole team benefits, and maintain it like you maintain your code.

Continue Learning