Skip to content

andrewneilson/plugin-maker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

name description allowed-tools
plugin-maker
Create, validate, and maintain Claude Code plugins. Use when the user wants to create a plugin, add a plugin, make a plugin, build a plugin, or mentions plugin creation. Also use when adding commands, agents, skills, or hooks to existing plugins, configuring plugin.json manifests, or debugging plugin discovery.
Read Write Edit Bash Glob Grep

Plugin Maker

Create discoverable Claude Code plugins that bundle commands, agents, skills, hooks, and MCP configurations.

Core Principles

  1. Plugins bundle components: A plugin is a container for related commands, agents, skills, hooks, and MCP configs
  2. Manifest-driven discovery: The .claude-plugin/plugin.json file makes the plugin discoverable
  3. Convention over configuration: Standard directory names enable automatic component discovery
  4. Plugins vs Skills: Use plugins when bundling multiple component types; use standalone skills for single capabilities

Plugin Structure

Warning: Do not place plugin.json directly in the plugin directory. It must be inside the .claude-plugin/ subdirectory for the plugin to be discovered.

my-plugin/
├── .claude-plugin/
│   └── plugin.json          # Required: manifest file (MUST be here)
├── README.md                 # Recommended: documentation
├── commands/                 # Slash commands (*.md)
│   ├── my-command.md
│   └── help.md
├── agents/                   # Subagent definitions (*.md)
│   └── my-agent.md
├── skills/                   # Skills (subdirs with SKILL.md)
│   └── my-skill/
│       └── SKILL.md
├── hooks/                    # Hook configurations
│   ├── hooks.json
│   └── handler.py
├── .mcp.json                 # MCP server configuration
└── .lsp.json                 # LSP server configuration

Quick Template: plugin.json

Every plugin requires .claude-plugin/plugin.json:

{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "Brief description of what this plugin does"
}

Optional author field for attribution:

{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "Brief description of what this plugin does",
  "author": {
    "name": "Your Name",
    "email": "you@example.com"
  }
}

Creating a Plugin

Step 1: Create Directory Structure

mkdir -p ./my-plugin/.claude-plugin
mkdir -p ./my-plugin/commands

Step 2: Create plugin.json

Create .claude-plugin/plugin.json with required fields:

{
  "name": "my-plugin",
  "description": "What this plugin does"
}

Step 3: Add Components

Add the components your plugin needs (see Component Quick Reference below).

Step 4: Test with --plugin-dir

Use the --plugin-dir flag to test your plugin without installing it:

claude --plugin-dir ./my-plugin

This loads your plugin for the current session only, allowing rapid iteration.

Step 5: Validate Structure

# Check manifest exists and is valid JSON
cat ./my-plugin/.claude-plugin/plugin.json | jq .

# List all components
ls -la ./my-plugin/

Step 6: Test Discovery

Ask Claude to use your plugin's commands or agents to verify discovery works.

Component Quick Reference

Commands (commands/*.md)

Slash commands users invoke explicitly. Plugin commands are namespaced as /plugin-name:command-name.

---
description: What this command does
argument-hint: [optional-args]
allowed-tools: ["Read", "Write", "Bash"]
---

# Command Name

Instructions for Claude when this command is invoked.

The user's input is available as $ARGUMENTS.

**Advanced argument access:**
- `$ARGUMENTS` - Full argument string
- `$1`, `$2`, `$3` - Individual arguments (space-separated)

Fields:

Field Required Description
description Yes Shown in /help and command completion
argument-hint No Hint text for arguments (e.g., [file-path])
allowed-tools No Restrict available tools (JSON array)
disable-model-invocation No If true, only explicit /command triggers it
model No Override model: inherit, sonnet, opus, haiku

Agents (agents/*.md)

Specialized subagents for parallel or delegated work.

---
name: my-agent
description: Use this agent when analyzing code for security issues. Examples: <example>Context: User asks about security\nuser: "Check this file for vulnerabilities"\nassistant: "I'll analyze with the security agent"</example>
model: sonnet
color: yellow
tools: ["Read", "Grep", "Glob"]
---

You are an expert at [specific task].

## Your Role

Detailed instructions for the agent...

Fields:

Field Required Description
name Yes Agent identifier (lowercase, hyphens)
description Yes When to use. Include Examples tags: <example>Context: ...\nuser: "..."\nassistant: "..."</example>
model No inherit, sonnet, opus, haiku
color No Visual indicator: yellow, blue, green, etc.
tools No Array of available tools

Triggering Tip: Use <example> tags in descriptions for complex use cases. Include context, user message, and assistant response to guide invocation.

Skills (skills/skill-name/SKILL.md)

Model-invoked capabilities that Claude activates based on context. Plugin skills are namespaced as /plugin-name:skill-name.

---
name: my-skill
description: What this skill does. Use when user mentions [trigger terms].
---

# Skill Name

Instructions...

Hooks (hooks/hooks.json)

Event-driven automation scripts. Use for validation, context injection, and workflow automation.

Hook Types:

  • Prompt-based (recommended): LLM-driven decisions with "type": "prompt"
  • Command-based: Bash scripts with "type": "command"
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Write|Edit",
      "hooks": [{
        "type": "prompt",
        "prompt": "Validate file write safety. Check: path traversal, credentials. Return 'approve' or 'deny'."
      }]
    }],
    "Stop": [{
      "matcher": "*",
      "hooks": [{
        "type": "prompt",
        "prompt": "Verify task completion: tests run, build succeeded. Return 'approve' or 'block'."
      }]
    }]
  }
}

Available Events:

Event Trigger
PreToolUse Before any tool executes
PostToolUse After a tool executes
UserPromptSubmit When user submits a prompt
Stop When Claude wants to stop
SubagentStop When subagent wants to stop
SessionStart Session begins
SessionEnd Session ends
PreCompact Before context compaction
Notification User notification sent

Important: Use ${CLAUDE_PLUGIN_ROOT} for paths in hook commands.

See Hook Development Guide for comprehensive patterns.

MCP Configuration (.mcp.json)

Integrate Model Context Protocol servers for additional tools:

{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["${CLAUDE_PLUGIN_ROOT}/mcp-server/index.js"],
      "env": {
        "NODE_ENV": "production"
      }
    }
  }
}

Server types: stdio, SSE, HTTP, WebSocket. Tools appear as mcp__plugin-name__tool-name.

Plugin Settings (.claude/plugin-name.local.md)

Store per-project configuration with YAML frontmatter:

---
enabled: true
strict_mode: false
max_retries: 3
---

# Plugin Configuration

Settings documentation here.

Usage:

  • Read from hooks, commands, and agents
  • Control plugin behavior per-project
  • Store state and configuration
  • Should be in .gitignore

See Plugin Settings Guide for parsing techniques and patterns.

LSP Configuration (.lsp.json)

Configure Language Server Protocol servers for enhanced editor support:

{
  "lspServers": {
    "my-lsp": {
      "command": "my-language-server",
      "args": ["--stdio"],
      "filetypes": ["mylang"]
    }
  }
}

Fields:

Field Required Description
command Yes The LSP server executable
args No Command-line arguments
filetypes Yes File extensions to activate for

Plugin Locations

Location Purpose
--plugin-dir ./path Development/testing (primary workflow)
~/.claude/plugins/ Personal plugins (installed)
.claude/plugins/ Project plugins (committed to git)

When to Create a Plugin

Standalone Skill vs Plugin Comparison

Feature Standalone Skill Plugin
Simplest option One SKILL.md file Multiple files/directories
Commands No Yes
Multiple skills No Yes
Agents No Yes
Hooks No Yes
MCP servers No Yes
LSP servers No Yes
Namespacing None /plugin-name:*
Distribution Copy file Package directory

Create a plugin when:

  • You need multiple component types (commands + agents, skills + hooks, etc.)
  • You want to bundle and distribute related functionality
  • Your team needs shared tooling with consistent behavior

Don't create a plugin when:

  • You only need a single skill (use standalone skill instead)
  • You only need a single command (consider a skill or CLAUDE.md instruction)
  • The functionality is project-specific and simple

Naming Conventions

Item Convention Example
Plugin directory lowercase-hyphenated my-plugin
plugin.json name matches directory "name": "my-plugin"
Commands directory plural commands/ not command/
Agents directory plural agents/ not agent/
Skills directory plural skills/ not skill/
Hooks directory singular hooks/ with hooks.json inside

Quick Reference

Create:

mkdir -p ./my-plugin/.claude-plugin

Test during development:

claude --plugin-dir ./my-plugin

Validate manifest:

cat ./my-plugin/.claude-plugin/plugin.json | jq .

Install plugin:

cp -r ./my-plugin ~/.claude/plugins/

List installed plugins:

ls ~/.claude/plugins/*/
ls .claude/plugins/*/

Additional Resources

About

Agent skill for making plugins

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •