Claude Code — Extension Architecture

Every customization mechanism available in Claude Code and how they connect
*12 mechanisms, one composable system — skills, hooks, memory, MCP, agents, and more*
Context & Instructions
Lifecycle & Hooks
Tools & Extensions
Memory & Persistence
Agents & Delegation
Security & Permissions

Session Lifecycle — Where Everything Plugs In

① Session Start
CLAUDE.md loaded Skill descriptions loaded MEMORY.md loaded Hook: SessionStart MCP servers connect Settings & permissions applied
② User Prompt
Hook: UserPromptSubmit Skill routing (intent match) Permission mode check
③ Model Inference
All context in window CLAUDE.md + Skills + Memory MCP tool definitions
↓ (tool call loop)
④ PreToolUse
Hook: can block (exit 2) Permission check (allow/deny/ask) Sandbox enforcement
⑤ Tool Execution
Built-in: Bash, Read, Edit, Write, Grep, Glob MCP tools: mcp__server__tool Task → Subagent Hook: SubagentStart/Stop Skill invocation
⑥ PostToolUse
Hook: observe results Back to ③ if more tools needed
↓ (response complete)
⑦ Stop
Hook: Stop Hook: Notification (if needs attention) Auto-memory update
↓ (if context full)
⑦b PreCompact
Hook: PreCompact Summarize older messages CLAUDE.md + Memory reloaded
↓ (user exits)
⑧ Session End
Hook: SessionEnd Transcript saved
Context & Instructions
📄
CLAUDE.md Files Native
Persistent instructions loaded into every conversation. The primary way to give Claude always-on context about your project, preferences, and rules.
*"The instructions that are always there"*
Precedence (highest → lowest): /etc/claude-code/CLAUDE.md ← managed policy ./CLAUDE.md ← project (committed) ./.claude/rules/*.md ← modular rules ~/.claude/CLAUDE.md ← personal global ./CLAUDE.local.md ← personal project ~/.claude/projects/*/memory/ ← auto-memory
Key features
FeatureHow
Import other files@path/to/import syntax (max depth 5)
Path-specific rulesYAML frontmatter with paths: glob
Additive loadingAll levels contribute simultaneously
Child dirsLoad on-demand when files accessed
Put team conventions in ./CLAUDE.md (committed), personal prefs in CLAUDE.local.md
Use .claude/rules/*.md for modular, topic-specific rules
Don't put secrets or API keys in CLAUDE.md — it's loaded into context
Skills Native
Markdown instruction packages with optional workflows, tools, and slash commands. Auto-invocable by intent matching or user-invocable via /name.
*"Teach Claude a new specialty"*
skill-name/ SKILL.md ← YAML frontmatter + instructions Workflows/ ← step-by-step procedures Tools/ ← CLI tools (TypeScript) *.md ← reference context files
Frontmatter options
FieldPurpose
nameSlash command name
descriptionIntent matching for auto-invocation
allowed-toolsSkip permission prompts
context: forkRun in isolated subagent
modelOverride model when active
hooksSkill-scoped lifecycle hooks
disable-model-invocationOnly user can trigger
Legacy: Slash Commands
Still supported but skills are preferred: .claude/commands/name.md ← project commands ~/.claude/commands/name.md ← global commands Same YAML frontmatter as skills. If a skill and command share a name, the skill takes precedence.
Write a strong description — Claude uses it for auto-invocation intent matching
Use context: fork for heavy skills to avoid polluting the main context
Don't use legacy .claude/commands/ for new work — skills are the replacement
⚙️
Settings & Config Native
JSON configuration files controlling permissions, hooks, environment, model, MCP, sandbox, UI, and more. Five-level precedence hierarchy.
*"The control plane"*
Precedence (highest → lowest): /etc/.../managed-settings.json ← org policy CLI flags ← session only .claude/settings.local.json ← personal project .claude/settings.json ← shared project ~/.claude/settings.json ← personal global
Key configuration areas
AreaKeys
Permissionsallow, deny, ask, defaultMode
Hookshooks object (event → handler map)
Environmentenv object (injected into all sessions)
Modelmodel, availableModels
MCPenableAllProjectMcpServers
Sandboxsandbox.enabled, network allowlists
PluginsenabledPlugins, marketplaces
Use .claude/settings.local.json for personal prefs that shouldn't be committed
Pre-approve safe commands in allow to reduce permission prompts
Don't put bypassPermissions outside containers — it disables all safety checks
Lifecycle & Automation
🪝
Hooks Native
Deterministic scripts at lifecycle events. Run outside the AI — no LLM involved (unless type: "prompt" or "agent"). Can block actions (exit 2).
*"Automation that runs every time, no exceptions"*
EventWhenCan Block?
SessionStartSession begins/resumesNo
UserPromptSubmitUser sends promptNo
PreToolUseBefore tool executesYes
PostToolUseAfter tool succeedsNo
StopClaude finishes respondingNo
SubagentStart/StopAgent spawned/finishedNo
NotificationAttention neededNo
PreCompactBefore context compactionNo
SessionEndSession terminatesNo
Hook types
TypeDescription
commandShell script (default). stdin=JSON, exit code=action
promptSingle-turn LLM eval (Haiku by default)
agentMulti-turn subagent with tool access
Use PreToolUse hooks to block dangerous commands (exit 2 = block)
Keep hooks fast — they run on every tool call and slow hooks hurt responsiveness
Don't put complex logic in hooks — use type: "agent" for multi-step verification
⌨️
Keyboard & UI Native
Interactive mode with keyboard shortcuts, vim mode, status line, and input modes.
*"The developer-facing surface"*
ShortcutAction
Ctrl+C/DCancel / Exit
Ctrl+GOpen prompt in editor
Ctrl+OToggle verbose output
Ctrl+BBackground running task
Ctrl+TToggle task list
Shift+TabCycle permission modes
Alt+PSwitch model
/Commands & skills
!Bash mode (direct exec)
@File path autocomplete
Use Ctrl+O to debug — verbose mode shows hook output and tool details
Use Shift+Tab to quickly switch to plan mode for exploration
Don't forget Ctrl+B — background long tasks instead of waiting
📊
Status Line Native
The bar below the prompt input. Shows model, permission mode, cost, and can be extended with a custom command that outputs dynamic info (git branch, project state, etc.).
*"Your always-visible dashboard"*
Configure in ~/.claude/settings.json: "statusLine": { "type": "command", "command": "~/.claude/statusline.sh" }
How it works
AspectDetail
InputScript receives CLAUDE_PROJECT_DIR and other env vars
OutputScript's stdout becomes the status line content
RefreshRuns on each prompt cycle — keep it fast (<100ms)
Default infoModel name, permission mode, token usage, cost
Custom infoGit branch, test status, build state, project context
Write a fast shell script — it runs on every prompt and slow scripts lag the UI
Show project-relevant context: git branch, active feature, environment
Don't do network calls or heavy computation in the status script
Tools & Extensions
🔌
MCP Servers Native
Model Context Protocol connects Claude to external tools, databases, and APIs. Open standard. Three transport types: HTTP, SSE, stdio.
*"External tool plugins via open protocol"*
Scope hierarchy: ~/.claude.json (project section) ← personal, this project .mcp.json (project root) ← team-shared ~/.claude.json (global section) ← personal, all projects managed-mcp.json ← organization-wide
Key features
FeatureDetail
Tool SearchLazy-loads tools, reduces context up to 95%
OAuthBuilt-in OAuth 2.0 for remote servers
Resources@server:protocol://path mentions
Prompts → CommandsBecome /mcp__server__prompt
Env vars${VAR:-default} in config
Use .mcp.json in project root for team-shared tool configs
Use ${VAR} in config for secrets — never hardcode API keys
Don't register too many MCP tools — use Tool Search (ENABLE_TOOL_SEARCH=auto) to lazy-load
🛠️
Built-in Tools Native
The core tool set Claude uses automatically. You don't call them directly — Claude picks the right tool based on your request. You guide via prompt shortcuts: @ for files, ! for bash, / for commands.
*"You describe the task, Claude picks the tool"*
ToolPurposeYou trigger via
BashShell commands! prefix or ask for terminal work
ReadFiles, images, PDFs@path mention or "read this file"
EditModify files"change X to Y in file"
WriteCreate files"create a new file with..."
GlobFind files by pattern"find all *.ts files"
GrepSearch content"search for X in the codebase"
WebFetchFetch URLsPaste a URL or "fetch this page"
WebSearchWeb search"search the web for..."
TaskSubagentsClaude delegates automatically
SkillInvoke skills/skill-name in prompt
Use @path/to/file to reference files — Claude will read them automatically
Use ! prefix for direct bash execution without Claude's interpretation
Don't micro-manage tool selection — describe what you want, Claude picks the best tool
📦
Plugins Native
Packaging layer that bundles skills, hooks, agents, and MCP servers into a single installable unit. Distributed via marketplaces.
*"npm for Claude Code extensions"*
plugin.json ← manifest skills/ ← bundled skills hooks/hooks.json ← bundled hooks agents/ ← bundled subagents .mcp.json ← bundled MCP servers
Marketplace sources
SourceExample
githubGitHub repository
npmnpm package
directoryLocal file path
urlDirect URL
Bundle related skills + hooks + agents into one plugin for easy distribution
Don't enable untrusted plugins — they can register hooks and MCP servers
Don't duplicate what a skill can do — plugins are for sharing across teams/projects
Memory & Persistence
🧠
Auto Memory Native
Per-project persistent memory. Claude reads and writes MEMORY.md (first 200 lines loaded at session start). Topic files loaded on demand.
*"Intelligence that compounds across sessions"*
~/.claude/projects/<project>/memory/ MEMORY.md ← auto-loaded (200 lines) debugging.md ← topic file (on demand) patterns.md ← topic file (on demand)
Controls
Env VarEffect
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1Disable auto-memory
/memory commandOpen memory files in editor
Keep MEMORY.md under 200 lines — only the first 200 are auto-loaded
Use topic files (debugging.md, patterns.md) for detailed notes
Don't store session-specific state — memory is for stable patterns confirmed across sessions
📝
Session Transcripts Native
Every session saved as JSONL. Enables context recovery, session continuation, and learning extraction. Auto-compaction when context approaches limits.
*"Nothing is ever truly lost"*
~/.claude/projects/<project>/ <session-id>.jsonl ← full transcript <session-id>/subagents/ ← agent transcripts
Use --resume to continue a previous session with full context preserved
Transcripts are great for post-hoc learning extraction and auditing
Don't rely on transcripts for secrets — they're stored as plain-text JSONL
🗜️
Context Compaction Native
When the conversation approaches context limits, Claude automatically summarizes earlier messages. The PreCompact hook fires before this happens.
*"Long conversations that never hit a wall"*
AspectDetail
TriggerAutomatic when context window fills (configurable %)
BehaviorSummarizes older messages, preserves recent context
HookPreCompact fires before — save state or inject reminders
ManualEsc Esc to rewind/summarize on demand
OverrideCLAUDE_AUTOCOMPACT_PCT_OVERRIDE sets trigger %
Use PreCompact hook to inject critical context that must survive compaction
Keep CLAUDE.md instructions concise — they reload after compaction
Don't rely on early conversation details surviving — put stable facts in memory files
Agents & Delegation
🤖
Subagents (Task Tool) Native
Spawn isolated agents for parallel or specialized work. Each runs in its own context window. Cannot nest (no subagent-of-subagent).
*"Divide and conquer with isolated contexts"*
Built-in TypeModelPurpose
ExploreHaikuFast, read-only codebase exploration
PlanInheritResearch during plan mode
general-purposeInheritComplex multi-step tasks
BashInheritTerminal commands in separate context
Custom agent frontmatter
Locations: .claude/agents/name.md ← project agents ~/.claude/agents/name.md ← global agents Frontmatter fields: name, description, tools, model permissionMode, maxTurns, skills mcpServers, hooks, memory
Use Explore (Haiku) for cheap, fast codebase searches — save Opus for complex work
Launch independent subagents in parallel — they don't share context
Don't expect nesting — subagents cannot spawn other subagents
👥
Agent Teams Native
Multiple independent Claude Code sessions that communicate via shared task lists and peer-to-peer messaging. Experimental.
*"Self-coordinating agents — no central manager"*
FeatureSubagentsTeams
ContextOwn window, returns to callerFully independent
CommunicationReports to main onlyPeer-to-peer
CoordinationMain managesShared task list
Enable
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
Use teams for truly independent workstreams that need to coordinate (e.g., frontend + backend)
Don't use teams when subagents suffice — teams have higher overhead and are experimental
Don't forget to set CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 — it's off by default
🧬
Custom Agents Native
Define reusable agent personas in markdown files with frontmatter. Each gets its own tools, model, permissions, skills, and optional persistent memory.
*"Specialists you design once and reuse forever"*
Locations: .claude/agents/reviewer.md ← project-scoped ~/.claude/agents/researcher.md ← global (all projects) Frontmatter: name, description, model, tools permissionMode, maxTurns, skills mcpServers, hooks, memory
Give agents narrow tools lists — an analyst doesn't need Edit or Write
Use memory: project for agents that should remember across sessions
Don't give agents broad permissions — use permissionMode: plan for read-only work
Security & Permissions
🔒
Permissions Native
Six permission modes with granular allow/deny/ask rules using glob-style patterns. Evaluation order: deny → ask → allow (first match wins).
*"Trust boundaries you actually control"*
ModeBehavior
defaultPrompt for first use of each tool
acceptEditsAuto-accept file edits
planRead-only (analyze, don't modify)
delegateCoordination-only for team leads
dontAskAuto-deny unless pre-approved
bypassPermissionsSkip all checks (containers only)
Rule syntax examples
Bash(npm run *) ← wildcard match Read(./.env) ← exact file Read(./secrets/**) ← directory glob WebFetch(domain:x.com) ← domain filter mcp__github__* ← MCP tool pattern Task(Explore) ← subagent control
Start with default mode, then add specific allow rules as you learn your patterns
Use deny rules for commands that should never run (e.g., Bash(rm -rf /))
Don't put broad wildcards in allowBash(*) defeats the entire purpose
📦
Sandbox Native
OS-level sandboxing for bash commands. Controls file system access, network access, and process isolation. Configurable via settings.
*"Defense in depth — not just permission prompts"*
SettingPurpose
sandbox.enabledToggle sandboxing
sandbox.network.allowedDomainsNetwork allowlist
sandbox.permissions.additionalDirectoriesExtra FS access
Enable sandbox in production/CI — it restricts file system and network at OS level
Whitelist only the domains your project actually needs in allowedDomains
Don't confuse sandbox with permissions — sandbox is OS-level, permissions are prompt-level
🏢
Managed Policies Native
Organization-level admin controls. Deployed to system paths, they override all user settings. Set allowed/denied MCP servers, enforce permission modes, and control model access.
*"Guardrails that individual users cannot override"*
System paths: /etc/claude-code/managed-settings.json ← Linux /etc/claude-code/CLAUDE.md ← org instructions /etc/claude-code/managed-mcp.json ← org MCP servers
What admins can control
ControlEffect
allowedMcpServersWhitelist specific MCP servers
deniedMcpServersBlock specific MCP servers
defaultModeForce a permission mode for all users
deny rulesBlock specific tools/commands org-wide
modelRestrict available models
Use managed policies for compliance requirements that users must not bypass
Deploy org-wide CLAUDE.md for coding standards all teams must follow
Don't over-restrict — heavy managed policies frustrate developers and reduce adoption
How It All Connects

The Complete Picture

DEFINE
CLAUDE.md → always-on instructions
SKILL.md → domain expertise
settings.json → configuration
.mcp.json → external tools
agents/*.md → custom agents
AUTOMATE
hooks → lifecycle triggers
PreToolUse → security gates
permissions → allow/deny/ask
sandbox → OS isolation
auto-memory → learn & persist
EXTEND
MCP servers → external APIs
plugins → packaged bundles
subagents → parallel workers
agent teams → coordination
keybindings → custom shortcuts
Key Environment Variables
VariablePurposeDefault
ANTHROPIC_MODELModel overrideclaude-sonnet-4-5-20250929
CLAUDE_CODE_MAX_OUTPUT_TOKENSMax output tokens32768 (max 65536)
BASH_DEFAULT_TIMEOUT_MSBash command timeout600000 (10 min)
CLAUDE_CODE_DISABLE_AUTO_MEMORYToggle auto-memory0 (enabled)
CLAUDE_CODE_EFFORT_LEVELReasoning effort (Opus 4.6)high
MAX_THINKING_TOKENSExtended thinking budget
CLAUDE_AUTOCOMPACT_PCT_OVERRIDEAuto-compaction trigger %
ENABLE_TOOL_SEARCHMCP lazy tool loadingauto
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMSEnable agent teams0 (off)
Claude Code Extension Architecture Reference — February 2026 Logo