Where Claude Code reads CLAUDE.md from, root, subdirectories, CLAUDE.local.md and --add-dir
Which CLAUDE.md files Claude Code loads and when: the upward search at startup, why subdirectory files load later, CLAUDE.local.md for personal notes, and loading --add-dir files.
Contents
You wrote a CLAUDE.md and it does not seem to apply. Most of the time the content is fine; the file is simply not in a place that gets loaded right now. Claude Code reads CLAUDE.md from several locations, and each one loads at a different moment.
In short: at startup Claude Code loads the CLAUDE.md files from the current directory upward, plus ~/.claude/CLAUDE.md. Files in subdirectories below the current directory load when Claude touches files there, and the CLAUDE.md in a directory added with --add-dir is not loaded at all unless you turn it on.
KEY POINT
What you will learn
- Which CLAUDE.md files load at startup and which load later
- What to put at the root and in each package of a monorepo
CLAUDE.local.mdfor personal notes that stay out of git- The environment variable that loads CLAUDE.md from
--add-dirdirectories - When to use
/contextand when to use/memory
Every location and when it loads
| Location | Loaded when | In git |
|---|---|---|
~/.claude/CLAUDE.md (user level) | Session start | No |
CLAUDE.md or .claude/CLAUDE.md in the current directory and its parents, up to the repository root | Session start | Yes |
CLAUDE.local.md at the repository root | Session start | No |
CLAUDE.md in a subdirectory below the current directory | When Claude reads or edits files in that directory | Yes |
CLAUDE.md in a directory added with --add-dir or permissions.additionalDirectories | Not by default; at session start once enabled by environment variable | Depends |
用語解説
Upward search: Claude Code walks from the starting directory up through its parents looking for CLAUDE.md, so the root file is loaded wherever you start inside the repository. Keeping both CLAUDE.md and .claude/CLAUDE.md at the same level loads the content twice, so choose one.
When a subdirectory CLAUDE.md loads
Start claude at the repository root and the root CLAUDE.md is loaded immediately, while packages/api/CLAUDE.md is loaded the first time Claude touches something under packages/api/. Start inside packages/api/ instead and both the package file and the root file load at once.
That behavior is what makes a monorepo layout work: shared rules at the root, package-specific rules in each package. Working in web then never pulls the api migration procedure into context.
repo/
├── CLAUDE.md # overall policy, shared commands, rules for every package
├── CLAUDE.local.md # your own notes (not in git)
├── packages/
│ ├── api/
│ │ └── CLAUDE.md # API-specific: migration steps, no-go areas
│ └── web/
│ └── CLAUDE.md # front-end-specific: component and styling rules
└── docs/
Root CLAUDE.md:
## Shared commands
- All tests: `pnpm -r test`
- Lint: `pnpm lint`
## Shared conventions
- Cross-package imports go through `packages/shared`; never import packages directly
- See packages/*/CLAUDE.md for package details
packages/api/CLAUDE.md:
## This package
- Tests: `pnpm --filter api test` (needs the Docker database: `docker compose up db`)
- Add new files under `prisma/migrations/`; never edit existing migrations
To load a subdirectory file up front, say "read packages/api/CLAUDE.md before starting", or start Claude inside that directory. Opposite rules at the root and in a subdirectory make behavior unstable, so subdirectory files should add information rather than override the root.
Subdirectory files cost context too
Once loaded, a CLAUDE.md stays in context for the rest of the session. Work that spans several packages accumulates each package's file, so keep every one of them short.
CLAUDE.local.md for notes only you need
The shared CLAUDE.md is no place for the name of your local database container or your personal to-do list. Those things go in CLAUDE.local.md at the repository root, which Claude Code loads alongside CLAUDE.md.
CLAUDE.md | CLAUDE.local.md | ~/.claude/CLAUDE.md | |
|---|---|---|---|
| Applies to | Everyone on this project | You, on this project | You, on every project |
| In git | Yes | No | No |
| Contents | Conventions, commands, no-go areas | Local environment, work in progress, personal preferences | Your preferences everywhere |
An example:
## Local environment
- Database runs in the Docker container `pg-local` on port 5433; start with `docker compose up db`
- Dev server on port 3001 (3000 is taken by another project)
## Work in progress
- Implementing billing on `feature/billing`
- `src/legacy/` is scheduled for removal; do not add code there
Do not contradict the team's conventions here. If Claude reads "the team does A" and "I do B", its behavior becomes unpredictable. Keep CLAUDE.local.md to additions.
Check that the file really is untracked. If Claude Code has not excluded it for you, add it to the repository's .gitignore by hand, together with the personal permissions file settings.local.json, which gets the same treatment (settings.json versus settings.local.json).
CLAUDE.local.md
.claude/settings.local.json
No secrets
Untracked or not, never put API keys or passwords in CLAUDE.local.md. Its contents are sent to the API every session. Write the variable name and keep the value in your environment.
A --add-dir directory's CLAUDE.md is not loaded
Keeping shared conventions in a separate repository and pointing Claude Code at it with claude --add-dir ../shared-config is a common setup, and the instructions in shared-config/CLAUDE.md are then silently ignored. --add-dir (or /add-dir inside a session) treats the location as an additional working directory so Claude can read and write files there; the official docs state that most .claude/ configuration is not discovered from these directories. permissions.additionalDirectories in settings.json plays the same role: file access, not configuration.
To load memory files from additional directories, set the CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD environment variable:
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config
The files loaded from the top of each additional directory are CLAUDE.md, .claude/CLAUDE.md, .claude/rules/*.md and CLAUDE.local.md (the last one not if local is excluded via --setting-sources). The environment variables page describes the variable as a colon-separated list of directories (semicolon-separated on Windows), while the memory page's example sets it to 1 alongside --add-dir. Whether both forms behave identically could not be confirmed from the official documentation. Start with the documented =1 plus --add-dir form, and fall back to listing the directory paths if it does not take effect.
To avoid typing the variable every time, put it under env in a settings file:
{
"env": {
"CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD": "1"
},
"permissions": {
"additionalDirectories": ["../shared-config/"]
}
}
Only load CLAUDE.md from directories you control
A CLAUDE.md in an additional directory hands its author's instructions straight to Claude. If you --add-dir a repository you cloned from someone else and enable this variable, you are opening the door to instructions you did not write. Keep it to directories your own team maintains.
If the shared instructions are short, importing them from your own CLAUDE.md with @../shared-config/rules.md is simpler than the environment variable (Adding to CLAUDE.md and the @ import syntax).
Checking which files are loaded
/contextlists the files loaded so far under Memory files. A subdirectory file is expected to be absent until Claude touches that directory/memorylists where the memory files live and opens one in your editor. It tells you where things are, not what is loaded
When a file is not loaded, check in this order: the name is exactly CLAUDE.md including case; you do not have both CLAUDE.md and .claude/CLAUDE.md at the same level; for a subdirectory file, Claude simply has not touched that directory yet.
Related
What to write and how long to make it are covered in the hub article How to write CLAUDE.md and in How long should CLAUDE.md be. To scope instructions to specific paths, see Path-scoped rules in .claude/rules. Keeping context small in general is covered in Managing context in Claude Code.
Summary
- At startup Claude Code loads CLAUDE.md from the current directory upward plus
~/.claude/CLAUDE.md; lower files load when their directory is touched - In a monorepo, keep shared rules at the root and package-specific rules in each package, and never let them contradict
- Personal notes go in
CLAUDE.local.mdat the root, kept out of git, with no secrets --add-dirandpermissions.additionalDirectoriesgrant file access only; setCLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MDto load CLAUDE.md from there, and only for directories you control- Check what is loaded with
/contextunder Memory files
FAQ
- Are all subdirectory CLAUDE.md files loaded at startup?
- No. At startup Claude Code loads the CLAUDE.md files from the current directory upward. Files in lower directories are loaded when Claude works with files in that directory.
- Where does CLAUDE.local.md go?
- Next to the project CLAUDE.md at the repository root. It holds notes you do not share with the team and should be kept out of git.
- Is the CLAUDE.md in a --add-dir directory loaded automatically?
- No. By default memory files from additional directories are not loaded. Set CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD to load them.
- How do I see which CLAUDE.md files are active?
- Run /context and look at the Memory files list. /memory shows where the memory files live and opens them for editing; it does not tell you what is loaded.
Primary sources
This article was drafted by AI from official documentation and reviewed by the site operator before publishing. Found a mistake? Let us know via the contact page.