Skip to content

Porting to Agent Plugins

skillsaw port converts Claude Code and Codex plugins to Agent Plugins v1 — the vendor-neutral plugin format — in place:

skillsaw port --to agent-plugin .

Point it at a single plugin, a marketplace, or any repository: every discovered plugin is converted. The port is additive — it writes a root plugin.json (and, when the plugin has a Claude .mcp.json, a portable mcp.json) and never modifies or removes the source format's files. Both formats coexist in the same directory, so Claude Code and Codex keep working exactly as before while any Agent Plugins client can now install the package.

$ skillsaw port --to agent-plugin .
✓ [plugins/release-notes] claude → plugin.json
✓ [plugins/release-notes] claude → mcp.json
  note: commands/ stay as client-specific content — Agent Plugins v1
        defines only skills and MCP servers
✓ [plugins/issue-triage] codex → plugin.json

Ported 2 packages; Agent Plugins validation passed.

What gets translated

  • Manifest metadataname, version, description, author, homepage, repository, license, and keywords carry over. A name that violates the Agent Plugins name rules (uppercase, underscores) is normalized, with a note. Dual-manifest plugins merge both sources, Claude values first.
  • MCP configuration.mcp.json servers become portable mcp.json entries: Claude's http transport maps to streamable-http, ${CLAUDE_PLUGIN_ROOT} becomes ${PLUGIN_ROOT} (or a ./ relative command), and servers the portable format cannot express (ws transport, shell-style commands, reserved environment names) are skipped with a note rather than silently dropped or mistranslated.
  • Skills — nothing to do: skills/*/SKILL.md is already the Agent Plugins location.
  • Commands, agents, hooks — stay behind as client-specific content; Agent Plugins v1 defines only skills and MCP servers.

Every port ends with the Agent Plugins rules (agent-plugin-json-valid, agent-plugin-mcp-valid) run over the output; the command fails if its own output doesn't validate. Use --dry-run to see the exact files before anything is written. A rerun over an already-ported tree is a no-op, and a root plugin.json that belongs to something else is never overwritten.

Marketplace catalogs

Agent Plugins v1 defines a package, not a marketplace — clients that discover plugins through a catalog need one alongside the ported packages. By default a multi-plugin port also writes Codex's .agents/plugins/marketplace.json, listing every ported plugin as a local source with the spec-recommended policy fields (and the category carried over from a Claude marketplace entry when one exists). Codex writing its catalog into the client-neutral .agents/ directory reads as a step toward a vendor-neutral catalog format, which makes it the reasonable one to emit until a real standard exists. An existing catalog is left untouched — codex-marketplace-registration's fix can append missing entries. Control it with --marketplaces (default codex, none to skip); more catalog formats can be added as marketplaces evolve.

Keeping it true: agent-plugin-required

The opt-in agent-plugin-required rule turns the one-time conversion into a standing guarantee. Enable it in .skillsaw.yaml:

rules:
  agent-plugin-required:
    enabled: true
    severity: error

It reports any plugin missing the portable manifest (fixable — skillsaw fix runs the same conversion), shared metadata that has drifted between the manifests, and a Claude MCP configuration with no portable counterpart. In CI, that means no plugin merges without the vendor-neutral format.