# Plugin Marketplace Architecture Reference for refactoring this repo of skills/agents/hooks/prompts into a single Git-based plugin marketplace installable by **Claude Code** and **GitHub Copilot CLI**, and for building the `marketplace-architect` skill that automates the migration. > **Provenance & staleness:** Verified against the official Claude Code plugin docs > (`code.claude.com/docs`) and GitHub Copilot CLI plugin docs (`docs.github.com`) as of > **June 2026**. Both ecosystems are moving fast; re-verify the divergence table before a > big migration. One item below (Copilot reading `.claude-plugin/plugin.json` per-plugin) is > **explicitly unverified** — see the flagged note. Don't treat that part as settled. --- ## 1. Core model (this part is correct and stable) - The **Git repository is the marketplace.** No backend, registry API, database, SaaS, or MCP server is required. A marketplace is just a manifest file that lists plugins and where to find them. - A **plugin is the deployable unit.** Each plugin bundles one or more of: skills, agents, hooks, prompts/commands (flat `.md`), MCP servers, and — Claude Code only — output styles, LSP servers, background monitors, a `bin/` on PATH, and default `settings.json`. "Workflows" from the handoff aren't a distinct file type; express them as a skill that orchestrates steps, or a command. - **Organize by user outcome, not file type.** `startup-cto/` and `security-reviewer/`, not `all-skills/` and `all-agents/`. - **Aim for ~10–20 opinionated plugins**, not 50 tiny ones. (This is a usability judgment, not a hard rule from either vendor — but it's sound. Many skills can live inside one plugin.) The handoff's suggested set, as a starting shape: `startup-cto`, `system-architect`, `security-reviewer`, `product-manager`, `growth-marketer`, `developer-relations`, `technical-writer`, `research-analyst`. Everything below is where the original handoff was either wrong or incomplete. --- ## 2. The two tools are convergent, NOT identical This is the single most important correction. The handoff assumed "write once, run both." In reality the formats overlap heavily but diverge in specific, breaking ways. **Skills are the portable core; manifests and agents are where they split.** **Recommended stance:** make **Claude Code the source of truth** (it's the stricter, more fully-specified format) and treat "loads in Copilot CLI" as a **tested checklist item per plugin**, not an assumption. Encode the Copilot deltas (manifest location, `.agent.md` naming) explicitly in the architect skill rather than pretending the two are the same. This is more honest than "write once, run both" and stops surprises at install time. ### Divergence table (ground truth) | Concern | Claude Code | GitHub Copilot CLI | Portable choice | |---|---|---|---| | Marketplace manifest path | `.claude-plugin/marketplace.json` (required) | `.github/plugin/marketplace.json` (primary); **also reads `.claude-plugin/`** | Put it in `.claude-plugin/` — both read it. Optionally also `.github/plugin/`. | | Plugin manifest path | `.claude-plugin/plugin.json` (required; **only** plugin.json goes in this dir) | `plugin.json` at **plugin root** | ⚠️ See flagged note — may need it in **both** locations | | Skills | `skills//SKILL.md` | `skills//SKILL.md` | ✅ Identical — lean on these | | Agents | `agents/.md` | `agents/.agent.md` (frontmatter incl. `tools:`) | Diverges — keep portable logic in skills; ship per-tool agent files only when needed | | Hooks | `hooks/hooks.json` | `hooks.json` at plugin root | Diverges; declare paths in manifest to be safe | | MCP servers | `.mcp.json` at plugin root | `.mcp.json` at plugin root | ✅ Same | | Relative `source` | must start with `./` | `./x` and `x` both valid | Always use `./` — valid for both | | Validate command | `claude plugin validate .` (or `/plugin validate .`) | none documented | Claude validator + custom JSON checks for Copilot | | Install marketplace | `claude plugin marketplace add owner/repo` | `copilot plugin marketplace add owner/repo` | Same shape | | Install plugin | `claude plugin install @` | from a registered marketplace by plugin name; **`@marketplace` suffix not confirmed** — `update`/`uninstall` take a bare ``, so don't assume Claude's `@marketplace` form | ⚠️ Verify the Copilot install string before documenting it | | Local install (dev) | `claude --plugin-dir ./plugin` | `copilot plugin install ./plugin` | Tool-specific | > ⚠️ **FLAGGED / UNVERIFIED — test this by hand before committing to a layout.** > Copilot's docs explicitly confirm it falls back to reading the **marketplace** manifest from > `.claude-plugin/`. They do **not** confirm the same fallback for an individual plugin's > `plugin.json`; the Copilot docs only show `plugin.json` at the plugin root. Claude *requires* > it in `.claude-plugin/`. Until you verify, the pragmatic move is to **ship `plugin.json` in > both** `plugin-name/plugin.json` and `plugin-name/.claude-plugin/plugin.json` (identical > content), then drop whichever proves redundant. The architect skill should generate both and > note the duplication. ### `@` resolves to the manifest `name`, not the repo `claude plugin install startup-cto@my-ai-marketplace` requires the marketplace manifest's top-level `name` field to be exactly `my-ai-marketplace`. It is **not** the GitHub repo name. Keep them aligned to avoid confusion, but know they're separate things. --- ## 3. Canonical repo layout (cross-compatible) ```text repo-root/ ├── .claude-plugin/ │ └── marketplace.json # both tools read here ├── .github/plugin/ │ └── marketplace.json # OPTIONAL: Copilot's canonical path (mirror of above) ├── plugins/ │ └── startup-cto/ │ ├── plugin.json # Copilot root manifest ┐ ship both until │ ├── .claude-plugin/ # │ the §2 note is │ │ └── plugin.json # Claude manifest ┘ verified │ ├── skills/ │ │ ├── fundraising/SKILL.md │ │ └── hiring/SKILL.md │ ├── agents/ │ │ ├── startup-cto.md # Claude │ │ └── startup-cto.agent.md # Copilot (only if you ship native agents) │ ├── hooks/hooks.json # Claude │ ├── hooks.json # Copilot (if hooks used) │ ├── docs/ │ └── README.md └── README.md ``` If maintaining two manifest copies is annoying, generate the mirrors from one source in CI (see §7) rather than hand-editing both. ### Manifest shapes `marketplace.json` (root): ```json { "name": "my-ai-marketplace", "owner": { "name": "Your Name", "email": "you@example.com" }, "metadata": { "description": "Agents, skills and workflows", "version": "1.0.0" }, "plugins": [ { "name": "startup-cto", "source": "./plugins/startup-cto", "description": "..." }, { "name": "system-architect", "source": "./plugins/system-architect", "description": "..." } ] } ``` `plugin.json` (keep minimal; add fields only when needed): ```json { "name": "startup-cto", "version": "1.0.0", "description": "Startup technical leadership toolkit", "author": { "name": "Your Name" } } ``` Plugin names must be **kebab-case** (lowercase, digits, hyphens). Claude.ai's marketplace sync rejects anything else even though the local CLI may tolerate it. --- ## 4. Gotchas the original handoff omitted These will cause real breakage during refactor. The architect skill must check for them. 1. **Plugins are copied to a cache on install.** A plugin **cannot** reference files outside its own directory (e.g. `../shared-utils`) — those files aren't copied. If your current repo shares helper files across skills/agents, that sharing breaks. Fix by **duplicating** the shared file into each plugin or using **symlinks**. Audit for cross-references before moving anything. 2. **Version-pinning footgun.** If `plugin.json` sets `"version"` and you don't bump it on a new release, existing users get **no update** — the cached copy is kept. Either bump every release, or **omit `version`** so the git commit SHA is used (every commit = new version). Don't set `version` in both `plugin.json` and the marketplace entry; the `plugin.json` value wins silently. 3. **Reserved marketplace names.** Claude blocks a set of names (`anthropic-*`, `claude-*`, `agent-skills`, and impersonators like `official-claude-plugins`). Validate against these. 4. **`commands/` ≠ `skills/` in Claude.** A flat `foo.md` is a legacy *command*; a `foo/SKILL.md` directory is a *skill*. Promote flat command files to skill directories during migration — don't treat them as interchangeable. 5. **Use `${CLAUDE_PLUGIN_ROOT}`** in Claude hook/MCP configs to reference in-plugin files, since the plugin runs from a cache path, not its repo location. 6. **Strict mode (Claude).** A marketplace plugin entry defaults to `strict: true` — `plugin.json` is authoritative and the entry can only supplement it. Set `strict: false` to make the marketplace entry the *entire* definition (it then declares `skills`/`agents`/`hooks`/`mcpServers` path arrays itself, and the plugin needs no `plugin.json`). Useful when the architect curates a plugin's exposed components differently from how the files are laid out. Don't mix the two — a `strict:false` entry plus a component-declaring `plugin.json` is a conflict and fails to load. 7. **Plugin sources beyond relative paths (Claude).** This repo uses `./plugins/x` relative sources (simplest for a monorepo). If you later split a plugin into its own repo, the `source` field also supports `github` (`owner/repo` + `ref`/`sha`), `git-subdir` (sparse clone of a monorepo path), `url` (any git host), and `npm` (published package). Copilot's docs only *show* relative-path sources — other source types aren't documented there, so don't rely on them cross-tool. Stay on relative paths unless you have a reason not to. 8. **Copilot declares component paths in `plugin.json` (Claude does it differently).** Copilot's `plugin.json` can carry `"skills": "skills/"`, `"agents": "agents/"`, `"hooks": "hooks.json"`, `"mcpServers": ".mcp.json"` fields that tell it where components live. Claude instead defaults to the standard dirs and only takes path overrides via the *marketplace entry* (see strict mode, #6). So the same `plugin.json` may need these path fields for Copilot but not for Claude — another reason the architect should generate per-tool manifests rather than one shared file. --- ## 5. The `marketplace-architect` skill spec Build this skill **on the corrected spec above** — not on the original handoff, which would bake in the format errors. It's a Claude Code skill (`skills/marketplace-architect/SKILL.md`) following standard skill conventions: a tight SKILL.md body (<500 lines) plus bundled `references/` and `scripts/` loaded progressively. ### Frontmatter (description is the trigger — make it pushy) ```yaml --- name: marketplace-architect description: > Audits a repository of Claude Code / Copilot CLI skills, agents, hooks, and prompts and refactors it into an installable plugin marketplace. Use this whenever the user wants to organize loose skills/agents into plugins, define plugin boundaries, generate plugin.json or marketplace.json manifests, plan a migration to a plugin marketplace, validate plugin naming or detect duplicate capabilities, or set up cross-tool (Claude Code + GitHub Copilot CLI) distribution — even if they don't say the word "marketplace". --- ``` ### Responsibilities (from the handoff, refined) 1. **Audit** — walk the repo; classify every asset as skill / command / agent / hook / prompt / MCP. 2. **Detect cross-references** — flag any `../` or shared-file dependencies that break under caching (§4.1). 3. **Recommend plugin boundaries** — group by outcome; warn on 50-tiny-plugins sprawl. 4. **Prevent duplicate capabilities** — diff skill descriptions/agents for overlap before splitting. 5. **Generate manifests** — emit `plugin.json` (both locations per §2 note) and `marketplace.json` (`.claude-plugin/`, optionally mirror to `.github/plugin/`). 6. **Validate naming** — kebab-case, reserved names, unique plugin names, `@name` ↔ manifest `name`. 7. **Produce a migration plan** — concrete file-move list (old path → new path) as a checklist. 8. **Emit cross-tool deltas** — for each plugin, note what's needed for Copilot (`.agent.md`, root `plugin.json`) vs Claude. 9. **Generate release notes + install docs** — per-plugin README with both `claude` and `copilot` install commands. ### Suggested bundled structure ```text skills/marketplace-architect/ ├── SKILL.md ├── references/ │ ├── claude-code.md # Claude paths, validate, version rules, reserved names │ ├── copilot-cli.md # Copilot paths, .agent.md, marketplace fallback │ └── cross-compat.md # the §2 divergence table — the heart of the skill └── scripts/ ├── inventory.py # scan repo → classify assets → emit a table ├── gen_manifests.py # write plugin.json + marketplace.json (both layouts) └── validate.py # wraps `claude plugin validate .` + JSON/naming checks ``` Put the §2 divergence table verbatim into `references/cross-compat.md` — that's the knowledge the skill exists to apply. Keep SKILL.md to the workflow (audit → boundaries → generate → validate) and point it at the reference files. ### Authoring notes - Use **imperative** instructions ("Scan the repo", "Emit the manifest"). - Explain *why* a rule matters (e.g. the cache constraint) rather than bare MUSTs — the model applies judgment better with rationale. - After drafting, run 2–3 realistic test prompts (e.g. "turn this repo into a marketplace", "which of these skills belong together?") and iterate. --- ## 6. Refactor playbook (corrected phases) Run these *with* the architect skill once it exists; it automates 1–5. 1. **Inventory.** Classify every asset (skill/command/agent/hook/prompt/MCP). Record current path. 2. **Detect breakage.** Find cross-references and shared files (§4.1). Decide duplicate vs symlink. 3. **Draw boundaries.** Group by outcome into ~10–20 plugins. De-dupe overlapping capabilities. 4. **Move files.** - `skills/react.md` (flat command) → `plugins/system-architect/skills/react/SKILL.md` - `agents/startup-founder.md` → `plugins/startup-cto/agents/startup-founder.md` (+ `startup-founder.agent.md` if shipping Copilot-native agents) 5. **Generate manifests.** Per-plugin `plugin.json` (both locations); root `marketplace.json`. 6. **Validate.** `claude plugin validate .` — fix every warning. Then test-install in both tools: - `claude --plugin-dir ./plugins/` then `/plugin install @` - `copilot plugin install ./plugins/` then `copilot plugin list` / `/skills list` / `/agent` 7. **Document.** Per-plugin README with both install commands; root README listing all plugins. --- ## 7. Future / roadmap (preserved from the handoff) Three post-migration features the original handoff called for. Not needed for the first cut, but recorded here so the intent isn't lost. ### Marketplace website Generate a docs site **directly from `marketplace.json`** — no separate content source. Iterate over the `plugins` array to produce a browsable catalog (one page per plugin from its `description`/`README.md`), publishable to something like `marketplace.example.com` via GitHub Pages. Because the manifest is the single source of truth, the site never drifts from what's installable. ### Plugin templates Add a `templates/` directory so contributors never start from scratch: ```text templates/ skill-plugin/ # plugin.json + skills//SKILL.md skeleton agent-plugin/ # plugin.json + agents/ skeleton (both .md and .agent.md) workflow-plugin/ # plugin.json + a multi-step orchestration skill ``` Each ships the dual-manifest layout from §3 so new plugins are cross-tool by default. ### CI validation (the cross-tool catch) A GitHub Action can gate PRs, but remember: **`claude plugin validate` covers the Claude side only.** There's no Copilot validator, so the Action needs custom JSON checks for the Copilot layout. Minimum checks: - Valid JSON in every `marketplace.json` / `plugin.json`. - Each plugin's `SKILL.md` files have valid YAML frontmatter. - Unique plugin names; kebab-case; no reserved names. - Every `source` path resolves to an existing directory. - (If mirroring) `.claude-plugin/` and `.github/plugin/` manifests are in sync. - Version consistency (no conflicting `version` in plugin.json vs marketplace entry). Fail the PR on any violation so the contributor flow stays self-service. ### Success criteria (the target end-state) A new contributor should be able to, with **no manual registry edits, no backend, no MCP dependency**: (1) fork the repo, (2) create a plugin folder, (3) add `plugin.json`, (4) add skills/agents, (5) open a PR, (6) have the plugin appear in the marketplace automatically once merged. If a step requires hand-editing a central list, the automation isn't done. --- ## Open questions to resolve first Two facts couldn't be confirmed from the published docs. Settle both with a one-skill test plugin before the architect generates layouts: 1. **Does Copilot CLI load a plugin whose `plugin.json` lives only in `.claude-plugin/`?** (Install the test plugin both ways.) The answer decides whether you ship one manifest or two. Copilot's docs put `plugin.json` at the plugin root; Claude requires `.claude-plugin/`. 2. **What is Copilot's exact install-from-marketplace command?** The how-to pages don't show the literal string, and Copilot's `update`/`uninstall` take a bare plugin name — so it may *not* use Claude's `@` form. Run `copilot plugin install --help` and confirm before putting the command in any README or the architect's generated docs.