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.
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 theplugin.jsonmanifestskills/holds skills, laid out as<skill-name>/SKILL.mdcommands/is the older skill format with flat Markdown files, and new plugins should useskills/insteadagents/contains custom agent definitionshooks/contains event handlers described inhooks.json.mcp.jsonconfigures MCP servers.lsp.jsonconfigures language servers for code intelligencemonitors/configures background monitorsbin/holds executables that join the PATH while the plugin is enabledsettings.jsonsupplies 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.