Files
gh-racurry-neat-little-pack…/skills/plugin-design/SKILL.md
2025-11-30 08:48:43 +08:00

17 KiB

name, description
name description
box-factory-plugin-design Interpretive guidance for designing Claude Code plugins. Helps you understand plugin architecture, marketplace distribution, and when plugins are the right pattern. Use when creating or reviewing plugins.

Plugin Design Skill

This skill provides interpretive guidance and best practices for creating Claude Code plugins. ALWAYS fetch current official documentation before creating plugins - this skill helps you understand what the docs mean and how to create excellent plugins.

Required Reading Before Creating Plugins

Fetch these docs with WebFetch every time:

Core Understanding

Plugins Are Packaging, Not Functionality

Key insight: Plugins don't add new capabilities to Claude Code. They package existing extension points (commands, agents, skills, hooks, MCP servers) for distribution.

What this means:

  • Plugins bundle components together
  • The value is distribution and discoverability
  • Components work the same inside or outside plugins
  • You're organizing and sharing, not creating new primitives

Decision test: If you're asking "should this be a plugin?", you're asking the wrong question. Ask "should I package these existing components for sharing?"

Critical Directory Structure (Official Specification)

The #1 mistake that causes plugins to install but not work:

✅ Correct:
plugin-name/
├── .claude-plugin/
│   └── plugin.json     ← Only metadata here
├── commands/            ← At plugin root
├── agents/              ← At plugin root
├── skills/              ← At plugin root
└── hooks/               ← At plugin root

❌ Wrong (won't work):
plugin-name/
└── .claude-plugin/
    ├── plugin.json
    ├── commands/        ← Won't be found!
    └── agents/          ← Won't be found!

Official docs say: "All other directories (commands/, agents/, skills/, hooks/) must be at the plugin root, not inside .claude-plugin/."

Skills Directory Structure

Skills use subdirectories with a SKILL.md file:

skills/
├── skill-one/
│   ├── SKILL.md         ← Skill definition
│   └── helpers.py       ← Supporting files (optional)
└── skill-two/
    └── SKILL.md

Plugin Manifest (plugin.json) - Official Specification

Located at .claude-plugin/plugin.json:

Required Fields

  • name: Unique identifier in kebab-case (e.g., "deployment-tools")

Optional Metadata Fields We Use

Field Type Purpose
version string Semantic versioning (e.g., "2.1.0")
description string Brief plugin purpose explanation
repository string Source code location

Optional Metadata Fields We NEVER Use

Field Type Purpose
author object Author details: {name, email, url}
homepage string Documentation URL
license string License identifier (MIT, Apache-2.0, etc.)
keywords array Discovery tags for categorization

Component Path Fields (Optional)

Override default locations:

  • commands: Additional command files/directories (string or array)
  • agents: Agent markdown files (string or array)
  • hooks: Hook configuration path or inline JSON
  • mcpServers: MCP server configuration path or inline JSON

Note: Custom paths supplement default directories, they don't replace them.

Best practice: Always include description and version even though they're optional - improves discoverability and user trust. Do NOT include author, repository, homepage, license, or keywords unless explicitly specified.

Advanced Features (Official Specification)

Environment Variables

Use ${CLAUDE_PLUGIN_ROOT} in paths to reference the plugin's absolute directory.

Custom Component Paths

Specify additional locations for components:

{
  "name": "my-plugin",
  "commands": ["./extra-commands", "./legacy/commands"],
  "agents": "./custom-agents"
}

All paths must be relative to plugin root and start with ./

Inline Component Configuration

Define hooks or MCP servers directly in plugin.json instead of separate files:

{
  "name": "my-plugin",
  "hooks": {
    "PreToolUse:Bash": "./hooks/bash-guard.sh"
  },
  "mcpServers": {
    "custom-server": {
      "command": "node",
      "args": ["./server.js"]
    }
  }
}

MCP Server Configuration (Best Practices)

CRITICAL: When configuring MCP servers in plugins, follow these security and maintainability patterns.

Always Use External Configuration Files

CORRECT - External file:

// plugin.json
{
  "name": "my-plugin",
  "mcpServers": "./.mcp.json"
}
// .mcp.json (at plugin root)
{
  "github": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": {
      "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
    }
  }
}

WRONG - Inline configuration:

{
  "name": "my-plugin",
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": ""
      }
    }
  }
}

Why external files are better:

  • Separation of concerns (metadata vs configuration)
  • Easier to edit MCP config independently
  • Cleaner plugin.json focused on plugin metadata
  • Matches user expectations from standalone MCP setups

Always Use Environment Variable References

CORRECT - Environment variable reference:

{
  "server-name": {
    "command": "server-binary",
    "env": {
      "API_KEY": "${API_KEY}",
      "AUTH_TOKEN": "${AUTH_TOKEN}",
      "DATABASE_URL": "${DATABASE_URL}"
    }
  }
}

WRONG - Hardcoded empty strings:

{
  "server-name": {
    "env": {
      "API_KEY": "",
      "AUTH_TOKEN": "",
      "DATABASE_URL": ""
    }
  }
}

VERY WRONG - Hardcoded actual secrets:

{
  "server-name": {
    "env": {
      "API_KEY": "sk_live_abc123..."
    }
  }
}

Why environment variables are critical:

  • Security: Never commit secrets to git history
  • Portability: Different users/environments have different credentials
  • Standard practice: ${VAR_NAME} is the established MCP pattern
  • Documentation clarity: Shows what env vars are required

Document Required Environment Variables

In your README, always include:

## MCP Server Setup

This plugin includes the [Server Name] MCP server.

### Prerequisites

- [Tool requirements, e.g., Node.js, Python]
- [Service account or API access]

### Configuration

1. Obtain credentials:
   - Visit [credential URL]
   - Create [token/API key] with `scope1`, `scope2` permissions

2. Set environment variables:
   ```bash
   export API_KEY="your_key_here"
   export AUTH_TOKEN="your_token_here"
  1. The MCP server will start automatically when the plugin is enabled

**Required documentation elements:**
- Prerequisites (tools, accounts, permissions)
- How to obtain credentials with specific scopes/permissions
- Exact environment variable names to set
- Example export commands
- When the server starts (usually: when plugin enabled)

#### Common MCP Server Types

**GitHub:**
```json
{
  "github": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": {
      "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
    }
  }
}

Filesystem:

{
  "filesystem": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
    "env": {}
  }
}

Database:

{
  "database": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-postgres"],
    "env": {
      "DATABASE_URL": "${DATABASE_URL}"
    }
  }
}

Custom server using plugin root:

{
  "custom": {
    "command": "${CLAUDE_PLUGIN_ROOT}/servers/custom-server",
    "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
    "env": {
      "CUSTOM_API_KEY": "${CUSTOM_API_KEY}"
    }
  }
}

MCP Configuration Checklist

Before publishing plugin with MCP servers:

Security:

  • ✓ All secrets use ${ENV_VAR} references (never hardcoded)
  • ✓ No empty string placeholders for secrets
  • ✓ No actual credentials in git history
  • ✓ .env files in .gitignore if used for local testing

Structure:

  • ✓ MCP configuration in external file (.mcp.json or custom path)
  • ✓ Path in plugin.json is relative and starts with ./
  • ✓ Valid JSON syntax in MCP configuration file

Documentation:

  • ✓ README explains how to obtain credentials
  • ✓ Required scopes/permissions documented
  • ✓ Environment variable names clearly listed
  • ✓ Example export commands provided
  • ✓ Troubleshooting section for common issues

Testing:

  • ✓ Verified MCP server starts with plugin enabled
  • ✓ Tested with actual credentials in environment
  • ✓ Confirmed required tools/dependencies work

Marketplace Distribution (Official Specification)

Marketplace.json Structure

Located at .claude-plugin/marketplace.json:

Required fields:

  • name: Marketplace identifier (kebab-case)
  • owner: Maintainer information object
  • plugins: Array of plugin entries

Plugin entry fields:

{
  "name": "plugin-name",
  "source": "./plugins/plugin-name",
  "description": "Optional override",
  "strict": true
}

Source Types

Local path (development):

"source": "./plugins/my-plugin"

GitHub repository:

"source": {
  "source": "github",
  "repo": "owner/repo"
}

Git URL:

"source": {
  "source": "url",
  "url": "https://gitlab.com/user/plugin.git"
}

The strict Field

  • strict: true (default): Plugin must have its own plugin.json
  • strict: false: Marketplace entry serves as complete manifest

Use strict: false when: Packaging third-party content without modifying it.

Decision Framework

When to Create a Plugin

Create plugin when:

  • You have multiple related components (commands + agents + hooks)
  • You want to share with team/community
  • You need versioning and distribution
  • You want one-command installation (/plugin install)

Don't create plugin when:

  • Single command/agent (just share the file)
  • Personal workflow (no distribution need)
  • Rapid iteration (plugins add packaging overhead)
  • Testing concepts (develop components first, package later)

Plugin Scope Philosophy (Best Practices)

Good plugin scope:

  • Focused purpose (testing suite, security scanner, docs generator)
  • Related components work together
  • Clear value proposition
  • Composable with other plugins

Bad plugin scope:

  • "Everything for development" (too broad)
  • Unrelated utilities thrown together
  • Duplicates core functionality
  • Conflicts with other plugins

Development Workflow (Best Practices)

The docs show the mechanics. Here's the philosophy:

  1. Build components first - Create and test commands/agents individually
  2. Test without packaging - Use .claude/ directories for iteration
  3. Package when ready - Add plugin.json and organize structure
  4. Validate locally - Use claude plugin validate . command
  5. Create test marketplace - Local marketplace with absolute paths
  6. Install and test - /plugin marketplace add ./path/to/marketplace
  7. Iterate - Fix issues, restart Claude Code, test again
  8. Document - Write comprehensive README
  9. Publish - Push to GitHub, share marketplace

Key insight: Don't start with plugin structure. Build components, then package them.

Testing Commands (Official Specification)

Validate plugin structure:

claude plugin validate .

Checks JSON syntax and directory structure.

Add local marketplace for testing:

/plugin marketplace add ./absolute/path/to/marketplace

Install from local marketplace:

/plugin install plugin-name@marketplace-name

Verify installation:

Check /help for newly installed commands and agents.

Common Pitfalls (Best Practices)

Pitfall #1: Components in Wrong Directory

Problem: Putting commands/agents inside .claude-plugin/

Why it fails: Claude Code only looks at plugin root for components

Solution: Keep .claude-plugin/ for metadata only, put all components at root

Pitfall #2: Premature Pluginification

Problem: Creating plugin for single command or concept

Why it fails:

  • Overhead of marketplace setup
  • Harder to iterate quickly
  • Users just want the file
  • More complex to maintain

Better: Share the markdown file directly, create plugin later if collection grows

Pitfall #3: Kitchen Sink Plugin

Problem: "All my utilities" plugin with unrelated components

Why it fails:

  • Unclear purpose
  • Users only want subset
  • Hard to maintain and version
  • Discovery problems

Better: Focused plugins (testing tools, git helpers, docs generators)

Pitfall #4: Missing Documentation

Problem: Plugin without README or usage examples

Why it fails:

  • Users don't know what's included
  • No installation instructions
  • No troubleshooting guidance
  • Low adoption

Solution: Comprehensive README with:

  • Installation steps
  • Component list with examples
  • Required dependencies
  • Troubleshooting section
  • Changelog

Pitfall #5: Ignoring Semantic Versioning

Problem: Breaking changes in minor/patch versions

Why it fails: Users expect:

  • 1.0.0 → 1.0.1 - Bug fixes only, safe to auto-update
  • 1.0.0 → 1.1.0 - New features, backward compatible
  • 1.0.0 → 2.0.0 - Breaking changes, needs migration

Solution: Follow semver strictly, document breaking changes

Marketplace Organization (Best Practices)

Embedded vs External Plugins

Embedded (monorepo approach):

marketplace/
├── .claude-plugin/marketplace.json
└── plugins/
    ├── plugin-one/
    └── plugin-two/

Pros:

  • Single source of truth
  • Atomic updates
  • Easier testing

Cons:

  • Monorepo management overhead
  • Slower independent development

External (distributed approach):

{
  "plugins": [
    {
      "name": "plugin-one",
      "source": {
        "source": "github",
        "repo": "org/plugin-one"
      }
    }
  ]
}

Pros:

  • Independent versioning
  • Faster iteration
  • Individual repos easier to manage

Cons:

  • Dependency coordination
  • Potential version conflicts

Team Distribution Strategy

Official mechanism: Configure .claude/settings.json at repository level:

{
  "extraKnownMarketplaces": ["owner/marketplace-repo"],
  "enabledPlugins": ["plugin-name@marketplace-name"]
}

Best practices to consider:

  • Test plugins thoroughly before team rollout
  • Document required environment variables
  • Have rollback plan if plugin breaks
  • Establish approval process for new plugins
  • Communicate plugin updates to team

Plugin Quality Checklist

Before publishing:

Structure (from official docs):

  • ✓ Valid plugin.json at .claude-plugin/plugin.json
  • ✓ Components at plugin root (not in .claude-plugin/)
  • ✓ Proper directory names (commands, agents, skills, hooks)
  • claude plugin validate . passes
  • ✓ Relative paths start with ./

Metadata (best practices):

  • ✓ Descriptive name (kebab-case)
  • ✓ Clear description (what problem it solves)
  • ✓ Semantic versioning
  • ✓ Author info (for support)
  • ✓ Repository link (for issues/PRs)
  • ✓ Keywords for discovery

Documentation (best practices):

  • ✓ Comprehensive README
  • ✓ Installation instructions
  • ✓ Usage examples for each component
  • ✓ Required dependencies documented
  • ✓ Troubleshooting section
  • ✓ Changelog

Design (best practices):

  • ✓ Focused scope (clear purpose)
  • ✓ No duplication of core functionality
  • ✓ Components complement each other
  • ✓ Tested locally before publishing

Example: High-Quality Plugin Manifest

Basic (what docs show):

{
  "name": "my-plugin",
  "description": "A plugin",
  "version": "1.0.0"
}

Issues:

  • Vague description

Excellent (applying best practices):

{
  "name": "python-testing-suite",
  "version": "1.0.0",
  "description": "Comprehensive Python testing tools with pytest integration, coverage reporting, and failure analysis",
  "repository": "https://github.com/username/python-testing-suite",
}

Improvements:

  • Specific description (what it does, how it helps)
  • (optional, but okay)Repository for issues and PRs

Documentation References

These are the authoritative sources. Fetch them before creating plugins:

Plugin creation:

Complete specifications:

Distribution:

Component specifications:

  • Reference agent-design, slash-command-design skills for component details

Remember: Official docs provide structure and features. This skill provides best practices and patterns for creating excellent plugins.