Back to skills
SkillHub ClubShip Full StackFull StackIntegration

plugin-best-practices

This skill should be used when the user asks to "validate a plugin", "optimize plugin", "check plugin quality", "review plugin structure", "find plugin issues", "check best practices", "analyze plugin", or mentions plugin validation, optimization, or quality assurance.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
426
Hot score
99
Updated
March 20, 2026
Overall rating
C4.0
Composite score
4.0
Best-practice grade
C62.8

Install command

npx @skill-hub/cli install fradser-dotclaude-plugin-best-practices

Repository

FradSer/dotclaude

Skill path: plugin-optimizer/skills/plugin-best-practices

This skill should be used when the user asks to "validate a plugin", "optimize plugin", "check plugin quality", "review plugin structure", "find plugin issues", "check best practices", "analyze plugin", or mentions plugin validation, optimization, or quality assurance.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Integration.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: FradSer.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install plugin-best-practices into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/FradSer/dotclaude before adding plugin-best-practices to shared team environments
  • Use plugin-best-practices for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: plugin-best-practices
description: This skill should be used when the user asks to "validate a plugin", "optimize plugin", "check plugin quality", "review plugin structure", "find plugin issues", "check best practices", "analyze plugin", or mentions plugin validation, optimization, or quality assurance.
version: 0.1.0
---

# Plugin Best Practices Validation

Comprehensive knowledge base for validating and optimizing Claude Code plugins against official standards.

## Purpose

This skill provides structured validation knowledge for analyzing Claude Code plugins. Use it when checking plugin quality, identifying issues, or generating optimization recommendations.

## Official Documentation

For the latest official Claude Code documentation, use the `claude-code-guide` agent to search and retrieve information about:
- Plugin development guidelines
- Component specifications (agents, commands, skills, hooks)
- API references and tool usage
- Best practices and examples

## Core Philosophy

**Minimal Configuration**: Rely on auto-discovery. Do not manually list commands, agents, or skills in plugin.json unless absolutely necessary.

**Standard Directory Structure**: Place components in root directories (commands/, agents/, skills/, hooks/) for automatic discovery.

**Tool Usage Rules**:
- Core file tools (Read, Write, Glob, Grep, Edit): Describe actions implicitly ("Find files matching...", "Read the configuration...")
- Skill tool: Always explicit ("Load the X skill using the Skill tool")
- Bash: Describe commands ("Run `git status`") rather than tool invocation

**Portable Paths**: Always use `${CLAUDE_PLUGIN_ROOT}` for file references. Never hardcode absolute paths.

**Naming Convention**: Use kebab-case for all files and directories (code-review.md, api-testing/).

**Component Decoupling**: Components (skills/agents/commands) must be independent and self-contained. See `references/directory-structure.md` and component-specific references for implementation details.

## Quick Reference

**Critical Component Requirements**:
- Agents: Must have 2-4 `<example>` blocks in description, second-person system prompts
- Skills: SKILL.md in subdirectory, third-person description, progressive disclosure pattern
- Commands: Frontmatter with description, instructions FOR Claude, tool restrictions via allowed-tools
- Hooks: Event-driven validation, exit codes (0=allow, 2=block)

**File Locations**:
- Manifest: `.claude-plugin/plugin.json`
- Components: `commands/*.md`, `agents/*.md`, `skills/*/SKILL.md`
- Configuration: `hooks/hooks.json`, `.mcp.json`

**Common Validation Checks**:
- Plugin.json has name, description, author.name
- All components use kebab-case naming
- No explicit tool invocations in component instructions
- Agents have triggering examples in descriptions
- Skills use imperative form, not second person
- Components (skills/agents/commands) are decoupled and do not directly reference each other

## Core Validation Categories

Plugin validation covers seven main categories. For detailed checks and patterns, consult the corresponding reference files:

1. **Plugin Structure & Organization** - Manifest location, component directories, naming conventions, portable paths
2. **Command Development** - Frontmatter, instructions style, tool restrictions, inline bash syntax
3. **Agent Design** - Frontmatter fields, example blocks, system prompts, output formats
4. **Skill Implementation** - File location, description style, progressive disclosure, body content
5. **Tool Invocation Patterns** - Correct vs anti-pattern tool references in component instructions
6. **File Format Patterns** - YAML frontmatter, markdown structure, naming conventions
7. **Manifest Quality** - Required/optional fields for plugin.json and marketplace.json

See "Progressive Disclosure Strategy" section below for reference file mappings.

## Validation Workflow

When validating a plugin:

1. **Load this skill** to access validation knowledge
2. **Scan structure**: Check directory layout, manifest, component locations
3. **Validate components**: For each component type (commands, agents, skills), check:
   - File format and frontmatter
   - Content patterns and anti-patterns
   - Naming conventions
4. **Check tool invocations**: Search for explicit tool call anti-patterns
5. **Review metadata**: Verify completeness of manifest and frontmatter fields
6. **Generate report**: Categorize issues by severity (critical/warning/info)
7. **Provide fixes**: Suggest exact Edit tool parameters for each issue

## Severity Levels

Categorize validation issues into three severity levels:

- **Critical** - Must fix before plugin works correctly
- **Warning** - Should fix for best practices compliance
- **Info** - Nice to have improvements for quality and discoverability

See reference files for specific examples of each severity level.

## Best Practices for Using This Skill

**When analyzing a plugin:**

1. Start with structure validation (manifest, directories)
2. Validate each component type systematically
3. Consult specific reference files for detailed patterns
4. Categorize all issues by severity
5. Provide actionable fix suggestions with exact parameters

**When generating reports:**

1. Summary section with compliance checklist
2. Issues grouped by severity (critical/warning/info)
3. Each issue with file:line reference
4. Auto-fix suggestions with Edit tool parameters
5. Overall quality assessment

**When fixing issues:**

1. Address critical issues first
2. Use provided Edit tool parameters
3. Re-validate after fixes
4. Iterate until all critical issues resolved

## Reference Resources & Scenario Guide

Use this guide to select the correct reference file based on the specific validation task or scenario encountered.

### 1. Structure & Manifest Validation
**Scenario**: Users report "plugin not found" or "invalid configuration".
- **Directory Layout**: usage of `references/directory-structure.md` - Validates file hierarchy, naming conventions (kebab-case), and component placement.
- **Manifest Configuration**: usage of `references/manifest-schema.md` - checks `plugin.json` fields, `marketplace.json` requirements, and metadata standards.

### 2. Component Implementation
**Scenario**: "How do I create an X?" or "Validation failed for component Y".
- **Commands**: `references/components/commands.md` - For `options`, `arguments`, and inline execution syntax.
- **Agents**: `references/components/agents.md` - For system prompts, persona definition, and triggering example blocks.
- **Skills**: `references/components/skills.md` - For `SKILL.md` structure, progressive disclosure patterns, and instruction formats.
- **Hooks**: `references/components/hooks.md` - For `PreStep`/`PostStep` triggers, `hooks.json` config, and exit code handling.
- **Common Patterns**: `references/component-patterns.md` - Shared best practices applicable across all components (VSCode compatibility, error handling).

### 3. Advanced Integrations & External Tools
**Scenario**: Integrating external servers/tools or fixing tool call errors.
- **MCP Servers**: `references/components/mcp-servers.md` & `references/mcp-patterns.md` - For defining and configuring Model Context Protocol servers.
- **LSP Servers**: `references/components/lsp-servers.md` - For Language Server Protocol integration details.
- **Tool Invocations**: `references/tool-invocations.md` - **CRITICAL**: Distinguishing between correct tool descriptions and forbidden explicit tool calls.

### 4. Workflow, Debugging & Documentation
**Scenario**: "Why isn't it working?" or "How do I test this?".
- **Debugging**: `references/debugging.md` - Strategies for diagnosing agent loops, tool failures, and state issues.
- **CLI Operations**: `references/cli-commands.md` - Reference for `claude` CLI commands used in testing and maintenance.
- **Documentation Standards**: `references/todowrite-usage.md` - Guidelines for using TodoWrite to maintain plugin context and documentation.

Load specific reference files as needed to provide detailed validation logic without overwhelming the context.


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/directory-structure.md

```markdown
# Plugin Directory Structure

## Standard plugin layout

A complete plugin follows this structure:

```
enterprise-plugin/
├── .claude-plugin/           # Metadata directory
│   └── plugin.json          # Required: plugin manifest
├── commands/                 # Default command location
│   ├── status.md
│   └── logs.md
├── agents/                   # Default agent location
│   ├── security-reviewer.md
│   ├── performance-tester.md
│   └── compliance-checker.md
├── skills/                   # Agent Skills
│   ├── code-reviewer/
│   │   └── SKILL.md
│   └── pdf-processor/
│       ├── SKILL.md
│       └── scripts/
├── hooks/                    # Hook configurations
│   ├── hooks.json           # Main hook config
│   └── security-hooks.json  # Additional hooks
├── .mcp.json                # MCP server definitions
├── .lsp.json                # LSP server configurations
├── scripts/                 # Hook and utility scripts
│   ├── security-scan.sh
│   ├── format-code.py
│   └── deploy.js
├── LICENSE                  # License file
└── CHANGELOG.md             # Version history
```

> **Warning**: The `.claude-plugin/` directory contains the `plugin.json` file. All other directories (commands/, agents/, skills/, hooks/) must be at the plugin root, not inside `.claude-plugin/`.

## File locations reference

| Component       | Default Location             | Purpose                          |
| :-------------- | :--------------------------- | :------------------------------- |
| **Manifest**    | `.claude-plugin/plugin.json` | Required metadata file           |
| **Commands**    | `commands/`                  | Slash command Markdown files     |
| **Agents**      | `agents/`                    | Subagent Markdown files          |
| **Skills**      | `skills/`                    | Agent Skills with SKILL.md files |
| **Hooks**       | `hooks/hooks.json`           | Hook configuration               |
| **MCP servers** | `.mcp.json`                  | MCP server definitions           |
| **LSP servers** | `.lsp.json`                  | Language server configurations   |

```

### references/manifest-schema.md

```markdown
# Plugin Manifest Schema

The `plugin.json` file defines your plugin's metadata and configuration. This section documents all supported fields and options.

## Complete schema

```json
{
  "name": "plugin-name",
  "version": "1.2.0",
  "description": "Brief plugin description",
  "author": {
    "name": "Author Name",
    "email": "[email protected]",
    "url": "https://github.com/author"
  },
  "homepage": "https://docs.example.com/plugin",
  "repository": "https://github.com/author/plugin",
  "license": "MIT",
  "keywords": ["keyword1", "keyword2"],
  "commands": ["./custom/commands/special.md"],
  "agents": "./custom/agents/",
  "skills": "./custom/skills/",
  "hooks": "./config/hooks.json",
  "mcpServers": "./mcp-config.json",
  "outputStyles": "./styles/",
  "lspServers": "./.lsp.json"
}
```

## Required fields

| Field  | Type   | Description                               | Example              |
| :----- | :----- | :---------------------------------------- | :------------------- |
| `name` | string | Unique identifier (kebab-case, no spaces) | `"deployment-tools"` |

## Metadata fields

| Field         | Type   | Description                         | Example                                            |
| :------------ | :----- | :---------------------------------- | :------------------------------------------------- |
| `version`     | string | Semantic version                    | `"2.1.0"`                                          |
| `description` | string | Brief explanation of plugin purpose | `"Deployment automation tools"`                    |
| `author`      | object | Author information                  | `{"name": "Dev Team", "email": "[email protected]"}` |
| `homepage`    | string | Documentation URL                   | `"https://docs.example.com"`                       |
| `repository`  | string | Source code URL                     | `"https://github.com/user/plugin"`                 |
| `license`     | string | License identifier                  | `"MIT"`, `"Apache-2.0"`                            |
| `keywords`    | array  | Discovery tags                      | `["deployment", "ci-cd"]`                          |

## Component path fields

| Field          | Type           | Description                                                                                                                                              | Example                                |
| :------------- | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------- |
| `commands`     | string\|array  | Additional command files/directories                                                                                                                     | `"./custom/cmd.md"` or `["./cmd1.md"]` |
| `agents`       | string\|array  | Additional agent files                                                                                                                                   | `"./custom/agents/"`                   |
| `skills`       | string\|array  | Additional skill directories                                                                                                                             | `"./custom/skills/"`                   |
| `hooks`        | string\|object | Hook config path or inline config                                                                                                                        | `"./hooks.json"`                       |
| `mcpServers`   | string\|object | MCP config path or inline config                                                                                                                         | `"./mcp-config.json"`                  |
| `outputStyles` | string\|array  | Additional output style files/directories                                                                                                                | `"./styles/"`                          |
| `lspServers`   | string\|object | [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) config for code intelligence (go to definition, find references, etc.) | `"./.lsp.json"`                        |

## Path behavior rules

**Important**: Custom paths supplement default directories - they don't replace them.

* If `commands/` exists, it's loaded in addition to custom command paths
* All paths must be relative to plugin root and start with `./`
* Commands from custom paths use the same naming and namespacing rules
* Multiple paths can be specified as arrays for flexibility

**Path examples**:

```json
{
  "commands": [
    "./specialized/deploy.md",
    "./utilities/batch-process.md"
  ],
  "agents": [
    "./custom-agents/reviewer.md",
    "./custom-agents/tester.md"
  ]
}
```

## Environment variables

**`${CLAUDE_PLUGIN_ROOT}`**: Contains the absolute path to your plugin directory. Use this in hooks, MCP servers, and scripts to ensure correct paths regardless of installation location.

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/process.sh"
          }
        ]
      }
    ]
  }
}
```

## Plugin installation scopes

When you install a plugin, you choose a **scope** that determines where the plugin is available and who else can use it:

| Scope     | Settings file                 | Use case                                                 |
| :-------- | :---------------------------- | :------------------------------------------------------- |
| `user`    | `~/.claude/settings.json`     | Personal plugins available across all projects (default) |
| `project` | `.claude/settings.json`       | Team plugins shared via version control                  |
| `local`   | `.claude/settings.local.json` | Project-specific plugins, gitignored                     |
| `managed` | `managed-settings.json`       | Managed plugins (read-only, update only)                 |

Plugins use the same scope system as other Claude Code configurations. For installation instructions and scope flags, see [Install plugins](/en/discover-plugins#install-plugins). For a complete explanation of scopes, see [Configuration scopes](/en/settings#configuration-scopes).

## Plugin caching and file resolution

For security and verification purposes, Claude Code copies plugins to a cache directory rather than using them in-place. Understanding this behavior is important when developing plugins that reference external files.

### How plugin caching works

When you install a plugin, Claude Code copies the plugin files to a cache directory:

* **For marketplace plugins with relative paths**: The path specified in the `source` field is copied recursively. For example, if your marketplace entry specifies `"source": "./plugins/my-plugin"`, the entire `./plugins` directory is copied.
* **For plugins with `.claude-plugin/plugin.json`**: The implicit root directory (the directory containing `.claude-plugin/plugin.json`) is copied recursively.

### Path traversal limitations

Plugins cannot reference files outside their copied directory structure. Paths that traverse outside the plugin root (such as `../shared-utils`) will not work after installation because those external files are not copied to the cache.

### Working with external dependencies

If your plugin needs to access files outside its directory, you have two options:

**Option 1: Use symlinks**

Create symbolic links to external files within your plugin directory. Symlinks are honored during the copy process:

```bash
# Inside your plugin directory
ln -s /path/to/shared-utils ./shared-utils
```

The symlinked content will be copied into the plugin cache.

**Option 2: Restructure your marketplace**

Set the plugin path to a parent directory that contains all required files, then provide the rest of the plugin manifest directly in the marketplace entry:

```json
{
  "name": "my-plugin",
  "source": "./",
  "description": "Plugin that needs root-level access",
  "commands": ["./plugins/my-plugin/commands/"],
  "agents": ["./plugins/my-plugin/agents/"],
  "strict": false
}
```

This approach copies the entire marketplace root, giving your plugin access to sibling directories.

> **Note**: Symlinks that point to locations outside the plugin's logical root are followed during copying. This provides flexibility while maintaining the security benefits of the caching system.

```

### references/components/commands.md

```markdown
# Commands Component Reference

Plugins add custom slash commands that integrate seamlessly with Claude Code's command system.

**Location**: `commands/` directory in plugin root

**File format**: Markdown files with YAML frontmatter + Markdown body

---

## Command Structure

### Frontmatter (YAML)

```yaml
---
description: Brief description of what this command does
argument-hint: <required-arg> [optional-arg]
allowed-tools: ["Read", "Write", "Bash(git:*)"]  # Optional: restrict tool access
disable-model-invocation: true  # Optional: for user-only commands
---
```

**Required Fields**:
- `description`: Short description shown in command list
- `argument-hint`: Usage pattern for arguments (use `<>` for required, `[]` for optional)

**Optional Fields**:
- `allowed-tools`: Array of tools Claude can use (see tool-invocations.md for syntax)
- `disable-model-invocation`: Set `true` for commands that only execute scripts without LLM

### Body (Markdown)

Write **directives FOR Claude** (instructions), not descriptions to users.

**Structure Pattern**:
```markdown
# Command Title

Brief introduction of what Claude will do.

## Core Principles (Optional)
- Guiding principle 1
- Guiding principle 2

## Phase 1: Phase Name

**Goal**: What this phase accomplishes

**CRITICAL**: Important instruction or warning (Optional)

**Actions**:
1. Specific instruction 1
2. Specific instruction 2

If the user says "condition", do specific action.

## Phase 2: Next Phase
...
```

## Integration Points

- Commands appear in `/help` and autocomplete
- Invoked via `/command-name [arguments]`
- Access to all Claude Code tools (unless restricted by `allowed-tools`)
- Can launch plugin agents and invoke skills
- User's working directory is preserved

## Best Practices

### Should Do
- **Use `allowed-tools`**: Restrict tool access (principle of least privilege) via `allowed-tools` frontmatter.
- **Dynamic Context**: Use inline bash backticks (e.g., `` `!git status` ``) to inject dynamic context into prompts.

### Must Do
- **Write Instructions FOR Claude**: Write prompts as directives _to_ the agent (e.g., "Review this code...") rather than descriptions _to_ the user.
- **Use YAML Frontmatter**: Include `description` and `argument-hint` in your `.md` files.
- **Validate Arguments**: Check for required arguments inside the prompt logic and handle missing inputs gracefully.

### Avoid
- **Chatty Prompts**: Don't waste tokens explaining what you are going to do; just provide the instructions to do it.
- **Destructive Defaults**: Avoid running destructive bash commands (delete/overwrite) without explicit user confirmation steps or validation.

```

### references/components/agents.md

```markdown
# Agents Component Reference

Plugins can provide specialized subagents for specific tasks that Claude can invoke automatically when appropriate.

**Location**: `agents/` directory in plugin root

**File format**: Markdown files describing agent capabilities

## Agent structure

```markdown
---
description: What this agent specializes in
capabilities: ["task1", "task2", "task3"]
---

# Agent Name

Detailed description of the agent's role, expertise, and when Claude should invoke it.

## Capabilities
- Specific task the agent excels at
- Another specialized capability
- When to use this agent vs others

## Context and examples
Provide examples of when this agent should be used and what kinds of problems it solves.
```

## Integration points

* Agents appear in the `/agents` interface
* Claude can invoke agents automatically based on task context
* Agents can be invoked manually by users
* Agents work alongside built-in Claude agents

## Best Practices

### Must Do
- **Concise Goal**: The goal description should be approximately 20 words or less - clear and direct.
- **Define Triggering Examples**: You **must** include 2-4 `<example>` blocks in the description showing Context, User input, and Assistant response. This is critical for the router.
- **Use Second Person**: Write system prompts addressing the agent directly ("You are an expert...", "Your responsibilities are...").
- **Define Output Format**: Clearly specify exactly how the agent should structure its final response.

### Avoid
- **First Person Prompts**: Never write "I am an agent..." in the system prompt.
- **Vague Triggers**: Avoid generic descriptions like "Helps with code." Be specific: "Use this agent when..."

## Configuration Reference

### Model Selection
- `inherit`: Default, uses parent context model
- `haiku`: Fast validation/checks
- `sonnet`: Balanced quality/speed
- `opus`: Complex reasoning

### Color Coding
- `blue`: Analysis/review
- `green`: Validation/testing
- `cyan`: Information gathering
- `yellow`: Warnings/checks
- `magenta`: Generation/creation
- `red`: Critical operations

## Common Agent Patterns

### Read-Only Agent
```yaml
name: analyzer
model: sonnet
color: blue
tools: ["Read", "Grep", "Glob"]
```

### Code Generation Agent
```yaml
name: generator
model: sonnet
color: magenta
tools: ["Read", "Write", "Edit"]
permissionMode: acceptEdits
```

### Fast Validation
```yaml
name: validator
model: haiku
color: yellow
tools: ["Read", "Bash(test:*)"]
```

```

### references/components/skills.md

```markdown
# Skills Component Reference

Plugins can provide Agent Skills that extend Claude's capabilities. Skills are model-invoked—Claude autonomously decides when to use them based on the task context.

**Location**: `skills/` directory in plugin root

**File format**: Directories containing `SKILL.md` files with frontmatter

## Skill structure

```
skills/
├── pdf-processor/
│   ├── SKILL.md
│   ├── reference.md (optional)
│   └── scripts/ (optional)
└── code-reviewer/
    └── SKILL.md
```

## Integration behavior

* Plugin Skills are automatically discovered when the plugin is installed
* Claude autonomously invokes Skills based on matching task context
* Skills can include supporting files alongside SKILL.md

## Best Practices

### Must Do
- **Use Imperative Style**: Write SKILL.md bodies using verb-first instructions ("Parse the file...", "Validate the input...") rather than "You should...".
- **Third-Person Descriptions**: Write frontmatter descriptions in the third person ("This skill should be used when...").
- **Structure Correctly**: Place the `SKILL.md` file inside a subdirectory (e.g., `skills/my-skill/SKILL.md`).

### Should Do
- **Keep Lean**: Keep SKILL.md lean (1,500-2,000 words). Move detailed docs to `references/` to save context window.
- **Configuration**: Use `user-invocable: false` for agent-only skills and `context: fork` for complex analysis to isolate context.

### Avoid
- **Monolithic Files**: Don't dump 5000+ words into `SKILL.md`. It bloats the context window.
- **Duplication**: Do not repeat information between `SKILL.md` and reference files.

```

### references/components/hooks.md

```markdown
# Hooks Component Reference

Plugins can provide event handlers that respond to Claude Code events automatically.

**Location**: `hooks/hooks.json` in plugin root, or inline in plugin.json

**Format**: JSON configuration with event matchers and actions

## Hook configuration

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format-code.sh"
          }
        ]
      }
    ]
  }
}
```

## Available events

* `PreToolUse`: Before Claude uses any tool
* `PostToolUse`: After Claude successfully uses any tool
* `PostToolUseFailure`: After Claude tool execution fails
* `PermissionRequest`: When a permission dialog is shown
* `UserPromptSubmit`: When user submits a prompt
* `Notification`: When Claude Code sends notifications
* `Stop`: When Claude attempts to stop
* `SubagentStart`: When a subagent is started
* `SubagentStop`: When a subagent attempts to stop
* `SessionStart`: At the beginning of sessions
* `SessionEnd`: At the end of sessions
* `PreCompact`: Before conversation history is compacted

## Hook types

* `command`: Execute shell commands or scripts
* `prompt`: Evaluate a prompt with an LLM (uses `$ARGUMENTS` placeholder for context)
* `agent`: Run an agentic verifier with tools for complex verification tasks

## Best Practices

### Must Do
- **Validate Inputs**: In bash hooks, strictly validate all JSON inputs and sanitize variables to prevent injection.
- **Quote Variables**: Always quote bash variables (e.g., `"$CLAUDE_PROJECT_DIR"`) to handle spaces in paths.
- **Return Valid JSON**: Ensure your hooks output valid JSON structures for decisions (`allow`/`deny`) and messages.

### Avoid
- **Blocking Errors**: Avoid returning exit code `2` (Blocking Error) unless the operation is critical and must be stopped. Use `1` (Non-blocking) or `0` (Success) otherwise.
- **Modifying Global State**: Avoid hooks that change the environment unexpectedly, as execution order is not guaranteed.

## Implementation Reference

### Exit Codes
- `0`: Success (use JSON output for allow/deny)
- `1`: Non-blocking error (allow, log warning)
- `2`: Blocking error (deny operation)

### Bash Hook Template
```bash
#!/bin/bash
INPUT=$(cat)

# Validate JSON
if ! echo "$INPUT" | jq . >/dev/null 2>&1; then
  echo '{"allow": true, "message": "Invalid input"}'
  exit 1
fi

# Extract and validate
TOOL=$(echo "$INPUT" | jq -r '.toolName // empty')
if [ -z "$TOOL" ]; then
  echo '{"allow": true, "message": "Missing tool"}'
  exit 1
fi

# Perform check
if [[ condition ]]; then
  echo '{"allow": false, "message": "⚠️ Denied"}'
  exit 0
fi

echo '{"allow": true}'
exit 0
```

```

### references/components/mcp-servers.md

```markdown
# MCP Servers Component Reference

Plugins can bundle Model Context Protocol (MCP) servers to connect Claude Code with external tools and services.

**Location**: `.mcp.json` in plugin root, or inline in plugin.json

**Format**: Standard MCP server configuration

## MCP server configuration

```json
{
  "mcpServers": {
    "plugin-database": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
      "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
      "env": {
        "DB_PATH": "${CLAUDE_PLUGIN_ROOT}/data"
      }
    },
    "plugin-api-client": {
      "command": "npx",
      "args": ["@company/mcp-server", "--plugin-mode"],
      "cwd": "${CLAUDE_PLUGIN_ROOT}"
    }
  }
}
```

## Integration behavior

* Plugin MCP servers start automatically when the plugin is enabled
* Servers appear as standard MCP tools in Claude's toolkit
* Server capabilities integrate seamlessly with Claude's existing tools
* Plugin servers can be configured independently of user MCP servers

```

### references/mcp-patterns.md

```markdown
# MCP Integration Patterns

Best practices for integrating Model Context Protocol servers in plugins.

## Configuration Options

### Standalone .mcp.json (Recommended)
```json
{
  "server-name": {
    "type": "stdio|http|sse",
    "command": "executable",
    "args": ["arg1", "arg2"],
    "env": {
      "VAR": "${ENV_VAR}"
    }
  }
}
```

### Embedded in plugin.json
```json
{
  "name": "plugin-name",
  "mcpServers": {
    "server-name": {
      "type": "stdio",
      "command": "executable"
    }
  }
}
```

## Transport Types

### stdio - Local CLI Tools
Best for: git, docker, npm, local scripts

```json
{
  "github": {
    "type": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": {
      "GITHUB_TOKEN": "${GITHUB_TOKEN}"
    }
  }
}
```

### http - Remote APIs
Best for: SaaS services, cloud APIs

```json
{
  "api-service": {
    "type": "http",
    "url": "https://api.example.com/mcp",
    "headers": {
      "Authorization": "Bearer ${API_TOKEN}"
    }
  }
}
```

### sse - Real-time Streaming
Best for: monitoring, live updates

```json
{
  "monitoring": {
    "type": "sse",
    "url": "https://monitor.example.com/stream",
    "headers": {
      "X-API-Key": "${MONITOR_KEY}"
    }
  }
}
```

## Common Integration Patterns

### GitHub
```json
{
  "github": {
    "type": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": {"GITHUB_TOKEN": "${GITHUB_TOKEN}"}
  }
}
```

### Database
```json
{
  "postgres": {
    "type": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-postgres"],
    "env": {"POSTGRES_URL": "${DATABASE_URL}"}
  }
}
```

### Kubernetes
```json
{
  "kubectl": {
    "type": "stdio",
    "command": "mcp-kubectl-wrapper",
    "args": ["--namespace", "${K8S_NAMESPACE}"],
    "env": {"KUBECONFIG": "${KUBECONFIG_PATH}"}
  }
}
```

## Best Practices

### Security
- **Never hardcode secrets** - always use `${ENV_VAR}` syntax
- Use minimal permission scopes for tokens
- Document required environment variables in README
- Provide `.env.example` template

### Environment Variables
```json
{
  "database": {
    "type": "http",
    "url": "${DB_URL}",
    "headers": {
      "Authorization": "Bearer ${DB_TOKEN}",
      "X-Project": "${PROJECT_ID}"
    }
  }
}
```

### Development
- Test stdio locally before deploying http/sse
- Use `.env.example` to document required vars
- Test MCP integration independently
- Provide clear error messages

### Performance
- Use http for remote services (avoids process overhead)
- Set reasonable timeouts
- Implement caching where appropriate
- Clean up resources on shutdown

## Validation Checklist

**Configuration:**
- [ ] Valid JSON syntax
- [ ] Required fields present (type, command/url)
- [ ] Transport type: stdio, http, or sse
- [ ] Server names use kebab-case

**Security:**
- [ ] No hardcoded secrets/API keys
- [ ] All credentials use ${ENV_VAR}
- [ ] Environment variables documented
- [ ] .env.example provided

**Functionality:**
- [ ] Server executable/URL accessible
- [ ] Required env vars available
- [ ] Transport matches server capabilities
- [ ] Headers/auth properly configured

## Troubleshooting

| Issue | Fix |
|-------|-----|
| Server not found | Verify command in PATH, check network for npx |
| Auth failures | Check env vars set, verify token permissions |
| Timeouts | Verify URL accessible, check firewall |
| Invalid config | Validate JSON, ensure required fields present |

```

### references/components/lsp-servers.md

```markdown
# LSP Servers Component Reference

> **Tip**: Looking to use LSP plugins? Install them from the official marketplace—search for "lsp" in the `/plugin` Discover tab. This section documents how to create LSP plugins for languages not covered by the official marketplace.

Plugins can provide [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) (LSP) servers to give Claude real-time code intelligence while working on your codebase.

LSP integration provides:

* **Instant diagnostics**: Claude sees errors and warnings immediately after each edit
* **Code navigation**: go to definition, find references, and hover information
* **Language awareness**: type information and documentation for code symbols

**Location**: `.lsp.json` in plugin root, or inline in `plugin.json`

**Format**: JSON configuration mapping language server names to their configurations

## `.lsp.json` file format

```json
{
  "go": {
    "command": "gopls",
    "args": ["serve"],
    "extensionToLanguage": {
      ".go": "go"
    }
  }
}
```

## Inline in `plugin.json`

```json
{
  "name": "my-plugin",
  "lspServers": {
    "go": {
      "command": "gopls",
      "args": ["serve"],
      "extensionToLanguage": {
        ".go": "go"
      }
    }
  }
}
```

## Required fields

| Field                 | Description                                  |
| :-------------------- | :------------------------------------------- |
| `command`             | The LSP binary to execute (must be in PATH)  |
| `extensionToLanguage` | Maps file extensions to language identifiers |

## Optional fields

| Field                   | Description                                               |
| :---------------------- | :-------------------------------------------------------- |
| `args`                  | Command-line arguments for the LSP server                 |
| `transport`             | Communication transport: `stdio` (default) or `socket`    |
| `env`                   | Environment variables to set when starting the server     |
| `initializationOptions` | Options passed to the server during initialization        |
| `settings`              | Settings passed via `workspace/didChangeConfiguration`    |
| `workspaceFolder`       | Workspace folder path for the server                      |
| `startupTimeout`        | Max time to wait for server startup (milliseconds)        |
| `shutdownTimeout`       | Max time to wait for graceful shutdown (milliseconds)     |
| `restartOnCrash`        | Whether to automatically restart the server if it crashes |
| `maxRestarts`           | Maximum number of restart attempts before giving up       |

> **Warning**: **You must install the language server binary separately.** LSP plugins configure how Claude Code connects to a language server, but they don't include the server itself. If you see `Executable not found in $PATH` in the `/plugin` Errors tab, install the required binary for your language.

## Available LSP plugins

| Plugin           | Language server            | Install command                                                                            |
| :--------------- | :------------------------- | :----------------------------------------------------------------------------------------- |
| `pyright-lsp`    | Pyright (Python)           | `pip install pyright` or `npm install -g pyright`                                          |
| `typescript-lsp` | TypeScript Language Server | `npm install -g typescript-language-server typescript`                                     |
| `rust-lsp`       | rust-analyzer              | [See rust-analyzer installation](https://rust-analyzer.github.io/manual.html#installation) |

Install the language server first, then install the plugin from the marketplace.

```

### references/tool-invocations.md

```markdown
# Tool Invocation Patterns

Best practices for referencing tools in plugin components.

## Core Principle

**Implicit Tool Usage**: Core file operations (Read, Write, Glob, Grep, Edit) should be described implicitly. Claude automatically infers the correct tool from context.

## Tool Invocation Rules

### Implicit (Describe Action Directly)

**Core File Operations:**
- Read, Write, Glob, Grep, Edit
- Bash (describe commands: "Run `git status`")
- Task (describe agent launch: "Launch code-reviewer agent")

```markdown
# Good Examples
Find all plugin files matching `**/*.md`
Read each file and extract frontmatter
Search for "TODO" patterns in the codebase
Run `git status` to check changes
Launch the validator agent to check compliance
```

### Explicit (State Tool Name)

**Workflow & External Tools:**
- Skill: "**Load X skill** using the Skill tool"
- AskUserQuestion: "Use AskUserQuestion tool to confirm"
- TodoWrite: "**Use TodoWrite tool** to track progress"
- WebFetch, WebSearch: "Use WebFetch tool to read docs"

```markdown
# Good Examples
**Load the hookify:writing-rules skill** using the Skill tool
Use AskUserQuestion tool to let user select options
**Use TodoWrite tool** to track validation progress
Use WebFetch tool to read official documentation
```

## In allowed-tools Configuration

Always use array syntax with filters for Bash:

```yaml
# Commands/Agents frontmatter
allowed-tools: ["Read", "Glob", "Grep", "Bash(git:*)"]

# Common filters
Bash(git:*)           # Git commands only
Bash(npm:*)           # NPM commands only
Bash(gh pr:*)         # GitHub PR commands only
```

**Never use bare `Bash`** - always specify command filters.

## Inline Bash Execution

In command files, use inline syntax for dynamic context:

```markdown
Current branch: !`git branch --show-current`
Modified files: !`git diff --name-only`
```

Format: `!`command`` (exclamation + backtick + command + backtick)

## Anti-Patterns to Avoid

```markdown
# Bad - Explicit tool calls for core operations
Use Glob tool to find files
Use Read tool to read each file
Use Bash tool to run git status
Use Task tool to launch validator agent

# Good - Implicit descriptions
Find files matching the pattern
Read each file and extract data
Run `git status` to check changes
Launch the validator agent
```

## Quick Reference

| Tool | Style | Example |
|------|-------|---------|
| Read, Write, Edit, Glob, Grep | Implicit | "Find files matching...", "Read the file..." |
| Bash | Implicit | "Run `git status`", "Check with `npm test`" |
| Task | Implicit | "Launch X agent", "Use a Haiku agent to..." |
| Skill | **Explicit** | "**Load X skill** using the Skill tool" |
| TodoWrite | **Explicit** | "**Use TodoWrite tool** to track progress" |
| AskUserQuestion | Explicit | "Use AskUserQuestion tool to confirm" |
| WebFetch/WebSearch | Explicit | "Use WebFetch tool to read docs" |

```

### references/debugging.md

```markdown
# Debugging and Development Tools

## Debugging commands

Use `claude --debug` to see plugin loading details:

```bash
claude --debug
```

This shows:

* Which plugins are being loaded
* Any errors in plugin manifests
* Command, agent, and hook registration
* MCP server initialization

## Common issues

| Issue                               | Cause                           | Solution                                                                          |
| :---------------------------------- | :------------------------------ | :-------------------------------------------------------------------------------- |
| Plugin not loading                  | Invalid `plugin.json`           | Validate JSON syntax with `claude plugin validate` or `/plugin validate`          |
| Commands not appearing              | Wrong directory structure       | Ensure `commands/` at root, not in `.claude-plugin/`                              |
| Hooks not firing                    | Script not executable           | Run `chmod +x script.sh`                                                          |
| MCP server fails                    | Missing `${CLAUDE_PLUGIN_ROOT}` | Use variable for all plugin paths                                                 |
| Path errors                         | Absolute paths used             | All paths must be relative and start with `./`                                    |
| LSP `Executable not found in $PATH` | Language server not installed   | Install the binary (e.g., `npm install -g typescript-language-server typescript`) |

## Example error messages

**Manifest validation errors**:

* `Invalid JSON syntax: Unexpected token } in JSON at position 142`: check for missing commas, extra commas, or unquoted strings
* `Plugin has an invalid manifest file at .claude-plugin/plugin.json. Validation errors: name: Required`: a required field is missing
* `Plugin has a corrupt manifest file at .claude-plugin/plugin.json. JSON parse error: ...`: JSON syntax error

**Plugin loading errors**:

* `Warning: No commands found in plugin my-plugin custom directory: ./cmds. Expected .md files or SKILL.md in subdirectories.`: command path exists but contains no valid command files
* `Plugin directory not found at path: ./plugins/my-plugin. Check that the marketplace entry has the correct path.`: the `source` path in marketplace.json points to a non-existent directory
* `Plugin my-plugin has conflicting manifests: both plugin.json and marketplace entry specify components.`: remove duplicate component definitions or set `strict: true` in marketplace entry

## Hook troubleshooting

**Hook script not executing**:

1. Check the script is executable: `chmod +x ./scripts/your-script.sh`
2. Verify the shebang line: First line should be `#!/bin/bash` or `#!/usr/bin/env bash`
3. Check the path uses `${CLAUDE_PLUGIN_ROOT}`: `"command": "${CLAUDE_PLUGIN_ROOT}/scripts/your-script.sh"`
4. Test the script manually: `./scripts/your-script.sh`

**Hook not triggering on expected events**:

1. Verify the event name is correct (case-sensitive): `PostToolUse`, not `postToolUse`
2. Check the matcher pattern matches your tools: `"matcher": "Write|Edit"` for file operations
3. Confirm the hook type is valid: `command`, `prompt`, or `agent`

## MCP server troubleshooting

**Server not starting**:

1. Check the command exists and is executable
2. Verify all paths use `${CLAUDE_PLUGIN_ROOT}` variable
3. Check the MCP server logs: `claude --debug` shows initialization errors
4. Test the server manually outside of Claude Code

**Server tools not appearing**:

1. Ensure the server is properly configured in `.mcp.json` or `plugin.json`
2. Verify the server implements the MCP protocol correctly
3. Check for connection timeouts in debug output

## Directory structure mistakes

**Symptoms**: Plugin loads but components (commands, agents, hooks) are missing.

**Correct structure**: Components must be at the plugin root, not inside `.claude-plugin/`. Only `plugin.json` belongs in `.claude-plugin/`.

```
my-plugin/
├── .claude-plugin/
│   └── plugin.json      ← Only manifest here
├── commands/            ← At root level
├── agents/              ← At root level
└── hooks/               ← At root level
```

If your components are inside `.claude-plugin/`, move them to the plugin root.

**Debug checklist**:

1. Run `claude --debug` and look for "loading plugin" messages
2. Check that each component directory is listed in the debug output
3. Verify file permissions allow reading the plugin files

## Distribution and versioning reference

### Version management

Follow semantic versioning for plugin releases:

```json
{
  "name": "my-plugin",
  "version": "2.1.0"
}
```

**Version format**: `MAJOR.MINOR.PATCH`

* **MAJOR**: Breaking changes (incompatible API changes)
* **MINOR**: New features (backward-compatible additions)
* **PATCH**: Bug fixes (backward-compatible fixes)

**Best practices**:

* Start at `1.0.0` for your first stable release
* Update the version in `plugin.json` before distributing changes
* Document changes in a `CHANGELOG.md` file
* Use pre-release versions like `2.0.0-beta.1` for testing

```

### references/cli-commands.md

```markdown
# CLI Commands Reference

Claude Code provides CLI commands for non-interactive plugin management, useful for scripting and automation.

## plugin install

Install a plugin from available marketplaces.

```bash
claude plugin install <plugin> [options]
```

**Arguments:**

* `<plugin>`: Plugin name or `plugin-name@marketplace-name` for a specific marketplace

**Options:**

| Option                | Description                                       | Default |
| :-------------------- | :------------------------------------------------ | :------ |
| `-s, --scope <scope>` | Installation scope: `user`, `project`, or `local` | `user`  |
| `-h, --help`          | Display help for command                          |         |

**Examples:**

```bash
# Install to user scope (default)
claude plugin install formatter@my-marketplace

# Install to project scope (shared with team)
claude plugin install formatter@my-marketplace --scope project

# Install to local scope (gitignored)
claude plugin install formatter@my-marketplace --scope local
```

## plugin uninstall

Remove an installed plugin.

```bash
claude plugin uninstall <plugin> [options]
```

**Arguments:**

* `<plugin>`: Plugin name or `plugin-name@marketplace-name`

**Options:**

| Option                | Description                                         | Default |
| :-------------------- | :-------------------------------------------------- | :------ |
| `-s, --scope <scope>` | Uninstall from scope: `user`, `project`, or `local` | `user`  |
| `-h, --help`          | Display help for command                            |         |

**Aliases:** `remove`, `rm`

## plugin enable

Enable a disabled plugin.

```bash
claude plugin enable <plugin> [options]
```

**Arguments:**

* `<plugin>`: Plugin name or `plugin-name@marketplace-name`

**Options:**

| Option                | Description                                    | Default |
| :-------------------- | :--------------------------------------------- | :------ |
| `-s, --scope <scope>` | Scope to enable: `user`, `project`, or `local` | `user`  |
| `-h, --help`          | Display help for command                       |         |

## plugin disable

Disable a plugin without uninstalling it.

```bash
claude plugin disable <plugin> [options]
```

**Arguments:**

* `<plugin>`: Plugin name or `plugin-name@marketplace-name`

**Options:**

| Option                | Description                                     | Default |
| :-------------------- | :---------------------------------------------- | :------ |
| `-s, --scope <scope>` | Scope to disable: `user`, `project`, or `local` | `user`  |
| `-h, --help`          | Display help for command                        |         |

## plugin update

Update a plugin to the latest version.

```bash
claude plugin update <plugin> [options]
```

**Arguments:**

* `<plugin>`: Plugin name or `plugin-name@marketplace-name`

**Options:**

| Option                | Description                                               | Default |
| :-------------------- | :-------------------------------------------------------- | :------ |
| `-s, --scope <scope>` | Scope to update: `user`, `project`, `local`, or `managed` | `user`  |
| `-h, --help`          | Display help for command                                  |         |

```

### references/todowrite-usage.md

```markdown
# TodoWrite Tool Usage Standards

Best practices for using the TodoWrite tool in plugin components.

## When to Use

**Use TodoWrite for:**
- Tasks with 3+ distinct steps
- Multi-file/multi-component work
- Sequential dependencies
- User progress visibility needs

**Don't use for:**
- Single file edits
- 1-2 step operations
- Pure research/reading
- Conversational responses

## Core Requirements

### 1. Dual Form Naming

Every task needs both forms:

```json
{
  "content": "Run tests",           // Imperative: what to do
  "activeForm": "Running tests",    // Continuous: doing it now
  "status": "in_progress"
}
```

### 2. Real-time Updates

- Mark `in_progress` BEFORE starting work
- Mark `completed` IMMEDIATELY after finishing
- Never batch updates

### 3. Single Active Task

Exactly ONE task as `in_progress` at any time.

### 4. Honest Status

Only mark `completed` when FULLY done. If blocked/failed, keep as `in_progress` and create new task for resolution.

## Task Structure

```json
{
  "content": "Imperative verb-first form",
  "activeForm": "Present continuous -ing form",
  "status": "pending|in_progress|completed"
}
```

## Good Examples

### Multi-Step Plugin Creation

```json
[
  {
    "content": "Create plugin manifest and directory structure",
    "activeForm": "Creating plugin manifest and directory structure",
    "status": "in_progress"
  },
  {
    "content": "Implement command with frontmatter",
    "activeForm": "Implementing command with frontmatter",
    "status": "pending"
  },
  {
    "content": "Validate plugin structure",
    "activeForm": "Validating plugin structure",
    "status": "pending"
  }
]
```

### Single File Edit

Don't use TodoWrite - just do it:
- "Fix typo in README.md"
- "Add missing description field"
- "Update version number"

## Common Mistakes

**Wrong:** Missing activeForm
```json
{"content": "Run tests", "status": "in_progress"}
```

**Right:** Both forms present
```json
{
  "content": "Run tests",
  "activeForm": "Running tests",
  "status": "in_progress"
}
```

**Wrong:** Multiple in_progress
```json
[
  {"content": "Task 1", "status": "in_progress"},
  {"content": "Task 2", "status": "in_progress"}
]
```

**Right:** Only one in_progress
```json
[
  {"content": "Task 1", "status": "completed"},
  {"content": "Task 2", "status": "in_progress"}
]
```

**Wrong:** Batched updates (do Task 1, Task 2, Task 3, then update all)

**Right:** Sequential updates (do Task 1, mark complete, do Task 2, mark complete...)

## In Plugin Components

### Commands

```markdown
**Use TodoWrite tool** to track the following phases:
1. Scan plugin structure
2. Validate components
3. Generate report
```

### Agents

```markdown
**Use TodoWrite tool** at the start to create tasks for multi-step workflows.
Mark each task as in_progress before starting, completed immediately after finishing.
```

## Quick Decision Tree

```mermaid
flowchart TD
    A[Is this 3+ steps?] -->|NO| B[Don't use TodoWrite]
    A -->|YES| C[Multiple files?]
    C -->|NO| D[Probably don't need TodoWrite]
    C -->|YES| E[Dependencies?]
    E -->|NO| F[Maybe don't need TodoWrite]
    E -->|YES| G[USE TodoWrite]
```

```

plugin-best-practices | SkillHub