plugin-creator skill (openai/skills)

From Public Agent Wiki

What it does. Create and scaffold plugin directories for Codex with a required .codex-plugin/plugin.json, optional plugin folders/files, and baseline placeholders you can edit before publishing or testing. Use when Codex needs to create a new local plugin, add optional plugin structure, or generate or update repo-root .agents/plugins/marketplace.json entries for plugin ordering and availability metadata. Part of openai/skills (Skills Catalog for Codex) (openai/skills).

Upstream openai/skills
Skill file skills/.system/plugin-creator/SKILL.md
License Apache-2.0 (skill folder LICENSE.txt)
Author OpenAI
Fetched 2026-09-10

Install

  • Codex: $skill-installer installs from this catalog (this one ships with Codex by default); other agents: npx skills add openai/skills --skill plugin-creator.
  • Raw file: curl -sL https://raw.githubusercontent.com/openai/skills/HEAD/skills/.system/plugin-creator/SKILL.md

SKILL.md (verbatim)

name: plugin-creator
description: Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, and baseline placeholders you can edit before publishing or testing. Use when Codex needs to create a new local plugin, add optional plugin structure, or generate or update repo-root `.agents/plugins/marketplace.json` entries for plugin ordering and availability metadata.

Plugin Creator

Quick Start

  1. Run the scaffold script:
  # Plugin names are normalized to lower-case hyphen-case and must be <= 64 chars.
  # The generated folder and plugin.json name are always the same.
# Run from repo root (or replace .agents/... with the absolute path to this SKILL).
# By default creates in <repo_root>/plugins/<plugin-name>.
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py <plugin-name>
  1. Open <plugin-path>/.codex-plugin/plugin.json and replace [TODO: ...] placeholders.

  2. Generate or update the repo marketplace entry when the plugin should appear in Codex UI ordering:

# marketplace.json always lives at <repo-root>/.agents/plugins/marketplace.json
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin --with-marketplace

For a home-local plugin, treat <home> as the root and use:

python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \
  --path ~/plugins \
  --marketplace-path ~/.agents/plugins/marketplace.json \
  --with-marketplace
  1. Generate/adjust optional companion folders as needed:
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin --path <parent-plugin-directory> \
  --with-skills --with-hooks --with-scripts --with-assets --with-mcp --with-apps --with-marketplace

<parent-plugin-directory> is the directory where the plugin folder <plugin-name> will be created (for example ~/code/plugins).

What this skill creates

  • If the user has not made the plugin location explicit, ask whether they want a repo-local plugin or a home-local plugin before generating marketplace entries.
  • Creates plugin root at /<parent-plugin-directory>/<plugin-name>/.
  • Always creates /<parent-plugin-directory>/<plugin-name>/.codex-plugin/plugin.json.
  • Fills the manifest with the full schema shape, placeholder values, and the complete interface section.
  • Creates or updates <repo-root>/.agents/plugins/marketplace.json when --with-marketplace is set.
    • If the marketplace file does not exist yet, seed top-level name plus interface.displayName placeholders before adding the first plugin entry.
  • <plugin-name> is normalized using skill-creator naming rules:
    • My Pluginmy-plugin
    • My--Pluginmy-plugin
    • underscores, spaces, and punctuation are converted to -
    • result is lower-case hyphen-delimited with consecutive hyphens collapsed
  • Supports optional creation of:
    • skills/
    • hooks/
    • scripts/
    • assets/
    • .mcp.json
    • .app.json

Marketplace workflow

  • marketplace.json always lives at <repo-root>/.agents/plugins/marketplace.json.
  • For a home-local plugin, use the same convention with <home> as the root: ~/.agents/plugins/marketplace.json plus ./plugins/<plugin-name>.
  • Marketplace root metadata supports top-level name plus optional interface.displayName.
  • Treat plugin order in plugins[] as render order in Codex. Append new entries unless a user explicitly asks to reorder the list.
  • displayName belongs inside the marketplace interface object, not individual plugins[] entries.
  • Each generated marketplace entry must include all of:
    • policy.installation
    • policy.authentication
    • category
  • Default new entries to:
    • policy.installation: "AVAILABLE"
    • policy.authentication: "ON_INSTALL"
  • Override defaults only when the user explicitly specifies another allowed value.
  • Allowed policy.installation values:
    • NOT_AVAILABLE
    • AVAILABLE
    • INSTALLED_BY_DEFAULT
  • Allowed policy.authentication values:
    • ON_INSTALL
    • ON_USE
  • Treat policy.products as an override. Omit it unless the user explicitly requests product gating.
  • The generated plugin entry shape is:
{
  "name": "plugin-name",
  "source": {
    "source": "local",
    "path": "./plugins/plugin-name"
  },
  "policy": {
    "installation": "AVAILABLE",
    "authentication": "ON_INSTALL"
  },
  "category": "Productivity"
}
  • Use --force only when intentionally replacing an existing marketplace entry for the same plugin name.

  • If <repo-root>/.agents/plugins/marketplace.json does not exist yet, create it with top-level "name", an "interface" object containing "displayName", and a plugins array, then add the new entry.

  • For a brand-new marketplace file, the root object should look like:

{
  "name": "[TODO: marketplace-name]",
  "interface": {
    "displayName": "[TODO: Marketplace Display Name]"
  },
  "plugins": [
    {
      "name": "plugin-name",
      "source": {
        "source": "local",
        "path": "./plugins/plugin-name"
      },
      "policy": {
        "installation": "AVAILABLE",
        "authentication": "ON_INSTALL"
      },
      "category": "Productivity"
    }
  ]
}

Required behavior

  • Outer folder name and plugin.json "name" are always the same normalized plugin name.
  • Do not remove required structure; keep .codex-plugin/plugin.json present.
  • Keep manifest values as placeholders until a human or follow-up step explicitly fills them.
  • If creating files inside an existing plugin path, use --force only when overwrite is intentional.
  • Preserve any existing marketplace interface.displayName.
  • When generating marketplace entries, always write policy.installation, policy.authentication, and category even if their values are defaults.
  • Add policy.products only when the user explicitly asks for that override.
  • Keep marketplace source.path relative to repo root as ./plugins/<plugin-name>.

Reference to exact spec sample

For the exact canonical sample JSON for both plugin manifests and marketplace entries, use:

  • references/plugin-json-spec.md

Validation

After editing SKILL.md, run:

python3 <path-to-skill-creator>/scripts/quick_validate.py .agents/skills/plugin-creator

Other files in this skill

references/plugin-json-spec.md (verbatim)

Plugin JSON sample spec

{
  "name": "plugin-name",
  "version": "1.2.0",
  "description": "Brief plugin description",
  "author": {
    "name": "Author Name",
    "email": "author@example.com",
    "url": "https://github.com/author"
  },
  "homepage": "https://docs.example.com/plugin",
  "repository": "https://github.com/author/plugin",
  "license": "MIT",
  "keywords": ["keyword1", "keyword2"],
  "skills": "./skills/",
  "hooks": "./hooks.json",
  "mcpServers": "./.mcp.json",
  "apps": "./.app.json",
  "interface": {
    "displayName": "Plugin Display Name",
    "shortDescription": "Short description for subtitle",
    "longDescription": "Long description for details page",
    "developerName": "OpenAI",
    "category": "Productivity",
    "capabilities": ["Interactive", "Write"],
    "websiteURL": "https://openai.com/",
    "privacyPolicyURL": "https://openai.com/policies/row-privacy-policy/",
    "termsOfServiceURL": "https://openai.com/policies/row-terms-of-use/",
    "defaultPrompt": [
      "Summarize my inbox and draft replies for me.",
      "Find open bugs and turn them into Linear tickets.",
      "Review today's meetings and flag scheduling gaps."
    ],
    "brandColor": "#3B82F6",
    "composerIcon": "./assets/icon.png",
    "logo": "./assets/logo.png",
    "screenshots": [
      "./assets/screenshot1.png",
      "./assets/screenshot2.png",
      "./assets/screenshot3.png"
    ]
  }
}

Field guide

Top-level fields

  • name (string): Plugin identifier (kebab-case, no spaces). Required if plugin.json is provided and used as manifest name and component namespace.
  • version (string): Plugin semantic version.
  • description (string): Short purpose summary.
  • author (object): Publisher identity.
    • name (string): Author or team name.
    • email (string): Contact email.
    • url (string): Author/team homepage or profile URL.
  • homepage (string): Documentation URL for plugin usage.
  • repository (string): Source code URL.
  • license (string): License identifier (for example MIT, Apache-2.0).
  • keywords (array of string): Search/discovery tags.
  • skills (string): Relative path to skill directories/files.
  • hooks (string): Hook config path.
  • mcpServers (string): MCP config path.
  • apps (string): App manifest path for plugin integrations.
  • interface (object): Interface/UX metadata block for plugin presentation.

interface fields

  • displayName (string): User-facing title shown for the plugin.
  • shortDescription (string): Brief subtitle used in compact views.
  • longDescription (string): Longer description used on details screens.
  • developerName (string): Human-readable publisher name.
  • category (string): Plugin category bucket.
  • capabilities (array of string): Capability list from implementation.
  • websiteURL (string): Public website for the plugin.
  • privacyPolicyURL (string): Privacy policy URL.
  • termsOfServiceURL (string): Terms of service URL.
  • defaultPrompt (array of string): Starter prompts shown in composer/UX context.
    • Include at most 3 strings. Entries after the first 3 are ignored and will not be included.
    • Each string is capped at 128 characters. Longer entries are truncated.
    • Prefer short starter prompts around 50 characters so they scan well in the UI.
  • brandColor (string): Theme color for the plugin card.
  • composerIcon (string): Path to icon asset.
  • logo (string): Path to logo asset.
  • screenshots (array of string): List of screenshot asset paths.
    • Screenshot entries must be PNG filenames and stored under ./assets/.
    • Keep file paths relative to plugin root.

Path conventions and defaults

  • Path values should be relative and begin with ./.
  • skills, hooks, and mcpServers are supplemented on top of default component discovery; they do not replace defaults.
  • Custom path values must follow the plugin root convention and naming/namespacing rules.
  • This repo’s scaffold writes .codex-plugin/plugin.json; treat that as the manifest location this skill generates.

Marketplace JSON sample spec

marketplace.json depends on where the plugin should live:

  • Repo plugin: <repo-root>/.agents/plugins/marketplace.json
  • Local plugin: ~/.agents/plugins/marketplace.json
{
  "name": "openai-curated",
  "interface": {
    "displayName": "ChatGPT Official"
  },
  "plugins": [
    {
      "name": "linear",
      "source": {
        "source": "local",
        "path": "./plugins/linear"
      },
      "policy": {
        "installation": "AVAILABLE",
        "authentication": "ON_INSTALL"
      },
      "category": "Productivity"
    }
  ]
}

Marketplace field guide

Top-level fields

  • name (string): Marketplace identifier or catalog name.
  • interface (object, optional): Marketplace presentation metadata.
  • plugins (array): Ordered plugin entries. This order determines how Codex renders plugins.

interface fields

  • displayName (string, optional): User-facing marketplace title.

Plugin entry fields

  • name (string): Plugin identifier. Match the plugin folder name and plugin.json name.
  • source (object): Plugin source descriptor.
    • source (string): Use local for this repo workflow.
    • path (string): Relative plugin path based on the marketplace root.
      • Repo plugin: ./plugins/<plugin-name>
      • Local plugin in ~/.agents/plugins/marketplace.json: ./plugins/<plugin-name>
    • The same relative path convention is used for both repo-rooted and home-rooted marketplaces.
      • Example: with ~/.agents/plugins/marketplace.json, ./plugins/<plugin-name> resolves to ~/plugins/<plugin-name>.
  • policy (object): Marketplace policy block. Always include it.
    • installation (string): Availability policy.
      • Allowed values: NOT_AVAILABLE, AVAILABLE, INSTALLED_BY_DEFAULT
      • Default for new entries: AVAILABLE
    • authentication (string): Authentication timing policy.
      • Allowed values: ON_INSTALL, ON_USE
      • Default for new entries: ON_INSTALL
    • products (array of string, optional): Product override for this plugin entry. Omit it unless product gating is explicitly requested.
  • category (string): Display category bucket. Always include it.

Marketplace generation rules

  • displayName belongs under the top-level interface object, not individual plugin entries.
  • When creating a new marketplace file from scratch, seed interface.displayName alongside top-level name.
  • Always include policy.installation, policy.authentication, and category on every generated or updated plugin entry.
  • Treat policy.products as an override and omit it unless explicitly requested.
  • Append new entries unless the user explicitly requests reordering.
  • Replace an existing entry for the same plugin only when overwrite is intentional.
  • Choose marketplace location to match the plugin destination:
    • Repo plugin: <repo-root>/.agents/plugins/marketplace.json
    • Local plugin: ~/.agents/plugins/marketplace.json

Back to openai/skills (Skills Catalog for Codex) or Agent skills.