When I evaluate Claude skills versus plugins, I start with the job I want Claude to repeat. If the job is mostly about following my method, I reach for a skill. If the job needs connected tools, commands, and a setup I want others to install, I reach for a plugin.
My default is to start smaller. I write a skill first when I am still proving the workflow. I turn it into a plugin when the workflow needs to travel across people, tools, and teams.
When I use a skill
I use a skill when I want Claude to follow a specific operating procedure without teaching it again every time.
I use skills for review checklists, incident writeups, release rubrics, and team specific document style. Claude's docs describe skills as directories with instructions, scripts, and resources that load dynamically when relevant.
incident-review-skill/
SKILL.md
templates/incident-summary.md
scripts/check-severity.py
This layout is the small version I would start with. It works when I can give Claude one exported incident file and I only need a repeatable review method.
incident-review-skill/SKILL.md
---
name: incident-review
description: Review an incident JSON file and produce a customer first summary.
argument-hint: "[incident-json-file]"
allowed-tools: Bash(python3 *)
---
Review $ARGUMENTS.
1. Read the incident input file.
2. Run the severity check:
!`python3 "${CLAUDE_SKILL_DIR}/scripts/check-severity.py" "$ARGUMENTS"`
3. Use [templates/incident-summary.md](templates/incident-summary.md).
4. Stop if customer impact, severity, owner, or next action is missing.
This file is the playbook. It runs the bundled Python check before the summary, so a clean looking review cannot hide missing ownership.
incident-review-skill/templates/incident-summary.md
# Incident summary
- Customer impact:
- Timeline:
- Root cause:
- Detection gap:
- Corrective actions:
- Owner:
- Follow up date:
The template keeps reviews from drifting. I want customer impact, detection gaps, and owners in every incident summary.
incident-review-skill/scripts/check-severity.py
#!/usr/bin/env python3
import json
import sys
from pathlib import Path
incident = json.loads(Path(sys.argv[1]).read_text())
missing = [k for k in ("severity", "customer_minutes", "owner", "next_action") if not incident.get(k)]
if missing:
raise SystemExit("fail: missing " + ", ".join(missing))
customer_minutes = int(incident["customer_minutes"])
severity = incident["severity"].lower()
if customer_minutes >= 30 and severity not in {"sev1", "sev2"}:
raise SystemExit(f"fail: {customer_minutes} customer minutes needs sev1/sev2 review")
print("pass")
The script fails fast when impact and severity disagree. That is the guardrail I want before Claude writes anything final.
When I use a plugin
I use a plugin when the workflow is bigger than instructions.
For the same incident assistant, a plugin makes sense when Claude needs to pull alerts, read tickets, create follow up work, and expose /incident-review:incident-review. Anthropic's plugin docs describe plugins as packages that can bundle skills, MCP connectors, slash commands, and sub-agents.
incident-review-plugin/
.claude-plugin/plugin.json
skills/incident-review/SKILL.md
commands/incident-review.md
connectors/pager-duty.mcp.json
connectors/jira.mcp.json
This is the first correction I would make to the folder you named: plugin.json belongs inside .claude-plugin/. The skills, commands, and connector files stay at the plugin root level.
incident-review-plugin/.claude-plugin/plugin.json
{
"name": "incident-review",
"displayName": "Incident Review",
"description": "Review production incidents with PagerDuty and Jira evidence.",
"version": "0.1.0",
"author": {
"name": "Platform Engineering"
},
"skills": "./skills/",
"commands": ["./commands/incident-review.md"],
"mcpServers": [
"./connectors/pager-duty.mcp.json",
"./connectors/jira.mcp.json"
],
"defaultEnabled": false
}
The manifest gives the plugin its identity and points Claude Code to the connector files. I set defaultEnabled to false because incident tools should be opt in.
incident-review-plugin/skills/incident-review/SKILL.md
---
description: Review PagerDuty and Jira evidence for a production incident.
argument-hint: "[pager-duty-incident-id]"
---
Use incident id $ARGUMENTS.
1. Get incident status, title, timestamps, responders, and services.
2. Get linked Jira tickets and open corrective actions.
3. Separate confirmed facts from assumptions.
4. Call out missing customer impact, owner, or due date.
5. Return a short summary, action list, and unresolved evidence list.
The plugin skill is still the method. It expects evidence from approved tools instead of screenshots and partial notes.
incident-review-plugin/commands/incident-review.md
---
description: Start a guided incident review from an incident id.
argument-hint: "[pager-duty-incident-id]"
disable-model-invocation: true
---
Start an incident review for $ARGUMENTS.
Use the incident-review skill. Pull PagerDuty and Jira evidence through the configured MCP servers. If the tools are unavailable, ask for an exported timeline file instead of guessing.
The command is the human entry point. I keep it thin so the skill owns the review method.
incident-review-plugin/connectors/pager-duty.mcp.json
{
"mcpServers": {
"pager-duty": {
"command": "npx",
"args": ["-y", "@company/pager-duty-mcp-server"],
"env": {
"PAGERDUTY_API_TOKEN": "${PAGERDUTY_API_TOKEN}"
}
}
}
}
This connector uses an environment variable. I would never hard code an incident tool token in a plugin package.
incident-review-plugin/connectors/jira.mcp.json
{
"mcpServers": {
"jira": {
"command": "npx",
"args": ["-y", "@company/jira-mcp-server"],
"env": {
"JIRA_BASE_URL": "${JIRA_BASE_URL}",
"JIRA_API_TOKEN": "${JIRA_API_TOKEN}"
}
}
}
}
The Jira connector follows the same pattern. The package names are placeholders for company approved MCP servers.
How I would roll it out
My test is simple: can this work from a file alone, or does it need live systems?
If an engineer drops an incident timeline into Claude, a skill is enough. If an SRE wants Claude to gather alerts, tickets, logs, and chat, I would use a plugin backed by MCP connectors. I would prove the skill with three past incidents before packaging the plugin.
My decision rule
I try not to overbuild the first version.
Use a skill for procedural knowledge. Use a plugin for a complete installed capability. Use MCP for live access. Use both when Claude needs the access and the playbook.
If I cannot explain the workflow as a skill first, I probably do not understand it well enough to package it as a plugin.