Howto codex

Static reading edition · s07-03

Write the right plugin manifest

Plugins26 min estimatedCodex app · CLI; plugins unavailable in IDE

Prepare a minimal portable package and distinguish it from supported compatibility layouts.

Understand the approach

New portable plugins use plugin.json at the package root. Skills live under the root skills/ directory; portable MCP configuration, when needed, uses root mcp.json with its transport declarations. A simple skills-only plugin can begin with identity fields and one SKILL.md. You do not need to scaffold unused servers, hooks, assets, or credentials. Keep the plugin's stable kebab-case name separate from a friendly display label.

Codex also supports a compatibility layout using .codex-plugin/plugin.json. The current creator can still scaffold that supported format with .mcp.json and optional resources. Do not rename the files mechanically and assume portability: the portable MCP format has its own schema and transport type. For a new manual package, follow the current portable guide; for an existing compatibility package, understand its actual manifest before changing it.

OpenAI-specific metadata belongs in extensions.com.openai in the portable root manifest. If that object is present, it replaces the compatibility overlay's OpenAI-specific settings rather than merging with it. Referenced resource paths must start with ./, resolve from the plugin root, and remain inside the package. Credentials do not belong in any manifest. A structurally valid file still needs workflow tests and source/license review.

The manifest identifies a package; components have their own files

The portable package root contains its manifest and components. Skill metadata lives in SKILL.md; optional MCP and hook configuration use their documented files. Validate the package and each referenced path rather than assuming a manifest makes every component executable.

The portable package root contains its manifest and components. Skill metadata lives in SKILL.md; optional MCP and hook configuration use their documented files. Validate the package and each referenced path rather than assuming a manifest makes every component executable.

Open the full diagram

Names, paths, and ownership are different checks

A stable name helps hosts identify the package; safe paths keep resources inside its boundary; a license explains permitted reuse. Passing one check does not imply the others. If adapting third-party material, retain its required notices and identify your modifications. Do not copy the source course's author identity into your own package as though you were that publisher. Use truthful metadata when a real release is prepared.

A concrete versioned change

The complete extension reference changes identity metadata only where needed: stable package name remains, version advances from 0.2.0 to 0.3.0, server metadata follows it, and the separate output schema accepts the added bounded fixture. The grader catches mismatches instead of accepting a version string in a release note.

About your environment

Verified October 21, 2026. Native metadata lifecycle tested on Windows with Codex CLI 0.163.0-alpha.11 in disposable child-only CODEX_HOME: starter 0.2.0 and extension 0.3.0 install/list/remove succeeded. Authenticated skill invocation, MCP inside Codex, hook trust/delivery, other platforms and publication were not run by the course author.

Try it step by step

  1. Inspect root plugin.json and mcp.json, their canonical schema provenance and the root skills directory.
  2. Validate the package; introduce a missing-name or invalid transport only in a generated copy, then repair it and retain both outputs.
  3. Inspect OpenAI-specific hook references and confirm package-root paths remain inside the package.
  4. Run the extension reference in a separate fresh workspace; confirm the manifest and server version both become 0.3.0 and the actual MCP enum exposes missing-both.
  5. Use the native installation track to inspect the installed version; do not call a schema check a host activation test.

A useful starting example

Illustration · adapt before use.

Example root plugin.json · inactive skills-only package text
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
  "name": "readme-review-practice",
  "version": "0.1.0",
  "description": "Review supplied README files for missing run and verification guidance."
}
From input to result

Portable stdio configuration

The local package launches its own bundled server, with no remote service.

Worked input text
{
  "mcpServers": {
    "workflowFixture": {
      "type": "stdio",
      "command": "node",
      "args": ["${PLUGIN_ROOT}/server.cjs"],
      "cwd": "${PLUGIN_ROOT}"
    }
  }
}
Expected result · compare with your run
Offline schema and path checks: pass. Native catalog/install metadata: observed in isolated CLI. Authenticated conversation MCP launch: not run.

The full file also declares the canonical MCP schema URL. The placeholder is supplied by the supported plugin host; it is not a shell variable to substitute manually.

Hands-on exercise

Your turn

Produce a before/after schema failure in a generated package, then repair it. Complete the bounded missing-both manifest/server/schema change and grade the actual protocol. Explain why a compatibility manifest cannot be converted by merely renaming files.

Try the exercise before opening its reference answer. Use a disposable practice folder.

Run the practice

Inspect a valid portable multi-component package

Extract into a new practice folder and keep the included labs folder. Run these commands from that extraction root, or from the course folder, using an existing Node.js installation.

  1. Command 1 text
    node labs/workflow-plugin/schema-check.cjs

    Check: Validates plugin.json and mcp.json against the bundled canonical schema snapshots and confirms the declared hook path remains inside the package.

  2. Command 2 text
    node --test labs/workflow-plugin/test.cjs

    Check: All 19 checks pass, including invalid-manifest and wrong-transport controls.

  3. Command 3 text
    node --test labs/workflow-plugin/depth.test.cjs

    Check: 5 checks pass, including starter failure, complete reference grading through actual stdio, preserved baseline suite and scope rejection.

Correct file names, transport declarations, and rooted paths make a package inspectable. Schema validation is one layer and does not establish runtime activation.

Check your result

  • The final manifest and MCP configuration match the bundled canonical schemas.
  • The negative control fails for the intended structural reason and the repaired copy passes.
  • No secrets, external endpoints, unexplained executables, or escaped resource paths are introduced.
Reference answer & rubric Try the exercise before opening

Keep a root portable manifest, a schema-correct stdio entry, a focused skill, and package-contained references.

  1. Inspect root plugin.json and identify its stable name, version, description, and extensions.com.openai local-executor and hook fields.
  2. Inspect mcp.json: type stdio, command node, the ${PLUGIN_ROOT}/server.cjs argument, and plugin-root cwd. Confirm the actual file exists.
  3. Run the cached-schema check without fetching packages. Explain that its evaluator supports the keywords in these snapshots and does not certify every future schema or OpenAI extension.
  4. Keep portable metadata separate from the supported .codex-plugin compatibility layout. If extensions.com.openai is present, do not assume compatibility overlay settings merge into it.
  5. Review every executable and packaged fixture before optional client installation. Credentials, unused endpoints, and external file paths have no place in this practice package.
Think it through

Check your understanding

Does a new portable skills-only manifest need a skills field?

  1. No; portable skills are discovered from the root skills/ directory.
  2. Yes; otherwise a server must be installed.
  3. Only if its filename starts with a dot.
Reveal the answer and explanation

Answer 1: No; portable skills are discovered from the root skills/ directory.

The current portable format uses fixed package locations. Compatibility manifests can use different declarations, so identify the format first.

Take this quiz in the interactive lesson to save your answer in the browser.

When it does not work

The manifest parses, but the server is not found after moving the folder.

Likely cause: A machine-specific or catalog-relative path replaced the plugin-root placeholder.

What to try: Use ${PLUGIN_ROOT} in the portable stdio entry and revalidate the actual scratch package.

A compatibility package loses interface or hook settings after migration.

Likely cause: The portable OpenAI extension replaces the compatibility overlay instead of merging it.

What to try: Move the required OpenAI-specific settings deliberately and check the final effective package; do not rename manifests mechanically.

Common mistakes

  • Mixing portable and compatibility manifest assumptions without checking which settings take precedence.
  • Copying a source .claude-plugin manifest or putting API keys into package metadata.
Source mapping & differences · different

Codex accepts a portable root manifest and supported compatibility format; source .claude-plugin paths and component declarations must be intentionally adapted.

Source topic: Plugin definition structure ↗

Go to the source

Official documentation, checked 21 October 2026. Product names, controls and availability may vary with your version, platform or account.

Continue in the interactive lesson →

Completion and quiz progress are saved
only in the interactive course.