Back to List

The Complete CLAUDE.md Guide: The Most Important File for Getting Great Results from Claude Code

2026-03-03·20 min read·AITutorial

Introduction

If Claude Code were a new hire on your team, CLAUDE.md would be the employee handbook you hand them on day one. It tells Claude what your project is, how you work, what conventions to follow, and what mistakes to avoid.

In the settings.json Guide, I explained: CLAUDE.md tells Claude "what to do," settings.json tells Claude "how to do it." But here's the thing — settings.json controls permissions, hooks, and model selection. CLAUDE.md controls everything else: your coding standards, architecture decisions, build commands, workflow conventions, and project-specific gotchas.

Of all the configuration files Claude Code reads, CLAUDE.md has the highest impact on output quality. A well-written CLAUDE.md turns Claude from a generic coding assistant into a teammate who understands your project. A poorly written one (or none at all) means you'll spend every conversation re-explaining the same context.

This post covers CLAUDE.md thoroughly — from the five-level file hierarchy to real-world examples, from writing principles to anti-patterns, from the memory system to advanced team patterns.


1. What is CLAUDE.md

1.1 One-Line Definition

CLAUDE.md is a Markdown instruction file that Claude Code automatically reads at startup and injects into its system prompt, giving Claude persistent context about your project, conventions, and workflow.

Every time you start a conversation, Claude Code scans for CLAUDE.md files at multiple levels, merges them, and loads the result into context. You write it once, and it works for every conversation — no more repeating "I'm using Next.js 16 with App Router" or "commit messages should be in English."

Think of it as:

  • An onboarding document for your AI teammate
  • Your project's "constitution"
  • An executable coding standard that Claude actually follows

1.2 How It Differs from Other Config Files

Claude Code has four types of configuration files, each with a distinct role:

FileFormatPurposeAnalogy
CLAUDE.mdMarkdownProject knowledge, coding standards, workflow instructionsEmployee handbook
settings.jsonJSONPermissions, hooks, MCP servers, model, environment variablesSecurity policy + IT config
.claude/commands/MarkdownReusable prompt templates (slash commands)SOP documents
.claudeignoreGitignore syntaxExclude files/directories from Claude's viewSecurity fence

A common mistake is stuffing everything into one file. The division is straightforward:

  • Natural language instructions → CLAUDE.md
  • Structured configuration (permissions, hooks, env vars) → settings.json
  • Reusable prompts you trigger manually → .claude/commands/
  • Files Claude should never see.claudeignore

If you find yourself writing JSON config blocks in CLAUDE.md, that content belongs in settings.json. If you find yourself writing prose instructions in settings.json, that belongs in CLAUDE.md.


2. File Hierarchy and Loading Order

2.1 The Five Levels

CLAUDE.md has five levels, from highest to lowest priority:

① Enterprise (highest priority, managed by IT)
   ~/.claude/enterprise/CLAUDE.md

② User-level (personal preferences, all projects)
   ~/.claude/CLAUDE.md

③ Project root (main project file, committed to Git)
   ./CLAUDE.md

④ Subdirectory (context-specific, loaded when working in that directory)
   ./src/CLAUDE.md
   ./packages/api/CLAUDE.md

⑤ Project user-specific (personal notes for this project)
   ~/.claude/projects/<project-hash>/CLAUDE.md

The three most commonly used are: User-level (personal preferences), Project root (team-shared), and Subdirectory (module-specific).

2.2 When to Use Each Level

LevelLocationCommitted to Git?Use CaseExample Content
Enterprise~/.claude/enterprise/CLAUDE.mdN/A (managed by IT)Company-wide coding standards"All code must pass security review"
User-level~/.claude/CLAUDE.mdNoPersonal preferences across all projects"Respond in English," "Use vim keybindings"
Project root./CLAUDE.mdYesMain project context, team conventionsTech stack, build commands, architecture
Subdirectory./src/CLAUDE.mdYesModule-specific rules"Components in this folder use PascalCase"
Project user-specific~/.claude/projects/<hash>/CLAUDE.mdNoPersonal notes for this specific project"The auth module is flaky, always run tests twice"

2.3 How Merging Works

Claude Code loads all applicable CLAUDE.md files and concatenates them into a single context block. This is different from settings.json's deep merge — CLAUDE.md files are simply appended together.

The loading order:

1. Enterprise CLAUDE.md (if exists)
2. User-level ~/.claude/CLAUDE.md (if exists)
3. Project root ./CLAUDE.md (if exists)
4. Subdirectory CLAUDE.md files (from root to current working directory)
5. Project user-specific CLAUDE.md (if exists)

When instructions conflict, later-loaded content takes priority because it appears closer to the end of the context. In practice:

Enterprise rules    → Cannot be overridden (enforced by the system)
User preferences    → Overridden by project rules
Project rules       → Overridden by subdirectory rules
Subdirectory rules  → Most specific, highest effective priority
Project user notes  → Personal overrides for this project

2.4 Visualizing the Hierarchy

Here's how it looks for a developer named Alice working on a monorepo:

~/.claude/enterprise/CLAUDE.md     "All commits must reference a Jira ticket"
         │
~/.claude/CLAUDE.md                "Respond in English, use conventional commits"
         │
project/CLAUDE.md                  "Next.js 16, pnpm, Turborepo monorepo"
         │
    ├── packages/web/CLAUDE.md     "React Server Components preferred"
    │
    ├── packages/api/CLAUDE.md     "Express + Prisma, REST conventions"
    │
    └── packages/shared/CLAUDE.md  "Pure TypeScript, no framework deps"
         │
~/.claude/projects/<hash>/CLAUDE.md  "Alice's personal notes: API team uses port 3001"

When Alice works in packages/api/, Claude sees the merged result of: Enterprise + User + Project root + packages/api/CLAUDE.md + Project user-specific. When she switches to packages/web/, the subdirectory context swaps automatically.


3. What to Include (The High-Value Content)

Not all content is equally useful in CLAUDE.md. Some instructions dramatically improve Claude's output; others waste tokens. This section covers the high-value categories, ranked by impact.

3.1 Build, Test, and Lint Commands (Highest Value)

This is the single most impactful thing you can put in CLAUDE.md. Claude needs to know how to verify its own work — run tests, check types, lint code. Without these commands, Claude either guesses (often wrong) or skips verification entirely.

## Commands
- Build: `npm run build`
- Test all: `npm test`
- Test single file: `npm test -- --run path/to/file.test.ts`
- Test single case: `npm test -- --run -t "test name"`
- Lint: `npx eslint . --ext .ts,.tsx`
- Type check: `npx tsc --noEmit`
- Format: `npx prettier --write .`

Why this matters: when Claude writes code and then runs npm test, it can catch its own mistakes and fix them in the same conversation. Without the test command, it writes code blindly.

Pro tip: Include the single-test command. Claude often needs to run just one test file, and the syntax varies wildly between test frameworks (jest, vitest, pytest, go test, etc.).

3.2 Code Style and Conventions

Only include conventions that differ from what Claude would assume by default. Claude already knows standard TypeScript conventions, PEP 8, Go formatting, etc. Focus on your project's unique rules.

## Code Style
- Use named exports, not default exports
- Prefer `interface` over `type` for object shapes
- Component files: PascalCase (e.g., `UserProfile.tsx`)
- Utility files: camelCase (e.g., `formatDate.ts`)
- All React components must have explicit return types
- Use `const` arrow functions for components, not `function` declarations
- CSS: use Tailwind utility classes, never write custom CSS unless absolutely necessary

What NOT to include:

# Bad — Claude already knows these
- Use meaningful variable names
- Add comments to complex code
- Follow DRY principles
- Use TypeScript for type safety

3.3 Architecture Overview

Keep this brief. Claude can read your code — it doesn't need a 200-line architecture document. Focus on the non-obvious structural decisions.

## Architecture
- App Router (Next.js 16): all routes under `app/[locale]/`
- Server Components by default, `'use client'` only when interaction is needed
- Data fetching: Server Components fetch directly, no client-side fetching
- State management: URL search params for shareable state, React context for UI-only state
- i18n: next-intl with `[locale]` dynamic segment, messages in `messages/*.json`

Compare this to a bad version:

# Bad — too much detail Claude doesn't need
## Architecture
The application uses Next.js 16 with the App Router pattern. The App Router was
introduced in Next.js 13 and has since become the recommended approach. It uses
React Server Components under the hood, which means components are rendered on
the server by default. This is different from the Pages Router which...
(continues for 50 more lines)

3.4 Important Warnings and Gotchas

These are the "don't touch the hot stove" instructions. They prevent Claude from making mistakes that are hard to debug.

## Warnings
- DO NOT modify `middleware.ts` — it contains next-intl routing config that breaks easily
- DO NOT use `useState`/`useEffect` in Server Components — causes hydration errors
- The `Locale` type is exported from `i18n/routing.ts` — always use it instead of `string`
- Tailwind v4 has NO `tailwind.config.js` — configuration is done in CSS with `@import "tailwindcss"`
- The `getSiteUrl()` function in `lib/env.ts` handles all URL construction — never hardcode URLs

These high-signal warnings save entire debugging sessions. Without the Tailwind v4 note, Claude might generate a tailwind.config.js file and wonder why nothing works.

3.5 Git and Workflow Conventions

## Git Conventions
- Commit messages: `type: description` (e.g., `feat: add user profile page`)
- Types: feat, fix, refactor, chore, docs, test, style
- Branch naming: `type/short-description` (e.g., `feat/user-profile`)
- Always create a new branch for features, never commit directly to main
- Do not auto-push — wait for my confirmation
- Do not amend commits unless explicitly asked

3.6 Testing Conventions

## Testing
- Framework: Vitest
- Test files: colocated as `*.test.ts` next to source files
- Mocking: use `vi.mock()` for module mocks, `vi.fn()` for function mocks
- Coverage: all utility functions in `lib/` must have tests
- Run tests after every code change to verify nothing broke
- When fixing a bug, write a regression test first

3.7 Tech Stack Summary

A concise list of your stack with version numbers. This is especially important when versions have breaking differences (like Tailwind v3 vs v4, or Next.js Pages Router vs App Router).

## Tech Stack
- Next.js 16.1 (App Router)
- TypeScript 5.7 (strict mode)
- Tailwind CSS v4 + @tailwindcss/typography
- next-intl for i18n (locales: zh, en)
- MDX via next-mdx-remote/rsc
- Vitest for testing
- pnpm as package manager

3.8 Content Priority Summary

CategoryImpactWhy
Build/test/lint commandsHighestClaude can self-verify its work
Warnings and gotchasVery HighPrevents hard-to-debug mistakes
Code style conventionsHighOnly non-obvious, project-specific rules
Tech stack with versionsHighPrevents version-mismatch errors
Architecture overviewMediumBrief context, Claude reads code for details
Git/workflow conventionsMediumConsistency across conversations
Testing conventionsMediumCorrect test patterns from the start

4. Writing Principles

4.1 Be Concise and Direct (Imperative Mood)

CLAUDE.md is instructions, not documentation. Use imperative mood — "do X" not "we usually do X."

BadGood
Our team generally prefers to use named exportsUse named exports. No default exports.
It would be nice if functions were kept shortFunctions must not exceed 50 lines.
We typically write tests for new featuresWrite tests for all new functions. Run npm test to verify.
The project uses ESM module formatUse ESM modules. Do not use CommonJS require().

Every sentence should be something Claude can act on. If it's not actionable, it probably doesn't belong in CLAUDE.md.

4.2 Prioritize High-Signal Information

Put the most important instructions first. Claude's attention is strongest at the beginning of the context. Structure your CLAUDE.md like an inverted pyramid:

## Commands              ← Seen first, used most often
## Warnings              ← Critical guardrails
## Code Style            ← Daily constraints
## Architecture          ← Reference when needed
## Git Conventions       ← Used at commit time
## Testing               ← Used when writing/running tests

If your CLAUDE.md is long, the instructions at the top get more weight than those at the bottom.

4.3 Don't Repeat What's in the Code

Claude can read your package.json, tsconfig.json, .eslintrc, and every other config file. Don't duplicate that information.

Don't WriteWhy
"Dependencies include react, next, tailwindcss..."Claude reads package.json
"TypeScript is configured with strict mode..."Claude reads tsconfig.json
"ESLint rules include no-unused-vars..."Claude reads .eslintrc
"The project has 47 components in the components/ folder..."Claude can list the directory

Instead, write things Claude cannot infer:

# Good — Claude can't infer these from config files
- When adding a new route, also update `app/sitemap.ts` and `app/feed.xml/route.ts`
- The `Locale` type must be used instead of `string` for all locale parameters
- CSS variables are defined in `globals.css` — never hardcode color values

4.4 Update Incrementally with /memory

You don't need to write the perfect CLAUDE.md on day one. Start small and grow it over time:

  1. Start with build/test commands and tech stack
  2. When Claude makes a mistake, add a rule to prevent it
  3. When you find yourself repeating an instruction, add it to CLAUDE.md
  4. When a rule never triggers, remove it

The /memory command is your friend here — it appends notes to your project user-specific CLAUDE.md during a conversation. More on this in Section 7.

4.5 Check It into Version Control

Your project root CLAUDE.md should be committed to Git:

git add CLAUDE.md
git commit -m "chore: add CLAUDE.md for AI-assisted development"

This way every team member loads the same conventions when using Claude Code. Review CLAUDE.md changes in pull requests — they're as important as your linter config.

What should NOT be committed:

  • ~/.claude/CLAUDE.md (personal, lives outside the repo)
  • ~/.claude/projects/<hash>/CLAUDE.md (personal project notes)
  • Anything containing secrets, tokens, or personal paths

4.6 Use Subdirectory CLAUDE.md for Monorepos

In monorepos or large projects, a single root CLAUDE.md gets unwieldy. Split context into subdirectories:

monorepo/
  CLAUDE.md                    ← Shared: Git conventions, CI commands, monorepo structure
  packages/
    web/CLAUDE.md              ← Frontend: React patterns, component conventions
    api/CLAUDE.md              ← Backend: API design, database conventions
    shared/CLAUDE.md           ← Shared lib: pure TypeScript, no framework deps

Claude only loads subdirectory CLAUDE.md files when working in that directory, so this keeps context focused and token-efficient.

4.7 Keep It Under ~500 Lines

CLAUDE.md consumes context window space. Every token spent on CLAUDE.md is a token not available for your actual conversation. Guidelines:

FileRecommended Length
Project root CLAUDE.md50–150 lines
Subdirectory CLAUDE.md20–50 lines
User-level ~/.claude/CLAUDE.md10–30 lines
Total merged resultUnder 500 lines

If your CLAUDE.md exceeds 500 lines, it's time to split into subdirectories or trim low-value content.


5. Anti-Patterns (What NOT to Do)

Knowing what to avoid is just as important as knowing what to include. These are the most common CLAUDE.md mistakes.

5.1 The Anti-Pattern Table

Anti-PatternProblemFix
Writing a novel (2000+ lines)Wastes tokens, dilutes important infoKeep under 500 lines total, split into subdirectories
Stating the obvious"Use TypeScript" when the project is already TSOnly include non-obvious, project-specific rules
Contradicting yourself"Use named exports" in one section, "use default exports" in anotherReview for consistency, single source of truth
Including secretsAPI keys, tokens, passwords in CLAUDE.mdUse settings.json env field or .env files
Micromanaging formatting"Use 2-space indentation, semicolons at end of lines..."Let your linter/formatter handle this (Prettier, ESLint)
Using it as documentationLong explanations of how the code worksCLAUDE.md is instructions for Claude, not a README
Dynamic/frequently-changing info"Current sprint: Sprint 47, deadline March 15"Use chat or /memory for ephemeral context
Duplicating config filesCopying tsconfig.json settings into CLAUDE.mdClaude reads config files directly

5.2 Don't Write a Novel

This is the most common mistake. A 2000-line CLAUDE.md doesn't make Claude smarter — it makes Claude slower and less focused.

# Bad — 2000 lines of this
## Architecture
The application follows a layered architecture pattern inspired by
Domain-Driven Design (DDD). In DDD, the domain layer represents the
core business logic and is independent of infrastructure concerns.
The application layer orchestrates use cases by coordinating between
the domain and infrastructure layers. The infrastructure layer handles
external concerns such as database access, API calls, and file system
operations. This separation of concerns allows us to...
(continues for 200 more lines)
# Good — 5 lines that actually help
## Architecture
- Clean Architecture: data → domain → presentation
- Domain layer: pure Dart, no external package imports
- Repository pattern: domain defines interfaces, data implements
- State: Riverpod exclusively (no setState, no Provider)

Claude can read your code to understand the details. CLAUDE.md just needs to point it in the right direction.

5.3 Don't Include Obvious Things

If your project is a TypeScript project with a tsconfig.json, Claude already knows you're using TypeScript. Don't waste tokens stating it.

# Bad — Claude already knows all of this
- This project uses TypeScript
- We use React for the frontend
- npm is our package manager
- Git is used for version control
# Good — things Claude can't infer
- TypeScript strict mode: all functions must have explicit return types
- React Server Components by default, 'use client' only for interactivity
- pnpm (not npm) — always use pnpm for install/run commands
- Git: conventional commits, never push directly to main

The difference: the "good" version tells Claude things that change its behavior. The "bad" version tells Claude things it already figured out from reading the codebase.

5.4 Don't Contradict Yourself

In a long CLAUDE.md, it's easy to write conflicting instructions. Claude will follow whichever instruction it sees last (or whichever seems more specific), leading to inconsistent behavior.

# Bad — contradictory
## Code Style
- Use default exports for all components
 
## Component Conventions
- Always use named exports

Review your CLAUDE.md periodically for contradictions. A good test: could a new team member follow all the instructions without confusion?

5.5 Don't Include Secrets

CLAUDE.md is committed to Git. Never put sensitive information in it.

# Bad — secrets in CLAUDE.md
## API Configuration
- API key: sk-1234567890abcdef
- Database URL: postgres://user:password@host:5432/db
- JWT secret: my-super-secret-key

Instead, use environment variables via settings.json:

// .claude/settings.local.json (not committed to Git)
{
  "env": {
    "API_KEY": "sk-1234567890abcdef",
    "DATABASE_URL": "postgres://user:password@host:5432/db"
  }
}

5.6 Don't Micromanage Formatting

If you have Prettier, ESLint, or any other formatter configured, let them handle formatting. Don't duplicate those rules in CLAUDE.md.

# Bad — let Prettier handle this
- Use 2-space indentation
- Always use semicolons
- Use single quotes for strings
- Max line length: 100 characters
- Trailing commas in multi-line objects
# Good — tell Claude to use the formatter
- Run `npx prettier --write .` after making changes
- All code must pass `npx eslint .` before committing

Even better: configure a PostToolUse hook in settings.json to auto-format after every file write.


6. CLAUDE.md vs the Memory System

6.1 How Memory Works

Claude Code has a built-in memory system that complements CLAUDE.md. Understanding the relationship between them is key to using both effectively.

The /memory command saves notes to your project user-specific CLAUDE.md:

~/.claude/projects/<project-hash>/CLAUDE.md

This file is:

  • Not committed to Git (it lives outside your project)
  • Specific to this project (the path includes a hash of your project directory)
  • Personal (only you see it, not your teammates)
  • Persistent (survives across conversations)

6.2 The /memory Command

During a conversation, you can tell Claude to remember something:

You: /memory
Claude: What would you like me to remember?
You: The auth module tests are flaky on CI — always run them twice to confirm failures
Claude: I've saved that to your project memory.

Or Claude may automatically suggest saving something to memory when it discovers important project context during a conversation.

What gets saved goes into ~/.claude/projects/<hash>/CLAUDE.md:

# Project Memory
 
- The auth module tests are flaky on CI — always run them twice to confirm failures
- Port 3001 is used by the API server in development
- The legacy payment module uses CommonJS (exception to the ESM rule)

6.3 Memory vs CLAUDE.md vs Chat

Three ways to give Claude context, each with different scope and persistence:

MethodScopePersistenceShared with Team?Best For
Chat instructionsCurrent conversation onlyGone when conversation endsNoOne-off instructions, temporary context
/memory (project user-specific)This project, all conversationsPersistent across conversationsNoPersonal notes, local environment quirks
Project CLAUDE.mdThis project, all conversationsPersistent, version-controlledYesTeam conventions, project standards
User-level CLAUDE.mdAll projects, all conversationsPersistentNoPersonal preferences (language, style)

6.4 Priority Order

When instructions conflict, the priority order is:

Chat instructions (highest — explicit in-conversation overrides)
    ↓
Project user-specific memory (~/.claude/projects/<hash>/CLAUDE.md)
    ↓
Subdirectory CLAUDE.md (./src/CLAUDE.md)
    ↓
Project root CLAUDE.md (./CLAUDE.md)
    ↓
User-level CLAUDE.md (~/.claude/CLAUDE.md)
    ↓
Enterprise CLAUDE.md (lowest for regular instructions)

This means if you say "use tabs" in chat but your CLAUDE.md says "use spaces," Claude will use tabs for that conversation. The chat instruction wins because it's the most recent and most specific.

6.5 When to Use Each

SituationUse
"Always respond in English"User-level ~/.claude/CLAUDE.md
"This project uses pnpm, not npm"Project root CLAUDE.md
"Components in this folder use Storybook"Subdirectory CLAUDE.md
"I discovered the API rate limits at 100 req/min"/memory command
"For this task, skip the tests"Chat instruction
"All code must pass security review"Enterprise CLAUDE.md

A good rule of thumb: if the information is useful to your team, put it in the project CLAUDE.md. If it's useful to you personally, use /memory. If it's only relevant right now, say it in chat.


7. Real-World Walkthrough: Complete Next.js Monorepo

Let's build a complete multi-layer CLAUDE.md setup for a realistic project: a Next.js monorepo with a web app, an API server, and a shared library.

7.1 Project Context

  • Monorepo managed by Turborepo + pnpm workspaces
  • packages/web: Next.js 16 frontend (App Router, Tailwind v4, next-intl)
  • packages/api: Express + Prisma REST API
  • packages/shared: Pure TypeScript utility library
  • Team of 4 developers, GitHub for collaboration
  • CI/CD via GitHub Actions

7.2 Project Root CLAUDE.md (~60 lines, team-shared)

# E-Commerce Platform
 
## Tech Stack
- Monorepo: Turborepo + pnpm workspaces
- Language: TypeScript 5.7 (strict mode across all packages)
- CI: GitHub Actions (runs on every PR)
 
## Commands
- Install deps: `pnpm install` (never use npm or yarn)
- Build all: `pnpm run build`
- Test all: `pnpm run test`
- Test single package: `pnpm --filter <package> test`
- Lint all: `pnpm run lint`
- Type check all: `pnpm run typecheck`
- Format: `pnpm run format`
 
## Monorepo Structure
- packages/web — Next.js 16 frontend
- packages/api — Express REST API
- packages/shared — Shared TypeScript utilities and types
 
## Git Conventions
- Commit format: `type(scope): description` (e.g., `feat(web): add product page`)
- Scopes: web, api, shared, ci, root
- Branch naming: `type/scope/short-description`
- Always create PR, never push directly to main
- PRs require 1 approval and passing CI
 
## Code Standards (All Packages)
- Named exports only, no default exports
- Explicit return types on all exported functions
- No `any` type — use `unknown` and narrow
- Error handling: never swallow errors silently, always log or rethrow
 
## Warnings
- DO NOT modify `turbo.json` pipeline config without team discussion
- DO NOT add dependencies to root package.json (add to specific packages)
- The shared package must have zero external dependencies
- pnpm-lock.yaml must be committed — never delete or gitignore it

7.3 packages/web/CLAUDE.md (Frontend-specific)

# Web Package (Next.js Frontend)
 
## Tech Stack
- Next.js 16 (App Router) + Tailwind CSS v4
- i18n: next-intl (locales: en, zh; default: en)
- Content: MDX via next-mdx-remote/rsc
 
## Commands
- Dev server: `pnpm --filter web dev` (don't run this for me)
- Build: `pnpm --filter web build`
- Test: `pnpm --filter web test`
- Test single: `pnpm --filter web test -- --run path/to/file.test.ts`
 
## Conventions
- Server Components by default, `'use client'` only for interactivity
- Locale params use `Locale` type from `@shared/types`, not `string`
- Tailwind v4: no tailwind.config.js, config via CSS `@import "tailwindcss"`
- CSS variables in `globals.css` — never hardcode colors
- All images use next/image with explicit width/height
 
## Routing
- All routes under `app/[locale]/`
- Dynamic routes: `app/[locale]/products/[id]/page.tsx`
- API routes: none (use packages/api instead)
 
## Warnings
- DO NOT modify `middleware.ts` (next-intl routing config)
- DO NOT use `useState`/`useEffect` in Server Components
- DO NOT import from `packages/api` — use HTTP calls via shared API client

7.4 packages/api/CLAUDE.md (API-specific)

# API Package (Express + Prisma)
 
## Tech Stack
- Express 5 + TypeScript
- Prisma ORM (PostgreSQL)
- Zod for request validation
- JWT for authentication
 
## Commands
- Dev server: `pnpm --filter api dev` (don't run this for me)
- Build: `pnpm --filter api build`
- Test: `pnpm --filter api test`
- DB migrate: `pnpm --filter api prisma migrate dev`
- DB generate: `pnpm --filter api prisma generate`
- DB seed: `pnpm --filter api prisma db seed`
 
## Conventions
- All routes in `src/routes/` — one file per resource
- Route handlers: thin controllers, business logic in `src/services/`
- All request bodies validated with Zod schemas in `src/schemas/`
- All responses follow `{ success: boolean, data?: T, error?: string }` format
- Error handling: throw `AppError` (from `src/utils/errors.ts`), caught by global middleware
 
## Database
- Prisma schema in `prisma/schema.prisma`
- Migrations committed to Git
- After schema changes: run `prisma migrate dev`, then `prisma generate`
- Never modify existing migrations — create new ones
 
## Warnings
- DO NOT expose Prisma client directly in route handlers — use services
- DO NOT store passwords in plain text — use bcrypt (already configured)
- DO NOT modify the auth middleware in `src/middleware/auth.ts` without review

7.5 User-level ~/.claude/CLAUDE.md (Personal preferences)

## My Preferences
- Respond in English
- Code comments in English
- Git commit messages in English
- Don't auto-push, wait for my confirmation
- Don't auto-commit, show me the diff first
- Prefer concise explanations over verbose ones

7.6 Project User-Specific Memory (Personal notes via /memory)

# Project Memory
 
- The API dev server runs on port 3001, web on port 3000
- Prisma migrations are slow on my machine — give them 30 seconds
- The `products` table has a full-text search index, use `@@fulltext` in queries
- Alice owns the auth module, check with her before modifying
- The staging database URL is in 1Password under "E-Commerce Staging DB"

7.7 The Merged Effective Result

When working in packages/api/, Claude sees all layers merged:

[Enterprise rules, if any]
+
[Personal preferences: English, no auto-push, concise]
+
[Root CLAUDE.md: monorepo structure, Git conventions, shared standards]
+
[packages/api/CLAUDE.md: Express conventions, Prisma rules, API patterns]
+
[Personal memory: port 3001, Prisma slow, Alice owns auth]

The result: Claude knows the monorepo structure, follows team Git conventions, uses Express/Prisma patterns correctly, respects personal preferences, and remembers project-specific quirks — all without you saying a word in chat.


8. Advanced Patterns

8.1 Conditional Instructions

You can write context-dependent instructions that only apply in specific situations. Claude is good at understanding conditional language:

## Testing
- When writing tests, always include both happy path and error cases
- When fixing a bug, write a regression test before writing the fix
- When adding a new API endpoint, add integration tests in `tests/integration/`
- When modifying database schemas, verify migrations with `prisma migrate dev`
 
## Code Review
- When reviewing a PR, check for: type safety, error handling, test coverage
- When the PR touches auth code, flag it for security review

This pattern is more useful than unconditional rules because it gives Claude the right instruction at the right time, without cluttering every interaction.

8.2 Referencing External Docs

CLAUDE.md should be concise, but your project may have detailed documentation elsewhere. Reference it:

## Architecture
- High-level overview: see `docs/architecture.md`
- API design decisions: see `docs/adr/` (Architecture Decision Records)
- Database schema diagram: see `docs/db-schema.png`
- Deployment process: see `docs/deployment.md`

Claude can read these files when it needs the details, keeping your CLAUDE.md lean. This is much better than copying 500 lines of architecture docs into CLAUDE.md.

8.3 Team Onboarding

One of the most underrated benefits of CLAUDE.md: new team members get project context instantly. When a new developer joins and starts using Claude Code, they get the same conventions, commands, and guardrails as everyone else.

This is especially powerful combined with the Custom Slash Commands Guide:

.claude/commands/
  onboard.md          "Explain the project structure and key conventions"
  new-feature.md      "Walk me through creating a new feature module"
  debug-ci.md         "Help me debug a failing CI pipeline"

New team members can run /onboard on day one and get a guided tour of the project, powered by the context in CLAUDE.md.

8.4 CI/CD Integration

Claude Code can run in headless mode for CI/CD pipelines, and it reads CLAUDE.md just like in interactive mode. This means your CLAUDE.md conventions are enforced even in automated workflows.

# In a GitHub Actions workflow
claude --headless --message "Review the changes in this PR for code quality issues"

Claude reads your CLAUDE.md, understands your conventions, and reviews the PR accordingly. You can add CI-specific instructions:

## CI/CD Notes
- In CI, always run the full test suite: `pnpm run test`
- Build must succeed with zero warnings (treat warnings as errors)
- Type check must pass: `pnpm run typecheck`
- Lint must pass: `pnpm run lint`

For CI-specific settings (permissions, model), use the session scope in settings.json:

claude --headless --settings ci-settings.json --message "..."

See the settings.json Guide Section 2 for details on session-level configuration.

8.5 Monorepo Strategies

For large monorepos, a layered CLAUDE.md strategy keeps context focused:

Strategy 1: Feature-based splitting

monorepo/
  CLAUDE.md                         ← Global: Git, CI, shared standards
  features/
    auth/CLAUDE.md                  ← Auth: security patterns, JWT conventions
    payments/CLAUDE.md              ← Payments: Stripe API, idempotency rules
    notifications/CLAUDE.md         ← Notifications: queue patterns, templates

Strategy 2: Layer-based splitting

monorepo/
  CLAUDE.md                         ← Global: Git, CI, shared standards
  src/
    domain/CLAUDE.md                ← Domain: pure business logic, no deps
    application/CLAUDE.md           ← Application: use cases, orchestration
    infrastructure/CLAUDE.md        ← Infrastructure: DB, APIs, external services
    presentation/CLAUDE.md          ← Presentation: React, components, styling

Strategy 3: Package-based splitting (most common)

monorepo/
  CLAUDE.md                         ← Global: Git, CI, monorepo structure
  packages/
    web/CLAUDE.md                   ← Frontend conventions
    api/CLAUDE.md                   ← Backend conventions
    mobile/CLAUDE.md                ← Mobile conventions
    shared/CLAUDE.md                ← Shared library rules

Choose the strategy that matches your project's organizational structure. The key principle: each CLAUDE.md should contain only the context relevant to that directory.

8.6 Version Control Best Practices

Treat CLAUDE.md changes like code changes:

# In your PR template or review checklist:
- [ ] If conventions changed, CLAUDE.md is updated
- [ ] If new tools/commands added, CLAUDE.md reflects them
- [ ] CLAUDE.md changes reviewed by at least one team member

Practical tips:

PracticeWhy
Review CLAUDE.md changes in PRsPrevents contradictions, maintains quality
Update CLAUDE.md when you update linter/formatter configKeeps instructions in sync with tooling
Add CLAUDE.md to your "new project" checklistStart every project with good AI context
Periodically audit CLAUDE.md (monthly)Remove stale rules, add missing ones
Use Git blame on CLAUDE.mdUnderstand why each rule was added

8.7 Using /init for Bootstrap

If you're starting from scratch, Claude Code's /init command generates a CLAUDE.md draft by analyzing your project:

claude
> /init

Claude will scan your package.json, config files, directory structure, and existing code to generate a starting CLAUDE.md. It's not perfect, but it's a solid starting point that you can refine.

After /init, review the generated file and:

  1. Remove obvious/redundant information
  2. Add project-specific warnings and gotchas
  3. Add your team's Git and workflow conventions
  4. Verify the commands are correct

9. Frequently Asked Questions

Q1: How long should my CLAUDE.md be?

The sweet spot for a project root CLAUDE.md is 50–150 lines. Under 50 and you're probably missing important context. Over 200 and you're likely including low-value information that dilutes the important stuff. If you need more, split into subdirectory CLAUDE.md files.

The total merged result across all levels should stay under ~500 lines. Beyond that, you're consuming significant context window space.

Q2: CLAUDE.md or README.md — what's the difference?

README.md is for humans reading your GitHub repo. CLAUDE.md is for Claude Code working in your project. They serve different audiences and should contain different content.

README.mdCLAUDE.md
AudienceHuman developers, usersClaude Code AI
ToneExplanatory, welcomingImperative, concise
ContentWhat the project does, how to install, how to contributeHow to build/test, coding conventions, warnings
LengthAs long as neededUnder 150 lines
FormatNarrative, badges, screenshotsBullet points, commands, rules

Some overlap is natural (both might mention the tech stack), but don't just copy your README into CLAUDE.md.

Q3: Claude doesn't seem to follow my CLAUDE.md instructions. Why?

Common causes:

  1. Instructions too vague — "Write good code" is less effective than "Functions must not exceed 50 lines." Be specific and actionable.
  2. Contradictory rules — Check for conflicting instructions across different sections or CLAUDE.md levels.
  3. Context window pressure — If your CLAUDE.md is very long and the conversation is also long, earlier CLAUDE.md content may get less attention. Put critical rules at the top.
  4. Chat overrides — Explicit instructions in the conversation take priority over CLAUDE.md. If you said something contradictory in chat, that wins.
  5. Wrong file location — Make sure your CLAUDE.md is in the project root (not in a subdirectory) if you want it to always load.

Q4: Should I put CLAUDE.md in .gitignore?

No — the project root CLAUDE.md should be committed to Git so your team shares the same conventions. Files that should NOT be committed:

  • ~/.claude/CLAUDE.md (personal, lives outside repo)
  • ~/.claude/projects/<hash>/CLAUDE.md (personal project notes, lives outside repo)

These are automatically outside your repo, so there's nothing to gitignore.

Q5: How does CLAUDE.md relate to Cursor Rules / Copilot Instructions / Windsurf Rules?

Same concept — project-level instructions for an AI coding assistant. Different tools use different file names and formats:

ToolFileFormat
Claude CodeCLAUDE.mdMarkdown
Cursor.cursor/rules/Markdown
GitHub Copilot.github/copilot-instructions.mdMarkdown
Windsurf.windsurfrulesMarkdown

They're not interchangeable (each tool reads its own file), but the content principles are the same. If you use multiple AI tools, you may need to maintain similar files for each — or create a shared source and copy it.

Q6: Can I use CLAUDE.md to make Claude behave differently for different tasks?

Yes, using conditional instructions (see Section 8.1). Claude understands context-dependent rules:

- When writing tests: use `describe`/`it` blocks, include edge cases
- When refactoring: preserve all existing tests, run full suite after changes
- When reviewing code: focus on type safety, error handling, and performance
- When writing documentation: use JSDoc format, include examples

This is more effective than trying to cover every scenario with unconditional rules.

Q7: How often should I update CLAUDE.md?

Treat it like your linter config — update it when:

  • Claude repeatedly makes the same mistake (add a rule)
  • You add new tools or change build commands (update commands)
  • A rule never seems to matter (remove it)
  • Your tech stack changes (update versions)
  • New team members report confusion (clarify)

A monthly review is a good cadence. Use /memory for quick additions during conversations, then periodically promote important memories to the project CLAUDE.md.

Q8: Does CLAUDE.md work with Claude on the web (claude.ai)?

No. CLAUDE.md is specific to Claude Code (the CLI/IDE tool). Claude on the web (claude.ai) uses Project Knowledge for similar functionality, but it's a different system. CLAUDE.md files are only read by Claude Code when it starts a session in your project directory.


Summary

CLAUDE.md boils down to three things:

  1. High-signal content only — Build/test commands, non-obvious conventions, and critical warnings are the highest-value content. Don't write a novel; write a cheat sheet.
  2. Right level, right content — Use the five-level hierarchy wisely: team conventions in the project root, module-specific rules in subdirectories, personal preferences in user-level, and ephemeral notes in memory.
  3. Iterate like code — Start small, add rules when Claude makes mistakes, remove rules that don't matter, review changes in PRs. A living CLAUDE.md beats a perfect-on-day-one CLAUDE.md.

Spending 30 minutes on a good CLAUDE.md saves you time in every future conversation. It's probably the highest-ROI file in your entire project.


Recommended Reading