You set up the same Claude Code commands, hooks, and subagents on every new machine, and you copy them by hand each time. A Claude Code plugin fixes that: it bundles all of it into one installable folder you can clone, share, or publish to a marketplace. This guide builds one from scratch, then shows you the real manifest and hooks from Evolving Lite, my open-source Claude Code plugin, so every snippet here is something you can clone and run, not a toy example.
A Claude Code plugin is a directory with a .claude-plugin/plugin.json manifest plus skills/, agents/, and hooks/ folders. Scaffold it with claude plugin init, drop your components in, then install it from a marketplace, a symlink into ~/.claude/skills/, or the --plugin-dir flag. Anything in ~/.claude/skills/ that carries a manifest auto-loads with no marketplace at all.
Twelve component types in all, per Anthropic's plugins reference as of 2026-08-15. You will never use most of them. The four that carry almost every real plugin are skills, agents, hooks and MCP servers.
What is a Claude Code plugin?
A Claude Code plugin is a self-contained directory that bundles commands, agents, skills, hooks, and MCP servers into one installable unit, described by a .claude-plugin/plugin.json manifest. Instead of pasting a slash command into one project and a hook into another, you package the whole workflow once and install it anywhere with a single command.
Ship the manifest if you want a plugin. It is formally optional in the reference, and the distinction is worth being precise about, because I got it wrong first time. A folder under ~/.claude/skills/ containing only a SKILL.md does load - that is the normal way to ship a skill, and I have 26 of them working right now. What it does not do is get adopted as a plugin: it will not appear in claude plugin list, and it cannot carry commands, agents, hooks or MCP servers. Add .claude-plugin/plugin.json and the same folder loads as name@skills-dir with all of that available. The manifest also carries the metadata you need to publish through a plugin marketplace.
That is the whole distinction: a skill is one capability, a plugin is a bundle with an identity. If you only ever wanted a skill, you do not need any of this.
This matters more as your setup grows. My Claude Code foundation ships 16 slash commands, 6 subagents, 16 hook scripts, and 2 skills as one plugin. Without the plugin format that is dozens of files to copy and re-wire on every machine. With it, the install is one clone and one command.
What you'll build
You'll build a minimal but real Claude Code plugin called my-plugin with four working parts:
- A
plugin.jsonmanifest with proper metadata. - One slash command (
/remember) that saves a note to memory. - One hook that fires on session start.
- A subagent and a skill, so you see how every component type slots in.
Then you'll install it three different ways and confirm it loads. By the end you'll have a folder you can push to GitHub and install on any other machine in about 30 seconds.
Prerequisites
You need three things before you start:
- Claude Code v2.1.157 or newer. Check with
claude --version. Theclaude plugin initscaffolder and.claude/skillsauto-loading both landed in that release. - A terminal and a text editor. Plugins are plain files: Markdown, JSON, and shell or Python scripts. No build step, no compiler.
- Basic familiarity with slash commands and hooks. If hooks are new to you, the Claude Code hooks guide walks through the event model first.
That's it. A plugin is just a folder Claude Code knows how to read, so there is nothing to install beyond Claude Code itself.
Step 1: Scaffold the plugin structure
Run the built-in scaffolder. As of v2.1.157, Claude Code ships claude plugin init <name>, which generates the conventional layout for you:
claude plugin init my-plugin
Note where that lands: ~/.claude/skills/my-plugin/, not the directory you are standing in. That is deliberate - it is already the auto-load location, so the plugin is live from the next session with no install step. Everything below edits files under that path.
Be clear about what the scaffolder actually gives you, because it is less than you might expect. Run against v2.1.233, claude plugin init creates exactly two files:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # manifest, with "skills": ["./"] and a TODO description
└── SKILL.md
That is the whole output. The fuller layout below is the convention a plugin follows, and every directory in it is one you create:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # created for you - ship this, it is what gets you adopted
├── SKILL.md # created for you
├── commands/ # you create: slash commands (.md)
├── agents/ # you create: subagents (.md)
├── skills/ # you create: skills (skill-name/SKILL.md)
├── hooks/
│ └── hooks.json # you create: hook registrations
├── .mcp.json # you create, optional: bundled MCP servers
└── README.md # you create
So when the next steps say to edit commands/remember.md and hooks/hooks.json, create the directory and the file first - init has not made them. You don't have to use every folder. A plugin can ship only commands, or only hooks, or only skills. Claude Code reads whichever standard directories exist and ignores the rest. The manifest is the one part not to skip - see above; without it the directory can still load as a plain skill, but it is not a plugin.
Step 2: Write the plugin.json manifest
The manifest lives at .claude-plugin/plugin.json and holds your plugin's identity. Here is the real, complete manifest that ships with Evolving Lite, copied straight from the repo:
{
"name": "evolving-lite",
"version": "1.1.0",
"description": "Self-evolving Claude Code system that learns from corrections, manages context, and improves every session",
"author": {
"name": "PrimeLine AI",
"email": "hello@primeline.cc",
"url": "https://primeline.cc"
},
"homepage": "https://primeline.cc/products/evolving-lite",
"repository": "https://github.com/primeline-ai/evolving-lite",
"license": "MIT",
"keywords": ["memory", "self-evolving", "context-management", "delegation", "hooks", "automation"]
}
The core fields are name, version, and description for identity, plus an author object, homepage, repository, license, and keywords for discovery. You can also add component-path overrides (commands, agents, skills, hooks, mcpServers, lspServers) when your files live somewhere other than the defaults. Newer releases added a defaultEnabled: false flag so a plugin can ship disabled until the user turns it on, with its dependencies auto-enabled alongside it.
Keep the version honest and bump it on every release. The marketplace install flow keys off name@version, so a stale version number is the fastest way to hand users an old plugin.
Step 3: Add a slash command and a hook
Now the two component types you'll reach for most: a slash command and a hook.
A slash command
Commands live in commands/ as Markdown files with YAML frontmatter. The filename becomes the command name, so commands/remember.md registers /remember. Anthropic's reference now describes these as "skills as flat Markdown files" and says to use skills/ for new plugins - commands/ keeps working, but a skill directory is the shape to reach for now. Here is the real /remember command from Evolving Lite, trimmed to its shape:
---
description: Explicitly save something to memory as an experience
argument-hint: [What to remember]
---
Save an explicit memory/experience to the Evolving Lite knowledge base.
## Input: $ARGUMENTS
If empty: "What should I remember? Describe what you
learned, decided, or want to keep."
## Process
1. **Classify the type** (solution, gotcha, pattern,
technique, decision, preference)
2. **Extract key fields** (summary, problem, solution, tags)
3. **Save as experience file**:
Write to `${CLAUDE_PLUGIN_ROOT}/_memory/experiences/exp-{timestamp}.json`
4. **Confirm**: "Saved: {summary}"
Two things to notice. $ARGUMENTS is where whatever the user typed after /remember lands. And ${CLAUDE_PLUGIN_ROOT} is a variable Claude Code expands to your plugin's install path, so the command writes inside the plugin no matter where it was cloned. That variable is what makes a plugin portable.
A hook
Hooks live in hooks/hooks.json and fire on lifecycle events. There are 31 hook events in total; the ones you will reach for first are SessionStart, SessionEnd, PreToolUse, PostToolUse, PermissionRequest, UserPromptSubmit, and Stop. I go through the full set, and which 18 of them can actually block, in the hooks post. Here is a real slice of the Evolving Lite hooks.json, wiring a health check to run when a session starts:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume|clear|compact",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/scripts/health-sentinel.sh",
"timeout": 10
}
]
}
]
}
}
The matcher decides which sub-events trigger the hook (here, any session that starts, resumes, clears, or compacts). The command runs your script, again resolved through ${CLAUDE_PLUGIN_ROOT}. Hook types go beyond command: you can also use http, mcp_tool, prompt, and agent. Evolving Lite alone wires 16 hook scripts across 6 events, which is how it warns you at 70% context and blocks dangerous bash before it runs. The full event model is covered in my Claude Code hooks guide.
This lives in primeline-ai/evolving-lite - the self-evolving Claude Code plugin. Free, MIT, no build step.
Step 4: Bundle agents and skills
The last two component types are subagents and skills, and they are where a plugin starts to feel like a real system rather than a config bundle.
Agents
Agents live in agents/ as Markdown files with frontmatter describing the subagent's behavior, tools, and which model it should run on. Claude Code invokes them for scoped tasks, which keeps the main context clean. Evolving Lite ships 6 of them, including a planner and a health monitor. If you want the reasoning behind routing work to subagents automatically, I wrote that up in score-based auto-delegation.
Skills
Skills live in skills/ as subdirectories, each holding a SKILL.md file. A skill is a reusable prompt-based workflow or chunk of reference knowledge that Claude loads only when it is relevant, so it costs you nothing in baseline context until it fires. Inside a plugin, skills are namespaced as plugin-name:skill-name, which prevents collisions with project-level or user-level skills of the same name.
Bundling all of this together is exactly what the plugin format is for. Commands, agents, skills, hooks, and MCP servers ship as one cohesive unit, install in one step, and update in one step. That is the difference between a knowledge architecture you can hand to someone else and one that only works on your laptop.
Step 5: Install and test your plugin
You have four ways to install a Claude Code plugin, from fastest to most shareable: drop it in the skills directory, symlink it there from wherever you keep it, load it for one session with --plugin-dir, or publish a marketplace. There is also a fifth thing you will find written down that does not work at all - see the warning under Option B.
Option A: drop it in .claude/skills (no marketplace)
Any directory under ~/.claude/skills/ that contains a .claude-plugin/plugin.json manifest is loaded as a plugin automatically, no marketplace required. This is the fastest path while you are building and testing.
If you scaffolded with claude plugin init in Step 1, you are already done - it writes straight to ~/.claude/skills/<name>/. Just restart:
claude
If you built the folder somewhere else by hand, move it there first:
mv my-plugin ~/.claude/skills/my-plugin
claude
Option B: clone it somewhere else and link it in
Use this when you want the repo to live somewhere you already keep code rather than inside ~/.claude/. You clone it, run a one-time setup script that checks hooks/hooks.json parses and then runs a health check, and link the directory in. Note what the script deliberately does not do: it leaves the ${CLAUDE_PLUGIN_ROOT} placeholders in hooks.json alone, because Claude Code substitutes that token itself. An earlier version baked an absolute path in with sed, which broke portability and fought the plugin loader.
If you have no reason to keep the repo elsewhere, the shorter route on the product page - cloning straight into ~/.claude/skills/evolving-lite and running setup.sh there - does the same job with one less step.
git clone https://github.com/primeline-ai/evolving-lite ~/.claude-plugins/evolving-lite
cd ~/.claude-plugins/evolving-lite && bash setup.sh
Then symlink it into your skills directory, which is where Claude Code looks:
ln -s ~/.claude-plugins/evolving-lite ~/.claude/skills/evolving-lite
Or load it for one session only, without installing:
claude --plugin-dir ~/.claude-plugins/evolving-lite
An earlier version of this post told you to add a "pluginDirectories" array to settings.json. That is wrong, and it fails in the worst way: silently. Unknown settings keys are ignored, so you get no plugin and no error message. Checked against Claude Code v2.1.233 - the string pluginDirectories does not appear in the binary at all, and a live test with the key set returns "No plugins installed." Use the symlink or the --plugin-dir flag above.
Option C: install from a marketplace
For sharing, a marketplace is a .claude-plugin/marketplace.json catalog in a Git repo that points to where each plugin lives. Users add the marketplace, then install from it:
/plugin marketplace add owner/repo
/plugin install my-plugin@my-marketplace
The /plugin command opens a manager UI with Discover, Installed, and Marketplaces tabs. Do not assume the official claude-plugins-official marketplace is already registered: on a fresh config the CLI reports No marketplaces configured, and claude plugin install <name> fails with "not found in any configured marketplace" until you add one. Add it first with claude plugin marketplace add <owner/repo>. Whichever option you pick, verify the plugin loaded: run /plugin list to see installed plugins, and check that /remember shows up in slash-command autocomplete. If it does, your plugin works.
Plugins vs skills vs the Agent SDK
People mix these up constantly, so here is the clean split. They are three layers of the same extension stack, not competitors. If MCP servers and subagents are also in your head as options, the four-way comparison takes all of them at once.
- -A single SKILL.md workflow or knowledge chunk
- -Loaded on demand, near-zero baseline cost
- -Auto-discovered from .claude/skills
- -Best for reusable reference and procedures
- +Bundles skills + commands + agents + hooks + MCP
- +One installable, shareable, versioned unit
- +Distributed via marketplaces or git clone
- +Best for shipping a whole workflow to others
The Agent SDK is the third layer: a Python or TypeScript library that runs the same Claude Code harness headlessly. It loads skills and plugins from the filesystem just like the CLI does, but it also lets you define subagents and tools programmatically in code instead of as files. Rule of thumb: write a skill for one reusable workflow, package a plugin when you want to ship several of them together, and reach for the Agent SDK only when you are building an automated agent that runs without a human at the terminal.
What changed in Claude Code plugins in 2026?
The plugin system moved fast in the first half of 2026. The changes that actually affect how you build matter more than the version numbers, so here is what shifted, with the releases that introduced them.
- Auto-loading from
.claude/skills(v2.1.157, May 2026). The biggest one. You no longer need a marketplace to test a plugin. Drop it in.claude/skills, andclaude plugin initscaffolds the layout for you. defaultEnabled: falseand dependencies (v2.1.154). Plugins can ship disabled by default, and a plugin's dependencies auto-enable when you enable it./plugin listand richer hooks (v2.1.163, June 2026). A CLI command to list installed plugins, plusStopandSubagentStophooks that can returnadditionalContextto keep a turn going.- Marketplace search (v2.1.172, June 2026). A search bar inside
/pluginfor browsing large marketplaces. - Portable data and seed dirs (v2.1.78, v2.1.79).
${CLAUDE_PLUGIN_DATA}gives plugins a persistent data directory that survives updates, andCLAUDE_CODE_PLUGIN_SEED_DIRlets you start from a predefined plugin set.
I could not re-verify which release each of these landed in. Anthropic's public changelog only reaches back to v2.1.200, and these all predate that. The behaviour is verified against v2.1.233 by running it; treat the specific version pins as my notes from the time, not as citations.
Claude Code ships almost daily, so pin any exact version number against the official Claude Code changelog before you depend on it. The dates above reflect the changelog as of mid-2026.
If you want a worked example of a plugin that uses these newer hook capabilities to reshape its own behavior between turns, that is the whole story of my self-improving Claude Code system.
Troubleshooting common plugin errors
A few failures show up again and again when people build their first Claude Code plugin.
- Plugin loads but commands don't appear. Your command files are probably outside
commands/, or the frontmatter is malformed. Commands must be.mdfiles with valid YAML frontmatter directly in thecommands/directory. - Hook runs but can't find its script. You hardcoded an absolute path instead of using
${CLAUDE_PLUGIN_ROOT}. After cloning, the install path changes, so always reference scripts through that variable (and run a setup step if yourhooks.jsonbakes in real paths). - Plugin shows as disabled. Check for
defaultEnabled: falsein the manifest, then enable it through/plugin. This is intended behavior for plugins that ship off by default. - Changes don't take effect. Plugins load at startup. Use
/reload-pluginsto pick up edits without restarting Claude Code. ${CLAUDE_PLUGIN_ROOT}is empty in a script. That variable is only set for hook and command execution. If you call a script outside that context, pass the path in yourself.
Once it loads cleanly, you have a real, portable Claude Code plugin. Clone primeline-ai/evolving-lite to see a production-grade one with 16 commands, 6 agents, and 16 hooks wired together, and use it as the template for your own. It installs in about 30 seconds and it is MIT-licensed, so copy whatever you need.



![Open Source Alternative to Mem0 for Claude Code [2026]](/_next/image?url=%2Fblog%2Fopen-source-mem0-alternative-hero.webp&w=3840&q=75)