Skip to content

Commit db83359

Browse files
ivan-magdaclaude
andcommitted
docs: improve plugin-authoring skill with testing methodology and anti-patterns
Add testing methodology and compliance patterns inspired by writing-skills: - Add testing-plugin-authoring.md with scenarios, pressure tests, and meta-testing methodology for validating skill effectiveness - Add best-practices/common-mistakes.md with comprehensive anti-patterns, explanations, and prevention checklist - Update SKILL.md with: - Improved description with explicit trigger conditions - Red Flags section for common mistake prevention - Why Validation Matters table with consequences - Links to new supporting files - Cross-reference to official Anthropic docs 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 244d82e commit db83359

3 files changed

Lines changed: 534 additions & 1 deletion

File tree

plugins/plugin-development/skills/plugin-authoring/SKILL.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
---
22
name: plugin-authoring
3-
description: Expert guidance for Claude Code plugin development. Use when creating or modifying plugins, working with plugin.json or marketplace.json, or adding commands, agents, Skills, or hooks.
3+
description: Use when creating, modifying, or debugging Claude Code plugins. Triggers on .claude-plugin/, plugin.json, marketplace.json, commands/, agents/, skills/, hooks/ directories. Provides schemas, templates, validation workflows, and troubleshooting.
44
allowed-tools: Read, Grep, Glob
55
---
66

77
# Plugin Authoring (Skill)
88

99
You are the canonical guide for Claude Code plugin development. Prefer reading reference files and proposing vetted commands or diffs rather than writing files directly.
1010

11+
**Official documentation**: For Anthropic's official skill authoring best practices, see https://docs.anthropic.com/en/docs/agents-and-tools/agent-skills/skill-authoring-best-practices
12+
1113
## Triggers & Scope
1214

1315
Activate whenever context includes `.claude-plugin/`, `plugin.json`, `marketplace.json`, `commands/`, `agents/`, `skills/`, or `hooks/`.
@@ -26,6 +28,8 @@ Activate whenever context includes `.claude-plugin/`, `plugin.json`, `marketplac
2628
- **Templates**: [templates/](templates/)
2729
- **Examples**: [examples/](examples/)
2830
- **Best practices**: [best-practices/](best-practices/)
31+
- **Common mistakes**: [best-practices/common-mistakes.md](best-practices/common-mistakes.md)
32+
- **Testing this skill**: [testing-plugin-authoring.md](testing-plugin-authoring.md)
2933

3034
## Checklists
3135

@@ -58,6 +62,30 @@ Activate whenever context includes `.claude-plugin/`, `plugin.json`, `marketplac
5862
□ README.md exists with usage examples
5963
```
6064

65+
## Red Flags (STOP If You're About To...)
66+
67+
- Put `commands/`, `agents/`, `skills/`, or `hooks/` inside `.claude-plugin/`**WRONG LOCATION** (components go at plugin root)
68+
- Add `"commands": "./commands/"` to plugin.json → **UNNECESSARY** (standard directories auto-discovered, this breaks things)
69+
- Use relative paths like `./scripts/format.sh` in hooks → **USE** `${CLAUDE_PLUGIN_ROOT}/scripts/format.sh`
70+
- Skip `/plugin-development:validate` before testing → **ALWAYS VALIDATE FIRST**
71+
- Forget `chmod +x` on hook scripts → **Scripts won't execute (silent failure)**
72+
- Use 'claude' or 'anthropic' in skill names → **RESERVED WORDS (will be rejected)**
73+
74+
**All of these cause silent failures. When in doubt, validate.**
75+
76+
For detailed explanations: [best-practices/common-mistakes.md](best-practices/common-mistakes.md)
77+
78+
## Why Validation Matters
79+
80+
| Skip This | What Happens |
81+
|-----------|--------------|
82+
| Validate manifest | Plugin won't load, no error message |
83+
| chmod +x scripts | Hooks silently fail |
84+
| ${CLAUDE_PLUGIN_ROOT} | Works in dev, breaks on install |
85+
| Standard directory rules | Components not discovered |
86+
87+
**Running `/plugin-development:validate` catches 90% of issues before debugging starts.**
88+
6189
## Playbooks
6290

6391
- **Scaffold**`/plugin-development:init <name>` then fill templates
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
# Common Plugin Mistakes
2+
3+
Avoid these patterns that cause silent failures.
4+
5+
## Directory Structure
6+
7+
### Components Inside .claude-plugin/
8+
9+
```
10+
my-plugin/
11+
├── .claude-plugin/
12+
│ ├── plugin.json
13+
│ ├── commands/ # WRONG!
14+
│ └── agents/ # WRONG!
15+
```
16+
17+
**Why it fails**: Claude Code only looks for `plugin.json` inside `.claude-plugin/`. Components are discovered at plugin root, not inside the manifest directory.
18+
19+
**Fix**:
20+
```
21+
my-plugin/
22+
├── .claude-plugin/
23+
│ └── plugin.json # Only this file here
24+
├── commands/ # At root
25+
├── agents/ # At root
26+
└── skills/ # At root
27+
```
28+
29+
---
30+
31+
## plugin.json Configuration
32+
33+
### Specifying Standard Paths
34+
35+
```json
36+
{
37+
"name": "my-plugin",
38+
"commands": "./commands/",
39+
"agents": "./agents/"
40+
}
41+
```
42+
43+
**Why it fails**: When you specify component paths, you're telling Claude Code to use ONLY those paths. Standard directories (`commands/`, `agents/`, `skills/`, `hooks/`) are auto-discovered—explicitly specifying them can interfere with discovery.
44+
45+
**Fix**:
46+
```json
47+
{
48+
"name": "my-plugin"
49+
}
50+
```
51+
52+
Only add component fields for **non-standard** locations like `./custom-commands/`.
53+
54+
### Absolute Paths
55+
56+
```json
57+
{
58+
"commands": "/Users/you/plugins/my-plugin/commands/"
59+
}
60+
```
61+
62+
**Why it fails**: Absolute paths break when plugin is installed on another machine or in a different location.
63+
64+
**Fix**: Always use relative paths starting with `./`:
65+
```json
66+
{
67+
"commands": ["./custom/cmd.md"]
68+
}
69+
```
70+
71+
---
72+
73+
## Hook Scripts
74+
75+
### Relative Paths in Hook Commands
76+
77+
```json
78+
{
79+
"command": "./scripts/format.sh"
80+
}
81+
```
82+
83+
**Why it fails**: Relative paths resolve from where Claude Code runs (the project directory), not from the plugin location. Works during development in the plugin directory, breaks completely when plugin is installed elsewhere.
84+
85+
**Fix**: Always use `${CLAUDE_PLUGIN_ROOT}`:
86+
```json
87+
{
88+
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
89+
}
90+
```
91+
92+
### Non-Executable Scripts
93+
94+
```bash
95+
# Created script but forgot: chmod +x scripts/format.sh
96+
```
97+
98+
**Why it fails**: Hook silently fails with no error message. You'll spend hours debugging why the hook "isn't running."
99+
100+
**Fix**: Always make scripts executable:
101+
```bash
102+
chmod +x scripts/*.sh
103+
```
104+
105+
### Missing Timeout on Slow Operations
106+
107+
```json
108+
{
109+
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/lint.sh"
110+
// No timeout specified
111+
}
112+
```
113+
114+
**Why it fails**: Default timeout is 60 seconds. If your script takes longer, it's killed silently.
115+
116+
**Fix**: Set appropriate timeout:
117+
```json
118+
{
119+
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/lint.sh",
120+
"timeout": 120
121+
}
122+
```
123+
124+
### Wrong Matcher Syntax
125+
126+
```json
127+
{
128+
"PreToolUse": [
129+
{
130+
"matcher": "write", // Wrong case!
131+
"hooks": [...]
132+
}
133+
]
134+
}
135+
```
136+
137+
**Why it fails**: Matchers are case-sensitive. `"write"` won't match the `Write` tool.
138+
139+
**Fix**: Use exact tool names:
140+
```json
141+
{
142+
"matcher": "Write|Edit"
143+
}
144+
```
145+
146+
---
147+
148+
## Skill Configuration
149+
150+
### Name Doesn't Match Directory
151+
152+
```
153+
skills/my-skill/SKILL.md
154+
---
155+
name: MySkill # Doesn't match directory!
156+
---
157+
```
158+
159+
**Why it fails**: Discovery uses directory name. Mismatched names cause confusion and potential discovery issues.
160+
161+
**Fix**: Name must match directory in kebab-case:
162+
```
163+
skills/my-skill/SKILL.md
164+
---
165+
name: my-skill # Matches directory
166+
---
167+
```
168+
169+
### Reserved Words in Skill Name
170+
171+
```yaml
172+
name: claude-helper # Contains 'claude'!
173+
name: anthropic-tools # Contains 'anthropic'!
174+
```
175+
176+
**Why it fails**: Names containing 'claude' or 'anthropic' are reserved and will be rejected.
177+
178+
**Fix**: Use different naming:
179+
```yaml
180+
name: assistant-helper
181+
name: ai-tools
182+
```
183+
184+
### Description Missing "When to Use"
185+
186+
```yaml
187+
description: Helps with code review
188+
```
189+
190+
**Why it fails**: Claude uses descriptions to decide when to activate skills. Without trigger conditions, skill may not activate when needed.
191+
192+
**Fix**: Include both what AND when:
193+
```yaml
194+
description: Provides code review guidance. Use when reviewing PRs, examining code quality, or preparing code for review.
195+
```
196+
197+
### Skill Over 500 Lines
198+
199+
```markdown
200+
# SKILL.md (2000 lines of content)
201+
Everything inline...
202+
```
203+
204+
**Why it fails**: Large skills consume excessive context tokens and may not be fully processed.
205+
206+
**Fix**: Use progressive disclosure:
207+
```markdown
208+
# SKILL.md (~300 lines)
209+
## Quick Links
210+
- [Detailed API Reference](./reference.md)
211+
- [Examples](./examples.md)
212+
```
213+
214+
---
215+
216+
## Marketplace Configuration
217+
218+
### Plugin Name Mismatch
219+
220+
```json
221+
// marketplace.json
222+
{
223+
"plugins": [
224+
{
225+
"name": "my-plugin",
226+
"source": "./plugins/other-name" // Directory doesn't match!
227+
}
228+
]
229+
}
230+
231+
// plugins/other-name/.claude-plugin/plugin.json
232+
{
233+
"name": "other-name" // Doesn't match marketplace entry!
234+
}
235+
```
236+
237+
**Why it fails**: The `name` in marketplace.json must match the `name` in the plugin's plugin.json.
238+
239+
**Fix**: Ensure names match:
240+
```json
241+
// Both must use "my-plugin"
242+
```
243+
244+
### Absolute Source Paths
245+
246+
```json
247+
{
248+
"source": "/Users/you/dev/plugins/my-plugin"
249+
}
250+
```
251+
252+
**Why it fails**: Breaks for anyone else using the marketplace.
253+
254+
**Fix**: Use relative paths:
255+
```json
256+
{
257+
"source": "./plugins/my-plugin"
258+
}
259+
```
260+
261+
---
262+
263+
## Validation Skipping
264+
265+
### Testing Without Validation
266+
267+
```bash
268+
# Skip validation, jump straight to testing
269+
/plugin install my-plugin@dev-marketplace
270+
# Wonder why nothing works...
271+
```
272+
273+
**Why it fails**: Many issues are silent. Plugin loads but components don't work. Hours wasted debugging.
274+
275+
**Fix**: ALWAYS validate first:
276+
```bash
277+
/plugin-development:validate
278+
# Fix any issues BEFORE testing
279+
/plugin install my-plugin@dev-marketplace
280+
```
281+
282+
---
283+
284+
## Prevention Checklist
285+
286+
Before testing any plugin:
287+
288+
```
289+
□ Components at plugin root (not inside .claude-plugin/)
290+
□ No component fields in plugin.json for standard directories
291+
□ Hooks use ${CLAUDE_PLUGIN_ROOT} for all paths
292+
□ Scripts are executable (chmod +x)
293+
□ Skill names match directory names (kebab-case)
294+
□ Skill names don't contain 'claude' or 'anthropic'
295+
□ Skill descriptions include when to use
296+
□ Marketplace plugin names match plugin.json names
297+
□ All paths are relative (start with ./)
298+
□ /plugin-development:validate passes
299+
```
300+
301+
## Quick Diagnostic
302+
303+
| Symptom | Likely Cause | Check |
304+
|---------|--------------|-------|
305+
| Plugin doesn't load | plugin.json location or syntax | `.claude-plugin/plugin.json` exists? Valid JSON? |
306+
| Commands don't appear | Wrong directory or missing frontmatter | `commands/*.md` at root? Has `description` frontmatter? |
307+
| Hooks don't run | Path or permission issue | Using `${CLAUDE_PLUGIN_ROOT}`? Scripts executable? |
308+
| Skill doesn't trigger | Description missing triggers | Includes "when to use"? |
309+
| Marketplace install fails | Name mismatch | Names identical in marketplace.json and plugin.json? |

0 commit comments

Comments
 (0)