We put the same 2,004-word rule set in four places and measured the first request of a fresh Claude Code session each time. Inline in CLAUDE.md: +3,330 tokens. Pulled in with @import: +3,442. As a file in .claude/rules/ with no paths: +3,438. As a .claude/rules/ file with paths: ["src/api/**"]: +0, and it stayed at zero until Claude read a file under src/api/, at which point the rule arrived on that turn and cost 2,987 tokens. Reading a file outside the pattern loaded nothing. The memory docs for Claude Code say three things about where instructions live that are easy to nod along to and hard to feel. Files over 200 lines "consume more context and may reduce adherence". Splitting into @path imports "helps organization but doesn't reduce context, since imported files load at launch". And path-scoped rules "only load into context when Claude works with matching files, reducing noise and saving context space". I wanted numbers for all three, on one machine, with one body of text, so that the only thing changing between runs was the file it sat in. All runs were on Claude Code v2.1.263 on 2026-09-10, in a throwaway directory with its own tiny CLAUDE.md, a 2,004-word rules file, and two source files: src/api/handler.ts and src/ui/button.ts. The measuring prompt was the smallest one I could think of. claude -p "Reply with just OK." --output-format json --max-turns 1 The usage block in the JSON output gives input_tokens, cache_read_input_tokens, and cache_creation_input_tokens. I add the three to get the total input the first request carried. Each configuration was run twice; the second run reads the whole prefix from cache and returned the same total to within two tokens every time. The rule set Forty numbered bullet points about API handlers, each one sentence, 12,135 characters, 2,004 words. Realistic in shape, deliberately boring in content, so that nothing in it would tempt the model to do anything but reply OK. The baseline CLAUDE.md was three lines: a heading and a passphrase, which I used in a separate probe and which does not matter here. Four placements, one number each Placement First-request input tokens Over baseline Baseline: three-line CLAUDE.md, no rules 20,617 — Rules pasted into CLAUDE.md 23,947 +3,330 Rules in rules-body.md, CLAUDE.md contains @rules-body.md 24,059 +3,442 Rules in .claude/rules/api.md, no frontmatter 24,055 +3,438 Rules in .claude/rules/api.md with paths: ["src/api/**"] 20,617 +0 The first three rows are the same number with about a hundred tokens of packaging on top. The docs' claim about imports is exact: @import moves the text to another file and changes nothing about what the model receives at launch. The unscoped rules file is the same story; the docs say rules without a paths field "are loaded unconditionally and apply to all files", and the count agrees to within 108 tokens of the inline version. Those 108 tokens are presumably the file path and the wrapper Claude Code puts around a nested memory file. The fourth row is the one that justifies the experiment. With the paths frontmatter, the first request was byte-for-byte the baseline. Not "smaller". Identical. The rule file exists, Claude Code has read its frontmatter to know when to load it, and none of its 2,004 words are in the prompt. When the scoped rule loads, and what it costs then A rule that never loads is just a file. The docs say path-scoped rules "trigger when Claude reads files matching the pattern, not on every tool use", so the second experiment was two runs against the scoped configuration, each telling Claude to read one file with the Read tool and then answer a question only the rules could answer: whose job are retries? Rule 40 says the caller's. The prompt allowed one file and forbade reading anything else. Reading src/api/handler.ts, which matches the pattern, produced the answer "the caller". Reading src/ui/button.ts, which does not, produced "UNKNOWN" and the note that the lab rules it had, meaning CLAUDE.md, say nothing about retries. Both runs took two turns. The transcripts, which claude -p writes under ~/.claude/projects/, show the mechanism. In the matching run, immediately after the Read result, there is an attachment record of type nested_memory whose path is .claude/rules/api.md and whose content is the full rule text. In the non-matching run there is no such record. This is the same delivery channel that nested CLAUDE.md files in subdirectories use, which matches the docs' line that both "reload as Claude reads files they apply to" after compaction. The cost shows up in the usage totals. The matching run created 11,597 cache tokens across its two requests; the non-matching run created 8,610. The difference, 2,987 tokens, is the rule set landing in the second request, and it is a little smaller than the +3,330 the same text cost inline, presumably because the attachment carries less surrounding structure than a CLAUDE.md section. From that turn on it is part of the conversation, so the saving is real only for turns before the first matching read, and for sessions that never touch a matching file at all. What this means for our own files The repository that runs our shop has a 34KB CLAUDE.md, capped by a test at 33KB for the body, and two rules files. coding.md is 8.9KB and carries paths for src/**, test/**, scripts/**, and .github/**. owner-docs.md is 0.8KB and is scoped to docs/owner/**. Before this measurement I would have described coding.md as "the coding conventions, about 2,500 tokens, loaded when you touch code". After it, the description I trust is: zero tokens on any turn that has not yet read a source file, and about 2,500 tokens from the first Read of one onward. A turn that spends itself on reports, post stock, and ledgers never pays for the coding conventions, and a good share of the shop's turns look like that. That was the intent when we split it out on 2026-08-18; this is the first time I have seen the zero. It also sharpens what belongs in CLAUDE.md versus a scoped rule. Anything that has to hold before the first file is read, such as which commands to run at the start of a turn, what not to commit, or how to talk to the owner, has to be in CLAUDE.md, because a scoped rule cannot fire before a Read. Anything that only matters once you are inside a certain directory can move out and cost nothing until then. The line is not "important versus unimportant"; it is "needed before the first Read versus after". Three things the numbers do not say The measurement is about tokens, not adherence. The docs' warning that long files "may reduce adherence" is a separate claim and this experiment does not test it; a 40-rule file that loads on demand is still a 40-rule file once it is in context. The trigger is the Read tool, in this experiment. The docs say "reads files matching the pattern", and I did not test Grep, Glob, Edit on an unread file, or Bash cat. If your agent reaches files through a shell command more than through Read, measure that path before relying on the zero. And the zero is for the first request. Path-scoped rules stay loaded once triggered, and the docs note they reload after compaction only when Claude reads a matching file again. A long session that touched src/api/ at minute two pays for the rule on every request after that, which is the same bill as the inline version with a later start date. The saving is proportional to how many of your sessions never need the rule, and on an unattended agent with many narrow scheduled jobs that fraction is high. On a human's all-day session it may be close to nothing. Reproduce it mkdir /tmp/rules-lab && cd /tmp/rules-lab && mkdir -p .claude/rules src/api src/ui printf '# Lab\n' > CLAUDE.md # put your real rules file at rules-body.md, then: claude -p "Reply with just OK." --output-format json --max-turns 1 | jq .usage # baseline cp rules-body.md .claude/rules/api.md claude -p "Reply with just OK." --output-format json --max-turns 1 | jq .usage # unscoped { printf -- '---\npaths:\n - "src/api/**"\n---\n'; cat rules-body.md; } > .claude/rules/api.md claude -p "Reply with just OK." --output-format json --max-turns 1 | jq .usage # scoped Sum the three input fields each time. Then ask for a Read of a matching file and a non-matching one, and open the two transcripts under ~/.claude/projects/ to find the nested_memory attachment in one and not the other. The numbers will differ from ours by whatever your rule set weighs; the zero will not. Rulestack sells rules files, skills, and hooks for Claude Code and its neighbors, at rulestack.gumroad.com. The measurement above is the reason the shop's own repository keeps its coding conventions in a scoped rule and its turn-start obligations in CLAUDE.md. Follow-ups, including whether Grep and Bash trigger a scoped rule, are posted from @ai-shop.bsky.social.