Where instructions come from — scope, load order, and @ imports
By the end you can
- Name the four CLAUDE.md scopes and where each one lives on disk
- State the order files enter context and why they concatenate rather than override
- Predict which CLAUDE.md files load at launch and which wait for a file read
- Use @ imports knowing the depth limit and that they do not save context
- Bridge an existing AGENTS.md in, since Claude Code reads only CLAUDE.md
- Verify what actually loaded with /context rather than assuming
You have a ~/.claude/CLAUDE.md with your personal preferences, the repo has a
CLAUDE.md the team wrote, and somebody added one in packages/api/ last
month. Claude just did something all three of those files have an opinion about,
and did it the wrong way. Before you can fix that, you need to know which of the
three was even in the window.
That is this lesson: not what to write, which is Lesson 6.2, but which files a session picked up, in what order, and which were still sitting on disk unread.
Two systems, one window
Every session begins with a fresh context window, and the docs name exactly two
mechanisms that carry knowledge across sessions: CLAUDE.md files, which you
write, and auto memory, which Claude writes (How Claude remembers your
project). Both load at the start of
every conversation, and both are context rather than enforced configuration —
the distinction Lesson 2.3 drew between advisory and guaranteed. Auto memory is
Lesson 6.4's subject, where the two are compared row by row. Everything below is
the first of them.
The four scopes, in load order
Four locations, and the docs are explicit that the list is an ordering:
The table below lists them in load order, from broadest scope to most specific, so a project instruction appears in context after a user instruction. — How Claude remembers your project
| Scope | Location | Shared with |
|---|---|---|
| Managed policy | macOS /Library/Application Support/ClaudeCode/CLAUDE.md; Linux and WSL /etc/claude-code/CLAUDE.md; Windows C:\Program Files\ClaudeCode\CLAUDE.md | All users in the organization |
| User instructions | ~/.claude/CLAUDE.md | Just you, all projects |
| Project instructions | ./CLAUDE.md or ./.claude/CLAUDE.md | Team members via source control |
| Local instructions | ./CLAUDE.local.md | Just you, this project |
The managed policy row is the one most people have never seen. If your organization ships one it applies to every session on the machine, in every repository, and no individual setting can exclude it.
Concatenated, not overridden
Here is the sentence the rest of this lesson hangs on:
All discovered files are concatenated into context rather than overriding each other. Across the directory tree, content is ordered from the filesystem root down to your working directory. — How Claude remembers your project
So "load order" is the order text arrives in the window, not a precedence chain. No discovered file is replaced by a later one. Your two-year-old personal rule is sitting in context right next to the project rule that contradicts it.
The docs draw the contrast with settings themselves, because settings work the other way:
This is different from CLAUDE.md, where global and project files are both loaded into context rather than merged key by key. — .claude directory reference
There are two separate ordering rules, worth keeping apart rather than fusing into one sequence:
- Across scopes — broadest to most specific, so a project instruction lands after a user instruction.
- Across the directory tree — filesystem root down to your working
directory. Launch in
foo/bar/andfoo/CLAUDE.mdappears beforefoo/bar/CLAUDE.md. Within each directory,CLAUDE.local.mdis appended afterCLAUDE.md, so your personal notes are the last thing read at that level.
No documented sentence says how those two interleave — whether a nested
CLAUDE.md is ordered before or after ~/.claude/CLAUDE.md, for instance. If
you need that answer, the real problem is that you are relying on order to
settle a disagreement.
Launch-time versus on-demand
Not every discovered file is present when you type your first prompt.
| File | When it enters context |
|---|---|
CLAUDE.md and CLAUDE.local.md in the working directory and every directory above it | At launch |
CLAUDE.md and CLAUDE.local.md in subdirectories below it | When Claude reads a file in that subdirectory |
Subdirectory files are "included when Claude reads files in those
subdirectories" (How Claude remembers your
project). This is the commonest reason
a CLAUDE.md "seems ignored", and the troubleshooting table is precise about
the trigger in a way that matters:
They load when Claude reads a file in that directory with the Read tool, not at launch and not when writing or creating files there. — Debug your configuration
Read the second half twice. Asking Claude to create a new file in
packages/api/ does not pull in packages/api/CLAUDE.md. The rules you wrote
for that package are absent for exactly the operation you wrote them for.
Two consequences you already half know:
- Where you launch decides the launch-time set. Lesson 1.4 rested on the
sentence that where you launch
claudedetermines "which CLAUDE.md files load into context at startup" (Work in large codebases) — the same decision, seen from the memory side. Start at the repository root and you get the root file only; start in a package and you get that directory's plus every ancestor's. - Lazily-loaded files are lazily re-loaded. Lesson 3.2's compaction table
puts nested
CLAUDE.mdin the "reloaded as Claude reads files in that subdirectory" row, not the "re-injected from disk" row. After a compaction it is gone again until something in that directory is read.
--add-dir is the other surprise. It grants access without granting memory:
The
--add-dirflag gives Claude access to additional directories outside your main working directory. By default, CLAUDE.md files from these directories are not loaded. — How Claude remembers your project
Opting in is an environment variable, and it brings CLAUDE.md,
.claude/CLAUDE.md, .claude/rules/*.md, and CLAUDE.local.md — that last one
only while local is among your --setting-sources, which it is by default:
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config@ imports: depth four, and no savings
A CLAUDE.md can pull in other files with @path/to/import:
See @README for project overview and @package.json for available npm commands.
- git workflow @docs/git-instructions.mdThree mechanics worth holding:
- Relative paths resolve against the importing file, not your working directory. Absolute paths work too.
- Imports nest, to a maximum depth of four hops. An imported file may import further files, up to that documented ceiling.
- Import parsing skips Markdown code spans and fenced code blocks. That is the documented way to write a path without importing it: in backticks, the text stays literal.
And the one that decides whether imports are worth reaching for at all:
Imported files are expanded and loaded into context at launch alongside the CLAUDE.md that references them. — How Claude remembers your project
Splitting a long file into imports buys organization and nothing else — it does not reduce context. If your motive was to shrink the window, imports are the wrong lever; Lesson 6.3's path-scoped rules and Lesson 6.6's trimming are the right ones.
That home-directory import has a real use. A gitignored CLAUDE.local.md exists
only in the worktree where you created it, so importing a file from ~ is how
personal instructions follow you across worktrees of the same repo.
The files that are not CLAUDE.md
Four more files come up whenever this one does, and it is worth knowing which lesson owns each:
| File | What it is | Where it is taught |
|---|---|---|
CLAUDE.local.md | Personal, per-project, gitignored; loads alongside CLAUDE.md | Here and 6.2 |
.claude/rules/*.md | Instructions split by topic, optionally scoped to file paths | Lesson 6.3 |
MEMORY.md under ~/.claude/projects/ | What Claude wrote about you | Lesson 6.4 |
AGENTS.md | Read by other agents, not by Claude Code | Below |
That last row is a real trap for repos that already standardised on AGENTS.md:
Claude Code reads
CLAUDE.md, notAGENTS.md. — How Claude remembers your project
The documented bridge is a CLAUDE.md whose first line is @AGENTS.md, with
any Claude-specific instructions appended below it — one import, both tools
reading the same instructions, no duplication. A symlink
(ln -s AGENTS.md CLAUDE.md) works too if you need nothing Claude-specific,
but on Windows it requires Administrator privileges or Developer Mode, so the
import is the portable choice.
One small economy while you are in the file: block-level HTML comments, written
as <!-- maintainer notes -->, are stripped before the content is injected into
context, so notes to your fellow humans cost nothing. Comments inside code
blocks are preserved, and all of them stay visible if Claude opens the file with
the Read tool.
Confirming it loaded
Everything above is a prediction. There is one command that turns it into an observation:
To confirm the file loaded, run
/contextin a session and check the list under Memory files. — How Claude remembers your project
The pairing to remember: /memory lists where memory files could be across
user and project scopes — including entries for files that do not exist yet —
and opens them in your editor. /context reports what actually loaded into the
session you are in. Only the second is evidence, which is Level 5's argument
applied to your configuration instead of your code. This course prints no sample
readout, for the reason Lesson 3.2 gave; run it in your own repo and read the
Memory files list against the four scopes above.
When the file is listed there and Claude still did not follow it, you have ruled out the whole of this lesson and are left with the honest answer:
CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt itself. Claude reads it and tries to follow it, but there's no guarantee of strict compliance, especially for vague or conflicting instructions. — How Claude remembers your project
Vague and conflicting are the two named causes, and they are the next two lessons: what to write so it can be verified (6.2), and where to put it so it is present when it matters (6.3).
Checkpoint
-
You launch
claudeat the repo root and ask it to create a new test file inpackages/api/. There is apackages/api/CLAUDE.mdwith a rule about test naming. Was that rule in context for the request? Why or why not?Show answerAnswer
No. Subdirectory files load on demand, and the documented trigger is narrow: they load when Claude reads a file in that directory with the Read tool, "not at launch and not when writing or creating files there." You launched at the root, so the launch-time set was the root file and its ancestors; creating a file in
packages/api/is precisely the operation the trigger excludes.This is the trap the lesson calls the commonest reason a
CLAUDE.md"seems ignored" — the rules you wrote for that package are absent for exactly the operation you wrote them for. Where you launch decides the launch-time set, so starting inpackages/api/would have loaded that directory's file plus every ancestor's before your first prompt. -
Your
~/.claude/CLAUDE.mdsays "prefer npm"; the repo'sCLAUDE.mdsays "always use pnpm". Both loaded. Describe what the docs actually promise here, and what you should do about it.Show answerAnswer
They promise nothing you can rely on. All discovered files are concatenated into context rather than overriding each other, so both sentences are sitting in the window in full. The reference page for
~/.claude/CLAUDE.mddoes say project-level instructions take priority when instructions conflict, but the memory page is blunter about the actual cost: if two rules contradict each other, Claude may pick one arbitrarily.So delete one — almost certainly the stale personal rule. Load order is the order text arrives in the window, not a precedence chain, and the tempting wrong answer is to reason "the project file loads later, so it wins" the way
settings.local.jsonwins oversettings.json. Two files that disagree is a defect to remove, not a precedence puzzle to solve. -
Your project
CLAUDE.mdhas grown well past the documented 200-line target, so you split it into six files pulled in with@imports. How much startup context did that save?Show answerAnswer
None. Imported files are expanded and loaded into context at launch alongside the
CLAUDE.mdthat references them, so the same text arrives in the same window — you have six files where you had one. Splitting buys organization and nothing else.If shrinking the window was the motive, imports are the wrong lever: the right ones are Lesson 6.3's path-scoped rules and Lesson 6.6's trimming.
-
Which single command tells you whether a given
CLAUDE.mdreached this session, and what is the other memory command not evidence of?Show answerAnswer
/context, read under the Memory files list — it reports what actually loaded into the session you are in. Everything else in this lesson is a prediction; this is the observation./memoryis not evidence of loading. It lists where memory files could be across user and project scopes — including entries for files that do not exist yet — and opens them in your editor. Seeing a path there tells you the location, not the load. And when the file is listed by/contextand Claude still did not follow it, you have ruled out this whole lesson: the content arrives as a user message after the system prompt, with no guarantee of strict compliance, and vague or conflicting instructions are the named causes.