Claude CodeApril 12, 2026 · 18 min read

CLAUDE.md Guide — The Perfect Setup for Every Project Type (2026)

After six months of using Claude Code daily, I've learned what makes a CLAUDE.md actually work — and what makes Claude silently ignore it. This guide covers 7 copy-paste templates, a diagnostic checklist, real token savings, and the decision tree I use to decide what belongs where.

G
Garry
Developer & Founder, ToolStackHub · Using Claude Code daily since launch

1. What Is CLAUDE.md and Why Does It Matter?

Every Claude Code session starts with a blank slate. Claude has no memory of the conversation you had yesterday, no recollection of the naming convention you spent 20 minutes explaining last week, and zero knowledge of the landmines buried in your codebase. You start from zero, every single time.

CLAUDE.md is the only file Claude Code loads automatically at session start. It's your project's onboarding document — not for a new human developer, but for your AI collaborator. Think of it as a README, except instead of explaining the project to humans, you're explaining it to Claude in a way that immediately changes its behavior.

Without a CLAUDE.md, you waste the first 10–15 messages of every session re-explaining context. Claude makes wrong assumptions about your tech stack, uses the wrong test command, and occasionally reaches into a folder it absolutely should not touch. With a well-written CLAUDE.md, Claude follows your conventions from message one, runs the right commands, and avoids your landmines.

It's also worth knowing that CLAUDE.md isn't exclusive to Claude Code. Cursor, Zed, and OpenCode use AGENTS.md — same concept, different filename. The principles in this guide apply to all of them. Once you understand how to write a good CLAUDE.md, you can adapt it to any AI coding tool in minutes.

⚡ The Token Budget Reality

LLMs can reliably follow approximately 150–200 distinct instructions. Claude Code's built-in system prompt already consumes around 50 of those slots. That leaves you roughly 100–150 instruction slots in your CLAUDE.md before compliance quality starts to degrade. This is why lean CLAUDE.md files outperform comprehensive ones — you're working with a finite budget.

2. Where to Put CLAUDE.md (File Hierarchy Explained)

Claude Code supports CLAUDE.md files in three locations. They all load together and cascade — think of it like CSS specificity, where more specific (deeper) files win conflicts.

LocationScopeBest For
~/.claude/CLAUDE.mdGlobal — all projectsPersonal preferences: tone, response format, output language
~/project/CLAUDE.mdProject root — most commonStack, commands, style rules, architecture constraints. Commit to git.
~/project/src/CLAUDE.mdDirectory-scopedMonorepos — per-package rules that override the root file
💡
My setup: Global CLAUDE.md holds my personal preferences — I like concise responses, I prefer TypeScript, and I want Claude to flag breaking changes before implementing them. The project root CLAUDE.md holds everything project-specific. I commit the project one to Git so the whole team benefits. The global one stays on my machine.

3. The 7 Sections Every CLAUDE.md Needs

After months of iteration, I've landed on seven sections that cover everything Claude needs without bloating the file. Here's each one with the reasoning behind it.

01

Project Overview

2–3 lines max. What it is, the core tech, and a one-liner purpose.

# Project: ShopFlow
E-commerce platform for D2C brands. Next.js 14 App Router,
Prisma ORM, Stripe, Tailwind CSS. Deployed on Vercel.

💬 The overview anchors every response. Without it, Claude sometimes drifts toward patterns from its training data rather than your actual project.

02

Tech Stack & Conventions

5–10 lines. Language version, framework, key libraries, naming conventions, import style.

## Tech Stack
- Node 20 / TypeScript 5.4 (strict mode)
- Next.js 14 App Router (NOT Pages Router)
- Tailwind CSS — no CSS modules
- Prisma + PostgreSQL
- Zod for all input validation
- camelCase variables, PascalCase components
- ES modules only — never require()

💬 The most important line is usually the one clarifying what version or pattern you're NOT using. "App Router, NOT Pages Router" has saved me countless corrections.

03

Key Commands

5–8 lines. The exact commands Claude should run, not guesses.

## Commands
- Dev:    npm run dev
- Build:  npm run build
- Test:   npx jest --watch
- Lint:   npm run lint
- DB:     npx prisma migrate dev
- Deploy: vercel --prod

💬 Claude will try to guess your commands from package.json patterns. It's usually right, but "usually" isn't good enough when it's about to run a destructive migration.

04

Code Style Rules

5–10 lines. Only rules Claude gets wrong without explicit instruction.

## Code Style
- Named exports only — never default exports
- API routes return { success: boolean, data?: T, error?: string }
- Use React Query for data fetching — never useEffect for data
- Server Components are default — only add "use client" when needed
- All dates stored/returned as ISO 8601 strings

💬 The key insight: don't document things Claude already knows. Only add rules for things you've had to correct Claude on at least twice.

05

Architecture Constraints

3–5 lines. The "never touch" rules — phrased with NEVER for emphasis.

## Architecture Rules
- NEVER modify files in /prisma/migrations/ directly
- All DB changes go through: npx prisma migrate dev
- NEVER commit .env — use .env.local
- API routes must validate with Zod before any DB call
- Images must use next/image — never raw <img>

💬 These are your landmines. Phrasing with NEVER in caps genuinely improves compliance — Claude weights it differently than softer language.

06

File Structure Overview

5–10 lines. Only what's non-obvious. Skip anything standard.

## Structure
- app/          Pages and API routes (App Router)
- components/   Reusable UI components
- lib/          Utilities and shared logic
- lib/db.ts     Singleton Prisma client — use this, don't import Prisma directly
- prisma/       Schema and migrations
- public/       Static assets

💬 The lib/db.ts note is the kind of thing that saves a session. Without it, Claude might instantiate a new Prisma client in every file.

07

Active TODOs / Current Focus

3–5 lines. What you're working on right now.

## Current Focus
- Migrating checkout flow from Pages Router to App Router
- DO NOT refactor auth — it's being replaced next sprint
- New API routes should follow pattern in app/api/products/route.ts

💬 This section has the highest ROI of any section. It eliminates the 5-minute context dump at the start of every session. Update it when your focus shifts.

Complete assembled example (all 7 sections):

# Project: ShopFlow
E-commerce for D2C brands. Next.js 14 App Router, Prisma + PostgreSQL,
Stripe, Tailwind CSS. Deployed on Vercel.

## Tech Stack
- Node 20 / TypeScript 5.4 strict
- Next.js 14 App Router (NOT Pages Router)
- Tailwind CSS (no CSS modules)
- Prisma ORM + PostgreSQL
- Zod for all input validation
- camelCase vars, PascalCase components, kebab-case files
- ES modules only — never require()

## Commands
- Dev:    npm run dev
- Build:  npm run build
- Test:   npx jest --watch
- Lint:   npm run lint
- DB:     npx prisma migrate dev
- Deploy: vercel --prod

## Code Style
- Named exports only — no default exports
- API responses: { success: boolean, data?: T, error?: string }
- Use React Query for data fetching — not useEffect
- Server Components are default — add "use client" only when needed
- All dates: ISO 8601 strings

## Architecture Rules
- NEVER edit /prisma/migrations/ directly
- NEVER commit .env — use .env.local
- All API routes validate input with Zod before any DB call
- Images: next/image only — never raw <img>

## Structure
- app/         Pages and API routes
- components/  Reusable UI
- lib/         Shared utilities
- lib/db.ts    Singleton Prisma client — import this, not prisma directly
- prisma/      Schema + migrations

## Current Focus
- Migrating checkout from Pages to App Router
- DO NOT refactor auth — being replaced next sprint
- Follow pattern in app/api/products/route.ts for new routes

4. 7 Copy-Paste Templates by Project Type

These templates are written as if I'm actually working with each stack daily — because I have been. Each one is immediately usable. Copy the one matching your project, swap the placeholder names, and prune anything that doesn't apply.

⚛️

Template 1: Next.js 14 / React

# Project: [Name]
Next.js 14 App Router with TypeScript, Tailwind CSS, and Prisma.

## Tech Stack
- Next.js 14 (App Router, NOT Pages Router)
- TypeScript strict mode
- Tailwind CSS (no CSS modules)
- Prisma ORM with PostgreSQL
- Deployed on Vercel

## Commands
- Dev:        npm run dev
- Build:      npm run build
- Test:       npx jest --watch
- Lint:       npm run lint
- DB migrate: npx prisma migrate dev
- DB studio:  npx prisma studio

## Code Style
- Named exports (not default exports) for all components
- "use client" only when hooks or browser APIs are needed
- Server Components are default — don't add "use client" unnecessarily
- ES module imports only — never require()
- Destructure: import { useState } from "react"
- All API input validated with Zod

## Architecture Rules
- NEVER edit /prisma/migrations/ directly
- All API routes in app/api/ return NextResponse.json()
- API routes must validate input with Zod before DB calls
- Environment vars: .env.local (never commit .env)
- Images: next/image only — never raw <img>
- Singleton Prisma client lives in lib/db.ts

## File Structure
- app/         Pages and API routes (App Router)
- components/  Reusable React components
- lib/         Utilities and shared logic
- lib/db.ts    Prisma singleton — use this everywhere
- prisma/      Schema and migrations
- public/      Static assets

## Current Focus
- [What you're working on right now]
🐍

Template 2: Python / Django

# Project: [Name]
Django 5.x REST API + PostgreSQL. Serves a React frontend via DRF.

## Tech Stack
- Python 3.12 / Django 5.1
- Django REST Framework (DRF) for API
- PostgreSQL via psycopg2-binary
- Redis for caching and Celery
- Black formatter, isort, mypy for type checking
- Virtual env: .venv (activate: source .venv/bin/activate)

## Commands
- Dev server:    python manage.py runserver
- Shell:         python manage.py shell_plus
- Migrate:       python manage.py migrate
- Make migration:python manage.py makemigrations
- Tests:         python manage.py test --verbosity=2
- Coverage:      coverage run -m pytest && coverage report
- Celery worker: celery -A config worker -l info

## Code Style
- Type hints on all function signatures (PEP 484)
- Black formatting (line length 88) — run before every commit
- isort for import ordering
- Docstrings on all public methods (Google style)
- snake_case for variables and functions
- Use Django ORM — never raw SQL unless explicitly needed
- All API views use DRF serializers — no manual response dicts

## Architecture Rules
- NEVER run migrations in production directly — always review first
- Settings split: config/settings/base.py, local.py, production.py
- Secrets via environment variables — never hardcode
- All model changes require migration files committed with the change
- Use select_related / prefetch_related — NEVER query inside loops
- Custom managers in models.py — not raw .filter() in views

## File Structure
- config/       Django project settings and URLs
- apps/         All Django apps (one app per domain concept)
- apps/users/   Auth, user model (custom AbstractUser)
- templates/    Django templates (admin only — DRF handles API)
- requirements/ base.txt, dev.txt, prod.txt

## Current Focus
- [Current sprint / active feature]
🟩

Template 3: Node.js / Express API

# Project: [Name]
Node.js + Express REST API. TypeScript. PostgreSQL via Knex.

## Tech Stack
- Node 20 LTS / TypeScript 5.4
- Express 4.x
- Knex.js query builder + PostgreSQL
- Zod for request validation
- Jest + Supertest for testing
- ESLint + Prettier

## Commands
- Dev (hot reload): npm run dev        (uses tsx watch)
- Build:            npm run build      (tsc)
- Start prod:       npm start
- Test:             npm test
- Test watch:       npm run test:watch
- Migrate:          npm run db:migrate
- Rollback:         npm run db:rollback
- Seed:             npm run db:seed

## Code Style
- All route handlers are async — always try/catch or use asyncHandler wrapper
- Standard error response: { success: false, error: string, code?: string }
- Standard success response: { success: true, data: T }
- Validate ALL request bodies/params with Zod schemas at route level
- Middleware order: cors → auth → validate → handler → errorHandler
- Named exports — never default exports from route files

## Architecture Rules
- NEVER write raw SQL — use Knex builder
- NEVER return database error messages to clients — sanitize first
- Auth middleware must run before any protected route handler
- Rate limiting applied at router level, not individual routes
- All DB queries go through repository functions in /repositories
- NEVER access req.user without running auth middleware first

## File Structure
- src/routes/       Express route definitions
- src/controllers/  Request handlers (thin — delegate to services)
- src/services/     Business logic
- src/repositories/ Database queries (Knex)
- src/middleware/   Auth, validation, error handling
- src/lib/          DB connection, logger, config

## Current Focus
- [Current active work]
📱

Template 4: Flutter / Dart

# Project: [Name]
Flutter app (iOS + Android). Riverpod for state management.

## Tech Stack
- Flutter 3.24 / Dart 3.5
- Riverpod 2.x (code generation enabled)
- go_router for navigation
- Dio for HTTP (with interceptors)
- Freezed + json_serializable for models
- Hive for local storage

## Commands
- Run:          flutter run
- Build Android: flutter build apk --release
- Build iOS:    flutter build ios --release
- Test:         flutter test
- Analyze:      flutter analyze
- Pub get:      flutter pub get
- Code gen:     dart run build_runner build --delete-conflicting-outputs

## Code Style
- Always run dart run build_runner after model changes
- Use Freezed for all data classes — never plain Dart classes for models
- Riverpod providers: prefer AsyncNotifierProvider for server data
- No setState in stateful widgets — use Riverpod ConsumerWidget
- Platform-specific code goes in platform/ with conditional imports
- Widget files: one widget per file, PascalCase filename

## Architecture Rules
- NEVER call APIs directly from widgets — go through a repository
- ALL API calls must handle DioException — never let them bubble raw
- Avoid BuildContext across async gaps — use mounted check
- Navigation only through go_router — never Navigator.push directly
- Local storage keys defined as constants in lib/constants/storage.dart

## File Structure
- lib/features/    Feature-based modules (auth, home, profile)
- lib/shared/      Reusable widgets and utilities
- lib/core/        App config, theme, router, DI
- lib/data/        Repositories and API services
- assets/          Images, fonts, translations

## Current Focus
- [Active feature or platform]
🐹

Template 5: Go / Golang

# Project: [Name]
Go REST API. Standard library net/http + chi router. PostgreSQL via pgx.

## Tech Stack
- Go 1.23
- chi v5 router
- pgx v5 for PostgreSQL (no ORM)
- sqlc for type-safe SQL queries
- golang-migrate for migrations
- golangci-lint for linting
- testify for assertions

## Commands
- Run:           go run ./cmd/server
- Build:         go build -o bin/server ./cmd/server
- Test:          go test ./... -v
- Test coverage: go test ./... -coverprofile=coverage.out
- Lint:          golangci-lint run
- Generate SQL:  sqlc generate
- Migrate up:    migrate -path db/migrations -database $DATABASE_URL up
- Format:        gofmt -w . && goimports -w .

## Code Style
- Always run gofmt — non-negotiable, CI will fail without it
- Error handling: check every error, no _ for error values
- Errors wrap with context: fmt.Errorf("getUserByID: %w", err)
- Use structured logging via slog (stdlib) — never fmt.Println in production
- Table-driven tests for all pure functions
- No panic() outside of main initialization

## Architecture Rules
- NEVER use ORM — SQL goes through sqlc-generated functions only
- All DB queries in internal/store/ — never in handlers
- Handlers are thin: parse → validate → call service → respond
- Middleware applied to router groups, not individual routes
- Config loaded from environment via os.Getenv — no config files in repo
- NEVER log sensitive data (passwords, tokens, PII)

## File Structure
- cmd/server/     main.go entry point
- internal/       All application code (not exported)
- internal/api/   HTTP handlers and router
- internal/store/ sqlc-generated DB layer
- internal/service/ Business logic
- db/migrations/  SQL migration files
- db/queries/     SQL queries for sqlc

## Current Focus
- [Active module or feature]
🏗️

Template 6: Monorepo (Turborepo)

# Project: [Name] Monorepo
Turborepo monorepo. Web (Next.js), API (Express), shared packages.

## Workspace Structure
- apps/web        Next.js 14 frontend
- apps/api        Express REST API
- packages/ui     Shared component library
- packages/types  Shared TypeScript types
- packages/utils  Shared utility functions
- packages/config Shared ESLint, TS, Tailwind configs

## Tech Stack
- Node 20 / TypeScript 5.4
- Turborepo for task orchestration
- pnpm workspaces (ALWAYS use pnpm — never npm or yarn in this repo)
- Changesets for versioning packages

## Commands
- Dev all:      pnpm dev           (turbo runs all dev tasks)
- Dev web only: pnpm --filter web dev
- Dev api only: pnpm --filter api dev
- Build all:    pnpm build
- Test all:     pnpm test
- Lint all:     pnpm lint
- Add dep:      pnpm --filter [app] add [package]
- Add shared:   pnpm --filter [app] add @repo/ui

## Code Style
- Imports from shared packages: @repo/ui, @repo/types, @repo/utils
- NEVER copy-paste code between apps — create a shared package
- All shared types live in packages/types — never duplicate
- Component exports from packages/ui follow named export pattern

## Architecture Rules
- NEVER install the same dependency in two apps — extract to packages/
- Cross-package changes must run: pnpm build in affected packages first
- Internal packages use workspace: * versioning
- API types shared via packages/types — always keep in sync
- NEVER import from apps/ directory in packages/ (one-way dependency)

## Which Package to Touch
- UI change:         packages/ui → then apps that use it
- New API endpoint:  apps/api + packages/types (for response types)
- New page:          apps/web only
- Shared logic:      packages/utils

## Current Focus
- [Current cross-package work or migration]
🌐

Template 7: WordPress / PHP

# Project: [Name] — WordPress
Custom WordPress theme + plugin. PHP 8.2. WooCommerce.

## Tech Stack
- WordPress 6.7 / PHP 8.2
- Custom theme: wp-content/themes/[theme-name]
- Custom plugin: wp-content/plugins/[plugin-name]
- WooCommerce 9.x
- WP-CLI for automation
- Composer for PHP dependencies
- Node + webpack for asset bundling (npm run build)

## Commands
- Dev assets:    npm run dev        (webpack watch)
- Build assets:  npm run build
- WP CLI:        wp [command]       (from /var/www/html)
- Install plugin: wp plugin install [slug] --activate
- Export DB:     wp db export backup.sql
- Cache flush:   wp cache flush
- PHP lint:      vendor/bin/phpcs --standard=WordPress .

## Code Style
- Follow WordPress Coding Standards (WPCS) — CI enforces this
- snake_case for all PHP functions and variables
- Prefix ALL functions, hooks, and classes: [prefix]_function_name
- Enqueue scripts/styles via wp_enqueue_scripts hook — never inline
- Use wp_nonce_field() for all forms — CSRF protection required
- Escape ALL output: esc_html(), esc_attr(), esc_url(), wp_kses_post()
- Sanitize ALL input: sanitize_text_field(), absint(), etc.

## Architecture Rules
- NEVER modify core WordPress files or WooCommerce files directly
- Extend WooCommerce via hooks/filters — never edit plugin files
- All custom DB tables use $wpdb with proper escaping
- Custom post types registered in [prefix]-post-types.php
- NEVER use short PHP tags: <?php only
- Meta values stored with update_post_meta — no custom tables for simple data

## File Structure (Theme)
- functions.php     Autoloader + hook registration
- inc/              PHP includes (post types, taxonomies, helpers)
- template-parts/   Reusable template fragments
- assets/src/       Raw JS and SCSS
- assets/dist/      Built assets (gitignored)

## WP Hooks Reference
- Init logic:       add_action('init', ...)
- Admin pages:      add_action('admin_menu', ...)
- WC cart change:   add_action('woocommerce_add_to_cart', ...)

## Current Focus
- [Active theme/plugin feature]

5. CLAUDE.md vs Skills vs docs/ — Where Does It Belong?

One of the most common mistakes I see is treating CLAUDE.md as a catch-all documentation dump. It's not. Here's the decision framework I use.

Content TypePut it in…Why
Project overview, tech stackCLAUDE.mdNeeded every session
Build / test / lint commandsCLAUDE.mdUsed constantly
Code style rulesCLAUDE.mdApplies to every edit
API documentationdocs/API.mdToo long for CLAUDE.md; reference when needed
Deployment proceduresdocs/DEPLOY.md or SkillOnly needed occasionally
Complex workflow (e.g. release)SkillOn-demand, not every session
One-time setup instructionsdocs/SETUP.mdOnly needed once
Architecture deep-divedocs/ARCHITECTURE.mdReference, not every-session
Linting / formatting rulesHooksDeterministic 100% enforcement
Security rules (never commit secrets)CLAUDE.md + HookBelt and suspenders
💡
The key mental model: CLAUDE.md is advisory — expect roughly 80% compliance on a well-written file. Hooks are deterministic — 100% enforcement, every time. If something must happen without exception (like formatting, or blocking a secret from being committed), make it a hook. If it's guidance that shapes judgment calls, CLAUDE.md is the right place.

6. CLAUDE.md Diagnostic — Fix What's Broken

If Claude isn't behaving the way your CLAUDE.md says it should, here's how to diagnose it. These are the exact symptoms I've hit — and the fixes that actually worked.

🔴

Symptom: Claude ignores your rules entirely

Cause: CLAUDE.md is too long (>200 lines)

Fix: Prune ruthlessly. Remove anything Claude knows by default. Move docs to docs/. Move workflows to Skills. Target 80–120 lines.

🟡

Symptom: Claude asks questions already answered in CLAUDE.md

Cause: Instructions are phrased as suggestions, not commands

Fix: Rewrite ambiguous lines as direct commands. "You should use named exports" → "Use named exports. Never use default exports."

🟡

Symptom: Claude uses wrong build/test commands

Cause: Commands section is missing or the commands are stale

Fix: Add a Commands section with exact, copy-paste commands. Update it every time your scripts change.

🔴

Symptom: Claude modifies files it shouldn't

Cause: No architecture constraints defined

Fix: Add NEVER rules in caps. "NEVER edit /prisma/migrations/ directly." The capitalization genuinely improves compliance.

🟡

Symptom: Claude's code style doesn't match yours

Cause: Style rules are too vague

Fix: Replace vague rules with concrete DO/DON'T examples in the code style section. Show the actual pattern you want.

🟢

Symptom: Sessions start noticeably slow to get productive

Cause: CLAUDE.md is loading too much context

Fix: Move heavy documentation to Skills (invoked on demand). Keep CLAUDE.md under 5,000 tokens.

🟡

Symptom: Claude gets worse (sloppier) mid-session

Cause: Context window bloat — your CLAUDE.md is competing with growing conversation

Fix: Run /compact periodically. Keep CLAUDE.md lean so it stays dominant. Put standing instructions in the highest-priority position (early in the file).

7. Before & After — Real Token Savings

I tracked my actual Claude Code usage across two projects before and after adding a proper CLAUDE.md. The results were more dramatic than I expected.

Example 1: React / Next.js Project

❌ Before (No CLAUDE.md)

  • • 15 messages per session just to set up context
  • • ~3,000 tokens per setup conversation
  • • 15 sessions/week = ~45,000 wasted tokens/week
  • • Claude used wrong test runner 40% of the time
  • • Default exports on every component

✅ After (35-line CLAUDE.md)

  • • 0 setup messages — productive from message 1
  • • CLAUDE.md costs ~900 tokens per session
  • • 15 sessions/week = 13,500 tokens on context
  • • Correct commands every time
  • • Named exports consistently applied

~70% reduction in context tokens. Sessions start productive immediately.

Example 2: Monorepo Project

❌ Before (400-line CLAUDE.md)

  • • Full API docs embedded in CLAUDE.md
  • • ~12,000 tokens per session just for the file
  • • Claude followed only ~40% of the rules
  • • Architecture rules ignored half the time
  • • Slow session starts, frequent /compact needed

✅ After (80-line CLAUDE.md + Skills)

  • • Core rules in CLAUDE.md (~2,400 tokens)
  • • API docs moved to docs/API.md (Skill-loaded)
  • • Release workflow moved to a Skill
  • • Rule compliance improved to ~85%
  • • Sessions faster, less /compact needed

80% fewer context tokens AND better rule compliance.

💡
The counterintuitive lesson: A bigger CLAUDE.md doesn't give Claude more guidance — it gives Claude more to ignore. The sweet spot is a lean file that covers exactly what Claude gets wrong without instruction. Everything else belongs elsewhere.

8. Advanced: Dynamic CLAUDE.md with /init

If you're setting up CLAUDE.md for the first time, don't start from scratch. Run /init inside Claude Code at your project root. Claude will scan your project and automatically detect your build system, test framework, code patterns, key dependencies, and file structure. The result is a generated starter CLAUDE.md that takes about 30 seconds instead of 30 minutes.

What /init detects: package manager (npm/pnpm/yarn), test runner (Jest/Vitest/pytest), framework version, CI configuration, linting setup, and common code patterns across your files. It's not perfect — it won't know your architecture constraints or your current focus — but it gives you 60% of a solid CLAUDE.md instantly.

After running /init: treat the output as a first draft. Read every line. Prune what Claude already knows. Add your architecture rules, NEVER constraints, and current focus. The generated file tends to be verbose — your job is to cut it down to what genuinely changes Claude's behavior.

For ongoing maintenance, I've built a simple habit: every two weeks, I paste my current CLAUDE.md into a session and ask: "Review my CLAUDE.md. Flag anything outdated, ambiguous, or redundant. Suggest what to remove and what's missing." Claude is genuinely good at this — it spots rules it's been silently ignoring and conventions that have drifted.

/init workflow

# 1. Generate starter
/init

# 2. Review what was generated
# Claude opens the file for you to inspect

# 3. Prune aggressively
# Remove anything Claude knows by default
# Remove anything you haven't needed to correct

# 4. Add your specifics
# Architecture constraints, NEVER rules, current focus

# 5. Periodic review (every 2 weeks)
# "Review my CLAUDE.md and suggest improvements"
# Ask Claude to flag: outdated commands, ambiguous rules,
# things it's been correcting without being asked

9. Common Mistakes That Make Claude Ignore Your Rules

I've made all of these. They're not obvious until you understand how Claude actually processes the file — which is why most guides don't cover them.

❌ Don't

Writing a comprehensive project manual

✅ Do

Document only what Claude gets wrong without explicit instruction

If Claude already handles it correctly, the rule wastes a precious instruction slot. Every line should earn its place.

❌ Don't

"Never use --foo-bar flag" (negative-only)

✅ Do

"Never use --foo-bar; use --baz instead" (give the alternative)

Negative-only rules leave Claude guessing. Always pair a prohibition with the correct alternative — it's more efficient and more effective.

❌ Don't

Auto-generating with /init and never editing

✅ Do

Treat CLAUDE.md like code: review, prune, test, iterate

The generated file is a starting point. Left unedited, it's usually 2–3x longer than it needs to be and includes rules Claude already follows.

❌ Don't

Duplicating your linter or formatter rules in CLAUDE.md

✅ Do

Use hooks for formatting enforcement, CLAUDE.md for judgment calls

If ESLint catches it, CLAUDE.md doesn't need to say it. Reserve CLAUDE.md for things that require Claude's judgment, not mechanical rules.

❌ Don't

One massive CLAUDE.md for the entire monorepo

✅ Do

Per-package CLAUDE.md files that cascade from the root

A 500-line CLAUDE.md for a 10-package monorepo is almost useless. Scope rules to the packages where they apply.

❌ Don't

Writing instructions Claude already follows by default

✅ Do

Add a rule only after Claude has gotten something wrong at least twice

This is the most common bloat source. Claude is already trained on best practices for most stacks — you don't need to re-teach them.

❌ Don't

Adding more emphasis when Claude ignores a rule

✅ Do

Prune the file — the rule is being crowded out, not overlooked

The instinct is to bold the text or add IMPORTANT: prefix. The real fix is removing 20 other rules so this one has room to land.

⚡ TL;DR — CLAUDE.md Cheatsheet

01

Start with /init — then prune ruthlessly to under 200 lines / 5,000 tokens

02

7 sections: overview · stack · commands · style · constraints · structure · TODOs

03

Move API docs to docs/ — move workflows to Skills — move enforcement to Hooks

04

NEVER rules in caps improve compliance — always pair with the correct alternative

05

A lean 80-line CLAUDE.md outperforms a bloated 400-line one, every time

06

Review every 2 weeks: "Claude, review my CLAUDE.md and suggest improvements"

07

If Claude ignores a rule — cut the file, don't add emphasis

08

Commit project CLAUDE.md to Git — your team deserves consistent Claude behavior

10. Frequently Asked Questions

What exactly is CLAUDE.md?
CLAUDE.md is a configuration file that Claude Code reads automatically at the start of every session. It's your project's onboarding document for Claude — telling it your tech stack, coding conventions, important commands, and architectural rules. Think of it as a README, except written for an AI collaborator rather than a human developer. Without it, every session starts with zero context. With it, Claude follows your conventions from the very first message, runs the right commands, and avoids the mistakes it would otherwise make by default.
Where should I put CLAUDE.md?
Three locations are supported: the global ~/.claude/CLAUDE.md (applies to all your projects), your project root CLAUDE.md (the most common — commit this to git), and subdirectory CLAUDE.md files for directory-level scoping (especially useful in monorepos). All are loaded and cascade together. Use the global file for personal preferences like your preferred response format or language. Use the project root for everything project-specific. Add per-directory files in monorepos to scope rules to specific packages.
How long should CLAUDE.md be?
Keep it under 200 lines or roughly 5,000 tokens. LLMs can reliably follow about 150–200 total instructions, but Claude Code's system prompt already uses around 50 of those slots. That gives you roughly 100–150 instruction slots before compliance quality degrades. In practice, I've found that 80–120 lines hits the sweet spot — comprehensive enough to cover the real edge cases, lean enough that Claude actually follows all of it. A 400-line CLAUDE.md is almost always worse than an 80-line one.
Does CLAUDE.md work with other AI coding tools?
Yes. Most modern AI coding tools support similar configuration files. Cursor, Zed, and OpenCode use AGENTS.md — same concept, different filename. The content is essentially identical: you may just need to rename the file (or in some cases, tools support both filenames). The principles in this guide — lean files, direct commands, architecture constraints, regular pruning — apply universally regardless of which AI coding tool you're using.
How do I generate a CLAUDE.md automatically?
Run /init inside Claude Code at your project root. Claude will scan your project structure and auto-generate a starter CLAUDE.md based on what it detects — your package manager, test framework, build system, and common code patterns. It typically saves 30 minutes of manual setup. Treat it as a first draft: prune anything Claude already follows by default, add your architecture constraints and NEVER rules, and update the current focus section to reflect what you're actually working on.
What's the difference between CLAUDE.md and Skills?
CLAUDE.md is always-on context — it's loaded automatically every session. Skills are on-demand: you invoke them with a slash command when you need a specific workflow. Put things Claude needs in every session (stack, commands, style rules, architecture constraints) in CLAUDE.md. Put complex multi-step workflows — like your release process, data migration procedure, or onboarding checklist — in Skills. The combination keeps CLAUDE.md lean while still giving Claude access to deep workflow knowledge when needed.
Should I commit CLAUDE.md to Git?
Yes, for your project root CLAUDE.md. It's team documentation — every developer on the project who uses Claude Code benefits from the same established conventions. Treat it like .editorconfig or .eslintrc: it belongs in version control, it should be reviewed in PRs, and it should evolve with the project. The only exception is your personal ~/.claude/CLAUDE.md — that lives on your machine and shouldn't be committed anywhere.
How often should I update CLAUDE.md?
Every two to four weeks, or after any significant stack change. The practical habit I've settled into: at the start of a new session, occasionally ask Claude to review the CLAUDE.md and suggest improvements. Claude is good at spotting outdated commands, ambiguous rules, and conventions it's been correcting silently without being asked. It takes about five minutes and consistently pays for itself with the next few sessions.
Does CLAUDE.md use up tokens?
Yes — CLAUDE.md is injected into your context window every session. A 5,000-token CLAUDE.md costs 5,000 input tokens per session. However, a well-written CLAUDE.md typically replaces 10–15 setup messages per session, which would cost significantly more. The net effect for most developers is a substantial token saving — particularly if you have multiple sessions per day. Keep it lean (under 5,000 tokens) and it easily pays for itself.
What if Claude keeps ignoring my CLAUDE.md rules?
The most common cause is a file that's too long. When CLAUDE.md exceeds 200 lines, Claude begins deprioritizing rules as the context window fills. The fix is to prune, not to emphasize — adding bold text or IMPORTANT: prefixes doesn't help if the file is already too long. Remove anything Claude follows by default. Move documentation to docs/. Move workflows to Skills. If the file is a reasonable length and a specific rule is still being ignored, the problem is usually ambiguous phrasing — rewrite it as a direct, unambiguous command.

Related Guides

G
Garry
Developer & Founder, ToolStackHub · Using Claude Code daily since launch