LEARN · PHASE 13 · LESSON 88

Context as Architecture, Not a Dump

You can decide where a fact lives — which layer, loaded when, by whom — instead

Type
Learn
Prerequisites
Lesson 87 (Progressive Disclosure), Lesson 65 (CLAUDE.md), Lesson 67 (Rules)
Time
~35 minutes

Learning Objectives

  • Ask four questions of any piece of context: home, lifetime, trigger, eviction
  • Sort a bloated CLAUDE.md line by line into keep / delete / rule / skill
  • Name which layer each fact belongs in, and defend the choice
  • Read the reload behavior of each layer after /compact and after a restart
  • Spot a dump: everything in one layer, in one file, at one priority

The Problem

Your CLAUDE.md grew to 900 lines. Someone added the deploy steps. Someone else added the whole API style guide. A third person pasted the test matrix. All of it is the same file, the same priority, loaded at the same moment, for every task.

Now Claude follows the wrong third of it at random. A rule that applies only to src/api/ fires while it edits a test file in src/lib/. You cannot tell which lines are load-bearing, because nothing about the file says. It is one flat pile where a design should be.

That is a dump. A dump has no place, no lifetime, and no owner. It just has volume.


The Concept

Every piece of context has three properties, whether you chose them or not:

  • Home — which layer it lives in.
  • Lifetime — when it loads, and when it goes away.
  • Owner — what loads it: the session start, a file match, an invocation.

A dump gives everything the same three answers: one layer, always, loaded by nothing in particular. An architecture gives each fact the answers that fit it.

graph TD
    subgraph Always["Loaded at session start, reloaded after /compact"]
        SP[System prompt — fixed]
        MEM[Auto memory]
        PROJ[CLAUDE.md — user + project]
    end
    subgraph OnMatch["Loaded when a file matches"]
        RULE[Path-scoped rules paths:]
    end
    subgraph OnInvoke["Loaded when used"]
        SK[Skill body]
        REF[Skill references/]
        MCPS[MCP schemas]
    end
    subgraph PerTurn["Grows every turn, summarized at compaction"]
        CONV[Conversation + file reads + tool output]
    end
Mermaid source — renders as a diagram where mermaid.js is available

The four questions

Ask these of any line before you decide where it goes:

  1. Does Claude need this before it acts, or only when it does a specific thing? If only for a specific thing, it belongs behind a trigger, not at startup.
  2. When should it load? Session start, a matching file, or an invocation.
  3. What loads it? If nothing loads it, it is a dump line.
  4. What removes it? /clear, /compact, a restart, or the end of the session. If the answer is "nothing, ever", you are paying for it every turn.

Where each layer reloads

LayerLoadedAfter /compactAfter restart
System promptSession startReloadedReloaded
Auto memorySession startReloadedReloaded
CLAUDE.mdSession startReloaded from diskReloaded from disk
Rule listingSession startThe listing does not re-inject; invoked skills doReloaded
Path-scoped ruleWhen a matching file is readStays if already readNot until re-matched
Skill descriptionSession startNot re-injectedReloaded
Skill bodyOn invokeRe-attached, first 5,000 tokensNot until re-invoked
File readWhen readRecent files re-read; older content summarizedGone
MCP tool namesSession startReloadedReloaded

The point of the table is not memorization. It is that a fact has a lifetime, and the lifetime decides whether you are paying for it every turn or only on the turn you use it.

The reframe: context is architecture, not a dump — every fact needs a home,

a lifetime, and an owner, and if you cannot name all three for a line, it does

not belong in the window yet.

Verified against the context window page and the memory page on 2026-10-15. Compaction details and reload behavior are version-gated; the four questions are not.


Build It

Take a real CLAUDE.md — ideally one that is over 200 lines, or any memory file you suspect is a dump.

  1. Print it with line numbers so you can point at decisions:

``bash cat -n CLAUDE.md ``

  1. Make a four-column table and process every line: line, decision, new home, why. The decisions are the only four allowed:

| Decision | New home | When it loads | |---|---|---| | Keep | CLAUDE.md, under 200 lines | Session start | | Rule | .claude/rules/<name>.md with paths: | When a matching file is read | | Skill | .claude/skills/<name>/SKILL.md | On invoke | | Delete | nowhere | never — it is derivable from the code |

  1. Do the sort. Do not skip lines. The uncomfortable ones — the 900-line file's deploy steps, its style guide — are the whole exercise.

✅ You pass when your table has a row for every line and no row says "keep, because it's important".

  1. Move one line of each non-Keep kind into its real home. Restart and run /context.

✅ You pass when the startup total drops and you can say which line moved where, and why that home and no other.

  1. Break it on purpose: put a path-scoped rule where an always-loaded one was and confirm it does not fire outside its paths:.

✅ You pass when you can show the rule loading for a matching file and staying out of the window for a non-matching one.


Use It

SituationWhere it belongs
"Always run the formatter before you finish."CLAUDE.md — true for every task
"Endpoints under src/api/ return this error shape."Path-scoped rule with paths: src/api/**
"How to cut a release: 8 numbered steps."A skill — a procedure, invoked when needed
"The deploy checklist is 200 lines."A skill plus a references/ file
"Read the spec before changing this module."A line in CLAUDE.md, or a rule, pointing at the spec
"The build command is pnpm build."CLAUDE.md, one line — or delete it if package.json says so
"Research how auth works across 12 files."A subagent — its reads never touch your window

Exercises

  1. Sort a dump. Take a memory file over 200 lines and produce the line / decision / new home / why table for all of it. ✅ You pass when no row is blank and at least three rows are Delete with a stated reason the code already implies them.
  1. Architect one fact end to end. Pick a single fact currently at startup. Move it to a path-scoped rule, a skill, or a subagent. Then show it loading in the right situation and absent in the wrong one. ✅ You pass when you can demonstrate both the load and the non-load from /context or a transcript.
  1. Defend a home. Ask a peer (or your past self) where one fact should live. If the answer is "just put it in CLAUDE.md", get all three properties — home, lifetime, owner — for that choice. ✅ You pass when you can name a fact whose correct home is not CLAUDE.md and say which of the four questions rules it out.

Key Terms

TermWhat people sayWhat it actually means
context dump"a thorough CLAUDE.md"Everything in one layer, at one priority, loaded always. Volume instead of design.
home / lifetime / owner"where does this go"The three properties every fact needs. No answer to all three means it is a dump line.
path-scoped rule"a rule"A rule with paths: — it loads when a matching file is read, not at startup.
reload behavior"it comes back"What a layer does after /compact or a restart. Skill descriptions do not re-inject; bodies re-attach capped; reads go stale.
derivable"worth documenting"Content the code or config already states. Keeping it in the window is a standing charge with no return.

What this lesson skipped

Auto memory internals. How MEMORY.md is written and trimmed is Lesson 68.

Output styles and imports. Other context layers, in Lessons 69–70.

Reducing a live context. The mechanics of cutting a specific window in half are Lesson 90.

Harness design. Designing the layers of a harness rather than a project is Phase 14.

Check yourself

4 questions. Answer before you reveal — recognising the right option is not the same as being able to produce it.

  1. A CLAUDE.md contains an eight-step release procedure. Where should it live?

    1. In CLAUDE.md, so it is always loaded and never forgotten
    2. In a skill, so it loads when someone cuts a release and costs nothing otherwise
    3. In a path-scoped rule matching the release script's directory
    4. Nowhere — release procedures cannot be stored as context
    Show answer

    B. In a skill, so it loads when someone cuts a release and costs nothing otherwise

    A procedure is a task invoked at a known moment, so a skill is the home: metadata always, body on invoke. Option A makes it a standing charge paid every session for a task you run rarely — the dump pattern. Option C would fire when the release script is edited, not when a release is run, which is the wrong trigger. Option D is false; the question is which layer, not whether.

  2. A rule says "code under src/api/ must return this error shape." You start a session to fix a CSS bug in src/web/. Which home removes the rule from your window?

    1. CLAUDE.md
    2. A path-scoped rule with paths: src/api/**
    3. An auto-memory entry
    4. A references/ file inside every skill
    Show answer

    B. A path-scoped rule with paths: src/api/**

    A path-scoped rule loads only when a matching file is read, so a src/web/ task never pays for it. Option A loads the rule at session start regardless of the task. Option C also loads at startup. Option D would attach the rule to skills you did not invoke, and it would not fire when an API file is edited — the wrong trigger entirely.

  3. You restart a session. Rank-free: which startup block is NOT re-injected after a /compact, even though it was loaded at the start?

    1. Project CLAUDE.md
    2. Auto memory (MEMORY.md)
    3. Skill descriptions
    4. The system prompt
    Show answer

    C. Skill descriptions

    The skill description listing is the block that does not re-inject after compaction; only skills you actually invoked are re-attached. Options A, B, and D are all reloaded — CLAUDE.md and memory from disk, the system prompt from the fixed prompt. The trap is assuming every startup block reloads identically; the lifetimes differ, which is the whole point of the architecture.

  4. Your memory file states "the build command is pnpm build", but package.json already defines that script. What is the right decision?

    1. Keep it — having it in two places is safer
    2. Change it to a path-scoped rule
    3. Delete it — it is derivable from the code, so it is a standing charge with no return
    4. Move it to auto memory so Claude learns it itself
    Show answer

    C. Delete it — it is derivable from the code, so it is a standing charge with no return

    Content the repo already states is derivable: keeping it in the window costs every session and buys nothing. Option A is the dump instinct — duplication is not safety, it is a second place to go stale. Option B misapplies path scoping to a fact that is not directory-specific. Option D solves the wrong problem; the fact does not need remembering, it needs reading when relevant.