Learning Objectives
Everything so far in this course was tooling: extractors, bundles, servers, gates. This closing module is about the human-side discipline that makes any of it work β how you structure a project so an agent finds the right context without drowning in the wrong context. By the end you will be able to:
- Explain why agent performance degrades as the context window fills, with real token arithmetic
- Apply the six structuring patterns: layered CLAUDE.md files, skills, subagents, permission deny rules, sparse worktrees, and code-intelligence plugins
- Choose the right pattern from an observed symptom, not from fashion
- Connect these manual patterns to the automated graph tools from Tracks 2β4 β they are the same principle at two levels of automation
- Evaluate the next generation of knowledge-graph tooling (OKF v0.2, trust systems, org-scale serving) with the skeptical toolkit this course gave you
The Root Problem: Context Windows Fill Fast
Here is the story this module β and honestly, this whole course β grew out of. A developer asks their coding agent to fix a session-timeout bug in authentication middleware. The fix is three lines. But before the agent gets there, it reads the entire logging system, the database migration history, half the API endpoints, and β for no discernible reason β the Terraform configs. The developer hits Escape at file 147.
The problem was not the model. The problem was the project structure: every convention, every build command, and every architectural decision had been dumped into one 340-line root CLAUDE.md file. The agent dutifully read all of it at startup, then spent the rest of its context budget exploring code that had nothing to do with authentication. That is what happens when you treat an AI agent like a junior developer who needs the full company handbook before fixing a typo. It doesn't. It needs the right context at the right time, not everything at once.
A context windowThe maximum amount of text (measured in tokens) a model can consider at once β the prompt, every file it has read, every command output, and its own responses all share this budget. is the model's entire working memory for a session. A typical agent context holds around 200,000 tokens, and a tokenThe unit models read text in β roughly 4 characters of English on average. "authentication" is about 3 tokens; a 500-line source file is about 2,000. is roughly 4 characters of text. Everything counts against it: every message you send, every file the agent reads, every command output, every instruction file loaded at startup, and every memory note.
Do the arithmetic and the problem stops being abstract. A 340-line root CLAUDE.md costs about 1,200 tokens β loaded every single session, relevant or not. Reading one 500-line file costs about 2,000 tokens. Exploring with grep and find adds more. In a large codebase you can burn through 50,000 tokens before the agent writes a single line of code. And the damage is not just budgetary: as the context fills, the model's performance degrades. It starts forgetting earlier instructions, re-reads files it already saw, and makes mistakes it would not make with a clean context.
The solution is not a bigger context window. Bigger windows fill too β they just take longer, and they cost more per query while doing it. The solution is keeping irrelevant content out in the first place.
Press play to fill the bars.
The before/after from the real case that opens this module: 147 file reads, 3 failed attempts, 35 minutes versus ~4 file reads in the main context, 1 successful attempt, 6 minutes. Same model, same bug, same three-line fix. The only variable was project structure. Every pattern below is one slice of that difference.
You have seen this exact disease before β in M00 it was called the exploration tax, and Tracks 2β4 built machinery to cure it. This module is the manual, no-tooling-required version of the same cure. Keep that in mind as you read: each pattern is progressive disclosure, done by hand.
The Six Patterns
Pattern 1 β Layered CLAUDE.md files, not one giant root file
Before a well-run restaurant opens, nobody hands every new dishwasher the full corporate operations binder β franchise accounting, marketing calendars, the recipe archive β and says "read this first." The pain is obvious: the dishwasher spends the shift reading about ad budgets, retains none of it, and still doesn't know where the detergent is. The mapping: a single root CLAUDE.md is the corporate binder. Layered CLAUDE.md files are the laminated one-page station guides β the dish station gets dish-station instructions, the grill gets grill instructions, and the two-paragraph company-wide rules ("wash hands, clock in") live in one small shared sheet everyone reads.
The mechanism that makes this work: the agent loads CLAUDE.md files from your current working directory up to the repository root at session start. Start the agent from a subdirectory and it loads that subdirectory's CLAUDE.md plus every parent's, up to the root β and nothing from sibling directories. That lookup path is the whole trick. Instead of one root file with everything, you split:
monorepo/
CLAUDE.md # repository-wide rules only (~40 lines)
packages/
api/
CLAUDE.md # API-specific conventions
.claude/skills/
src/
web/
CLAUDE.md # frontend-specific conventions
.claude/skills/
src/
shared/
CLAUDE.md # shared library conventions
src/Let's build the actual pair for orderflow, our running example. First the root file. Notice what it contains β structure and conventions that apply everywhere β and what it pointedly does not contain: nothing about FastAPI, nothing about the event bus, nothing any single service owns.
# Repository Structure
This is a small monorepo with three services under services/:
- services/billing: FastAPI billing API (invoices, payment webhooks)
- services/orders: order lifecycle, orders_fact writes, WAU metric
- services/notifications: event consumers
Shared code lives in shared/ (auth, db pool, event bus).
Run commands from the repo root; tests with `pytest`.
# Commit Conventions
- Prefix commits with the service name: "billing: fix webhook idempotency"
- One commit per logical change; run tests before committing
- The knowledge/ bundle is refreshed by the post-commit hook β do not edit
generated Dependencies sections by hand (see M08)And the billing service's own file, which only ever loads when you start the agent inside services/billing/:
# Billing Service
FastAPI app in app.py. Domain logic in invoice.py, webhook handling in webhooks.py.
## Commands
- Run tests: `pytest services/billing`
- Run dev server: `uvicorn services.billing.app:app --reload` (port 8001)
## Code Patterns
- Every route verifies auth via shared.auth.verify_token β never inline JWT logic
- State changes publish events via shared.events.publish; consumers must stay isolated
- Raise WebhookError for bad payloads; app.py maps it to HTTP 400The result in the original case: the agent loads 80 lines of instructions instead of 340, and the authentication bug fix reads 12 files instead of 147 β before any of the other patterns are even applied. Use this pattern the moment you catch yourself scrolling past irrelevant sections of your root file, or when a teammate asks why the API instructions mention frontend conventions.
Pattern 2 β Skills for on-demand knowledge
Even a well-layered CLAUDE.md starts bloating, and the bloat always has the same shape: procedures. Testing patterns. Deploy checklists. Debugging runbooks. These are not facts the agent needs every session β they are instructions it needs when, and only when, a task calls for them. Loading a deploy checklist to fix a typo is the handbook problem all over again, one layer down.
A skillA markdown file under .claude/skills/ with a name and description in frontmatter. The agent loads it only when the description matches the task, or when invoked explicitly as a slash command. is a markdown file under .claude/skills/ that loads on demand. The frontmatter's description tells the agent when the skill is relevant; the body carries the actual content. It can also be invoked explicitly as a slash command for repeatable workflows. Startup cost when the task doesn't match: zero tokens.
Here is the canonical example β testing patterns moved out of an API package's CLAUDE.md into a skill:
---
name: api-testing
description: Testing patterns for the API package. Use when writing or
modifying tests in packages/api/.
---
## Test Structure
Tests are in `src/__tests__/` mirroring the `src/` directory structure.
## Running Tests
- All tests: `npm test`
- Single file: `npm test -- src/__tests__/routes/users.test.ts`
## Patterns
- Use `supertest` for HTTP assertions, not raw fetch
- Always wrap database tests in a transaction that rolls back
- Mock external services in `src/__tests__/mocks/`Now the behavior splits exactly the way you want: ask the agent to "write tests for the auth middleware" and it loads the skill, sees the transaction-rollback rule, and follows it. Ask it to "fix the session timeout bug" and the skill never loads, because testing isn't relevant. A skill invoked explicitly β say /fix-pr-comments β can hold a whole workflow: read PR review comments, apply the changes, run tests, push. The entire procedure lives in the skill, consuming zero context in the sessions that don't use it.
If it's a fact the agent needs every session (repo layout, commit format, "never inline JWT logic"), it goes in CLAUDE.md. If it's a procedure or reference material (how to run the test suite's watch mode, the deploy checklist), it becomes a skill. When a CLAUDE.md section has grown into a checklist, that's the signal it wants to be a skill.
Pattern 3 β Subagents for isolated exploration
Layered files and skills control what loads at startup. But exploration during the session still pollutes the context: ask "how does authentication work?" and the agent traces the login flow, session storage, token refresh, and logout β forty file reads whose contents sit in the main context forever after, long after the question is answered.
A subagentA worker agent with its own separate context window. It performs a delegated task (like exploration) and returns only a summary to the main conversation; everything it read stays in its context and is discarded. fixes this with the same isolation trick an OS uses for processes: it runs in its own context window, does the messy exploration there, and returns only a summary. The forty file reads happen β they just happen somewhere disposable. The main conversation receives a clean two-hundred-word explanation instead of forty files of raw content. You invoke it by asking:
Use a subagent to investigate how our authentication system handles
session timeout and token refresh. Report back what files are involved
and how the flow works.The second classic use is review: after the agent implements something, a subagent reviews the diff with fresh eyes β it sees only the change, not the implementation reasoning that produced it, which is exactly the bias you want a reviewer not to have.
Subagent summaries lose detail. A summary that says "timeout logic is in the auth middleware" has dropped the line number your main agent now needs, so it may re-read a file the subagent already saw. That's usually still a bargain β one targeted re-read versus forty speculative reads β but don't expect exact line numbers or verbatim snippets to survive the summary boundary. If you need them, say so in the delegation prompt.
Pattern 4 β Block reads of generated and vendored code
Agents respect .gitignore by default, so node_modules/ and dist/ stay out of searches. But plenty of generated or vendored code is checked in: compiled protobuf definitions, vendored SDKs, generated GraphQL types. A search for "GraphQL resolvers" happily returns the 8,000-line generated schema, and the agent happily reads it β thousands of tokens of machine-written noise that answer nothing.
Permission deny rules make those files unreadable at the tool level:
{
"permissions": {
"deny": [
"Read(./**/dist/**)",
"Read(./**/build/**)",
"Read(./**/*.generated.*)",
"Read(./vendor/**)"
]
}
}Now the search result still appears, but the Read tool returns permission denied β and the agent typically responds by asking where the source files are, which is exactly the redirect you wanted. Verify the current syntax against the docs for your agent version; the shape of the idea is stable even where the config keys evolve.
Deny rules also block your own explicit requests. Ask the agent to "read src/schema.generated.ts" and it can't β you'll need to temporarily remove the rule. That is the price of a rule the agent can't talk itself around, and most days it's worth paying.
Pattern 5 β Sparse worktrees for faster checkouts
Agents can create git worktreesAdditional working directories attached to the same repository, letting parallel work happen on different branches without re-cloning. for parallel or isolated work β and by default each worktree checks out the entire repository. In a monorepo that's pure waste: an API bugfix worktree does not need the frontend, the mobile app, or the data pipelines on disk.
Git's sparse-checkoutA git feature (2.25+) that writes only chosen directories to disk while keeping the rest in the index β a partial working copy of a full repository. feature writes only chosen directories to disk, and a worktree.sparsePaths setting applies it to every worktree the agent creates:
{
"worktree": {
"sparsePaths": [
".claude",
"packages/api",
"packages/shared"
]
}
}Worktrees now contain only .claude/, the API package, its shared dependency, and root-level files. They're faster to create, smaller on disk, and β the context benefit β there is physically less repository for the agent to wander into. If the agent tries to read a file that isn't checked out, git errors and the agent asks what's available. Requires git 2.25 or newer (git --version to check). Reach for this when checkouts take more than ten seconds or you're spawning many parallel worktrees.
Pattern 6 β Code intelligence plugins instead of file scanning
The last pattern attacks the most common exploration query of all: "where is this defined, and who uses it?" Answered by scanning, that costs many grep calls plus reading every candidate file. Answered by a language serverA background process (LSP β Language Server Protocol) that maintains a live semantic index of a codebase: definitions, references, types. Editors use it for go-to-definition; agents can too., it costs one query:
/plugin install typescript-lsp@claude-plugins-official
# "where is refreshAuthToken used?" now returns, instantly:
src/middleware/auth.ts:47
src/routes/users.ts:103
src/__tests__/auth.test.ts:22Zero file reads. Exact file-and-line answers from the language server's live index. The plugin also surfaces type errors immediately after edits β no separate compile step β so mistakes get caught at edit time instead of test time. This pairs beautifully with Pattern 4: deny rules block the noise, code intelligence removes the need to scan what remains.
If that "one query instead of N file reads" shape feels familiar, it should β it is exactly what the MCP graph server did in M09, with one difference: the LSP indexes live semantics for the language it serves, while your graph server indexes whole-repo structure plus docs plus narrative. They are complements, not rivals.
"A bigger context window makes all this unnecessary." β No. Bigger windows fill too, degrade the same way as they fill, and cost more while doing it. Selection beats capacity; that has been true in every module of this course.
"More instructions in CLAUDE.md = better-behaved agent." β Usually the opposite. Instructions compete for attention; 340 lines of everything means nothing stands out. The 40-line root file outperformed it.
"Subagents are slower, so they waste resources." β The forty reads happen either way. The question is whether their bulk poisons your main context for the rest of the session. Isolation is the savings, not the latency.
"Deny rules are redundant with .gitignore." β .gitignore only covers untracked junk. Checked-in generated code (protobuf stubs, generated types, vendored SDKs) sails straight past it; deny rules are the only fence.
Which Pattern When
None of this is doctrine β a 50-file single-repo project needs almost none of it. The patterns pay off when a codebase outgrows any single person's head. Match the symptom you actually observe to the pattern that treats it:
Press play to walk the pairs.
The goal is not to apply every pattern blindly. It's to recognize when context is getting cluttered β and reach for the one pattern that cleans up the specific clutter you've got.
The Combined Effect β and the Course Connection
Run the opening story again with all six patterns in place. The developer starts the agent from packages/api/. It loads the 40-line root file plus the 50-line API file β 90 lines, not 340. Asked to fix the session-timeout bug, it dispatches a subagent to investigate the auth flow; twenty files get read in that disposable context, and the summary comes back: timeout logic in src/middleware/auth.ts line 47, wrong comparison operator. The main agent reads that one file, fixes the bug, writes a test (the api-testing skill loads now, because now it's relevant), runs it, and stops.
| Before | After | |
|---|---|---|
| File reads in main context | 147 | ~4 |
| Attempts | 3 failed, then success | 1 |
| Wall-clock | 35 minutes | 6 minutes |
| Startup instruction load | 340 lines every session | ~90 lines, task-relevant |
Now step back, because this is the point of putting this module at the end of a knowledge-graph course. Every one of these patterns is progressive disclosure done by hand. Layered CLAUDE.md files are a manual index.md hierarchy β read the level you're at, nothing else. Skills are concept files that load on demand. Subagents are the orchestrator-routes-to-a-scoped-reader pattern from M09. Deny rules are a hand-maintained .graphifyignore. Code intelligence is a live structural graph, scoped to one language.
The graph tools from Tracks 2β4 automate exactly this discipline: Graphify builds the map so nobody hand-writes it; OKF's index.md formalizes the layered-entry-point idea; the MCP server makes "one query instead of forty reads" a tool call instead of a delegation prompt. If you ever work in an environment where you can't install any of that tooling β you can still get most of the benefit with a text editor and these six habits. And if you can install the tooling, these habits are what make it actually pay off, because a perfectly-indexed repo behind a 340-line instruction file is still half-blind.
Walk it, step by step
The layered pattern applied, then measured. This is the module's honest step: on a large repository the per-module files cost more than they saved, and on a small one a single root file beat everything.
What's Next β the Road Ahead for the Ecosystem
You are finishing this course roughly ninety days into this ecosystem's existence. Karpathy's LLM-wiki post, Graphify's launch, OKF v0.1, the integration toolkits, the first scrutiny wave β all of it happened inside one spring-to-summer window in 2026. So the honest closing move is not a victory lap; it's a map of what is genuinely unsettled, and the toolkit for judging whatever ships next.
Press play to walk the timeline.
OKF v0.2: from format to trust system
v0.1 deliberately standardized almost nothing: one required field, lenient consumers, no enforcement. The announced v0.2 direction adds what production teams discovered they were missing the hard way β provenance (who or what wrote this concept, from which sources), verification (has a human or a checker attested it), and freshness (is this claim current) as first-class representations. Notice that this is exactly the M11 story arriving in the spec itself: your repository and identity systems will still have to decide what counts as verified, but the format will at least have a place to write the answer down. The surrounding trust-system work β content hashing to detect tampering, tombstones so deleted concepts don't silently resurrect, freshness gates as a spec-level concept rather than a CI habit β is where the serious engineering attention is moving.
Serving at organization scale
Everything you built in this course served one repo to one agent. The next frontier is org-wide: okf-server-style projects putting a REST + GraphQL API over multi-repository knowledge graphs, LSP-server modes so any editor can consume the graph (hover, go-to-definition, find-references backed by the bundle), interactive visualizers, and continuous indexing across hundreds of repos. The design questions are the ones you already know how to ask: who rebuilds, how staleness is detected, and whose lint gates a bundle before other teams' agents trust it β the same M08/M11 questions with more zeros.
The ecosystem watch list
- Gbrain β open-source agent-memory infrastructure (released by Y Combinator CEO Garry Tan): embeds saved context and retrieves by semantic similarity β "cases where similar decisions were made in the past." A vector layer purpose-built for agent memory rather than document search; watch how it pairs with OKF bundles.
- Kiso β a publishing engine that compiles an OKF bundle into a static site: HTML for humans, plus auto-generated
llms.txtand sitemap for crawler-style agents, designed to run in CI on every merge so the published bundle never lags the source. - ai-context-hooks β the interesting contrarian bet: instead of serving organized knowledge, it gives agents a path back to the pre-knowledge context β the meeting notes, chat threads, doubts, and unfinished discussions that existed before anyone wrote a concept file. OKF is the format after knowledge is organized; a context hook is the entry point before that happens.
Open problems nobody has solved yet
Three gaps deserve to be named plainly. First, there is no type registry: OKF's one required field is producer-defined and unvalidated, so multi-team bundles drift ("API Endpoint" here, "Route" there) with nothing but local lint rules holding the line. Second, links are untyped and unenforced: a cross-reference is a Markdown link whose meaning lives in surrounding prose, which caps how much formal graph reasoning β automated dependency traversal, provable impact analysis β an agent can safely do compared to an RDF/OWL-style knowledge graph with typed, validated edges. Whether the ecosystem grows typed links or decides prose-plus-leniency was the right trade is genuinely undecided. Third, there are no long-running production case studies: the spec is months old, and nobody has operated a thousand-file bundle under forty-commits-a-day load for a year. Every maintenance-cost claim you read, including this course's, extrapolates.
How to evaluate whatever ships next
New tools in this space will arrive monthly. You now own a two-part evaluation kit. Part one, the M05 comparison axes: storage substrate (database vs Markdown), sync model (watchers vs hooks vs manual), provenance labeling (does it distinguish extracted from inferred?), local vs cloud, query surface (CLI / MCP / slash command), and multimodal reach. Part two, the M11 24-hour test: ask the vendor β or yourself β "how would I detect, within 24 hours, that this thing's index has gone stale?" If the answer isn't specific and mechanical, you're looking at a demo that hasn't failed yet. And always read the BENCHMARKS.md the way M04 taught you: vendor ceiling case vs replicated range, and what corpus topology the headline number quietly assumes.
Hands-On Exercise β Structure orderflow for Agents
What you'll build: the full six-pattern setup on the orderflow sample repo. Time: 25β35 minutes. Prerequisites: the labs environment from labs/SETUP.md; orderflow at labs/sample-project/.
Step 1 β Write the layered CLAUDE.md pair
What & why: the root file carries repo-wide facts; the billing file carries billing facts. Create labs/sample-project/CLAUDE.md and labs/sample-project/services/billing/CLAUDE.md using the two examples from Pattern 1 above (copy buttons provided).
Check: root file under 25 lines, billing file mentions nothing about orders or notifications.
Start your agent from services/billing/ and ask "what are this repo's commit conventions and this service's error-handling pattern?" β it should answer both without reading any source files, because both facts are in the loaded instruction files.
Step 2 β Move a procedure into a skill
What & why: the bundle-maintenance procedure from M08 is a procedure, not a fact. Create .claude/skills/bundle-maintenance/SKILL.md:
---
name: bundle-maintenance
description: How to refresh and lint the orderflow OKF bundle. Use when
editing files under knowledge/ or when the post-commit hook fails.
---
## Refresh
python ../M08-enrichment-hook/solution/refresh_concepts.py .
## Lint (hard gate β never publish on failure)
python ../M06-okf-authoring/solution/validate.py knowledge
## Rules
- Never hand-edit generated Dependencies sections
- Every refresh appends to log.md; check it in the same commitAsk the agent to "refresh the knowledge bundle" β it should load this skill and run the two commands, in order, and refuse to continue if lint fails.
Step 3 β Add deny rules
What & why: graphify-out/ is generated; agents should query it via the MCP server (M09), never read it raw into context. Add to labs/sample-project/.claude/settings.json:
{
"permissions": {
"deny": [
"Read(./graphify-out/**)",
"Read(./**/__pycache__/**)"
]
}
}Ask the agent to read graphify-out/graph.json directly β the read should be denied. Ask it "who calls decode_jwt?" with the M09 server registered β it should answer via one tool call. Noise fenced, signal served.
Step 4 β Delegate one exploration
What & why: practice the isolation habit. Ask: "Use a subagent to investigate how a payment webhook becomes a customer notification in this repo. Report the files and the event topics involved."
The answer names webhooks.py, events.py, worker.py and the payment.settled topic β and your main conversation contains a summary, not five files of source.
Troubleshooting: skill not loading β check the description mentions the trigger words you're using; deny rule ignored β confirm the settings.json path is inside the directory you started the agent from; subagent returns too little β ask for specific artifacts (file paths, topic names) in the delegation prompt.
π Done: orderflow now has hand-built progressive disclosure wrapped around its automated graph. That combination β habits plus tooling β is the finished state this course has been building toward. The capstone assembles all of it end-to-end.
The six patterns are the four context-engineering levers (M03B) operated by hand: layered CLAUDE.md is add done sparingly; deny rules are crop; subagent exploration is offload/isolate (the reads stay in another context); skills and LSP plugins are retrieve on demand. The graph tools in Tracks 2β4 automate what these patterns do manually β same levers, different operator. Full mapping in M02B.
Knowledge Check
Six questions. Click an answer to get immediate feedback.
1. Your API package's CLAUDE.md contains both "routes live in src/routes/" and a 30-line release checklist. What should move, and where?
2. What does subagent isolation actually preserve?
3. You add Read(./**/*.generated.*) to your deny rules. What's the tradeoff to remember?
4. "The agent spends more time finding where refreshAuthToken is used than writing code, and this is a TypeScript repo." Which pattern treats this symptom directly?
5. What does the announced OKF v0.2 direction add that v0.1 deliberately left out?
6. A new codebase-knowledge tool launches next month with a "60x token savings" headline. Per this course, what are the first two things you check?
Module Summary
What we built
orderflow now carries a layered CLAUDE.md pair, a bundle-maintenance skill, deny rules fencing off generated artifacts, and a demonstrated subagent-delegation habit β the manual context discipline wrapped around the automated graph stack from earlier tracks.
Next: the Capstone
Everything converges. In the capstone you play platform engineer for orderflow and assemble the complete system β structural graph, OKF bundle, self-updating hook, MCP serving, CI freshness gate β measure it honestly, sabotage it deliberately, and answer the course's defining question in writing. It is the course in miniature, built by you.
References
- Sarath S β How I Structure Claude Code Projects So Agents Don't Get Lost in Large Codebases (the six patterns and the 147-file story)
- Claude Code documentation β memory & CLAUDE.md files, skills, subagents, permissions, worktrees (verify config syntax for your version at code.claude.com/docs)
- Udaykiran Estari β From Self-Updating OKF Wiki to Production Trust System (OKF v0.2 provenance/verification/freshness direction)
- okf-rs roadmap β Phase 4 "Ecosystem": okf-server REST/GraphQL, LSP serving, org-scale indexing (github.com/jyjeanne/okf-rs)
- Ecosystem watch list: Gbrain (agent memory), Kiso (OKF static-site publishing), ai-context-hooks (pre-knowledge context)
- Google Cloud β Open Knowledge Format specification v0.1 (GoogleCloudPlatform/knowledge-catalog)