How to Write a CLAUDE.md That Saves Tokens Instead of Burning Them

•By Blacdisk Team

How to Write a CLAUDE.md That Saves Tokens Instead of Burning Them

A CLAUDE.md file loads into every session before you type a word. That makes it either the cheapest context you'll spend all day or the thing quietly taxing every message you send. The difference isn't length for length's sake: it's whether the file holds facts Claude needs every single time, or content that belongs somewhere that loads only when relevant.

This guide walks through what to put in CLAUDE.md, what to move out, and how to keep the file under the 200-line target Anthropic's own documentation recommends.

Key Takeaways

  • Target under 200 lines per CLAUDE.md file. Anthropic's documentation states plainly that longer files consume more context and reduce adherence.
  • @path imports help you organize a long file, but they don't save tokens. Imported files still load in full at launch.
  • Move multi-step procedures to skills and file-type-specific rules to path-scoped .claude/rules/, so they load only when relevant instead of every session.
  • Run /init to draft a starting file from your codebase, then delete the parts that state the obvious. Run /doctor (v2.1.206+) later to catch bloat.

What CLAUDE.md Actually Costs You

CLAUDE.md files are loaded into the context window at the start of every session, consuming tokens alongside your conversation, and the official memory documentation is direct about the consequence: because they're context rather than enforced configuration, longer files consume more context and reduce adherence (Claude Code docs: How Claude remembers your project, retrieved 2026-09-22). The size guidance that follows from this is concrete: target under 200 lines per file.

That target isn't arbitrary busywork. Two mechanisms turn a bloated CLAUDE.md into a recurring cost rather than a one-time one:

The file format itself gives you one cheap win before you write a word of instructions: block-level HTML comments (<!-- like this -->) are stripped before the content is injected into Claude's context. Use them for notes to human maintainers, and they cost nothing.

The Test for What Belongs in CLAUDE.md

Ask whether the fact needs to be true in every session, for every file Claude might touch. If the answer is no, it probably belongs in a rule or a skill instead of the main file.

The docs frame the "yes" side of that test around repetition: treat CLAUDE.md as the place you write down what you'd otherwise re-explain, and add to it when Claude makes the same mistake twice, when a code review catches something Claude should have known, when you type the same correction into chat that you typed last session, or when a new teammate would need the same context to be productive.

Keep it to facts Claude should hold in every session: build commands, conventions, project layout, "always do X" rules. If an entry is a multi-step procedure, or only matters for one part of the codebase, the docs say to move it to a skill or a path-scoped rule instead.

Keep in CLAUDE.md Move elsewhere
npm test is the test command A 12-step release checklist → skill
API handlers live in src/api/handlers/ API-route validation rules that only apply under src/api/** → path-scoped rule
Use 2-space indentation Your personal sandbox URL → CLAUDE.local.md
Never push directly to main Company-wide compliance policy → managed CLAUDE.md

Write Instructions Claude Can Actually Follow

Length isn't the only lever. The docs name three qualities that determine how reliably an instruction is followed, independent of how many lines it takes:

Structure. Use markdown headers and bullets to group related instructions. Claude scans structure the way readers do, so organized sections are easier to follow than dense paragraphs.

Specificity. Write instructions concrete enough to verify. The docs give three side-by-side examples:

Consistency. If two rules contradict each other, Claude may pick one arbitrarily. Review your CLAUDE.md files, nested CLAUDE.md files in subdirectories, and .claude/rules/ periodically to remove outdated or conflicting instructions.

A file that is both short and vague isn't actually cheap. It costs the same tokens as a specific one and gets followed less reliably, which is the worst combination.

Move Detail to Rules, Not Just Shorter Prose

For larger projects, .claude/rules/ breaks instructions into topic files (code-style.md, testing.md, security.md), which keeps things modular for a team. On their own, files in that directory without paths frontmatter still load at launch with the same priority as .claude/CLAUDE.md. Splitting into rules without scoping them is an organization win, not a token win.

The token win comes from path-scoped rules. Add paths frontmatter and the rule only loads when Claude works with a file matching the pattern:

---
paths:
  - "src/api/**/*.ts"
---

# API Development Rules

- All API endpoints must include input validation
- Use the standard error response format
- Include OpenAPI documentation comments

Path-scoped rules trigger when Claude reads a matching file, not on every tool use. This is the mechanism that actually shrinks what loads at session start: instructions specific to your API layer, your test suite, or your frontend components stay out of context entirely until Claude opens a file there.

Glob patterns support brace expansion for multiple extensions in one line, such as src/**/*.{ts,tsx}. Keep the whole paths list under the shared budget of 1,000 expanded patterns; a rule that exceeds it is used unexpanded, so its literal braces won't match anything.

For personal preferences that apply to every project you touch, not just this one, ~/.claude/rules/ does the same job at the user level, loaded before project rules.

The Import Trap

@path imports are the feature most likely to give you false confidence about token savings. CLAUDE.md files can import additional files with @path/to/import syntax, and this is genuinely useful for keeping a single file readable: reference a README, a package.json, or a workflow guide without pasting their contents inline.

But the docs are explicit about what imports do and don't do: imported files are expanded and loaded into context at launch alongside the CLAUDE.md that references them. Splitting content into imports helps organization but doesn't reduce context, since imported files still load and enter the context window at launch.

In other words, moving 150 lines from CLAUDE.md into an imported file and replacing them with @docs/conventions.md does not shrink your context. It shrinks the file you look at, not the tokens Claude reads. If your goal is fewer tokens, the two tools that actually work are:

  1. Path-scoped rules, which load conditionally.
  2. Skills, which load only when invoked or when Claude determines they're relevant to your prompt.

Imports are for readability. Rules and skills are for token cost. Don't confuse the two.

Generate a Draft, Then Cut It Down

You don't have to write a CLAUDE.md from a blank file. Run /init and Claude analyzes your codebase and creates a file with build commands, test instructions, and project conventions it discovers. If a CLAUDE.md already exists, /init suggests improvements rather than overwriting it.

The generated draft is a starting point, not a finished product, and this is where most of the line-count bloat creeps in. /init tends to describe what it found, and some of that description is redundant with the codebase itself. The fix is a second pass, and as of v2.1.206, Claude Code automates part of it: the /doctor checkup inspects a checked-in CLAUDE.md and proposes trims. It cuts content Claude can derive from the codebase, such as directory layouts, dependency lists, and architecture overviews, and keeps pitfalls, rationale, and conventions that differ from tool defaults.

That last distinction is the one worth internalizing even if you never run /doctor. A CLAUDE.md earns its tokens by stating what Claude would get wrong without it, not by restating what's already visible in package.json or the folder structure.

A Worked Example

Here's a before-and-after that follows the rules above. The "before" version is a plausible /init output that hasn't been trimmed:

# Project Overview

This is a TypeScript project that uses React for the frontend
and Express for the backend API. It uses npm for package
management. The project has a src/ directory containing all
source code, organized into components/, api/, and utils/
subdirectories. Tests are written using Jest and are located
alongside the source files with a .test.ts extension.

## Getting Started

To install dependencies, run npm install. To start the
development server, run npm run dev. To run tests, run
npm test. To build for production, run npm run build.

## Code Style

Please write clean, readable code. Use meaningful variable
names. Keep functions small and focused. Follow best
practices for TypeScript development.

## API Conventions

All API endpoints should validate their input. Error
responses should follow a consistent format. Use proper
HTTP status codes. Document your endpoints well.

Most of that is either visible in package.json (npm, Jest, the scripts) or too vague to verify ("clean, readable code", "best practices"). Here's a trimmed version that keeps what Claude can't derive and moves the rest:

# Project Instructions

## Commands
- Test: `npm test`
- Dev server: `npm run dev`
- Build: `npm run build`

## Conventions
- 2-space indentation, no semicolons
- New components go in `src/components/`, one file per component
- Never edit files in `src/generated/` directly; they're regenerated by `npm run codegen`

## Architecture notes
- The API layer talks to Postgres directly; there's no ORM by design (see `docs/decisions/no-orm.md`)

The API validation rule from the original moved to a path-scoped rule at .claude/rules/api-conventions.md with paths: ["src/api/**/*.ts"], since it only matters when Claude is actually touching that directory. The result is shorter, more specific, and cheaper on every session where Claude never opens the API layer.

Where Auto Memory Fits (and Where It Doesn't)

Auto memory is a separate, complementary system: notes Claude writes itself based on your corrections and preferences, without you writing anything. It's worth understanding because it interacts with your token budget differently than CLAUDE.md does.

The load-time limit is stricter than CLAUDE.md's: the first 200 lines of MEMORY.md, or the first 25KB, whichever comes first, are loaded at the start of every conversation, and content beyond that threshold isn't loaded. That's a hard read limit, not just guidance. If MEMORY.md is near the limit, Claude Code reminds Claude to shorten it; if it's over the limit, the write still succeeds but everything past the limit is dropped on the next load.

By contrast, a CLAUDE.md file loads in full up to 4 MiB, and Claude Code skips a file larger than that entirely. The 200-line target for CLAUDE.md is a recommendation for adherence and token cost; the 200-line/25KB figure for MEMORY.md is an actual read boundary.

Auto memory also has a built-in discipline that CLAUDE.md doesn't: Claude skips anything it can derive from the codebase, and it skips anything your CLAUDE.md files already say. That second rule means a good CLAUDE.md and healthy auto memory reinforce each other rather than duplicate content, as long as you keep CLAUDE.md accurate. When CLAUDE.md goes stale, Claude may end up re-learning the same correction as an auto memory entry instead.

Quick Checklist

Before you commit a CLAUDE.md, run through this:

Frequently Asked Questions

Does splitting CLAUDE.md into multiple imported files save tokens?

No. Imported files are expanded and loaded into context at launch alongside the CLAUDE.md that references them, so the total token cost is the same as if the content were inline. Imports improve organization and readability, not token usage. To actually reduce what loads, use path-scoped rules or skills instead.

What's the real difference between a rule and a skill?

A rule shapes the session: it's context Claude reads passively, either always (no paths field) or when a matching file is opened (paths set). A skill is a workflow Claude runs: it loads only when invoked directly or when Claude determines it's relevant to your prompt, and it can include multi-step procedures, scripts, and reference material. If the content is "always true about this codebase," it's a rule. If it's "here's how to do this specific task," it's a skill.

Will a CLAUDE.md that's too long actually break anything?

Not in the sense of erroring out, up to 4 MiB, beyond which Claude Code skips the file entirely. Below that ceiling, the cost is degraded adherence and wasted tokens on every session, not a hard failure. That's exactly why it's easy to let it grow unnoticed.

Do CLAUDE.md instructions survive /compact?

The project-root CLAUDE.md does: it's re-read from disk and re-injected after compaction. Nested CLAUDE.md files in subdirectories and path-scoped rules only reload as Claude reads files they apply to, so an instruction that seems to vanish after compaction is often one that was only ever given in the conversation itself, not written into the file.

Should I use CLAUDE.md or AGENTS.md?

If your repository already has an AGENTS.md for other tools, Claude Code can read it directly without you adding anything, as long as there's no CLAUDE.md in the working directory or above it. The size and specificity advice in this guide applies to either file equally, since the format Claude reads doesn't change what makes an instruction cheap or effective.

Where to Go Next

Open your current CLAUDE.md and run the checklist above against it. If you don't have one yet, run /init, then spend ten minutes cutting anything that restates what's already visible in the codebase. The file you end up with should read like the notes you'd hand a new hire on their first day, not like documentation.

Recap: