{"slug": "why-can-t-we-agree-on-a-plugin-format", "title": "Why Can't We Agree on a Plugin Format?", "summary": "A developer has created a template repository to solve the problem of incompatible plugin formats across coding assistants like Claude Code, GitHub Copilot CLI, and OpenCode, which require different packaging formats and manual editing to transfer plugins. The project aims to let users author a complete plugin once and have it work with each tool's native install flow, addressing a gap in existing solutions that only handle skills or prompts.", "body_md": "I switch between coding assistants from time to time. Sometimes it’s Claude Code, sometimes it’s GitHub Copilot CLI, or occasionally I’m playing with OpenCode on a side project. Each one is good at different things, and I like having the option to switch between them.\n\nWhat I don’t like is the tax I pay every time I move my own plugins between them.\n\n## The annoying part[#](#the-annoying-part)\n\nMy plugins aren’t anything fancy. A handful of skills and agents, plus a few MCP servers here and there. Stuff I’ve built up over time and want available wherever I happen to be typing that day.\n\nThe problem is that every tool has its own packaging format:\n\n**Claude Code** wants a`.claude-plugin/`\n\ndirectory, a`marketplace.json`\n\nregistry, and skill/agent markdown files with very specific frontmatter.**Copilot CLI** wants a`plugin.json`\n\nmanifest with its own schema, plus a`.github/plugin/marketplace.json`\n\nregistry to be discoverable.**Codex CLI** uses yet another layout under`~/.codex/`\n\n.**OpenCode** has no marketplace concept at all. Each plugin is just files you drop into a project’s`.opencode/`\n\nfolder.\n\nThe differences are small on their own (a field gets renamed in one tool, a directory moves in another, frontmatter keys swap around), but copy-pasting one plugin into the layout another tool expects still takes about fifteen minutes of fiddly editing every time. And I have to do it again on each of my dev machines. Multiply by a few plugins and the friction adds up fast… and then when I want to switch back… well, you get the idea.\n\n## What other people are doing[#](#what-other-people-are-doing)\n\nBefore I built anything, I poked around to see how other people were solving this. There’s a fair bit going on, but most of it didn’t directly address my problem.\n\nThe biggest projects in this space are large skills libraries that handle the cross-tool install for you. [ alirezarezvani/claude-skills](https://github.com/alirezarezvani/claude-skills) and\n\n[both ship hundreds of](https://github.com/borghei/Claude-Skills)\n\n`borghei/Claude-Skills`\n\n`SKILL.md`\n\nfiles plus install scripts (`./scripts/convert.sh --tool all`\n\n, `npx @borghei/claude-skills add ...`\n\n) that drop the right thing into each tool’s expected directory. They cover 9–11 assistants between them and they clearly work, which is why they have thousands of stars. The catch is they’re skills-only. A skill is one thing in a plugin. Agents, MCP server configs, hooks, slash commands, and the marketplace registry that tells `/plugin install`\n\nwhat’s available are different things, and those libraries don’t handle them. They also assume Claude’s `SKILL.md`\n\nschema as the canonical source and convert outward, which is fine until you want to author in a tool-neutral format.[ Happier](https://guides.happier.dev/how-to-keep-prompts-and-skills-in-sync-across-claude-code-codex-and-opencode) is a companion app that treats your prompt/skill library as the source of truth and exports it to provider-native locations on each machine. It’s a thoughtful approach if you want a long-lived app managing your library, but again the surface is prompts and skills, not full plugin bundles.\n\nA few people are reaching for [ symlinks](https://understandingdata.com/posts/symlinked-agent-configs/), keeping one master file and linking it into each tool’s expected path. That only solves the case where the files are\n\n*identical*across tools. But a lot of the providers have different frontmatter requirements, and some have fields the others don’t support.\n\nThese are all really cool projects. They just don’t solve the specific thing I was hitting: I wanted to author a complete plugin (skills, agents, hooks, MCP, plus the marketplace metadata) once, and let each tool’s native `/plugin install`\n\nflow consume it without me hand-editing four versions every time something changed.\n\n## The template repo[#](#the-template-repo)\n\n[ plugin-marketplace-template](https://github.com/jrob5756/plugin-marketplace-template) is a GitHub template repository I created to help eliminate some of this toil. You click “Use this template,” get your own copy, and that copy is a working plugin marketplace from day one. It’s a template because it doesn’t actually contain any plugins, just the scaffolding to make it easy to add your own and keep them in sync across tools.\n\nYou author each plugin once:\n\n```\nplugins/<name>/\n  plugin.yaml             # declarative manifest, with per-target overrides\n  agents/<agent>.md       # body only, no frontmatter\n  skills/<skill>/SKILL.md # body only\n  .mcp.json               # optional\n  hooks/hooks.json        # optional\n```\n\nThen `npm run build`\n\nruns a small Node transpiler that produces:\n\n```\ndist/claude/<name>/      → Claude Code plugin\ndist/copilot/<name>/     → Copilot CLI plugin\ndist/codex/<name>/       → Codex CLI plugin\ndist/opencode/<name>/    → OpenCode bundle\n```\n\n…and regenerates the per-tool marketplace registries (`.claude-plugin/marketplace.json`\n\n, `.github/plugin/marketplace.json`\n\n) so each assistant’s `/plugin install`\n\nflow just works.\n\nThe `dist/`\n\ndirectory is committed on purpose. The generated marketplace files point at `./dist/<target>/<plugin>`\n\nas the plugin source, and the tools resolve those paths over the remote git tree. So the downstream loop is: edit `plugins/`\n\n, run `npm run build`\n\n, commit both, push. That’s the whole workflow.\n\nAdding a fifth target later (Gemini CLI, Cursor, whatever) is a drop-in transpiler. There’s a section in the `AGENTS.md`\n\nwalking through what to implement and where the tests live.\n\n## Using it[#](#using-it)\n\nOnce you’ve created your marketplace from the template, point each tool at it:\n\n**Claude Code**\n\n```\n/plugin marketplace add <you>/my-plugins\n/plugin install my-skill@my-plugins\n```\n\n**Copilot CLI** and **Codex CLI** follow the same flow. Register the marketplace, then install.\n\n**OpenCode** has no marketplace concept, but each `dist/opencode/<plugin>/`\n\nfolder ships with a README explaining how to drop it into a project’s `.opencode/`\n\ndirectory.\n\nOn every new dev machine, the only setup is configuring the tool to know about your marketplace. The plugins themselves come along for the ride.\n\n## Keeping forks in sync[#](#keeping-forks-in-sync)\n\nOne thing I wanted to get right was upstream syncing. GitHub doesn’t give template-derived repos a “Sync fork” button (that’s a fork-only feature), so the template ships with a `.gitattributes`\n\nthat marks downstream-owned paths (`plugins/**`\n\n, `marketplace.yaml`\n\n, `dist/**`\n\n) as `merge=ours`\n\n. After a one-time `git remote add template ...`\n\n, pulling in upstream tooling improvements is `git fetch template && git merge template/main`\n\n, and your own plugins stay untouched while the build tooling, schemas, and docs flow through cleanly.\n\n## If something better comes along[#](#if-something-better-comes-along)\n\nHonestly, I’d love for this template to become unnecessary. The long-term answer is for the tools to converge on a shared plugin format. If that happens, I’ll archive the repo and move on happily :).\n\nUntil then, this is what I’m using to keep my own plugins portable, and I figured I’d put it out there in case it’s useful to anyone else. If you’ve built something similar, or you have a better idea, I’d like to hear about it. The repo is on [GitHub](https://github.com/jrob5756/plugin-marketplace-template). Issues and PRs welcome.", "url": "https://wpnews.pro/news/why-can-t-we-agree-on-a-plugin-format", "canonical_source": "https://jasonrobert.dev/blog/2026-06-04-why-cant-we-agree-on-a-plugin-format/", "published_at": "2026-06-15 15:23:52+00:00", "updated_at": "2026-06-15 15:38:22.194023+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "ai-agents"], "entities": ["Claude Code", "GitHub Copilot CLI", "OpenCode", "Codex CLI", "plugin-marketplace-template", "alirezarezvani/claude-skills", "borghei/Claude-Skills", "Happier"], "alternates": {"html": "https://wpnews.pro/news/why-can-t-we-agree-on-a-plugin-format", "markdown": "https://wpnews.pro/news/why-can-t-we-agree-on-a-plugin-format.md", "text": "https://wpnews.pro/news/why-can-t-we-agree-on-a-plugin-format.txt", "jsonld": "https://wpnews.pro/news/why-can-t-we-agree-on-a-plugin-format.jsonld"}}