**Skill**: plugin-best-practices
This skill inherits all available tools. When active, it can use any tool Claude has access to.
Skill: plugin-best-practices Version: 1.0.0 Last Updated: 2025-11-16 Derived From: Real-world debugging of plugin loading failures
Comprehensive knowledge base of Claude Code plugin development patterns, validation rules, and common pitfalls learned from actual plugin system internals.
✅ CORRECT:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "What the plugin does",
"author": {
"name": "Your Name",
"email": "you@example.com"
},
"keywords": ["tag1", "tag2"]
}
❌ WRONG (causes validation error):
{
"name": "my-plugin",
"version": "1.0.0",
"commands": "./commands", // ❌ REMOVE THIS
"agents": "./agents", // ❌ REMOVE THIS
"skills": "./skills", // ❌ REMOVE THIS
"hooks": "./hooks/hooks.json" // ❌ REMOVE THIS
}
Why: Claude Code uses auto-discovery for components. Manual paths cause validation errors: "agents: Invalid input: must end with .md"
Error in Debug Logs:
[ERROR] Plugin not available for MCP: my-plugin
[DEBUG] Validation errors: agents: Invalid input: must end with ".md"
Claude Code automatically finds:
commands/*.mdagents/*.mdskills/*/SKILL.mdhooks.json (if needed)Directory Structure:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Metadata only
├── commands/ # Auto-discovered
│ ├── hello.md
│ └── task.md
├── agents/ # Auto-discovered
│ └── helper.md
└── skills/ # Auto-discovered
└── my-skill/
└── SKILL.md
✅ CORRECT (appears in plugin manager):
{
"moodle-plugins-marketplace": {
"source": {
"source": "github",
"repo": "owner/repo-name"
},
"installLocation": "...",
"lastUpdated": "2025-11-16T15:26:44.679Z"
}
}
❌ WRONG (marketplace invisible):
{
"moodle-plugins-marketplace": {
"source": {
"source": "git",
"url": "https://github.com/owner/repo-name.git"
}
}
}
Why: Claude Code UI only recognizes "github" source type, not "git" URL format.
✅ CORRECT:
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "my-marketplace",
"version": "1.0.0",
"description": "Marketplace description",
"owner": {
"name": "Your Name",
"email": "you@example.com"
},
"plugins": [...]
}
❌ WRONG (marketplace won't load):
{
"name": "my-marketplace",
"owner": {
"name": "Your Name"
},
"plugins": [...]
}
Missing:
$schema - JSON schema referenceversion - Marketplace versiondescription - What marketplace providesowner.email - Contact emailPlugins must exist in ~/.claude/plugins/installed_plugins.json:
{
"version": 1,
"plugins": {
"my-plugin@my-marketplace": {
"version": "1.0.0",
"installedAt": "2025-11-16T15:14:37.313Z",
"lastUpdated": "2025-11-16T15:14:37.313Z",
"installPath": "/path/to/plugin",
"gitCommitSha": "abc123...",
"isLocal": true
}
}
}
Without registration: Plugin exists but is invisible to UI
Frontmatter:
---
name: my-command
description: "What this command does"
category: productivity
---
Sections:
Example:
---
name: hello
description: "Greet the user"
---
# /hello - Greeting Command
Provides personalized greeting.
## Usage
/hello [name]
## Examples
/hello Alice → Hello, Alice!
/hello → Hello there!
Format:
# Agent Name
**Role**: Brief role description
**Expertise**:
- Area 1
- Area 2
- Area 3
## When to Use This Agent
- Scenario 1
- Scenario 2
## Agent Capabilities
### Capability 1
Description and examples
### Capability 2
Description and examples
## Example Interactions
### Scenario A
**User**: Question
**Agent**: Response
## Key Principles
1. Principle 1
2. Principle 2
SKILL.md Format:
# Skill Title
**Skill**: skill-name
**Version**: 1.0.0
**Last Updated**: 2025-11-16
## Purpose
What knowledge this skill provides
## Core Concepts
### Concept 1
Details and examples
### Concept 2
Details and examples
## Best Practices
1. Practice 1
2. Practice 2
## Common Patterns
### Pattern 1
```code example```
### Pattern 2
```code example```
## Anti-Patterns
❌ What not to do
✅ What to do instead
## Reference
- External links
- Related documentation
Before publishing, verify:
.claude-plugin/plugin.json exists.md.mdSKILL.mdmarketplace.json has $schemamarketplace.json has versionmarketplace.json has descriptionowner.email presentinstalled_plugins.jsonknown_marketplaces.json/helpSymptom: Plugin doesn't load, debug logs show validation error
Cause: plugin.json contains "commands": "./commands"
Fix: Remove all component path specifications
Symptom: Marketplace not visible in plugin manager UI
Cause: Using "git" instead of "github" in known_marketplaces.json
Fix: Change to "github" format with "repo" field
Symptom: Marketplace installed but not showing
Cause: Missing $schema, version, or description in marketplace.json
Fix: Add all required fields to marketplace.json
Symptom: Plugin files exist but invisible
Cause: Missing entry in installed_plugins.json
Fix: Add plugin registration with proper metadata
Symptom: Plugin shows as outdated or has version mismatch
Cause: gitCommitSha in installed_plugins.json doesn't match actual commit
Fix: Update SHA to current commit hash
❌ Bad: 10MB reference file in plugin ✅ Good: Link to external documentation
❌ Bad: 50 commands in one plugin ✅ Good: Split into focused plugins
❌ Bad: Load all data at plugin init ✅ Good: Load on-demand when command invoked
my-plugin-namemoodle-dev-pro not dev-toolshelper, utils, toolkitcreate-task, list-itemshello not say-hello-to-usermy-command not my_commandvalidator, architectplugin-validator not helpermigration-validatordatabase-best-practicesplugin-architecture-patternscode-review-guidelines.env files with secretschmod 600 .env # Credentials read-only by owner
chmod 644 plugin.json # Config readable by all
chmod 755 scripts/ # Scripts executable
~/.claude/plugins/local/my-plugin/validate my-plugin
/debug-plugin my-plugin
v1.0.0When plugin doesn't load:
Check Debug Logs
tail -f ~/.claude/debug/latest
Run Validation
/validate my-plugin
Check Registration
cat ~/.claude/plugins/installed_plugins.json | grep my-plugin
Verify Structure
ls -la ~/.claude/plugins/marketplaces/my-marketplace/my-plugin/
Fix and Restart
plugin.jsongitCommitSha in installed_plugins.jsonGolden Rules:
When in Doubt:
/validate/debug-plugin for diagnosisRemember: These rules come from real debugging experience. Following them prevents the most common plugin loading failures.