Atlas
TechnicalFrom Atlas

Claude Code Plugins: Build a Team Marketplace

Package skills, subagents and hooks as a Claude Code plugin, host a team marketplace in git, and make every teammate get it. Commands and config included.

The short version

  • A Claude Code plugin is one directory that bundles skills, subagents, hooks and MCP servers, with a small plugin.json manifest, so a team installs a whole setup as one unit.
  • Test a plugin with claude plugin validate and claude --plugin-dir before you publish anything; no marketplace is needed while you build.
  • A team marketplace is a git repository with a .claude-plugin/marketplace.json file; commit the project settings that --scope project writes and teammates get it once they trust the folder.
  • Set a version on every release or leave it out everywhere; if you set one and push without changing it, users keep their cached copy.
  • Every enabled plugin adds names and descriptions to each session's context, so keep the set small and check what each one costs.
On this page
  1. The short version
  2. What is a Claude Code plugin?
  3. How do I create a plugin?
  4. How do I test a plugin before sharing it?
  5. How do I move an existing .claude setup into a plugin?
  6. How do I set up a team marketplace?
  7. How do teammates get the plugins?
  8. How do versions and updates work?
  9. What does a plugin cost and what can go wrong?
  10. Where Atlas fits
  11. Conclusion
  12. Questions people ask

If your team keeps copying the same skills, subagents and hooks between repositories, a Claude Code plugin is the way to stop. A plugin is one directory that Claude Code installs and loads as a unit, and a marketplace is a git repository that lists plugins so teammates can install and update them by name. This guide builds a plugin, tests it locally, publishes it as a team marketplace and covers the settings that make it arrive on every machine.

What is a Claude Code plugin?

A plugin is a directory of skills, agents, hooks, MCP servers or other components, loaded as one unit. A JSON manifest at .claude-plugin/plugin.json gives it a name and optional metadata. Skills, agents, hooks and MCP servers all work on their own without a plugin, so you do not need one for a setup that serves one project or only you.

Reach for a plugin when you want to share the setup with teammates, install it in several projects, or publish versioned releases. Plugin skills and agents get the plugin name as a prefix, such as /my-plugin:hello, so two plugins can each ship a hello skill without colliding.

If you have not written skills and hooks yet, start with those; a plugin is how you ship them to others.

How do I create a plugin?

The layout is fixed. Only plugin.json goes inside .claude-plugin/; everything else sits at the plugin root.

LocationContents
.claude-plugin/plugin.jsonThe manifest
skills/One <name>/SKILL.md directory per skill
agents/One Markdown file per subagent
hooks/hooks.jsonHook configuration
.mcp.jsonMCP server definitions

Components saved inside .claude-plugin/ do not load. Create a minimal plugin:

bash
mkdir -p my-first-plugin/.claude-plugin
mkdir -p my-first-plugin/skills/hello
json
{
  "name": "my-first-plugin",
  "description": "A greeting plugin to learn the basics",
  "version": "1.0.0",
  "author": {
    "name": "Your Name"
  }
}

Save that as my-first-plugin/.claude-plugin/plugin.json. Only name is required, and it must not contain spaces. Then add a skill at my-first-plugin/skills/hello/SKILL.md:

markdown
---
name: 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.

disable-model-invocation: true stops Claude from running the skill on its own, so you run it as /my-first-plugin:hello. Remove the line for a skill you want Claude to pick up by itself.

How do I test a plugin before sharing it?

You do not need a marketplace while you build. Validate first, then load the folder for one session:

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

Validation checks the manifest and the frontmatter of every skill, agent and command file, and exits 0 on Validation passed. Add --strict to fail on warnings too. Inside the session, /reload-plugins applies edits you made on disk. The /plugin Installed tab shows the components Claude Code found, and its Errors tab shows what failed to load.

Two pitfalls. Pointing --plugin-dir at a marketplace root loads nothing and shows no error, because the flag wants one plugin's folder. And a plugin that loads cleanly can still fail to steer Claude the way you meant; claude plugin eval runs your test cases with and without the plugin and scores the difference.

Other ways to load a plugin without installing it: --plugin-url takes a .zip from a URL (handy for a CI build artifact, and only for archives you control or trust), and the CLAUDE_CODE_PLUGIN_DIRS environment variable lists paths when you cannot add a flag.

How do I move an existing .claude setup into a plugin?

Copy the directories, then move the hooks. Run this from the project root:

bash
mkdir -p my-plugin/.claude-plugin
cp -r .claude/skills my-plugin/
cp -r .claude/agents my-plugin/
mkdir -p my-plugin/hooks

Put a plugin.json in my-plugin/.claude-plugin/. Then create my-plugin/hooks/hooks.json with the hooks object copied from your settings file; the format is the same:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npm run lint:fix" }]
      }
    ]
  }
}

Load it with claude --plugin-dir ./my-plugin and check each piece under its new name, for example /my-plugin:deploy for a skill that was /deploy. While the originals remain under .claude/, skills and agents do not collide because of the prefix, but hooks have no prefix, so a hook in both places runs twice. Delete the originals once the plugin works.

How do I set up a team marketplace?

A marketplace is a directory or repository with .claude-plugin/marketplace.json. It requires a name, an owner and a plugins array, and each plugin entry needs a name and a source.

bash
mkdir -p my-marketplace/.claude-plugin my-marketplace/plugins
cp -r my-first-plugin my-marketplace/plugins/
json
{
  "name": "my-marketplace",
  "description": "Plugins for my team",
  "owner": { "name": "Your Name" },
  "plugins": [
    {
      "name": "my-first-plugin",
      "source": "./plugins/my-first-plugin",
      "description": "A greeting plugin to learn the basics"
    }
  ]
}

Write relative paths from the marketplace root, the directory that contains .claude-plugin/; paths with .. fail validation. Keep the entry name the same as the name in the plugin's own manifest, or installs by manifest name report that the plugin is not found. Then validate, register and install locally:

bash
claude plugin validate ./my-marketplace
claude plugin marketplace add ./my-marketplace
claude plugin install my-first-plugin@my-marketplace
claude plugin list

The install id is the entry name, an @, and the marketplace name. Because this local marketplace uses a relative path, edits show up at the next session start or /reload-plugins, with no version change.

For plugins that live elsewhere, source can be an object: { "source": "github", "repo": "your-org/my-first-plugin" }, or git-subdir for a folder inside a monorepo. Other source types are url, archive (a zip over HTTPS), npm and command. Pin a git-based source with ref or sha.

How do teammates get the plugins?

Push the marketplace to a git host. Teammates run /plugin marketplace add your-org/your-marketplace in a session, or claude plugin marketplace add in the shell. For hosts other than GitHub, send the full URL, since owner/repo shorthand always means github.com. To pin a branch or tag, append #<ref>.

To avoid asking everyone to run commands, register the marketplace for the repository. Run this once in the repo and commit the .claude/settings.json it writes:

bash
claude plugin marketplace add your-org/your-marketplace --scope project

Claude Code then registers the marketplace for each teammate who trusts the folder. In an untrusted folder it ignores the entries without a message. If a plugin's marketplace entry points to an external source, such as its own GitHub repository, each contributor sees that it is enabled in project settings but not installed, until they run claude plugin install <name>@<marketplace> --scope project. Plugins listed by relative path load from the marketplace copy.

You can enable plugins in the same settings file with enabledPlugins, using plugin-name@marketplace-name keys. Organizations can force this through managed settings with extraKnownMarketplaces and enabledPlugins, and managed settings take precedence over every other scope.

In claude -p and CI runs, plugins install in the background, so one can be missing from the first turn. Set CLAUDE_CODE_SYNC_PLUGIN_INSTALL=1 to make the run wait. For private marketplaces, Claude Code has no git token of its own; it runs git on the machine with prompts turned off and relies on credentials already stored there. On GitHub Actions, export a token with read access as GH_TOKEN and run gh auth setup-git.

How do versions and updates work?

Users get a new copy of a plugin only when its computed version changes. You have two safe choices:

  • Bump version on every release. If you set "1.0.0" and push new commits without changing it, users keep the cached copy.
  • Omit version everywhere, and users track your commits.

Do not set version in both plugin.json and the marketplace entry; Claude Code silently uses the plugin.json value and validation reports the mismatch.

Background auto-update is off by default and marketplace.json has no field to turn it on. Each user enables it under Marketplaces in /plugin, or an admin sets "autoUpdate": true on the managed marketplace entry. Without it, users run /plugin marketplace update <name> or claude plugin update <plugin>@<name>.

To change the label users see without breaking installs, set displayName in plugin.json. If you must change the plugin's name, add a top-level renames map to marketplace.json so existing installs migrate; null marks a removed plugin:

json
{
  "renames": {
    "formatter": "code-formatter",
    "legacy-linter": null
  }
}

What does a plugin cost and what can go wrong?

An enabled plugin is part of every session. The name and description of each skill, agent and command Claude can invoke on its own sit in context on every turn, which counts toward usage even when nothing from the plugin runs. Its MCP servers run alongside the session and its hooks fire at their events. Disable one without uninstalling with claude plugin disable.

Security matters as much. What a plugin runs, it runs as you, and a third-party marketplace is any one other than Anthropic's. Read a plugin's hooks and MCP config before installing. Administrators can restrict sources with strictKnownMarketplaces, block plugins by setting them to false in managed enabledPlugins, and reject --plugin-dir and --plugin-url with disableSideloadFlags.

Where Atlas fits

Atlas is a team of AI engineers built on Claude Code. It has its own domain plugins, which teach the team a product's rules: the plugin's personas rename the roles, and its rules are checked against every change before work counts as done. Salesforce is one example.

Installing Claude Code plugins from a team marketplace, as described above, is not something Atlas does today. That is coming to Atlas, built in, so it will need no setup on your side. Until then, install your plugins in Claude Code yourself. Learn more at the Atlas home page.

Conclusion

Start with one plugin that holds the skills and hooks your team already copies around, validate it, and test it with --plugin-dir. Put it in a small git marketplace, commit the project-scoped registration, and decide up front whether you bump version or omit it. Keep the enabled set small, since each plugin adds to every session.

Questions people ask

What is a Claude Code plugin?

A plugin is a directory of skills, agents, hooks, MCP servers or other components, with a plugin.json manifest, that Claude Code installs and loads as one unit. Use one when you want to share a setup with teammates or install it in several projects.

How do I test a Claude Code plugin locally?

Run claude plugin validate on the folder, then start a session with claude --plugin-dir pointing at it. Use /reload-plugins after edits and check the Errors tab in /plugin if something does not load.

How do I share a plugin marketplace with my team?

Push a repository containing .claude-plugin/marketplace.json to a git host and have teammates run /plugin marketplace add. To cover a whole repository, add it with --scope project and commit the .claude/settings.json it writes.

Why are my plugin updates not reaching users?

Users get a new copy only when the plugin's version changes. If you set a version and push commits without bumping it, they keep the cached copy; omit the version everywhere to track commits instead.

Do plugins increase token usage?

Yes. Names and descriptions of skills, agents and commands Claude can invoke on its own are in context on every turn, even when the plugin is not used, so keep the enabled set small.

Sources

  1. Plugins overview - Claude Code Docs
  2. Create a Claude Code plugin
  3. Create a marketplace
  4. Host and maintain a marketplace
  5. Manage Claude Code plugins for your organization

Researched and drafted with Claude, then checked against the sources above. Atlas is an independent product, not affiliated with Anthropic or OpenAI. Claude and Claude Code are trademarks of Anthropic; Codex is a product of OpenAI.