CLAUDE.md files are the primary mechanism for embedding persistent, scoped context into Claude Code sessions. Knowing where to place them, what to include at each level, and how they cascade is central to the exam — and to production-grade Claude Code deployments.
Imagine a global corporation with three tiers of documentation:
Company Handbook (global): “All employees must follow data security policy SEC-101 and use approved communication tools.” This applies everywhere, always.
Department Manual (project): “The Engineering department uses Conventional Commits format and requires all PRs to reference a Jira ticket.” Only engineers care about this; Sales ignores it.
Team Playbook (local): “The Payments team formats all currency values in USD with 2 decimal places stored as strings, not floats.” Only the Payments submodule applies this rule.
CLAUDE.md files work the same way: global rules cascade down, local rules specialize without polluting broader contexts, and every level knows only what it needs to know.
A CLAUDE.md file is a Markdown document that Claude Code automatically reads and incorporates into its system context at the start of every session within that file’s scope. It functions as a persistent instruction layer that gives Claude awareness of:
A README is documentation for humans. A CLAUDE.md is operational context for Claude. The key distinction: CLAUDE.md is loaded into Claude’s active context window every session, shaping its behavior. It’s a behavioral configuration file, not a reference document. On the exam, questions often test whether you know the difference between where to place human-facing docs vs. Claude-behavioral context.
Without CLAUDE.md, Claude must rediscover project context on every session through exploration, wasting tokens and risking incorrect assumptions about conventions. With a well-structured CLAUDE.md hierarchy, Claude operates like a senior team member from the first message.
Claude Code recognizes CLAUDE.md files placed at three distinct levels in a repository. Each level has a specific location, scope, and purpose:
Applies across all projects on the machine. Ideal for personal coding style, preferred tools, global security constraints, and universal habits that should follow you everywhere.
Applies to the entire repository. Contains architecture decisions, cross-cutting conventions, approved dependencies, and team-wide standards. Checked into version control and shared.
Applies only to files within that subdirectory. Overrides or supplements the parent-level rules for specialized modules, microservices, or domain-specific conventions.
The global CLAUDE.md lives outside the repo and is never committed — it holds personal preferences. The project-root CLAUDE.md must be committed so all team members share consistent Claude behavior. Subdirectory CLAUDE.md files are committed only when that subdirectory has legitimately different conventions from the root.
When Claude Code resolves what context applies to a given file, it reads all CLAUDE.md files in the ancestor chain and combines them. The precedence order (most specific wins on conflict) is:
| Precedence | Level | File Location | Scope |
|---|---|---|---|
| Highest | Subdirectory | /project/src/payments/CLAUDE.md |
Only src/payments/** |
| Middle | Project Root | /project/CLAUDE.md |
All of /project/** |
| Base | Global | ~/.claude/CLAUDE.md |
All projects on machine |
Additive by default: Instructions at all levels are combined and all apply, unless they conflict. In the case of conflict, the more specific (lower-level) file’s instruction takes precedence. For example: global says “use 4-space indent”, project says “use 2-space indent” — the project file wins for that project.
A common exam distractor is “subdirectory CLAUDE.md replaces the project-root CLAUDE.md.” This is wrong. All levels are additive and cascading. A subdirectory CLAUDE.md supplements and can override parent instructions on specific points, but the parent’s instructions still apply for everything not overridden.
When Claude works on a file in /project/src/payments/process.py, it reads and merges the following CLAUDE.md files in order:
Knowing where to place content is as important as knowing what to write. Misplacing content causes unnecessary noise (global pollution) or missing context (too narrow scope).
| Level | Belongs Here | Does NOT Belong Here |
|---|---|---|
| Global |
Personal coding style preferences Default language/framework preferences Explicit “always ask before deleting files” safety rules Favorite tools (ripgrep, fd, jq) Personal API key naming conventions |
Project-specific package names Database schemas or domain types Team-specific branching strategy Any repo-specific paths or URLs |
| Project Root |
Tech stack and architecture overview Approved/forbidden libraries Branching strategy and PR conventions Test framework and coverage requirements Environment setup instructions Coding standards (indent size, naming) Common commands (build, test, lint) |
Subdirectory-specific data formats Module-internal implementation details Personal style preferences |
| Subdirectory |
Module-specific business rules Domain model and type conventions Integration-specific patterns for that module Local override of parent conventions Subservice-specific environment vars |
Universal coding standards (in root) Auth/security policies (in root or global) Cross-cutting architectural patterns |
Large projects can grow CLAUDE.md files that become unwieldy — hundreds of lines covering coding standards, architecture, tooling, security rules, and more. The solution is modular organization using @-prefixed imports:
# Project: PayStream Platform ## Architecture Overview Microservices on ECS Fargate. All services expose REST APIs documented via OpenAPI 3.1. Event-driven communication via SQS. No direct DB-to-DB calls between services. ## Imported Modules @docs/claude/coding-standards.md # Language-specific style guides @docs/claude/testing-conventions.md # Test framework, coverage rules @docs/claude/approved-libraries.md # Allow/deny list of packages @docs/claude/security-requirements.md # Auth patterns, secrets handling @docs/claude/common-commands.md # Build, test, deploy commands ## Critical Rules (inline, not imported) - NEVER commit secrets or API keys to version control - Always check for existing utility functions before implementing new ones - Every new service endpoint must have a corresponding OpenAPI spec entry
Keep the most critical, always-needed rules inline in the main CLAUDE.md so they’re unmissable. Move verbose reference material (long lists of libraries, detailed style guides) into imported modules that Claude can load on demand. This keeps the primary file scannable and avoids burying critical instructions in long scrolling content.
security-requirements.md independently of frontend standards.coding-standards.md can be imported by both root and subdirectory CLAUDE.md files if needed.# My Global Claude Preferences ## Code Style - Prefer explicit over implicit. Verbose variable names over cryptic abbreviations. - Python: type hints on all function signatures, docstrings for public functions. - TypeScript: strict mode always. No `any` type. ## Safety Rules (Personal) - Always show me a diff before modifying more than 5 files at once. - Never run destructive shell commands (rm -rf, DROP TABLE) without explicit confirmation. - Prefer non-destructive alternatives and suggest them when relevant. ## Tools I Prefer - File search: ripgrep (rg) and fd, not grep and find - JSON processing: jq - HTTP testing: httpie (http) not curl for readability ## Communication Style - Be concise. Skip preambles. Start with the answer, then reasoning. - Flag architectural concerns as separate items, not buried in implementation notes.
# PayStream Platform ## Stack - Backend: Python 3.12, FastAPI, SQLAlchemy 2.0, Alembic - Frontend: TypeScript, React 18, Vite, TailwindCSS - Infra: AWS ECS Fargate, RDS PostgreSQL, SQS, CloudFront ## Architecture Rules - Services communicate via SQS events — no direct service-to-service HTTP in hot paths. - All DB interactions go through the repository layer in `src/repositories/`. - Never bypass the repository layer with raw SQL in handlers/services. ## Coding Standards - Indentation: 4 spaces (Python), 2 spaces (TypeScript/JSON/YAML). - Naming: snake_case for Python, camelCase for TypeScript variables, PascalCase for classes. - No wildcard imports (`from module import *`). ## Testing - Framework: pytest with pytest-asyncio for async handlers. - Coverage minimum: 80% for new modules, 70% overall. - Integration tests live in `tests/integration/`, unit tests in `tests/unit/`. - Always run `make test` before committing. ## Common Commands - Run tests: `make test` - Run linter: `make lint` - DB migrations: `alembic upgrade head` - Start dev server: `make dev` ## Critical Rules - NEVER commit `.env` files or any file containing API keys. - Check `src/utils/` before implementing new utility functions. - PRs must reference a Jira ticket in the format `[PAYS-123]` in the title.
# Payments Module ## Domain Rules (OVERRIDES project root where noted) ### Currency Handling - ALWAYS store monetary values as integers (cents/pence), never floats. - Use `Decimal` for intermediate calculations, convert to `int` before persistence. - Display formatting is handled exclusively in the presentation layer, NOT here. - Override: Unlike other modules, amounts here use `amount_cents` not `amount`. ### Payment States Valid transitions: pending → processing → completed | failed | refunded Never skip states. Use `src/payments/state_machine.py` for all transitions. ### PCI Compliance (CRITICAL) - Raw card numbers must NEVER appear in logs, errors, or return values. - Use tokenized references (pay_tok_XXXX) from the payment provider exclusively. - Any logging in this module: run through `payments.utils.sanitize_for_log()` first. ### Testing (Supplements root rules) - Mock the payment gateway using `tests/mocks/payment_gateway_mock.py`. - All payment flow tests must cover the failure path, not just happy path. ## Key Files - State machine: `src/payments/state_machine.py` - Gateway abstraction: `src/payments/gateway/` - Models: `src/payments/models.py`
Putting everything in one massive file (500+ lines) at the project root. Critical rules get buried, the file becomes hard to maintain, and context becomes irrelevant to the scope Claude is working in.
Placing project-specific rules in the global ~/.claude/CLAUDE.md. These project rules bleed into every other project you work on, causing confusion and potentially incorrect behavior in unrelated codebases.
Creating subdirectory CLAUDE.md files for modules that have no legitimately different conventions from the root. This adds maintenance overhead with no benefit and fragments context unnecessarily.
Not updating CLAUDE.md when the tech stack, conventions, or architecture changes. Outdated instructions mislead Claude into following deprecated patterns confidently. CLAUDE.md must evolve with the codebase.
Burying the most critical constraints (security rules, “never do X” prohibitions) inside imported @module files, where they may not be visible at a glance. Critical rules should always be inline in the main file.
Putting human-facing explanatory documentation in CLAUDE.md assuming Claude will share it. CLAUDE.md is behavioral config for Claude, not documentation. It should read as imperative instructions, not narrative prose.
Use @imports to split large CLAUDE.md files into domain-focused modules. Root file stays concise; detailed standards live in imported topic files (security, testing, APIs).
Ask: “Does this rule apply to the whole project, or just to one subdirectory?” If just a subdirectory, put it there. Avoid root-level clutter from local concerns.
Review CLAUDE.md files during sprint retros or major refactors. Make CLAUDE.md updates part of the definition of done for architectural changes.
Scenario: A monorepo contains three services: auth/, payments/, and notifications/. Each has distinct conventions. The team shares common coding standards. Where should CLAUDE.md files be placed?
Correct answer: One project-root CLAUDE.md for shared team standards, plus individual CLAUDE.md files inside auth/, payments/, and notifications/ for service-specific conventions. Each inherits the root standards and adds its own.
Common distractor: “One massive root CLAUDE.md with all three services’ rules combined” — wrong, this violates the Single Responsibility principle for configuration scoping.
If global says “use 4-space indent”, project root says “use 2-space indent”, and src/api/CLAUDE.md says “use tabs”, what applies in src/api/handler.py?
Answer: Tabs — the most specific level (subdirectory) wins for conflicting rules. All non-conflicting rules from global and project root still apply.
payments/CLAUDE.md, not the root. Root pollution with narrow rules wastes context and reduces clarity.