← All posts

Explainer

Skills vs plugins vs MCP vs subagents in Claude Code: how to choose

Skills vs plugins vs MCP vs subagents in Claude Code: how to choose

Claude Code has six extension points, and they are not six siblings. Three of them are genuinely different kinds of thing: a skill is prose the model loads when it matches, a subagent is a second context window, an MCP server is a process that speaks a wire protocol. Plugins and marketplaces are not a fourth kind — they are packaging and distribution for the first three. And slash commands have stopped being a separate mechanism at all: Anthropic's own docs now say custom commands have been merged into skills.

That last sentence is why "should this be a skill or a slash command?" gets mushy answers. Half the write-ups on the internet are describing a taxonomy that no longer exists. Everything below was checked against Claude Code 2.1.221 and the current reference pages at code.claude.com/docs in August 2026, with the CLI commands run on a real machine. Where the docs and the folklore disagree, the folklore is called out.

The decision table

Start here. If you know what you are trying to accomplish, this settles it in one row.

You want to…Reach forNot, because
Teach the agent a procedure — a checklist, a house convention, a multi-step workflow Skill An MCP server adds capability, not behaviour. A subagent would run the procedure somewhere you can't see.
Trigger that procedure yourself, by name, on demand Skill (or a legacy .claude/commands/*.md file) Same mechanism now. Add disable-model-invocation: true if only you should start it.
Reach a system Claude can't reach — an API, a database, a SaaS product MCP server A skill has no credentials and no code path of its own; it can only tell Claude to use tools it already has.
Keep a long, noisy sub-task out of your main conversation Subagent A skill's body lands in your context and stays there for the session.
Make something happen on a lifecycle event, whether or not the model cooperates Hook Skills and MCP tools are model-invoked. A hook is not — it fires deterministically.
Ship a bundle of the above to your team, versioned Plugin Loose files in .claude/ can't be versioned, namespaced or installed.
Let people discover and install that bundle Marketplace A marketplace is a catalogue file. It holds no behaviour of its own.

What each one actually is

MechanismLives atWho starts itRuns code?
Skill ~/.claude/skills/<name>/SKILL.md, .claude/skills/<name>/SKILL.md You (/name) or the model, by matching the description No — it is text that can instruct Claude to run a bundled script with its own tools
Subagent .claude/agents/*.md, ~/.claude/agents/*.md The model, via the Agent tool, routed on the description Yes — it has its own tools, permissions and model
MCP server .mcp.json (project) or ~/.claude.json (local / user) The model, by calling mcp__server__tool Yes — a separate process or a remote endpoint, with its own auth
Hook settings.json, keyed by event name Claude Code itself, on a lifecycle event Yes — and the model has no say in whether it fires
Plugin A directory with .claude-plugin/plugin.json, cached under ~/.claude/plugins/ Nothing — it contributes the four above Only through what it bundles
Marketplace .claude-plugin/marketplace.json in a git repo Nothing — it is a catalogue No

The axis that actually separates them: when it enters your context

Almost every practical difference between a skill, an MCP server and a subagent comes down to what is in the model's context at session start, and what only arrives when it's needed. Get that picture right and the rest follows.

at session start only when needed skill: name + description budgeted at ~1% of the window the full SKILL.md body lands in your window, stays all session MCP: tool names + instructions schemas deferred by tool search the schema, then the call only the tools Claude actually uses subagent: name + description routing signal only a separate window entirely only the summary comes back
All three advertise themselves cheaply and load expensively. The difference is where the expensive part lands: in your window (skill), as a typed call and result (MCP), or in a window you never see (subagent).

The change that broke everyone's mental model: commands are skills

The skills reference carries a note that most write-ups predate. Quoting it directly: "Custom commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way." Existing .claude/commands/ files keep working; if a skill and a command share a name, the skill takes precedence.

So the two trees still exist on disk, but they are no longer two mechanisms. What the folder form buys you is real, though, and it is worth migrating for: a directory to put supporting files in, frontmatter that controls whether you or the model can invoke it, and — the big one — the model loading it automatically when your request matches the description. A file in .claude/commands/ supports the same frontmatter; it just can't carry a bundled script or a reference doc next to itself. If you're still mapping the command surface, our guide to the slash commands that matter covers the built-ins this doesn't touch.

Skills: prose that loads when it matches

A skill is a folder containing SKILL.md. Personal skills live in ~/.claude/skills/<name>/ and follow you across projects; project skills live in <repo>/.claude/skills/<name>/ and travel with the repo. A minimal one is two lines of frontmatter and a body:

---
description: Review a PR diff for correctness bugs first, then style. Use before opening a PR.
---

Read the diff. Flag real correctness bugs before anything cosmetic.
Name the inputs that produce the wrong outcome, or it is a note, not a blocker.

Three things about that frontmatter surprise people, and all three are documented:

That is the mechanism people mean by progressive disclosure: descriptions always in context, body only on invocation. One consequence rarely mentioned: once a skill is invoked, its rendered body enters the conversation as a single message and stays there for the rest of the session. Claude Code does not re-read the file on later turns. Write standing instructions, not one-time steps.

Beyond the body, a skill folder can carry templates, reference docs and scripts. Reference them from SKILL.md using ${CLAUDE_SKILL_DIR} so the path resolves wherever the skill is installed. allowed-tools pre-approves specific tools for the turn that invokes the skill — the grant clears on your next message, which is a good deal more conservative than it first sounds.

Two precedence rules worth memorising. Across levels, enterprise overrides personal, and personal overrides project — note the direction, because subagents resolve the opposite way. And nested .claude/skills/ directories below your working directory load lazily: the first time Claude reads or edits a file under apps/web/, that package's skills become available, appearing as /apps/web:deploy if the name clashes with a root-level one.

What a skill cannot do is the useful half of the definition. It has no code path of its own. It cannot add a tool, hold a credential, open a socket, or fire on an event. It can tell Claude to run a bundled script — but the running is the Bash tool, under your permission rules, exactly as if you had typed the instruction yourself.

Subagents: a second context window with its own permissions

A subagent is a markdown file with YAML frontmatter in .claude/agents/ (project) or ~/.claude/agents/ (personal). Unlike skills, name and description are both required here. The body is the subagent's system prompt — and only that, plus basic environment details. It does not inherit your conversation or the full Claude Code system prompt.

Delegation is description-routed, same as skill selection: the model reads descriptions and picks. The mechanism is the Agent tool, which means you can switch delegation off entirely by denying Agent in your permission rules. The frontmatter is where subagents pull ahead of skills: tools and disallowedTools scope what it can touch, model routes cheap work to a cheaper model, permissionMode and maxTurns bound it, isolation: worktree gives it its own checkout, and memory gives it a directory that survives across conversations.

The precedence trap: for subagents the order runs managed settings → the --agents CLI flag → .claude/agents/~/.claude/agents/ → plugin agents, so a project definition beats your personal one. For skills it is the reverse. If you keep a personal code-reviewer in both trees and wonder which one ran, that is why. We go deeper on isolation and fan-out in Claude Code subagents explained.

MCP servers: a process, not a prompt

An MCP server is the only mechanism here that is not a markdown file. It is a program — local over stdio, or remote over HTTP, SSE or WebSocket — that advertises tools, resources and prompts over the Model Context Protocol. Configuration lives at one of three scopes:

ScopeLoads inStored inShared with the team
Local (default)The current project only~/.claude.json, under that project's pathNo
ProjectThe current project only.mcp.json in the repo rootYes, via version control
UserAll your projects~/.claude.jsonNo
claude mcp add --transport http notion https://mcp.notion.com/mcp
claude mcp add --transport http shared-server --scope project https://example.com/mcp
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable -- npx -y airtable-mcp-server

Tools arrive namespaced as mcp__<server>__<tool>. There is a trap worth knowing if you also write hooks: a server bundled inside a plugin registers its tools as mcp__plugin_<plugin-name>_<server-name>__<tool-name>, so a hook matcher written against the bare server key never fires for it. MCP also gives you two things people forget exist — resources you pull into a prompt with @server:protocol://path, and server-side prompts that show up in your / menu as /mcp__server__prompt.

Now the correction. The received wisdom is that skills are cheap because only the description loads, while MCP tool schemas are always in context and eat your window. That is out of date. Claude Code ships MCP tool search, enabled by default: tool definitions are deferred, only tool names and each server's instructions load at session start, and Claude searches for the schemas it needs. In the docs' words, "adding more MCP servers has minimal impact on your context window." Two consequences: the context-cost argument is no longer the tiebreaker between a skill and an MCP server, and if you are writing a server, its instructions field now does the same job a skill's description does — with a 2 KB truncation limit on both tool descriptions and server instructions.

The real line is capability, not cost. An MCP server can hold an OAuth token, paginate a result set, and return typed structured data. A skill cannot. For the setup path end to end, see Claude Code MCP servers.

The one that isn't in the list: hooks

Skills, MCP tools and subagents are all model-invoked. The model decides, and the model can decide not to. If your requirement is "this must happen every time, whether or not the agent is in the mood", none of them is the answer — you want a hook. Hooks register in settings.json against a lifecycle event, get a JSON payload on stdin, and for some events their exit code changes what the agent does next. Formatting on every write, blocking a command pattern, notifying you when a turn ends: those are hooks, not skills. The full event list and the exit-code semantics are in Claude Code hooks explained.

Plugins: packaging, not a capability

"Skill vs plugin" is a category error, and it is the most common one. A plugin does not compete with a skill — it contains skills, alongside everything else. A plugin is a directory, optionally with a .claude-plugin/plugin.json manifest, and the components sit at the plugin root:

Path in the pluginWhat it contributes
.claude-plugin/plugin.jsonThe manifest — name (which becomes the namespace), description, version
skills/<name>/SKILL.mdSkills, invoked as /plugin-name:name
commands/*.mdSkills in the flat legacy form
agents/*.mdSubagent definitions
hooks/hooks.jsonEvent handlers
.mcp.jsonMCP server configurations
.lsp.jsonLanguage servers, for real code intelligence
monitors/monitors.jsonBackground watchers that push notifications into the session
bin/Executables added to the Bash tool's PATH while enabled

The docs flag one mistake specifically, because everybody makes it: do not put skills/, agents/, commands/ or hooks/ inside .claude-plugin/. Only the manifest goes in there. Everything else sits at the plugin root.

Anthropic's own guidance on when to bother is refreshingly blunt. Standalone .claude/ configuration is for personal workflows, project-specific customisation and quick experiments, and it buys you short names like /deploy. Plugins are for sharing with teammates, distributing to a community, versioned releases and reuse across projects — and the price is namespaced invocation like /my-plugin:deploy. Start standalone, convert when you're ready to share. Test a plugin without installing it with claude --plugin-dir ./my-plugin, and /reload-plugins after edits.

The boundary is genuinely blurring, though, and it's worth knowing before you draw a hard line. claude plugin init my-tool scaffolds a plugin inside your skills directory — it creates ~/.claude/skills/my-tool/ with a manifest and a starter SKILL.md, and it loads on the next session as my-tool@skills-dir with no marketplace and no install step. Drop a .claude-plugin/plugin.json into any skill folder and it becomes a plugin that can bundle agents, hooks and MCP servers. So "is it a skill or a plugin" can now be answered "yes".

Marketplaces: the catalogue — and what's really in it

A marketplace is a git repo with a .claude-plugin/marketplace.json listing plugins and their sources. You register one and install from it:

claude plugin marketplace add anthropics/claude-plugins-official
claude plugin marketplace list
claude plugin install <plugin-name>@<marketplace>
claude plugin list --available --json

Anthropic runs two public ones. claude-plugins-official is curated and registers itself automatically the first time you launch Claude Code interactively — there is no application process; Anthropic decides what goes in. claude-community is the reviewed community catalogue, and you add it yourself from anthropics/claude-plugins-community.

Here is the part that changes how you should think about the marketplace, and it takes ten seconds to check for yourself. Running claude plugin list --available --json in August 2026 returned 278 plugins, every single one of them from claude-plugins-official. The manifest's own category counts: development 116, productivity 49, database 36, monitoring 20, security 17, deployment 8, design 7. And the names, in alphabetical order, tell the story faster than the counts do — Airtable, AlloyDB, Adobe, Aikido, Amplitude, Apollo, Appwrite, Asana, Atlassian, Auth0, Box, Canva, ClickHouse.

The plugin marketplace is a connector directory. It is where vendors ship an integration with their product, and it is very good at that. It is not a library of craft — "how we review a PR here", "the checklist before a migration", "our house TypeScript conventions". Mostly it can't be: that knowledge is repo-specific and belongs in your .claude/skills/. If you went to the marketplace looking for taste and came back disappointed, nothing was wrong with your search.

The second ecosystem, which most write-ups miss

There is a whole parallel distribution system for skills that has nothing to do with plugins or marketplaces. Skill repos are plain git repos full of skill folders, installed with a separate CLI:

npx skills add vercel-labs/agent-skills

The CLI comes from vercel-labs/skills, with a registry at skills.sh. What makes it interesting is where it puts things. It installs a canonical copy and symlinks each agent's directory at it, so one skill can serve several tools. On this machine, five of the entries in ~/.claude/skills/ are symlinks:

$ ls -l ~/.claude/skills/     # abridged
drwxr-xr-x  council
drwxr-xr-x  wrangler
lrwxr-xr-x  clean-code -> ../../.agents/skills/clean-code
lrwxr-xr-x  find-skills -> /Users/me/.agents/skills/find-skills
lrwxr-xr-x  frontend-design -> ../../.agents/skills/frontend-design
lrwxr-xr-x  typescript-expert -> ../../.agents/skills/typescript-expert
lrwxr-xr-x  vercel-react-best-practices -> /Users/me/.agents/skills/vercel-react-best-practices

The ~/.agents/ path is the point: it is deliberately vendor-neutral, so the same folder can serve Claude Code, Cursor, Cline and the rest — the CLI claims detection for 75+ coding agents, on the basis that skills follow a shared Agent Skills specification rather than a Claude-specific one. And this is not a hack Claude Code merely tolerates: the skills reference explicitly says a skill entry "can be a symlink to a directory elsewhere on disk", that Claude Code follows it, and that a target reachable from two places is loaded once.

So there are two shipping lanes, and they are good at different things. Plugins and marketplaces are Claude-only, versioned, and can carry hooks, MCP servers and executables. Skill repos are cross-agent, prose-only, and install in one line without a manifest. If you are publishing a coding convention, the second lane reaches more agents. If you are publishing an integration, only the first lane can carry it. Anthropic maintains a skills repo of its own at anthropics/skills, which is also where the packaging script lives for uploading skills to claude.ai.

One catch if you publish that way: outside Claude Code, only six frontmatter fields are legal — name, description, license, compatibility, metadata and allowed-tools. Everything else in Claude Code's frontmatter table is a Claude Code extension, and including one makes packaging or upload fail with a hard error rather than a warning.

Where two of these genuinely overlap

The decision table covers the clean cases. These are the ones where two mechanisms really do both work, and pretending otherwise is how you end up with a bad answer.

A skill that shells out vs an MCP server

You want Claude to query your Postgres. You could write an MCP server, or you could write a skill that says "use psql, here is the connection string variable, here are the three tables you'll actually need". The skill is legitimate and it is cheaper: no process to run, no schema to maintain, and it works today if psql and the credentials are already in the environment. It stops being legitimate the moment you want typed results instead of parsed text, pagination, OAuth rather than an env var, or an install path a non-developer can follow. The tiebreaker is who holds the credential and who parses the result — not context cost, which tool search has taken off the table.

A skill vs a subagent — the docs call them the same system

This overlap is real and it is bidirectional. A skill can set context: fork and agent: Explore, which runs the skill body as a forked subagent's prompt in an isolated context. A subagent can list skills: in its frontmatter, which injects the full skill content into its context at startup rather than just the description. The reference is explicit that these are "the same underlying system", inverted. So choose by ownership: if the procedure is the point and you want it available to whatever agent is running, write a skill. If the worker is the point — its tools, its model, its permission mode — write a subagent and hang skills off it.

A skill vs a line in CLAUDE.md

The docs give a good trigger for this one: write a skill "when a section of CLAUDE.md has grown into a procedure rather than a fact". CLAUDE.md is always in context, so every line you add is rent you pay on every turn; a skill's body costs nothing until it is used. Facts about the repo — the package manager, the test command, the branch convention — stay in CLAUDE.md. Multi-step procedures move to a skill. If you're also deciding what belongs in the cross-tool file instead, we compare them in CLAUDE.md vs AGENTS.md.

A bare skill vs a plugin holding one skill

Genuinely a coin flip until one of three things is true: you need a version other people can pin to, you need a hook or an MCP server travelling with the prose, or you need it installable rather than copy-pasteable. Any of those, make it a plugin and accept the /my-plugin:name prefix. None of them, leave it in .claude/skills/ and keep the short name.

Frequently asked questions

Should this be a skill or an MCP server?

A skill is prose: it changes how Claude behaves using tools it already has. An MCP server is a process: it gives Claude a tool it did not have, with its own credentials, its own wire protocol and typed results. If the capability needs auth, pagination, or code running outside Claude's tool set, it is an MCP server. If it needs Claude to follow your procedure with the Bash, Read and Edit tools it already has, it is a skill. The old tiebreaker — "MCP servers cost context, skills do not" — no longer holds: MCP tool search is on by default and tool schemas are deferred until Claude searches for them.

What is the difference between a skill and a plugin?

They are not alternatives. A plugin is a package that can contain skills, subagents, hooks, MCP servers, LSP servers and executables in one versioned, namespaced unit. Skills are one of the things a plugin ships. You write a skill; you distribute it in a plugin. Use a bare skill in .claude/skills/ for personal or single-project work, and a plugin the moment you need version pinning, a marketplace, or a hook and an MCP server travelling alongside the prose.

Are slash commands still separate from skills?

No. The skills reference states that custom commands have been merged into skills: a file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way. Existing .claude/commands/ files keep working, and if a skill and a command share a name, the skill wins. The folder form adds supporting files, frontmatter controlling who can invoke it, and automatic loading when it matches your request.

Where do skills live on disk?

Personal: ~/.claude/skills/<name>/SKILL.md, in every project. Project: <repo>/.claude/skills/<name>/SKILL.md. Plugin: <plugin>/skills/<name>/SKILL.md, namespaced as /plugin-name:skill-name. On a clash, enterprise overrides personal and personal overrides project — the opposite direction from subagents, where the project definition wins over the personal one.

What is actually in the plugin marketplace?

Vendor integrations, overwhelmingly. claude plugin list --available --json returned 278 plugins, every one from claude-plugins-official: Airtable, AlloyDB, Adobe, Aikido, Amplitude, Asana, Auth0, Box, Canva, ClickHouse. It is a connector directory, not a library of craft skills. Anthropic also runs a reviewed community marketplace, claude-community, which you add yourself from anthropics/claude-plugins-community.

Where Backgrind fits

Backgrind doesn't extend Claude Code — it runs your real CLI in an always-on-top overlay with a tab per session, and pings you only when one of them needs a decision. The one place it touches this topic: its skills browser reads what you actually have installed, across both ecosystems at once. Global and project skills, legacy .claude/commands/ files, and the entries that are really symlinks into ~/.agents/skills/ — flagged as links, so removing one takes the link and never the shared target — plus your installed plugins and the marketplace catalogue behind them. After reading this far you know how many places that inventory is scattered across. Seeing it in one list is the point. Watch the loop in the live demo.

Verified August 2026 against Claude Code 2.1.221 and the current reference pages: skills (the commands-merged-into-skills note, the frontmatter table, scope precedence, the listing budget and the 1,536-character cap, symlink support, context: fork), plugins (component directories, the .claude-plugin/ warning, standalone-vs-plugin guidance, claude plugin init, both public marketplaces), subagents (scope priority, required name and description, the frontmatter fields, skills: preloading, isolation: worktree) and MCP (the three scopes, transports, plugin tool naming, tool search on by default). Plugin counts and category breakdown from claude plugin list --available --json and the official marketplace manifest; the symlink listing from ls -l ~/.claude/skills/ on the author's machine. Second-ecosystem details from vercel-labs/skills and skills.sh. This surface moves fast — the commands-into-skills merge and tool-search-by-default are both recent, and several frontmatter fields carry explicit minimum versions. Check the reference before you build on a specific field.