
Claude Code Skills vs Subagents vs Slash Commands vs Hooks vs Plugins: The Decision Guide (2026)

Written by
Sumit Patel
Published
July 23, 2026
Updated
July 23, 2026
Reading Level
Advanced Strategy
Investment
26 min read
Skills vs subagents vs commands vs hooks vs plugins — the short version
- 1Skill → a folder with SKILL.md (plus optional files) that teaches Claude a reusable method. Invoked by you as /command-name, or auto-invoked when its description matches the task. Custom slash commands are now part of this system.
- 2Slash command → today, mostly a synonym: old .claude/commands/*.md files still work, but new custom commands should be skills. Built-in commands (/help, /clear, /model, /compact) remain separate CLI features.
- 3Subagent → a forked Claude with its own context window. Use for delegation, exploration, and anything parallel. Its context is lost when it finishes — that's the price of isolation.
- 4Hook → a deterministic script at a lifecycle event (PreToolUse, PostToolUse, Stop...). Runs every time, no model judgment. Formatters, guards, test gates.
- 5Plugin → a versioned bundle of all of the above plus MCP definitions. The distribution format, not a new kind of logic.
- 6CLAUDE.md → ambient always-loaded rules. Keep it short; extract situational content into skills.
- 7One-line rule → command the human triggers: skill. Behavior that must happen regardless: hook. Work to delegate or parallelize: subagent. Setup to share: plugin.
Why I'm the one writing this — and why most comparison posts need a correction.
I'm a frontend developer. I build a 25-module ERP plus client CRM projects in React and TypeScript, and Claude Code drives a large share of that work daily — which means I've lived through every stage of its extension system, including the stage where 'should this be a command or a skill?' was a genuine time-wasting dilemma with comparison tables that contradicted each other. Then Anthropic resolved the dilemma by dissolving it: custom slash commands were folded into the skills system, with full backwards compatibility. That's the right design decision — the two things were never meaningfully different — but it quietly obsoleted a large share of the comparison content that still ranks for these queries. If you've read a 'commands vs skills' guide that treats them as rival systems, you've read pre-merge documentation. This post is the current map: the five primitives as one decision framework, verified against the official docs at my current Claude Code version ([[FILL: your Claude Code version at time of writing (claude --version)]]), illustrated with my actual — deliberately small — setup rather than an aspirational one. Where my own usage is thin (I'll be honest about which primitives I barely touch), I say so instead of pretending. No affiliation with Anthropic, no affiliate links; Claude Code ships new versions constantly, so verify mechanics against code.claude.com/docs before you standardize a team on anything here.
Every Claude Code user hits the same wall around week two: you've repeated the same instructions enough times that you know you should automate them — and then you discover there are five different ways to do it, and every guide defines them in isolation. Skills. Subagents. Slash commands. Hooks. Plugins. Add CLAUDE.md and MCP servers to the pile and you have seven concepts fighting for one job in your head. The comparison posts don't help as much as they should, for a specific reason: many of them are already wrong. Custom slash commands were merged into the skills system — old command files still work, but the 'commands vs skills' debate those posts agonize over has been settled by Anthropic deleting the distinction. So this guide does two things the existing content doesn't. First, it gives you the post-merge taxonomy — what each primitive actually is in the current Claude Code, verified against the official docs rather than months-old blog posts. Second, and more useful, it replaces five definitions with one decision framework built on a single question: who triggers this work, and how much discretion should the model have about it? Answer that question and the primitive picks itself. Human triggers it explicitly: user-invoked skill. Model should apply it when relevant: auto-invoked skill. Must happen every time with no discretion: hook. Needs its own context or needs to run in parallel: subagent. Needs to be shared as a package: plugin. The rest of this article is that framework expanded — with the comparison table, my own real (and modest) setup as the running example, and the anti-patterns section covering the expensive mistakes: judgment in hooks, destructive workflows on auto-trigger, and one-off prompts promoted into skills they didn't earn.
Key Takeaways
8 PointsThe 30-Second Decision Framework
If you only read one section, read this one.
Stop asking 'what's the difference between X and Y' five times. Ask one question about the work itself: who should trigger it, and how much discretion should the model have?
If a human should explicitly start it — a release checklist, a PR-description generator, a refactor procedure — make it a skill and invoke it as /command-name. The explicit trigger is a feature: you get a deliberate, button-like moment for workflows that shouldn't fire on a model's guess.
If the model should apply it whenever relevant — 'how we write migrations in this repo,' 'our component conventions' — make it a skill with a good description and let auto-invocation do the work. Same primitive, different trigger setting.
If it must happen every single time, with zero discretion — format after every edit, block writes outside the repo, run the test suite when the session stops — that's a hook. Hooks don't ask the model; they fire at lifecycle events, deterministically.
If the work should be delegated with its own context, or needs to run in parallel — codebase exploration, an independent review pass, three research threads at once — that's a subagent: a forked Claude with an isolated context window. The keyword is literally 'parallel': nothing else in the system does it.
If you're packaging any of the above to share — with your team, or the community — that's a plugin: a versioned bundle of skills, subagents, commands, hooks, and MCP definitions.
Notice what's not in the framework: 'slash command' as a separate destination. That's the merge — commands are how you invoke skills now, not a rival system. The next section covers why, because it's the correction half the internet still needs.
First, the Merge: Slash Commands Became Skills (And Your Old Files Still Work)
This is the fact that dates every comparison post written about the old system, so let's get it exactly right.
Historically, Claude Code had two separate customization paths that did nearly the same thing. Slash commands lived in .claude/commands/ as single markdown files — create review.md, get /review. Skills lived in .claude/skills/ as directories containing a SKILL.md plus supporting files, designed for auto-discovery when the task matched their description. Both created invocable workflows. Both could be auto-triggered. Both loaded instructions into context. Developers burned real time deciding between them, and the honest answer was usually 'it barely matters.'
So Anthropic unified them: as of v2.1.3, custom slash commands are part of the skills system. The practical rules of the merged world:
One — backwards compatibility is real. Files in .claude/commands/ keep working unchanged; nothing breaks on update. In my own setup, [[FILL: whether your old .claude/commands/ files still work post-merge, and whether you migrated them to skills]].
Two — skills are the recommended path for anything new, because they carry features flat command files don't: a directory for supporting files (templates, examples, scripts), frontmatter controls like disable-model-invocation, user-invocable, and allowed-tools, and automatic invocation on description match.
Three — precedence: if a skill and a command share a name, the skill wins. .claude/commands/review.md and .claude/skills/review/SKILL.md both want to be /review; the skill gets it.
Four — the /command surface itself now has several sources: built-in CLI commands (/help, /clear, /model, /compact — hardcoded features, untouched by the merge), your skills, plugin-provided commands (namespaced by plugin), and MCP prompts. Same slash, four origins.
One genuinely useful newer mechanic worth knowing: skill stacking. Recent versions let you start a message with multiple skills — the first plus up to five more — and pass trailing text as arguments to each, so /code-review /fix-issue 123 loads both with 123 as the argument. Check /skills for what's available in your session; it lists built-ins and your own.
- v2.1.3 merged custom slash commands into the skills system — the 'commands vs skills' debate is settled by design.
- .claude/commands/*.md files still work, unchanged. Migration is optional, not urgent.
- New custom commands should be skills: .claude/skills/name/SKILL.md, with supporting files and frontmatter controls.
- Name conflict → the skill wins over the command.
- The / prefix now surfaces four sources: built-in CLI commands, skills, plugin commands, MCP prompts.
- Skill stacking: invoke multiple skills in one message (first plus up to five more), with trailing text passed as arguments to each.
Skills: The Playbook Primitive (And Why They're Cheap on Context)
A skill is a folder-based instruction pack: a directory under .claude/skills/ containing a SKILL.md — the method, written in markdown with optional YAML frontmatter — plus whatever supporting files the method needs: templates, examples, reference docs, even scripts. It turns a general agent into a specialist for one recurring job in your codebase.
The design detail that makes skills the workhorse primitive is progressive disclosure, and it's worth understanding because it's the answer to 'won't all these files bloat my context?' Skills load in three levels. Level one: only the name and description are scanned each session — a few lines per skill, nearly free. Level two: when a skill fires (you invoke it, or its description matches the task), the SKILL.md body loads. Level three: supporting resources load only if the work actually needs them. Compare that to pasting the same instructions into every conversation, or to a bloated CLAUDE.md that occupies context whether relevant or not, and you see why the pattern won.
The trigger is configurable per skill, which is where the decision framework from earlier becomes concrete frontmatter. Want it human-only — a deploy procedure that should never fire on a model's guess? Set disable-model-invocation: true. Want it model-discoverable — repo conventions Claude should apply whenever it touches the relevant code? Write a precise description and let matching work. The description field is doing real routing work either way: vague descriptions mean skills that fire at the wrong times or never.
From my own setup, the skill I use most: [[FILL: one real skill or command from your workflow, what it does, roughly how its file is structured]]. Nothing exotic — and that's representative. The best skills encode boring, repeated method: how this repo writes a Redux slice, what a PR description must contain, the checklist before touching the billing module.
When a skill is the wrong choice: when the work needs guaranteed execution (hook), when it needs isolated or parallel context (subagent), or when it's a rule that genuinely applies every session (CLAUDE.md — sparingly).
Subagents: Isolation and Parallelism (The Only Primitive That Forks)
A subagent is a forked Claude instance with its own context window. Your main session delegates a task to it; the subagent works in isolation; results come back; the subagent's context is discarded. Every property that matters about subagents follows from that shape.
Isolation is the headline benefit. Long agentic sessions die by context pollution — exploration transcripts, file dumps, dead ends accumulating until the model loses the plot. Delegating the noisy phases to a subagent keeps your main context clean: an exploration subagent can read thirty files and return a two-paragraph summary, and your session pays for the summary, not the thirty files. That's why 'use subagents to keep the main context small, especially for exploration and planning' has become standard advice.
Parallelism is the exclusive benefit. Subagents are the only primitive in this taxonomy that supports running work concurrently — the practical keyword rule holds: when a task description contains 'in parallel,' the answer is subagents, full stop. Nothing else forks.
The cost is symmetric with the benefit: the isolated context is lost when the subagent finishes. Whatever nuance it discovered and didn't put in its return summary is gone. That makes subagents wrong for work where accumulated context is the point — a long refactor where each step builds on the judgment of the last belongs in your main session, not scattered across amnesiac forks.
On my ERP codebase, the shape that earns subagents is [[FILL: one real situation where you used or would use a subagent on the ERP codebase]] — the pattern being: bounded question in, compact answer out, details safely forgettable.
One composition note that ties the system together: primitives stack. A skill can specify that its work runs as a subagent; a user-invoked skill can orchestrate a pipeline where a subagent explores, the main session implements, and a hook formats the result. The primitives are less five rival features than five roles in one workflow.
- Subagent = forked Claude with an isolated context window; results return, context is discarded.
- Use for: exploration, research, independent review passes — anything where the main session needs the answer, not the transcript.
- The exclusive capability: parallel execution. 'In parallel' in a task description = subagents, always.
- The cost: no context persistence. Work whose value is accumulated judgment stays in the main session.
- Primitives compose: skills can delegate to subagents; hooks can wrap the results. Think roles in a pipeline, not rival features.
Hooks: The Guarantee Primitive (Determinism, Not Judgment)
Everything else in this taxonomy involves the model deciding something. Hooks are the opposite: deterministic scripts bound to lifecycle events, configured in settings.json or as scripts in your hooks directory, that fire every time the event occurs — no discretion, no description-matching, no model in the loop for the decision to run.
The lifecycle events are the vocabulary: PreToolUse fires before a tool call (and can block it — this is where 'never write outside the repo' guards live), PostToolUse fires after (the classic: run the formatter after every file edit), and Stop fires when Claude finishes (run the test suite, notify, lint the diff). The common production patterns are exactly the ones you'd guess: auto-format on edit, path and command guards, test gates on completion, secret redaction on shell commands.
The design principle that keeps hooks healthy is the one the best guides converge on: hooks are for certainty, skills are for method. A hook is excellent at 'this command pattern is forbidden' and terrible at 'is this code well-designed?' — deterministic checks, yes; broad review taste, no. If a check requires judgment, it belongs in a skill or subagent where the model can reason; forcing judgment into a hook gets you brittle regexes doing a reviewer's job badly.
The honest state of my own hook usage: [[FILL: one real hook you run (e.g. formatter after edits) — or an honest note that you don't use hooks yet and why]]. I'll flag the pattern I see in my own behavior and in readers': hooks are the most under-adopted primitive relative to their value, probably because they live in settings rather than in the conversational flow — you set them up once in cold blood rather than discovering them mid-task.
When a hook is the wrong choice: anything needing model judgment, and anything a human should consciously trigger. A hook that auto-deploys on Stop is not a productivity win; it's an incident report with a timestamp.
Plugins: The Shipping Box, Not a Sixth Logic
Plugins are the easiest primitive to place once you stop looking for new behavior in them: a plugin is a versioned bundle that packages skills, subagents, commands, hooks, and MCP server definitions together for installation as a unit. It's the distribution layer. Skills are playbooks, hooks are guarantees, subagents are delegates — plugins are the box they ship in.
What that means practically: when you install a plugin, you're installing a complete configured setup — its commands appear in your session namespaced by plugin (so a design plugin's command arrives as /plugin-name:command rather than colliding with yours), its hooks register, its skills become available. This is how whole workflows move between people: a team lead packages the repo's conventions, review skill, and formatting hooks once, and every developer installs one thing instead of copying five files into the right directories.
When to build one: the moment your setup needs to exist identically on a second machine or a second person. Before that moment, plugins are premature packaging — loose files in .claude/ are easier to iterate on. After it, they're the difference between 'here's my zip of dotfiles and a README' and versioned, updatable infrastructure. Teams should also treat plugin choice with mild security seriousness: a plugin can register hooks that run scripts on your lifecycle events, so 'install from people you trust' applies with the same force as any package manager.
My own usage is the honest baseline for how optional plugins are for a solo developer: my setup is [[FILL: how many skills/commands/hooks you actually have in your setup right now, and the 2-3 you use most]], and none of it is packaged as a plugin — because no second machine or teammate needs it yet. The day EdgeNRoots standardizes the ERP conventions across the team is the day that changes, and that's exactly the boundary the primitive is for.
The Five-Way Comparison Table
The framework, compressed into the table you'll actually screenshot. One deliberate editorial choice: 'slash command' gets a column so the table answers the query people search, but its column mostly points at skills — because that's the true post-merge answer.
| dimension | skill | slash command | subagent | hook | plugin |
|---|---|---|---|---|---|
| What it is | Folder with SKILL.md + supporting files — a reusable method | Post-merge: how you invoke a skill. Old .claude/commands/ files still work; built-ins (/help, /clear) are separate CLI features | Forked Claude with its own context window | Deterministic script at a lifecycle event | Versioned bundle of skills + subagents + commands + hooks + MCP definitions |
| Who triggers it | You (/name) or the model (description match) — configurable per skill | You, explicitly | The model (delegation) or a skill that specifies it | The lifecycle event — always, automatically | N/A — it's packaging; its contents keep their own triggers |
| Model discretion | Yes — the model applies the method with judgment | Yes, once invoked | Yes, in its own context | None. That's the point | Inherited from contents |
| Context behavior | Progressive disclosure: metadata always, body on trigger, resources on need — cheap until used | Loads the skill body into current context on invocation | Isolated window; main session pays only for the returned summary; context lost after | Runs outside the conversation — effectively zero context cost | Per its contents |
| Parallel execution | No | No (can stack up to six skills in one invocation, but they run in-session) | Yes — the only primitive that does | No (fires per event) | No (packaging) |
| Lives at | .claude/skills/name/SKILL.md (project) or ~/.claude/skills/ (user) | Legacy: .claude/commands/*.md — still honored; skill wins name conflicts | Defined via agent configuration / invoked as a task | settings.json or hooks scripts directory | Installed from a marketplace or repo; commands namespaced by plugin |
| Best for | Recurring method: conventions, checklists, procedures with templates | Deliberate human-triggered workflows (deploy, release, PR description) | Exploration, research, review passes, anything parallel | Formatters, guards, test gates, secret redaction — guarantees | Sharing a complete setup with a team or the community |
| Wrong for | One-off prompts; rules that must run every time | Anything the model should discover on its own | Work whose value is accumulated context across steps | Judgment calls; anything destructive on auto-fire | A solo setup nobody else installs — premature packaging |
* Claude Code ships new versions near-daily, and mechanics in this table — stacking limits, frontmatter fields, precedence rules — are version-dependent. Everything here was verified against the official documentation at code.claude.com/docs at the time of writing (Claude Code [[FILL: your Claude Code version at time of writing (claude --version)]]). Re-verify before standardizing a team convention on any row.
Where CLAUDE.md and MCP Fit (The Two Adjacent Pieces)
Two things sit next to this taxonomy and get wrongly merged into it, so let's place them precisely.
CLAUDE.md is the ambient layer: a markdown file read at the start of every session, encoding persistent instructions — project conventions, commands to run, hard constraints. Its defining property is also its cost: it occupies context all the time, relevant or not. That yields a clean division of labor with skills. Rules that genuinely apply to every session — 'this repo uses pnpm,' 'never touch the generated folder' — earn their permanent context residence in CLAUDE.md. Anything situational — the migration procedure, the release checklist, the PR format — belongs in a skill, where progressive disclosure makes it free until needed. The practical audit: read your CLAUDE.md and ask, per paragraph, 'does this apply to every single session?' The paragraphs that answer 'only sometimes' are skills waiting to be extracted, and extracting them is the cheapest context optimization available.
MCP servers are the capability layer: they connect Claude to external systems — databases, browsers, issue trackers, design tools — giving it tools it doesn't natively have. The clean distinction from skills: MCP provides abilities, skills provide method. An MCP server lets Claude query your Postgres; a skill teaches it how your team writes reporting queries against that Postgres. They compose rather than compete — a skill can direct MCP tool use, and plugins can bundle MCP definitions alongside everything else. One operational contrast worth knowing: traditional MCP servers load their tool definitions up front, which historically made heavy MCP setups context-expensive at session start — one more reason the skills pattern, with its lazy loading, took over so much of the customization surface. I covered the setup side in my MCP servers guide; this taxonomy is the 'when to reach for which' layer above it.
With those two placed, the full stack reads cleanly: CLAUDE.md for always-true context, skills for on-demand method, hooks for guarantees, subagents for delegation, MCP for external capability, plugins for shipping the lot.
- CLAUDE.md = ambient rules, paid for in context every session. Reserve for genuinely always-true instructions.
- The audit: any CLAUDE.md paragraph that applies 'only sometimes' should be extracted into a skill.
- MCP = external capability (tools); skills = method for using capability. They compose, not compete.
- MCP tool definitions historically load up front (context-heavy); skills load progressively (context-cheap) — a key reason skills became the default customization surface.
- Full stack in one line: CLAUDE.md (context) → skills (method) → hooks (guarantees) → subagents (delegation) → MCP (capability) → plugins (distribution).
Anti-Patterns: The Four Expensive Mistakes
The framework tells you what to build. Experience — mine and the community's — says these four things not to build cost the most.
One: judgment in hooks. Hooks excel at deterministic checks — block that path, run that formatter — and fail at taste. A hook trying to enforce 'good code review' via pattern matching is a brittle regex doing a reviewer's job; the review belongs in a skill or subagent where the model can actually reason. If writing the hook script has you encoding opinions rather than rules, you're in the wrong primitive.
Two: destructive workflows on auto-trigger. Anything that can deploy, publish, delete, spend money, or touch production should keep a deliberate human invocation — a user-invoked skill with disable-model-invocation set, never an auto-matched skill or a Stop hook. The convenience delta of auto-triggering a deploy is seconds; the failure mode is production. Package the method as a skill by all means; keep the trigger in human hands.
Three: one-off prompts promoted to skills. A skill earns its directory when a workflow repeats and benefits from structure — templates, references, checklists. A prompt you liked once is not a skill; it's a note. Promoting every good prompt creates a skills directory full of vague descriptions that misfire on auto-invocation and bury the five skills that matter. My own bar, stated earlier: third repetition, or it stays a note.
Four: collecting primitives as strategy. Knowing many commands, installing many plugins, defining subagents you never delegate to — surface area isn't capability. The developers getting real leverage from this system run small, sharp setups where every piece answers the who-triggers-it question crisply. Mine is deliberately minimal, and the honest inventory is in the sections above; I'd rather ship that than an impressive-looking .claude/ directory I don't use.
The meta-pattern across all four: every mistake is a trigger mismatch — model discretion where determinism belonged, automation where deliberation belonged, permanence where a one-off belonged. Which is the framework's final argument for itself: get the trigger right and the rest of the decision collapses.
Frequently Asked Questions
Strategic Summary
Final Thoughts
The honest summary: Claude Code doesn't have five competing features. It has one extension system with five roles, and the confusion mostly comes from documentation written before the roles settled — especially before custom slash commands were merged into skills, a change that quietly retired half the comparison content still ranking for these queries. The framework that survives contact with real work fits in four lines. Skill: a method, triggered by you or discovered by the model. Hook: a guarantee, fired by lifecycle events with no discretion. Subagent: a delegate with its own disposable context — and the only route to parallelism. Plugin: the box you ship the other three in. CLAUDE.md holds the always-true context underneath; MCP supplies external capability alongside. My parting advice mirrors my own deliberately small setup: build less than you think. One skill at the third repetition of a method. One hook for the thing you keep reminding the model to do. A subagent when the transcript would pollute your session or the work can genuinely fork. A plugin the day a second person needs your setup. Every primitive added past need is context, maintenance, and misfire surface — the developers winning with this system run sharp little toolkits, not museums. And because Claude Code ships versions near-daily: the mechanics here were verified against the official docs at my version on the publish date, and the framework will outlive the details — but check code.claude.com/docs before you standardize a team on any specific behavior. When the taxonomy shifts again, this post will get the same correction treatment I just gave everyone else's. --- Last reviewed: July 2026. Mechanics — the commands-into-skills merge, precedence rules, frontmatter fields, stacking limits, hook events, plugin composition — are taken from official Claude Code documentation (code.claude.com/docs) and version-release coverage at the time of writing, at Claude Code [[FILL: your Claude Code version at time of writing (claude --version)]]. Claude Code updates near-daily; verify against current docs before relying on version-specific behavior. Setup examples reflect my own real configuration. No affiliation with Anthropic; no affiliate links.
What does your .claude/ directory actually look like — how many skills, hooks, and subagent definitions, and which three earn their place? Tell me in the comments. I'm collecting real setup inventories across solo devs and teams, and early signs say the median winning setup is much smaller than the tutorials imply.
If you found this useful, I write hands-on, no-hype guides to Claude Code's moving parts — extension primitives, MCP setup, usage limits — from daily use in real client work. Browse the AI Tools for Developers hub, or reach me via stacknovahq.com/contact.
Next Up
Continue your research
MCP Servers for Frontend Devs: A Practical Setup Guide (Claude Code, 2026)
Claude Code vs Cursor on a 25-Module ERP: An Honest Comparison
Claude Sonnet 5 Tested on Real Production Code
How to Debug AI-Generated Code: A Real Developer's Vibe Debugging Guide
Claude's Two July Promos, Untangled: Cowork 2x Usage vs the Fable 5 50% Window
Sources & Research
Claude Code documentation — Extend Claude with skills (official; skill invocation, stacking, arguments)
https://code.claude.com/docs/en/skills
Claude Code documentation — full docs index (verify hooks events, plugin mechanics, and version behavior here before publishing)
https://docs.claude.com/en/docs/claude-code/overview
LaoZhang AI — Hooks vs Slash Commands vs Skills: trigger-owner framing and stop rules (June 2026)
https://blog.laozhang.ai/en/posts/claude-code-hooks-slash-commands-skills
Brent W. Peterson — Commands vs Skills in Claude Code (the v2.1.3 unification explained)
https://medium.com/@brentwpeterson/commands-vs-skills-in-claude-code-607610c47284
Totalum — Claude Code Skills in 2026: vs Hooks, vs Subagents, vs MCP (folder anatomy and hook patterns)
https://www.totalum.app/blog/claude-code-skills-totalum
alexop.dev — Claude Code Customization: CLAUDE.md, Slash Commands, Skills, and Subagents
https://alexop.dev/posts/claude-code-customization-guide-claudemd-skills-subagents/


