Claude Code Extension Points: When to Use What¶
Choose the right extension point — CLAUDE.md, rules, skills, hooks, subagents, MCP servers, or plugins — based on enforcement needs, context cost, and portability.
At a glance¶
| Extension point | Purpose | Loads when | Context cost |
|---|---|---|---|
| CLAUDE.md | Project conventions | Session start | Full content every turn |
.claude/rules/ |
Path-targeted rules | Session start or file match | Path-scoped |
| Skills | Workflows and reference knowledge | Descriptions at start; full on invoke | Progressive |
| Hooks | Deterministic shell commands at lifecycle events | On trigger | Zero (external) |
| MCP servers | External tool and service access | Session start | Schemas only |
| Subagents | Isolated agents for focused tasks | On spawn | Zero (isolated) |
| Agent teams | Multi-agent coordination | On session creation | Zero per teammate |
| Plugins | Distribution bundles | On install | Varies |
Decision framework¶
flowchart TD
A[Need to extend Claude Code] --> B{Must happen 100%<br/>of the time?}
B -- Yes --> C[Hook]
B -- No --> D{Needs external<br/>service access?}
D -- Yes --> E[MCP server]
D -- No --> F{Applies to every<br/>session universally?}
F -- Yes --> G{Short and<br/>global?}
G -- Yes --> H[CLAUDE.md]
G -- No --> I[.claude/rules/]
F -- No --> J{Repeatable workflow<br/>or reference knowledge?}
J -- Yes --> K[Skill]
J -- No --> L{Needs isolated context<br/>or parallel execution?}
L -- Yes --> M[Subagent]
L -- No --> N{Multiple agents<br/>need to coordinate?}
N -- Yes --> O[Agent team]
N -- No --> P{Needs to be shared<br/>across repos/teams?}
P -- Yes --> Q[Plugin]
P -- No --> H
Based on the official features overview and community models (Ottmann, GenAI Unplugged).
CLAUDE.md vs .claude/rules/ vs skills¶
All three deliver instructions, but differ in scope and context cost.
| CLAUDE.md | .claude/rules/ | Skills | |
|---|---|---|---|
| When to use | Core conventions, under ~200 lines | Domain rules scoped to file paths | On-demand reference or /name workflows |
| Loads | Every session, unconditionally | Session start or on file-path match | Descriptions at start; full on invocation |
| Context cost | High — always present | Medium — path-targeted | Low — progressive |
| Typical content | Architecture, test commands, conventions | Lint rules for frontend/, API rules for api/ |
Procedures, checklists, templates |
Keep CLAUDE.md lean: path-specific rules go in .claude/rules/, detailed procedures go in skills. See Hierarchical CLAUDE.md and Progressive Disclosure.
Deterministic vs probabilistic¶
Deterministic — the model cannot override:
- Hooks fire at 18 lifecycle events. The agent cannot skip or override them.
- CLAUDE.md loads unconditionally at session start (memory docs).
Probabilistic — the model decides when to invoke:
- Skills: Claude invokes them based on description relevance (skills docs). Set
disable-model-invocation: truefor explicit-only. - Subagent delegation: the parent decides when to spawn.
For non-negotiable rules, prefer hooks. See Hooks vs Prompts.
When extension points combine¶
- CLAUDE.md and hooks: CLAUDE.md states the rule; a
PreToolUsehook enforces it. See Hooks for Enforcement vs Prompts for Guidance. - Skills and subagents: a skill defines the procedure; a subagent runs it in isolation.
- MCP and skills: MCP exposes external tools; a skill provides the workflow that uses them.
- Plugins bundle agents, skills, hooks, and MCP configs for distribution. Plugins solve distribution, not logic.
Commands are merged into skills — existing .claude/commands/ files continue to work.
Why the determinism boundary matters¶
The CLI spawns hooks as shell processes at lifecycle events, independent of the model's token stream. The model cannot see or suppress them. Skills, subagents, and .claude/rules/ are text in the model's context, so a confusing context can cause the model to skip them. Anything routed through model reasoning is probabilistic; anything run at the infrastructure layer is deterministic.
CLAUDE.md's high context cost follows from this: it is injected into every request unconditionally. Skills load full content only on invocation.
When this backfires¶
- Overlapping extension points: a path-scoped rule that also needs enforcement requires both a
.claude/rules/entry and a hook. You then maintain the rule in two places, which creates drift. - Hook proliferation: hooks applied to stylistic preferences, rather than non-negotiable compliance, add startup latency and more failure modes.
- CLAUDE.md bloat: at 500+ lines, unconditional injection weakens instruction-following on unrelated tasks. Move domain content to rules or skills early.
- Premature plugins: bundling before two or more repos need the config adds release overhead. A shared git subtree is cheaper at small scale.
Security: per-server MCP trust¶
Before v2.1.69, .mcp.json silently trusted all servers. Claude Code now shows a per-server trust dialog on first session (changelog) — automated setups relying on silent enablement will see a prompt per server after updating.
Deprecation: /output-style → /config¶
/output-style was deprecated in v2.1.73 for /config (changelog). Output style is now fixed at session start to preserve prompt cache hit rates — mid-session changes invalidated the cache. Custom style directories (~/.claude/output-styles/, .claude/output-styles/) still work. See System Prompt Replacement for substituting a domain-specific identity for the default persona.
Example¶
A team wants to enforce that all SQL migrations include a DOWN migration. They also want a reusable database review workflow and access to their internal schema registry.
| Requirement | Extension point | Why |
|---|---|---|
Every migration file must contain DOWN |
Hook (PreToolUse on Write) |
Non-negotiable — must fire 100% of the time, the model cannot skip it |
| "Review this migration" workflow | Skill (.claude/skills/review-migration.md) |
On-demand procedure with steps; loads only when invoked |
| "All SQL uses snake_case" convention | .claude/rules/db.md with glob db/migrations/** |
Path-scoped rule; only loads when touching migration files |
| Schema registry lookup | MCP server | External service access; exposes get_schema tool |
| Share all of the above across repos | Plugin | Bundles the hook, skill, rule, and MCP config for npm install distribution |
The hook script (hooks/check-down-migration.sh) runs deterministically. The skill and rule are probabilistic but scoped. The MCP server bridges to an external system. The plugin packages everything for distribution.
Key Takeaways¶
- Start with the decision flowchart: enforcement need, service access, scope, and portability each point to a different extension point
- CLAUDE.md is for short, universal conventions;
.claude/rules/for path-targeted rules; skills for on-demand knowledge - Hooks are the only fully deterministic extension point — use them when compliance is non-negotiable
- Skills load progressively; hooks and subagents have zero context cost — choose based on context budget
- Plugins are distribution packaging, not a separate logic layer
- MCP servers now require per-server trust approval (v2.1.69) — silent bulk enablement is no longer supported
/output-styleis deprecated in favor of/config(v2.1.73) — output style is fixed at session start for cache efficiency