- .wiki/concepts/skill-vs-plugin.md: when a bare SKILL.md suffices vs when
a plugin is required (slash commands, hooks, sub-agents, MCP via
marketplace). Concrete breakdown of `superpowers` showing why each of
its non-skill artifacts needs the plugin format.
- .wiki/index.md, log.md: linked / logged.
Backlog: project-bootstrap Step 4 has the same defect as the wiki step
(now fixed in 1cae0a2) — it creates a single flat STATUS.md and never
mentions the per-task files that task-status-wiki actually expects. Added
to .tasks/STATUS.md backlog for a conscious follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.8 KiB
title, type, updated
| title | type | updated |
|---|---|---|
| Skill vs Plugin | concept | 2026-04-28 |
Skill vs Plugin
When to ship a capability as a bare SKILL.md vs as a full Claude Code plugin.
What a plugin can ship
A plugin is a bundle. It can include any of:
| Component | Purpose | Loadable any other way? |
|---|---|---|
Skills (skills/<name>/SKILL.md) |
Behavioral guidance for Claude | Yes — copy to ~/.claude/skills/ |
Slash commands (commands/<name>.md) |
/foo invocations |
No — only via plugin manifest |
Hooks (hooks/) |
session-start, pre-tool-use, etc., executed by the harness |
No — must be in plugin |
Sub-agents (agents/<name>.md) |
Agent { subagent_type: "<name>" } |
No — only via plugin |
MCP servers (.mcp.json) |
Adds tools like mcp__context7__* |
Manual ~/.claude/settings.json, but loses versioning/marketplace ops |
| Output styles, statusline, etc. | Cosmetic / harness config | No |
| Versioning + release notes | /plugin update X flow |
No |
A bare SKILL.md is just one row in that table — the first one.
When the bare skill is enough
If the artifact is only SKILL.md files (with optional assets/, references/):
- A folder under
~/.claude/skills/<name>/works. - Distribute via
.skillarchive (zip) or copy the folder. - All 13 skills in this repo are bare skills. No plugin needed.
When you actually need a plugin
Any of:
- A slash command.
/brainstorm,/commit,/loop. Only path iscommands/<name>.mdin a plugin. - A hook. Auto-load behavior on session start / prompt submit / post-tool-use. Hooks fire from the harness, not from Claude. Plugin manifest is how the harness finds them.
- A sub-agent type. Plugin manifest is how
Agentdiscovers it. - MCP server registration. Yes, you can shove it into
~/.claude/settings.jsonmanually (we did this for context7 originally). But the official plugin gets you marketplace ops —/plugin install,/plugin update,/plugin uninstall— which manual JSON doesn't. - Versioning + marketplace path. Consumers can pull updates without chasing.
Real example: superpowers
The official superpowers plugin ships:
| Component | Count | Notes |
|---|---|---|
| Skills | 14 | Could live as bare skills |
| Slash commands | 3 | /brainstorm, /execute-plan, /write-plan — only via plugin |
| Hooks | 4 | Includes session-start |
| Sub-agents | 1 | code-reviewer |
The killer feature: the session-start hook auto-injects using-superpowers content at the top of every session. That's why we see superpowers:brainstorming, superpowers:writing-plans, etc. listed in available_skills from the very first message — without anyone saying "use superpowers". Bare-skill copies can't do that.
Decision flow
Want to ship a capability →
Only SKILL.md content? → bare skill (skills/<name>/, install via copy/zip)
Need /<command>? → plugin
Need a session-start (or other) hook? → plugin
Need a subagent_type? → plugin
MCP server with /plugin update? → plugin (see context7-setup.md)
What this means for this repo
All 13 of our skills are currently bare. None ships slash commands, hooks, or sub-agents — so no plugin format is needed today.
The moment to reconsider: if we want a /caveman slash command, or a session-start hook that auto-loads active-platform based on uname, or a sub-agent like a "skill-tester". At that point — wrap the relevant skills into a plugin and publish through a marketplace (own or claude-plugins-official if that channel becomes available).
See also
- context7-setup.md — concrete example of switching a manual MCP registration to a plugin (and the cost: re-injecting
--api-keyafter/plugin update).