npx skills add ...
npx skills add openai/codex --skill plugin-creator
npx skills add openai/codex --skill plugin-creator
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.
Edit <plugin-path>/.codex-plugin/plugin.json when the request gives specific metadata.
The scaffold starts with valid defaults and must not contain [TODO: ...] placeholders.
Generate or update the personal marketplace entry when the plugin should appear in Codex UI ordering:
Only specify --marketplace-name <name> when the default personal marketplace name is already
taken or installed and you need to seed a different new marketplace file:
Only use a repo/team marketplace when the user specifically asks for that destination:
When the user specifies a marketplace path, make sure that marketplace is actually installed before
telling the user to reinstall from it. The default personal marketplace file at
~/.agents/plugins/marketplace.json is discovered implicitly, but other marketplace paths are not.
On Windows, use the equivalent path under the user profile.
<parent-plugin-directory> is the directory where the plugin folder <plugin-name> will be
created (for example ~/plugins).
For updates to an existing local plugin during development, keep the scaffold flow as-is and use the reference instead of hand-editing marketplace files:
Prefer the helper default cachebuster unless the user explicitly asks for a specific override.
See references/installing-and-updating.md for the expected cachebuster and reinstall flow while iterating on an existing local plugin.
~/.agents/plugins/marketplace.json, with plugins generally being stored in
~/plugins/<plugin-name>/./<parent-plugin-directory>/<plugin-name>/./<parent-plugin-directory>/<plugin-name>/.codex-plugin/plugin.json.~/.agents/plugins/marketplace.json when --with-marketplace is set.
<plugin-name> is normalized using skill-creator naming rules:
My Plugin → my-pluginMy--Plugin → my-plugin-skills/hooks/scripts/assets/.mcp.json.app.json~/.agents/plugins/marketplace.json. Here,
"personal marketplace" means the marketplace whose file is at that path.--path and --marketplace-path, only
when the user specifically requests it.--marketplace-name is an exception path. Use it only when the default personal marketplace
name is already taken and you need to seed a different new marketplace file.--marketplace-name to rename an existing marketplace file in place. If the file
already exists, its top-level name must already match.codex plugin marketplace add.scripts/read_marketplace_name.py when you need the marketplace name from any
marketplace.json file. With no argument it reads the default personal marketplace; with an
explicit path it works for repo/team marketplaces too../plugins/<plugin-name>.name plus optional interface.displayName.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.policy.installationpolicy.authenticationcategorypolicy.installation: "AVAILABLE"policy.authentication: "ON_INSTALL"policy.installation values:
NOT_AVAILABLEAVAILABLEINSTALLED_BY_DEFAULTpolicy.authentication values:
ON_INSTALLON_USEpolicy.products as an override. Omit it unless the user explicitly requests product gating.Use --force only when intentionally replacing an existing marketplace entry for the same plugin name.
If the target marketplace file 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:
plugin.json "name" are always the same normalized plugin name..codex-plugin/plugin.json present.[TODO: ...] placeholders in plugin manifests.apps and mcpServers out of plugin.json unless their companion files are actually created.hooks.--force only when overwrite is intentional.interface.displayName.policy.installation, policy.authentication, and category even if their values are defaults.policy.products only when the user explicitly asks for that override.source.path relative to the selected marketplace root as ./plugins/<plugin-name>.--marketplace-name when creating a new marketplace file whose name should not be
personal because that name is already taken or installed elsewhere.marketplace.json. Use the update flow documented in
references/installing-and-updating.md and scripts/update_plugin_cachebuster.py.codex plugin marketplace add for the default personal-marketplace
flow. That command is for explicit non-default marketplace configuration, not for the standard
~/.agents/plugins/marketplace.json path.--marketplace-path, make sure that marketplace is installed
before giving reinstall instructions. Use codex plugin marketplace add <path-to-marketplace-root>
when that explicit marketplace has not been configured yet.To view this in the Codex app: and write
View <normalized plugin name> and Share <normalized plugin name> as Markdown links, not raw
URLs or code spans.codex://plugins/<normalized plugin name>?marketplacePath=<absolute marketplace.json path>.
The Share deeplink uses the same URL with &mode=share.marketplace.json
path from the scaffolded plugin. URL-encode the path segment and query value when needed.pluginName or hostId query parameters to these deeplinks. Codex derives both after
the user clicks the link.View <normalized plugin name> or Share <normalized plugin name> links when no marketplace entry was
created or updated.For the exact canonical sample JSON for both plugin manifests and marketplace entries, use:
references/plugin-json-spec.mdreferences/installing-and-updating.md for update/reinstall guidance while
iterating on an existing local plugin, plus the new-thread pickup behavior after reinstallAfter editing SKILL.md, run:
Before handing back a generated plugin, run:
python3 scripts/create_basic_plugin.py my-plugin \
--with-marketplace \
--marketplace-name team-localpython3 scripts/create_basic_plugin.py my-plugin \
--path <repo-root>/plugins \
--marketplace-path <repo-root>/.agents/plugins/marketplace.json \
--with-marketplacepython3 scripts/create_basic_plugin.py my-plugin \
--path <parent-plugin-directory> \
--marketplace-path <marketplace-json-path> \
--with-skills --with-hooks --with-scripts --with-assets --with-mcp --with-apps --with-marketplacepython3 scripts/validate_plugin.py <plugin-path>python3 scripts/validate_plugin.py <plugin-path>python3 scripts/update_plugin_cachebuster.py <plugin-path>{
"name": "plugin-name",
"source": {
"source": "local",
"path": "./plugins/plugin-name"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}{
"name": "personal",
"interface": {
"displayName": "Personal"
},
"plugins": [
{
"name": "plugin-name",
"source": {
"source": "local",
"path": "./plugins/plugin-name"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
}python3 ../skill-creator/scripts/quick_validate.py .