Plugin Marketplaces

Copy Markdown View Source

Codex.Plugins.Marketplace models the local .agents/plugins/marketplace.json file used by Codex discovery.

Canonical Shape

Use nested policy.* fields for every plugin entry:

{:ok, marketplace} =
  Codex.Plugins.new_marketplace(
    name: "repo-marketplace",
    interface: [display_name: "Repo Plugins"],
    plugins: [
      [
        name: "demo-plugin",
        source: [source: :local, path: "./plugins/demo-plugin"],
        policy: [installation: :available, authentication: :on_install],
        category: "Productivity"
      ]
    ]
  )

The SDK writes:

  • policy.installation
  • policy.authentication
  • optional policy.products

It does not emit legacy top-level installPolicy or authPolicy as the canonical output shape.

Safe Updates

Use add_marketplace_plugin/3 for read-modify-write updates:

{:ok, result} =
  Codex.Plugins.add_marketplace_plugin(
    "/repo/.agents/plugins/marketplace.json",
    name: "demo-plugin",
    source: [source: :local, path: "./plugins/demo-plugin"],
    policy: [installation: :available, authentication: :on_install],
    category: "Productivity"
  )

Behavior:

  • preserves unrelated plugin entries
  • preserves unknown forward-compatible keys where possible, including overwrite updates on an existing entry
  • preserves optional compatible metadata such as policy.products unless you replace it explicitly
  • refuses duplicate plugin names unless overwrite: true
  • writes deterministic pretty JSON with a trailing newline

Path Rules

Marketplace source paths must:

  • start with ./
  • reject traversal segments such as .., even when the expanded path would still land under the marketplace root
  • stay within the marketplace root
  • resolve relative to the root owning .agents/plugins/marketplace.json

The root-containment check runs on read, write, and update flows when the actual marketplace path is known.

For repo scope that means:

  • marketplace: <repo-root>/.agents/plugins/marketplace.json
  • plugin source path: ./plugins/<plugin-name>

For personal scope that means:

  • marketplace: ~/.agents/plugins/marketplace.json
  • plugin source path: ./plugins/<plugin-name>

Verification Workflow

Recommended split:

  1. Author locally with Codex.Plugins.*.
  2. Start codex app-server only if you want runtime verification.
  3. Verify discovery with plugin/list.
  4. Verify details with plugin/read.

The local authoring layer and the runtime verification layer share validation vocabulary where it is stable, but they remain separate APIs.