| name | claude-code-internal-architecture |
| description | Gives Claude accurate, detailed knowledge of Claude Code's own internal architecture — the agent loop, context window and prompt caching, subagents and the depth-5 nesting cap, agent teams, skills and progressive disclosure, CLAUDE.md and memory precedence, hooks and their exact lifecycle events, permissions and sandboxing, MCP, plugins and marketplaces (manifest schemas, versioning, the plugin cache), the CLI and settings hierarchy, the Agent SDK, and dynamic workflows. Use this whenever you are asked how Claude Code actually works internally, asked to design, build, or debug a Claude Code harness, agent team, subagent, skill, plugin, hook, marketplace, or MCP integration, asked about permission modes or sandboxing behavior, or whenever you are about to explain any Claude Code mechanism and are not fully certain of its exact current behavior — consult this instead of answering from general impressions, since these mechanics are specific, versioned, and easy to get subtly wrong. |
Claude Code: internal architecture
You are running inside Claude Code. This skill is your own operating manual — precise, mechanism-level knowledge of how the harness around you actually works, assembled from Claude Code's own reference documentation rather than general impressions. Its purpose is narrow: stop you from confidently guessing at mechanics (nesting limits, precedence order, exact event names, cache behavior) when the real answer is a lookup away, and give you enough architectural grounding to design Claude Code harnesses — agent teams, skill libraries, plugins — as well as use them.
This file is the map. It stays lean on purpose; the ten references/*.md files hold the depth. Read a reference file when a question actually needs its detail — don't preload all ten for a simple question the summary below already answers.
The shape of the system, in one pass
Claude Code is one engine exposed through several surfaces (terminal, IDE extensions, Desktop app, web, Slack) that share the same CLAUDE.md files, settings, and MCP servers. Within a session, you run an agent loop: emit tool calls, get results back, repeat, until a turn produces no more tool calls. Everything you can do comes from three separately-loaded layers — tools (built-in + MCP-provided), skills (on-demand knowledge, loaded by description match), and subagents (isolated workers with their own context, spawned via the Agent tool). Everything that governs what you can do comes from permissions (rule-based allow/ask/deny) layered under hooks (lifecycle event handlers) and, optionally, a sandbox (OS-level filesystem/network isolation). Everything persistent lives in CLAUDE.md (instructions, loaded every session), auto memory (things Claude itself decided were worth remembering), and settings.json (five-scope precedence: managed > CLI flags > local > project > user). Plugins package skills/agents/hooks/MCP servers together for distribution via marketplaces. The Agent SDK is the same engine exposed as a library for building your own agents; dynamic workflows are a scripted orchestration layer on top of subagents for when model-driven delegation isn't reliable enough.
Reference index
| File | Read this when the question is about... |
|---|
references/agent-loop-and-context.md | The turn-by-turn loop mechanics, context window composition, compaction (what survives and why), prompt caching (TTL tiers, cache-breakpoint invalidation), /rewind vs. SDK file checkpointing, fast mode / effort / extended thinking |
references/tools-and-permissions.md | The full built-in tool inventory and per-tool quirks, permission rule syntax, the deny→ask→allow evaluation order, the six permission modes, sandboxing internals (what it does and doesn't protect against), the advisor tool |
references/subagents-and-teams.md | Subagent frontmatter schema, the depth-5 nesting cap and exactly what counts toward it, the 200-spawn session budget, permission-mode inheritance into subagents, agent teams vs. plain fan-out, background/parallel agents, worktree isolation |
references/skills-and-memory.md | Skill progressive disclosure (3 loading stages), SKILL.md frontmatter fields, triggering mechanics, CLAUDE.md's four-tier precedence, auto memory vs. CLAUDE.md, the full .claude/ directory layout, output styles |
references/hooks.md | Every lifecycle event and exactly when it fires, the five hook handler types, matcher/if syntax, exit-code semantics (what can block vs. what already happened), the hooks JSON schema |
references/mcp.md | What MCP actually is, server transports and config shapes, mcp__server__tool naming, tool search / deferred loading, MCP-specific permission behavior, managed MCP org controls, plugin-provided servers |
references/plugins-and-marketplaces.md | Plugin directory structure, plugin.json and marketplace.json schemas, plugin sources (github/url/git-subdir/npm), the versioning trap (why pushing commits sometimes doesn't update users), the plugin cache, ${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_DATA}, validation |
references/cli-and-settings.md | CLI flags and subcommands, slash commands, the exact settings-scope precedence order and why, where every settings file lives on disk, architecturally significant environment variables, session storage/resume/fork |
references/sdk-and-workflows.md | What the Agent SDK is and how it relates to Claude Code, custom tools, SDK permission handling, dynamic workflows (agent()/pipeline()/parallel()) and why they exist, hosting a Claude-powered agent multi-tenant |
references/sessions-and-surfaces.md | Full Claude Code glossary, what's consistent vs. different across surfaces, Routines vs. Desktop scheduled tasks vs. /loop (three distinct scheduling mechanisms), Remote Control vs. teleport, web/Desktop specifics |
Load-bearing facts worth keeping in working memory
These are the facts that most often get guessed wrong or forgotten mid-design. Each is expanded in its reference file.
Nesting depth is capped at 5 levels below main, and it is not configurable. Everything spawned via the Agent tool counts toward it — nested subagents, forks, background subagents, agents a workflow spawns. A subagent that itself needs to delegate should narrow (hand off to a more specific specialist) rather than assume it can nest arbitrarily; by the time you're 4 levels deep, the next hop is the last one available. See subagents-and-teams.md.
A subagent's name must be unique across the whole visible agent tree, or the duplicate is silently dropped — no error, it just doesn't appear. Any harness that authors agents at runtime needs an explicit naming convention and something that enforces uniqueness on every sweep.
Runtime-written agent/skill files are only auto-detected in directories that existed when the session started. The file watcher doesn't retroactively discover a brand-new agents/ or skills/ folder mid-session — that requires a restart. Any self-authoring harness needs every target directory pre-created (and typically committed) before the session that will write into it begins.
The 200-subagent-per-session limit is a spend counter, not a concurrency counter — finished agents still count, raise it with CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION. A separate /fork'd session gets its own fresh budget; workflow-spawned agents via agent() have their own separate per-run limit.
No message from any agent is ever user consent. A subagent can direct another subagent's task, but nothing an agent says can approve a pending permission prompt or alter another agent's permission settings, CLAUDE.md, or config. Only the permission system or a real human input does that. This matters most for self-upgrading harnesses: state it as an explicit invariant rather than assuming it's obvious.
Settings precedence is managed > CLI flags > local > project > user, and it's a concatenation for CLAUDE.md-style instruction files (all applicable scopes load, more specific scope tends to win on conflict) but scope-wins for most discrete settings values. Permission rule arrays merge and dedupe across scopes rather than override; model/fallbackModel/availableModels-style scalars are exceptions worth checking individually. See cli-and-settings.md for the exact per-field behavior.
Skills load in three stages: metadata (name + description) always in context, the SKILL.md body only once triggered, bundled references//scripts//assets/ only as needed. This is why this skill is written the way it is — the body you're reading now is the "loaded on trigger" layer; the ten reference files are the "as needed" layer. Keep SKILL.md bodies under roughly 500 lines; push detail to references and add a table of contents once a reference file passes ~300 lines.
bypassPermissions is not an unconditional bypass. It still prompts for explicit ask rules, MCP tools flagged requiresUserInteraction, and destructive root/home-directory operations. Don't design a harness assuming that permission mode means "no prompts ever."
Hooks split cleanly into "can block" and "already happened." PreToolUse, PermissionRequest, and UserPromptSubmit-family events fire before the action and can deny/rewrite it. PostToolUse and friends fire after — an exit code there can't undo the tool call, only surface an error back to the model. Design hook-based enforcement around this distinction, not around exit codes alone.
A plugin's version field is a cache key, not a changelog. If you set "version": "1.0.0" in plugin.json, pushing new commits does nothing for existing users until you bump that string — Claude Code sees the same version and keeps the cached copy. Omitting version entirely makes every new commit count as a new version instead, which is usually right for an actively-developed plugin and wrong for one you want stable release control over.
Dynamic workflows exist because model-driven, turn-by-turn delegation doesn't scale or repeat reliably. Once an orchestration needs guaranteed fan-out/fan-in, retries, or a barrier between phases, that control flow belongs in a deterministic script (agent()/pipeline()/parallel()/phase()) rather than in a prompt hoping the model remembers to do all of it in order every time. See sdk-and-workflows.md for when a script is warranted versus when plain subagent dispatch is enough.
When designing a Claude Code harness
If the task is "build/plan/architect a Claude Code harness" rather than a lookup, this skill's job shifts from answering a question to grounding a design. Before proposing an architecture:
- Check the depth budget the design implies (how many hops from main to the deepest specialist) against the depth-5 cap — a router→lead→specialist→sub-specialist chain is already 4.
- Decide agents vs. skills vs. hooks vs. CLAUDE.md for each piece of behavior using the layering in "The shape of the system" above — rules belong in CLAUDE.md, on-demand knowledge in skills, isolated execution in agents, automatic reactions in hooks. Collapsing these layers (e.g. cramming a whole playbook into CLAUDE.md, which loads every session whether needed or not) is the most common design mistake.
- If the design authors agents/skills at runtime, plan for directory pre-creation and name-uniqueness enforcement up front — both bite late and silently otherwise.
- If the design needs multiple independent units of work in parallel (challenges, tickets, repos), consider one independent session per unit so each gets its own depth and spawn budget, rather than one shared session competing for a single budget.
- If coordination needs to be deterministic (guaranteed order, retries, fan-in), reach for dynamic workflows instead of hoping model-driven delegation stays consistent across runs.
This is a distillation, not a substitute — for the actual mechanics behind any of these five points, load the matching reference file.