You have spent a few weeks deep in Claude Code. You built a skill that turns messy notes into a clean PRD. You wrote a subagent that pulls competitor data on command. You saved three or four custom commands you now run every day. Your own productivity as a PM, an APM, or a product designer has jumped.
Then a teammate watches you work and asks the obvious question: "How do I get that?"
And you freeze. Because right now the honest answer is "copy these files into your .claude folder, and the other ones into this other folder, and oh wait you also need this MCP server." That is not sharing. That is a support ticket.
This is exactly the problem Claude Code plugins solve. A plugin is the native, installable package format for your skills, subagents, and custom commands. Get the structure right once, push it to a GitHub repo, and your whole team installs your entire toolkit in three commands. This guide walks through the exact structure a plugin needs, why that structure matters, and the full step by step to ship one your team actually uses.
Learn this hands-on
Become a 10x PM by learning how to use Claude Code in your daily work as a Product Manager, through 3 highly efficient live sessions of 1h30. Join the Claude Code for PMs live cohort.

What a Claude Code plugin actually is
A Claude Code plugin is a folder, synced to a Git repo, that bundles your custom components so Claude Code can install them natively. Instead of asking teammates to hand-place files, you give them a repo, and Claude Code reads it, registers everything, and namespaces it cleanly.
A single plugin can carry any mix of:
- Skills (the
skills/folder): reusable instructions Claude loads on demand. Think of these as the reusable layer of your team's expertise, similar to how a custom MCP encodes your workflows. - Subagents (the
agents/folder): specialized agents your team can call by name. - Custom commands (the
commands/folder): the slash commands you run every day.
The reason to bother with the plugin format instead of zipping a folder is that Claude Code treats a properly structured plugin like any marketplace entry. The same native flow that installs a public plugin installs yours: /plugin marketplace add, /plugin install, and later /plugin marketplace update. No manual file placement, no per project setup, no drift between teammates.
The exact structure a Claude Code plugin needs
This is the part most people get wrong, so it is worth slowing down. Claude Code only installs a plugin natively when the folders and manifests sit in precisely the right places. Here is the skeleton, using a real example repo called excalidraw-plugins:
excalidraw-plugins/ # the repo = the marketplace
├── .claude-plugin/
│ └── marketplace.json # the catalog: lists every team plugin
├── product/ # one plugin (the lead)
│ ├── .claude-plugin/
│ │ └── plugin.json # this plugin's manifest
│ ├── agents/ # subagents live here
│ ├── commands/ # custom commands live here
│ └── skills/ # skills live here
├── engineering/ # its own plugin
│ └── .claude-plugin/plugin.json
└── marketing/ # its own plugin
└── .claude-plugin/plugin.json
Read that tree slowly, because three rules make or break native install:
- The repo root holds
.claude-plugin/marketplace.json. This single file is the catalog. It is what shows up under Marketplaces when anyone runs/plugin, and itsnamemust equal the Git repo name. - Each plugin lives in its own top-level folder (
product/,engineering/,marketing/) and carries its own.claude-plugin/plugin.json. That manifest is the plugin's identity and namespace. - Components live at the plugin's root, never inside
.claude-plugin/. The only thing that ever sits inside a.claude-plugin/folder is a manifest (plugin.json, ormarketplace.jsonat the repo root). Youragents/,commands/, andskills/folders sit one level up, directly under the plugin folder. Put a skill inside.claude-plugin/by mistake and Claude Code will not see it.
Inside plugin.json
Each plugin's manifest is small and declares its name, version, and description:
{
"name": "excalidraw-product",
"version": "0.1.0",
"description": "Product team toolkit: PRD skills, competitor agent, planning commands.",
"author": { "name": "Jules" }
}
The name is the namespace. Once you drop components in, they resolve as /<plugin-name>:<thing>. So a generate-prd command inside the product plugin becomes /excalidraw-product:generate-prd. That namespacing is why two teams can each ship a command called summarize without colliding.
Inside marketplace.json
The catalog at the repo root lists every plugin and points to its folder:
{
"name": "excalidraw-plugins",
"description": "Per-team Claude Code toolkits.",
"owner": { "name": "Jules" },
"plugins": [
{ "name": "excalidraw-product", "source": "./product", "description": "Product team toolkit (lead)." },
{ "name": "excalidraw-engineering", "source": "./engineering", "description": "Engineering team toolkit." },
{ "name": "excalidraw-marketing", "source": "./marketing", "description": "Marketing team toolkit." }
]
}
The catalog name is not a free choice: it must match the exact Git repository name (the part after the last slash in your remote URL, minus any .git). That is the name teammates will reference when they install, so getting it wrong breaks the install command.
The model that scales: one plugin per team
Notice the skeleton above is not a single plugin. It is a marketplace that holds several, one per team. This is the pattern that scales inside a real company.
One folder = one plugin = one team. The repo is the marketplace. Each team (product, engineering, marketing) gets its own plugin folder, and each teammate installs only the plugin for their team. A PM installs excalidraw-product and gets the PRD skill and the competitor agent. An engineer installs excalidraw-engineering and gets a different set. Nobody is forced to carry tools they will never run.
This split has a quiet structural benefit too. A subagent and the skills it depends on always live inside the same team plugin, so you can never ship an agent that references a skill a teammate did not install. Each plugin is self-contained by construction.
As Charity Majors, co-founder and CTO of Honeycomb, put it: "The knowledge in our heads is unavailable to AI until we encode it into the system, after all." That is exactly what a plugin does. It takes what lives in one person's .claude/ folder and turns it into something the whole team can pull down and run.
The knowledge in our heads is unavailable to AI until we encode it into the system, after all.
Build your own plugin, step by step
Here is the exact process to go from "I have some scattered components" to "my team installs my toolkit in three commands."
Step 1: Scaffold the empty marketplace
Create a new, empty project (for example excalidraw-plugins) and connect it to a fresh GitHub repo. Open Claude Code in that empty folder and paste the scaffolding prompt below. It builds the entire skeleton, the manifests, and the empty component folders, then validates everything, without inventing any component content:
# Generate a blank per-team Claude Code plugin marketplace
You are scaffolding a brand-new, empty Git repo that acts as a marketplace
catalog of multiple team plugins, matching this exact shape:
<repo>/ # e.g. excalidraw-plugins
├── .claude-plugin/marketplace.json # the catalog: lists all team plugins
├── product/ # the lead plugin, ready for components
│ ├── .claude-plugin/plugin.json
│ ├── agents/.gitkeep
│ ├── commands/.gitkeep
│ └── skills/.gitkeep
├── engineering/ # ready for components
│ ├── .claude-plugin/plugin.json
│ ├── agents/.gitkeep
│ ├── commands/.gitkeep
│ └── skills/.gitkeep
└── marketing/ # ready for components
├── .claude-plugin/plugin.json
├── agents/.gitkeep
├── commands/.gitkeep
└── skills/.gitkeep
Each team is its own installable plugin; a user installs only the plugin for
their team. This repo starts blank: create the skeleton and valid manifests so
teams drop their components in later. Work autonomously; ask me only when a
required value is genuinely ambiguous. Do not invent component content. Create
empty, valid manifests and directories only.
## 1. Teams
The catalog has exactly three teams: product, engineering, marketing. Every team
gets .claude-plugin/plugin.json plus empty agents/, commands/, and skills/
directories (each with a .gitkeep so Git tracks the empty dir). product is the
lead plugin; the others are scaffolded identically.
## 2. Build the skeleton
Run git init if needed. Create the directory tree above. Components live at each
team plugin's root, NOT inside .claude/, and NEVER inside any .claude-plugin/
(the only thing inside a .claude-plugin/ is plugin.json, except the repo-root one
which holds marketplace.json). Add a top-level README.md and a .gitignore.
## 3. Per-team plugin.json
For each team, write <team>/.claude-plugin/plugin.json:
{
"name": "<repo-prefix>-<team>",
"version": "0.1.0",
"description": "<one sentence on what this team's plugin will hold>",
"author": { "name": "<git config user.name, else ask>" }
}
name is the namespace: commands/skills resolve as /<repo-prefix>-<team>:<thing>
(e.g. /excalidraw-product:generate-prd). Take the catalog name and strip a
trailing -plugins if present (excalidraw-plugins to prefix excalidraw).
## 4. Catalog marketplace.json
Write .claude-plugin/marketplace.json at the repo root:
{
"name": "<catalog-name>",
"description": "<owner/repo> team toolkits.",
"owner": { "name": "<author>" },
"plugins": [
{ "name": "<repo-prefix>-product", "source": "./product", "description": "Product team toolkit (lead)." },
{ "name": "<repo-prefix>-engineering", "source": "./engineering", "description": "Engineering team toolkit." },
{ "name": "<repo-prefix>-marketing", "source": "./marketing", "description": "Marketing team toolkit." }
]
}
Set "name" to the EXACT Git repository name. Derive it from the remote: run
git remote get-url origin, take the part after the last /, strip a trailing .git.
This name is what shows up under Marketplaces in /plugin, so it MUST equal the
repo name. If there is no remote yet, ask me for the exact repo name.
## 5. Validate
Run claude plugin validate .; resolve every error and warning. If unavailable,
manually verify: marketplace.json parses and lists every plugin with a valid
source path; each plugin.json parses and has a name and version; no component dir
lives inside any .claude-plugin/; every team has empty agents/, commands/, skills/
tracked via .gitkeep. An empty plugin is valid.
## 6. Report and remaining tasks
Output the team table, the final directory tree, the chosen prefix, the catalog
name and where it came from, and the exact git commands to commit and push (do
not push automatically). Then show the install flow others will use.
The prompt does the boring, error-prone work for you: every folder in the right place, every manifest valid, the catalog name derived from your actual repo. When it finishes, you have a blank but valid marketplace.
Step 2: Fill a team and push
Drop your real components into the lead plugin. Subagents go in product/agents/ as *.md files, custom commands go flat in product/commands/, and each skill gets its own folder at product/skills/<name>/SKILL.md. Bump the version in that plugin's plugin.json, then push:
git add -A
git commit -m "Add product team toolkit"
git push -u origin main
Nothing is installable by anyone until this is pushed. The repo is the distribution channel.
Step 3: Register the marketplace and install
This is the three command flow your whole team will use. Catalog plus plugin is two steps by design: you register a source once, then install plugins from it.
# 1. Register the marketplace (once per machine)
/plugin marketplace add <github-user>/<repo>
# example: /plugin marketplace add julesb22/excalidraw-plugins
# 2. Install the plugin for your team
/plugin install <plugin-name>@<marketplace-name>
# example: /plugin install excalidraw-product@excalidraw-plugins
# 3. Apply it
/reload-plugins
Step 1 is a one time trust decision for the source. Step 2 is per team and repeatable. That is the whole onboarding: a new teammate runs three commands and has your entire toolkit.
A few things worth knowing:
- The plugin installs at the user level (
~/.claude/), so it works across all of that person's projects with zero per project config. - A public repo installs directly. A private repo requires read access for the installer.
Update and contribute back
Once the plugin is live, it has a lifecycle. Two roles split the work cleanly.
The consumer (most of your team) installs once and updates occasionally. They never touch Git:
/plugin marketplace update <marketplace-name>
That re-reads the catalog and pulls new or updated plugins, no reinstall needed. Note that updates are not automatic by default for third party marketplaces. Each person enables it once in /plugin, under the Marketplaces tab, with Enable auto-update (Claude Code v2.0.70 and up). Restart the session so updated agents register.
The AI enabler (you, or whoever owns the toolkit) clones the repo, edits a component, bumps the version in plugin.json, and pushes. That requires write access (be a collaborator, or fork and open a pull request).
The healthiest pattern for a growing team is contribution by pull request. A teammate who built a great skill clones the repo, branches, copies the skill out of their own ~/.claude/skills/, pushes, and opens a PR. The enabler reviews it for quality, name collisions, and machine specific paths, merges, and bumps the version. Everyone gets the new skill on their next update. The toolkit improves without anyone hand-delivering files.
One watch-out: naming is the contract. Renaming a plugin or marketplace does not auto-migrate anyone, so consumers would have to reinstall. And external prerequisites (MCP servers, gh auth, local paths, env vars) ship separately from the plugin, so each installer configures those once if a component depends on them.
How plugins stack with your other Claude Code config
A plugin does not replace your personal setup. It layers on top of it. In any session, Claude Code merges three scopes without duplication:
- The team plugin (installed at the user level): the shared toolkit everyone runs.
- Your personal
~/.claude/: your own agents and skills, available in every one of your projects. Pairing this with Claude Code Plan Mode gives you a structured way to work through complex tasks before any code is written. - The project
.claude/: agents and skills specific to a single repo, versioned in that codebase.
This is what makes the model comfortable to adopt. You keep your personal experiments in ~/.claude/, a given codebase keeps its repo-specific helpers in its own .claude/, and the shared, blessed toolkit arrives as the plugin. The three coexist, and the best of your personal kit can graduate into the team plugin through a pull request whenever it proves useful.
Want to build your team's plugin live, with guidance? This is exactly what we teach in Claude Code for PMs, our live cohort for product teams: 3 live sessions of 90 minutes over 2 weeks. Every PM ships a real feature, builds their own agent, and gets personalized written feedback.
Ship one this week
The mechanics are genuinely simple once the structure clicks: a repo is a marketplace, a folder is a plugin, components sit at the plugin root, and three commands install the whole thing. The hard part was never the tooling. It was knowing the exact skeleton Claude Code expects, which you now have.
Pick your most-used skill, your one reliable subagent, and the two custom commands you run daily. Scaffold the marketplace with the prompt above, drop them into the product plugin, push, and send your team the three install commands. That is the difference between "I have a cool setup" and "my whole team runs on the same OS."

