plugin-creator

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, valid manifest defaults, and personal-marketplace entries by default. Use when Codex needs to create a new personal plugin, add optional plugin structure, generate or update marketplace entries for plugin ordering and availability metadata, or update an existing local plugin during development with the CLI-driven cachebuster and reinstall flow.

codex-rs/skills/src/assets/samples/plugin-creator/SKILL.md

Download bundle ↓
main · 18d7ace11 bundle filesScanned 2026-09-14

references/plugin-json-spec.md

2,198 tokens · o200k_base · 9,179 bytes

Source excerpt starting at line 1.
# Plugin JSON sample spec ```json{  "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",    "logoDark": "./assets/logo-dark.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` or `object`): MCP config path, or an object whose keys are MCP server names and whose values are MCP server config objects.- `apps` (`string`): App manifest path for plugin integrations.- `interface` (`object`): Interface/UX metadata block for plugin presentation. `mcpServers` may be declared as a companion file path: ```json{  "mcpServers": "./.mcp.json"}``` Or as an object directly in `plugin.json`: ```json{  "mcpServers": {    "counter": {      "type": "http",      "url": "https://sample.example/counter/mcp"    }  }}``` ### `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.- `logoDark` (`string`): Optional path to the logo asset used in dark mode.- `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 string-valued `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. New plugin creation defaults to thepersonal marketplace unless the caller explicitly requests a repo-local destination: - Personal plugin: `~/.agents/plugins/marketplace.json`- Repo/team plugin: `<repo-root>/.agents/plugins/marketplace.json` ```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.    - Personal plugin in `~/.agents/plugins/marketplace.json`: `./plugins/<plugin-name>`    - Repo/team plugin: `./plugins/<plugin-name>`  - The same relative path convention is used for both personal and repo/team 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.- Default new plugin creation to the personal marketplace.- Use a repo/team marketplace only when the user specifically requests that destination.- Only override the marketplace `name` when the default `personal` name is already taken or  installed and you need to seed a different new marketplace file.- Choose marketplace location to match the selected destination:  - Personal plugin: `~/.agents/plugins/marketplace.json`  - Repo/team plugin: `<repo-root>/.agents/plugins/marketplace.json` ### Plugin validation notes - The validator mirrors the workspace plugin ingestion schema so generated plugins follow the same  manifest contract from the start.- Plugin manifests must include real values for `name`, `version`, `description`,  `author.name`, and the required `interface` fields.- `version` must use strict semver.- `websiteURL`, `privacyPolicyURL`, and `termsOfServiceURL` must be absolute `https://` URLs when  present.- `composerIcon`, `logo`, `logoDark`, and `screenshots` must point to real files inside the plugin archive when  present.- `apps` should appear in `plugin.json` only when `.app.json` actually exists.- `mcpServers` may point to `.mcp.json` or contain the MCP server object directly in  `plugin.json`.- Validation rejects unsupported manifest fields such as `hooks`, so the scaffold keeps them out of  generated manifests.- Run `scripts/validate_plugin.py <plugin-path>` before handing back a generated plugin. It adds one  intentional preflight check that rejects leftover `[TODO: ...]` placeholders. 
Referenced from SKILL.md