plugins/build.md +271 −33
4plugins in Codex, see [Plugins](https://developers.openai.com/codex/plugins). If you are still iterating on4plugins in Codex, see [Plugins](https://developers.openai.com/codex/plugins). If you are still iterating on
5one repo or one personal workflow, start with a local skill. Build a plugin5one repo or one personal workflow, start with a local skill. Build a plugin
6when you want to share that workflow across teams, bundle app integrations or6when you want to share that workflow across teams, bundle app integrations or
77MCP config, or publish a stable package.MCP config, package lifecycle hooks, or publish a stable package.
8 8
9## Create a plugin with `$plugin-creator`9## Create a plugin with `$plugin-creator`
10 10
11For the fastest setup, use the built-in `$plugin-creator` skill.11For the fastest setup, use the built-in `$plugin-creator` skill.
12 12
1313<CodexScreenshot
14 alt="plugin-creator skill in Codex"
15 lightSrc="/images/codex/plugins/plugin-creator.png"
16 darkSrc="/images/codex/plugins/plugin-creator-dark.png"
17/>
14 18
15It scaffolds the required `.codex-plugin/plugin.json` manifest and can also19It scaffolds the required `.codex-plugin/plugin.json` manifest and can also
16generate a local marketplace entry for testing. If you already have a plugin20generate a local marketplace entry for testing. If you already have a plugin
17folder, you can still use `$plugin-creator` to wire it into a local21folder, you can still use `$plugin-creator` to wire it into a local
18marketplace.22marketplace.
19 23
2024<CodexScreenshot
25 alt="how to invoke the plugin-creator skill"
26 lightSrc="/images/codex/plugins/plugin-creator-invoke.png"
27 darkSrc="/images/codex/plugins/plugin-creator-invoke-dark.png"
28/>
21 29
22### Build your own curated plugin list30### Build your own curated plugin list
23 31
38single plugin while you are testing, then grow into a larger curated catalog as46single plugin while you are testing, then grow into a larger curated catalog as
39you add more plugins.47you add more plugins.
40 48
4149<CodexScreenshot
50 alt="custom local marketplace in the plugin directory"
51 lightSrc="/images/codex/plugins/codex-local-plugin-light.png"
52 darkSrc="/images/codex/plugins/codex-local-plugin.png"
53/>
54
55### Add a marketplace from the CLI
56
57Use `codex plugin marketplace add` when you want Codex to install and track a
58marketplace source for you instead of editing `config.toml` by hand.
59
60```bash
61codex plugin marketplace add owner/repo
62codex plugin marketplace add owner/repo --ref main
63codex plugin marketplace add https://github.com/example/plugins.git --sparse .agents/plugins
64codex plugin marketplace add ./local-marketplace-root
65```
66
67Marketplace sources can be GitHub shorthand (`owner/repo` or
68`owner/repo@ref`), HTTP or HTTPS Git URLs, SSH Git URLs, or local marketplace root
69directories. Use `--ref` to pin a Git ref, and repeat `--sparse PATH` to use a
70sparse checkout for Git-backed marketplace repos. `--sparse` is valid only for
71Git marketplace sources.
72
73To refresh or remove configured marketplaces:
74
75```bash
76codex plugin marketplace upgrade
77codex plugin marketplace upgrade marketplace-name
78codex plugin marketplace remove marketplace-name
79```
42 80
43### Create a plugin manually81### Create a plugin manually
44 82
93Use a repo marketplace or a personal marketplace, depending on who should be131Use a repo marketplace or a personal marketplace, depending on who should be
94able to access the plugin or curated list.132able to access the plugin or curated list.
95 133
134<Tabs
135 id="codex-plugins-local-install"
136 param="install-scope"
137 defaultTab="workspace"
138 tabs={[
139 {
140 id: "workspace",
141 label: "Repo",
142 },
143 {
144 id: "global",
145 label: "Personal",
146 },
147 ]}
148>
149 <div slot="workspace">
96 Add a marketplace file at `$REPO_ROOT/.agents/plugins/marketplace.json`150 Add a marketplace file at `$REPO_ROOT/.agents/plugins/marketplace.json`
97 and store your plugins under `$REPO_ROOT/plugins/`.151 and store your plugins under `$REPO_ROOT/plugins/`.
98 152
131 185
132 Step 3: Restart Codex and verify that the plugin appears.186 Step 3: Restart Codex and verify that the plugin appears.
133 187
188 </div>
189
190 <div slot="global">
134 Add a marketplace file at `~/.agents/plugins/marketplace.json` and store191 Add a marketplace file at `~/.agents/plugins/marketplace.json` and store
135 your plugins under `~/.codex/plugins/`.192 your plugins under `~/.codex/plugins/`.
136 193
148 205
149 Step 3: Restart Codex and verify that the plugin appears.206 Step 3: Restart Codex and verify that the plugin appears.
150 207
208 </div>
209</Tabs>
210
151The marketplace file points to the plugin location, so those directories are211The marketplace file points to the plugin location, so those directories are
152examples rather than fixed requirements. Codex resolves `source.path` relative212examples rather than fixed requirements. Codex resolves `source.path` relative
153to the marketplace root, not relative to the `.agents/plugins/` folder. See213to the marketplace root, not relative to the `.agents/plugins/` folder. See
211 personal installs, a common pattern is `./.codex/plugins/<plugin-name>`.271 personal installs, a common pattern is `./.codex/plugins/<plugin-name>`.
212- Keep `source.path` relative to the marketplace root, start it with `./`, and272- Keep `source.path` relative to the marketplace root, start it with `./`, and
213 keep it inside that root.273 keep it inside that root.
274- For local entries, `source` can also be a plain string path such as
275 `"./plugins/my-plugin"`.
214- Always include `policy.installation`, `policy.authentication`, and276- Always include `policy.installation`, `policy.authentication`, and
215 `category` on each plugin entry.277 `category` on each plugin entry.
216- Use `policy.installation` values such as `AVAILABLE`,278- Use `policy.installation` values such as `AVAILABLE`,
218- Use `policy.authentication` to decide whether auth happens on install or280- Use `policy.authentication` to decide whether auth happens on install or
219 first use.281 first use.
220 282
221283The marketplace controls where Codex loads the plugin from. `source.path` canThe marketplace controls where Codex loads the plugin from. A local
222284point somewhere else if your plugin lives outside those example directories. A`source.path` can point somewhere else if your plugin lives outside those
223285marketplace file can live in the repo where you are developing the plugin or inexample directories. A marketplace file can live in the repo where you are
224286a separate marketplace repo, and one marketplace file can point to one plugindeveloping the plugin or in a separate marketplace repo, and one marketplace
225287or many.file can point to one plugin or many.
288
289Marketplace entries can also point at Git-backed plugin sources. Use
290`"source": "url"` when the plugin lives at the repository root, or
291`"source": "git-subdir"` when the plugin lives in a subdirectory:
292
293```json
294{
295 "name": "remote-helper",
296 "source": {
297 "source": "git-subdir",
298 "url": "https://github.com/example/codex-plugins.git",
299 "path": "./plugins/remote-helper",
300 "ref": "main"
301 },
302 "policy": {
303 "installation": "AVAILABLE",
304 "authentication": "ON_INSTALL"
305 },
306 "category": "Productivity"
307}
308```
309
310Git-backed entries may use `ref` or `sha` selectors. If Codex can't resolve a
311marketplace entry's source, it skips that plugin entry instead of failing the
312whole marketplace.
226 313
227### How Codex uses marketplaces314### How Codex uses marketplaces
228 315
233 320
234- the curated marketplace that powers the official Plugin Directory321- the curated marketplace that powers the official Plugin Directory
235- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`322- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`
323- a legacy-compatible marketplace at `$REPO_ROOT/.claude-plugin/marketplace.json`
236- a personal marketplace at `~/.agents/plugins/marketplace.json`324- a personal marketplace at `~/.agents/plugins/marketplace.json`
237 325
238You can install any plugin exposed through a marketplace. Codex installs326You can install any plugin exposed through a marketplace. Codex installs
249### Plugin structure337### Plugin structure
250 338
251Every plugin has a manifest at `.codex-plugin/plugin.json`. It can also include339Every plugin has a manifest at `.codex-plugin/plugin.json`. It can also include
252340a `skills/` directory, an `.app.json` file that points at one or more apps ora `skills/` directory, a `hooks/` directory for lifecycle hooks, an `.app.json`
253341connectors, an `.mcp.json` file that configures MCP servers, and assets used tofile that points at one or more apps or connectors, an `.mcp.json` file that
254342present the plugin across supported surfaces.configures MCP servers, and assets used to present the plugin across supported
255343 surfaces.
256344- my-plugin/
257345 <FileTree
258346 - .codex-plugin/ class="mt-4"
259347 tree={[
260348 - plugin.json Required: plugin manifest {
261349 - skills/ name: "my-plugin/",
262350 open: true,
263351 - my-skill/ children: [
264352 {
265353 - SKILL.md Optional: skill instructions name: ".codex-plugin/",
266354 - .app.json Optional: app or connector mappings open: true,
267355 - .mcp.json Optional: MCP server configuration children: [
268356 - assets/ Optional: icons, logos, screenshots {
357 name: "plugin.json",
358 comment: "Required: plugin manifest",
359 },
360 ],
361 },
362 {
363 name: "skills/",
364 open: true,
365 children: [
366 {
367 name: "my-skill/",
368 open: true,
369 children: [
370 {
371 name: "SKILL.md",
372 comment: "Optional: skill instructions",
373 },
374 ],
375 },
376 ],
377 },
378 {
379 name: "hooks/",
380 open: true,
381 children: [
382 {
383 name: "hooks.json",
384 comment: "Optional: lifecycle hooks",
385 },
386 ],
387 },
388 {
389 name: ".app.json",
390 comment: "Optional: app or connector mappings",
391 },
392 {
393 name: ".mcp.json",
394 comment: "Optional: MCP server configuration",
395 },
396 {
397 name: "assets/",
398 comment: "Optional: icons, logos, screenshots",
399 },
400 ],
401 },
402 ]}
403/>
269 404
270405Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `assets/`,Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `hooks/`,
271406`.mcp.json`, and `.app.json` at the plugin root.`assets/`, `.mcp.json`, and `.app.json` at the plugin root.
272 407
273Published plugins typically use a richer manifest than the minimal example that408Published plugins typically use a richer manifest than the minimal example that
274appears in quick-start scaffolds. The manifest has three jobs:409appears in quick-start scaffolds. The manifest has three jobs:
275 410
276- Identify the plugin.411- Identify the plugin.
277412- Point to bundled components such as skills, apps, or MCP servers.- Point to bundled components such as skills, apps, MCP servers, or hooks.
278- Provide install-surface metadata such as descriptions, icons, and legal413- Provide install-surface metadata such as descriptions, icons, and legal
279 links.414 links.
280 415
297 "skills": "./skills/",432 "skills": "./skills/",
298 "mcpServers": "./.mcp.json",433 "mcpServers": "./.mcp.json",
299 "apps": "./.app.json",434 "apps": "./.app.json",
435 "hooks": "./hooks/hooks.json",
300 "interface": {436 "interface": {
301 "displayName": "My Plugin",437 "displayName": "My Plugin",
302 "shortDescription": "Reusable skills and apps",438 "shortDescription": "Reusable skills and apps",
330- `name`, `version`, and `description` identify the plugin.466- `name`, `version`, and `description` identify the plugin.
331- `author`, `homepage`, `repository`, `license`, and `keywords` provide467- `author`, `homepage`, `repository`, `license`, and `keywords` provide
332 publisher and discovery metadata.468 publisher and discovery metadata.
333469- `skills`, `mcpServers`, and `apps` point to bundled components relative to- `skills`, `mcpServers`, `apps`, and `hooks` point to bundled components
334470 the plugin root. relative to the plugin root.
335- `interface` controls how install surfaces present the plugin.471- `interface` controls how install surfaces present the plugin.
336 472
337Use the `interface` object for install-surface metadata:473Use the `interface` object for install-surface metadata:
350- Keep manifest paths relative to the plugin root and start them with `./`.486- Keep manifest paths relative to the plugin root and start them with `./`.
351- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under487- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under
352 `./assets/` when possible.488 `./assets/` when possible.
353489- Use `skills` for bundled skill folders, `apps` for `.app.json`, and- Use `skills` for bundled skill folders, `apps` for `.app.json`,
354490 `mcpServers` for `.mcp.json`. `mcpServers` for `.mcp.json`, and `hooks` for lifecycle hooks.
491- Plugin hooks are off by default in this release; bundled hooks won't run
492 unless `[features].plugin_hooks = true`.
493- When plugin hooks are enabled, omit `hooks` to use the default
494 `./hooks/hooks.json` file when present.
495
496### Bundled MCP servers and lifecycle hooks
497
498`mcpServers` can point to an `.mcp.json` file that contains either a direct
499server map or a wrapped `mcp_servers` object.
500
501Direct server map:
502
503```json
504{
505 "docs": {
506 "command": "docs-mcp",
507 "args": ["--stdio"]
508 }
509}
510```
511
512Wrapped server map:
513
514```json
515{
516 "mcp_servers": {
517 "docs": {
518 "command": "docs-mcp",
519 "args": ["--stdio"]
520 }
521 }
522}
523```
524
525After installation, users can enable or disable a bundled MCP server and tune
526tool approval policy from their Codex config without editing the plugin. Use
527`plugins.<plugin>.mcp_servers.<server>` for plugin-scoped MCP server policy:
528
529```toml
530[plugins."my-plugin".mcp_servers.docs]
531enabled = true
532default_tools_approval_mode = "prompt"
533enabled_tools = ["search"]
534
535[plugins."my-plugin".mcp_servers.docs.tools.search]
536approval_mode = "approve"
537```
538
539Plugin hooks are off by default in this release. When
540`[features].plugin_hooks = true` and your plugin is enabled, Codex can load
541lifecycle hooks from your plugin alongside user, project, and managed hooks.
542
543```toml
544[features]
545plugin_hooks = true
546```
547
548The default plugin hook file is `hooks/hooks.json`:
549
550```json
551{
552 "hooks": {
553 "SessionStart": [
554 {
555 "hooks": [
556 {
557 "type": "command",
558 "command": "python3 ${PLUGIN_ROOT}/hooks/session_start.py",
559 "statusMessage": "Loading plugin context"
560 }
561 ]
562 }
563 ]
564 }
565}
566```
567
568If you define `hooks` in `.codex-plugin/plugin.json`, Codex uses that manifest
569entry instead of the default `hooks/hooks.json`. The manifest field can be a
570single path, an array of paths, an inline hooks object, or an array of inline
571hooks objects.
572
573```json
574{
575 "name": "repo-policy",
576 "hooks": ["./hooks/session.json", "./hooks/tools.json"]
577}
578```
579
580Hook paths follow the same manifest path rules as `skills`, `apps`, and
581`mcpServers`: start with `./`, resolve relative to the plugin root, and stay
582inside the plugin root.
583
584Plugin hook commands receive the Codex-specific environment variables
585`PLUGIN_ROOT` and `PLUGIN_DATA`. `PLUGIN_ROOT` points to the installed plugin
586root, and `PLUGIN_DATA` points to the plugin's writable data directory. Codex
587also sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` for compatibility with
588existing plugin hooks.
589
590Plugin hooks use the same event schema as regular hooks. See
591[Hooks](https://developers.openai.com/codex/hooks) for supported events, inputs, outputs, trust review, and
592current limitations.
355 593
356### Publish official public plugins594### Publish official public plugins
357 595