Workflow · last verified 2026-07-13
Context engineering in the repo: structure your codebase so agents act well
This is the working practice of context engineering inside a repository — deciding, file by file, what an agent loads at launch, what it loads on demand, what survives compaction, and what never enters the window at all. It is part of the Engineering Workflow Library: one prescribed way of working, with real commands, the artifacts each step produces, and a dated changelog.
This page is the workflow. For what context engineering is — the discipline, attention as a budget, why long contexts degrade — see the context engineering guide; nothing there is restated here. The two pages deliberately share a name: the guide is the concept, this is the repo practice.
The job this workflow does
Anthropic's framing is the operating premise here: context "must be treated as a finite resource with diminishing marginal returns" — an attention budget you spend, not a bucket you fill. The failure mode is well measured: performance degrades non-uniformly as input grows, distractors hurt more the longer the input gets, and Anthropic's own guidance is blunt — "LLM performance degrades as context fills… the most important resource to manage."
Most repos spend that budget by accident: a CLAUDE.md that grew by accretion, procedures pasted where facts belong, docs written for humans that agents must swallow whole, tool outputs nobody trimmed. This workflow turns the spend deliberate, in eight steps. Each step produces an artifact you keep in the repo — a pruned CLAUDE.md, path-scoped rules, skills, a docs index — so the practice survives the session that created it.
It prescribes one way. This is the practice we run on aiarch.dev itself — nested CLAUDE.md files, a skill library, subagent isolation — and the steps below are in the order we'd rebuild it.
The workflow
1. Audit what loads
You cannot budget what you haven't measured. In a live Claude Code session, run /context — it shows a live breakdown of the window by category: system prompt, memory files, tool schemas, skill descriptions, messages. Then measure the standing overhead your repo imposes on every session:
# every CLAUDE.md an agent might load, with line counts
git ls-files '*CLAUDE.md' | xargs wc -l | sort -rn
Know what the numbers mean before cutting. Memory files load in a fixed hierarchy: managed policy → user ~/.claude/CLAUDE.md → project ./CLAUDE.md → ./CLAUDE.local.md (gitignored). Claude Code walks up the tree from the working directory loading all of them at launch; CLAUDE.md files in child directories load on demand, only when files there are read — so a nested CLAUDE.md is already cheaper than a root one. @path imports (max depth 4; backticked paths are not imported) load at launch with their parent — the docs are explicit that "splitting into imports helps organization but does not reduce context." If your repo standardizes on AGENTS.md, know that Claude Code does not read it; the official pattern is a CLAUDE.md containing @AGENTS.md.
The audit's output is a table: file, line count, loads-at-launch or loads-on-demand. Everything at launch is standing cost on every single session.
2. Prune CLAUDE.md to constraints
The documented size rule: target under 200 lines per CLAUDE.md — longer files consume more context and reduce adherence. The docs' prune test is the knife: "Would removing this cause Claude to make mistakes? If not, cut it. Bloated CLAUDE.md files cause Claude to ignore your actual instructions!"
What earns a line: bash commands the agent can't guess, non-default style rules, repo etiquette, gotchas that cost a session to rediscover. What doesn't: anything inferable from the code itself — an agent can read your package.json; it cannot guess that your migrations tool is broken and files must be applied directly. One mechanical note: HTML comments are stripped before injection, so <!-- --> annotations cost the reader nothing.
# the pruning loop, per file over 200 lines # 1. for each section, ask: would removing this cause a mistake? # 2. fact the code already states → delete # 3. procedure (multi-step how-to) → step 3: skill or rule # 4. constraint the agent can't infer → keep
We hold this line on aiarch.dev by treating CLAUDE.md edits as reviewable diffs: every addition must name the mistake it prevents, or it doesn't land.
3. Push procedures into skills and path-scoped rules
The heuristic from the docs: move CLAUDE.md content to a skill when "a section has grown into a procedure rather than a fact." Skills are on-demand context — at startup only the one-line descriptions load (description plus when-to-use, truncated at 1,536 characters); the body loads only when the skill is used. A 300-line release runbook as a skill costs a sentence per session instead of 300 lines. Be aware of the flip side: once loaded, a skill body stays in context for the rest of the session — a recurring cost, which is exactly why procedures you use once per session belong in skills and constraints you need every turn belong in CLAUDE.md.
For rules that only matter in part of the tree, use .claude/rules/ — one topic per file, discovered recursively, with a paths: glob in frontmatter so the rule loads only when matching files are touched. This is the documented answer to the oversized-CLAUDE.md problem:
# .claude/rules/frontend.md
---
paths:
- "public/**/*.js"
- "public/**/*.html"
---
Front-end JS is not typechecked. Run node --check after every edit.
Bump the ?v= query on every edited asset in all referencing HTML.
Two more levers: paths-gated skills load only in the directories they apply to; disable-model-invocation keeps even the description out of context for skills you only invoke explicitly. Monorepos can drop irrelevant memory files entirely with the claudeMdExcludes setting. aiArch runs the nested pattern — src/, public/, content/, and test/ each carry their own CLAUDE.md that loads only when work touches that directory, and repo runbooks (release, incident, metrics) are skills.
4. Structure docs for retrieval, not reading
Agent-facing docs should be indexes an agent navigates, not prose it ingests. The llms.txt convention (Jeremy Howard, 2024) exists precisely because "LLM context windows cannot accommodate complete websites" — a root markdown index of what exists and where; Anthropic ships one for its own docs at code.claude.com/docs/llms.txt and a full-text variant on the platform docs. Apply the same shape inside the repo: a short index that names each doc and its one-line purpose, so the agent greps and opens the one file it needs.
This is the just-in-time pattern from Anthropic's context-engineering guidance: keep lightweight identifiers — paths, links, one-line summaries — in context, and retrieve the heavy content on demand. Concretely:
# docs/llms.txt — an index, not a document
# aiarch.dev docs
- docs/DESIGN.md: engineering spec — schema, API routes, build slices
- docs/CURRICULUM.md: locked module-by-module content map
- docs/PLAN.md: historical build rationale (superseded on strategy)
Greppable naming does the rest: predictable file names, one topic per file, headings that contain the words someone would search for. A doc an agent can find with one grep costs a few hundred tokens; a doc it must read end-to-end to locate one fact costs the whole file — on every session that needs it.
5. Set the compaction contract
Long sessions get compacted, and compaction is lossy in specific, documented ways — so decide in advance what must survive. Auto-compaction first clears older tool outputs, then summarizes the conversation, with a thrashing guard that stops after a few attempts. What comes back afterwards: the project-root CLAUDE.md is re-injected. What does not: nested CLAUDE.md files and path-scoped rules, and skill descriptions are not reloaded — an invoked skill persists truncated, keeping the start of the file. The docs' consequence is your authoring rule: put the most important instructions near the top of SKILL.md.
Steer the summarizer instead of trusting it: /compact <instructions> tells it what to preserve, and a "Compact Instructions" section in CLAUDE.md sets a standing policy:
# CLAUDE.md
## Compact Instructions
Preserve: the current task's acceptance criteria, files edited so far,
and any command that failed with its error. Drop exploratory tool output.
The rest of the contract is session discipline: /clear between unrelated tasks rather than letting one task's residue distract the next; after two failed corrections, /clear and write a better prompt instead of arguing with a polluted window; Esc Esc to rewind to an earlier point; /btw for side questions that shouldn't enter the main thread at all. Window sizes make this discipline cheaper to ignore than it used to be — Sonnet 5, Opus 4.8, and Fable 5 run 1M-token windows — but a big window fills with the same non-uniform degradation, just later; and the 4.7-generation tokenizer produces roughly 30% more tokens for the same text, so re-baseline any budgets you carried over.
6. Isolate exploration in subagents
The single biggest context lever: a subagent gets its own window and returns only a summary — on the order of 1,000–2,000 tokens — while the exploration itself (the file dumps, the dead ends, the twenty greps) stays in the subagent's window and dies with it. Anthropic's best-practices guidance puts it directly: since context is your fundamental constraint, subagents are one of the most powerful tools. The named anti-pattern is "the infinite exploration" — an orchestrator that reads file after file in its own window until the actual task drowns.
The practice: any question whose answer requires reading more than a couple of files — "how does X work," "where is Y handled," "what would break" — goes to an Explore subagent; the main thread keeps the conclusion, not the transcript. Built-in Explore and Plan subagents skip loading CLAUDE.md and git status by design — they are deliberately lean. Two configuration notes: as of v2.1.198 subagents run in the background by default, and declaring mcpServers inline in an agent's file keeps those tool schemas out of the main context entirely — the orchestrator never pays for tools only the subagent uses.
# .claude/agents/db-explorer.md — schemas load in the subagent, not the main thread
---
name: db-explorer
description: Answers questions about the D1 schema and seed pipeline.
mcpServers:
d1-tools:
command: npx
args: ["-y", "my-d1-mcp"]
---
7. Keep tool output on a budget
Every token a tool returns is context the model re-reads on subsequent turns. Claude Code caps a single MCP tool response at 25,000 tokens by default — but a tool that regularly approaches the cap is a design problem, not a limit problem. Anthropic's tool-writing guidance is the checklist: return high-signal fields, not UUIDs and boilerplate; default to pagination and filtering; make the compact response the default and the verbose one opt-in.
For tools you own — an MCP server, a script the agent runs — this is a code review criterion: the response should be the summary the model needs, not the row the database has. For tools you don't own, wrap or filter: a subagent (step 6) that calls the verbose tool and returns three lines is often the cheapest adapter you can write.
8. Let memory accumulate deliberately
Claude Code's auto memory is on by default since v2.1.59: per-repo notes live at ~/.claude/projects/<project>/memory/, with a MEMORY.md index (first 200 lines / 25KB) loaded each session and topic files pulled on demand. That index is standing context in every session — which makes it repo infrastructure, and infrastructure gets maintained. Browse it with /memory on a regular cadence; apply the same prune test as step 2. A wrong note is worse than no note: it is a distractor that loads every session, and the context-rot measurements say distractors hurt more as the window fills.
# review the accumulated memory; prune stale or wrong notes /memory # opt out entirely, per project or globally # settings.json: "autoMemoryEnabled": false — or CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
For agents you build on the API rather than in Claude Code, the same pattern is GA as the memory tool ({"type": "memory_20250818"}, no beta header): the model requests file operations under a /memories directory and your client executes them — you own the store, so you own the hygiene.
Artifacts this workflow produces
- A pruned CLAUDE.md — committed, under 200 lines, constraints only, every line answering the prune test.
- .claude/rules/ — topic-per-file rules with
paths:globs, loading only where they apply. - .claude/skills/ — procedures as on-demand skills, most important instructions at the top of each SKILL.md.
- A docs index — llms.txt or equivalent: lightweight identifiers in, full documents retrieved on demand.
- A memory directory under review — auto memory browsed on a cadence, wrong notes pruned like code.
Pitfalls
- Imports as a diet.
@pathimports load at launch with their parent — the docs say it plainly: splitting into imports helps organization but does not reduce context. To actually reduce load, move content to child-dir CLAUDE.md files, path-scoped rules, or skills. - Procedures in CLAUDE.md. A runbook pasted into memory costs every session what it should cost only the session that runs it. The moment a section reads as steps rather than facts, it is a skill.
- Trusting nested context past compaction. Only the project-root CLAUDE.md is re-injected after compaction; nested files and path-scoped rules are not, and skill descriptions are not reloaded. Anything that must survive a long session belongs in the root file or in the compact instructions.
- Bottom-loading SKILL.md. Invoked skills persist truncated from the top after compaction. Critical instructions at the bottom of a long skill quietly vanish mid-session.
- An AGENTS.md nobody reads. Claude Code does not read AGENTS.md. If you keep one for other tooling, the official bridge is a CLAUDE.md containing
@AGENTS.md— not a duplicate. - Exploring in the main thread. Twenty greps and ten file reads to answer one question is the infinite-exploration anti-pattern. Delegate; keep the conclusion.
- Unattended memory. Auto memory's index loads every session. A stale or wrong note is a permanent distractor — and distractor impact amplifies as input grows.
- Assuming a bigger window fixes it. 1M tokens moves the wall; it doesn't remove it. Recall accuracy still decreases as the window fills — and models have been measured performing worse on coherent long inputs than shuffled ones, so "it all fits" is not "it all works."
When not to use this workflow
Don't run the full audit on a repo agents barely touch. A small codebase with a 60-line CLAUDE.md and short sessions has no context problem to engineer away — the 200-line rule already holds, compaction rarely fires, and adding rules directories and skills there is structure without a payload. Start this workflow when the symptoms appear: instructions being ignored mid-session, agents re-discovering the same gotchas, /context showing memory and tool schemas crowding out the actual work.
And don't use this page to learn what context engineering is — that's the guide's job. This page assumes the concept and prescribes the repo practice.
Changelog
- 2026-07-13 — initial version, verified against Claude Code docs (v2.1.2xx) and Anthropic engineering guidance.
- Attention budget and just-in-time retrieval: Effective context engineering for AI agents (Anthropic engineering, 2025-09-29) — "context must be treated as a finite resource with diminishing marginal returns."
- Memory hierarchy, imports, on-demand child CLAUDE.md,
.claude/rules/, auto memory: code.claude.com/docs/en/memory. - 200-line target, prune test, include/exclude guidance, subagent and compaction steering: code.claude.com/docs/en/best-practices.
- Skills as on-demand context, description truncation,
disable-model-invocation: code.claude.com/docs/en/skills. - Window sizes,
/context, auto-compaction behavior and what survives it: code.claude.com/docs/en/context-window and the how-Claude-Code-works docs. - Subagent isolation, Explore/Plan behavior, inline
mcpServers: code.claude.com/docs/en/sub-agents; summary-size figure from Anthropic's engineering blog. - Tool-output economy and the 25k default cap: Writing tools for agents (Anthropic engineering).
- llms.txt convention: llmstxt.org (Jeremy Howard, 2024-09-03); Anthropic's own index at code.claude.com/docs/llms.txt.
- Context rot measurements: Context Rot (Kelly Hong et al., Chroma research, 2025-07-14) — 18 models, non-uniform degradation, distractor amplification, coherent-vs-shuffled haystacks.
- API memory tool: platform.claude.com memory tool docs (GA,
memory_20250818). - The nested-CLAUDE.md, skill-library, and subagent-isolation practice described is aiArch's own — this repo runs it, stated as first-person practice.
Claude Code minors change memory and compaction behavior; re-verify against the docs before relying on a newer version than the one named above. Corrections: hello@aiarch.dev.
Learn the engineering underneath the workflow.
aiArch teaches context engineering, agents, and production architecture by building — on a platform that is itself run by agents under the exact practice on this page. The build is the curriculum.
See how aiArch helps senior engineers become AI-native, or compare Professional Membership pricing.
Free sample — no signup · every claim cited · full curriculum is waitlist-only