plugins/build.md +92 −25
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
320 320
321- the curated marketplace that powers the official Plugin Directory321- the curated marketplace that powers the official Plugin Directory
322- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`322- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`
323323- a Claude-style marketplace at `$REPO_ROOT/.claude-plugin/marketplace.json`- a legacy-compatible marketplace at `$REPO_ROOT/.claude-plugin/marketplace.json`
324- a personal marketplace at `~/.agents/plugins/marketplace.json`324- a personal marketplace at `~/.agents/plugins/marketplace.json`
325 325
326You can install any plugin exposed through a marketplace. Codex installs326You can install any plugin exposed through a marketplace. Codex installs
337### Plugin structure337### Plugin structure
338 338
339Every 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
340340a `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`
341341connectors, an `.mcp.json` file that configures MCP servers, lifecycle config,file that points at one or more apps or connectors, an `.mcp.json` file that
342342and assets used to present the plugin across supported surfaces.configures MCP servers, and assets used to present the plugin across supported
343surfaces.
343 344
344<FileTree345<FileTree
345 class="mt-4"346 class="mt-4"
374 },375 },
375 ],376 ],
376 },377 },
377 {
378 name: ".app.json",
379 comment: "Optional: app or connector mappings",
380 },
381 {
382 name: ".mcp.json",
383 comment: "Optional: MCP server configuration",
384 },
385 {378 {
386 name: "hooks/",379 name: "hooks/",
387 open: true,380 open: true,
388 children: [381 children: [
389 {382 {
390 name: "hooks.json",383 name: "hooks.json",
391384 comment: "Optional: lifecycle configuration", comment: "Optional: lifecycle hooks",
392 },385 },
393 ],386 ],
394 },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 },
395 {396 {
396 name: "assets/",397 name: "assets/",
397 comment: "Optional: icons, logos, screenshots",398 comment: "Optional: icons, logos, screenshots",
401 ]}402 ]}
402/>403/>
403 404
404405Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `assets/`,Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `hooks/`,
405406`.mcp.json`, `.app.json`, and lifecycle config files at the plugin root.`assets/`, `.mcp.json`, and `.app.json` at the plugin root.
406 407
407Published plugins typically use a richer manifest than the minimal example that408Published plugins typically use a richer manifest than the minimal example that
408appears in quick-start scaffolds. The manifest has three jobs:409appears in quick-start scaffolds. The manifest has three jobs:
409 410
410- Identify the plugin.411- Identify the plugin.
411412- Point to bundled components such as skills, apps, or MCP servers.- Point to bundled components such as skills, apps, MCP servers, or hooks.
412- Provide install-surface metadata such as descriptions, icons, and legal413- Provide install-surface metadata such as descriptions, icons, and legal
413 links.414 links.
414 415
486- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under487- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under
487 `./assets/` when possible.488 `./assets/` when possible.
488- Use `skills` for bundled skill folders, `apps` for `.app.json`,489- Use `skills` for bundled skill folders, `apps` for `.app.json`,
489490 `mcpServers` for `.mcp.json`, and `hooks` for lifecycle config. `mcpServers` for `.mcp.json`, and `hooks` for lifecycle hooks.
490491- If you omit `hooks` and the plugin includes `./hooks/hooks.json`, Codex loads- Plugin hooks are off by default in this release; bundled hooks won't run
491492 that default lifecycle config automatically. unless `[features].plugin_hooks = true`.
493- When plugin hooks are enabled, omit `hooks` to use the default
494 `./hooks/hooks.json` file when present.
492 495
493496### Bundled MCP servers and lifecycle config### Bundled MCP servers and lifecycle hooks
494 497
495`mcpServers` can point to an `.mcp.json` file that contains either a direct498`mcpServers` can point to an `.mcp.json` file that contains either a direct
496server map or a wrapped `mcp_servers` object.499server map or a wrapped `mcp_servers` object.
519}522}
520```523```
521 524
522525`hooks` can point to one lifecycle JSON file, an array of lifecycle JSON files,After installation, users can enable or disable a bundled MCP server and tune
523526an inline lifecycle object, or an array of inline lifecycle objects. File pathstool approval policy from their Codex config without editing the plugin. Use
524527must follow the same `./`-prefixed plugin-root path rules as other manifest`plugins.<plugin>.mcp_servers.<server>` for plugin-scoped MCP server policy:
525528paths. If you omit the manifest field, Codex still checks `./hooks/hooks.json`.
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.
526 593
527### Publish official public plugins594### Publish official public plugins
528 595