Skip to content
zero2vibecodelearn vibe coding
Claude Code: Pro LevelUpdated: By Mikhail Kuzmitskii

CLAUDE.md that scales: @imports, per-folder rules and what actually loads

In a growing project, CLAUDE.md swells and every line loads into every session. @path imports keep it organised, rules in .claude/rules with a paths field load only when Claude reads a matching file, and /context all shows what really made it in.

You already know how to write a CLAUDE.md. Then the project grows: build commands, conventions, rules for the API, for tests, for markup. Every one of those lines loads into every session, including the one where you only wanted to fix a typo in the README. And when Claude ignores a rule anyway, the instinct is to write it again in capitals.

A glowing lantern above an open book on a desk, with thin threads leading to books on a shelf

This is the fourth post in a series on the Claude Code: Pro Level course, based on the lesson project memory, done properly. Two tools keep memory in order — imports and rules — and two more tell you whether a file loaded at all.

Imports with @path: order, not savings

A line with @ and a path pulls another file in along with CLAUDE.md:

# The linkcheck project

@AGENTS.md

- npm commands: @package.json
- Architecture: @docs/architecture.md

This organises memory. It does not save context: the imported file always loads, together with the file that imports it. Splitting one long CLAUDE.md into five imported files gives you five tidy files and exactly the same context bill.

Two small things that trip people up:

  • the path runs up to the first space, so do not put a full stop right after it;
  • the path is relative to the file that contains the import, not to the folder where you started Claude.

Importing a file outside the working folder, such as @~/notes.md, asks for your approval the first time it is used in a project. Decline, and it stays off.

The AGENTS.md trap

Many projects already keep an AGENTS.md for other coding agents, and Claude Code reads it on its own — but only while there is no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md in your folder or above it. Here is the catch: the moment one of those exists, Claude reads the CLAUDE.md files instead, and your carefully written AGENTS.md is silently skipped. That includes a personal CLAUDE.local.md you added for yourself.

The fix is one line — make @AGENTS.md the first line of CLAUDE.md, and the rules live in one place. Or open /config and set Project instructions to claude-md-and-agents-md, which reads both. Where the other agents look for their files is its own topic: the lesson where each AI coding tool reads its instructions lines up Claude Code, Codex, Gemini CLI and Cursor.

Rules for a folder: load only when needed

Imports do not save context, but rules can. A rule is a Markdown file in .claude/rules/. Without a paths header it loads at startup, like an ordinary CLAUDE.md. With one, it loads only when Claude works with a matching file:

---
paths:
  - "test/**/*.js"
---

# Tests

- Use node:test and node:assert/strict; do not add other libraries.

Patterns are relative to the project root. * does not cross a folder boundary, **/ goes through any number of folders, and braces such as src/**/*.{ts,tsx} work too.

The subtlety that matters: a rule with paths applies when Claude reads, writes or edits a matching file — with the Read, Write or Edit tool, or with a plain cat, head or tail on that one file in the shell. Listing a folder, piping the file into another command or reading several files at once does not count. So when you test a rule, ask exactly that: “read test/config.test.js”.

What loads, and when

Instruction fileWhen it loads
CLAUDE.md at the root, and a rule without pathsat session start
AGENTS.md, when there is no CLAUDE.mdat session start
a file pulled in by an @path importalong with the file that imports it
a rule with pathswhen Claude reads, writes or edits a matching file
auto memory — notes Claude keeps itselfat startup: the first 200 lines or 25 KB of the MEMORY.md index

For personal instructions in one project there is CLAUDE.local.md, which you create by hand and do not commit.

Claude is not listening? Check the load first

Before rewording a rule, find out whether the file loaded at all. The lesson’s point is blunt: much of what looks like disobedience is a pattern with a typo, an AGENTS.md without an import, or an edit made mid-session.

/context all. Plain /context can collapse the list; all expands it. The Memory files section shows what loaded at startup. Rules with paths appear there only after a matching file has been read.

The InstructionsLoaded hook. It fires every time a CLAUDE.md, a rule or an import loads — though not for an AGENTS.md that Claude reads directly, only for one a CLAUDE.md imports. Put it in a separate settings file and start a session with claude --settings:

{
  "hooks": {
    "InstructionsLoaded": [
      { "hooks": [ { "type": "command", "command": "jq -r '[.load_reason, .file_path] | @tsv' >> \"$CLAUDE_PROJECT_DIR/.practice/loaded.txt\"" } ] }
    ]
  }
}

Every line in the log carries a reason: session_start for startup, include for an import, path_glob_match for a rule that applied through its pattern. No path_glob_match line for your rule? Compare the pattern with the real files:

git ls-files ':(glob)src/api/**/*.js'

Empty output means the pattern matches nothing. The classic: a rule for source/** in a project where the code lives in src/.

Editing mid-session

What does not belong in memory

CLAUDE.md is context, not a setting Claude is obliged to obey. Two consequences:

  • A rule that must never be broken belongs in a hook. A PreToolUse hook that exits with code 2 blocks the action every time; the previous post on Claude Code hooks shows how.
  • Long procedures for rare tasks belong in skills. Every line of CLAUDE.md loads into every session, so keep it short.

Frequently asked questions

Does an @path import save context?

No. The imported file always loads together with the file that imports it. Imports bring order; rules with a paths field are what load on demand.

Does Claude Code read AGENTS.md?

Yes, on its own, as long as the project has no CLAUDE.md, .claude/CLAUDE.md or CLAUDE.local.md. Once one of them exists, Claude reads the CLAUDE.md files instead. Put @AGENTS.md on the first line of CLAUDE.md to use both, or set Project instructions in /config to read both.

Why did my rule in .claude/rules not load?

Usually the pattern matches no real file, or Claude has not read a matching file yet — listing a folder or piping a file through another command does not count. Check with /context all, the InstructionsLoaded hook, or git ls-files with the same glob.

Practice

The project memory lesson has a practice terminal: create a CLAUDE.md that imports @AGENTS.md, then pick the draft rule whose pattern matches the real source folder and move it into .claude/rules/. It is the same diagnosis you will run on a real project, just smaller.

Read next

Try it hands-on

Free interactive courses on this topic — in your browser, from zero.