Plugins & marketplaces
You’ve spent the last month tuning the way you work with your agent: a deploy-checklist skill, a security-reviewer subagent, a hook that runs the linter after every edit, an MCP server pointed at your issue tracker, three slash commands for the team’s pre-merge workflow. It all lives in your tool’s dot-directory at the root of one repo. It works beautifully.
Then you start a second repo. You want the same setup, so you copy the directory across. Then a new teammate joins - “how do you get this stuff?” - and the answer is “clone my dotfiles, copy these directories, edit your settings file, install these MCP servers, oh, you also need…” The setup that worked beautifully in one repo doesn’t survive contact with anyone else’s filesystem.
A plugin is the packaging unit that closes that gap. It bundles a CLI’s extension primitives - skills, hooks, subagents, MCP servers, commands - into one installable thing, namespaced so two plugins don’t fight, distributed through a marketplace so your teammate runs one install command instead of following eleven steps.
What the tools disagree about is not whether that’s useful. It’s whether there’s a bundle at all, and what the bundle is allowed to contain. So “install this” means something different in each one, and in most of them part of your setup stays behind.
Real-world examples of what teams actually package as plugins:
- Team conventions bundle - your repo’s style guide as a skill, a pre-commit linting hook, a code-review subagent, an MCP server for your issue tracker. One install, whole-team consistency.
- Domain plugins - a “payments” plugin with PCI-aware skills, an audit-log hook, and a subagent that knows the payment processor’s API.
- Personal toolkit - your own
/tldr,/skeptic,/pre-shipcommands plus your favourite review subagent. Install on every machine you use, kept in sync via the marketplace. - Open-source plugins - community-maintained bundles for a specific stack (Rust + Tokio, Next.js + Drizzle, Django + Celery). Skill + agent + permissions tuned for that stack.
- Org-wide standards - managed-scope plugin installed on every dev’s machine: enforce the security hook, the audit MCP server, the approved-subagent list. The team has no choice about installing it.
- Workshop / tutorial materials - pin a known-good toolkit for a workshop so every attendee starts from the same baseline.
The test: if you’ve ever zipped up your agent’s dot-directory and emailed it to someone, or opened a message with “first, copy these files…”, you wanted a plugin.
Which pieces ride in the bundle
Section titled “Which pieces ride in the bundle”One team setup - a skill, a subagent, a hook, an MCP server, a slash command - and what happens to each piece when you ship it to a teammate. Read the pieces marked as loose files: those are the ones your teammate ends up missing.
Pi isn’t in the widget above. Its unit is a package, installed with pi install npm:<pkg> or pi install git:<repo>, carrying extensions, skills, prompt templates and themes together. MCP servers are the one piece it can’t bundle, because Pi has no native MCP at all.
Only Claude Code carries all five pieces. Everywhere else the honest install instruction has a second step - copy the agent files too, register the MCP server yourself, commit the commands directory - and the second step is the one people forget. Write it down somewhere the plugin can’t: a README next to the marketplace entry, or the repo it ships from.
What “install this plugin” actually does
Section titled “What “install this plugin” actually does”The word covers three different kinds of object, and they behave differently the moment you install one.
- A static bundle of files. Claude Code, Codex, Copilot, and Pi packages all ship content: directories of skills, hook definitions, MCP configs, agent files, named by a manifest. Codex makes the shape explicit -
.codex-plugin/plugin.json, one optional field per component type (skills,mcpServers,apps,hooks), each a path relative to the plugin root. The gotcha: the installed copy is not the repo you installed from. Claude Code copies plugins into~/.claude/plugins/cache/, so a path reaching outside the plugin’s own directory stops resolving after install. - Live code. An OpenCode plugin is a JS/TS module exporting a function that returns hook handlers and tool definitions. Installing one means the npm packages listed in
opencode.jsonare fetched with Bun at startup and cached in~/.cache/opencode/node_modules/. You aren’t copying content into place; you’re adding a program, and its dependencies, to the startup path. - Nothing native. Cursor has no bundle format for rules plus skills plus subagents plus hooks. Its packaging surfaces are inherited ones: OpenVSX-backed VS Code extensions, and the MCP Marketplace for servers. Sharing a Cursor setup means committing the
.cursor/*files and lettinggit pullbe the installer.
That difference decides what you can check before you trust someone else’s bundle: a static bundle reads as files, a live plugin has to be read as code. Either way the install isn’t free - every skill a bundle brings in contributes its description to the always-loaded part of the window in every session afterwards, so a twelve-skill plugin installed for one skill charges you for twelve.
Why this and not…
Section titled “Why this and not…”| You want to… | Reach for | Not |
|---|---|---|
| Bundle multiple primitives (skills + hooks + agents + MCP) as one unit | Plugin | Loose files |
| Share that bundle with teammates / a community | Plugin (via a marketplace) | A README with copy-paste instructions |
| Distribute just a single skill | A standalone skill folder (especially SKILL.md is cross-tool portable) | Wrapping it in a plugin |
| Add one MCP server | MCP config directly | Plugin-wrapping it |
| Enforce a configuration across the org | Managed-scope plugin (Claude Code) / managed config | Plugin marketplace alone |
| Add live event-handling code (OpenCode) | OpenCode plugin (JS/TS) | Static skill |
A plugin pays its weight when there are multiple extension pieces that belong together. A single skill or single hook doesn’t need a plugin wrapper - keep it as a loose file until you find yourself shipping it alongside something else.
How it works in each tool
Section titled “How it works in each tool”A plugin is a directory bundling some combination of:
- Skills (
skills/<name>/SKILL.md) - Subagents (
agents/<name>.md) - Hooks
- MCP servers
- Commands
Each plugin’s skills/commands are namespaced when installed - they appear as /my-plugin:cmd so multiple plugins coexist without colliding.
Marketplaces are hosted collections of plugins. You point Claude Code at a marketplace URL and browse/install from inside the CLI.
Marketplace commands:
/plugin marketplace add <owner/repo | git-url | local-path | marketplace.json-url>/plugin marketplace list/plugin marketplace update <marketplace-name>/plugin marketplace remove <marketplace-name>(/plugin market is a shortcut for /plugin marketplace; rm aliases remove.)
Plugin commands:
/plugin install <plugin>@<marketplace>/plugin enable|disable <plugin>@<marketplace>/plugin uninstall <plugin>@<marketplace>/reload-plugins # hot-reload without restartclaude plugin install <plugin>@<marketplace> --scope projectScopes: user (default), project (committed to .claude/settings.json), local (this repo, not shared), managed (admin-set).
On-disk layout: installed plugins are copied into a cache rooted at ~/.claude/plugins/cache/. Because plugins live in the cache (not their source repo), paths referencing files outside the plugin directory don’t work. Plugin skills are namespaced under the plugin (e.g. commit-commands exposes /commit-commands:commit). Project-scope marketplaces are registered in .claude/settings.json under extraKnownMarketplaces. The official Anthropic marketplace claude-plugins-official is auto-available.
Codex has a plugin system: a directory bundling some combination of skills, MCP servers, app connectors, and lifecycle hooks - browsed and installed from a marketplace.
A plugin is a directory with a manifest at .codex-plugin/plugin.json. Required fields: name (kebab-case, doubles as the plugin identifier), version, description. Optional fields point at bundled components, each a relative path from the plugin root:
skills→./skills/(portable skill folders)mcpServers→./.mcp.json(MCP server configs)apps→./.app.json(built-in connectors: Slack, GitHub, Google Drive, etc.)hooks→./hooks/hooks.json(lifecycle event handlers - Codex checks this default path even without a manifest entry)
There’s no agents field. Subagent definitions (.codex/agents/*.toml) aren’t a bundleable plugin component - they ship as loose files alongside a plugin, not inside one.
There’s also no dedicated “commands” field, and you don’t need one: standalone custom prompts in ~/.codex/prompts/ are themselves deprecated in favour of skills, so a plugin-bundled command is just a skill in ./skills/.
Install and browse: /plugins in the Codex CLI (also reachable from the ChatGPT app’s Plugins panel and the IDE extension’s Settings → Plugins). Plugin directories are organized into tabs - OpenAI-curated, workspace, and personal marketplace sources. Per-plugin enabled state is tracked in ~/.codex/config.toml, e.g. [plugins."team-stack@team-plugins"] enabled = false disables without uninstalling.
Marketplaces are marketplace.json files - locally at $REPO_ROOT/.agents/plugins/marketplace.json or ~/.agents/plugins/marketplace.json, or registered as a source in config.toml under [marketplaces.<name>]. A marketplace entry’s source can point at a local path, a Git repo (optionally pinned to a ref/sha), or an npm package.
As of 2026-07. This is a genuine addition - Codex didn’t have a plugin format before; the composition-by-hand path (skill + MCP server + SDK, wired up manually) is now the fallback, not the only option.
A plugin is a JS/TS module that exports a function. The function receives a context (project, client, $, directory, worktree) and returns a map of hook handlers and/or tool definitions.
export default ({ project, client, $ }) => ({ hooks: { 'file.edited': async (event) => { /* ... */ }, }, tools: { myCustomTool: { schema: /* Zod schema */, execute: async (input) => { /* ... */ }, }, },});Plugins are live JS code, not static bundles - closer in spirit to a VS Code extension than to a Claude Code plugin.
Discovery / loading. Two paths:
- Local files in
.opencode/plugins/(project) or~/.config/opencode/plugins/(global) - auto-loaded at startup. - npm packages listed under the top-level
pluginarray inopencode.json- installed automatically using Bun at startup (e.g."plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]). Packages and their dependencies are cached in~/.cache/opencode/node_modules/.
Slash commands. The plugin docs describe hook subscriptions (e.g. file.edited, tool.execute.before, session.created) and custom tool registration, but do not document slash-command registration as a plugin capability. Slash commands live in .opencode/commands/ as standalone markdown files.
Ecosystem. No official registry. The community index is awesome-opencode; the docs ecosystem page also links community plugins.
Cursor’s plugin surface is broader than its CLI peers because it inherits the VS Code extension model:
- Extensions - installed from Cursor’s OpenVSX-backed marketplace and from Anysphere-published mirrors of popular VS Code extensions. Microsoft’s official marketplace is not accessible. Coverage is meaningfully less than upstream VS Code; some extensions never ship to OpenVSX. Side-loading
.vsixfiles works for the ones that don’t. - MCP Marketplace - in-app browser plus cursor.directory with one-click install. This is the closest analog to a “skills/agents marketplace” for context-engineering content.
- Rules / Skills / Subagents / Commands - Cursor’s public marketplace documentation does not establish a central registry for these primitives. Treat community directories as community distribution and verify any official registry claim against current Cursor docs.
- Cursor Marketplace (general) - referenced in MCP docs as the surface for official, vetted MCP plugins.
There is no formal “plugin” abstraction that bundles rules + skills + hooks + subagents together (a community feature request exists at forum.cursor.com/t/151250). For now, sharing a Cursor configuration means sharing the relevant .cursor/* files directly.
Copilot has the densest plugin/marketplace surface of any CLI in foundations scope. Two distinct primitives, both shipping in 2026:
Copilot Extensions - @-invocable in Chat:
- Two flavors: Skillsets (lightweight, retrieval-focused) and Agents (full LLM-backed responders)
- Distributed via GitHub Marketplace (
github.com/marketplace?type=apps&copilot_app=true) - Invoked as
@extension-namein VS Code Chat - Built with the Copilot Extensions SDK
- Reference impls in the
copilot-extensionsorg
Copilot plugins (distinct from Extensions; preview as of 2026):
- Bundle agents + skills + hooks + MCP server configs + LSP configs into one installable unit
- Format shared between VS Code agent plugins and Copilot CLI plugins
- Distributed via plugin marketplaces - Copilot ships with two default marketplaces registered:
github/copilot-plugins(official) andgithub/awesome-copilot(community, 48+ plugins) - Marketplaces can be hosted on github.com, any Git server, or a local filesystem
- Enterprise admins can configure baseline plugins available to every user
MCP Registry (github.com/mcp) - curated, one-click MCP server install from inside the IDE. Separate from the plugin marketplace; MCP servers are a component plugins can ship, not a replacement for them.
awesome-copilot is the practical jump-off: real-world instructions, prompts, skills, agents, hooks, and plugins published by GitHub and the community.
Note the terminology overload: Extensions (Marketplace, @-invocable, Chat-centric) and plugins (marketplace-registered, bundle-of-everything) are different things with overlapping but distinct distribution mechanics.
Pi calls its distribution unit a package, and it’s the umbrella for everything installable: extensions, skills, prompt templates, and themes bundled together.
Install:
pi install npm:@scope/pkgpi install git:github.com/org/repoA package can carry any mix of the resource types Pi supports - a package might ship a couple of extensions (for hooks/tools), a skill or two, and a prompt template, all installed as one unit rather than managed separately.
This is Pi’s answer to plugin marketplaces elsewhere: no central registry ships with Pi itself, but the npm: and git: install forms mean anything published to npm or hosted in a git repo is installable without Pi-specific packaging infrastructure. Resource-path arrays in settings.json (packages, extensions, skills, prompts, themes - see Configuration) determine what actually loads from an installed package.
Comparison
Section titled “Comparison”| Aspect | Claude Code | Codex | OpenCode | Cursor | Copilot | Pi |
|---|---|---|---|---|---|---|
| First-class plugin format | Yes (static bundle) | Yes (skills + apps + MCP + hooks; subagents are not documented as a plugin component) | Yes (live JS/TS) | No (no rules + skills + agents + hooks bundle) | Yes (preview, 2026) | Yes - Pi packages |
| Bundles skills + hooks + agents + MCP | Yes | Partial - skills + hooks + MCP + app connectors; subagents are documented separately | Yes (via plugin code) | - | Yes (skills + agents + hooks + MCP + LSP) | Extensions + skills + prompts + themes (no MCP - no native MCP at all) |
| Namespacing | /plugin:cmd | Plugin name is the identifier; no documented skill/command invocation-prefix | Slash commands not a documented plugin capability | - | Plugin-scoped | Package-scoped |
| Distribution mechanism | Marketplaces | Marketplaces (marketplace.json: local path, Git repo, or npm source) | npm + community awesome-opencode index | OpenVSX extensions + MCP Marketplace (cursor.directory) | GitHub Marketplace (Extensions), plus plugin marketplaces (default: github/copilot-plugins, github/awesome-copilot) | pi install npm:<pkg> / pi install git:<repo> |
| Closest analogue (if no native plugins) | - | - (has native plugins now) | - | Share .cursor/* files directly | - | - (has native packages) |
Separate @-invocable extension surface | - | - | - | - | Copilot Extensions (Skillsets / Agents) via GitHub Marketplace | - |
Name collisions
Section titled “Name collisions”- A Claude Code plugin is a static bundle of files. An OpenCode plugin is live JS/TS code. They are not the same abstraction layer - one is content packaging, the other is event-driven code.
- In Copilot, Extensions and plugins are two distinct primitives that both ship in 2026. Extensions are
@-invocable Chat agents distributed via GitHub Marketplace; plugins are marketplace-registered bundles (skills + agents + hooks + MCP + LSP) for VS Code Chat and Copilot CLI. Don’t conflate them.
Start from what you already have. List the extension files in your busiest repo, check each one against your tool’s bundle above, and you end up with two lists: the pieces a plugin will carry, and the pieces your install instruction still has to name out loud. Package the first, write down the second, and the next teammate is one command and one short paragraph away from your setup rather than an afternoon.