Standard Directory Structure
Every Claude Code plugin follows this organizational pattern:Critical Rules
- Manifest location: The
plugin.jsonmanifest MUST be in.claude-plugin/directory - Component locations: All component directories MUST be at plugin root level
- Optional components: Only create directories for components the plugin actually uses
- Naming convention: Use kebab-case for all directory and file names
Plugin Manifest (plugin.json)
The manifest defines plugin metadata and configuration.Required Fields
- Use kebab-case format (lowercase with hyphens)
- Must be unique across installed plugins
- No spaces or special characters
- Examples:
code-review-assistant,test-runner,api-docs
Recommended Metadata
Custom Component Paths
Specify custom paths for components (supplements default directories):Custom paths supplement defaults—they don’t replace them. Components in both default directories and custom paths will load.
- Must be relative to plugin root
- Must start with
./ - Cannot use absolute paths
- Support arrays for multiple locations
Component Organization
Commands
Location:commands/ directory
Format: Markdown files with YAML frontmatter
Auto-discovery: All .md files in commands/ load automatically
Agents
Location:agents/ directory
Format: Markdown files with YAML frontmatter
Auto-discovery: All .md files in agents/ load automatically
Skills
Location:skills/ directory with subdirectories per skill
Format: Each skill in its own directory with SKILL.md file
Auto-discovery: All SKILL.md files in skill subdirectories load automatically
Hooks
Location:hooks/hooks.json or inline in plugin.json
Format: JSON configuration defining event handlers
MCP Servers
Location:.mcp.json at plugin root or inline in plugin.json
Format: JSON configuration for MCP server definitions
Portable Path References
$
Use${CLAUDE_PLUGIN_ROOT} environment variable for all intra-plugin path references:
- User installation method (marketplace, local, npm)
- Operating system conventions
- User preferences
- Hook command paths
- MCP server command arguments
- Script execution references
- Resource file paths
- Hardcoded absolute paths (
/Users/name/plugins/...) - Relative paths from working directory (
./scripts/...in commands) - Home directory shortcuts (
~/plugins/...)
Path Resolution
In manifest JSON fields:File Naming Conventions
Component Files
Commands: Use kebab-case.md files
code-review.md→/code-reviewrun-tests.md→/run-testsapi-docs.md→/api-docs
.md files describing role
test-generator.mdcode-reviewer.mdperformance-analyzer.md
api-testing/database-migrations/error-handling/
Supporting Files
Scripts: Use descriptive kebab-case names with appropriate extensionsvalidate-input.shgenerate-report.pyprocess-data.js
api-reference.mdmigration-guide.mdbest-practices.md
hooks.json.mcp.jsonplugin.json
Auto-Discovery Mechanism
Claude Code automatically discovers and loads components:
Discovery timing:
- Plugin installation: Components register with Claude Code
- Plugin enable: Components become available for use
- No restart required: Changes take effect on next Claude Code session
Common Patterns
Minimal Plugin
Single command with no dependencies:Full-Featured Plugin
Complete plugin with all component types:Skill-Focused Plugin
Plugin providing only skills:Best Practices
Logical Grouping
Group related components together in subdirectories
Minimal Manifest
Keep plugin.json lean, rely on auto-discovery
Consistent Naming
Use consistent naming across components
Portable Paths
Always use $ for paths
Troubleshooting
Component Not Loading
- Verify file is in correct directory with correct extension
- Check YAML frontmatter syntax (commands, agents, skills)
- Ensure skill has
SKILL.md(notREADME.mdor other name) - Confirm plugin is enabled in Claude Code settings
Path Resolution Errors
- Replace all hardcoded paths with
${CLAUDE_PLUGIN_ROOT} - Verify paths are relative and start with
./in manifest - Check that referenced files exist at specified paths
- Test with
echo $CLAUDE_PLUGIN_ROOTin hook scripts
Auto-Discovery Not Working
- Confirm directories are at plugin root (not in
.claude-plugin/) - Check file naming follows conventions (kebab-case, correct extensions)
- Verify custom paths in manifest are correct
- Restart Claude Code to reload plugin configuration
Conflicts Between Plugins
- Use unique, descriptive component names
- Namespace commands with plugin name if needed
- Document potential conflicts in plugin README
- Consider command prefixes for related functionality