Claude Code // Field Manual · Part II
measured 25 aug – 1 sep 2026
every number by command
About this manual

What Surrounds a Window was written by Serge Osaulenko (Selenko) in September 2026, from measurements — not vendor docs — taken on his own production Claude Code environment: a multi-seat system of specialist project folders (a strategy seat, an engagements engine, a study project, and more) governed by a written constitution for AI workers he calls DNA Core. Examples in this public edition are genericized; every behavior described was observed on that live system and graded across 21 revisions. The eval bench behind the grades is his as well; a public edition may follow.

PUBLIC EDITION OF THE SEPTEMBER 2026 MANUAL · © 2026 SERGE OSAULENKO / SELENKO · SHARED WITH ATTRIBUTION (CC BY 4.0)

The core idea

What surrounds a window

A window starts out knowing nothing. Then four different places each push something into it — rules, skills, tools, helpers. Every confusing thing here is one of two questions being mixed up.

2

Two questions, two different switches

Supply — does this thing exist in the window at all? Decided by where it lives and what scope it's switched on for.
Reach — is this particular window allowed to use it? Decided by the helper's own file. Keep them apart and everything else follows.

The four placements — and how far each one reaches

LAYER 1
The machine floor
~/.claude/ — house rules, your 34 helpers, settings, the memory cabinet, machine-wide connections
every window, every folder, always
LAYER 2
The folder you open
<project>/CLAUDE.md plus every folder above it, added together — decides what a window knows
only windows launched here
LAYER 3
The helper's own file
--agent <name> — its job, its model, the tools it may hold. The only layer that can take things away
travels with the helper
LAYER 4
Handed in at launch
--settings · --plugin-dir · --mcp-config · --append-system-prompt — rules, a plugin, a connection, even rulebook text — for this run only
this one launch
Aa
Words, before anything else (v20 policy). The vendor's own terms lead on every page: CLAUDE.md, rules, auto memory, skills, subagents, MCP servers, hooks, permission rules, sandbox, plugins, user / project / local scope, auto-compact. The pictures this manual uses — the floor, the folder, helper, rulebook, drawer, doorman — are ours, invented here as memory aids. Wherever one appears it is marked here: helper, and the Glossary page maps every nickname to the official word, so nothing you read elsewhere sounds foreign. Older pages still say helper and rulebook in their body text; the glossary is the bridge until they are swept.

The third question — WHEN it arrives

WHAT arrives

Instructions, tools, an identity, walls, checks, meters, a way to move it all. Nine jobs — the page The Nine Jobs.

WHERE it comes from — and how far it reaches

Four sources. Vendor terms first: user scope (~/.claude/) · the working directory and its parents · the agent file · the launch flags. here: floor · folder · file · flags

WHEN it enters

Five moments: launch · turn · dispatch · compaction · stop. A path-scoped rule is instructions (what), from the project folder (where), at the first matching read (when). One thing, three coordinates — the page When Things Arrive.

The seven direction rules — each mechanism has one home and reaches one way

1 · CLAUDE.md stacks upward. Open a deep folder and every CLAUDE.md above it loads too — user, then any folder above, then the project. Only the CLAUDE.md family stacks. measured
2 · Settings stay home. A folder's hooks, permission rules and plugin switches bind the launch folder only; a subfolder launch does not inherit them. "Project scope" means the folder you launched in. measured twice
3 · Agents climb to the repo root. Agent files are found walking up from the launch folder, but only as far as the git repository root. vendor doc
4 · Things below wake on touch. A nested CLAUDE.md, a nested skills folder, a path-scoped rule — none load at launch; they arrive when Claude reads a file down there. measured (rules)
5 · Auto memory follows the git repository. Every subfolder and worktree of one repo shares one memory directory; outside a repo, the folder itself. measured
6 · The agent's kit travels. Whatever an agent file carries — tools line, skills, hooks, its own memory — goes wherever that agent is launched or dispatched. measured (tools, hooks, skills)
7 · A CLAUDE.md can be pulled sideways, for one launch. --add-dir plus CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 loads the added folder's CLAUDE.md and rules for that run only. vendor doc · untested here

These seven answer the folder-above-your-projects question in one line: a folder above contributes exactly one thing to the projects beneath it — its CLAUDE.md (rule 1). Its settings stay home (2), its agents are scanned only inside the same repo (3), and memory ignores it unless that folder is the git repository (5).

!
The one sentence: the folder decides what a window knows. The helper decides what it can do — and it decides it the same way however the helper arrives: from the machine floor (Layer 3, --agent name) or carried in by a plugin at launch (Layer 4, --plugin-dir … --agent plugin:name). And because rules and hooks both obey the folder, the helper file and the launch are the only two ways out of it.
✓
That "however it arrives" clause was tested before it went on this page. The prototype's listing-analyst — a helper that exists only inside a plugin — was launched with --plugin-dir and --agent real-estate:listing-analyst, then asked to name every tool it could call: Read, Write, Bash — nothing else. No skills listed, no roster, no mcp__ tool. Identical fencing to a floor helper. One leak worth knowing: the outside services' instruction text (~1.9 KB) still arrives — describing tools the seat cannot reach. Text leaks; tools don't.

The launch line, as you'd actually type it

TERMINAL — four launches, one folder
~/Projects/strategy-seat $ claude
  a launch with empty hands: floor + folder + memory + every tool

~/Projects/strategy-seat $ claude --agent gap-checker
  Layer 3 applied: skills listed, no Write, no roster, no outside tools

~/Projects/strategy-seat $ claude --plugin-dir ~/Projects/strategy-seat/tools/lab/example-marketplace/real-estate --agent real-estate:listing-analyst
  Layer 4 supplies the helper, Layer 3 fences it: Read, Write, Bash — nothing else (tested)

~/Projects/strategy-seat $ claude --settings ~/ring-rules.json --mcp-config ~/one-server.json --append-system-prompt "House rule for this run only."
  three things handed in, none of them known to the folder. all three arrived (tested)
?
How every cell on these pages was settled. Not by asking "are you sure?" — by asking "what else would look exactly like this?" and building a test that tells the two apart. One window proposes a reading; a different window names the other thing that could produce the same observation; a cell is run that separates them. Today that killed three readings and confirmed two, between this window and a peer seat, in both directions. Amber on these pages means the separating test has not been run yet — not that the answer is unknown, but that two explanations still fit.
The launch is just Enter

Typing claude is a launch with empty hands. Every flag is more words on that same line — and they stack: --agent gap-checker --plugin-dir … took effect together, each layer still doing its own job in order.

Too late once open

Equipment is assembled at Enter. The CLI's own words for a dropped-in plugin: "auto-loads next session." To change what a window is, close it and launch its successor — nothing durable lives in the window.

The master off-switch

--bare skips hooks, plugins, memory and rulebook discovery in one word — every layer on this page, disabled at once. The only way to see a truly naked window.

The window lab

Move the levers.
Watch what lands.

Four levers on the left; the window on the right shows exactly what arrived, from which layer, and what exists but cannot be reached. Every line has a WHERE FROM button naming the file it came from.

Presets — one click loads a configuration. Every lever stays live afterwards: change anything.
No preset loaded yet — the levers show your setup today.
1 · Which folder you open
2 · How you launch
3 · Plugins installed — three homes for the switch

Installing writes one on/off line (enabledPlugins) into one of three files. The scope buttons pick which file — the line under them names it, and who that file reaches.

4 · Handed in at launch — the fourth way in

No file at all: the launch line itself carries the thing in, for one run. If the same plugin is also installed, nothing loads twice — the handed-in copy replaces the installed one for that run (measured 28 Aug, two distinguishable copies).

0
tokens before you type
What this configuration shows

Where the numbers come from

Measured

The 28 skills (5,304 tokens always-on), the helper roster (~10,600, from measured sizes), the strategy seat rulebook (~18,500) and memory (~6,250), the outside-tool list (~3,075), the real-estate plugin's four slots (~630: agents 267, skills ~230, MCP tool 131 deferred — /context, 30 Aug).

Illustrative

The monolith and real-estate folder rulebook sizes, the floor briefing, and the house rules. Real folders, plausible sizes. The meter is about the relative size of layers, not exact figures.

Fences

Some fences cut
one at a time.
Some cut everything.

A helper's file is the only layer that takes things away — but it doesn't fence every kind of thing the same way. That difference is the one you need to design around.

WhatHow the helper file fences itVerified on this machine
Built-in toolsper item Read, Write, Bash… each named individually on the tools linehome-lead holds Read and Write only — no Bash
Outside-service tools (MCP)per item each tool named individually — a helper can hold a server's read tools and not its send toolinbox-digest: the Gmail read tools, never send. The connection runs; the tool is simply absent
The helper rosterper item Agent(gap-checker, general-purpose) names exactly who may be dispatched; no Agent tool at all means no roster arrivesgm names two; a one-worker seat carries 812 B of roster instead of 42,473
Skillsall or nothing for the listing: the Skill tool is present or absent. But a helper file can ADD: a skills: list preloads those skills' full bodies into a dispatched childgap-checker sees 28; home-lead sees none at all. Preload measured today: the skill's marker arrived in a dispatched child's first turn — and did nothing on a --agent launch
Rulebooks (CLAUDE.md)not fenceable no key in the helper format excludes a rulebookevery helper reads its launch folder's rulebook in full
Memorynot fenceable no memory key in the formatmeasured across all 34 helper files
Hooksnot fenceable — only addable a helper file can carry its own Stop check; it cannot remove a floor hook32 of 34 carry the produce-then-verify check
=
The rule: tools are fenced one at a time. Skills are fenced as a set. Knowledge and rules aren't fenced at all — they arrive with the folder, whoever you are. And the helper file subtracts AND adds: the tools line removes; skills: (measured), hooks: (measured), mcpServers: and memory: (vendor docs) put things in.
↩
The bypass, proven: a helper with no skill tool was asked to open a skill file and report its first step. It did. The skills fence is around the listing and the shortcut, never around the contents — anything that can read a file can follow a skill.

A fenced helper walks into the strategy seat folder — what it gets, item by item

RULEBOOK + MEMORY
arrives
Not fenceable. The whole strategy seat rulebook and memory index land, same as for a plain window.
SKILLS
nothing
home-lead has no Skill tool → no listing at all. It can still read a SKILL.md by path.
HELPER ROSTER
nothing
No Agent tool → the roster is never delivered. A helper with Agent(x, y) would get exactly x and y.
OUTSIDE TOOLS
nothing
Its tools line names no MCP tool. inbox-digest, by contrast, names the read tools and gets exactly those.
Subagents here: helpers

Where a helper
comes from — and what it arrives with

A helper is a file: a name, a description, a tools line, a model, its instructions. That file is its identity. Where the file sits decides who can see it. Where it is launched decides what it knows. Those are three different things, and every confusion about helpers is two of them being read as one.

The four places a helper's file can come from — every row tested

HomeWho can see itOn this machineEvidence
~/.claude/agents/every seat, launched anywhere — and every window pays ~1,250 B of roster for each34 helpers — your entire rostera /tmp window and a brand-new folder both listed all of them
<project>/.claude/agents/only seats launched in that folder; subfolders don't inheritunused — absent in strategy seat, monolith, message couriera probe helper planted there was found by name from that folder and not found from strategy seat, both as a dispatch and as a launch
inside a pluginwherever the plugin's scope reaches; prefixed real-estate:listing-analystmonolith carries none; the prototype carries tworoster 35 → 37 with the plugin, 35 → 41 with a 6-helper plugin
handed in at launch — --agents '{json}'that one window, and the children it dispatchesnever used heretested today: an inline helper joined the roster, was dispatched (returned its marker, held exactly Read), and a window was launched as it
TERMINAL — the fourth channel, a helper that exists only on the launch line
~/Projects/strategy-seat $ claude --agents '{"probe-json": {"description": "A probe helper defined inline, for one run.", "prompt": "You are a probe. Your marker is PROBE-JSON-5150.", "tools": ["Read"]}}' --agent probe-json
  (1) marker: PROBE-JSON-5150        ← the identity came from the JSON
  (2) tools: Read only                  ← its fence held
  (3) sees the strategy seat rulebook: yes   ← the equipment came from the FOLDER
  (4) sees the strategy seat memory:   yes

Two verbs, one rule

Launch — the helper IS the window

claude --agent gap-checker. You talk to it. It gets the launch folder's rulebook, memory drawer and hooks, then its own file subtracts.

Dispatch — a window sends a child

The Agent tool, subagent_type: gap-checker. The child is born fresh and loads nothing of its own — it inherits the block the parent rendered at boot, then its own file subtracts.

!
Both verbs need the name on the roster of the seat doing the calling. A helper that exists on disk in some other project is not found from here — tested both ways. "Use the strategy-seat project's helper" from a monolith window really means "run this as the strategy-seat project": launch it there, and it brings the strategy seat's knowledge with it.

Universal identity is not universal knowledge

≠

The roster makes the WHO universal. The folder still decides the WHAT.

A floor helper is the same identity everywhere — same tools, same model, same instructions. But gap-checker launched in strategy seat reads the strategy seat's rulebook and memory; launched in monolith it reads monolith's. The inline JSON helper above proved the split in one cell: identity from the launch line, equipment from the folder. Floor = everyone knows, everyone pays · project = only here · plugin = wherever you switch it on · launch = this run.

Skills

A skill is a file.
The magic is the listing.

Every skill has two required pieces: a name and a one-line description. Everything under that is ordinary written instructions. What the system adds is the listing at boot and a tidy way to load it — nothing else.

~/Projects/monolith/plugins/monolith/skills/corpus/SKILL.md — the whole "mechanism"
---
name: corpus
description: "Use whenever you need information from the operator's knowledge home
  (~/Projects/knowledge-base) — business frameworks, venture facts, the operator profile…"
---

# Corpus — using the knowledge home
1. **Route** — read ~/Projects/knowledge-base/index.md …
2. **Pull** — read wiki/<slug>.md …
3. **Needle** — grep across wiki/ AND raw/ …

Two front-matter lines, then ordinary instructions. The description is the only part a window sees before it decides to load the skill — which makes it the entire routing mechanism.

The four homes — and what each holds on this machine, today

~/.claude/skills/<name>/
exists, empty
The machine floor. A folder dropped here loads on its own for every window, under its bare name. No install step.
<project>/.claude/skills/<name>/
works — proved
The project folder. A probe skill planted here was listed under its bare name for windows launched there. None of your projects use it today.
<plugin>/skills/<name>/
28 + 14 live here
Inside a plugin. Arrives prefixed (monolith:corpus, superpowers:brainstorming). Switched on per scope — and loaded from the installed copy, never your source. That is the pipeline below.
ships with the app
built in
Bundled. pdf, docx, design. Not yours to edit; always present.

The journey from your folder to a window — and the three places it breaks

Turn the breaks on and off. The first is on because it is true on this machine right now.

The costs, measured

In the listing: ~190 tokens per skill on every launch, used or not. The full instructions: 520 to 33,800 tokens, only when used. The listing is budget-capped and quietly shortens when it overflows — this machine runs that budget at double the default.
The no-tool fallback: a 7 KB index file any window can read on demand. Past a certain shelf size, reading a list beats being handed one.
Plugins

A folder you
switch on as one unit

Think of it as an app. It has a name and a version so the system can refer to it, and room for five kinds of thing — skills are only one of them.

The five slots · your monolith plugin fills one
Skills — 28 here
Agents — 0 here · proven elsewhere: join the roster immediately, prefixed real-estate:listing-analyst
Hooks — 0 here · proven: a rule inside a plugin fired in a folder with no connection to it
MCP servers — 0 here · the slot exists in the format, but see Where Things Live
LSP servers — 0 here

Not in the format: permissions and rulebooks. The CLI's component vocabulary is exactly agents · commands · hooks · lspServers · mcpServers · skills; 0 of 39 official plugins ship settings.

A marketplace is not required

It's an address book for finding plugins to install. A folder in ~/.claude/skills/<name>/ auto-loads on its own, and --plugin-dir carries one in for a single run with no install at all.

Install ≠ author

Install copies the plugin into ~/.claude/plugins/cache/. Windows load the copy. Your copy is 0.4.0 with 11 skills; your source is 0.5.6 with 28 — 17 skills authored, never published, for 35 days, with no error anywhere.

What the files look like — the prototype's, verbatim

.claude-plugin/plugin.json
{
  "name": "real-estate",
  "version": "0.1.0",
  "description": "A brokerage's listing and transaction craft…",
  "author": { "name": "Harborline Realty (illustrative example)" }
}
hooks/hooks.json — the rule that fired in a stranger's folder
{
  "hooks": {
    "PostToolUse": [
      { "matcher": "Read|Write|Edit",
        "hooks": [ { "type": "command",
                     "command": "python3 \"${CLAUDE_PLUGIN_ROOT}/hooks/stamp.py\"",
                     "timeout": 10 } ] }
    ]
  }
}

The folder layout is the whole format: .claude-plugin/plugin.json · skills/<name>/SKILL.md · agents/<name>.md · hooks/hooks.json · .mcp.json. Seven files made the prototype.

A second real plugin, installed today — and the scoping rule shown on it

superpowers 6.3.0 · from the official marketplace (source: github.com/obra/superpowers)
Skills — 14 (brainstorming, systematic-debugging, test-driven-development, writing-plans, using-git-worktrees …)
Hooks — 1: SessionStart on startup, clear and compact, running its own script. The CLI projects it as harness-only — no context cost
Agents · MCP · LSP — none
Always-on cost — ~688 tokens (the CLI's own projection), against monolith's ~5,304 for 28
Installed at PROJECT scope, on purpose — then measured
Window opened insuperpowers: skills seen
~/Projects/strategy-seat14
~/Projects/strategy-seat/reference0 — a subfolder does not inherit the switch
/tmp0
a child dispatched FROM an strategy seat windowlists them (10 counted by the probe) — it inherits the parent's render
a child dispatched from strategy seat/reference0 — the parent had none to render

So "scope" does two jobs. For a window it means which launch folder switches the plugin on. For a child it means nothing directly — a child sees whatever its parent had rendered at boot, plugin skills included. Measured, both rows.

The switch is one line in ~/Projects/strategy-seat/.claude/settings.json; the files sit in ~/.claude/plugins/cache/. Nothing else on the machine pays for it. That is the difference between this and monolith's user-scope switch, on two real plugins side by side.

Scope — who pays, and the surprise

Switched on atWho sees itEvidence
user (the default)every folder on the machinea window in /tmp sees all 28
projectwindows launched in that folder — and only that folderone settings line turned monolith OFF for a folder: 28 → 0
localsame, just yourecorded in settings.local.json
a subfolder of that projectreverts to the machine defaultlaunched in the subfolder: back to 28 — retested with a git root, same. "Project scope" means launch-folder scope
the launchthis run only--plugin-dir — helpers, skills, a working hook and (measured 28 Aug) its MCP server arrived; gone at close. Same plugin also installed? One copy loads — the handed-in one

The switch and the files — click through the four measured positions

A plugin is two things that are easy to conflate: where its files live and where its switch is. Pick one of each and watch what a window opened in the case folder actually loads — and what goes stale when you edit the source. Every position below was measured with the sample plugin on 30 Aug.

Where the files live
Where the switch is
Then you edit a skill in the source
≠
The two things, named: the switch is one line — enabledPlugins: {"real-estate@re-lab": true} — in whichever settings file the scope names. The files are wherever the marketplace points, copied to ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/ at install. Windows load the copy. --plugin-dir is the one path that loads the folder you name directly.
$
The scaling arithmetic: every window today loads ~24k tokens of agents and skills (/context, 30 Aug: agents 16k + skills 8k), everywhere. The sample real-estate plugin — two helpers, two skills, a working rule, and its own outside-tool server — costs ~630 (131 of it a deferred MCP tool; ~500 lands at launch). A folder doing only real-estate work could carry its full kit for about 2–3% of what it carries now. Skills are cheap to have many of; helpers are the thing to keep scoped — a skill loads its body only when used, a helper puts its whole description on the roster with no deferral.
✓
The sample plugin is real now (28 Aug). It moved from this session's vanishing scratchpad to ~/Projects/strategy-seat/tools/lab/example-marketplace/real-estate/, all four slots working — the MCP slot got a self-contained server (comps-db) after the OAuth-dependent one proved unbootable. One line each: claude plugin marketplace add ~/Projects/strategy-seat/tools/lab/example-marketplace (once) · claude plugin install real-estate@re-lab --scope local (swap the scope to watch the switch land in a different file) · claude plugin uninstall real-estate@re-lab --scope local · bash ~/re-plugin-demo.sh (section 4 in real life — handed in by path, nothing installed).
!
A plugin can also ship default settings — exactly two keys are honored (vendor doc; untested here). agent: the session boots as one of the plugin's own helpers — its prompt, tools and model become the main thread's, wherever the plugin is enabled. That is the key a rig-as-plugin would lean on: ship the trustee and make every window in scope open as it. subagentStatusLine: display formatting for dispatched helpers' status rows. Nothing else — no permissions, no rulebook, no memory.
Hooks

Rules that run,
not rules that are read

A hook is a small program that fires by itself at a fixed moment. It doesn't ask. That makes it the strongest rule you have — and it still obeys the reach rules of wherever it lives.

The moments — and which can say no

MomentWhenCan it stop things?
PreToolUsebefore a tool callprevents the only one that stops an action before it happens
PostToolUseafter a tool callcan block usually just records; blocking is a choice, not a limit
Stopa window tries to finishcan block refuses the exit, sends the window back to work
UserPromptSubmityou press Entercan block
SubagentStopa dispatched helper finishesbest-effort on leaf helpers — not guaranteed
InstructionsLoadedeach instruction file as it loadsobserves the instrument for this whole manual — tested today: it logged every rulebook with a load_reason (session_start · include · path_glob_match), the importing parent, and the glob that triggered a path-scoped rule. Two limits, measured: it does not log auto memory (MEMORY.md never appeared, even for a window whose memory clearly loaded), and it fires zero times for a dispatched child — because a child loads nothing; it inherits the parent's rendered block (confirmed by a timed test with a rule file written after the parent booted)
SessionStarta window bootsobserves / injects can ADD text — your floor briefing arrives this way
Notification · PostCompacteventsobserve only

The useful subset, not the inventory — the registry holds 31 moments. And a hook isn't only a script: command, prompt and agent kinds exist; the last two let a rule think before deciding.

Where a hook lives decides who it governs — try it

Pick a home. fires never sees it untested

~/.claude/agents/gm.md — a hook riding inside a helper file (escape one)
---
name: gm
model: opus
tools: Read, Write, Edit, Bash, Agent(gap-checker, general-purpose), ListAgents, SendMessage, Skill
hooks:
  Stop:
    - hooks:
        - type: command
          command: "~/.claude/hooks/stop-hook.sh"
        - type: command
          command: "~/.claude/hooks/capture-hook.sh"
---

Two things in one frontmatter: the tools line that fences (note Agent(gap-checker, general-purpose) — a roster of exactly two) and the hooks block that travels with the helper into any folder. 27 of your 34 helper files carry a Stop block like this.

Wired on this machine, today

The knowledge-home guard (PreToolUse, machine floor) — DENIES any write to the knowledge home before it happens. Two matchers, file tools and shell, plus a designed ceremony door.
register-postwrite (PostToolUse, machine floor) — records every write. Never blocks.
The seat Stop check (in the helper files) — the produce-then-verify gate, carried by 32 of 34 helper files so it travels anywhere. Plain windows exempt by design; dispatched helpers best-effort; a ring gets it only down the launch channel — probed: accepted, fired, block honoured. Its full reach map is its own page: The Stop-Hook Map.
The floor briefing (SessionStart) — a hook that ADDS: the shared log tail and pinned rules, injected at every launch. Why hooks aren't free even when they never block.
Three built, wired to nothing: blast-radius-guard · bash-exfil-guard · dna-liveness-probe. And the scar: engagement enforcement exists, is armed, and cannot fire on the engagements — they run from folders that load no hooks. Rebuilding those gates where they sit would change nothing.
Memory

A cabinet on the floor,
one drawer per folder

The right words: each fact is a memory file, they sit in a memory directory, and MEMORY.md is the index. Only the index loads at start; a memory file is opened when its line looks relevant. Cabinet and catalog.

Where the files sit vs. what selects them
you open     ~/Projects/strategy-seat
it becomes   -Users-you-Projects-strategy-seat  (every / turns into a -)
the drawer   ~/.claude/projects/-Users-you-Projects-strategy-seat/memory/

The cabinet stands on the machine floor — that is where the bytes are. But it has one drawer per git repository (outside a repo: per folder), and opening any folder of that repo hands you that drawer and no other. A drawer directory is created at every launch, so most of them are empty scratch folders. ~/.claude/memory does not exist — there is no global memory.

Shared across time, not across projects. Every window ever opened from strategy seat reads the same store. A monolith window asked for the strategy seat's first entry: no. strategy seat 161 · monolith 45 · consultant 11.
Follows the repository, not the folder. A window opened in strategy seat/reference/ was handed the strategy seat drawer — probed tonight. A category folder above your repos contributes nothing; make the category the repo and every project inside shares its drawer. (Section 08.)
The launch can suppress it — or redirect it. --bare skips auto-memory; --settings with autoMemoryDirectory pointed a window at a new drawer, created at launch (probed tonight).
~/.claude/projects/-Users-you-Projects-strategy-seat/memory/MEMORY.md — the index, first lines
- [strategy seat CLI port](strategy-seat-cli-port.md) — what the strategy seat is; phase-1 (Notion dead, knowledge read-only)
- [System roadmap](system-roadmap.md) — LIVING roadmap at reference/roadmap.md; read on strategy/sequencing
- [Title X vs Title Co](title-x-vs-title-co-distinction.md) — "Title X" (#146) = friend PM favor; NEVER his own Title Co
…  127 lines · 24,864 bytes · one line per memory file · the ONLY part loaded at start

The cabinet and the catalog — the strategy seat store, measured

THE CABINET
161
memory files on disk. One fact each, named by topic — a filing cabinet, not a diary. Edited in place when a fact changes.
THE CATALOG
124
files named by an index line — the only ones a session knows exist at start.
THE GHOSTS
37
files with no index line. Intact, invisible at boot, findable only by searching the folder. Some retired on purpose; the rest fell off.

The wall the index stands against

The documented limit: the first 200 lines OR 25 KB of the index — whichever comes first — load at start. Everything past that is silently dropped at load (the writer gets a warning; the reader gets nothing).
This store: 24,864 of 25,600 bytes — 97% full. About 4 index lines of headroom. Truncation is sequential from the bottom, so the newest entries vanish first. 127 of 200 lines used — the binding wall here is bytes.

What memory costs — try it

161 slim files and 161 heavy files cost exactly the same at boot, because only the index loads. Weight is paid per open, by the session that opens it.

6,218
tokens of memory in the window
Boot state: the index alone — 6,218 tokens, however heavy the cabinet is.

Who writes it, and the rules

The session itself writes memory — no scheduler. Triggered by you saying "remember this," or by a durable fact landing. The rules arrive with every session, in writing.
The rules: one fact per file · four types only (project 88 · feedback 57 · reference 11 · user 1) · update an existing file rather than duplicate · delete what turns out wrong · never store what the repo already records · write the index line in the same act.
Memory across projects

One window,
one drawer

The rulebook stacks — global, category and project all load. Memory never stacks: a window is handed exactly one memory directory. "User scope" is not a second layer on top of a project drawer; it is the same single slot, filled from a different settings file.

1

Exactly one drawer — verified four ways tonight

Vendor doc: "Claude Code uses the value from the highest level that sets it." · The schema: the key is one string, not a list. · The code: falls back to the user setting only when nothing higher sets it. · The probe: a scratch repo whose project settings said drawer X, launched with the command line saying drawer Y — the window named Y only, and X was never even created.

What decides the drawer — highest wins, nothing adds

Read top-down. The first level that names a drawer wins; every level below it is ignored for that window. Only when no level names one does the default apply.

MANAGED
An organisation's policy
Deployed by an employer or MDM. None on this Mac.
wins over everything
LAUNCH
The command line — --settings
One window, one run. Probed tonight: the window was pointed at a fresh drawer and the folder appeared at launch.
wins over the folders below
PROJECT · LOCAL
.claude/settings.local.json
Your personal setting for this one project — not committed to git.
wins over project & user
PROJECT
.claude/settings.json
The project's shared setting — committed, travels with the repo. This is the carve-out: set it here and the project uses its own drawer and no other.
wins over user
USER
~/.claude/settings.json — the machine floor
This is "user scope." The vendor's word for the machine-floor settings file every window on this Mac reads. Name a drawer here and every project uses it — unless a level above names its own.
the lowest setting
DEFAULT
No level set anything (your situation today)
The git repository's own drawer: ~/.claude/projects/<repo-path>/memory/. Every subfolder and worktree of one repo shares it. Outside a repo, the folder itself.
the rule when nothing is set

Try the setups — three of your projects, one slot each

Each switch is one real mechanism. Watch which drawer each project is handed, and who decided it. The paths under the switches are example values.

Switches — click to turn on

The five channels — the only ways memory crosses a project line

ChannelWhat it isWho shares the drawerOn this Mac
1 · Same repositoryThe default. Every subfolder and worktree of one git repo is handed the repo's drawer.All windows opened anywhere inside that repo.Probed: a window opened in strategy seat/reference/ was handed the strategy seat drawer. All seven folders under ~/Projects are their own repos; ~/Projects itself is not.
2 · autoMemoryDirectoryA settings key that points a window at any folder. Set in one project = that project's own drawer wherever it sits. Set at user scope = one drawer for every window on the Mac.Whoever shares the setting — one project, or the whole machine.Probed: a window launched with it named the new path and the folder was created at launch. Not set anywhere today.
3 · A second machine floorCLAUDE_CONFIG_DIR runs Claude Code on a separate floor — its own settings, plugins, memory, transcripts — like a second account. CLAUDE_CODE_PROJECT_DIR_NAME beside it lands every launch on that floor in one named drawer (v2.1.234+).Every launch under that floor, whatever repo it starts in.Not used. A fleet tool — a way to give headless seats (keepers, message courier, the box) a floor of their own with one shared memory.
4 · A helper's own notebookmemory: user | project | local in a helper file. The helper is born with its own index (same 200-line / 25 KB rule) and gets Read/Write/Edit for it. user → ~/.claude/agent-memory/<name>/ across all projects; project → inside the repo, committed; local → inside the repo, not committed.That helper only. Window and helper never see each other's drawer.One helper declares it (domain-researcher, memory: user); its directory has never been created — never used.
5 · What does not crossAdditional directories bring no memory (this window edits four other folders; its drawer is still the strategy seat's). A dispatched helper is born without the parent's memory — a fork is the exception, it copies the parent. The memory files themselves never load at start — only the index, 200 lines / 25 KB.Nobody.Measured this week: a child inherited the parent's rendered rulebook block, not its drawer.
?
ANSWERED BY THE VENDOR PAGE · BUDGET-BLOCKED · UNTESTED IN PRACTICE (relabelled 8/28; your "potential" marking stands until a test). The one bridge to a second index: an @~/.claude/projects/<other>/memory/MEMORY.md line in a rulebook. Mechanically valid — @ imports take absolute paths, four hops deep. But an import loads at launch, in full, so it adds a whole index to an always-on set already over its ceiling. And in a project rulebook an outside path triggers the one-time approval dialog: decline it once and the import stays disabled and the dialog never returns. User-scope rulebooks skip the dialog. Not written anywhere; not tried.
→
The design consequence. Knowledge every window must see cannot ride on memory — it rides on the rulebook layer (the user CLAUDE.md, ~/.claude/rules/), because that layer stacks and memory does not. That is exactly what constitution.md already is. And if several projects ever share one drawer, they share one index and one cap — the strategy seat's alone is at 97%.
Rules

The rulebook,
split into files

A rule is not a new kind of thing. It is a page of the rulebook kept as its own file — .claude/rules/<topic>.md, one topic per file — and loaded exactly like .claude/CLAUDE.md. None existed on this Mac when this page was first written. ⭐ That changed 2026-09-01: ~/Projects/study-project/.claude/rules/claude-code.md is a live always-on rule file. And it carries a measured finding of its own — an HTML comment inside a rule file does not reach the session it governs (19 lines on disk, 16 injected; the missing 3 were a comment block).

2

Two kinds of rule, two homes

A rule file with no paths: line is always-on: it loads at launch with the same priority as the project rulebook. A rule file that opens with paths: is path-scoped: it stays out of the window until Claude reads a file that matches, then arrives. Both were tested here this week with planted markers. The home decides who gets it: the machine floor reaches every project; a project folder reaches that launch folder.

HOME 1
~/.claude/rules/ — the machine floor
Personal rules for every project on the Mac. Loaded before project rules, so a project rule on the same topic wins.
every window
HOME 2
<project>/.claude/rules/ — the folder you open
Discovered recursively (subfolders allowed). Symlinks work — one shared rule set can be linked into many projects. Skipped if project is excluded from --setting-sources.
that launch folder
ALWAYS-ON
No paths: line
Arrives at launch. Re-injected from disk after a compaction, like the root rulebook.
measured: at launch
PATH-SCOPED
paths: ["reference/records/**"]
Absent at launch; injected the moment a matching file is read. Summarized away at compaction until a matching file is read again. One budget per rule: 1,000 expanded patterns / 4 MiB.
measured: on first matching read

Four things that look alike — told apart

CLAUDE.md
Who writes: you.
Loads: every launch, in full (up to 4 MiB).
Reach: the folder you open plus every folder above it — stacks.
For: standing instructions.
RULES
Who writes: you.
Loads: every launch — or only when a matching file is read.
Reach: machine floor or launch folder. Same layer as CLAUDE.md, one topic per file.
For: a big rulebook kept in pages; rules that should cost nothing until they apply.
SKILLS
Who writes: you (or a plugin).
Loads: the listing at launch; the body only when invoked or judged relevant.
Reach: per its home; fenced all-or-nothing by the Skill tool.
For: a procedure, run on demand.
MEMORY
Who writes: Claude.
Loads: the index only (200 lines / 25 KB); a memory file on demand.
Reach: one drawer per git repository — never stacks.
For: what Claude learned from you.

What one would look like — an example, not on disk

~/Projects/strategy-seat/.claude/rules/records.md — EXAMPLE ONLY (no such file exists)
---
paths:
  - "reference/records/**"
---
# Records
- Every record carries its date in the filename and a `class:` line at the top.
- A count stated in a record is produced by a command, never recalled.
- A record that names a live artifact's version is updated in the same act as the artifact.

Because of the paths: line this would cost the window nothing at launch and arrive only when a record is opened. The same three lines without paths: would load every time, like a page of CLAUDE.md.

Where this fits your floor. constitution.md is one long always-on page imported by the user CLAUDE.md. The same content split into ~/.claude/rules/*.md would load identically — same layer, same priority, one topic per file — with the option of parking the rarely-needed parts behind a paths: line.
Rules are not enforcement. Like CLAUDE.md, a rule is read and followed; it does not stop anything. The vendor's own line: to block an action regardless of what Claude decides, use a hook.
The evidence for the two measured kinds sits in the matrix (section 10), row "Rule files".

A path-scoped rule — where it takes effect, step by step

The rule does not follow the file around. It belongs to a launch folder, watches for a pattern, and lands in the window that reads a matching file — from that moment, for that session.

1 · it sits
in .claude/rules/
of the folder you open (or ~/.claude/rules/ for every project)
Opens with a paths: list — glob patterns, relative to the project.
→
2 · the window launches
not loaded
0 words of always-on cost
Measured: absent at launch. An always-on rule would already be in by now.
→
3 · Claude reads a matching file
trigger
e.g. reference/records/x.md
The doc says reads; measured with a Read. The pattern is matched against the file's path.
→
4 · injected — and logged
arrives
load_reason: path_glob_match · glob · trigger_file_path
The InstructionsLoaded hook names the rule, the pattern and the file that tripped it. Nothing on the floor uses this instrument yet.
→
5 · it stays — until compaction
for the session
then summarized away
The root rulebook and always-on rules are re-injected after a compaction; a path-scoped rule comes back only on the next matching read.
not measuredwhether an Edit or Write (not a Read) trips it · whether a file in an additional directory trips a rule from the launch folder · whether a dispatched child's read trips it (children load no instruction files of their own — measured this week) · whether a machine-floor rule's paths: resolves against each project.

Sharp edges the vendor documents (added 8/28)

A pattern can silently match nothing. Glob reads [ as a bracket expression; a [ it cannot parse makes that pattern match nothing while the rule's other patterns keep working — escape it as \[. Before v2.1.207 one invalid pattern failed the Read tool for every file the rule was evaluated against. For a privacy dial keyed on paths, this is the failure nobody notices.
Brace expansion is budgeted. A rule's whole paths: list shares 1,000 expanded patterns / 4 MiB; a pattern over budget is used unexpanded and its literal braces match nothing. Before v2.1.217 many brace groups stalled or crashed the CLI at startup.
Version edges. Symlinked-path matching from v2.1.198 · before v2.1.211 on-demand rules loaded even when project was excluded from --setting-sources.

How it could be used on your floor — five candidates, not decisions

Each row is a real folder on this Mac and a rule the floor already carries somewhere always-on. Behind a paths: line it would cost nothing until that kind of file is touched.

PatternWhat the rule would sayTrips whenToday it lives
reference/records/**A record carries its date in the filename and a class: line; a count in a record is produced by a command; a record naming a live artifact's version is updated in the same act.Any record is read.Always-on, in strategy seat/CLAUDE.md's reliability pass.
reference/decisions-ledger.mdThe ledger is provenance, not governance: a STANDING row names its standing home or is marked provenance only; file in the same act the ruling lands.The ledger is opened.Always-on, in strategy seat/CLAUDE.md (the ⭐⭐ standing-home rule).
tools/launch/**A standing seat rotates by pointer, never a composed boot; the launcher carries the rotation gate; a launcher is not charter-class and is not graded.A launcher is read or written.A memory card plus the roadmap's class row.
.claude/agents/**A YAML comment containing --- before hooks: ends the front matter and kills the helper's hooks; verify a helper's hooks by the fire log, never by reading the file.A helper file is touched.A memory card (the 8/26 scar).
clients/<name>/**That engagement's privacy dial — the one place HIPAA-class or "never store" material would be walled, per client, as you ruled 8/26. Every other engagement stays default-open.That client's files are touched.Nowhere yet — the per-engagement dial has no home.

Where does a rule go — the decision, in order

MUST HAPPEN
It has to happen regardless of what Claude decides
A hook, a permission rule, or the sandbox. Not prose, anywhere. The vendor's own line.
enforcement
EVERYONE
You wrote it; every window must have it at every launch
The machine floor: the user CLAUDE.md (what the constitution file is) or ~/.claude/rules/. Same cost, same priority — rules files are pages.
always-on
THIS PROJECT
Only windows opened in this folder
The project CLAUDE.md or .claude/rules/.
always-on
THESE FILES
Only when certain files are touched
A path-scoped rule. The one thing a rules file does that CLAUDE.md cannot. Today almost nothing on the floor keys on a file path — the daily control says so.
on demand
A PROCEDURE
Steps to run on demand
A skill — listed at launch, body loaded when invoked. The control names this as the real lever for the CLAUDE.md diet.
on demand
A LEARNING
Claude learned it from you
Memory. Many rules live there today as feedback cards — but only the index line loads, and the card only when opened. A rule you need followed should not live only there.
index only
The gauge that makes the choice real (daily control, read today): the always-on set is 17,528 words against a 17,000 ceiling — FAIL; strategy seat/CLAUDE.md is 354 lines against ~200. Adding an always-on rule means retiring one. The control's own verdict: "NOT via .claude/rules/: unscoped rules load at launch anyway and save nothing… The lever is moving the multi-step procedures to a SKILL." Two more remedies the vendor names (added 8/28): claudeMdExcludes — skip a named CLAUDE.md or rules folder by path or glob, at any settings layer, arrays merging (managed files cannot be excluded); and /doctor, which proposes trims of what Claude can derive from the codebase (v2.1.206+). And a hard edge: a CLAUDE.md over 4 MiB is skipped entirely, not truncated.

Three verbs that get mixed up — and the instrument for each

LOADED
Did the rule reach the window? Instrument: the InstructionsLoaded hook — names every file, when, and why. Fired 7 times in this week's test. Unused on the floor. Cheapest check, no hook: /context lists what loaded under Memory files.
ENFORCED
Was the act stopped or forced at the moment? Instrument: a hook (PreToolUse blocks, Stop refuses to finish), a permission deny, the sandbox. Your floor runs hooks on six events.
FOLLOWED
Did the window actually do what the rule said? Instrument: a Stop hook that inspects the record, or a fresh grader that did not do the work. Loaded is not followed; the vendor promises no compliance for any instruction file.
⏳
The part that is genuinely open — and whose it is. Your one recorded decision ask that the four homes of a rule (the constitution file · a project CLAUDE.md · memory · the shared log) be "better organized" is OPEN — explained, not answered — owned by the knowledge track through the loading model. Your 8/27 rider that the constitution file reaches every dispatched seat you never talk to is filed in that same row. Whether the volume of always-on text degrades rule-following is your hypothesis, never measured here; the compliance-by-position numbers an earlier draft carried were struck.
Where things live

Every part,
every place

Rows are kinds of moving part. Columns are places. Click any cell for its evidence. Solid green was verified on this machine this week; outlined green is a standard mechanism not exercised here; amber is untested or inconclusive. Five cells that were amber yesterday were tested today.

The scaffolding — click any file to see what it is and what's in it

The real folders on this Mac, with the real contents of the files that matter (structure only where a file holds secrets). Each node names which layer it belongs to.

▸ this mac · click to expand · click a file to read it

The matrix — every part, every place

The direction rules — same tree, different answers

Rulebooks stack upward. Open a deep folder and every CLAUDE.md above it is added in.
Imports that leave the launch folder are gated, and headless runs decline them silently. Measured: an @ line pointing up or outside was ignored even as a full path, the line still visible. The vendor page names the mechanism: an import that resolves outside the working directory is "external" — an interactive window shows a one-time approval dialog; a headless run has nobody to answer it. User-scope files (~/.claude/CLAUDE.md) are trusted without the dialog, which is why constitution.md always arrives. Relative import paths resolve against the importing file, not the launch folder; up to four hops.
Rulebooks below you load lazily. A CLAUDE.md in a subfolder beneath the launch folder is not read at launch — it arrives when Claude reads a file in that subfolder (vendor docs). Same for a rule file with paths: frontmatter — tested today: absent at launch, injected on the first matching read.
Compaction treats them differently. The root CLAUDE.md and unscoped rules are re-injected from disk after a compaction; path-scoped rules and nested CLAUDE.md files are summarized away until a matching file is read again. The docs' own advice: if a rule must survive compaction, drop its paths: or move it to the root CLAUDE.md.
Memory follows the git repository. Every subfolder of one repo gets the repo's drawer (probed from strategy seat/reference/); a folder above the repo contributes nothing. Section 08.
Project settings don't flow down — tested twice today. A folder's plugin switch AND a folder's hooks both stop at the launch folder: a window in the subfolder reverted to the machine default, and the project hook fired for the parent launch but not the subfolder launch. "Project" means launch folder.
Folder rules stay home. Enforcement never follows work elsewhere — only rules carried by a helper, a plugin, or the launch travel.
A rulebook can be pulled sideways for one launch — opt-in (added 8/28). --add-dir gives a window another folder, but by default that folder's CLAUDE.md is not loaded. Set CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 and the added folder's CLAUDE.md, .claude/CLAUDE.md, .claude/rules/*.md and CLAUDE.local.md load too (vendor doc; untested here). The seventh direction — lateral, per launch — and the only way to share a rules folder across repos without a symlink.
Playground

Flip one thing.
See what it moves.

Four control panels, one per layer, in layer order — floor, folder, helper, launch. The window below them is reassembled every time you click. The strip under its title says exactly what your last click added and removed. Locked controls tell you which layer actually holds that lever.

LAYER 1The machine floorevery window · always
LAYER 2The folderthis launch
Click anything. This strip shows what that one click changed.
Knows
Can do
Rules running
LAYER 3The helper filethe only subtractor
LAYER 4Handed in at launchthis run only
DISPATCHA helper dispatched FROM this windowa child, born fresh
?
Reading the board. Every chip is clickable — it opens the real file it points at (or says why there is no file). A chip with a colored source tag arrived from that layer. A dashed, struck-through chip would be there but was removed — the red line says by what. A green outline is what your last click added; a red outline is what it took away. The dark strip at the bottom is the build order, step by step.
The nine jobs

Every mechanism,
by purpose

The pages before this one mapped what a window knows and can do. This page adds the layer you named as missing — evaluation, guardrails, verification, observation — and puts every mechanism in one table by the job it does, where it lives, what it costs, and whether it is a request or an enforcement. Sources: the vendor's own pages, read today, plus this manual's measurements.

The nine jobs — vendor names first, one card each, click to see a real example

Everything that shapes a window does one of nine jobs. Each card says what the job is in the vendor's words, where it lives, when it fires, and whether this floor uses it today. The one-word nicknames are ours — memory aids, marked as such.

Instructionshere: toldused
What: the text a window is given to follow — the CLAUDE.md family, .claude/rules/, skills, auto memory, and text handed in with --append-system-prompt. The vendor's phrase: context, not enforced configuration; no guarantee of strict compliance.
Where · when: user, project and local scope; at launch (always-on), mid-turn (a skill body, a memory file, a path-scoped rule), re-injected after compaction (root CLAUDE.md, unscoped rules, memory).
On this Mac: /context in the strategy seat folder, 30 Aug: Memory files 44k (the CLAUDE.md stack + the memory index) · Skills 8k · Custom agents 16k · system 6k — about 74k of always-on load; the live read says 79k because 4.9k of the run's own messages are on the counter too.
/context — headless, ~/Projects/strategy-seat, 2026-08-30
| Category              | Tokens | Percentage |
| System prompt         | 4.4k   | 0.4%  |
| System tools          | 1.7k   | 0.2%  |
| MCP tools (deferred)  | 115.5k | 11.6% |   ← names only; schemas load on search
| System tools (deferred) | 13.3k | 1.3% |
| Custom agents         | 16k    | 1.6%  |
| Memory files          | 44k    | 4.4%  |   ← CLAUDE.md stack + MEMORY.md
| Skills                | 8k     | 0.8%  |
| Messages              | 4.9k   | 0.5%  |
Tokens: 79k / 1m (8%)
Toolshere: heldused
What: what a window can do: the built-in tools (Read, Edit, Bash…), MCP servers from three sources (~/.claude.json machine-wide, per-folder registrations, a project .mcp.json), and language servers (LSP). Power, not prose — and the only kind of thing a fence removes one item at a time.
The cost, finally measured: with tool search on (the default), MCP tool schemas are deferred — 165 tools across 6 servers would be 115.5k if loaded, and add ~0 to the 79k a window carries at launch. The earlier belief that MCP is "the pollutant" was a hypothesis; this is the number.
Where · when: declared in ~/.claude.json / .mcp.json / a plugin / --mcp-config; names at launch, schemas on ToolSearch.
/context — MCP tools by server (same run)
claude_ai_Notion    37 tools   42.4k
claude_ai_Gmail     29 tools   21.0k
github              45 tools   19.2k
brave-search         8 tools   13.1k
workspace-mcp       22 tools   13.0k
playwright          24 tools    6.5k
TOTAL              165 tools  115.3k  — all deferred; loaded only when searched
Agents & subagentshere: worn · helperused — 34 files (✓cmd 30 Aug)
What: an identity file — name, description, tools:, model:, and what it carries (skills:, hooks:, memory:, mcpServers:). Launched as the main thread (claude --agent gm) or dispatched as a subagent (the Agent tool). The only place a subtraction of capability lives.
Where · when: ~/.claude/agents/ · <project>/.claude/agents/ · inside a plugin (prefixed) · --agents '{json}' for one run. Identity at launch; a dispatched child inherits the parent's rendered block (measured).
~/.claude/agents/home-lead.md — the fenced one
---
name: home-lead
model: sonnet
tools: Read, Write          ← no Skill (no listing), no Agent (no roster), no MCP tool
hooks:
  Stop: [ stop-hook.sh ]   ← travels with it
---
Enforcementhere: walledhooks used · 1 deny · sandbox off
What: what physically stops an act, as opposed to prose that asks. Three walls, weakest to strongest: a hook (a program at a fixed moment that can say no), a permission rule (allow / ask / deny per tool pattern; deny wins), the sandbox (the OS fencing files and network under every command).
Where · when: settings at any scope, an agent file, --settings, a plugin; at the event, at the call, on every Bash. Full page: Walls.
the floor's live walls, 2026-08-30
PreToolUse hook   knowledge-home-guard.py  → DENIES any write into ~/Projects/knowledge-base  (exercised at every boot)
permissions.deny  one rule in ~/.claude/settings.json
sandbox.enabled   false   (the strongest wall, unused)
Verificationhere: checked3 of 3 rungs used — since 2026-09-01
What: is the work right? Three rungs, cut by who judges. Rung 1 — "check your work" in the prompt: the same window grades itself. Rung 2 — an automatic judge at the exit: /goal (a session-scoped prompt-based Stop hook: after each turn a small fast model reads the condition and the transcript and decides met / not yet / impossible) or a hand-written Stop hook (type: command inspects the work; type: prompt reads the transcript). Rung 3 — a fresh reviewer that did not build the thing.
The /goal edges (vendor doc): the evaluator runs no commands and reads no files — the condition must be something the transcript shows ("npm test exits 0"); one goal per session, up to 4,000 characters; /goal clear removes it; several turns with no tool use stops the loop with a warning; an unrecoverable error clears it. It does not change your permission mode.
On this Mac: rung 2 (script kind) = the seat Stop hook in 32 of 34 agent files; rung 3 = gap-checker. The model kind (/goal) was EXERCISED 2026-09-01 (CLI 2.1.251) — the first run of it here, and this page said "never used" until then. One condition, one throwaway folder, twice. Reachable: the latch installed, judged once from the transcript, passed and released — ~20 s · 949 goal tokens · 270,516 tokens summed across the transcript · 6 assistant turns. Unreachable (the write denied): 39 evaluator verdicts — 38 blocking, then one terminal impossible — 88 assistant turns, ~7 minutes, 16,670 goal tokens · 6,056,113 tokens summed, exit 0, the file never created. ⇒ Like for like that is 17.6× the goal's own tokens and 22.4× the transcript — compare the same measure on both sides; the goal's tokens field is not the run's cost. ⚠️ n=1, and neither arm was a clean rig: the evidence records two distinct denial mechanisms, one of them a plausible path-resolution defect, so part of that 6M is likely rig and not latch. An unreachable goal did stop itself here — via the terminal impossible, which requires the assistant to have tried and said it cannot be done. Not a general guarantee.
Plan mode — read from the binary, NOT run. ⚠️ The typed path (/goal … typed during plan mode) was never executed; no plan-mode gate appears on it in the code. Do not treat this as established. What the binary blocks is Claude proposing a goal during planning — verbatim from the binary: "Plan mode is active, so a goal cannot be proposed yet. Keep planning; propose the goal after the plan is approved." The approve-the-plan-then-build moment is the intended slot, not an exclusion. ProposeGoal also refuses inside subagents and outside interactive local sessions.
the two rung-2 kinds, verbatim shapes
/goal all tests in test/auth pass and the lint step is clean — or stop after 20 turns

"Stop": [ { "hooks": [ { "type": "prompt",
   "prompt": "Check if all tasks are complete. If not, respond with {\"ok\": false, \"reason\": \"what remains\"}." } ] } ]

"Stop": [ { "hooks": [ { "type": "command", "command": "~/.claude/hooks/stop-hook.sh" } ] } ]   ← yours today
Evaluationhere: scoredearly access — EXERCISED 2026-09-01
What: does a package actually help? A driving test — cases plus what a good answer must contain, run with and without the plugin, and the delta reported. claude plugin eval <plugin>.
⭐ This job has its own page. The three machines, the measured costs, the defect that silently under-reports, and what is yours to decide all live in Evals — section 13 in the rail. One home, so these numbers cannot drift apart from each other.
Observabilityhere: watchedtelemetry off · hand-built instead
What: what every window did, after the fact, without anyone writing a log line. OpenTelemetry is the standard: CLAUDE_CODE_ENABLE_TELEMETRY=1 plus the OTEL_* exporter variables. Metrics: claude_code.session.count · cost.usage · token.usage · lines_of_code.count · active_time.total. Events (each prefixed claude_code.): user_prompt · api_request · api_error · tool_result · tool_decision · assistant_response, each tagged with session, user, organization and prompt id. Content is redacted by default (OTEL_LOG_USER_PROMPTS=1 to include it).
In-session meters: /context (what loaded, by category) · /usage (cost + plan limits) · /insights (an HTML report over recent sessions) · /doctor (setup checkup: unused plugins, CLAUDE.md trims, slow hooks).
On this Mac: telemetry off. The floor's substitute is written by the workers themselves — the shared log, the board, a hook fire log.
turning it on — vendor doc, not run here
export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=console      # or otlp / prometheus
export OTEL_LOGS_EXPORTER=console
claude
# → claude_code.token.usage{type=input|output|cacheRead…}  claude_code.cost.usage  claude_code.tool_decision{decision=accept|reject}
Orchestrationhere: directeddispatch + workflows used
What: one window directing others. Subagents (the Agent tool — a child born fresh, does one bounded job, returns a report) · a forked subagent (/subtask — the one child that inherits the whole conversation and reports back into it; /fork copies the conversation into a separate background session instead) · workflows (a script running many subagents in a fixed pattern) · agent teams (off here) · messages between sessions (SendMessage) · /loop and routines (/schedule) · /background (detach a session) · worktrees · headless -p.
Where · when: the Agent tool, skills, launch flags; on demand. The rule that matters: a dispatched child loads no instruction files of its own — it inherits the block its parent rendered at boot (measured with a timed discriminator).
the four shapes, as this floor runs them
dispatch    Agent(subagent_type: gap-checker, prompt: "grade this artifact…")     ← fresh context, returns a file
fork        /subtask "verify the three numbers above"                            ← copies the conversation
workflow    parallel(findings.map(f => agent("verify " + f.title)))             ← many children, fixed pattern
schedule    /loop 20m /check-deploy   ·   /schedule "every weekday 6am, run the brief"
Packaginghere: shipped2 plugins live
What: moving a setup somewhere else as one unit — a plugin: a folder with .claude-plugin/plugin.json and slots for skills, commands, agents, hooks, mcpServers, lspServers (and userConfig). Found through a marketplace (an address book), installed at user / project / local scope, or carried for one run with --plugin-dir. defaultEnabled: false installs it switched off.
The vendor's trigger: a second repository needs the same setup. Full mechanics, measured: the Plugins page ("the switch and the files") and The Case and the Procedure.
the sample plugin, real on this Mac
~/Projects/strategy-seat/tools/lab/example-marketplace/          ← a marketplace (address book)
  .claude-plugin/marketplace.json                     name: re-lab · plugins: [ real-estate ]
  real-estate/                                        ← the plugin
    .claude-plugin/plugin.json   skills/ (2)   agents/ (2)   hooks/hooks.json   .mcp.json (comps-db)

$ claude plugin marketplace add ~/Projects/strategy-seat/tools/lab/example-marketplace
$ claude plugin install real-estate@re-lab --scope local     → .claude/settings.local.json: enabledPlugins

All nine, as a reference table — knowledge split into its four homes

PurposeMechanismWhere · whenRequest or enforcement
Knowledge · alwaysCLAUDE.md — managed, user, project, localthe floor, the folder and its ancestors · at launch; a subfolder's own CLAUDE.md only when files there are readrequest
Knowledge · by topic.claude/rules/*.md (and ~/.claude/rules/)project / user · unscoped: at launch · with paths: — on the first matching readrequest
Knowledge · on demandSkillsfloor · project · plugin · bundled · one line each at launch; the body when used; disable-model-invocation = nothing until you type itrequest
Knowledge · rememberedAuto memory; a helper's own memory: directorythe cabinet, one drawer per git repo; agent-memory/<name>/ at user, project or local scope · the index at launch (200 lines / 25 KB); files on demandrequest
CapabilityBuilt-in tools · MCP servers · code intelligence (LSP)tools: the harness · MCP: ~/.claude.json machine-wide or per-folder, .mcp.json, a helper's mcpServers:, --mcp-config · names at launch, schemas deferredfenced per item by the helper's tools line
IdentityHelper files — tools, model, effort, permissionMode, maxTurns, skills, mcpServers, hooks, memory, isolation, backgroundmanaged › --agents › project › floor › plugin (that is the order on a name clash) · launched or dispatchedthe tools line enforces; the rest adds
EnforcementHooks (five kinds: command · prompt · agent · HTTP · MCP call) · permission rules and modes · the Bash sandbox (the OS fences files and network for every command and its children)settings at any scope, a helper file, --settings, a plugin · on the event / on the call / on every Bashenforcement — the vendor: "a request, not a guarantee" vs "a PreToolUse hook that blocks the edit is enforcement"
VerificationA check Claude runs itself → an automatic judge at the exit — a model that reads the transcript (/goal, a prompt Stop hook) or a script that inspects the work (a command Stop hook) → a fresh-context reviewerthe prompt · settings (/goal is a session-scoped prompt Stop hook) · a helper file · a subagent · per turn · at Stop · on demandthree rungs, cut by WHO judges — your floor's seat Stop check is the script type of rung two; the gap-checker is rung three
Evaluationclaude plugin eval: cases in evals/, graders, a no-plugin baseline arm and the score delta; the skill-creator's trigger evalbeside the thing it measures — <plugin>/evals/, <skill>/evals/ · on demand, by commandmeasurement — the numbers, the costs and the defect live in Evals, section 13
ObservationOpenTelemetry (CLAUDE_CODE_ENABLE_TELEMETRY=1): tokens, cost, sessions, tool decisions, API calls — attributed by agent, skill, plugin and server; content redacted by default · in-session /context /usage /insights /doctor · the InstructionsLoaded hookenvironment / managed settings; hooks · continuous once onmeasurement — not enabled here
OrchestrationSubagents (a fork inherits the conversation) · dynamic workflows · agent teams (off) · cross-session messages · /loop and scheduled tasks · /batch · worktrees · headless -pthe Agent tool, skills, launch flags · on demand—
PackagingPlugins — manifest fields skills · commands · agents · hooks · mcpServers · lspServers · outputStyles · userConfig — and marketplacesthe cache + a switch at user / project / local scope; or carried in at launch · at launch, per scopepackaging

The vendor's own build order — quoted, not invented

Trigger → add
Claude gets a convention or command wrong twice → CLAUDE.md
You keep typing the same prompt to start a task → a skill you invoke
You paste the same playbook a third time → a skill
You keep copying data from a browser tab Claude can't see → an MCP server
A side task floods your conversation → a subagent
You want something to happen every time without asking → a hook
A second repository needs the same setup → package it as a plugin. That sentence is the whole answer to "what should be prepackaged": whatever a second folder would otherwise have to copy.
!
Guardrails are never prose. The vendor, twice: hooks are deterministic where CLAUDE.md is advisory; the sandbox lets the operating system enforce which files and domains a command may touch. If a rule must hold every time, it is a hook or a sandbox rule — never a sentence a seat is asked to remember.
Δ
An eval is a delta, not a score. claude plugin eval runs each case with and without the plugin and reports the difference; graders that only fire when the plugin is present (tool_used: Skill) count as "the plugin fired," not as points. The skill-creator's benchmark does the same with pass-rate, time and tokens, mean ± spread, against a baseline. Corrected 2026-09-01: "0 plugins ship an evals/ folder" stands as a claim about plugin roots — but "neither exists" was half wrong. The skill-creator's format is on this machine at math-olympiad/skills/math-olympiad/evals/trigger_eval.json — exactly the <skill>/evals/ home this very page names. Same folder name, two different machines behind it.
✓
Verification is a ladder of three, cut by WHO judges — and since 2026-09-01 you stand on all three. A check in the prompt (you) · an automatic judge at the exit door — either a model reading the transcript or a script inspecting the work · a fresh reviewer. /goal is exactly the first kind: vendor-verbatim, "a wrapper around a session-scoped prompt-based Stop hook" — it runs no commands and reads no files, so the goal must be something the transcript shows, and after several turns with no tool use it stops and warns. Your produce-then-verify Stop check is the script kind; the gap-checker is the reviewer; the model kind you had never used — until 2026-09-01, when it was run twice and both costs were measured (see Verification above). (Re-cut 8/28 from a four-rung version after a peer review verified at the vendor's goal page.)

What this research corrected on the pages before it

"No per-skill selection exists." A helper's skills: field preloads full skill bodies into a dispatched child — measured today (the marker arrived in the child's first turn; on a --agent launch the same field did nothing). The listing fence stays all-or-nothing; preloading is an add.
"A helper can only subtract." It can also add: skills: and hooks: (measured), mcpServers: and memory: (vendor docs).
"Three kinds of hook." Five: command, prompt, agent, HTTP request, MCP tool call.
Explore and Plan are the only built-in helpers that skip CLAUDE.md and git status. A fork is the one child not born fresh — it inherits the whole conversation, prompt, tools and model.
Evals

A driving test
for a tool

An eval grades the tool, never a piece of work — that is a different machine, and you already own it. This page is the whole eval side: what exists, what it costs, and what happened when a session stopped believing the question was closed. Measured 31 Aug – 1 Sep 2026, CLI 2.1.251.

Start here — two questions, one word

Verification — is this piece of work right?

Asked once, about one thing just produced. Answered by a judge at the exit, or by a fresh reader who did not do the work. You are fully built here: the seat Stop check is the judge, gap-checker is the fresh reader.

Evaluation — is this tool any good?

Asked about the tool itself, with fixed cases, run repeatedly. Answered by a score — or better, by the difference between two scores. Neither of your existing machines has an opinion about whether a skill is worth having.

That gap is what evals fill. Keeping the two apart is most of the topic.

The three machines — the whole inventory, there is no fourth

claude plugin eval
open — one variable away
The real thing. Cases, graders, and a baseline arm that runs the same cases without the plugin, so you get a difference rather than a number. Writes an HTML report. Gated per organization, but the gate has a documented override and it works here.
skill-creator · trigger eval
open — and broken by default
Narrower and genuinely useful: given ~20 realistic prompts, does the skill fire when it should and stay quiet when it should not. It tests the description, not the work. Runs today — and reports false failures until you change one flag.
the verification ladder
already yours
Not an eval at all. Three rungs cut by who judges. Listed here only so it stops being filed under the same word. Full treatment: The Nine Jobs.

Why a delta, not a score

Δ

A score alone cannot tell you the tool did anything

A skill that scores 8 out of 10 tells you nothing on its own, because you do not know what the same ten cases score with the skill switched off. If the answer is also 8, the skill is decoration. That is what the baseline arm is for — the same cases, run twice, once without. It is the write-vs-grade instinct pointed at a tool instead of a document.

!
The trap this session actually fell into. A test skill scored 3 out of 6 — and had fired zero times out of eighteen runs. Every point came from a "should not trigger" case passing, and they all passed for free: a skill that never fires never fires wrongly either. A dead skill scores 50% on a balanced set. ⇒ Read the fire count before you read the score.

⛔ The defect — the open machine under-reports, and it looks like a bad description

!
Read this before the table under it. The contrast reproduced twice and then, on a third instrumented attempt, inverted — serial failed, parallel passed. With only two tries per side, this comparison has almost no power to tell anything apart, and a noisy process produces both orderings routinely. ⇒ The honest lesson is harder than "the measurement was solid and only the explanations collapsed": the measurement was underpowered from the start, and the collapsing explanations were downstream of that. What follows is what was seen, not a settled result.

What was run: the same rigged-to-pass control twice in one fresh folder, changing only how many test runs go at once.

Positive control — two queries that name the skill outrightWorkersTimeoutResult
Control, serialized1180s2 / 2 triggered
Identical control490s0 / 2
Identical control4300s0 / 2 — so: not the clock
Six-query set, 3 runs each not part of the contrast12—0 / 18 fires — ⚠️ no serial control was run: different queries, different worker count, nothing rigged-to-pass in the same configuration. The evidence file excludes it; it sits here only as the observation that produced the scoreboard lesson above.
the naming scheme — READ FROM the script's source, not captured from a run
t+2s  command files present: 4
  net-sheet-skill-259a47e4.md
  net-sheet-skill-b95fcf52.md
  net-sheet-skill-c3666a31.md
  net-sheet-skill-d748d95b.md
  ↑ same description · four names · each worker counts only its own
  illustrative names. the SCHEME is read from the script's source; these four
  strings are not a captured poll. real, and a genuine hazard — but NOT what
  caused the zeros.
✕
Three explanations were published for this, and all three were demoted. The first — each worker counts only its own copy — predicts partial under-reporting, while every parallel run showed total failure. A fresh reader did that arithmetic in one pass. The replacement (the checker gives up at the first wrong tool) failed a follow-up. So did the third. ⭐ And the honest version, which is less flattering: the under-reporting is real and it reproduces — but the contrast meant to isolate it inverted on a third run, and one filed bug misreports at any worker count. So this is not "the measurement was solid and only the stories collapsed." The measurement was underpowered, and the stories were downstream of that.
Three CANDIDATE causes are filed upstream, all still open — and none was shown to produce these numbers. Two match explanations proposed and abandoned here; the third nobody here thought of: the tool does not isolate your other connected services, so every test run boots them first. They compound, which is why no single one matched the evidence. Candidates, not a verdict.
A second hole beside the first: the script discards every error message its runs produce. A run that fails outright is recorded as a quiet "didn't trigger," indistinguishable from a real one. Which is why stretching the limit from 90s to 300s could not have settled it either way: that test rules out latency, but it cannot rule out a fast silent failure — more time cannot surface an error that was discarded.
And the contrast itself stopped reproducing. On a final instrumented run the result inverted. The instrument was blamed; a grader named the simpler answer — with two tries per side this comparison has almost no power, and a noisy process produces both orderings routinely. Blaming the instrument was itself another untested story.
What to actually do. Run one at a time — cheap, and the bug report's own recommended workaround. Turn off other connected services while testing, for comparability. Know that one of these bugs misreports at any setting, so treat this tool's numbers as directional. Nothing is fixed upstream: the copy on this machine is byte-for-byte identical to the current published one.
What the default costs you: the shipped default is ten workers. Left alone, the description optimizer will tell you a perfectly sound description is failing — and you will rewrite something that was never broken. Turning it to one worker is the bug report's own documented workaround and a cheap precaution — NOT a measured cure. (An earlier draft called it "measured to fix the contrast"; a fresh grade demoted that.) It closes only one of the ways this script can quietly report a failure that never happened, and one filed bug misreports at any worker count.
reproduce it yourself — builds a throwaway skill, runs the control twice, cleans up
$ bash reference/claude-code/repro-eval-worker-defect.sh
  Both queries name the skill outright. Every run SHOULD trigger.
  WARNING: this contrast has been observed to INVERT (serial fail / parallel pass) on an
  instrumented copy, 2026-09-01. Treat a single result as provisional. The published cause is
  THREE compounding bugs -- see section 8 of evals-measured-2026-08-31.md.

  --- serialized (--num-workers 1) ---   Results: 2/2 passed
  --- parallel   (--num-workers 4) ---   Results: 0/2 passed

Running a real one — and what it costs

The tool writes your first case for you and refuses to do it outside a plugin folder — a guardrail, not an obstacle. Cases live beside the plugin at evals/<case>/prompt.md with graders/*.md; results and an HTML report land under evals/results/<timestamp>/. The no-plugin arm runs by default whenever a plugin resolves — --ablation none turns it off. Six grader kinds ship: regex (match the text) · tool_used · file_exists · tool_order · llm (a model's verdict) · baseline. One case was run both ways, three times each:

GraderWith pluginWithoutDid it measure anything?
Model judgepassed 1 of 3passed 0 of 3Yes — the entire delta, and a weak one
Text match3 of 33 of 3No — matched in all six runs
Did the skill fire3 of 3—Indicator, not points
The whole argument for a delta, turning up unprompted on the first real case. The text-match grader passes whether or not the plugin exists, because ordinary Claude already talks about commission and escrow unaided. Read the with-plugin score alone — it looks healthy — and both graders look like they are working. (The 1.00 usually quoted is the n=1 figure; at the tool's default three runs the with-arm scores 0.67.) Only the without-arm reveals that one measures nothing.
The first number was wrong by 3×. One run per side put the gap at +0.50; three runs per side — the tool's own default — put it at +0.17. The single run had caught the one lucky pass. That was the fourth time in this investigation a one-run result inflated something.
⛔ SUPERSEDED 2026-09-02 — that +0.17 is inside the noise floor. A later session measured the wobble on purpose: three identical batches of the same case, same graders, same settings, gave +0.67 / +1.00 / +1.00 — a spread of 0.33, a third of the whole scale. A three-run delta of +0.17 is therefore not distinguishable from zero, and this page presented it as the trustworthy figure that corrected the n=1 error. It corrected one over-claim with another. The honest reading of that experiment is: direction unknown at that sample size. ⚠️ The wobble was measured on a different skill and grader set, so 0.33 is this tool's noise on that setup, not a proven universal constant — but it is enough to retire +0.17 as a finding. Working rule: trust the direction, never the second decimal, and never call one version better than another on a gap smaller than the spread. Evidence: reference/claude-code/eval-authoring-measured-2026-09-02.md §4.
⭐ But six runs showed what one could not: the skill fired every single time, and the judge still passed only one in three. Triggering is reliable; doing the job is not. A skill can activate perfectly and still ignore its own instructions — which means every trigger test on this page measures the smaller of the two questions.
What it costs — measured, not estimated

$0.06 for a trivial case with a mechanical grader. $0.61 for a realistic one run both ways at the default three runs. ⇒ a twenty-case suite is on the order of $12 per full pass (arithmetic from measured points, not itself measured — an earlier version got this multiplication wrong by 4×).

$
Do not use the bare command as a harmless check. It searches for cases in every folder beneath wherever you run it, runs whatever it finds, and uploads the report to your account by default. Measured the expensive way: a reviewer took that advice, ran it from a scratch folder, hit an old test directory left by something unrelated, and was billed $0.19 for a run nobody asked for, report published. ⇒ To check the gate: --help. To run on purpose: --no-publish and a cost ceiling.

The four settings a working suite needs — and what each one silently does when it is missing

Everything above this line was measured on a suite that had a bug in it. A later session built a suite from nothing — a skill, a case that should fire, a case that should not — and found that three graders out of three were faulty, each in a different way. None of them announced it. Each one reported a number. The four settings below are the difference between a suite that measures something and a suite that reports confidently on nothing.

SettingWhat it doesWhat happens without it
arm: bothRuns the grader in the without-tool arm as well as the with-tool arm.The grader scores nothing. A grader on Skill defaults to with-only, because a skill cannot fire in an arm where it does not exist. It is not silent — the tool prints [with-only, not scored] — but it is easy to read past, and the suite still shows a healthy number beside it.
min: 0, max: 0Scores a grader as correct when the thing did not happen.You cannot express "this must not fire". Every grader reads bigger-is-better, so the case that proves your tool stays quiet has no way to pass.
timeout_secondsHow long a run may take before it is cut off.⛔ An under-set timeout reads as a score of 0, not as a timeout. The tool's own guide warns about this. A whole class of false failure that looks exactly like a bad answer.
the negative caseA case the tool should not change, run alongside the ones it should.Nothing tells you the tool is over-firing. A suite of only positive cases can only ever deliver good news.
⛔ Two of those four were already published when they were re-derived. The concept behind arm: both was on this page already; min: 0, max: 0 is in the tool's own guide, word for word. They were worked out again from scratch anyway. That is the sixth time on this subject. The lesson is not "read the manual" — it was read. It is that reading it once at the start is not the same as consulting it at the moment you need it.
⛔ A suite mean is meaningless once a negative case is in it. On a positive case a bigger delta is better; on a negative case a delta of zero is the correct answer. Averaging the two produces a number that means nothing and moves for the wrong reasons. Read the rows, never the average.
⭐ Firing is not following. With the skill present, the labelling rule passed 9 of 9 runs while the skill's own formatting rules passed 8 of 9. A rule nobody grades can rot while the grader beside it reports perfect scores. Every rule you care about needs its own grader, or it is not being measured.

How much the number wobbles — measured on purpose, and it is worse than it looks

The page above retires +0.17 because of this measurement. Here is the measurement itself: three identical batches — same case, same graders, same settings, nothing changed between them — scored +0.67 / +1.00 / +1.00. A spread of 0.33, a third of the whole scale, and the entire spread traces to two grader outcomes out of thirty-six.

⛔ Do not turn 0.33 into a threshold. Three points give a range that is a biased-low estimate of the real spread — three samples cannot find the edges. And with two graders across three runs, a score can only move in steps of 1/6 ≈ 0.167, so 0.33 is the second-smallest value this design can even express. A rule built on it was written and withdrawn the same day.
⭐ The rule that survived, and it needs no arithmetic: a delta that changes when you remove any one run is not a result. Drop each run in turn and look again. If the answer moves, you measured noise.
There are two layers of noise, not one. The model doing the work varies between runs — and the judge disagrees with itself on the same text: PASS FAIL PASS, FAIL PASS PASS, PASS PASS FAIL on identical answers. The three-vote majority absorbs the second layer. It is load-bearing, not decoration — a single judge vote is a coin with a bias you cannot see.
Where the money actually goes, and it is not where you would guess. Judge grading is $0.157 of $6.03 — 2.6% of the bill. The cost sits in the baseline arm: per successful run, with-tool $0.1075, without-tool $0.1918 — a ratio of 1.78×. Ordinary Claude works harder without the tool than with it. ⇒ The judge is not the thing to economise on, and switching off the baseline arm to save money removes the only part that makes the number mean anything. This is an addition to the $0.06 / $0.61 / ~$12 figures above, not a correction — those were measured two-arm and stand.
⛔ A failed run scores exactly like a bad answer. One run died on a transient sign-in error and reported score 0.00, judge FAIL FAIL FAIL, skill called 0× — indistinguishable from the tool being useless. Only a separate error line on the tool's own output told the two apart. ⚠️ Four exchanges went into theories about why before a plain retry worked with nothing changed. Check for an error line before you believe a zero.
Neither model was pinned in the runs behind this section — not the one doing the work (--model), not the one judging (--judge-model). Some of the wobble may be a model changing under the test. Pin both, or the run is not repeatable. Evidence: reference/claude-code/eval-authoring-measured-2026-09-02.md — 8 suite invocations, 45 runs, $6.03.

How the finding was reached — two of these steps were being wrong

Order matters: each step only makes sense after the one before it. The wrongness is the instructive part.

1 · Opened the manual before measuring anything. It already had a section on evals carrying the status early access, unused. Reading it first is what kept the session from re-deriving a published answer.
2 · Nearly published a false correction. Found a folder named evals/ on disk and began treating it as proof the manual had gone stale. It holds the other format entirely — a naming collision, not a counterexample. Caught before it shipped.
3 · Ran the command and found it gated. early access, on stderr, exit 1, fired before it even looked at the target. The manual was right; the confirmation cost one command.
4 · Misread its own measurement. Reported exit code 0 from a probe piped through head — so $? was reporting head's status. True code is 1. A pipe eats the exit code of the command before it — worth knowing generally.
5 · Ran a rewrite test at one run per query, and it lied. A rewritten description appeared to improve 3/6 → 4/6. Re-run at three runs per query the gain vanished — both arms 3/6, both zero fires. One run per query is not a measurement.
6 · Ran a positive control, which failed — and that was the real finding. A query saying "run the net sheet skill" scored zero. The same control passed once one flag changed, so the rig was not simply broken: right at one setting and wrong at another — the harder case to catch.
7 · Published the right defect with the wrong cause — three times running. A grader who had not done the work checked the causal claim against the numbers on the page and found they contradicted it. The replacement failed a follow-up. So did the one after that.

What is yours to decide — nothing here needs an answer today

The real eval command is available now

The gate is a per-organization rollout flag with an environment-variable override. Setting it for a single command opens it — no restart, nothing persisted:

the whole thing
$ CLAUDE_CODE_WALNUT_SPIRE=1 claude plugin eval --help

⚠️ Where that name comes from matters: it was read out of a compiled-in string in the CLI binary, not from published documentation — slightly less than a documented feature. A real case then ran clean for six cents. To set it permanently there is reference/claude-code/enable-plugin-eval.sh — ⚠️ that settings route is BINARY-sourced and was never RUN; only the per-command form above is measured. What none of this does is write your cases — that thinking is the actual work either way.

Point trigger evals at the skills that already misfire

This is the part that runs today, and the floor has a standing complaint it fits exactly: skills that under-trigger. A trigger eval turns "it doesn't seem to fire" into a number you can move — provided it runs serialized.

Know that publishing is the default

When claude plugin eval does open, its HTML report publishes to claude.ai automatically wherever the account supports it. --no-publish is the opt-out. An eval report is an outward-facing artifact unless you say otherwise.

Sourcing — and one correction about method

Every number here came from a command run on 31 Aug or 1 Sep 2026 against CLI 2.1.251 — the control runs, the worker counts, the exit code, the fire counts. Two things did not and are marked as such: the list of options new since the manual, and the publish-by-default behaviour, both read from --help rather than from a run. They cannot be confirmed by running, because running is gated.
The full record, with the source named beside each claim and a limits section saying what these numbers do not cover: reference/claude-code/evals-measured-2026-08-31.md. The fresh-context grade that forced the correction sits beside it at reference/grades/evals-measured-grade.md.
One thing these numbers do not record, and should: which model ran them. Triggering behaviour depends on it, and the runs did not pin it.
⛔ A correction about method, not facts. The section on writing cases reads as discovery. It is not. The Field Manual from five days earlier already listed all six grader types, the folder layout and the indicator-grader scoring rule — and had even named its worked example the same thing this session independently chose. It was read at the start, and the same ground was re-derived from scratch anyway. That is the fourth time. Reading the manual once at the beginning is not the same as consulting it at the moment you need it.

⭐ Where the vendor's own words are — and the retrieval trap on this exact subject

⛔⛔ THE PUBLIC DOCUMENTATION SITE HAS NO PAGE FOR THIS FEATURE — AND THAT ABSENCE IS ITSELF THE TRAP. The vendor's own documentation index (code.claude.com/docs/llms.txt) lists no page for plugin evals, graders or eval suites. ⇒ A session that searches the docs site alone concludes the feature is undocumented, and is wrong. The first-party text exists in exactly two places: the binary's own claude plugin eval --help, and the anthropics/claude-plugins-official repository. Established twice, independently, on 2026-09-08 — by a sweep of the docs index and by a separate search of the vendor's domains. Search the binary's help text and the repo, not the docs site.
⭐ The vendor has a NAME for the wobble this page measures. Anthropic's engineering write-up Demystifying evals for AI agents (anthropic.com/engineering/demystifying-evals-for-ai-agents) calls the run-to-run-variance metrics pass@k and pass^k. ⚠️ It does not overturn anything above — it sets no sample size, and covers neither ablation arms nor where the cost sits. It gives the measurement the vendor's vocabulary, nothing more. The same piece splits graders into code-based (fast, cheap, objective, reproducible) and model-based (flexible, handles open-ended output) — the distinction this page draws in its own words.
⚠️ VERSION DRIFT, stated because nobody had stated it. Every figure on this page was measured against CLI 2.1.251. This machine now runs 2.1.265. Nothing here has been re-measured against the newer build, and the help text HAS moved in the meantime — --judge-model now states its default (haiku) outright, and the early-access gate is open on this machine without the environment-variable prefix, which retires the setting route this page marks as never-run. ⇒ Treat the numbers as directionally sound and the flags as needing a re-read.
⭐ The authoring interview nobody used. claude plugin eval init runs an interview by default in a terminal — the vendor's words: "Author an eval suite under the eval dir … via an interview that sources inputs and designs graders." The suite behind this page was hand-written anyway. If you are starting a suite, start there.

Lookup

TermWhat it means here
deltaThe difference between the with-tool score and the without-tool score. The whole point of an eval: a bare score cannot tell you the tool did anything, because you do not know what the same cases score without it.
evalA driving test for a tool. Fixed cases, run with and without the thing, scored on the difference. Grades the tool, never a single piece of work.
caseOne test prompt, plus what a good answer has to contain.
graderThe thing that scores one case. Six kinds ship: text match, which tool got used, whether a file appeared, a model's judgement, the order tools ran in, and the baseline.
baseline arm · ablationThe same cases run again with the tool switched off, so the result is a difference rather than a bare score.
trigger evalThe narrow test: does the skill fire on the right prompts and stay quiet on the wrong ones. Tests the description.
positive controlA case rigged so it cannot fail. When it fails anyway, the result you were about to report is void — either the equipment is broken or a setting is wrong. Run it in the same configuration you intend to report from, or it proves nothing.
false negativeA test reporting failure for something that actually worked. The defect on this page produces these — which is what makes it dangerous: it looks like ordinary bad news.
armOne side of the comparison — with the tool, or without it. A grader set to both is scored on each side; left alone, some graders only run on the with-side and quietly contribute nothing to the difference.
negative caseA test the tool should not change. Success is a delta of zero. It is the half of a suite that can deliver bad news.
repeatabilityHow much the same test moves when you run it again with nothing changed. Measured here at 0.33 on a 0–1 scale. Any finding smaller than the wobble is not a finding.
leave-one-outThe check that costs no arithmetic: drop each run in turn and see whether the answer survives. If it moves, you measured noise.
workerOne of several copies of a test running at once to finish sooner. The count is a flag; here it changes the answer.
Walls

What stops an act —
as opposed to what asks

Instructions ask. Three mechanisms stop: a hook, a permission rule, and the sandbox. They sit in that order, each stronger than the last, and a fenced tools line sits in front of all three. here: sign on the door · doorman · locked door · wall

Permission rules — vendor terms

Three arrays in any settings file: allow, ask, deny. Each entry is a tool pattern: Bash(git *), Edit(src/**), Read(~/.env), WebFetch(domain:example.com), mcp__workspace-mcp__send_gmail_message. Precedence: deny > ask > allow — a deny anywhere blocks regardless. Lists merge across scopes (user + project + local + --settings); a single-valued setting does not.

.claude/settings.json — the grammar
"permissions": {
  "allow": [ "Bash(git status *)", "Read(**)" ],
  "ask":   [ "Bash(git push *)" ],
  "deny":  [ "Edit(~/Projects/knowledge-base/**)", "mcp__workspace-mcp__send_gmail_message" ],
  "defaultMode": "acceptEdits"
}
Permission modes — the CLI's own list
default — shown as Manual in the mode indicator and in claude --help (the CLI also accepts manual): asks before anything not covered by a rule.
acceptEdits — file edits run without asking; commands still ask.
plan — reads and plans only; nothing is changed until you leave plan mode.
auto — everything runs, with a second model (a classifier) reviewing each action against your request instead of you; autoMode.environment is its policy (vendor doc).
dontAsk — never prompts: anything that would have asked is auto-denied; only what an allow rule, the built-in read-only Bash set, or a PreToolUse hook already approves runs. A locked-down mode, not a read-only one (vendor doc).
bypassPermissions — skips the prompts and the safety checks; a deny rule still blocks in every mode, including this one, and so do hooks and the sandbox. Allow rules stop mattering because nothing is asked (vendor doc). The floor's headless rings run under an enforced deny floor.

Set with --permission-mode <mode>, defaultMode in settings, or cycle live with Shift+Tab. Six modes; claude --help on this Mac (30 Aug, CLI 2.1.251) lists them as acceptEdits · auto · bypassPermissions · manual · dontAsk · plan — default and manual are the same mode. Definitions from the vendor's permission-modes page.

The sandbox — the strongest wall

The operating system itself fencing what a command may touch: which files, which network. Every Bash call and its children run inside it. sandbox.enabled: true in settings, or /sandbox to toggle; macOS, Linux, WSL. Off on this Mac. The vendor's own line: hooks are deterministic where CLAUDE.md is advisory; the sandbox lets the OS enforce which files and domains a command may touch.

Hooks as walls: several moments can refuse, each its own thing — only PreToolUse can stop a tool call before it runs (permissionDecision: deny); Stop refuses an exit; PreCompact refuses a compaction (the vendor's can-block table, and the binary carries the string). When several hooks match, the most restrictive answer wins — deny, defer, ask, allow. And a hook does not bypass the rules: deny and ask rules are evaluated whatever a PreToolUse hook returns, while a blocking hook beats an allow rule (vendor doc).

Try it — pick an act, set the walls, watch which one catches it

The order is real: the agent's tools line first (if the tool is not held, nothing else is consulted), then any PreToolUse hook, then the permission rules and mode, then the sandbox under every command.

The act
The mode
The walls that exist
=
The rule to keep: if something must hold every time, it is a hook, a deny rule, or the sandbox — never a sentence a window is asked to remember. This floor's own history proves it in both directions: the knowledge-home guard's own log reads 79 denials, 26 self-denials and 24 deliberate ceremony allowances — the one narrow class it was built to let through — with a canary exercising it at every boot; the rules that lived only as prose were the ones that kept getting re-learned.
When things arrive

Five moments.
Launch · turn · dispatch · compaction · stop

The third question. Everything on the earlier pages enters a window at one of five moments — and some things leave at one of them. Click a moment.

Arrives · is re-injected
    Leaves · does not come

      Why the moment matters more than the place

      Same place, two moments. Two rule files in the same .claude/rules/ folder: the one without paths: arrives at launch and is re-injected after a compaction; the one with paths: arrives mid-turn on a matching read and is summarized away at compaction. Measured.
      Dispatch is a copy, not a load. A subagent loads no instruction files of its own — it inherits the block its parent rendered at the parent's launch. A rule file written after the parent booted was invisible to a child dispatched a minute later. Only a fork copies the conversation too.
      Compaction is the one moment things die. Conversation-only instructions ("from now on, always…") do not survive it unless they were also written to a file the harness re-injects. The next page is about exactly that.
      Stop is where enforcement of the work lives. A Stop hook runs when the agent finishes responding, not on a user interrupt (vendor doc). The harness's own hook table reads "including clear, resume, compact" (a string in the binary), while the vendor names SessionEnd for exit, /clear and an interactive /resume, and SessionStart with a compact or resume source — so a check that must survive those is registered on those events too. On this floor that is where produce-then-verify and registration are checked.
      Compaction

      The window squeezes itself.
      What survives is decided by files.

      A window's context fills — every message, every file read, every tool result. When it nears the limit, Claude Code compacts: it folds the conversation into a summary and continues from that. Auto-compact is on by default and needs nobody present. The whole question is what comes back after the cut, and the answer is: whatever a file re-supplies.

      Try it — fill a window, watch it cut

      auto-compact window1,000kthis Mac: nothing set → the model's limit — 1M for Fable 5 and for Opus 5 alike (both read "/ 1m" in /context)
      trigger percent100%CLAUDE_AUTOCOMPACT_PCT_OVERRIDE — can only move the cut earlier
      After the cut — re-injected from disk
      • L1·L2The root CLAUDE.md stack and unscoped rules — re-read from disk
      • L2Auto memory — the index, first 200 lines / 25 KB
      • L2The plan written in plan mode — re-injected from disk (vendor doc)
      • L1The system prompt — untouched
      • turnFiles recently read or edited — up to 5 re-read, most recent first (vendor doc)
      • turnInvoked skill bodies — re-injected, capped ~5k each / 25k total (vendor doc)
      • L3Hooks, tools, the agent's identity — never in the conversation, so never cut
      After the cut — summarized away
      • goneThe conversation itself — folded into the summary; older tool outputs are cleared first, summarization only if that is not enough
      • gonePath-scoped rules and nested CLAUDE.md — until a matching file is read again; the rules matching the up-to-five re-read files reload on their own (vendor doc)
      • goneAnything a hook injected (a SessionStart briefing) — unless a SessionStart hook also matches compact
      • goneInstructions given only in conversation — the ones that "die"

      The levers — vendor names, this Mac's values (30 Aug)

      LeverWhat it doesHere
      autoCompactEnabledthe on/off switch (settings); DISABLE_AUTO_COMPACT=1 overrides it; /compact always stays availableon (default)
      /autocompact <n>sets the window size — how full it gets before the cut — and saves it as autoCompactWindow; range 100k–1M; forms 500k, 200000not set → the model's limit
      --autocompact <auto|tokens>the same, for one launch—
      CLAUDE_CODE_AUTO_COMPACT_WINDOWenv var; takes precedence over all three; plain integer only — 500k reads as 500 and clamps to the 100K minimum (vendor doc)not set
      CLAUDE_AUTOCOMPACT_PCT_OVERRIDEpercentage (1–100) of the window at which the cut fires; only lowers the trigger; applies to subagents too. "Come back at 400k, but 10% before" = window 400k + override 90not set
      /compact [focus]cut now; the focus text steers what the summary keeps. A # Compact instructions section in CLAUDE.md does the same standingused — this window compacted on 28 Aug with a focus on your learning goal
      PreCompact · PostCompact hooksmatcher manual | auto. PreCompact fires knowing the cut is coming and can refuse it (the binary carries "Compaction blocked by PreCompact hook"); PostCompact receives the summarythe floor's precompact-snapshot.sh records machine truth at the cut

      Three things measured on 27 Aug that the docs only imply

      It cuts mid-turn (this window's transcript, 27 Aug: a headless probe in /tmp). The check runs before every model request, not at turn boundaries. A headless seat fed oversized files compacted three times inside one turn — each cut landing between a tool result and the next tool call — until the harness's thrashing breaker stopped it with an error rather than looping forever. There is no "finish the work, then compact"; the summary is handed to the model mid-flight and it continues from it.
      No hook can invoke a compaction — but an observer can force one on a headless seat. claude --resume <sid> -p "/compact keep only …" landed a real compaction on a running seat: the transcript gained a compact_boundary and the next resumed turn remembered only the summary. The harness decides when; a hook decides what survives.
      What a summary looks like. This very window was continued from one on 28 Aug: the new turn opened with "This session is being continued from a previous conversation that ran out of context. The summary below covers the earlier portion…" followed by a numbered summary — request and intent, key concepts, files, errors, pending tasks. Everything you had said in conversation and nowhere else was in that summary or gone.
      ✓
      The design rule this page exists for: a rule that must survive a compaction lives in a file the harness re-injects — the root CLAUDE.md, an unscoped rule, memory — never only in the chat. The floor's PreCompact snapshot + a SessionStart(compact) re-injector are the right pair: one records the machine's truth at the cut, the other puts it back after.
      Sessions & in-chat controls

      A chat is a file.
      The window is what you do to it.

      Everything the earlier pages assemble lands in one running session. This page is the part that happens inside it — what a session is, where it is stored, how to find it again, the commands you type at the prompt, and how to get out of a screen you did not mean to open. Folded from Part I (the chats manual) plus the vendor's interactive-mode and commands pages, 30 Aug.

      What a session is — four facts

      ONE CONVERSATION = ONE FILE
      Every session has a unique id and is appended to disk as you go: ~/.claude/projects/<encoded-folder>/<session-id>.jsonl. Plain JSONL — readable, greppable, yours. This window's file, 63aec6b8-….jsonl, was 10.4 MB / 5,818 records at 09:58 on 30 Aug and is larger by the time you read this — that is the point.
      FOLDER-SCOPED
      The folder you started in decides which directory here: drawer the file lands in (every / in the path becomes a -). claude --resume lists only that folder's sessions. There is no global inbox — which is exactly why old chats feel hard to find.
      PERSISTS FOREVER
      Closing the terminal deletes nothing. Resume days later from the same folder, or from anywhere by id. A resume appends to the same file.
      ONE SESSION, MANY SCREENS
      The terminal, the Desktop app (/desktop moved this very session mid-stream), the iPhone app via Remote Control (/remote-control), and claude agents — a dashboard of every running session — are windows onto the same file.

      The launch and resume commands — click one to see what it does

      TERMINAL

      Find an old chat in three steps: cd into the folder it happened in, then claude --resume · don't know the folder? ls -lt ~/.claude/projects/*/ lists every session across every folder, newest first · once you have the id, claude --resume <id> works from anywhere. Name a session as you start it (claude -n "fridge inventory") or later (/rename) and resume it by name.

      Getting out — the keys that close things

      The /memory trap of 28 Aug: you opened a CLAUDE.md in the viewer, pressed Ctrl-C, and stayed stuck. The vendor's interactive-mode page settles it:

      Esccloses a dialog — the /memory file viewer, the /plugin manager, any menu. Mid-turn, it interrupts the response. On a permission prompt, it declines.
      Esc Escon a non-empty prompt clears the draft (kept in history); on an empty prompt opens the rewind menu.
      Ctrl+Cinterrupts a running operation; when idle, the first press clears the input, the second press exits Claude Code. It does not close a viewer — that is why it did not work.
      Ctrl+Dexits the session — first press shows a hint, second within 800 ms exits.
      Ctrl+Otoggles the transcript viewer (tool calls, timestamps, model); inside it q, Esc or Ctrl+C leave it.
      Shift+Tabcycles the permission mode: Manual (default) → acceptEdits → plan → bypassPermissions when available (vendor doc).
      Ctrl+Bsends a running Bash command to the background.
      Ctrl+L Ctrl+Rredraw a garbled screen · search command history.

      The commands you will actually type — the vendor's table, curated

      CommandWhat it doesPage here
      /context [all]what loaded, by category — CLAUDE.md stack, memory, skills, agents, MCP tools — as a grid with token counts. The one instrument that answers "why is this window heavy"The Nine Jobs
      /compact [focus]fold the conversation into a summary now; the focus text steers what is keptCompaction
      /autocompact [auto|tokens]set how full the window gets before an automatic cutCompaction
      /clear [name]start a new conversation with empty context — the files, memory and tools reload; the chat does not. Stop hooks fire on itWhen Things Arrive
      /memoryopen the CLAUDE.md files and auto memory in a viewer; toggle auto memory on or off. Esc closes itMemory
      /rewindrewind the conversation and/or the code to an earlier checkpoint (also Esc Esc on an empty prompt)—
      /resume [id|name] · /rename · /clear namethe session picker from inside a session; name the current one; start a named onethis page
      /model · /effort · /fastswitch the model, the effort level, fast mode—
      /goal [condition|clear]keep working until a condition the transcript can show is metThe Nine Jobs · Verification
      /permissions · /sandbox · /hooksmanage allow/ask/deny rules · toggle the sandbox · view hook configurationWalls · Hooks
      /plugin · /reload-plugins · /skills · /agents · /mcpthe plugin manager (Discover / Installed / Marketplaces / Errors) · apply plugin changes without restart · list skills · agents reminder · MCP connections and OAuthPlugins · Skills · Subagents
      /usage (/cost, /stats) · /insights · /doctorsession cost and plan limits · an HTML report over recent sessions · a setup checkup (unused plugins, CLAUDE.md trims, slow hooks)The Nine Jobs · Observability
      /background · /tasks · /fork · /subtask · /loop · /scheduledetach this session · see background work · copy the conversation into a child · run a prompt on an interval · routines on a scheduleThe Nine Jobs · Orchestration
      /add-dir · /cdgive this session another folder (direction rule 7) · move the session to a different working directory, conversation intactCore Idea
      /desktop · /remote-control · /export · /exitcontinue in the Desktop app · share with the phone · export the conversation as text · leavethis page

      Headless, and the flags that change a launch

      claude -p "…" — print (headless) mode: one prompt, no screen, exits when done. Slash commands work inside it (/compact and /context both ran headless this week); the /plugin UI does not. Every keeper and ring on this floor is one of these.
      --resume <id> · --continue · --fork-session · --session-id <uuid> · -n <name> — resume by id or name, the newest in this folder, resume into a new id, pin an id, name it.
      --bare — the master off-switch: no hooks, no plugins, no memory, no CLAUDE.md discovery. The only way to see a naked window.

      Accounts — the reason this page has a new address

      !
      Artifacts follow the account, not the machine. You run three sign-ins; a page published under one is readable from the others only if shared, and updatable only by the account that published it. This manual has now been minted three times — first-account (v1–v5 of the Lab), personal (v6–v19), and this one (v20–v21) — and a fourth copy is shared in from the other account. What survives every switch is the file, and since 2026-09-01 there is exactly one: ~/Projects/study-project/reference/claude-code/field-manual.html. ⛔ The older reference/records/field-manual-part-ii-2026-08-27.html is superseded — it predates this page's v21 corrections. The published page is a rendered OUTPUT of the file, never the master. Share this page once from its menu and the next switch stops breaking the link.
      The case and the procedure

      The folder holds the knowledge.
      The plugin does the work.

      Your own picture, in the vendor's words: a project (CLAUDE.md, rules, auto memory, the case files) with a plugin switched on for it (subagents, skills, hooks, MCP servers), the plugin sourced from one versioned folder you can switch on in any other project. This page is your architecture-in-progress — the distinction, the avenues, and what the machine measured about each. These measurements change the weight of three of the objections; the choice is still yours — no recommendation is drawn.

      ≠

      The case is unique and accumulates. The procedure is stable and repeats.

      The case: one listing, one buyer, one refrigerator — an address or a name; correspondence, documents, decisions, history. It never repeats. The procedure: the work performed on a case — run the comps, build the net sheet, take the inventory. Templated, reused, maintained once. Your instinct: they must not live in the same place. The manual's one sentence agrees with you: the folder decides what a window knows; the agent — here, the plugin's agent — decides what it can do.

      The picture, with the four measured facts drawn onto it

      PROJECT
      ~/Projects/brokerage/<property>/ — the case
      CLAUDE.md (how to work here) · .claude/rules/ with paths: (how to handle these files — your "rules on how to interact with specific files") · auto memory, one directory per git repo here: drawer · the case files · the plugin's switch: one line in .claude/settings.json
      knows
      PLUGIN
      real-estate@re-lab — the procedure kit here: kit = a plugin
      subagents (comp-researcher, listing-analyst) · skills (listing-workup, seller-net-sheet) · a hook · an MCP server (comps-db). Its files live in the marketplace folder and are copied to a cache at install — the switch and the files are two different things.
      does
      THE WORKER
      an agent from the plugin, launched or dispatched in the case folder
      Identity from the plugin (its tools line, model, instructions); knowledge from the folder (the case's CLAUDE.md, rules, memory). Measured with the listing-analyst (27 and 30 Aug): equipment from the folder, fence from the file here: fence = the tools line.
      knows + does

      What the machine said about your hypothesis — measured 30 Aug

      Holds: the four slots travel as one unit, and the switch is per project. The sample plugin, installed at local scope in a scratch "case" folder, put its two agents, two skills, hook and MCP server into that folder's windows for ~630 tokens (131 of them the MCP tool, deferred like every other, so about 500 land at launch); a blank case window totalled 39.4k before typing, against the strategy seat's 79k. Switch it on in a second project with one line; the files are not copied twice.
      Breaks, as pictured: "refine the plugin while working" does not happen in place. The plugin is copied to a cache at install (~/.claude/plugins/cache/re-lab/real-estate/0.1.0/, a real directory, not a link — exactly as the vendor's plugin pages say: an installed plugin is copied to the cache, and only a link-mode command source runs in place). A skill edited in the source was invisible to a fresh window, and claude plugin update refused with "already at the latest version." The loop that works: edit the source → bump version in plugin.json → claude plugin update real-estate@re-lab --scope local → new windows see it (measured: 0.1.0 → 0.1.1, the marker arrived). One asymmetry: the MCP server script ran from the source path even so — a server edit is live at once, a skill edit is not.
      The MCP tax you were designing around is ~0 at launch. With tool search on (the default), MCP tool schemas are deferred: the strategy seat's 165 tools would be 115.5k if loaded and add nothing to the 79k a window carries before you type. The real weights are the CLAUDE.md stack + memory index (44k), the 34-agent roster (16k) and skills (8k). Your briefing's own advice — measure before designing around it — is now done.
      defaultEnabled: false is the switch, not a discount. Declared on the plugin's marketplace entry, install wrote enabledPlugins: {"re-de@de-lab": false}, status "disabled," and nothing of it loaded — not the skills, not the MCP server (measured). Enable it and everything comes. It cannot give you "installed but MCP-free."
      The plugin has no memory of its own. Auto memory follows the case's git root, so nothing carries a kit's accumulated experience across properties — unless an agent inside the plugin declares memory: user (a notebook at ~/.claude/agent-memory/<name>/ that follows that agent everywhere; vendor doc, never used here). Whether you want procedures that learn on their own is your call; deliberate edits to the versioned skills are the other answer.

      The four avenues — named, with the honest case for and against each

      AvenueForAgainst — and what changed on 30 Aug
      everything at user scopeone place to maintain; nothing to dispatch; results land where the state already livesevery window pays the kit's cost — about 500 tokens at launch for the sample kit, MCP schemas deferred (measured 30 Aug); whether that is small is yours to weigh.
      dedicated workflow foldersclean separation; each procedure's environment is exactly what it needsthe sprawl you rejected: N folders to keep in sync, case state serialized across, and the folder's CLAUDE.md does not load just because it was pointed at (direction rule 7 needs the opt-in variable).
      plugins installed at user or project scopeone versioned folder per procedure; the MCP server ships inside; switch on per project with one line — your fridge picturethe refine loop needs a version bump + update, not a save; the kit carries no memory; per-project scope binds the launch folder only (a subfolder launch does not inherit).
      plugins carried per run with --plugin-dircase windows stay bare; the kit arrives only where launched and dies at close; loads from the folder you name, so edits are livenothing is installed, so nothing is "always on" in the case folder; the launch line must carry the flag every time (a launcher script solves that); same memory gap.
      the coordinator pattern — across all fourthe case window dispatches several procedures at once and pulls the results back; parallelism is where the modularity earns out, since each dispatched session burns its own contextnothing arbitrates concurrent writes back into the case folder — the open question below

      Still open — yours to answer, in the order the briefing put them

      Which of your real procedures are briefable ("run a comp on this property") versus needing the window that already knows the client (a negotiation position)? That sorting criterion is yours and it decides how much dispatch the design wants.
      Do you want procedures to accumulate their own memory? If yes, the agent-level memory: user drawer is the mechanism to test; if no, versioned skill edits are the whole story.
      One procedure library, or split by transaction side (listing vs buyer)? Affects how the marketplace folder is organized — one plugin with branching skills, or two plugins.
      When several dispatched procedures write back into one case folder at once, what arbitrates? Nothing does today. A convention is needed before, not after.
      Answered 30 Aug: what defaultEnabled:false suppresses (everything) · the measured MCP cost (deferred, ~0 at launch) · whether a window launched with --plugin-dir reads the case folder's CLAUDE.md (yes — measured 30 Aug: a plain headless window and the plugin's own listing-analyst, both launched in a scratch case folder carrying a marker CLAUDE.md, saw the marker; the agent held Read, Write, Bash plus the harness's advisor tool).
      ?
      How to keep working this through: the Plugins page has the click-through of exactly these mechanics — where the files live, where the switch lives, what a window in the case folder loads, what goes stale when you edit the source. Every position in it is one of the measurements above.
      Glossary & trust

      Our pictures,
      the vendor's words

      Every nickname this manual uses, mapped to the term you will meet in the documentation and everywhere else. When you read outside, translate left-to-right; when you read here, the nickname is only a picture.

      Said hereThe vendor's termWhat it is, in one line
      a window · a seata session (interactive, or headless with -p)one running Claude Code conversation; a file on disk
      the machine flooruser scope — ~/.claude/settings, agents, memory cabinet and CLAUDE.md that reach every session on this Mac
      the folder you openthe working directory (project scope, plus its parent directories)where a session is launched; supplies CLAUDE.md, rules, settings, the memory drawer
      the rulebookCLAUDE.md (user · project · .claude/CLAUDE.md · CLAUDE.local.md · managed)instructions read automatically at launch because of the filename
      a rule · a page of the rulebooka rules file — .claude/rules/*.md, optionally with paths:a CLAUDE.md page kept as its own file; path-scoped ones load on a matching read
      a helperan agent / subagent (.claude/agents/*.md, --agent, the Agent tool)an identity file: tools, model, instructions, and what it carries
      the rosterthe available subagents listed to a sessioneach agent's name + description, fenced per item by Agent(a, b)
      recipe vs cookskill vs subagenttext the window follows itself vs a fresh window born with the instructions
      outside-service tools · connectionsMCP servers and their tools (mcp__server__tool)declared in ~/.claude.json, .mcp.json, a plugin, or --mcp-config
      the cabinet · a drawer · a card · the indexauto memory: ~/.claude/projects/<slug>/memory/ · a memory file · MEMORY.mdone directory per git repo; only the index loads at start (200 lines / 25 KB)
      the switchenabledPlugins in a settings file (user · project · local)one true/false line per plugin per scope
      the kit · the boxa plugin (manifest + skills · agents · hooks · mcpServers · lspServers), found through a marketplacea versioned folder, installed to a cache or carried with --plugin-dir
      handed in at launch · the flagsCLI flags: --settings --plugin-dir --mcp-config --append-system-prompt --agents --add-dirsupplied for one run, gone at close
      an automatic rule · the doormana hook (command · prompt · agent · http · mcp_tool types, on ~30 events)a program at a fixed moment; only PreToolUse can prevent an act
      a locked doorpermission rules (allow · ask · deny) and permission modesper tool pattern, per scope; deny wins
      the wallthe sandbox (sandbox.enabled, /sandbox)the OS fencing files and network under every command
      a fence · fenced per item / all-or-nothingthe agent's tools: linetools and MCP tools removed one at a time; the Skill listing present or absent as a set
      the squeeze · the cutcompaction (auto-compact, /compact)the conversation folded into a summary; files re-injected
      a judge at the exita Stop hook — /goal is a prompt-based oneruns when a turn ends; can refuse the exit
      a stranger's eyes · fresh contexta subagent dispatched to review (here: gap-checker)a different session that did not build the thing grades it
      told · held · worn · walled · checked · scored · watched · directed · shippedinstructions · tools · agents · enforcement · verification · evaluation · observability · orchestration · packagingthe nine jobs — our one-word memory aids, never the vendor's names
      a sign on the doorinstructions — CLAUDE.md, rules, skills: advisory contextread and followed; nothing enforced
      a ring · a keeper · the conductor · "this floor"this firm's names for headless sessions run on a schedule or by an engine — and "this floor" means this whole operation, distinct from the machine floor (user scope)firm vocabulary, not the vendor's

      Used and unused on this Mac — the takeaway

      Used

      Agents (34 files at user scope, ✓cmd 30 Aug) · hooks on six events · one deny rule · the script judge at the exit (the seat Stop hook in 32 of 34 agent files) · fresh reviewers · dispatch and workflows · two plugins (monolith, superpowers) · auto memory · a very large CLAUDE.md stack. Added 2026-09-01: /goal (the model judge at the exit) and claude plugin eval — both exercised for the first time, both with their costs measured.

      Unused, and available today

      the sandbox · OpenTelemetry · path-scoped rule files · an agent's own memory drawer · defaultEnabled: false · the InstructionsLoaded hook · /autocompact and the PreCompact/SessionStart(compact) pair · project-scope agents and skills.

      Trust — how each page was settled

      Measured on this Mac, 25–30 Aug 2026: every direction rule except 3 and 7; the child-inherits-parent-render result; the memory probes; the plugin scope files, the collision rule, the MCP-in-plugin result, the cache-copy and version-bump loop, defaultEnabled:false; the /context numbers; the mid-turn compaction and the forced compaction of a headless seat (this window's transcript, 27 Aug); the --plugin-dir-reads-the-case-CLAUDE.md probe and the listing-analyst tools probe (30 Aug); the permission-mode names from claude --help (their definitions are the vendor's). CLI 2.1.233 at the 28 Aug measurements, 2.1.251 on 30 Aug. Added 31 Aug – 1 Sep 2026 (CLI 2.1.251): /goal run end to end twice (reachable and unreachable), and claude plugin eval run end to end behind its enablement variable — including a measured defect in a shipped Anthropic eval script whose cause is still OPEN: three mechanisms were proposed and all three were demoted as explanations — but two of them are filed upstream as real, still-open defects, plus a fourth nobody here proposed. Each demotion was correct as a demotion and each threw away a true candidate.
      Quoted from the vendor, not exercised here: the compaction survival table, permission-rule grammar, the sandbox, OpenTelemetry, agent memory drawers, /goal's remaining edges (the no-tool-use warning, permission-mode neutrality, the whole interactive surface) and the untried plugin eval options and graders, direction rules 3 and 7, the interactive-mode keys.
      Where a summary of the doc was wrong, and the doc was right: a docs digest used during the build said a locally-sourced plugin loads in place; the vendor's own plugin pages say an installed plugin is copied to ~/.claude/plugins/cache (only a link-mode command source runs in place) — exactly what the 30 Aug measurement found (CLI 2.1.233 at measurement; 2.1.251 today). A subagent's summary is not the primary; the page is.
      Open, and whose: the four homes of a rule (the knowledge track) · the strategy seat memory index at 97% and its 37 unindexed files (a sitting with the strategy seat) · whether an Edit, a child's read, or an additional directory trips a path-scoped rule · the case-and-procedure decisions on the previous page (yours).