1# Build plugins1# Build plugins
2 2
3This page is for plugin authors. If you want to browse, install, and use3To build or submit a plugin, use the complete
4plugins with ChatGPT Work on the web or with ChatGPT Work or Codex in the4[builder documentation on developers.openai.com](https://developers.openai.com/plugins).
5ChatGPT desktop app, see [Plugins](https://learn.chatgpt.com/docs/plugins). If you are still iterating on
6one repo or one personal workflow, start with a local skill. Build a plugin when
7you want to share that workflow across teams, bundle connectors or MCP config,
8package lifecycle hooks, or publish a stable package.
9 5
10A plugin can include skills, an MCP-backed app, or both. If your plugin needs6<div className="not-prose my-6">
11to connect to a service or expose tools through an MCP server, see7 <ButtonLink href="/plugins" color="primary" variant="solid" size="lg">
12[Build an app](https://learn.chatgpt.com/docs/build-app).8 Build and submit a plugin
9 </ButtonLink>
10</div>
11
12This page provides a brief introduction. A plugin is an installable package
13that can include skills, an MCP server, or both. An MCP server can also return
14optional UI.
15
16ChatGPT and Codex share one universal plugin directory. Publish a public plugin
17once to make the same listing discoverable from supported surfaces in both
18products. During development, use a local marketplace to test the package
19before submitting it to the universal directory.
13 20
14For complete public examples, inspect21Start with a skill when you are still iterating on one personal workflow.
15[Figma](https://github.com/openai/plugins/tree/main/plugins/figma),22Build a plugin when you want to share that workflow, package related skills,
16[Notion](https://github.com/openai/plugins/tree/main/plugins/notion), and23connect to an external service, or distribute a stable capability to a team.
17[Build web apps](https://github.com/openai/plugins/tree/main/plugins/build-web-apps).
18 24
19## Create a plugin with `@plugin-creator`25## Create a plugin with `@plugin-creator`
20 26
21For the fastest setup, use the built-in `@plugin-creator` skill.27For the fastest setup, use the built-in `@plugin-creator` skill in ChatGPT Work
28mode or `$plugin-creator` in Codex.
22 29
23<CodexScreenshot30<CodexScreenshot
24 alt="Plugin creator skill in ChatGPT"31 alt="Plugin creator skill in ChatGPT"
26 darkSrc="/images/codex/plugins/plugin-creator-dark.png"33 darkSrc="/images/codex/plugins/plugin-creator-dark.png"
27/>34/>
28 35
29It scaffolds the required `.codex-plugin/plugin.json` manifest and can also36Describe the outcome, the skills or MCP server to include, and whether you want
30generate a local marketplace entry for testing. If you already have a plugin37a local marketplace entry for testing. For example:
31folder, you can still use `@plugin-creator` to wire it into a local
32marketplace.
33
34<CodexScreenshot
35 alt="how to invoke the plugin-creator skill"
36 lightSrc="/images/codex/plugins/plugin-creator-invoke.png"
37 darkSrc="/images/codex/plugins/plugin-creator-invoke-dark.png"
38/>
39
40### Create and test a plugin locally that points to an MCP-server-backed dev-mode app
41
42You can also use the plugin-creator skill if you want to test a plugin locally
43that includes an MCP-server backed app. The plugin still needs a local plugin
44folder and manifest, but the app itself starts in ChatGPT developer mode.
45
46First, enable developer mode in ChatGPT:
47
481. Open [ChatGPT](https://chatgpt.com).
492. Open **Settings**.
503. Select **Security and login**.
514. Turn on **Developer mode**.
52
53Then create the app in developer mode:
54
551. Open **Settings → Plugins** or [the Plugins page](https://chatgpt.com/plugins).
562. Select the plus button.
573. Complete the modal to create a developer-mode app for your MCP server.
584. After ChatGPT creates it, copy the app ID from the browser URL. It starts
59 with `plugin_asdk_app`.
60
61Give that `plugin_asdk_app...` ID to `@plugin-creator` in a ChatGPT Work chat
62or `$plugin-creator` in Codex. For example, with ChatGPT Work:
63
64<div class="not-prose my-6 overflow-hidden rounded-xl border border-subtle bg-surface shadow-sm">
65 <div class="border-b border-subtle bg-surface-secondary px-4 py-3">
66 <span class="inline-flex rounded-md bg-purple-100 px-2.5 py-1 text-sm font-medium text-purple-700 dark:bg-purple-950/60 dark:text-purple-200">
67 Plugin Creator prompt
68 </span>
69 </div>
70 <div class="overflow-x-auto p-4 font-mono text-sm leading-6 text-primary">
71 <code class="whitespace-pre-wrap break-words">{`@plugin-creator create a Codex plugin for my ChatGPT app.
72Use plugin_asdk_app_6a4c0062f3b88191855c0a80eac5d53d and name it Acme Support.
73Include a personal marketplace entry so I can test it locally.`}</code>
74 </div>
75</div>
76
77The plugin-creator skill will create the plugin folder, create the required
78`.codex-plugin/plugin.json`, and add app wiring for the ChatGPT app. If you ask
79it to create a personal marketplace entry, the plugin appears under your local
80source in the Plugins Directory for testing.
81
82After the plugin-creator skill creates the plugin:
83 38
841. Review `.app.json` and confirm it points at the correct39```text
85 `plugin_asdk_app...` ID.40@plugin-creator Create a plugin named meeting-follow-up.
862. Review `.codex-plugin/plugin.json` and make sure its `apps` field points to41Include a skill that turns meeting notes into decisions, owners, and next steps.
87 `./.app.json`.42Add it to a personal marketplace so I can test it locally.
883. Add any bundled skills under `skills/` if the plugin should include43```
89 repeatable workflows alongside the app.
904. If the skill created a personal marketplace entry, refresh ChatGPT
91 and install the plugin from your local source in the Plugins Directory. Then
92 test it in a new chat.
93
94For the manifest shape and file layout, see [Plugin structure](#plugin-structure)
95and [Path rules](#path-rules).
96
97### Build your own curated plugin list
98
99A marketplace is a JSON catalog of plugins. `@plugin-creator` can generate one
100for a single plugin, and you can keep adding entries to that same marketplace
101to build your own curated list for a repo, team, or personal workflow.
102
103In ChatGPT Work or Codex in the ChatGPT desktop app, each marketplace appears as a
104selectable source in the Plugins Directory. Use
105`$REPO_ROOT/.agents/plugins/marketplace.json` for a repo-scoped list or
106`~/.agents/plugins/marketplace.json` for a personal list. Add one entry per
107plugin under `plugins[]`, point each `source.path` at the plugin folder with a
108`./`-prefixed path relative to the marketplace root, and set
109`interface.displayName` to the label you want the app to show in the marketplace
110picker. Then restart the ChatGPT desktop app. After that, open the Plugins
111Directory, choose your marketplace, and browse or install the plugins in that
112curated list.
113 44
114You don't need a separate marketplace per plugin. One marketplace can expose a45The skill creates the required `.codex-plugin/plugin.json` manifest, organizes
115single plugin while you are testing, then grow into a larger curated catalog as46the plugin folder, and can add the plugin to a local marketplace.
116you add more plugins.
117 47
118<CodexScreenshot48<CodexScreenshot
119 alt="custom local marketplace in the Plugins Directory"49 alt="Invoking the plugin creator skill"
120 lightSrc="/images/codex/plugins/codex-local-plugin-light.png"50 lightSrc="/images/codex/plugins/plugin-creator-invoke.png"
121 darkSrc="/images/codex/plugins/codex-local-plugin.png"51 darkSrc="/images/codex/plugins/plugin-creator-invoke-dark.png"
122/>52/>
123 53
124### Add a marketplace from the CLI54After it finishes:
125 55
126Use `codex plugin marketplace add` to add and track a marketplace source instead561. Review `.codex-plugin/plugin.json`.
127of editing `config.toml` by hand. These commands support plugin authoring and572. Check each bundled skill under `skills/`.
128catalog setup. Use the ChatGPT desktop app to install and test a local plugin.583. Refresh ChatGPT or Codex and install the plugin from its local marketplace
59 source.
604. Test the plugin in a new conversation with representative requests.
129 61
130```bash62If the plugin includes an MCP server, first build and test that server, then
131codex plugin marketplace add owner/repo63give `@plugin-creator` the registered connection details. Follow the complete
132codex plugin marketplace add owner/repo --ref main64[MCP server workflow](https://developers.openai.com/plugins/build/mcp-server)
133codex plugin marketplace add https://github.com/example/plugins.git --sparse .agents/plugins65for tools, authentication, deployment, and testing.
134codex plugin marketplace add ./local-marketplace-root
135```
136 66
137Marketplace sources can be GitHub shorthand (`owner/repo` or67## Create a skills-only plugin manually
138`owner/repo@ref`), HTTP or HTTPS Git URLs, SSH Git URLs, or local marketplace root
139directories. Use `--ref` to pin a Git ref, and repeat `--sparse PATH` to use a
140sparse checkout for Git-backed marketplace repos. `--sparse` is valid only for
141Git marketplace sources.
142 68
143To inspect, refresh, or remove configured marketplaces:69A minimal plugin contains a manifest and at least one skill:
144 70
145```bash71```text
146codex plugin marketplace list72meeting-follow-up/
147codex plugin marketplace upgrade73├── .codex-plugin/
148codex plugin marketplace upgrade marketplace-name74│ └── plugin.json
149codex plugin marketplace remove marketplace-name75└── skills/
76 └── meeting-follow-up/
77 └── SKILL.md
150```78```
151 79
152`codex plugin marketplace list` prints each marketplace Codex is considering80Create `.codex-plugin/plugin.json`:
153and the root path it resolves from, including local default marketplaces and
154configured marketplace snapshots.
155
156### Create a plugin manually
157
158Start with a minimal plugin that packages one skill.
159
1601. Create a plugin folder with a manifest at `.codex-plugin/plugin.json`.
161
162```bash
163mkdir -p my-first-plugin/.codex-plugin
164```
165
166`my-first-plugin/.codex-plugin/plugin.json`
167 81
168```json82```json
169{83{
170 "name": "my-first-plugin",84 "name": "meeting-follow-up",
171 "version": "1.0.0",85 "version": "1.0.0",
172 "description": "Reusable greeting workflow",86 "description": "Turn meeting notes into decisions and next steps",
173 "skills": "./skills/"87 "skills": "./skills/"
174}88}
175```89```
176 90
177Use a stable plugin `name` in kebab-case. Codex uses it as the plugin91Then add `skills/meeting-follow-up/SKILL.md`:
178identifier and component namespace.
179
1802. Add a skill under `skills/<skill-name>/SKILL.md`.
181
182```bash
183mkdir -p my-first-plugin/skills/hello
184```
185
186`my-first-plugin/skills/hello/SKILL.md`
187 92
188```md93```md
189---94---
190name: hello95name: meeting-follow-up
191description: Greet the user with a friendly message.96description: Extract decisions, owners, and next steps from meeting notes.
192---97---
193 98
194Greet the user warmly and ask how you can help.99Review the meeting notes. Return:
195```
196
1973. Add the plugin to a marketplace. Use `@plugin-creator` to generate one, or
198 follow [Build your own curated plugin list](#build-your-own-curated-plugin-list)
199 to wire the plugin into Codex manually.
200
201From there, you can add MCP config, connectors, or marketplace metadata
202as needed.
203
204### Install a local plugin manually
205
206Use a repo marketplace or a personal marketplace, depending on who should be
207able to access the plugin or curated list.
208
209<Tabs
210 id="codex-plugins-local-install"
211 param="install-scope"
212 defaultTab="workspace"
213 tabs={[
214 {
215 id: "workspace",
216 label: "Repo",
217 },
218 {
219 id: "global",
220 label: "Personal",
221 },
222 ]}
223>
224 <div slot="workspace">
225 Add a marketplace file at `$REPO_ROOT/.agents/plugins/marketplace.json`
226 and store your plugins under `$REPO_ROOT/plugins/`.
227
228 **Repo marketplace example**
229
230 Step 1: Copy the plugin folder into `$REPO_ROOT/plugins/my-plugin`.
231
232```bash
233mkdir -p ./plugins
234cp -R /absolute/path/to/my-plugin ./plugins/my-plugin
235```
236
237 Step 2: Add or update `$REPO_ROOT/.agents/plugins/marketplace.json` so
238 that `source.path` points to that plugin directory with a `./`-prefixed
239 relative path:
240
241```json
242{
243 "name": "local-repo",
244 "plugins": [
245 {
246 "name": "my-plugin",
247 "source": {
248 "source": "local",
249 "path": "./plugins/my-plugin"
250 },
251 "policy": {
252 "installation": "AVAILABLE",
253 "authentication": "ON_INSTALL"
254 },
255 "category": "Productivity"
256 }
257 ]
258}
259```
260
261 Step 3: Restart the ChatGPT desktop app and verify that the plugin appears.
262
263 </div>
264
265 <div slot="global">
266 Add a marketplace file at `~/.agents/plugins/marketplace.json` and store
267 your plugins under `~/.codex/plugins/`.
268
269 **Personal marketplace example**
270
271 Step 1: Copy the plugin folder into `~/.codex/plugins/my-plugin`.
272
273```bash
274mkdir -p ~/.codex/plugins
275cp -R /absolute/path/to/my-plugin ~/.codex/plugins/my-plugin
276```
277
278 Step 2: Add or update `~/.agents/plugins/marketplace.json` so that the
279 plugin entry's `source.path` points to that directory.
280
281 Step 3: Restart the ChatGPT desktop app and verify that the plugin appears.
282
283 </div>
284</Tabs>
285
286The marketplace file points to the plugin location, so those directories are
287examples rather than fixed requirements. Codex resolves `source.path` relative
288to the marketplace root, not relative to the `.agents/plugins/` folder. See
289[Marketplace metadata](#marketplace-metadata) for the file format.
290
291After you change the plugin, update the plugin directory that your marketplace
292entry points to and restart the ChatGPT desktop app so the local install picks
293up the new files.
294
295### Share a local plugin with your workspace
296
297After you create a plugin, add it from the ChatGPT desktop app. Select ChatGPT
298and switch to Work in the switcher, or select Codex, then open **Plugins**. You can then
299share it with other members of your ChatGPT workspace.
300
3011. Open **Plugins** in the ChatGPT desktop app.
3022. Go to **Created by you** and open the plugin details page.
3033. Select **Share**.
3044. Add workspace members or workspace groups, or copy a share link.
3055. Choose who has access, then send the invitation or link.
306
307People you share with can find the plugin under **Shared with you** in the
308Plugins Directory. Sharing a local plugin with your workspace doesn't publish
309it to the public Plugins Directory. Shared plugins stay within your workspace
310and organization boundary; accounts that aren't signed in to that workspace
311can't access them. Use groups when a team or role should share the same plugin
312access. Use a marketplace when you want repo or CLI distribution, and use
313workspace sharing when you want selected teammates to install a plugin from the
314ChatGPT desktop app.
315
316Workspace admins can disable plugin sharing from cloud-managed requirements by
317adding `features.plugin_sharing = false` to `requirements.toml`:
318
319```toml
320features.plugin_sharing = false
321```
322
323### Marketplace metadata
324
325If you maintain a repo marketplace, define it in
326`$REPO_ROOT/.agents/plugins/marketplace.json`. For a personal marketplace, use
327`~/.agents/plugins/marketplace.json`. A marketplace file controls plugin
328ordering and install policies in the ChatGPT desktop app. It can represent one
329plugin while you are testing or a curated list of plugins that you want the app
330to show together under one marketplace name. Before you add a plugin to a
331marketplace, make sure its `version`, publisher metadata, and install-surface
332copy are ready for other developers to see.
333
334```json
335{
336 "name": "local-example-plugins",
337 "interface": {
338 "displayName": "Local Example Plugins"
339 },
340 "plugins": [
341 {
342 "name": "my-plugin",
343 "source": {
344 "source": "local",
345 "path": "./plugins/my-plugin"
346 },
347 "policy": {
348 "installation": "AVAILABLE",
349 "authentication": "ON_INSTALL"
350 },
351 "category": "Productivity"
352 },
353 {
354 "name": "research-helper",
355 "source": {
356 "source": "local",
357 "path": "./plugins/research-helper"
358 },
359 "policy": {
360 "installation": "AVAILABLE",
361 "authentication": "ON_INSTALL"
362 },
363 "category": "Productivity"
364 }
365 ]
366}
367```
368
369- Use top-level `name` to identify the marketplace.
370- Use `interface.displayName` for the marketplace title shown in the ChatGPT
371 desktop app.
372- Add one object per plugin under `plugins` to build a curated list that the app
373 shows under that marketplace title.
374- Point each plugin entry's `source.path` at the plugin directory you want
375 Codex to load. For repo installs, that often lives under `./plugins/`. For
376 personal installs, a common pattern is `./.codex/plugins/<plugin-name>`.
377- Keep `source.path` relative to the marketplace root, start it with `./`, and
378 keep it inside that root.
379- For local entries, `source` can also be a plain string path such as
380 `"./plugins/my-plugin"`.
381- Always include `policy.installation`, `policy.authentication`, and
382 `category` on each plugin entry.
383- Use `policy.installation` values such as `AVAILABLE`,
384 `INSTALLED_BY_DEFAULT`, or `NOT_AVAILABLE`.
385- Use `policy.authentication` to decide whether auth happens on install or
386 first use.
387
388The marketplace controls where Codex loads the plugin from. A local
389`source.path` can point somewhere else if your plugin lives outside those
390example directories. A marketplace file can live in the repo where you are
391developing the plugin or in a separate marketplace repo, and one marketplace
392file can point to one plugin or many.
393
394Marketplace entries can also point at Git-backed plugin sources. Use
395`"source": "url"` when the plugin lives at the repository root, or
396`"source": "git-subdir"` when the plugin lives in a subdirectory:
397
398```json
399{
400 "name": "remote-helper",
401 "source": {
402 "source": "git-subdir",
403 "url": "https://github.com/example/codex-plugins.git",
404 "path": "./plugins/remote-helper",
405 "ref": "main"
406 },
407 "policy": {
408 "installation": "AVAILABLE",
409 "authentication": "ON_INSTALL"
410 },
411 "category": "Productivity"
412}
413```
414
415Git-backed entries may use `ref` or `sha` selectors. If Codex can't resolve a
416marketplace entry's source, it skips that plugin entry instead of failing the
417whole marketplace.
418
419Marketplace entries can also install a plugin from a JavaScript package registry:
420
421```json
422{
423 "name": "npm-helper",
424 "source": {
425 "source": "npm",
426 "package": "@example/codex-plugin",
427 "version": "^1.2.0",
428 "registry": "https://registry.npmjs.org"
429 },
430 "policy": {
431 "installation": "AVAILABLE",
432 "authentication": "ON_INSTALL"
433 },
434 "category": "Productivity"
435}
436```
437
438`package` is required and can include a registry scope. `version` is optional
439and accepts package versions, distribution tags, and version ranges, but not
440path or URL selectors.
441`registry` is optional and must be an HTTPS URL without embedded credentials,
442a query, or a fragment. Codex downloads the package without running lifecycle
443scripts. The `npm` CLI must be installed, and registry authentication comes
444from its configuration.
445
446### How the ChatGPT desktop app uses marketplaces
447
448A plugin marketplace is a JSON catalog of plugins that the ChatGPT desktop app
449can read and install.
450
451The app can read marketplace files from:
452
453- the curated marketplace that powers the official Plugins Directory
454- a repo marketplace at `$REPO_ROOT/.agents/plugins/marketplace.json`
455- a legacy-compatible marketplace at `$REPO_ROOT/.claude-plugin/marketplace.json`
456- a personal marketplace at `~/.agents/plugins/marketplace.json`
457
458You can install any plugin exposed through a marketplace. The app installs
459plugins into
460`~/.codex/plugins/cache/$MARKETPLACE_NAME/$PLUGIN_NAME/$VERSION/`. For local
461plugins, `$VERSION` is `local`, and the app loads the installed copy from that
462cache path rather than directly from the marketplace entry.
463
464You can enable or disable each plugin individually. The app stores each plugin's
465on or off state in `~/.codex/config.toml`.
466
467## Package and distribute plugins
468
469### Plugin structure
470
471Every plugin has a manifest at `.codex-plugin/plugin.json`. It can also include
472a `skills/` directory, a `hooks/` directory for lifecycle hooks, an `.app.json`
473file that points at one or more connectors, an `.mcp.json` file that
474configures MCP servers, and assets used to present the plugin across supported
475surfaces.
476
477<FileTree
478 class="mt-4"
479 tree={[
480 {
481 name: "my-plugin/",
482 open: true,
483 children: [
484 {
485 name: ".codex-plugin/",
486 open: true,
487 children: [
488 {
489 name: "plugin.json",
490 comment: "Required: plugin manifest",
491 },
492 ],
493 },
494 {
495 name: "skills/",
496 open: true,
497 children: [
498 {
499 name: "my-skill/",
500 open: true,
501 children: [
502 {
503 name: "SKILL.md",
504 comment: "Optional: skill instructions",
505 },
506 ],
507 },
508 ],
509 },
510 {
511 name: "hooks/",
512 open: true,
513 children: [
514 {
515 name: "hooks.json",
516 comment: "Optional: lifecycle hooks",
517 },
518 ],
519 },
520 {
521 name: ".app.json",
522 comment: "Optional: app or connector mappings",
523 },
524 {
525 name: ".mcp.json",
526 comment: "Optional: MCP server configuration",
527 },
528 {
529 name: "assets/",
530 comment: "Optional: icons, logos, screenshots",
531 },
532 ],
533 },
534 ]}
535/>
536
537Only `plugin.json` belongs in `.codex-plugin/`. Keep `skills/`, `hooks/`,
538`assets/`, `.mcp.json`, and `.app.json` at the plugin root.
539
540Published plugins typically use a richer manifest than the minimal example that
541appears in quick-start scaffolds. The manifest has three jobs:
542
543- Identify the plugin.
544- Point to bundled components such as skills, connectors, MCP servers, or hooks.
545- Provide install-surface metadata such as descriptions, icons, and legal
546 links.
547
548Here's a complete manifest example:
549
550```json
551{
552 "name": "my-plugin",
553 "version": "0.1.0",
554 "description": "Bundle reusable skills and connectors.",
555 "author": {
556 "name": "Your team",
557 "email": "team@example.com",
558 "url": "https://example.com"
559 },
560 "homepage": "https://example.com/plugins/my-plugin",
561 "repository": "https://github.com/example/my-plugin",
562 "license": "MIT",
563 "keywords": ["research", "crm"],
564 "skills": "./skills/",
565 "mcpServers": "./.mcp.json",
566 "apps": "./.app.json",
567 "hooks": "./hooks/hooks.json",
568 "interface": {
569 "displayName": "My Plugin",
570 "shortDescription": "Reusable skills and connectors",
571 "longDescription": "Distribute skills and connectors together.",
572 "developerName": "Your team",
573 "category": "Productivity",
574 "capabilities": ["Read", "Write"],
575 "websiteURL": "https://example.com",
576 "privacyPolicyURL": "https://example.com/privacy",
577 "termsOfServiceURL": "https://example.com/terms",
578 "defaultPrompt": [
579 "Use My Plugin to summarize new CRM notes.",
580 "Use My Plugin to triage new customer follow-ups."
581 ],
582 "brandColor": "#10A37F",
583 "composerIcon": "./assets/icon.png",
584 "logo": "./assets/logo.png",
585 "screenshots": ["./assets/screenshot-1.png"]
586 }
587}
588```
589
590`.codex-plugin/plugin.json` is the required entry point. The other manifest
591fields are optional, but published plugins commonly use them.
592
593### Manifest fields
594
595Use the top-level fields to define package metadata and point to bundled
596components:
597
598- `name`, `version`, and `description` identify the plugin.
599- `author`, `homepage`, `repository`, `license`, and `keywords` provide
600 publisher and discovery metadata.
601- `skills`, `mcpServers`, `apps`, and `hooks` point to bundled components
602 relative to the plugin root.
603- `interface` controls how install surfaces present the plugin.
604
605Use the `interface` object for install-surface metadata:
606
607- `displayName`, `shortDescription`, and `longDescription` control the title
608 and descriptive copy.
609- `developerName`, `category`, and `capabilities` add publisher and capability
610 metadata.
611- `websiteURL`, `privacyPolicyURL`, and `termsOfServiceURL` provide external
612 links.
613- `defaultPrompt`, `brandColor`, `composerIcon`, `logo`, and `screenshots`
614 control starter prompts and visual presentation.
615
616### Path rules
617
618- Keep manifest paths relative to the plugin root and start them with `./`.
619- Store visual assets such as `composerIcon`, `logo`, and `screenshots` under
620 `./assets/` when possible.
621- Use `skills` for bundled skill folders, `apps` for `.app.json`,
622 `mcpServers` for `.mcp.json`, and `hooks` for lifecycle hooks.
623- Enabled plugins can include lifecycle hooks alongside skills, MCP servers, and
624 connectors.
625- If your plugin stores hooks at `./hooks/hooks.json`, you don't need a
626 `hooks` entry in `.codex-plugin/plugin.json`; Codex checks that default file
627 automatically.
628
629### Bundled MCP servers and lifecycle hooks
630
631`mcpServers` can point to an `.mcp.json` file that contains either a direct
632server map or a wrapped `mcp_servers` object.
633
634Direct server map:
635
636```json
637{
638 "docs": {
639 "command": "docs-mcp",
640 "args": ["--stdio"]
641 }
642}
643```
644
645Wrapped server map:
646
647```json
648{
649 "mcp_servers": {
650 "docs": {
651 "command": "docs-mcp",
652 "args": ["--stdio"]
653 }
654 }
655}
656```
657
658After installation, users can enable or disable a bundled MCP server and tune
659tool approval policy from their Codex config without editing the plugin. Use
660`plugins.<plugin>.mcp_servers.<server>` for plugin-scoped MCP server policy:
661 100
662```toml1011. Decisions
663[plugins."my-plugin".mcp_servers.docs]1022. Action items with owners
664enabled = true1033. Open questions
665default_tools_approval_mode = "prompt"
666enabled_tools = ["search"]
667
668[plugins."my-plugin".mcp_servers.docs.tools.search]
669approval_mode = "approve"
670```104```
671 105
672When your plugin is enabled, Codex can load lifecycle hooks from your plugin106Use a stable plugin name in kebab case. Keep the skill description specific
673alongside user, project, and managed hooks.107enough for ChatGPT and Codex to recognize when the workflow applies.
674
675Installing or enabling a plugin doesn't automatically trust its hooks.
676Plugin-bundled hooks are non-managed hooks, so Codex skips them until the user
677reviews and trusts the current hook definition.
678
679The default plugin hook file is `hooks/hooks.json`:
680
681```json
682{
683 "hooks": {
684 "SessionStart": [
685 {
686 "hooks": [
687 {
688 "type": "command",
689 "command": "python3 ${PLUGIN_ROOT}/hooks/session_start.py",
690 "statusMessage": "Loading plugin context"
691 }
692 ]
693 }
694 ]
695 }
696}
697```
698
699If you define `hooks` in `.codex-plugin/plugin.json`, Codex uses that manifest
700entry instead of the default `hooks/hooks.json`. The manifest field can be a
701single path, an array of paths, an inline hooks object, or an array of inline
702hooks objects.
703
704```json
705{
706 "name": "repo-policy",
707 "hooks": ["./hooks/session.json", "./hooks/tools.json"]
708}
709```
710 108
711Hook paths follow the same manifest path rules as `skills`, `apps`, and109Use `@plugin-creator` to add the folder to a local marketplace, then install and
712`mcpServers`: start with `./`, resolve relative to the plugin root, and stay110test it before sharing it.
713inside the plugin root.
714 111
715Plugin hook commands receive the Codex-specific environment variables112## Continue with the builder documentation
716`PLUGIN_ROOT` and `PLUGIN_DATA`. `PLUGIN_ROOT` points to the installed plugin
717root, and `PLUGIN_DATA` points to the plugin's writable data directory. Codex
718also sets `CLAUDE_PLUGIN_ROOT` and `CLAUDE_PLUGIN_DATA` for compatibility with
719existing plugin hooks.
720 113
721Plugin hooks use the same event schema as regular hooks. See114For complete builder documentation, use the
722[Hooks](https://learn.chatgpt.com/docs/hooks) for supported events, inputs, outputs, trust review, and115[Plugins documentation](https://developers.openai.com/plugins/). It covers:
723current limitations.
724 116
725### Publish official public plugins117- [Plugin architecture](https://developers.openai.com/plugins/concepts/plugins)
118- [Building skills](https://developers.openai.com/plugins/build/skills)
119- [Building an MCP server](https://developers.openai.com/plugins/build/mcp-server)
120- [Adding optional UI](https://developers.openai.com/plugins/build/chatgpt-ui)
121- [Packaging a plugin](https://developers.openai.com/plugins/build/plugins)
122- [Testing a plugin](https://developers.openai.com/plugins/deploy/connect-chatgpt)
123- [Submitting and publishing](https://developers.openai.com/plugins/deploy/submission)
726 124
727To publish a plugin for public use, submit it through the plugin submission125To browse, install, enable, or remove plugins, see [Use
728portal. See [Submit plugins](https://learn.chatgpt.com/docs/submit-plugins) for the full review and126plugins](https://learn.chatgpt.com/docs/plugins).
729publishing process.