📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,502 @@
|
||||
# Plugin Structure Reference
|
||||
|
||||
Complete directory layout and configuration schemas for Claude Code plugins.
|
||||
|
||||
## Plugin Structure
|
||||
|
||||
How you structure plugins depends on how they're distributed.
|
||||
|
||||
### Single Plugin (Standalone)
|
||||
|
||||
Standalone plugins need their own `.claude-plugin/plugin.json`:
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Plugin manifest (required)
|
||||
├── commands/
|
||||
├── agents/
|
||||
├── hooks/
|
||||
│ └── hooks.json # Auto-discovered hooks (or inline in plugin.json)
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Marketplace with Local Plugins (Consolidated)
|
||||
|
||||
When all plugins live in the same repo as the marketplace, use `strict: false` to consolidate metadata in `marketplace.json`. Plugins don't need their own manifests:
|
||||
|
||||
```
|
||||
my-marketplace/
|
||||
├── .claude-plugin/
|
||||
│ └── marketplace.json # All metadata here (strict: false)
|
||||
├── plugin-a/
|
||||
│ ├── commands/
|
||||
│ ├── agents/
|
||||
│ └── README.md
|
||||
├── plugin-b/
|
||||
│ ├── skills/
|
||||
│ └── README.md
|
||||
└── README.md
|
||||
```
|
||||
|
||||
**Benefits:** Single source of truth, no version drift, simpler structure.
|
||||
|
||||
### Marketplace with External Plugins (Distributed)
|
||||
|
||||
When referencing plugins from external repos (GitHub, GitLab, etc.), let each plugin own its manifest:
|
||||
|
||||
```
|
||||
my-marketplace/
|
||||
├── .claude-plugin/
|
||||
│ └── marketplace.json # Points to external repos
|
||||
└── README.md
|
||||
|
||||
# External repos each have:
|
||||
external-plugin/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Plugin owns its manifest
|
||||
├── commands/
|
||||
└── README.md
|
||||
```
|
||||
|
||||
**Key principle:** External plugins are self-contained. The marketplace.json points to them via `source` but doesn't define their metadata.
|
||||
|
||||
### Mixed Approach
|
||||
|
||||
Marketplaces can combine both patterns—consolidated for local plugins, distributed for external:
|
||||
|
||||
```json
|
||||
{
|
||||
"strict": false,
|
||||
"plugins": [
|
||||
{"name": "local-plugin", "source": "./local-plugin", "version": "1.0.0"},
|
||||
{"name": "external-plugin", "source": {"source": "github", "repo": "owner/plugin"}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Directory Structure
|
||||
|
||||
### Minimal Standalone Plugin
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Required: metadata
|
||||
└── README.md # Required for distribution
|
||||
```
|
||||
|
||||
### Complete Standalone Plugin
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Plugin metadata
|
||||
├── README.md # Documentation
|
||||
├── CHANGELOG.md # Version history
|
||||
├── LICENSE # License file
|
||||
├── .gitignore # Git ignore patterns
|
||||
├── commands/ # Slash commands
|
||||
│ ├── core/ # Core commands
|
||||
│ │ └── help.md
|
||||
│ └── advanced/ # Advanced features
|
||||
│ └── deploy.md
|
||||
├── agents/ # Custom agents
|
||||
│ ├── reviewer.md
|
||||
│ └── analyzer.md
|
||||
├── skills/ # Reusable skills
|
||||
│ └── my-skill/
|
||||
│ └── SKILL.md
|
||||
├── hooks/ # Event hooks
|
||||
│ └── hooks.json # Auto-discovered (required format)
|
||||
├── servers/ # MCP servers
|
||||
│ └── my-server/
|
||||
│ ├── server.py
|
||||
│ └── pyproject.toml
|
||||
└── scripts/ # Utility scripts
|
||||
└── setup.sh
|
||||
```
|
||||
|
||||
## plugin.json Schema
|
||||
|
||||
### Required Fields
|
||||
|
||||
| Field | Type | Description | Example |
|
||||
|-------|------|-------------|---------|
|
||||
| `name` | string | Unique identifier (kebab-case, no spaces) | `"deployment-tools"` |
|
||||
|
||||
### Recommended Metadata Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `version` | string | Semantic version (e.g., "1.0.0") |
|
||||
| `description` | string | Brief plugin description |
|
||||
|
||||
### Optional Standard Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `author` | object | Creator information |
|
||||
| `author.name` | string | Author name |
|
||||
| `author.email` | string | Author email |
|
||||
| `homepage` | string | Documentation URL |
|
||||
| `repository` | string | Source code URL |
|
||||
| `license` | string | SPDX identifier (MIT, Apache-2.0) |
|
||||
| `keywords` | array | Search tags |
|
||||
| `category` | string | Plugin category |
|
||||
| `tags` | array | Additional searchability tags |
|
||||
|
||||
### Component Configuration Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `commands` | string\|array | Custom paths to command files or directories |
|
||||
| `agents` | string\|array | Custom paths to agent files |
|
||||
| `hooks` | string\|object | Hook config path or inline config |
|
||||
| `mcpServers` | string\|object | MCP config path or inline config |
|
||||
| `lspServers` | string\|object | LSP config path or inline config |
|
||||
|
||||
### Behavior Control
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `strict` | boolean | `true` | Set at marketplace level. When `false`, local plugins don't need `.claude-plugin/plugin.json`—marketplace defines all metadata. Use `false` for consolidated local plugins, `true` (or omit) for external plugins. |
|
||||
|
||||
> **Note:** Hooks can be defined inline in plugin.json OR in a separate `hooks/hooks.json` file.
|
||||
|
||||
### Complete Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "enterprise-tools",
|
||||
"version": "2.1.0",
|
||||
"description": "Enterprise workflow automation tools",
|
||||
"author": {
|
||||
"name": "Enterprise Team",
|
||||
"email": "team@company.com"
|
||||
},
|
||||
"homepage": "https://docs.company.com/plugins",
|
||||
"repository": "https://github.com/company/enterprise-tools",
|
||||
"license": "MIT",
|
||||
"keywords": ["enterprise", "workflow", "automation"],
|
||||
"category": "productivity",
|
||||
"commands": [
|
||||
"./commands/core/",
|
||||
"./commands/enterprise/"
|
||||
],
|
||||
"agents": [
|
||||
"./agents/security-reviewer.md",
|
||||
"./agents/compliance-checker.md"
|
||||
],
|
||||
"mcpServers": {
|
||||
"database": {
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
|
||||
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
|
||||
"env": {
|
||||
"DB_HOST": "${DATABASE_HOST}",
|
||||
"DB_PASSWORD": "${DATABASE_PASSWORD}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** Hooks can be inlined in plugin.json (add a `"hooks"` key) or defined in `hooks/hooks.json`. See [Event Hooks](#event-hooks) below.
|
||||
|
||||
## Slash Commands
|
||||
|
||||
### Command File Structure
|
||||
|
||||
Commands are markdown files with YAML frontmatter in `commands/`.
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: "Brief description shown in /help"
|
||||
---
|
||||
|
||||
Command instructions here.
|
||||
Use {{0}}, {{1}} for parameters.
|
||||
```
|
||||
|
||||
### Parameter Syntax
|
||||
|
||||
| Syntax | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `{{0}}` | First parameter | `/cmd value` |
|
||||
| `{{1}}` | Second parameter | `/cmd val1 val2` |
|
||||
| `{{0:name}}` | Named (documentation) | `{{0:environment}}` |
|
||||
| `{{...}}` | All remaining | `/cmd arg1 arg2 arg3` |
|
||||
|
||||
### Example Command
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: "Deploy to specified environment"
|
||||
---
|
||||
|
||||
Deploy application to {{0:environment}}.
|
||||
|
||||
Steps:
|
||||
1. Validate environment configuration
|
||||
2. Run pre-deployment checks
|
||||
3. Deploy application
|
||||
4. Verify deployment
|
||||
```
|
||||
|
||||
## Custom Agents
|
||||
|
||||
### Agent File Structure
|
||||
|
||||
Agents are markdown files with YAML frontmatter in `agents/`.
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: "What this agent specializes in"
|
||||
capabilities: ["task1", "task2", "task3"]
|
||||
allowed-tools: Read, Grep, Glob
|
||||
---
|
||||
|
||||
# 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.
|
||||
```
|
||||
|
||||
### Agent Frontmatter Fields
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `description` | string | Brief explanation of what the agent does |
|
||||
| `capabilities` | array | List of tasks the agent can perform (aids discovery) |
|
||||
| `allowed-tools` | string | Comma-separated list of allowed tools (optional) |
|
||||
|
||||
### Tool Restrictions
|
||||
|
||||
| Restriction | Tools | Use Case |
|
||||
|-------------|-------|----------|
|
||||
| Read-only | `Read, Grep, Glob` | Analysis only |
|
||||
| With execution | `Read, Grep, Glob, Bash` | Analysis + commands |
|
||||
| No restriction | (omit field) | Full capabilities |
|
||||
|
||||
## Event Hooks
|
||||
|
||||
Two ways to define hooks in a plugin:
|
||||
|
||||
1. **Inline in plugin.json** — Add a `"hooks"` key directly
|
||||
2. **File-based** — Auto-discovered from `hooks/hooks.json`
|
||||
|
||||
### Option 1: Inline in plugin.json
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"version": "1.0.0",
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option 2: Separate hooks.json File
|
||||
|
||||
```
|
||||
my-plugin/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json # Can also have hooks inline here
|
||||
└── hooks/
|
||||
└── hooks.json # Auto-discovered if present
|
||||
```
|
||||
|
||||
### Hook Types
|
||||
|
||||
| Type | When | Use Cases |
|
||||
|------|------|-----------|
|
||||
| `PreToolUse` | Before tool | Validation, permissions |
|
||||
| `PostToolUse` | After tool | Logging, formatting |
|
||||
| `UserPromptSubmit` | Before prompt | Input validation |
|
||||
| `Stop` | After response | Cleanup, notifications |
|
||||
| `SessionStart` | Session begins | Context loading |
|
||||
| `SessionEnd` | Session ends | Cleanup |
|
||||
|
||||
### hooks/hooks.json Format
|
||||
|
||||
When using a separate file, it requires a root-level `"hooks"` wrapper:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/validate.sh",
|
||||
"timeout": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write(*.ts)",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "biome check --write \"$file\"",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Key Points
|
||||
|
||||
- Hooks can be inline in plugin.json OR in `hooks/hooks.json`
|
||||
- Both formats use a `"hooks"` object containing event types
|
||||
- Use `${CLAUDE_PLUGIN_ROOT}` for paths relative to plugin
|
||||
- Use `$file` for the affected file path in PostToolUse
|
||||
|
||||
### Hook Script Interface
|
||||
|
||||
**Input (stdin):**
|
||||
|
||||
```json
|
||||
{
|
||||
"session_id": "abc123",
|
||||
"transcript_path": "/path/to/transcript.jsonl",
|
||||
"cwd": "/current/working/directory",
|
||||
"hook_event_name": "PreToolUse",
|
||||
"tool_name": "Write",
|
||||
"tool_input": {
|
||||
"file_path": "/project/src/file.ts",
|
||||
"content": "export const foo = 'bar';"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Output (stdout):**
|
||||
|
||||
Allow:
|
||||
|
||||
```json
|
||||
{"allowed": true}
|
||||
```
|
||||
|
||||
Block:
|
||||
|
||||
```json
|
||||
{
|
||||
"allowed": false,
|
||||
"message": "Validation failed: reason"
|
||||
}
|
||||
```
|
||||
|
||||
Modify:
|
||||
|
||||
```json
|
||||
{
|
||||
"allowed": true,
|
||||
"modified_parameters": {
|
||||
"content": "modified content"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example Hook Script
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
input=$(cat)
|
||||
|
||||
file_path=$(echo "$input" | jq -r '.tool_input.file_path')
|
||||
content=$(echo "$input" | jq -r '.tool_input.content')
|
||||
|
||||
# Check for secrets
|
||||
if echo "$content" | grep -qiE 'api[_-]?key.*=.*[a-zA-Z0-9]{16,}'; then
|
||||
echo '{"allowed": false, "message": "Potential secret detected"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo '{"allowed": true}'
|
||||
```
|
||||
|
||||
## MCP Servers
|
||||
|
||||
### Server Configuration
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"server-name": {
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/servers/my-server",
|
||||
"args": ["--flag", "value"],
|
||||
"env": {
|
||||
"API_KEY": "${MY_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Variable Substitution
|
||||
|
||||
| Variable | Resolves To |
|
||||
|----------|-------------|
|
||||
| `${CLAUDE_PLUGIN_ROOT}` | Plugin installation directory |
|
||||
| `${VAR_NAME}` | Environment variable |
|
||||
|
||||
### Python MCP Server Example
|
||||
|
||||
```python
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
mcp = FastMCP("my-server")
|
||||
|
||||
@mcp.tool()
|
||||
async def my_tool(param: str) -> str:
|
||||
"""Tool description"""
|
||||
return f"Result: {param}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
mcp.run(transport='stdio')
|
||||
```
|
||||
|
||||
## Platform Considerations
|
||||
|
||||
### macOS
|
||||
|
||||
- Config: `~/Library/Application Support/Claude/`
|
||||
- Logs: `~/Library/Logs/Claude/`
|
||||
|
||||
### Windows
|
||||
|
||||
- Config: `%APPDATA%\Claude\`
|
||||
- Use forward slashes or double backslashes
|
||||
|
||||
### Linux
|
||||
|
||||
- Config: `~/.config/claude/`
|
||||
- Check shebang and permissions
|
||||
Reference in New Issue
Block a user