Claude Marketplace¶
The Claude Code Official Marketplace hosts community plugins for Claude Code.
Repository Structure¶
anthropics/claude-plugins-official/
├── official_plugins/ # Anthropic-maintained plugins
└── external_plugins/ # Community plugins
└── your-plugin/
├── .claude-plugin/
│ └── plugin.json # Consolidated config (MCP + hooks embedded)
├── commands/ # Optional: Slash commands
├── skills/ # Optional: Skills
├── agents/ # Optional: Agents
└── README.md # Required: Documentation
Requirements¶
Your plugin must have:
.claude-plugin/plugin.json- Plugin manifest (with embedded MCP and hooks)README.md- Documentation
Generating with Bundle API¶
Use the assistantkit bundle package to generate properly formatted plugin files:
package main
import (
"log"
"github.com/agentplexus/assistantkit/bundle"
"github.com/agentplexus/assistantkit/hooks/core"
)
func main() {
// Create bundle
b := bundle.New("my-plugin", "1.0.0", "A helpful plugin")
b.Plugin.Author = "Your Name"
b.Plugin.License = "MIT"
b.Plugin.Repository = "https://github.com/yourname/my-plugin"
// Add MCP server
b.AddMCPServer("my-server", bundle.MCPServer{
Command: "./my-server",
Env: map[string]string{
"API_KEY": "${MY_API_KEY}",
},
})
// Add hooks
cfg := bundle.NewHooksConfig()
cfg.AddHook(core.OnStop, core.Hook{
Type: "prompt",
Prompt: "Task stopped. Consider follow-up actions.",
})
b.SetHooks(cfg)
// Add skill
skill := bundle.NewSkill("my-skill", "Skill description")
skill.Instructions = "# My Skill\n\nInstructions here..."
b.AddSkill(skill)
// Add command
cmd := bundle.NewCommand("my-cmd", "Command description")
cmd.Instructions = "Command instructions..."
b.AddCommand(cmd)
// Generate for Claude Code
if err := b.Generate("claude", "./output"); err != nil {
log.Fatalf("Generate failed: %v", err)
}
}
This generates:
output/
├── .claude-plugin/
│ └── plugin.json # Consolidated with MCP + hooks embedded
├── commands/
│ └── my-cmd.md
└── skills/
└── my-skill/
└── SKILL.md
Manual Submission¶
1. Fork the Repository¶
Fork anthropics/claude-plugins-official
2. Add Your Plugin¶
# Clone your fork
git clone https://github.com/YOUR_USERNAME/claude-plugins-official
cd claude-plugins-official
# Create branch
git checkout -b add-my-plugin
# Copy your plugin
cp -r /path/to/your/plugin external_plugins/my-plugin
3. Create Pull Request¶
Push and create a PR to anthropics/claude-plugins-official.
Automated Submission¶
Use AI Assist Kit to automate the PR creation:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/agentplexus/assistantkit/publish/claude"
"github.com/agentplexus/assistantkit/publish/core"
)
func main() {
ctx := context.Background()
token := os.Getenv("GITHUB_TOKEN")
publisher := claude.NewPublisher(token)
// Validate plugin first
if err := publisher.Validate("./plugins/claude"); err != nil {
log.Fatalf("Validation failed: %v", err)
}
// Submit to marketplace
result, err := publisher.Publish(ctx, core.PublishOptions{
PluginDir: "./plugins/claude",
PluginName: "my-plugin",
Title: "Add my-plugin to marketplace",
Verbose: true,
})
if err != nil {
log.Fatalf("Publish failed: %v", err)
}
fmt.Printf("PR created: %s\n", result.PRURL)
}
Publish Options¶
| Option | Description | Required |
|---|---|---|
PluginDir |
Path to plugin directory | Yes |
PluginName |
Plugin name in marketplace | Yes |
Title |
PR title | No |
Body |
PR description | No |
Branch |
Branch name | No |
ForkOwner |
GitHub username for fork | No |
DryRun |
Simulate without creating PR | No |
Verbose |
Print progress | No |
Generated PR¶
The automated publisher creates a PR with:
## Summary
Adding the **my-plugin** plugin to the Claude Code marketplace.
### Description
[Extracted from README.md]
### Checklist
- [ ] Plugin has `.claude-plugin/plugin.json`
- [ ] Plugin has `README.md` with documentation
- [ ] All commands/skills/agents are documented
- [ ] No security issues or sensitive data
- [ ] Tested locally with Claude Code
---
*Submitted via [aiassistkit](https://github.com/agentplexus/assistantkit) publish tool*
Validation¶
Before publishing, validate your plugin:
publisher := claude.NewPublisher(token)
err := publisher.Validate("./plugins/claude")
if err != nil {
// Handle validation error
if validationErr, ok := err.(*core.ValidationError); ok {
fmt.Printf("Missing files: %v\n", validationErr.Missing)
}
}
Required Files¶
| File | Description |
|---|---|
.claude-plugin/plugin.json |
Plugin metadata |
README.md |
Documentation |
plugin.json Format¶
The consolidated format embeds MCP servers and hooks directly in plugin.json:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "A helpful plugin for developers",
"author": "Your Name",
"repository": "https://github.com/yourname/my-plugin",
"license": "MIT",
"mcpServers": {
"my-server": {
"command": "./my-server",
"args": ["--mode", "production"],
"env": {
"API_KEY": "${MY_API_KEY}"
}
}
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo 'Running command...'"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "prompt",
"prompt": "The task has stopped. Consider if follow-up is needed."
}
]
}
]
},
"commands": "./commands/",
"skills": "./skills/",
"agents": "./agents/"
}
plugin.json Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Plugin identifier (lowercase, dashes) |
version |
string | Yes | Semantic version (e.g., 1.0.0) |
description |
string | Yes | Brief description |
author |
string | No | Author name or organization |
license |
string | No | License identifier (e.g., MIT) |
repository |
string | No | GitHub repository URL |
homepage |
string | No | Project homepage URL |
mcpServers |
object | No | MCP server configurations |
hooks |
object | No | Event hooks (PreToolUse, PostToolUse, Stop, etc.) |
commands |
string | No | Path to commands directory |
skills |
string | No | Path to skills directory |
agents |
string | No | Path to agents directory |
MCP Server Configuration¶
{
"mcpServers": {
"server-name": {
"command": "./path/to/binary",
"args": ["--flag", "value"],
"env": {
"VAR_NAME": "${ENV_VAR}"
},
"cwd": "/optional/working/dir",
"disabled": false
}
}
}
Hooks Configuration¶
Hooks are triggered on specific events:
| Event | Description |
|---|---|
PreToolUse |
Before tool execution (can use matcher to filter) |
PostToolUse |
After tool execution |
Stop |
When agent stops |
Notification |
When notifications occur |
SubagentStop |
When subagent stops |
Hook types:
command- Execute a shell commandprompt- Inject a prompt for the model to consider
Dry Run¶
Test the publish process without creating a PR:
result, err := publisher.Publish(ctx, core.PublishOptions{
PluginDir: "./plugins/claude",
PluginName: "my-plugin",
DryRun: true,
Verbose: true,
})
// result.Status = "Dry run completed - no PR created"
Error Handling¶
result, err := publisher.Publish(ctx, opts)
if err != nil {
switch e := err.(type) {
case *core.ValidationError:
fmt.Printf("Missing: %v\n", e.Missing)
case *core.ForkError:
fmt.Printf("Fork failed: %v\n", e.Err)
case *core.BranchError:
fmt.Printf("Branch failed: %v\n", e.Err)
case *core.CommitError:
fmt.Printf("Commit failed: %v\n", e.Err)
case *core.PRError:
fmt.Printf("PR failed: %v\n", e.Err)
case *core.AuthError:
fmt.Printf("Auth failed: %s\n", e.Message)
default:
fmt.Printf("Unknown error: %v\n", err)
}
}
GitHub Token¶
Create a token at github.com/settings/tokens with:
repo- Full control of private repositoriesworkflow- Update GitHub Action workflows (if needed)
After Submission¶
- Wait for Review - Anthropic team reviews submissions
- Address Feedback - Make requested changes
- Merge - Once approved, your plugin is published
- Announce - Let users know about your plugin!