Skip to content

CLAUDE.md

Configuring project context, team conventions, and personal preferences with CLAUDE.md files.

CLAUDE.md is the highest-leverage thing you can do for your team’s Claude Code productivity. It gives Claude persistent context about your project — conventions, commands, architecture, and rules — loaded automatically into every conversation.

What CLAUDE.md does

CLAUDE.md is loaded into every Claude Code conversation in your project directory.

Without CLAUDE.md: Claude generates generic code using default conventions.

With CLAUDE.md: Claude generates code that follows your team’s specific patterns.

File hierarchy

Claude reads from multiple levels and merges them. Later levels override earlier ones.

FileScopeIn Git?Purpose
~/.claude/CLAUDE.mdGlobalNoYour preferences across all projects
CLAUDE.mdProjectYesTeam-wide conventions
CLAUDE.local.mdProjectNoPersonal preferences for this project

Global CLAUDE.md: your personal defaults

Your ~/.claude/CLAUDE.md applies to every project. Use it for preferences that are always true about how you work, regardless of which codebase you are in.

Example ~/.claude/CLAUDE.md:

# Personal Preferences

- I prefer concise responses. Skip explanations unless I ask for them.
- When writing tests, always include edge cases for null/empty inputs.
- I use VS Code as my editor.
- I prefer functional programming patterns over OOP when practical.
- Always suggest running tests after making changes.
- When committing, use conventional commit format (feat:, fix:, etc.).
- I prefer TypeScript strict mode and explicit return types.

Project CLAUDE.md: team conventions

Lives at the project root. Contains standards the entire team shares:

  • Tech stack and version constraints
  • Build, test, and lint commands
  • Coding conventions and architectural rules
  • “Do NOT” rules for common mistakes

CLAUDE.local.md: personal overrides

Git-ignored. Your personal preferences for a specific project:

# My Preferences
- Always run tests after making changes
- Keep explanations brief unless I ask for detail
- My local Postgres is at localhost:5433 (not default 5432)
- When writing Java, include SLF4J logging in new classes
- I prefer React components as arrow functions

What to put in CLAUDE.md

Tech stack — be specific about versions

## Tech Stack
- Java 17 (not 21 — we deploy to a Java 17 runtime)
- Spring Boot 3.2.x
- PostgreSQL 15
- React 18 with TypeScript 5.x strict mode
- Redux Toolkit for state management (not plain Redux)

Build and test commands — exact commands

## Build & Test
- Build: `mvn clean package -DskipTests`
- Unit tests: `mvn test`
- Integration tests: `mvn verify -Pintegration`
- Frontend: `cd frontend && npm test`
- Full stack: `docker compose up -d && ./scripts/e2e.sh`
- Lint: `npm run lint` (must pass before commits)

Coding standards — specific and actionable

## Coding Standards
- Use early returns to reduce nesting
- Max 20 lines per method — extract if longer
- Error handling: use Result<T> pattern, never throw from services
- All public API methods need JSDoc with @example
- Use branded types for IDs (UserId, OrderId — not raw strings)
- Prices are always in cents (integer), never dollars (float)

Architecture — where things go

## Architecture
- `src/api/` — Express route handlers, thin layer, validation only
- `src/services/` — business logic, all domain rules live here
- `src/repositories/` — database access, raw SQL, no business logic
- `src/types/` — shared TypeScript types and interfaces
- New features: add route in api/, logic in services/, data access in repositories/
- Never import from api/ into services/ (dependency flows inward)

What NOT to do — hard rules

## Rules
- NEVER use `any` in TypeScript — use `unknown` and narrow
- NEVER use console.log for debugging — use our Logger utility
- NEVER commit .env files or hardcoded secrets
- NEVER modify migration files after they've been deployed
- Do not add new npm dependencies without discussing in #engineering Slack

Testing conventions

## Testing

### Java
- Framework: JUnit 5 with Mockito
- Assertions: AssertJ (not Hamcrest)
- Test naming: methodName_givenCondition_expectedResult
- Always add @DisplayName annotations
- Mock external services, don't use in-memory databases

### TypeScript
- Framework: Jest with React Testing Library
- Query by role/text, not test IDs
- Use userEvent, not fireEvent
- Use waitFor for async assertions

Code review standards

## Code Review

When reviewing code, check for:
1. SQL injection (parameterized queries required)
2. Authentication on all API endpoints
3. Input validation on user-facing endpoints
4. Error handling that doesn't swallow exceptions
5. No hardcoded secrets or credentials

What NOT to put in CLAUDE.md

Don’t IncludeWhy
”Write clean code”Too vague. Say “max 20 lines per method” instead
Entire file contentsWastes context window. Reference files: “See src/types.ts”
Obvious language features”Use TypeScript types” — Claude already knows
Outdated informationWorse than nothing. Review CLAUDE.md in PRs
Personal preferencesPut those in CLAUDE.local.md
Temporary workaroundsThese go stale fast; add an expiry comment if you must
Authentication tokens or secretsNever put credentials in any markdown file

Settings files

Beyond CLAUDE.md, Claude Code uses JSON settings files for permissions and configuration.

.claude/settings.json — team permissions

Committed to git. Shared by the entire team. Controls what Claude can do automatically:

{
  "permissions": {
    "allow": [
      "Bash(npm test *)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(git status)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push *)",
      "Bash(git reset --hard *)"
    ]
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "npx eslint --fix $(cat | jq -r '.tool_input.file_path')" }
        ]
      }
    ]
  }
}

Allow list = things Claude does repeatedly that are safe (test runners, git read commands, linters).

Deny list = things Claude should never do without asking (destructive file operations, pushing to remote, hard resets).

Everything not in allow or deny = Claude asks you each time.

Permission rule syntax

Permission rules support wildcard patterns with * for matching. This lets you pre-approve entire categories of operations:

{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Bash(npm run lint:*)",
      "Bash(npm run build:*)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(git status)",
      "Bash(gh pr list *)",
      "Bash(gh pr diff *)",
      "Bash(gh issue view *)",
      "Read(.env.example)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push --force *)",
      "Bash(git reset --hard *)",
      "Read(.env)",
      "Read(./secrets/**)"
    ]
  }
}
PatternMatches
Bash(npm run *)Any npm run command
Bash(git diff *)git diff with any arguments
Read(./.env)Reading the specific .env file
Read(./secrets/**)Reading any file under secrets/ recursively
WebFetch(domain:example.com)Fetch requests to example.com

Check your current permissions in a session with /permissions. Pre-approve safe commands in .claude/settings.json so the whole team gets a consistent, interruption-free experience.

.claude/settings.local.json — personal overrides

Git-ignored. Your personal overrides for this project:

{
  "permissions": {
    "allow": ["Bash(docker compose *)"]
  },
  "env": {
    "DATABASE_URL": "postgresql://localhost:5432/myapp_dev"
  },
  "mcpServers": {
    "local-db": {
      "command": "npx",
      "args": ["@anthropic-ai/mcp-server-postgres", "postgresql://localhost:5432/myapp_dev"]
    }
  }
}

~/.claude/settings.json — global permissions

Applies to all projects on your machine:

{
  "permissions": {
    "allow": [
      "Bash(git *)",
      "Bash(npm test *)",
      "Bash(npx tsc --noEmit)"
    ]
  }
}

The full configuration hierarchy

Claude Code loads configuration from multiple levels, with later levels overriding earlier ones:

  1. Enterprise managed settings — Set by org admins. Highest priority, cannot be overridden.
  2. Project settings (.claude/settings.json) — Committed to git, shared with team.
  3. Personal project settings (.claude/settings.local.json) — Git-ignored, your overrides.
  4. Project instructions (CLAUDE.md) — Committed to git, team conventions.
  5. Personal project instructions (CLAUDE.local.md) — Git-ignored, your preferences.
  6. Global settings (~/.claude/settings.json) — All projects on your machine.
  7. Global instructions (~/.claude/CLAUDE.md) — Your personal defaults everywhere.

Key principle: Shared settings go in committed files. Personal preferences go in git-ignored files. Security policies go in enterprise settings.

Team-specific settings examples

Java/Kotlin backend team

{
  "permissions": {
    "allow": [
      "Bash(./gradlew test*)",
      "Bash(./gradlew check*)",
      "Bash(./gradlew spotlessCheck*)",
      "Bash(mvn test*)",
      "Bash(mvn verify*)"
    ]
  },
  "env": {
    "JAVA_TOOL_OPTIONS": "-Dfile.encoding=UTF-8",
    "SPRING_PROFILES_ACTIVE": "test"
  }
}

Ruby/Rails team

{
  "permissions": {
    "allow": [
      "Bash(bundle exec rspec*)",
      "Bash(bundle exec rubocop*)",
      "Bash(bundle exec rake test*)",
      "Bash(bundle exec rails routes)"
    ]
  },
  "env": {
    "RAILS_ENV": "test"
  }
}

React/TypeScript frontend team

{
  "permissions": {
    "allow": [
      "Bash(npm test*)",
      "Bash(npx jest*)",
      "Bash(npx tsc --noEmit*)",
      "Bash(npx eslint*)",
      "Bash(npm run lint*)",
      "Bash(npm run build*)"
    ]
  },
  "env": {
    "NODE_ENV": "test",
    "CI": "true"
  }
}

Full-stack team

{
  "permissions": {
    "allow": [
      "Bash(./gradlew test*)",
      "Bash(bundle exec rspec*)",
      "Bash(npm test*)",
      "Bash(npx jest*)",
      "Bash(npx tsc --noEmit*)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git status)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push *)",
      "Bash(git reset --hard *)"
    ]
  }
}

Writing your first CLAUDE.md

Step 1: Ask Claude to draft it

Read all the files in this project and draft a CLAUDE.md that captures:
- The tech stack and versions used
- Build, test, and run commands
- Coding conventions visible in existing code
- Directory structure and architecture
- Any patterns or anti-patterns you notice

Step 2: Refine it yourself

Claude’s draft will be 80% right. You need to add:

  • Things Claude cannot infer (why certain decisions were made)
  • Hard rules (“never do X because of [incident]”)
  • Commands that need environment variables or setup

Step 3: Test it

Use /clear to reset context, then ask Claude to do a task. Compare the output with and without the CLAUDE.md.

Full CLAUDE.md template

Copy and customize this template for your project:

# [Project Name]

## Overview

[2-3 sentences describing what this project does, who uses it, and why it exists.]

## Architecture

[High-level description of the system architecture. Include services, communication
patterns, and data flow. A simple ASCII diagram or link to a diagram is helpful.]

## Tech Stack

- **Language(s)**: [e.g., Java 17, Ruby 3.2, TypeScript 5.x]
- **Frameworks**: [e.g., Spring Boot 3.x, Rails 7.x, React 18, Redux Toolkit]
- **Database**: [e.g., PostgreSQL 15, Redis 7]
- **CI/CD**: [e.g., GitHub Actions]
- **Infrastructure**: [e.g., AWS ECS, Kubernetes]

## Build and Run

### Install dependencies
\`\`\`bash
[exact command, e.g., npm install && bundle install]
\`\`\`

### Run the application locally
\`\`\`bash
[exact command]
\`\`\`

### Run all tests
\`\`\`bash
[exact command, e.g., npm test && bundle exec rspec && mvn test]
\`\`\`

### Run the linter
\`\`\`bash
[exact command]
\`\`\`

### Build for production
\`\`\`bash
[exact command]
\`\`\`

## Code Conventions

### File Organization
- [Describe your directory structure and where different types of files live]
- [Example: "Controllers go in src/controllers/, services in src/services/"]

### Naming Conventions
- [Files: describe your naming pattern, e.g., PascalCase for components, snake_case for Ruby]
- [Classes: describe your pattern]
- [Functions/methods: describe your pattern]
- [Variables: describe your pattern]
- [Database tables: describe your pattern]

### Code Style
- [Describe your formatting rules or reference your linter config]
- [Example: "We use Prettier with the default config for TypeScript"]
- [Example: "We use Rubocop with the .rubocop.yml in the repo root"]

### API Design
- [Describe your REST conventions, URL patterns, response formats]
- [Example: "All API endpoints return JSON with {data: ..., error: ...} structure"]
- [Example: "Use plural nouns for resource URLs: /api/users, /api/activities"]

### Error Handling
- [Describe your error handling patterns]
- [Example: "Use custom exception classes that map to HTTP status codes"]
- [Example: "Always return structured error responses with error code and message"]

## Testing Requirements

### General Rules
- All new code must include tests.
- Minimum test coverage: [your threshold, e.g., 80%].
- Tests must pass before any PR can be merged.

### Test Patterns
- [Describe your testing patterns per layer]
- [Example: "Unit tests mock all external dependencies"]
- [Example: "Integration tests use a test database that is reset between suites"]
- [Example: "Frontend tests use React Testing Library, test behavior not implementation"]

### Test Naming
- [Describe your test naming convention]
- [Example: Java: "should_[expected]_when_[condition]"]
- [Example: Ruby: "it 'does something when condition'"]
- [Example: JS/TS: "it('should do something when condition')"]

## Git and PR Conventions

### Branch Naming
- Features: `feature/[ticket-id]-short-description`
- Bug fixes: `fix/[ticket-id]-short-description`
- Chores: `chore/short-description`

### Commit Messages
- [Describe your commit message format]
- [Example: "Use conventional commits: feat:, fix:, chore:, docs:, test:, refactor:"]

### PR Requirements
- [List your PR requirements]
- [Example: "All PRs require at least one approval"]
- [Example: "PR description must include: what changed, why, how to test"]
- [Example: "All CI checks must pass before merge"]

## Common Pitfalls

- [List things that frequently trip up developers in this codebase]
- [Example: "The user_id column is a UUID string, not an integer. Use string comparison."]
- [Example: "The Redux store is normalized. Always use selectors, never access state directly."]
- [Example: "The background job queue processes in FIFO order. Do not rely on priority."]

## Do NOT

- Do NOT modify migration files that have already been applied to production.
- Do NOT use `any` type in TypeScript. Use `unknown` if the type is truly unknown.
- Do NOT commit `.env` files or hardcode secrets anywhere in the codebase.
- Do NOT skip writing tests for new endpoints or components.
- Do NOT use raw SQL queries. Use the ORM ([ActiveRecord/JPA/Prisma/etc.]).
- Do NOT add new npm dependencies without checking bundle size impact.
- [Add your project-specific rules here]

## Helpful Context

- [Add any other context that helps Claude Code work effectively in your codebase]
- [Example: "We are migrating from REST to GraphQL. New endpoints should use GraphQL."]
- [Example: "The legacy auth module is being replaced. Do not add new code to /auth/legacy/."]
- [Example: "Performance-sensitive paths are marked with @CriticalPath annotation."]

Auto memory

Auto memory is a separate system from CLAUDE.md. While CLAUDE.md contains instructions you write, auto memory contains notes Claude writes for itself — build commands it discovered, debugging insights, code style preferences, and workflow habits it learned from your corrections.

How it works

Auto memory is on by default. Claude decides what to save based on whether information would be useful in a future conversation. Notes are stored at ~/.claude/projects/<project>/memory/:

~/.claude/projects/<project>/memory/
├── MEMORY.md          # Index file, loaded into every session
├── debugging.md       # Detailed notes on debugging patterns
├── api-conventions.md # API design decisions
└── ...                # Other topic files Claude creates

The first 200 lines (or 25KB) of MEMORY.md load at session start. Topic files load on demand when Claude needs them.

Managing auto memory

Use /memory to browse everything Claude remembers, toggle auto memory on or off, and open files in your editor. All memory files are plain markdown you can edit or delete at any time.

To disable auto memory via settings:

{
  "autoMemoryEnabled": false
}

Or via environment variable: CLAUDE_CODE_DISABLE_AUTO_MEMORY=1.

When to use CLAUDE.md vs. auto memory

Use CLAUDE.md forLet auto memory handle
Rules you want enforced consistentlyBuild commands Claude discovers
Team-wide coding standardsYour personal workflow quirks
Architecture decisions and rationaleDebugging insights for this project
”Never do X” rulesPatterns Claude learns from your corrections

Auto dream (experimental)

Auto dream is a memory consolidation feature that is currently in staged rollout and not yet officially documented by Anthropic. When enabled, it spawns a background subagent that performs a reflective pass over your memory files — merging duplicates, converting relative dates to absolute dates, removing stale or contradicted entries, and keeping MEMORY.md concise.

The toggle appears under /memory in recent Claude Code versions. The setting is autoDreamEnabled in your settings. Note that as of early 2026, this feature is behind a server-side feature flag and may not be available or fully functional for all users.

Evolving your CLAUDE.md

Review it like code

  • Include CLAUDE.md changes in PR reviews
  • Remove outdated rules
  • Add rules when you catch Claude making the same mistake twice

Start small, grow organically

You do not need a perfect CLAUDE.md on day one. Start with:

  1. Tech stack
  2. Build/test commands
  3. Three most important conventions

Then add rules as you discover what Claude gets wrong.

Compounding engineering with @.claude

The most powerful CLAUDE.md evolution pattern is catching mistakes during code review and feeding corrections back immediately. When you spot Claude making an error in a PR, add the correction to CLAUDE.md in the same PR:

# In a PR review comment:
nit: use a string literal union, not a TypeScript enum.
→ Add to CLAUDE.md: "Never use TypeScript enums. Always use string literal unions."

If you’ve installed the Claude Code GitHub Action (via /install-github-app), you can tag @claude in PR comments with instructions to update CLAUDE.md automatically. Claude reads the comment, updates the file, and commits the change to the PR.

This creates a compounding loop: every code review makes Claude smarter. Over weeks, mistake rates drop measurably because the corrections accumulate in a file Claude reads on every conversation.

The pattern:

  1. Claude makes a mistake in a PR
  2. Reviewer catches it and adds a CLAUDE.md rule
  3. Claude never makes that mistake again
  4. Repeat across the team — corrections compound

Quick test: is your CLAUDE.md working?

After writing your CLAUDE.md, try this:

  1. /clear to reset context
  2. Ask Claude to add a small feature
  3. Check: does the output follow your conventions?

If not, your CLAUDE.md probably needs more specific rules. Add them, /clear, and try again.

Tips for team adoption

  1. Start simple — a 10-line CLAUDE.md is better than no CLAUDE.md
  2. Add conventions when they matter — if Claude keeps doing something wrong, add a rule
  3. Review CLAUDE.md in PRs — it should evolve like any other code standard
  4. Don’t over-specify — Claude is smart. You don’t need to explain basic coding practices
  5. Share what works — when someone discovers a great prompt or configuration, share it with the team