CCLearn

Where instructions come from — scope, load order, and @ imports

verified against Claude Code 2.1.261 · 2026-09-0915 min

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

ScopeLocationShared with
Managed policymacOS /Library/Application Support/ClaudeCode/CLAUDE.md; Linux and WSL /etc/claude-code/CLAUDE.md; Windows C:\Program Files\ClaudeCode\CLAUDE.mdAll users in the organization
User instructions~/.claude/CLAUDE.mdJust you, all projects
Project instructions./CLAUDE.md or ./.claude/CLAUDE.mdTeam members via source control
Local instructions./CLAUDE.local.mdJust 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:

  1. Across scopes — broadest to most specific, so a project instruction lands after a user instruction.
  2. Across the directory tree — filesystem root down to your working directory. Launch in foo/bar/ and foo/CLAUDE.md appears before foo/bar/CLAUDE.md. Within each directory, CLAUDE.local.md is appended after CLAUDE.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.

FileWhen it enters context
CLAUDE.md and CLAUDE.local.md in the working directory and every directory above itAt launch
CLAUDE.md and CLAUDE.local.md in subdirectories below itWhen 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 claude determines "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.md in 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-dir flag 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:

bash
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:

text
See @README for project overview and @package.json for available npm commands.
- git workflow @docs/git-instructions.md

Three 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:

FileWhat it isWhere it is taught
CLAUDE.local.mdPersonal, per-project, gitignored; loads alongside CLAUDE.mdHere and 6.2
.claude/rules/*.mdInstructions split by topic, optionally scoped to file pathsLesson 6.3
MEMORY.md under ~/.claude/projects/What Claude wrote about youLesson 6.4
AGENTS.mdRead by other agents, not by Claude CodeBelow

That last row is a real trap for repos that already standardised on AGENTS.md:

Claude Code reads CLAUDE.md, not AGENTS.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 /context in 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

  1. You launch claude at the repo root and ask it to create a new test file in packages/api/. There is a packages/api/CLAUDE.md with a rule about test naming. Was that rule in context for the request? Why or why not?

    Show answer

    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 in packages/api/ would have loaded that directory's file plus every ancestor's before your first prompt.

  2. Your ~/.claude/CLAUDE.md says "prefer npm"; the repo's CLAUDE.md says "always use pnpm". Both loaded. Describe what the docs actually promise here, and what you should do about it.

    Show answer

    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.md does 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.json wins over settings.json. Two files that disagree is a defect to remove, not a precedence puzzle to solve.

  3. Your project CLAUDE.md has 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 answer

    None. Imported files are expanded and loaded into context at launch alongside the CLAUDE.md that 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.

  4. Which single command tells you whether a given CLAUDE.md reached this session, and what is the other memory command not evidence of?

    Show answer

    /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.

    /memory is 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 /context and 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.

Sources