Skip to content

feat: build one Agent Plugins package for several clients - #42

Merged
steve-calvert-glean merged 3 commits into
mainfrom
feat/multi-client-packages
Oct 21, 2026
Merged

steve-calvert-glean merged 3 commits into
mainfrom
feat/multi-client-packages

Conversation

@steve-calvert-glean

@steve-calvert-glean steve-calvert-glean commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The codex target builds an Agent Plugins package with one client profile and one marketplace, and the agent-plugins target builds packages with none. Codex, GitHub Copilot, VS Code and Cursor all read Agent Plugins packages, so a plugin built once could serve all of them. pluginpack had no way to write more than one client's marketplace and client-only files for the same package.

Change

Adds clients to the agent-plugins target (ADR 0002):

"agent-plugins": {
  outDir: "dist/agent-plugins",
  clients: { codex: {}, copilot: {} },
  plugins: {
    acme: {
      source: "shared/acme",
      manifest: { extensions: { "com.openai": { interface: { displayName: "Acme" } } } },
      clients: { codex: { entry: { policy: { installation: "AVAILABLE", authentication: "ON_INSTALL" }, category: "Productivity" } } },
    },
  },
},
  • Each plugin is built once: plugin.json, mcp.json, skills/.
  • Each listed client gets its marketplace: Codex .agents/plugins/marketplace.json, Copilot .github/plugin/marketplace.json.
  • Client-only kinds a listed client loads go in its extension directory. Copilot agents go to com.github.copilot/agents/NAME.agent.md, renamed from NAME.md.
  • validate checks every package, then each client marketplace that's present. Every entry must point at a package with the same plugin.json name, and Copilot agents need a valid name and frontmatter.
  • Without clients, the target still writes packages only. One config change applies with or without clients: the target-level manifest and per-plugin entry are now config errors, because the target writes no shared marketplace. Move them to clients.<client>.manifest and plugins.<name>.clients.<client>.entry. Before, they were accepted and ignored. agent-plugins is unreleased (it landed after v0.11.1), so no released config breaks. Other targets don't change: Glean's claude, cursor and codex output is byte-identical to main (191 files).

Layout facts for each client are cited in src/package-clients.ts (Copilot CLI plugin reference, retrieved 2026-10-20) and CONFORMANCE.md.

Verification

  • npm run check passes with 292 tests on Node 24, and CI runs it on the 22.12.0 floor.
  • Tests cover the build, the config errors, the validate errors, and a conformance test against the vendored Agent Plugins schemas.
  • End to end with the Glean plugin: Copilot CLI 1.0.100 installs it from the generated marketplace (glean@glean-plugins, 19 skills, MCP server registered), and Codex 0.160.1 installs the same package from its marketplace.

Known gaps

  • install-info still reports no install command for agent-plugins. It will be updated when the Copilot plugin publishes.
  • Copilot loading the agents in a signed-in session is untested.

@steve-calvert-glean steve-calvert-glean added the enhancement New feature or request label Oct 20, 2026
@steve-calvert-glean
steve-calvert-glean force-pushed the feat/multi-client-packages branch from 0981713 to ba7228e Compare October 21, 2026 01:08
The codex target builds an Agent Plugins package with one client profile
and one marketplace, and the agent-plugins target builds packages with
none. Codex, Copilot, VS Code and Cursor all read the format, so a plugin
built once can serve them all, given each client's marketplace file and
client-only files.

Add `clients` to the agent-plugins target (ADR 0002):

- `clients: { codex: {}, copilot: {} }` writes each client's marketplace:
  Codex .agents/plugins/marketplace.json, Copilot
  .github/plugin/marketplace.json. `clients.<client>.manifest` and
  `plugins.<name>.clients.<client>.entry` are deep-merged into them. The
  shared `entry` and target `manifest` are config errors on agent-plugins
  that name the client-scoped field instead.
- Client-only kinds a listed client loads are selected by default and
  written to its extension directory: Copilot agents go to
  com.github.copilot/agents/, with .md, .markdown and .mdc renamed to
  NAME.agent.md. Any other file in agents/, or two files that land on
  the same path, fail the build.
- A client-only kind that no listed client loads stays a config error,
  and the message names the client that would load it. A file of such a
  kind that arrives another way, such as additionalFiles, fails the
  build. Client names are checked strictly, a client set to undefined
  counts as not listed, and `clients` is rejected on other targets.
- validate checks each client marketplace present: entries, including
  structured local Codex sources, must point at a package whose
  plugin.json has the same name. Copilot needs a marketplace owner, and
  its agents need NAME.agent.md names and valid frontmatter.
- src/package-clients.ts holds each client's namespace, marketplace,
  file placement and validation, with citations to the client docs.
- The engine gains two optional hooks, clientMarketplaces and placeFile.
  Other targets don't set them, and Glean's claude, cursor and codex
  output is byte-identical (191 files).

Verified end to end with the Glean plugin: Copilot CLI 1.0.100 and Codex
0.160.1 both install it from their marketplace in the same output.
@steve-calvert-glean
steve-calvert-glean force-pushed the feat/multi-client-packages branch from ba7228e to 6f9a02f Compare October 21, 2026 17:25
…es paths

With clients set, hooks/hooks.json from additionalFiles skipped the client-only guard and shipped at the package root. A target that defines placeFile now places hooks too.

An additionalFiles destination starting with ./ could silently replace a placed file. Destinations are now normalized, and the collision check keys on the output path.

Also: reword client-only errors to say pluginpack doesn't place the kind yet, test that metadata.owner wins over metadata.author for Copilot, and document the manifest and entry errors, Copilot agent checks, and new marketplace collisions in README, CLAUDE.md and the config skill.
@steve-calvert-glean
steve-calvert-glean marked this pull request as ready for review October 21, 2026 19:56
@steve-calvert-glean
steve-calvert-glean merged commit c8826be into main Oct 21, 2026
3 checks passed
@steve-calvert-glean
steve-calvert-glean deleted the feat/multi-client-packages branch October 21, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant