Reference: how Claude Code assembles context
What the model's context window holds at the start of a Claude Code turn, where each piece comes from, and which failures produce no error.
Updated
Map what my Claude Code actually loads, against this page
Measures what Claude Code actually loads on this machine against this page and records every contradiction in CONTEXT-MAP.md. Changes nothing else.
PROMPT 1 of 2 — learn how Claude Code assembles context by measuring it on THIS machine, against the reference page. Read only. You change nothing.
HOW LONG THIS TAKES: a multi-step measurement (6 steps, a couple of questions, one map file written) — expect roughly 10–20 minutes across several turns. Running headless with a timeout? Budget for that, or start with a shorter prompt first. Cut off partway? Paste this prompt again — it resumes from its checklist rather than starting over.
ASK EVERY QUESTION IN THIS PROMPT WITH the `AskUserQuestion` tool, each with a RECOMMENDED option first and one line of why. A question asked in prose has no options, so it carries no recommendation.
I am a senior technical person. Do not explain what a context window is. Where my setup contradicts what I believe about it, say so with the evidence.
FIRST — WRITE YOUR CHECKLIST TO A FILE
RESUMING? Before you write anything, check whether ~/CONTEXT-ASSEMBLY-LEARN-CHECKLIST.md already exists. If it does, this prompt was interrupted: read it, tell me which steps are already ticked, and continue from the first unchecked step. Do not overwrite it, do not redo a ticked step, and do not re-ask a question whose answer it already records — the scope answer under ## Rules included. Only if it does not exist, write it fresh as below.
Long sessions compress their own history — and this page says exactly what survives: project CLAUDE.md, unscoped rules and auto memory are re-injected, the skill listing is NOT. Instructions pasted into chat are not on that list. Write this to ~/CONTEXT-ASSEMBLY-LEARN-CHECKLIST.md and work from the file:
# Context assembly — learn
## Tasks
- [ ] 1. Fetch the reference and my version
- [ ] 2. Walk the load order on this machine
- [ ] 3. Split always-on from on-trigger, with a byte total
- [ ] 4. Check the five silent failures
- [ ] 5. Explain it back, and have me check you with /context
- [ ] 6. Write CONTEXT-MAP.md, and tell me to paste prompt 2
## Rules
- Read only. I create this checklist and CONTEXT-MAP.md. Nothing else.
- I report that ~/.claude/.credentials.json exists and its mode. I never read it or print a value.
- Every claim about this machine carries the command that produced it.
- Where the page and this machine disagree, the machine wins and I record the contradiction.
1 — FETCH
https://docs.utopiamodels.ai/docs/reference/context-assembly.md
If the fetch fails, say what you got and stop. Then run `claude --version`. The page was measured against v2.1.251; if mine differs, say so — every claim below is then a claim to check, not a fact.
Tick box 1.
2 — THE LOAD ORDER, HERE
Walk the four scopes the page names, broadest to most specific — managed policy (/etc/claude-code/CLAUDE.md on Linux/WSL, /Library/Application Support/ClaudeCode/CLAUDE.md on macOS), ~/.claude/CLAUDE.md, ./CLAUDE.md or ./.claude/CLAUDE.md, ./CLAUDE.local.md — plus every CLAUDE.md in each directory ABOVE my cwd. For each: exists or not, byte count, line count.
Then resolve every @-import in those files, following up to four hops, relative paths against the file that contains them. The page is explicit: imports expand at launch and save nothing. Count them in the total.
Then .claude/rules/*.md at user and project scope: which carry `paths:` frontmatter (load only when a matching file is read) and which do not (load at launch, like CLAUDE.md).
Tick box 2.
3 — ALWAYS-ON VERSUS ON-TRIGGER
Split everything you found into two columns:
ALWAYS system prompt · auto memory MEMORY.md (first 200 lines / 25 KB) · MCP tool NAMES · skill
DESCRIPTIONS · every CLAUDE.md in the walk · unscoped rules · everything they @-import
TRIGGER full skill bodies · path-scoped rules · subdirectory CLAUDE.md below cwd (loads on a Read
there, never on a Write) · MCP schemas
Give the ALWAYS column a total in bytes. Flag any CLAUDE.md over 200 lines (advisory) and any over 4 MiB (skipped ENTIRELY, with no error).
Tick box 3.
4 — THE FIVE SILENT FAILURES
The page names five that produce zero error output. Check each here and answer present / absent / inconclusive, with the command:
a skill whose description names a TOPIC rather than an OCCASION — list every one
skill descriptions over 1,536 chars, and whether the listing overflows its budget — if it does, the least-used skills lose their descriptions and stop firing
malformed skill frontmatter — /skill-name still works, auto-invocation is dead
permissions, hooks or env written into ~/.claude.json, which is not a settings file and is never read for them
a repo that relies on permissions.allow while being run with -p or the SDK, where it is silently not applied but its hooks, env and .mcp.json still run
Tick box 4.
5 — EXPLAIN IT BACK
In five short paragraphs, each tied to something you measured in steps 2–4 rather than to the page:
why CLAUDE.md files concatenate rather than override, and which of mine now sit together
why CLAUDE.md arrives as a user message and not in the system prompt, and what does modify the system prompt
what the next /compact will drop from this session that I would not expect
which of my skills would fire right now, and which exist and are inert
the one line in my always-on files costing the most for the least
Then ask me with the `AskUserQuestion` tool to run /context in this session and paste its grid — RECOMMENDED: yes, because it is the only view of what ACTUALLY loaded, with the source each piece came from, and your walk is a reconstruction. Diff your map against it and name every mismatch.
Tick box 5.
6 — WRITE AND FINISH
Write CONTEXT-MAP.md in the directory I launched you from, with exactly these headings, because prompt 2 reads them:
## LOAD ORDER every file, scope, bytes, lines, @-imports resolved
## ALWAYS vs TRIGGER the two columns and the always-on byte total
## SILENT FAILURES the five, each with its verdict and command
## /CONTEXT DIFF what /context showed that the walk missed, and the reverse
## CONTRADICTIONS where this machine disagrees with the page
Then say exactly this:
"Context map complete. Paste prompt 2 from docs.utopiamodels.ai/docs/reference/context-assembly to fix what it found."
Then stop.
Tick box 6.Fix my context setup, one confirmed change at a time
Proposes every fix to your context setup from the map prompt 1 wrote, then applies each one you confirm, backing up any file first.
PROMPT 2 of 2 — fix how my Claude Code setup assembles context, from the map prompt 1 wrote. Propose everything first. Write nothing I have not confirmed.
HOW LONG THIS TAKES: a multi-step fix (one confirmed change at a time, a question per change) — expect roughly 10–30 minutes, depending on how many changes the map found across several turns. Running headless with a timeout? Budget for that, or start with a shorter prompt first. Cut off partway? Paste this prompt again — it resumes from its checklist rather than starting over.
ASK EVERY QUESTION WITH the `AskUserQuestion` tool, one at a time, RECOMMENDED option first with one line of why. If I accept every recommendation without reading, I must end with a setup that loads less and fires more.
READ THE MAP FIRST
./CONTEXT-MAP.md
If it is missing, stop and tell me to run prompt 1. Fixing a context you have not measured is guessing. Then re-fetch https://docs.utopiamodels.ai/docs/reference/context-assembly.md — the limits below are its numbers, not yours.
CHECKLIST TO A FILE
RESUMING? Before you write anything, check whether ~/CONTEXT-ASSEMBLY-BUILD-CHECKLIST.md already exists. If it does, this prompt was interrupted: read it, tell me which steps are already ticked, and continue from the first unchecked step. Do not overwrite it, do not redo a ticked step, and do not re-ask a question whose answer it already records — the scope answer under ## Rules included, if it's there. If ## Rules has no Scope field, this checklist predates the scope question: say so plainly in your first output line and ask it now, before anything else. Only if the file does not exist, write it fresh as below.
Write ~/CONTEXT-ASSEMBLY-BUILD-CHECKLIST.md — one task per change in the manifest, plus the rules below — and work from it. Tick as you go.
## Rules
- Before editing ANY existing file I copy it to <file>.bak-context-assembly, and I never edit a file I did not create without a the `AskUserQuestion` tool yes.
- I never touch ~/.claude/.credentials.json, and I never commit .claude/settings.local.json, CLAUDE.local.md or anything under ~/.claude/.
- I paste REAL command output. I never write "verified" without the output above it.
- If a change does not do what I said it would, I say so, restore the .bak, and stop.
SCOPE — ASK ME BEFORE YOU SURVEY ANYTHING OF MINE
Before step 1, ask me this with the `AskUserQuestion` tool, with both options exactly as written:
"Should I treat any path as off-limits, or do you want me to have full access to survey and propose changes anywhere in this environment?"
A — Exclude .env*, credentials and CI/deploy config (.github/workflows/, deploy keys) from anything I read or propose touching. [RECOMMENDED for most readers]
B — No exclusions. Full access to survey and propose anywhere, including secrets and CI files.
This is my preference, not a policy: some people want their agent to reach everything, some do not, and neither answer is the correct one. Never assume it and never pick for me. My answer governs every read and every proposal for the rest of this prompt. Write my answer under ## Rules in the checklist as "Scope: A" or "Scope: B", so it survives compaction. It governs the SURVEY and PROPOSE steps only — nothing gets written until step 2, and there one confirmed change at a time.
Before you ask, decide whether an answer can reach me at all. It cannot in a one-shot non-interactive run — `claude -p`, `codex exec`, `gemini -p`, a scripted or CI invocation — and you can tell without guessing: the `AskUserQuestion` tool is missing from your tool list there, while an interactive session has it. It also cannot if the question comes back immediately with no real answer. In either case do not ask, do not wait and do not re-ask: a question asked as plain text in a one-shot run ends the run with nothing done. This is the one case where you pick for me: treat A as my answer, record and hold it exactly as above, and make the first line of your output exactly: "No interactive scope answer available — defaulted to A (excluded .env*, credentials and CI/deploy config). To choose B, re-run this prompt in an interactive session and answer the scope question."
Only if the `AskUserQuestion` tool is in your tool list but fails when you call it, ask the same question as plain numbered text in one message instead.
1 — PROPOSE THE MANIFEST, THEN STOP
From CONTEXT-MAP.md, build one list, ranked by bytes saved or skills revived per line changed. Draw only from what the map found. The kinds of change this page supports:
REWRITE a skill description from topic to occasion — "keywords users would naturally say" is the documented fix. Show old and new side by side.
TRIM a description over 1,536 chars, or retire a skill, when the listing overflows — a working skill can stop firing because others were added.
REPAIR malformed skill frontmatter.
MOVE permissions, hooks or env out of ~/.claude.json into ~/.claude/settings.json, where they are actually read.
SCOPE a rule with `paths:` frontmatter when it only matters for some files, so it stops loading every session.
SPLIT a CLAUDE.md over 200 lines: what is a behaviour stays; what is reference moves to a path-scoped rule or a file the pointer names. An @-import is NOT a saving — it expands at launch.
ADD one InstructionsLoaded hook that appends to a log which instruction file loaded, when and why — the documented way to see the walk rather than reconstruct it. Remember: stderr on exit 0 reaches the debug log only, never Claude.
Where a repo is run with -p or the SDK and relies on permissions.allow, name it — that allow is not applied there — and propose a deny in settings instead.
For each: the file, the exact change, the bytes it moves out of ALWAYS, and the line of this page it rests on.
Print the manifest and WAIT. Do not change a file. A manifest is one screen and I will see a wrong assumption in it; twenty edited files hide it for a week.
Tick.
2 — CONFIRM, ONE CHANGE AT A TIME
Ask with the `AskUserQuestion` tool per change: [apply — RECOMMENDED] [skip] [change it]. Apply only what I accept, backing up first. Record each answer in ~/CONTEXT-ASSEMBLY-BUILD-CHECKLIST.md.
Tick.
When the writes are done, tell me in one line, filled in with the real paths:
"To undo, delete `~/CONTEXT-ASSEMBLY-BUILD-CHECKLIST.md` and move each `<file>.bak-context-assembly` back over its original (`mv <file>.bak-context-assembly <file>`) — nothing else on your system was touched."
3 — PROVE IT
Paste real output for each:
the always-on byte total before (from the map) and after, re-measured the same way
a sentence that SHOULD fire each rewritten skill → it fired; one that should NOT → it stayed quiet. A skill that fires on everything is as broken as one that fires on nothing, and only the negative test catches it.
if you added the InstructionsLoaded hook: `claude -p "reply ok"` from the project, then the log lines it wrote
ask me with the `AskUserQuestion` tool to run /context in a FRESH session and paste it — RECOMMENDED yes, because a hook or a CLAUDE.md edit takes effect on the next session, never the running one
Tick.
FINISH
Every file changed with its .bak path, the before/after always-on total, both skill tests per rewritten skill, and what you proposed that I declined. Append a ## CHANGES section to CONTEXT-MAP.md so the next run starts from the new truth.
Then say exactly this:
"Context setup fixed. Always-on went from [X] to [Y] bytes; [N] skills now fire that did not."
Then stop.Many module prompts on this wiki say "find the always-on instruction file this harness loads every session." This page answers that instruction. Every module here targets Claude Code as its one harness, so the answer is for Claude Code, with real paths.
Researched 2026-08-30 against primary sources. Each claim is marked CONFIRMED, with the page or source file it came from, or UNCONFIRMED. Where a doc contradicts the shipped source, we trust the source and record the contradiction.
Read the marks. We use this file to write commands that must actually work, so a named gap is more useful than a plausible guess.
Before you trust any of it: the doc tree moved in 2026
Older guides point at URLs that now return 404. An agent that fetches them gets nothing and reports that.
| Old location | 2026 location |
|---|---|
code.claude.com/docs/en/docs/claude-code/<page> (returns 404) | code.claude.com/docs/en/<page>, with the index at /docs/llms.txt |
Claude Code (CLI)
We measured against v2.1.251 on Linux/WSL2 as well as reading the docs.
A. Context assembly
Claude Code loads these scopes from broadest to most specific (CONFIRMED, /docs/en/memory):
| Scope | Path |
|---|---|
| Managed policy | macOS /Library/Application Support/ClaudeCode/CLAUDE.md, Linux and WSL /etc/claude-code/CLAUDE.md, Windows C:\Program Files\ClaudeCode\CLAUDE.md |
| User | ~/.claude/CLAUDE.md |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md |
| Local | ./CLAUDE.local.md |
The files concatenate. None of them overrides another. The docs say "All discovered files are
concatenated into context rather than overriding each other… ordered from the filesystem root down to
your working directory." Within each directory, CLAUDE.local.md is appended after CLAUDE.md. It is
not deprecated (CONFIRMED, the docs still describe it as live).
Claude Code delivers CLAUDE.md as a user message after the system prompt, not as part of the system prompt (CONFIRMED). Output styles are what modify the system prompt.
Claude Code walks upward at launch and downward only on demand. It loads files from the working directory
"and every directory above it." A file in a subdirectory loads only when Claude reads a file in that
directory with the Read tool. It does not load at launch, and it does not load when Claude writes or
creates files there (CONFIRMED, /docs/en/debug-your-config).
The import syntax is @path/to/import. Imports follow at most four hops. A relative path resolves
against the file that contains the import, and @~/.claude/foo.md works. Imports expand at launch, so
they do not save any context.
.claude/rules/*.md is the 2026 mechanism for rules. A rule file without paths: frontmatter loads at
launch with the same priority as .claude/CLAUDE.md, and user rules load before project rules. A rule
file with paths: loads only when Claude reads a matching file. The brace-expansion budget is 1,000
patterns or 4 MiB. Claude Code uses an over-budget pattern unexpanded, and it then matches nothing.
The docs split what loads every time from what loads on a trigger (CONFIRMED, /docs/en/context-window;
the token counts are the doc's own). Every session loads the system prompt (~4,200), auto memory
MEMORY.md (~680), environment info (~280), MCP tool names only (~120, with schemas deferred), skill
descriptions only, and then user and project CLAUDE.md. A full skill body loads only when the skill is
used. Once loaded, it stays in the conversation for later turns.
These are the documented limits:
| Limit | Value |
|---|---|
| CLAUDE.md hard limit | 4 MiB. Claude Code skips a larger file entirely |
| CLAUDE.md advisory | under 200 lines |
Auto memory MEMORY.md | first 200 lines or 25 KB |
| Skill description in listing | truncated at 1,536 chars |
| Skill listing budget | 1% of context window, fallback 8,000 chars |
| MCP tool description | 2 KB each |
| Number of skills | no documented cap. The budget is the real limit |
Compaction
After compaction, Claude Code re-injects project CLAUDE.md, unscoped rules, auto memory and the plan from disk. It brings back files Claude read, for up to five files. Invoked skill bodies come back at 5,000 tokens each, with a 25,000 total. Context added by hooks is summarized away.
The skill listing is the surprise. Claude Code does not re-inject it after /compact, so from then on
Claude can auto-invoke only the skills it already used in that session (CONFIRMED). No page we fetched
mentions "microcompact", so that term is UNCONFIRMED.
Showing what is loaded
Use /context [all]. It shows a colored grid that breaks out the system prompt, MCP tools, subagents
with the source each one loaded from, memory files and skills. /memory lists locations, including
files that do not exist yet, rather than what actually loaded. /status shows the active settings
sources. /doctor is now a bundled skill rather than a screen.
B. Inputs and outputs
The permission modes are default (alias manual), acceptEdits, plan, auto, dontAsk and
bypassPermissions (CONFIRMED against the binary). Claude Code evaluates deny rules, then ask rules,
then allow rules, and the first match wins. A more specific rule does not change that order, so a broad
Bash(aws *) deny beats a narrow Bash(aws s3 ls) allow.
Two syntax traps are worth memorizing. Bash(ls *), with a space, does not match lsof, but
Bash(ls*) does. In Read and Edit rules, /path is relative to the settings source and not to the
filesystem root. The absolute form is //path.
Sandboxing works on macOS (Seatbelt) and on Linux and WSL2 (bubblewrap). Native Windows and WSL1 are
unsupported. By default the sandbox allows writes to the working directory plus any --add-dir. It
allows reads of the entire computer except denied paths, which still includes ~/.aws/credentials and
~/.ssh/.
MCP servers have three scopes. local is the default and lives in ~/.claude.json. project lives in
.mcp.json at the repo root. The third is user. The transports are http, sse (deprecated), stdio and
ws. Each machine must approve a project server once.
Subagents live in .claude/agents/ and ~/.claude/agents/, and each one gets its own context window.
The precedence is inverted between the two. For skills, a personal skill overrides a project skill. For
subagents, a project subagent outranks a user one. The built-in Explore and Plan subagents skip CLAUDE.md
and git status, while custom subagents load it as usual.
Claude Code has 33 hook events (CONFIRMED, /docs/en/hooks). One of them is InstructionsLoaded, which
fires when a CLAUDE.md or rules file loads. The docs name it as the way to "log exactly which instruction
files are loaded, when they load, and why." Exit code 2 blocks absolutely. It overrides JSON output, and
not even permissionDecision: allow can override it. On exit 0, stderr goes only to the debug log and
never reaches Claude. PreToolUse fires before any permission check in every mode, including
bypassPermissions. Even so, a hook allow cannot loosen a deny in settings.
For headless runs, use claude -p with --output-format text|json|stream-json, and --json-schema for
structured output. The exit code is 0 on success, non-zero on failure and 143 on SIGTERM. --bare skips
discovery of hooks, skills, commands, subagents, plugins, MCP and CLAUDE.md, and it never reads the
keychain. The docs say it "will become the default for -p in a future release." The SDK packages are
@anthropic-ai/claude-agent-sdk and claude-agent-sdk. The package @anthropic-ai/claude-code is not
the SDK.
C. State on disk
We checked these paths directly on a live install as well as in the docs.
~/.claude/CLAUDE.md user memory
~/.claude/settings.json permissions, hooks, env, model
~/.claude/settings.local.json written BY Claude Code on "don't ask again"
~/.claude/.credentials.json mode 0600 — Linux/WSL/Windows (macOS uses Keychain)
~/.claude/projects/<munged-cwd>/<uuid>.jsonl full transcript: every message, tool call, result
~/.claude/projects/<project>/memory/MEMORY.md auto memory, keyed by GIT REPO (worktrees share it)
~/.claude/history.jsonl every prompt ever typed, with timestamps
~/.claude/{skills,agents,plugins,shell-snapshots,file-history,state}/
~/.claude.json MCP servers, trust decisions, OAuth account — NOT settings~/.claude/todos/, statsig/ and logs/ are legacy, and Claude Code no longer writes to them. Tooling
that reads them reads stale data. CLAUDE_CONFIG_DIR moves all of these paths.
Never commit .claude/settings.local.json, CLAUDE.local.md, .credentials.json or anything under
~/.claude/. One catch is that Claude Code adds settings.local.json to your global git excludes, not
to the repo's .gitignore. If you create the file by hand, you have to exclude it yourself. Transcripts
are also not encrypted at rest. If a tool reads a .env, its values end up in the session .jsonl.
D. The most common silent misconfiguration
If a skill's description names a topic rather than an occasion, the skill never fires. It shows up in
/skills, loads and appears in the listing, and does nothing, with no error output. The docs say to fix
it by including "keywords users would naturally say."
Four more fail just as quietly:
- Claude Code truncates skill descriptions without warning, or drops them. When the listing overflows its 1% budget, Claude Code "drops descriptions starting with the skills you invoke least." A skill that worked can stop working only because you added other skills.
- If a skill's frontmatter is malformed, Claude Code loads the body with empty metadata.
/skill-namestill works, but auto-invocation stops. ~/.claude.jsonis not a settings file. Claude Code never readspermissions,hooksorenvwritten there.- In
-pand the SDK, the trust gate fails open in the wrong direction. Claude Code silently skips the repo'spermissions.allow, but it still runs the repo's hooks,envand.mcp.jsonservers.
What this page does not establish
We list these because a named gap is more useful than a guess:
- We do not know whether Claude Code's CLAUDE.md walk stops at the repo root or continues to
/. No current doc mentions "microcompact".
Module: running dispatched agents on a Linux server for maximum execution efficiency
Four steps. You study a fleet that runs, design yours around what your machine has, build it, and dispatch one real task from start to finish.
Reference: the agent-to-agent channel
How an agent in one fleet tells an agent in another fleet something. It cites pages by URL in three lines and never pastes them.