obsidian/wiki/claude-code/create-plugins.md
2026-04-17 12:41:33 +01:00

5.3 KiB

title aliases tags sources created updated
Creating Claude Code Plugins
claude-code-plugins
plugin-authoring
claude-plugins
claude-code
plugins
skills
agents
hooks
mcp
extensibility
raw/Create plugins.md
2026-04-17 2026-04-17

Creating Claude Code Plugins

Plugins package skills, agents, hooks, MCP servers, LSP servers, and background monitors into a shareable, versioned unit. They are the distribution mechanism for Claude Code extensions.

Standalone Config vs. Plugins

Approach Skill names Best for
Standalone (.claude/ dir) /hello Personal workflows, single-project, quick experiments
Plugin (dir with .claude-plugin/plugin.json) /my-plugin:hello Team sharing, multi-project reuse, marketplace distribution
  • Start standalone → convert to plugin when ready to share
  • Plugins namespace skill names (/plugin-name:skill) to prevent conflicts

Plugin Directory Structure

my-plugin/
├── .claude-plugin/
│   └── plugin.json        ← manifest (ONLY file inside .claude-plugin/)
├── skills/
│   └── code-review/
│       └── SKILL.md
├── commands/              ← legacy flat .md skills (use skills/ for new)
├── agents/                ← custom agent definitions
├── hooks/
│   └── hooks.json
├── monitors/
│   └── monitors.json
├── bin/                   ← executables added to PATH
├── .mcp.json              ← MCP server configs
├── .lsp.json              ← LSP server configs
└── settings.json          ← default settings when plugin enabled

Critical mistake to avoid: Never put skills/, agents/, hooks/, or commands/ inside .claude-plugin/. Only plugin.json lives there.

Plugin Components

Skills

  • Add skills/<name>/SKILL.md at plugin root
  • Include description: in frontmatter so Claude knows when to invoke
  • Model-invoked automatically based on task context
  • Run /reload-plugins after changes
---
description: Reviews code for best practices. Use when reviewing PRs or analyzing code quality.
---

When reviewing code, check for:
1. Error handling
2. Security concerns
3. Test coverage

LSP Servers

  • Add .lsp.json at plugin root for language intelligence
  • Users must have the language server binary installed
  • Use pre-built marketplace LSP plugins for common languages (TS, Python, Rust)
{
  "go": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": { ".go": "go" }
  }
}

Background Monitors

  • Add monitors/monitors.json — array of monitor entries
  • Each stdout line from command is delivered to Claude as a notification
  • Started automatically when plugin is active
[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]

Default Settings

  • settings.json at plugin root applies config when plugin is enabled
  • Supported keys: agent, subagentStatusLine
  • Setting agent activates a plugin agent as the main thread
{ "agent": "security-reviewer" }

Testing Locally

# Load one plugin
claude --plugin-dir ./my-plugin

# Load multiple plugins
claude --plugin-dir ./plugin-one --plugin-dir ./plugin-two
  • Local --plugin-dir takes precedence over installed marketplace plugins of the same name
  • Run /reload-plugins during development to pick up changes without restart
  • Test skills: /plugin-name:skill-name | Check agents: /agents

Migrating from Standalone to Plugin

Standalone (.claude/) Plugin
Available in one project Shareable via marketplace
commands/ in .claude/ commands/ at plugin root
Hooks in settings.json hooks/hooks.json
Manual copy to share Install with /plugin install

After migrating, remove original .claude/ files to avoid duplicates.

Distribution

  1. Add README.md with install + usage instructions
  2. Use semantic versioning in plugin.json
  3. Submit to official marketplace via claude.ai/settings/plugins/submit or platform.claude.com/plugins/submit
  4. Distribute through a plugin marketplace (official or team-hosted)

Key Takeaways

  • Plugin root structure: manifest in .claude-plugin/plugin.json, everything else at root level
  • Skills are model-invoked; slash commands are user-invoked — they live in different dirs (skills/ vs commands/)
  • Use --plugin-dir for local testing; run /reload-plugins to hot-reload changes
  • Background monitors run automatically and stream stdout lines to Claude as notifications
  • settings.json can activate a plugin agent as the default main-thread agent
  • Start with standalone .claude/ config, convert to plugin when ready to distribute
  • Plugin skill names are always namespaced: /plugin-name:skill-name

Sources