{"slug": "your-claude-md-is-eating-your-context-keep-agent-memory-under-a-token-budget", "title": "Your CLAUDE.md Is Eating Your Context. Keep Agent Memory Under a Token Budget", "summary": "A developer has published a method for auditing the token cost of Claude Code's always-loaded CLAUDE.md memory files, which load at the start of every session and on most subagents. The approach uses Anthropic's free token counting endpoint via a shell script to measure each instruction file, and recommends keeping files under the documented 200-line target since longer files consume more context and reduce rule adherence. The writeup notes that @path imports do not reduce context cost and that Claude 4.7 and later tokenizers produce roughly 30 percent more tokens for the same text.", "body_md": "[Claude Code](https://code.claude.com/docs/en/overview)'s own docs tell you when to add a line to CLAUDE.md: when Claude makes the same mistake a second time, or when you type the same correction you typed last session ([memory docs](https://code.claude.com/docs/en/memory)). It's good advice. Nobody tells you when to take a line out.\n\nSo the file grows. The pnpm rule. The rule about the legacy billing folder. A release checklist you run once a quarter. A directory tree pasted in before a refactor moved half the folders. All of it loads at the start of every session, before the agent opens a single file of your code. Subagents load their own copy too, counted against their own context ([context window docs](https://code.claude.com/docs/en/context-window)). The built-in Explore and Plan agents skip it, and a custom subagent can opt out with `omitClaudeMd: true` ([subagent docs](https://code.claude.com/docs/en/sub-agents)).\n\nThe same docs set a target: under 200 lines per CLAUDE.md file, because \"longer files consume more context and reduce adherence.\" You pay twice. Once in tokens on every session, and again in rules followed less reliably because they compete with each other.\n\nStart with what actually loads. In a Claude Code session, run `/context` and look under **Memory files**. Claude Code loads `CLAUDE.md` and `CLAUDE.local.md` from your working directory and every directory above it, plus your personal `~/.claude/CLAUDE.md`, plus any `.claude/rules/` file without a `paths:` field. Auto memory adds the first 200 lines or 25KB of its `MEMORY.md` index. And `@path` imports don't help: the docs say they organize a long file \"but don't reduce its context cost, because imported files also load at launch.\"\n\nIf a file is over the recommended length, Claude Code warns you at startup and when you run `/status`.\n\nLine counts are a rough proxy. For tokens, use Anthropic's [token counting endpoint](https://platform.claude.com/docs/en/build-with-claude/token-counting). It's free to call (rate-limited by usage tier) and counts with the tokenizer of whichever model you name. CLAUDE.md reaches Claude as a user message after the system prompt, so counting each file as one user message is a fair approximation. This script needs [jq](https://jqlang.org) and curl:\n\n``` bash\n#!/usr/bin/env bash\n# count-context.sh: estimated tokens per instruction file\nset -euo pipefail\nmodel=\"${MODEL:-claude-opus-5-5}\"\nfor f in \"$@\"; do\n  n=$(jq -Rs --arg m \"$model\" \\\n      '{model: $m, messages: [{role: \"user\", content: .}]}' \\\n      \"$f\" |\n    curl -s https://api.anthropic.com/v1/messages/count_tokens \\\n      -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n      -H \"anthropic-version: 2023-06-01\" \\\n      -H \"content-type: application/json\" \\\n      -d @- | jq '.input_tokens')\n  printf '%7s  %s\\n' \"$n\" \"$f\"\ndone\n```\n\nPoint it at your instruction files. Count path-scoped rules separately: they only cost context when they load.\n\n```\nchmod +x count-context.sh\n./count-context.sh ~/.claude/CLAUDE.md CLAUDE.md \\\n  .claude/rules/*.md\n```\n\nIf a row prints `null`, the API returned an error for that file; run the curl by hand to read it. Set `MODEL` to the model your agent actually runs.\n\nRead the numbers with a few caveats. The docs call every count an estimate, and a count may include a few tokens Anthropic adds for system optimizations, which you aren't billed for. Block-level HTML comments (`<!-- like this -->`) are stripped from CLAUDE.md before it reaches the model, so a file full of maintainer notes counts higher here than it costs in a session. And recount when you switch models: Claude 4.7 and later use a newer tokenizer that produces roughly 30 percent more tokens for the same text, per the same token counting page.\n\n*Every always-loaded rule rides along on every session, and on most subagents.*\n\nEvery line in CLAUDE.md should pass one test: does the agent need this in every session? The memory docs answer most of the rest. Multi-step procedures belong in a [skill](https://code.claude.com/docs/en/skills). Rules for one part of the codebase belong in a path-scoped rule. Anything that must happen at a fixed point, like a lint before every commit, belongs in a [hook](https://code.claude.com/docs/en/hooks-guide), which runs as a shell command instead of sitting in context.\n\n| What the line is | Where it goes | When it costs context | \n|---|---|---|\n| Build and test commands, non-default conventions | `CLAUDE.md` | Every session | \n| Rules for one area of the code | `.claude/rules/*.md` with`paths:` | When a matching file is read or edited | \n| A multi-step procedure | `.claude/skills/<name>/SKILL.md` | Description always, body when used | \n| Must run every time | A hook | Not in context | \n| Directory trees, dependency lists | Delete | Claude can read the code | \n\nA path-scoped rule is a markdown file with a `paths` list in its frontmatter. It loads when Claude reads, writes or edits a file that matches:\n\n```\n---\npaths:\n  - \"src/billing/**/*.ts\"\n---\n\n# Billing\n- Amounts are integer cents. Never use floats.\n- Every write goes through LedgerService.\n```\n\nOne catch: a path-scoped rule loads into message history, so `/compact` summarizes it away until a matching file is touched again. A rule that must survive compaction belongs in the project-root CLAUDE.md, which is re-read from disk after `/compact`.\n\nThe quarterly release checklist becomes a skill. Only the description sits in context until the skill is used:\n\n```\n---\ndescription: Cut a release. Use when asked to release or tag.\n---\n\n1. Run `pnpm test` and stop on any failure.\n2. Bump the version in package.json.\n3. Add the merged PRs to CHANGELOG.md.\n4. Tag vX.Y.Z and push the tag.\n```\n\nSave it as `.claude/skills/release/SKILL.md`. The skills docs put it this way: \"a skill's body loads only when it's used, so long reference material costs almost nothing until you need it.\"\n\n*The short card is read every time. The shelf is opened only when a task needs it.*\n\nSplitting moves the cost around. Pruning removes it, and two kinds of evidence are cheap to collect.\n\nThe first is how often each on-demand file actually loads. Claude Code fires an [`InstructionsLoaded` hook](https://code.claude.com/docs/en/hooks) whenever a CLAUDE.md or rules file loads, with the file path and a `load_reason` of `session_start`, `nested_traversal`, `path_glob_match`, `include` or `compact`. It can't block anything; it exists for logging. Save this as `.claude/hooks/log-load.sh`:\n\n``` bash\n#!/bin/sh\n# One JSON line per lazily loaded instruction file.\njq -c '{at: (now | todate), file: .file_path,\n  why: .load_reason, by: .trigger_file_path}' \\\n  >> \"$CLAUDE_PROJECT_DIR/.claude/instructions.log\"\n```\n\nMake it executable, then register it in `.claude/settings.json` for lazy loads only:\n\n```\n{\n  \"hooks\": {\n    \"InstructionsLoaded\": [{\n      \"matcher\": \"path_glob_match|nested_traversal\",\n      \"hooks\": [{\n        \"type\": \"command\",\n        \"command\": \"$CLAUDE_PROJECT_DIR/.claude/hooks/log-load.sh\"\n      }]\n    }]\n  }\n}\n```\n\nIf your project path contains spaces, wrap the variable in escaped quotes the way the hooks guide does. Add `.claude/instructions.log` to `.gitignore`. After a couple of weeks of normal work:\n\n```\njq -r .file .claude/instructions.log | sort | uniq -c | sort -rn\n```\n\nThe top of that list is where the tokens go. A path-scoped rule that loads in nearly every session has a glob so broad that it costs about as much as an always-loaded line, so tighten the glob or move the rule into CLAUDE.md on purpose. A path-scoped rule that never appears costs nothing, but it either has a glob that matches nothing or covers code nobody touched in that window. Fix the glob, or decide whether that code still needs a rule at all. Rules files without `paths:` load at `session_start`, which this hook skips, so judge those by the second kind of evidence.\n\nThe second kind of evidence is a reason for every line that stays always-loaded. Since block-level HTML comments are stripped before injection, the reason costs nothing:\n\n```\n- Package manager: pnpm. Never npm or yarn.\n\n<!-- Added 2026-09: agent ran npm install, lockfile churn -->\n```\n\nA line with no reason, or a reason that no longer applies, is a candidate. Move the doubtful ones into a file nothing imports, work normally for a week, and put back any rule whose mistake returns. The rest were dead weight.\n\nClaude Code will also do a first pass. `/doctor prompt-audit` (v2.1.283 or later) looks for instructions written for older models, references to files or commands that don't exist, and files that contradict each other. It changes nothing until you ask. The plain `/doctor` checkup proposes trims for a checked-in CLAUDE.md, cutting what Claude can derive from the codebase, such as directory layouts and dependency lists.\n\n*Keep the rules with a reason. Park the rest and see what you miss.*\n\n[Codex](https://learn.chatgpt.com/docs/agent-configuration/agents-md) reads `AGENTS.md` starting at the project root and walking down to your working directory, at most one file per directory, and concatenates them with nearer files later. It stops adding files once the combined size reaches `project_doc_max_bytes`, 32 KiB by default, and the docs list \"Instructions truncated\" among the problems to troubleshoot. Check where you stand:\n\n```\nfind . -name AGENTS.md -not -path '*/node_modules/*' \\\n  -exec wc -c {} +\n```\n\nThe token script works on `AGENTS.md` too, and that matters if you share one file across agents. Claude Code v2.1.277 and later reads `AGENTS.md` directly when no `CLAUDE.md` or `CLAUDE.local.md` sits in your working directory or above it. If one does, Claude reads that instead, unless the CLAUDE.md imports `@AGENTS.md` or you change the **Project instructions** setting in `/config`. One shared file means one budget to keep, read by both agents.\n\nI build [Hermes IDE](https://hermes-ide.com), so weigh this section with that in mind. Hermes runs Claude Code, Codex and other CLI agents side by side, each in its own terminal, and its project memory follows the split above.\n\nThe derivable half is generated. Hermes scans each project for its languages, frameworks, architecture and conventions, and points your agent at a context file with what the scan found. That file is kept within a token budget you can set per project ([README](https://github.com/hermes-hq/hermes-ide)). The stack and layout stop being lines you maintain by hand in CLAUDE.md, and the generated version comes with a cap.\n\nThe facts half is pinned. Memory and context pins save facts and pinned files for a project, and they reach every later session's agent, also after a restart. \"The API tests need a local Redis instance\" is a pin: it should outlive the session where you found it out.\n\nThe README describes the budget for the scanned context file, not for the CLAUDE.md or AGENTS.md you wrote, so measuring, splitting and pruning still apply to those. Hermes can also attach several projects to one session, and their context reaches the agent together, so set the budget on each project you attach.\n\nHermes is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux. Release notes for each version are on [GitHub](https://github.com/hermes-hq/hermes-ide/releases/latest). It is not affiliated with Anthropic, OpenAI, Nous Research or any agent vendor.\n\nPrompting a coding agent is mostly context management now: what loads, when, and what it costs per session. My [Prompt Engineering Pocket Guide](https://www.amazon.com/dp/B0GX38N645) covers system prompts and context engineering in short form. If you run more than one agent on a repo, [download Hermes IDE](https://hermes-ide.com/download), and if the per-project budget saves you tokens, [star it on GitHub](https://github.com/hermes-hq/hermes-ide).", "url": "https://wpnews.pro/news/your-claude-md-is-eating-your-context-keep-agent-memory-under-a-token-budget", "canonical_source": "https://dev.to/gabrielanhaia/your-claudemd-is-eating-your-context-keep-agent-memory-under-a-token-budget-lll", "published_at": "2026-10-15 19:48:09+00:00", "updated_at": "2026-10-15 19:56:45.283656+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "large-language-models", "mlops"], "entities": ["Claude Code", "Anthropic", "jq", "curl"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/your-claude-md-is-eating-your-context-keep-agent-memory-under-a-token-budget", "markdown": "https://wpnews.pro/news/your-claude-md-is-eating-your-context-keep-agent-memory-under-a-token-budget.md", "text": "https://wpnews.pro/news/your-claude-md-is-eating-your-context-keep-agent-memory-under-a-token-budget.txt", "jsonld": "https://wpnews.pro/news/your-claude-md-is-eating-your-context-keep-agent-memory-under-a-token-budget.jsonld"}}