Claude Code Extensions: Skills, Subagents, Hooks, and Plugins

June 23, 2026 · updated June 25, 2026 · How Claude Actually Works (part 17)

▶ Watch on YouTube & subscribe to The Stack Underflow

Four words — skills, subagents, hooks, plugins — get swapped around constantly in Claude Code discussions, even by people who use the tool every day. That confusion is expensive. Reaching for a hook when you need a skill, or a plugin when you need a subagent, produces setups that are either fragile (soft suggestions when you needed hard guarantees) or bloated (heavyweight bundles when a single Markdown file would do). The four extension points exist because they solve genuinely different problems, live in different places on disk, and fire at different points in the agent loop.

Getting this taxonomy right is the difference between a Claude Code configuration that feels like it was designed — and one that grew like scar tissue. This tutorial maps all four, explains the mechanics underneath each one, and gives you a decision rule for reaching into the right bay.

The one-sentence version: Skills add domain know-how and auto-invoke when relevant; subagents add isolation and parallelism via their own context windows; hooks add deterministic lifecycle guarantees via code that fires every time; and plugins bundle all three into a versioned, shareable package.

The Four Extension Bays at a Glance

Before diving into any single one, here is the master map. The location is the tell — each extension lives in a different place, and that home reflects its job.

ExtensionLives atCore jobThe tell
SkillSKILL.md directoryAdds domain know-how; auto-invoked when relevantPlain text; portable open standard
Subagent.claude/agents/Isolated sessions; parallel executionSeparate context window per invocation
Hooksettings.json (or .claude/settings.json)Deterministic lifecycle gatesCode, not vibes — fires every matching event
PluginMarketplace or local bundle dirBundles skill + subagent + hook + slash command + MCP serverVersioned crate; installable with /plugin

Different homes, different powers. Learn the path, and the right tool becomes obvious.

Skills — Packaged Know-How That Auto-Invokes

A skill is a directory containing a SKILL.md file. That file starts with YAML frontmatter declaring two required fields — name and description — followed by instructions, optional executable scripts, and optional resource references. That is the entire format: text files on disk, no binary, no proprietary encoding.

my-pdf-skill/
  SKILL.md            ← entry point: name + description + instructions
  scripts/
    extract-text.py   ← optional executables the skill can reference
  prompts/
    system-prompt.txt ← optional extra resources

The SKILL.md file structure:

---
name: pdf-processor
description: Extract, parse, and summarise PDF documents for code review or analysis
---

## Instructions

When given a PDF file path, use the read_file tool to load it,
extract structured text section by section, and return a summary
with headers matching the document's structure.

Reference: ./prompts/system-prompt.txt for formatting guidance.

The behavior that distinguishes skills from everything else: when a task appears that matches the skill’s description, Claude auto-pulls that skill in — no explicit /skill invoke prompt required. You describe what the skill is for, and the relevance matching happens automatically inside the agent loop.

Anthropic published the Agent Skills open standard in December 2025 (docs.anthropic.com), and it was adopted across major AI coding tools including OpenAI Codex CLI, Microsoft’s Agent Framework, Cursor, and GitHub Copilot within months. A SKILL.md you author today is portable: it does not lock you to Claude Code. That cross-platform portability is a deliberate design choice — skills are the lingua franca of the agentic tooling ecosystem.

When to reach for a skill: you have a repeatable task type (PDF parsing, code review checklists, database migration scripts, API documentation generation) and you want Claude to arrive pre-loaded with the right context every time that task appears, without manually pasting instructions into every prompt.

Subagents — Isolation and Parallelism via Separate Sessions

Subagents live under .claude/agents/. Each one is defined as a Markdown file with YAML frontmatter that can declare a custom system prompt, tool restrictions, permission modes, and its own hooks and skills. When Claude encounters a task matching a subagent’s description, it delegates to that subagent using the Task tool — which spins up a completely independent session.

.claude/
  agents/
    search-agent.md       ← custom web search + summarisation agent
    test-runner.md        ← runs test suite, reports results
    backend-builder.md    ← spins up API endpoints in isolation

A minimal subagent definition:

---
name: search-agent
description: Performs web research tasks — use for any broad search or information gathering
tools: [web_search, read_file]
---

You are a research specialist. Search broadly, gather sources,
and return a concise synthesis. Do not attempt code edits.

The architecture produces two distinct benefits that work together:

Main session (clean context)

  ├─► Task tool ──► subagent-A (own context window)
  │                   noisy search → 40 intermediate results
  │                   false starts → retries
  │                   final output ──► returned to main

  └─► Task tool ──► subagent-B (own context window)
                    code generation branch A
                    final output ──► returned to main

Isolation: a noisy operation (broad web search, exploratory file scanning, large-corpus analysis) happens inside the subagent’s context window, not the main one. The main session receives only the clean, synthesised result. Context pollution does not flow back upstream.

Parallelism: multiple subagents can run simultaneously. Two research threads, two code-generation branches, a backend builder and a frontend builder — all in parallel, results merged back into the main session when each completes.

Claude Code ships with three built-in subagents — Explore (codebase exploration), Plan (task planning and breakdown), and a general-purpose agent — plus the /agents command for creating custom ones. Scoping is flexible: project scope (shareable via version control), user scope (applicable across projects), or local scope (not checked in).

When to reach for a subagent: any task that is either (a) context-polluting by nature, such as broad searches and exploratory work, or (b) independently parallelisable, such as fan-out research patterns, concurrent code generation branches, or simultaneous verification passes.

Hooks — Deterministic Lifecycle Gates

Hooks live in settings.json (or .claude/settings.json at project scope). They attach to named lifecycle events and fire a shell command — or a script — every single time that event occurs. No exceptions. No vibes.

The full event taxonomy as of 2026 (docs.anthropic.com/en/docs/claude-code/hooks):

CadenceEvents
Once per sessionSessionStart, SessionEnd
Once per turnUserPromptSubmit, Stop, StopFailure
Per tool callPreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch
Lifecycle signalsSubagentStart, SubagentStop, PreCompact, Notification, PermissionRequest

A minimal hook configuration in settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "scripts/validate-bash-call.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "scripts/run-lint.sh"
          }
        ]
      }
    ]
  }
}

The PreToolUse hook is especially powerful: it can allow, deny, ask (escalate to the user), or defer a tool call — and it can also modify the tool input before execution. When multiple PreToolUse hooks return conflicting decisions, the precedence is deny greater than defer greater than ask greater than allow. For UserPromptSubmit and SessionStart hooks, anything written to stdout is injected directly into Claude’s context for that session.

The critical distinction from a prompt instruction: a system prompt saying “please don’t run dangerous shell commands” is a soft suggestion. A PreToolUse hook on Bash that validates the command is code. It fires every time Bash is called, before execution. A bad call gets blocked before it runs. That is not a better suggestion — it is a different category of control entirely.

This is where organisational policy belongs: “no shell commands touching production databases”, “log all file writes to the audit trail”, “run lint after every code edit”, “send a Slack notification when a session ends”. Policies belong in hooks, not in system prompts.

When to reach for a hook: you need a hard guarantee, not a soft suggestion. Anything that must happen on every invocation — auditing, safety gates, automatic validation, CI triggers, team notifications — is a hook.

Plugins — Versioned Bundles for Sharing and Pinning

A plugin is a versioned crate that packages any combination of:

  • A skill (or several)
  • A subagent (or several)
  • Hooks
  • Slash commands
  • MCP servers
my-devops-plugin-v2.1.0/
  SKILL.md                 ← domain know-how bundled in
  agents/
    deploy-agent.md        ← purpose-built subagent
  hooks/
    pre_tool_use.sh        ← policy enforcement
  commands/
    /deploy.md             ← slash command shortcut
  mcp/
    server.py              ← MCP server providing tools
  manifest.json            ← name, version, description, dependencies

Plugins are in public beta as of 2026 and install directly inside Claude Code with the /plugin command. Anyone can build and host plugins, and third-party marketplaces are already operating — one community curator has published over 80 specialised subagent plugins covering DevOps automation, documentation generation, project management, and testing suites (anthropic.com/news/claude-code-plugins).

The version tag in manifest.json is not cosmetic. It means a team can pin to my-devops-plugin@v2.1.0 and know that every developer on the team has identical behaviour — identical skills, identical subagent prompts, identical hooks, identical tool access. Loose file-copying cannot give you that guarantee. Plugins make configuration reproducible and auditable.

When to reach for a plugin: you have built a setup (a combination of skill, hook, and MCP integration) that works well and you want to share it across projects or with other developers — either on your team or publicly — without manually copying and versioning individual files.

The Full Map: Where Each Extension Lives

~/ or project root

├── my-pdf-skill/
│   └── SKILL.md              ← Skills (auto-invoked know-how, open standard)

├── .claude/
│   ├── agents/
│   │   ├── search-agent.md   ← Subagents (isolated sessions, Task tool)
│   │   └── test-runner.md
│   │
│   └── settings.json         ← Hooks (lifecycle gates, always fires)
│       {
│         "hooks": { ... }
│       }

└── ~/.claude/plugins/        ← Plugins (versioned bundles, /plugin install)
    └── my-devops-plugin-v2.1.0/
        ├── SKILL.md
        ├── agents/
        ├── hooks/
        ├── mcp/
        └── manifest.json

How to Apply This: A Decision Rule

Given a problem, ask one question at a time:

Is this recurring domain knowledge Claude should always have for this task type?
  YES  →  Skill
  NO   ↓

Is this task context-polluting or parallelisable?
  YES  →  Subagent
  NO   ↓

Does something need to fire deterministically at a lifecycle event, every time?
  YES  →  Hook
  NO   ↓

Do I need to share a combination of the above across projects or with a team?
  YES  →  Plugin (which will contain skills, subagents, and hooks inside it)

Start with skills — they are the lowest-friction entry point. A Markdown file, a description, done. Graduate to hooks once you need policy guarantees. Add subagents once you have work that is either noisy or independently parallelisable. Reach for plugins when you want to share a working configuration, not just copy files.

Common Misconceptions

“Skills are just system prompt injections.” A skill is a structured directory following the Agent Skills open standard, with a declared name and description that drives automatic relevance matching. Unlike pasting text into every system prompt, a skill is only pulled in when the task matches — and because it follows an open standard, it is portable across Claude Code, Cursor, GitHub Copilot, and other tools that adopted the specification. The auto-invocation and portability are what make it a first-class mechanism rather than a workaround.

“Subagents share context with the main session.” They do not. Each subagent gets its own entirely separate context window. The main session stays uncontaminated regardless of how much noise the subagent generates while doing its work. Only the final synthesised output flows back. That isolation is the entire value proposition.

“Hooks are optional niceties I can replace with prompt instructions.” A prompt instruction is a soft suggestion that can be overridden, forgotten, or lost across turns. A PreToolUse hook on Bash is code that fires before every matched tool call, outside the model’s reasoning loop entirely. These are not alternatives — they are different categories. For anything that must always happen (auditing, blocking dangerous calls, triggering CI), only a hook gives you the guarantee.

“Plugins are just bundles for distribution.” Plugins do enable sharing, but they also enforce versioning. The version tag means you can pin a team to v2.1.0 and know every member has identical behaviour — the same skill instructions, the same subagent prompts, the same hook scripts, the same MCP server. Loose file-copying cannot replicate that. Reproducibility is the other half of what plugins solve.

Frequently Asked Questions

Can I use multiple skills at the same time? Yes. Claude can pull in multiple skills simultaneously if multiple task types match the work at hand. If you are doing work that involves both PDF parsing and database migrations, and you have skills covering both, both can be active in the same session. Skills do not conflict — they compose.

Do hooks run for all tool calls, or only specific ones? Hooks are scoped by event name and optionally by a matcher pattern against the tool name. You can attach a hook to every Bash call, only Edit calls, or all tool calls indiscriminately. The guarantee — that the hook fires every matching time — holds either way. Use the matcher to keep hooks surgical and avoid unnecessary overhead.

Is there a performance cost to using subagents? Each subagent is a separate session with its own context window, so there is some spin-up overhead per invocation. For tasks that are genuinely parallelisable, the wall-clock time often improves despite the per-session cost, because two subagents running in parallel beat one main session doing both tasks sequentially. The meaningful question is not “is there overhead?” but “does the isolation or parallelism justify it for this task?”

What is the difference between a skill and a subagent system prompt? A skill’s instructions are loaded dynamically when a task matches — they are not permanently in scope. A subagent’s system prompt is always active for that subagent’s session. Skills are good for broad domain know-how that applies to many task types. Subagent system prompts are good for narrow, purpose-built personas (a deploy agent, a test runner) that should always behave a specific way regardless of what task they receive.

Are plugins stable enough to use in production? As of 2026, plugins are in public beta. The core extension types they bundle — skills, subagents, hooks, MCP servers — are stable. The plugin packaging and /plugin installation mechanism is the beta surface. For teams that need reproducibility today, using plugins with pinned versions is a reasonable approach; just account for potential breaking changes in the plugin CLI during the beta period.

Where do I start if I have never used Claude Code extensions? Skills first. Write a SKILL.md for your most common repeating task type — the thing you find yourself re-explaining to Claude every session. Drop it in a directory, point Claude Code at it, and watch the auto-invocation work. Once you have a feel for that, add a PreToolUse hook for any tool call you want to validate. Subagents and plugins are the next step once you are running into context pollution or sharing needs.

Where This Fits in the Series

This tutorial is part of How Claude Actually Works, a course that builds a developer-accurate mental model of Claude from first principles — tokenisation and context windows through to tool use, MCP, and the full extension architecture of Claude Code.

The four extension bays covered here are Layer 4 of the Claude Stack mental model: the building blocks you reach for once you start treating Claude Code as a platform rather than a chat interface. For the full overview of how all these pieces fit together, see the Claude Stack overview of MCP, hooks, skills, and subagents which goes deeper on the hooks lifecycle specifically.

The next step in the series is the Agent SDK, which takes these same building blocks — skills, subagents, hooks — and makes them programmatically composable via Python and TypeScript libraries, so you can orchestrate multi-agent pipelines from code rather than configuration files.

For the CI/CD angle — running Claude Code headlessly in pipelines where hooks and subagents do most of the heavy lifting — see Claude Code in CI/CD.

Browse all tutorials to follow the full series.

Found this useful? The deep version lives on YouTube — new breakdowns of how AI dev tools actually work, weekly.

Subscribe on YouTube →