Build, Test, Version, and Publish a Claude Code Plugin Marketplace
·Course·Sudeep Devkota

Build, Test, Version, and Publish a Claude Code Plugin Marketplace

Create a production Claude Code plugin with manifest, skills, agents, hooks, MCP servers, namespacing, behavioral tests, immutable releases, and marketplace distribution.


Build, Test, Version, and Publish a Claude Code Plugin Marketplace

Quick answer

Create a plugin directory with .claude-plugin/plugin.json and only the components you need: skills, agents, hooks, MCP servers, LSP servers, or commands. Use ${CLAUDE_PLUGIN_ROOT} for packaged files and ${CLAUDE_PLUGIN_DATA} for persistent state, namespace every exposed component, test from a local marketplace, validate manifests, pin dependencies, version releases intentionally, and publish a marketplace catalog with ownership and immutable sources. Follow Anthropic's plugin creation guide and marketplace guide.

Design one coherent product

A plugin should solve a recognizable workflow, not collect unrelated prompts. Example: incident-commander might contain:

incident-commander/
├── .claude-plugin/plugin.json
├── skills/triage/SKILL.md
├── agents/log-investigator.md
├── hooks/hooks.json
├── .mcp.json
├── scripts/redact-and-summarize.sh
├── references/severity-policy.md
└── tests/

The skill orchestrates triage, the agent investigates logs read-only, the hook blocks unsafe production mutations, MCP connects to a read-only monitoring service, and the script redacts bounded evidence. Every component reinforces the same job.

Write the manifest

{
  "name": "incident-commander",
  "description": "Read-only incident triage with evidence collection and handoff",
  "version": "1.0.0",
  "author": { "name": "Reliability Team" },
  "license": "Apache-2.0",
  "repository": "https://github.com/example/incident-commander"
}

Check the current schema for component declarations and optional metadata. Keep the name stable because it participates in command/tool namespaces. Do not impersonate official marketplace or plugin names.

Handle paths and state correctly

Installed plugins are copied into a cache, so references outside the plugin directory will break. Resolve packaged scripts and configuration through ${CLAUDE_PLUGIN_ROOT}. Store state that must survive updates under ${CLAUDE_PLUGIN_DATA} rather than modifying cached source. Never use persistent state as an unencrypted secret store.

Plugin MCP tools include plugin and server namespaces. Use their full canonical names in skills, agent tool lists, permissions, and hook matchers. Test names with punctuation because normalization rules matter.

Build a local marketplace

At the marketplace root, create .claude-plugin/marketplace.json:

{
  "name": "acme-engineering",
  "owner": { "name": "Acme Developer Experience" },
  "plugins": [
    {
      "name": "incident-commander",
      "source": "./plugins/incident-commander",
      "description": "Evidence-first, read-only incident triage"
    }
  ]
}

Add it locally, install the plugin, reload, and test before hosting. Marketplace source and plugin source are distinct; production catalogs can point to GitHub, Git URLs/subdirectories, or npm sources. Prefer immutable commit SHA pins for controlled releases and keep ownership/contact data current.

Test the complete lifecycle

Test manifest validation, installation, namespaced invocation, automatic skill triggering, hooks, MCP connection/auth failure, permission denials, upgrade with persistent state, disable/reload, uninstall, and revoked external credentials. Add malicious inputs, missing dependencies, offline behavior, spaces in paths, and Windows differences if supported.

Version changes when consumers should receive an update. Publish release notes covering capability, permission, data-flow, and migration changes—not merely features.

FAQ

Does every plugin need an MCP server?

No. Add components only when they materially improve the workflow; a focused skill-only plugin is valid.

Should marketplace entries use strict: false?

Use it only when the marketplace intentionally owns the entire component definition. The default manifest-authoritative model is clearer for most plugin authors.

How do I distribute privately?

Use a private supported source with organization-managed authentication and marketplace policy, then test installation in the same restricted environment.

Subscribe to our newsletter

Get the latest posts delivered right to your inbox.

Subscribe on LinkedIn