plugin-development
Use when creating or modifying Han plugins. Covers plugin structure, configuration, hooks, skills, and best practices.
SKILL.md
Full skill instructions
Han Plugin Development
This skill provides comprehensive guidance for developing Han plugins.
Plugin Types
Han supports several plugin categories:
- Language/Validation - Skills and validation hooks for languages/tools
- Discipline - Specialized agents for specific domains
- Service/Tool - MCP servers for external integrations
Directory Structure
Every plugin must follow this structure:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Plugin metadata (required)
├── han-plugin.yml # Hook configuration (optional)
├── skills/ # Skills directory (optional)
│ └── my-skill/
│ └── SKILL.md # Skill definition
├── commands/ # Commands directory (optional)
│ └── my-command.md # Slash command
├── hooks/ # Hook scripts (optional)
│ └── my-hook.sh # Hook implementation
└── README.md # Documentation
plugin.json (Required)
The plugin.json file defines metadata:
{
"name": "my-plugin-name",
"version": "1.0.0",
"description": "What the plugin does",
"author": {
"name": "Author Name",
"url": "https://author-website.com"
},
"license": "MIT",
"keywords": ["keyword1", "keyword2"]
}
Required fields:
name- Must match directory nameversion- Semantic versioning
han-plugin.yml (Hooks)
Define validation hooks that run at lifecycle events:
hooks:
my-validation:
event: Stop # When to run
command: bash "hooks/my-hook.sh"
description: What this hook does
# Optional filters:
if_changed: # Only run if these files changed
- "**/*.ts"
dirs_with: # Only run in dirs containing
- "package.json"
Hook Events
Setup- Plugin installationSessionStart- Session beginsUserPromptSubmit- User sends messagePreToolUse- Before tool executionPostToolUse- After tool executionStop- Work completion (validation)SubagentStop- Subagent completion
Hook Environment Variables
Scripts receive:
CLAUDE_PLUGIN_ROOT- Plugin directory pathHAN_SESSION_ID- Current session IDHAN_PROJECT_DIR- Project directoryHAN_FILES- Changed files (space-separated)
Skills (SKILL.md)
Skills provide domain expertise:
---
name: skill-name
description: When to use this skill
allowed-tools: [Read, Write, Edit, Bash, Glob, Grep]
---
# Skill Title
Skill content with guidance, examples, and best practices.
Required frontmatter:
name- Skill identifierdescription- When Claude should use this skill
Commands (Slash Commands)
Commands provide slash command functionality:
---
description: What the command does
---
Command implementation content...
Invoke with: /plugin-name:command-name
Validation
Before publishing, validate your plugin:
cd my-plugin
han plugin validate
This checks:
- Required files exist
- JSON/YAML syntax is valid
- Frontmatter is correct
- No misplaced files
Best Practices
Hook Scripts
- Use
set -e- Exit on first error - Quote variables -
"${HAN_FILES}"not$HAN_FILES - Clear error messages - Write to stderr on failure
- Exit codes - 0 for success, non-zero for failure
Skills
- Specific descriptions - Help Claude know when to use
- Practical examples - Show real usage patterns
- Progressive detail - Start simple, add complexity
- Troubleshooting - Include common issues
General
- Follow naming conventions - short names matching directory
- Include README - Installation and usage docs
- Version properly - Use semantic versioning
- Test locally - Install via path before publishing
Local Installation
Test your plugin locally:
# Install from local path
han plugin install /path/to/my-plugin --scope project
# Or add to .claude/settings.json manually
Publishing
Share your plugin:
- Push to a git repository
- Add to the Han marketplace (optional)
- Users install via:
han plugin install github:user/repo
Troubleshooting
Hook Not Running
- Check
eventmatches lifecycle point - Verify
commandpath is correct - Check
if_changed/dirs_withfilters
Validation Fails
- Run
han plugin validatefor specific errors - Check plugin.json syntax
- Verify skill frontmatter
Skill Not Found
- Check SKILL.md path and naming
- Verify frontmatter has required fields
- Skill name should match directory name
