Strona główna / Artykuły / Claude Code Plugins: Build, Test and Publish Your First Plugin

Artykuł opublikowany po angielsku.

Claude Code Plugins: Build, Test and Publish Your First Plugin

A practical tour of Claude Code's plugin system: manifest, skills, LSP servers and monitors, local testing, marketplace submission and migrating from a .claude folder.

1628 słów

Claude Code plugins look like a small packaging feature, but they address a bigger issue. Before they existed, a Claude Code setup lived loosely inside the .claude/ folder. Sharing it was awkward, versioning it was messy and auditing it was hard. A plugin bundles all of that into one standard unit.

One detail explains the whole design. Everything a plugin can hold, meaning skills, agents, hooks and MCP servers, already existed on its own. Plugins add no new capabilities. They standardize how those pieces are packaged and handed to other people.

Standalone config or plugin?

The two options differ in naming and in who they're for:

  • Standalone config in the .claude/ folder. Commands are invoked as /hello. It fits personal workflows, project-specific tweaks and quick experiments.
  • Plugin, a self-contained directory with a manifest. Commands carry a prefix, as in /plugin-name:hello. It fits team sharing, community distribution, versioned releases and reuse across projects.

A sensible path is to iterate quickly with a standalone config and turn it into a plugin once it's ready to be shared.

Building a first plugin in three steps

1. Create the folder and manifest.

mkdir my-first-plugin
mkdir my-first-plugin/.claude-plugin

The manifest file plugin.json goes in that hidden folder and gives the plugin an identity:

{
  "name": "my-first-plugin",
  "description": "A greeting plugin to learn the basics",
  "version": "1.0.0",
  "author": {
    "name": "Your Name"
  }
}

The name value is the unique identifier and also becomes the namespace for every skill in the plugin. The version field is optional. When it's set, users receive updates only after the number is bumped.

2. Add a skill. Skills sit in the skills/ directory, each in its own folder with a SKILL.md file:

mkdir -p my-first-plugin/skills/hello---
description: Greet the user with a friendly message
disable-model-invocation: true
---

Greet the user warmly and ask how you can help them today.

3. Try it locally.

claude --plugin-dir ./my-first-plugin

Once Claude starts, typing /my-first-plugin:hello runs the skill.

The namespacing deserves a mention. Every plugin skill follows the /plugin-name:skill-name pattern, so two plugins can ship skills with the same name and never collide.

To let a skill take input, put the $ARGUMENTS placeholder into its SKILL.md:

---
description: Greet the user with a personalized message
---

# Hello Skill

Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.

After editing, /reload-plugins applies the changes. One quirk: the skill count shown after a reload only includes the commands/ directory, so it may say zero even though the new skill is loaded and works.

There's also a shortcut. Running claude plugin init my-tool sets up a plugin under ~/.claude/skills/, and it loads in every future session as my-tool@skills-dir with no need for --plugin-dir.

What a plugin can contain

Each location in the plugin root has a fixed role:

  • .claude-plugin/ holds only the plugin.json manifest
  • skills/ holds skills, laid out as <skill-name>/SKILL.md
  • commands/ is the older skill format with flat Markdown files, and new plugins should use skills/ instead
  • agents/ contains custom agent definitions
  • hooks/ contains event handlers described in hooks.json
  • .mcp.json configures MCP servers
  • .lsp.json configures language servers for code intelligence
  • monitors/ configures background monitors
  • bin/ holds executables that join the PATH while the plugin is enabled
  • settings.json supplies default settings applied when the plugin is enabled

The classic beginner mistake is placing commands/, agents/, skills/ or other content folders inside .claude-plugin/. Only the manifest belongs there. Everything else sits directly in the plugin root.

For a plugin with one skill, SKILL.md can live in the root, and the name in its frontmatter becomes the invocation name. Plugins with several skills should use the skills/ layout.

Extras for more advanced plugins

Language servers. To support a language that Claude Code doesn't cover natively, add a .lsp.json file:

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

People who install the plugin need the matching language server binary on their machine. Without it, a startup failure appears in the Errors tab of the /plugin manager.

Background monitors. Define them in monitors/monitors.json and they start when the plugin is activated. Each line the command prints to stdout reaches Claude as a notification:

[
  {
    "name": "error-log",
    "command": "tail -F ./logs/error.log",
    "description": "Application error log"
  }
]

Default settings. settings.json currently understands only two keys, agent and subagentStatusLine, and unknown keys are ignored without a warning. The agent key can make one of the plugin's own agents the main thread, which changes Claude Code's default behavior:

{
  "agent": "security-reviewer"
}

Testing

The --plugin-dir flag is the main development tool. It accepts a directory and also a zipped package:

claude --plugin-dir ./my-plugin.zip

When a local plugin has the same name as an installed marketplace plugin, the local copy wins for that session. That's handy for trying changes without uninstalling anything. It can't override plugins that are force-enabled or force-disabled.

For remote testing there's --plugin-url:

claude --plugin-url https://example.com/my-plugin.zip

If the download fails or the archive is broken, Claude Code still starts and records the problem in the Errors tab of /plugin. As with any plugin, load only sources you trust.

During development, /reload-plugins applies changes without a restart. When something doesn't work, check the directory layout, test each component separately and lean on the CLI debugging helpers documented in Anthropic's reference pages.

Getting listed in a marketplace

Anthropic runs two public marketplaces:

  • claude-plugins-official is curated by Anthropic and gets registered automatically on the first interactive launch. A plugin accepted there is offered to users natively.
  • claude-community is community-run, and third-party submissions are added after review. Add it with /plugin marketplace add anthropics/claude-plugins-community.

Validate before submitting:

claude plugin validate ./your-plugin

A pass prints a "Validation passed" message, and any warnings are listed. Adding --strict turns warnings into errors.

Submission goes through one of two forms. One route is the claude.ai form, open only to Team or Enterprise organizations. Solo authors go through the Console form instead. After approval, the plugin is pinned to a particular commit SHA in the community repository, and CI moves the pin on every new commit. Public directories sync nightly, so a gap between approval and appearing in marketplace.json is normal.

The official marketplace works differently. Anthropic decides what goes in, and there's no public application.

Moving an existing setup

Standalone configurations convert cheaply. Create the plugin folder and manifest, then copy content across:

cp -r .claude/commands my-plugin/
cp -r .claude/agents my-plugin/
cp -r .claude/skills my-plugin/

Hooks need separate handling. Take the hooks object from the existing settings.json and place it in hooks/hooks.json.

Afterwards, delete the originals from .claude/. Agents in .claude/agents/, at project or user level, override plugin agents of the same name, so leftovers would keep the new version from taking effect. Skills don't clash this way, because plugin skills are namespaced and both versions can coexist.

What plugins change

No new capability came with plugins. Skills, agents, hooks and MCP servers worked fine as loose configuration. What plugins add is structure: versioning, consistent naming, descriptions and real distribution channels.

That moves Claude Code from being a tool toward being a platform. A tool does one job well, while a platform lets others build on top of it. What will grow in the marketplace is hard to predict, but copying whole .claude/ folders between machines is clearly on its way out. Other AI coding products, Cursor among them, have launched plugin marketplaces too, so scattered components are turning into packaged, shareable units across the ecosystem.