16 KiB
Plugin Development Best Practices
Comprehensive guide to creating high-quality, maintainable Claude Code plugins.
Development Workflow
Starting a New Plugin
Step 1: Plan Your Plugin
- Define clear purpose and scope
- Decide what components you need
- Choose appropriate plugin pattern
- Identify target users and use cases
Step 2: Create Basic Structure
mkdir my-plugin
mkdir my-plugin/.claude-plugin
Step 3: Create Minimal Manifest Start with only required fields:
{
"name": "my-plugin",
"version": "0.1.0"
}
Step 4: Add First Component Start with one component type, test it, then add more.
Step 5: Test Locally
/plugin install /path/to/my-plugin
Step 6: Iterate
- Test each component
- Refine based on usage
- Add documentation
- Increment version
Local Development Setup
Option 1: Standalone Plugin Directory
mkdir ~/my-plugins
cd ~/my-plugins
mkdir my-plugin
# Develop plugin
/plugin install ~/my-plugins/my-plugin
Option 2: Personal Marketplace
mkdir ~/my-marketplace
cd ~/my-marketplace
mkdir .claude-plugin
# Create marketplace.json
mkdir my-plugin
# Develop plugin
/plugin marketplace add ~/my-marketplace
/plugin install my-plugin@my-marketplace
Recommended: Use personal marketplace for managing multiple plugins.
Iterative Development
- Make changes to plugin files
- Update the plugin using one of these methods:
- Easiest: Run
/pluginand select the plugin to update (Claude Code will reload it) - Manual:
/plugin uninstall my-plugin@marketplace-namethen/plugin install my-plugin@marketplace-name
- Easiest: Run
- Restart Claude Code if prompted to apply changes
- Test the changes
- Repeat until satisfied
Tips:
- The
/pluginmenu command is the easiest way to update during development - Restart Claude Code to reload all plugins without manual uninstall/reinstall
- For marketplaces, changes are picked up when reinstalling from the marketplace
Versioning
Semantic Versioning
Follow semantic versioning strictly: MAJOR.MINOR.PATCH
MAJOR version (e.g., 1.0.0 → 2.0.0)
- Breaking changes to existing functionality
- Removing components
- Changing component behavior in incompatible ways
- Renaming plugin
MINOR version (e.g., 1.0.0 → 1.1.0)
- New features added
- New components added
- Backward-compatible enhancements
- New optional parameters
PATCH version (e.g., 1.0.0 → 1.0.1)
- Bug fixes
- Documentation updates
- Performance improvements
- No functionality changes
Version Examples
Breaking change (MAJOR):
// Version 1.0.0
{
"name": "data-processor",
"version": "1.0.0",
"skills": ["./skills"]
}
// Version 2.0.0 - Removed commands, renamed skills directory
{
"name": "data-processor",
"version": "2.0.0",
"skills": ["./processors"]
}
New feature (MINOR):
// Version 1.0.0
{
"name": "toolkit",
"version": "1.0.0",
"skills": ["./skills"]
}
// Version 1.1.0 - Added commands
{
"name": "toolkit",
"version": "1.1.0",
"skills": ["./skills"],
"commands": ["./commands"]
}
Bug fix (PATCH):
// Version 1.0.0 - Has a bug in skill logic
{
"name": "analyzer",
"version": "1.0.0",
"skills": ["./skills"]
}
// Version 1.0.1 - Fixed skill logic, no API changes
{
"name": "analyzer",
"version": "1.0.1",
"skills": ["./skills"]
}
Pre-release Versions
For development and testing:
{
"version": "0.1.0" // Initial development
}
{
"version": "0.9.0" // Feature complete, testing
}
{
"version": "1.0.0" // Stable release
}
Convention:
0.x.x= Under development, breaking changes allowed1.0.0= First stable release1.x.x+= Maintain backward compatibility
Naming Conventions
Plugin Names
Format: kebab-case
Good names:
git-workflow- Descriptive, clear purposedata-analyzer- Indicates functionalityreact-toolkit- Shows what it helps withsecurity-scanner- Obvious use case
Bad names:
helpers- Too vagueutils- Doesn't indicate purposemy_plugin- Wrong case (use kebab-case)MyPlugin- Wrong case (use kebab-case)stuff- Not descriptive
Guidelines:
- Use 2-3 words typically
- Be specific about functionality
- Avoid generic terms (utils, helpers, tools)
- Make it discoverable by name alone
Component Names
Commands: Action verbs
deploy-app.mdrun-tests.mdgenerate-report.md
Skills: Gerund form (verb + -ing)
processing-data/analyzing-code/generating-reports/
Agents: Role-based
code-reviewer.mdsecurity-auditor.mdtest-generator.md
Documentation
Plugin Description
Write descriptions that:
- Clearly state purpose
- Include key terms for discoverability
- Are concise (1-2 sentences)
- Help users understand when to use it
Good examples:
{
"description": "Tools for processing and analyzing CSV and JSON data files with validation and transformation capabilities"
}
{
"description": "Git workflow automation including branch management, PR creation, and commit formatting"
}
Bad examples:
{
"description": "Helpful stuff" // Too vague
}
{
"description": "This plugin provides various utilities and tools that can help you with different tasks in your workflow and make things easier when working with data and files" // Too verbose
}
Keywords
Choose keywords that:
- Describe functionality
- Match user search terms
- Are specific and relevant
- Help with discovery
Example:
{
"name": "react-toolkit",
"keywords": ["react", "components", "typescript", "testing", "hooks"]
}
Guidelines:
- Include 3-7 keywords
- Use specific terms, not generic ones
- Think about how users would search
- Include technology names when relevant
README Files
Include README.md for complex plugins:
Essential sections:
- Overview: What does the plugin do?
- Installation: How to install it
- Components: What's included
- Usage: How to use each component
- Examples: Real-world usage examples
- Requirements: Any dependencies or prerequisites
- License: Licensing information
CRITICAL: Keep README synchronized with plugin contents
When adding or removing components (especially skills), ALWAYS update the README to reflect the changes:
- Adding a skill: Add it to the Components section with a brief description
- Removing a skill: Remove it from the Components section
- Updating a skill: Update its description if purpose changed
- Adding commands/agents: Document them in the appropriate sections
This is easy to forget but critical for discoverability. Users read the README to understand what the plugin offers.
Example README structure:
# My Plugin
Brief description of what the plugin does.
## Installation
```bash
/plugin marketplace add <marketplace-url>
/plugin install my-plugin@marketplace-name
Components
Skills
- Processing Data: Handles CSV and JSON files
- Validating Input: Validates data against schemas
Commands
/process-data: Process data files/validate-schema: Validate data schema
Usage Examples
Processing CSV Files
...
Requirements
- Node.js 18+
- Python 3.9+ (for validation scripts)
License
MIT
## Testing
### Local Testing Workflow
**1. Installation Test**
```bash
# Install plugin
/plugin install /path/to/my-plugin
# Verify installation
/plugin
# Check for errors
claude --debug
2. Component Testing
# Verify commands appear
/help
# Test slash command
/my-command
# Test skill (use it in conversation)
# Skills are auto-discovered and invoked
# Verify agents registered
# Agents appear in specialized workflows
3. Path Testing
- Verify all component paths are relative
- Check paths start with
./ - Ensure directories/files exist
- Test that components load correctly
4. Manifest Validation
# Validate JSON syntax
cat .claude-plugin/plugin.json | python -m json.tool
# Check required fields
# - name (present and kebab-case)
# - version (semantic versioning format)
5. Clean Environment Testing Before sharing:
- Uninstall plugin
- Restart Claude Code
- Reinstall and test fresh
Testing Checklist
Before releasing:
- Plugin installs without errors
- All components load correctly
- Commands appear in
/help - Skills are discoverable
- Agents work as expected
- Hooks trigger correctly
- No errors in
claude --debug - Documentation is accurate
- Version number is correct
- Tested in clean environment
Code Quality
Manifest Quality
Required fields present:
{
"name": "my-plugin", // ✓ Required
"version": "1.0.0" // ✓ Required
}
Metadata complete:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "...", // ✓ Recommended
"author": {
"name": "..." // ✓ Recommended
},
"keywords": [...] // ✓ Recommended
}
Paths correct:
{
"skills": ["./skills"], // ✓ Relative path
"commands": ["./commands"], // ✓ Starts with ./
"hooks": "./hooks/hooks.json" // ✓ File reference
}
Component Quality
Skills:
- Have clear SKILL.md with frontmatter
- Include name and description in frontmatter
- Keep SKILL.md under 500 lines
- Use reference files for details
Commands:
- Have frontmatter with name and description
- Clear, concise command prompts
- Include usage examples
- Document parameters
Agents:
- Clear agent descriptions
- Specific capabilities listed
- Tool restrictions if needed
Hooks:
- Valid hooks.json format
- Scripts exist at specified paths
- Proper permissions on scripts
- Error handling in scripts
Error Handling
In scripts:
#!/bin/bash
set -e # Exit on error
# Validate inputs
if [ -z "$1" ]; then
echo "Error: Missing required parameter"
exit 1
fi
# Main logic here
In MCP servers:
try {
// Server logic
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}
Organization
Single Responsibility
Each plugin should have ONE clear purpose.
Good: Focused plugins
git-workflow- Git operations onlydata-analyzer- Data analysis onlyreact-toolkit- React development only
Bad: Catch-all plugins
my-utils- Vague, does everythinghelpers- No clear purposetools- Too generic
Component Organization
By functionality:
my-plugin/
├── skills/
│ ├── core-processing/ # Core functionality
│ ├── validation/ # Validation features
│ └── reporting/ # Reporting features
By category:
data-plugin/
├── skills/
│ ├── csv/ # CSV-specific
│ ├── json/ # JSON-specific
│ └── xml/ # XML-specific
Flat structure (simple plugins):
simple-plugin/
├── skills/
│ ├── skill-one/
│ └── skill-two/
File Organization
Supporting files:
my-plugin/
├── .claude-plugin/
│ └── plugin.json
├── skills/
│ └── my-skill/
│ ├── SKILL.md
│ ├── reference/ # Detailed docs
│ ├── templates/ # Templates
│ └── scripts/ # Helper scripts
├── scripts/ # Plugin-level scripts
├── docs/ # Additional documentation
├── tests/ # Test files (if applicable)
├── README.md
└── LICENSE
Distribution
Via Marketplace
Best for:
- Sharing with teams
- Publishing to community
- Managing multiple plugins
- Versioning and updates
Steps:
- Create/add to marketplace
- Add entry to marketplace.json
- Share marketplace URL
- Users add marketplace once
- Users install/update plugins easily
Example marketplace.json entry:
{
"plugins": [
{
"name": "my-plugin",
"source": "./my-plugin",
"description": "Plugin description"
}
]
}
Direct Installation
Best for:
- Quick testing
- Private plugins
- One-off sharing
Methods:
# Local path
/plugin install /path/to/plugin
# Git repository
/plugin install https://github.com/user/plugin
# GitHub shorthand
/plugin install github:user/plugin
Common Pitfalls
Absolute Paths
Problem:
{
"skills": "/Users/me/plugins/my-plugin/skills" // ✗ Absolute
}
Solution:
{
"skills": ["./skills"] // ✓ Relative
}
Missing Plugin Directory
Problem:
my-plugin/
└── plugin.json // ✗ Wrong location
Solution:
my-plugin/
└── .claude-plugin/
└── plugin.json // ✓ Correct location
Invalid Version Format
Problem:
{
"version": "1" // ✗ Invalid
}
{
"version": "v1.0.0" // ✗ Don't include 'v'
}
Solution:
{
"version": "1.0.0" // ✓ Semantic versioning
}
Overly Generic Names
Problem:
{
"name": "utils" // ✗ Too vague
}
Solution:
{
"name": "data-utils" // ✓ More specific
}
Missing Component Files
Problem:
{
"skills": ["./skills"]
}
// But no skills/ directory exists
Solution:
- Create directory before referencing
- Or remove reference from plugin.json
Wrong Component Format
Problem:
# My Skill
Content without frontmatter
Solution:
---
name: My Skill
description: Skill description
---
# My Skill
Content
Maintenance
Keeping Plugins Updated
Regular maintenance:
- Fix bugs promptly
- Update documentation
- Respond to user feedback
- Test with new Claude Code versions
Version updates:
- Follow semantic versioning
- Document changes in CHANGELOG.md
- Test before releasing
- Update marketplace.json
Deprecation Strategy
When removing features:
1. Announce deprecation (MINOR version)
{
"version": "1.5.0",
"description": "Note: feature X deprecated, will be removed in 2.0.0"
}
2. Remove feature (MAJOR version)
{
"version": "2.0.0",
"description": "Breaking: feature X removed"
}
3. Document migration in README
Backward Compatibility
Maintain in MINOR versions:
- Keep existing component paths
- Don't remove components
- Don't break existing functionality
- Add, don't replace
Break only in MAJOR versions:
- Remove components
- Change component behavior
- Rename paths
- Require new dependencies
Security Considerations
Script Safety
- Validate all inputs
- Use proper permissions
- Avoid executing untrusted code
- Document security requirements
Sensitive Data
- Don't hardcode credentials
- Use environment variables
- Document required secrets
- Provide examples, not real values
MCP Server Security
- Validate external inputs
- Use HTTPS for remote connections
- Handle errors gracefully
- Log security-relevant events
Summary
Key Best Practices:
- Plan before building - Clear purpose, right components
- Start minimal - plugin.json only, add as needed
- Use relative paths - Always start with
./ - Follow semantic versioning - MAJOR.MINOR.PATCH strictly
- Test thoroughly - Install, test, debug before sharing
- Document well - Clear descriptions, examples, README
- Organize logically - Single responsibility, clear structure
- Maintain actively - Fix bugs, respond to feedback
- Version carefully - Don't break backward compatibility
- Secure by default - Validate inputs, protect secrets
Follow these practices to create high-quality, maintainable plugins that users will trust and enjoy using.