audience self · brad
status reference — research notes for the Vrataski three-mode design
kind reference (working)
sources_verified 2026-06-21 (raw doc markdown, non-WebFetch)

Claude Code loading & discovery — research notes

What this is. Source-verified notes on how and when Claude Code loads CLAUDE.md, skills, commands, settings, and plugins — gathered to ground the Vrataski three-mode (Standalone / Jacket / Mimic) distribution design. Facts below were read from the raw doc markdown (curl of code.claude.com/docs/en/*.md), not a WebFetch summary, on 2026-06-21. Source lines cited where it matters.

Sources

  • code.claude.com/docs/en/memory.md (captured separately as claude-code-memory-docs.md)
  • code.claude.com/docs/en/skills.md
  • code.claude.com/docs/en/permissions.md
  • code.claude.com/docs/en/plugins.md + plugins-reference.md

1. CLAUDE.md / memory (recap from memory.md)

  • Load order: walk up the tree from cwd; managed → user (~/.claude/CLAUDE.md) → project (./CLAUDE.md or ./.claude/CLAUDE.md) → local (CLAUDE.local.md). Concatenated root→cwd; closer-to-cwd read last.
  • Subdirectory CLAUDE.md loads ON DEMAND when Claude reads a file there — not at launch.
  • Imports: @path (relative-to-the-file or absolute / ~/), max depth 4 hops, skipped inside backticks & code fences, external imports prompt a one-time approval dialog.
  • Additional dirs do NOT load CLAUDE.md by default. Set CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 to load CLAUDE.md, .claude/CLAUDE.md, .claude/rules/*.md, CLAUDE.local.md from an --add-dir directory.

2. Skills (skills.md)

  • Where skills live (override order enterprise > personal > project):
    • Personal: ~/.claude/skills/<name>/SKILL.md — all projects.
    • Project: .claude/skills/<name>/SKILL.md — this project only.
    • Plugin: namespaced plugin-name:skill-name.
  • Parent + nested discovery (line 112, 134–136): project skills load from .claude/skills/ in cwd and every parent up to the repo root. Skills in nested .claude/skills/ BELOW cwd load ON DEMAND when Claude reads/edits a file in that subdir. A name clash keeps both — the nested one gets a directory-qualified name (apps/web:deploy).
  • Timing: descriptions loaded at startup (progressive disclosure); full body on invoke. Subagents with preloaded skills get full content at startup.
  • --add-dir is the skills exception (line 158): .claude/skills/ inside an --add-dir / /add-dir directory IS loaded automatically. The permissions.additionalDirectories SETTING grants file access only and does NOT load skills. ← load-bearing distinction.
  • Live reload (line 128): edits/adds/removes under ~/.claude/skills/, project .claude/skills/, or an --add-dir .claude/skills/ take effect mid-session. Creating a new top-level skills dir that didn't exist at launch needs a restart.

3. Commands (skills.md line 16, 110, 160)

  • "Custom commands have been merged into skills." A .claude/commands/deploy.md and a .claude/skills/deploy/SKILL.md both create /deploy. Existing .claude/commands/ keep working; skill wins on a name clash. Skills add: supporting-file dir, invoke-control frontmatter, and model-auto-invocation.
  • Commands are NOT loaded from additional directories (line 160) — only skills are the add-dir exception. So a command expressed as a commands/*.md file won't travel via --add-dir; the same thing expressed as a skill will.
  • Command nesting: .claude/commands/foo/bar.md namespacing is limited; skills carry the robust directory-qualified naming.

4. settings.json

  • Precedence (high→low): managed → CLI flags → local (.claude/settings.local.json) → project (.claude/settings.json) → user (~/.claude/settings.json).
  • Project .claude/settings.json auto-applies on CWD (subject to the workspace trust dialog on first entry). allowed-tools in project skills + autoMemoryDirectory etc. also gated by that trust dialog.
  • permissions.additionalDirectories--add-dir flag. The setting = file read/edit access only. The flag = file access plus the skills + CLAUDE.md(-with-env-var) exceptions.

5. Plugins (plugins.md / plugins-reference.md)

  • Structure: .claude-plugin/plugin.json manifest + skills/, commands/ (legacy), agents/, hooks/hooks.json, .mcp.json, bin/, etc.
  • Local install paths (no remote marketplace needed):
    • claude --plugin-dir ./path (or .zip) — loads a local plugin for that session (dev/testing). Repeatable; local copy beats an installed same-name plugin for the session.
    • claude --plugin-url <zip-url> — fetch a remote zip per session.
    • Skills-directory plugin (the elegant one): drop a .claude-plugin/plugin.json into a skill folder and it loads as <name>@skills-dir, bundling agents/hooks/MCP too. claude plugin init <name> scaffolds one at ~/.claude/skills/<name>/ (auto-loads next session, all projects). In a project .claude/skills/ it auto-loads project-scoped after the workspace trust dialog.
    • Marketplace: /plugin marketplace add + /plugin install for sharing (later/public).
  • Scope: ~/.claude/skills/<x>@skills-dir = global; project .claude/skills/ plugin = that project only; --plugin-dir = that session only.

What this means for the three modes (design inputs — NOT yet decided)

The naive plan breaks: "drop Vrataski in .jacket/ + add it to additionalDirectories setting + gitignore it" gives file access but loads NOTHING — not skills, not commands, not CLAUDE.md. The additionalDirectories setting is the wrong lever.

Levers that actually activate a toolkit dropped in a subdirectory:

Mechanism Skills Commands CLAUDE.md/docs Persistent? Cost
additionalDirectories setting yes (file access) useless for activation
--add-dir flag ✅ w/ env var per-launch (or scripted) needs flag every session
Skills-dir plugin (.claude-plugin/plugin.json in .claude/skills/) via skills ❌ (docs separate) ✅ project-scoped (trust dialog) commands must be skills; docs need another path
@import appended to host CLAUDE.md docs only, no skills
Nested .claude/skills/ under .jacket/ ✅ on-demand only weak (only when Claude touches .jacket/ files) not reliable from session start

Implication: Jacket almost certainly needs two wires, not one — (a) a skills-dir plugin (or --add-dir) to activate skills/commands, and (b) an @import in the host CLAUDE.md (or the --add-dir + env var) to load the root docs. "Commands merged into skills" also nudges the whole refactor toward expressing Vrataski commands AS skills, since only skills travel via the add-dir/plugin paths.

Correction to an earlier in-session claim: I'd said nested .claude/ below the project root isn't discovered. That's wrong — nested .claude/skills/ are discovered (on demand); it's nested commands and the additionalDirectories setting that don't load.


Prior art & landscape (research 2026-06-21)

Monolith-vs-layered verdict: the ecosystem median is one monolithic instruction file per tool at the project root (CLAUDE.md, .cursorrules, .github/copilot-instructions.md, .windsurfrules); reuse-across-projects = copy-paste or a single global file. Tight personal/shared-substrate/project separation as independent repos is early-adopter, not fringe — two-layer (global personal + project) is now common/platform-blessed; the 3+-tier discipline is uncommon-but-emerging.

  • AGENTS.md (agents.md): cross-tool convention, 60k+ repos, read by Cursor/Aider/Codex/ Copilot/Zed/Devin/Junie/etc. Nested/modular within a repo (nearest-file-wins), but no notion of a portable personal layer or shareable toolkit — solves cross-tool + intra-monorepo, not cross-project reuse. Input for our own AGENTS.md (subproject 0).
  • Jacket prior art — yzhao062/anywhere-agents (https://github.com/yzhao062/anywhere-agents): drops a gitignored .agent-config/ into any repo, host otherwise untouched, uninstall = delete dir. Beat-for-beat Jacket. Differences: it writes into host .claude/ + ~/.claude/ (less self-contained) and pulls live from upstream (vs. our frozen vendored copy). Has a source-vs-consumer self-detection test — directly relevant to the INSTALL.md "am I a pending jacket?" idea. → study from source when designing Jacket.
  • Mimic is the most idiosyncratic — no established convention for "reach in from outside." Works from the main loop (toolkit is cwd, reaches target via file access/--add-dir); the wall is subagents inherit parent cwd — open feature request https://github.com/anthropics/claude-code/issues/31940 (per-subagent cwd/additionalDirectories).

Parked (future, not this design)

  • ⏸️ Jacket self-update — keeping a deployed .jacket/ in sync with upstream Vrataski. Brad has ideas; deferred. Decision for now: Jacket vendors a frozen copy (no live-pull), self-updating is a later enhancement. (Contrast: anywhere-agents live-pulls.)