Building a plugin marketplace: what we can learn from Codex's plugin system
How Codex's plugin architecture works under the hood — marketplace catalogs, plugin manifests, installation lifecycle, permission models, and the design decisions that make an agent plugin system installable and safe.
Every platform eventually needs a plugin system. VS Code has extensions. Chrome has extensions. npm has packages. AI coding agents are no different — they need a way to bundle and distribute reusable capabilities.
Codex’s plugin architecture is a worked example of how to build one. Plugins bundle skills, app integrations, and MCP servers into installable units distributed through marketplace catalogs. The architecture makes specific design choices worth understanding whether you’re building on Codex or designing your own agent plugin system.
What a plugin actually bundles
A plugin is a directory with a manifest. It can contain four kinds of components:
| Component | Defined in | Purpose |
|---|---|---|
| Skills | skills/<name>/SKILL.md | Task-specific instructions that load on demand |
| Apps | .app.json | Connections to external tools (GitHub, Slack, Gmail) |
| MCP Servers | .mcp.json | Model Context Protocol server configuration |
| Lifecycle hooks | hooks/hooks.json | Event-driven automation at session boundaries |
Only the manifest at .codex-plugin/plugin.json is required. Everything else is optional. The minimal viable plugin packages one skill — that’s enough to be useful.
{
"name": "my-first-plugin",
"version": "1.0.0",
"description": "Reusable greeting workflow",
"skills": "./skills/"
} The plugin manifest
The manifest has three jobs: identify the plugin, point to bundled components, and provide install-surface metadata. Published plugins use a richer manifest:
{
"name": "my-plugin",
"version": "0.1.0",
"description": "Bundle reusable skills and app integrations.",
"author": {
"name": "Your team",
"email": "team@example.com",
"url": "https://example.com"
},
"homepage": "https://example.com/plugins/my-plugin",
"repository": "https://github.com/example/my-plugin",
"license": "MIT",
"keywords": ["research", "crm"],
"skills": "./skills/",
"mcpServers": "./.mcp.json",
"apps": "./.app.json",
"hooks": "./hooks/hooks.json",
"interface": {
"displayName": "My Plugin",
"shortDescription": "Reusable skills and apps",
"longDescription": "Distribute skills and app integrations together.",
"developerName": "Your team",
"category": "Productivity",
"capabilities": ["Read", "Write"],
"websiteURL": "https://example.com",
"privacyPolicyURL": "https://example.com/privacy",
"termsOfServiceURL": "https://example.com/terms",
"defaultPrompt": [
"Use My Plugin to summarize new CRM notes.",
"Use My Plugin to triage new customer follow-ups."
],
"brandColor": "#10A37F",
"composerIcon": "./assets/icon.png",
"logo": "./assets/logo.png",
"screenshots": ["./assets/screenshot-1.png"]
}
} The interface object is where install-surface design happens. displayName, shortDescription, and longDescription control how the plugin appears in directories. defaultPrompt provides starter prompts that appear in the composer. brandColor, composerIcon, and logo control visual presentation. privacyPolicyURL and termsOfServiceURL provide legal links.
The marketplace catalog
A marketplace is a JSON catalog of plugins. It’s what turns a directory of plugin files into something installable:
{
"name": "local-example-plugins",
"interface": {
"displayName": "Local Example Plugins"
},
"plugins": [
{
"name": "my-plugin",
"source": {
"source": "local",
"path": "./plugins/my-plugin"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
},
{
"name": "research-helper",
"source": {
"source": "local",
"path": "./plugins/research-helper"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
]
} Each marketplace entry specifies:
source— Where the plugin lives (localpath orurl/git-subdirfor Git-backed plugins)policy.installation—AVAILABLE,INSTALLED_BY_DEFAULT, orNOT_AVAILABLEpolicy.authentication— Whether auth happensON_INSTALLor on first usecategory— Grouping label in the plugin directory
Marketplace sources
Codex supports three source types:
| Source type | Use case | Example |
|---|---|---|
local | Plugin in a local directory | { "source": "local", "path": "./plugins/my-plugin" } |
url | Plugin at a Git repository root | { "source": "url", "url": "https://github.com/example/plugin.git" } |
git-subdir | Plugin in a subdirectory of a Git repo | Add "path": "./plugins/remote-helper" and optional "ref" |
Git-backed entries can pin to a ref (branch or tag) or sha. If Codex can’t resolve a marketplace entry’s source, it skips that plugin entry instead of failing the whole marketplace.
Marketplace files live at:
$REPO_ROOT/.agents/plugins/marketplace.json— repo-scoped catalog~/.agents/plugins/marketplace.json— personal catalog
The CLI can manage marketplace sources:
codex plugin marketplace add owner/repo
codex plugin marketplace add owner/repo --ref main
codex plugin marketplace add ./local-marketplace-root
codex plugin marketplace upgrade # refresh all
codex plugin marketplace remove marketplace-name
Installation lifecycle
When a user installs a plugin, Codex copies it into a cache:
~/.codex/plugins/cache/$MARKETPLACE_NAME/$PLUGIN_NAME/$VERSION/
For local plugins, $VERSION is local. Codex loads the installed copy from this cache path, not directly from the marketplace entry. This means marketplace updates don’t affect installed plugins until the user re-installs.
After installation, the plugin is available immediately. Bundled skills appear in skill selectors. MCP servers are configured. Hooks are loaded. Apps may prompt for authentication on first use.
Permission and security model
Installing a plugin makes its workflows available, but existing approval settings still apply. The security model has layers:
- Installation policy —
INSTALLED_BY_DEFAULTvs.AVAILABLEcontrols who sees what. - Approval settings — Your
approval_policystill governs whether the agent needs permission before acting. - App authentication — External services require their own auth. No data flows without consent.
- Sandbox policy — File access is still constrained by sandbox mode.
When Codex sends data through a bundled app, that app’s terms and privacy policy apply. Plugins don’t create new data-sharing paths — they wire existing services into the agent’s tool surface.
Building your own curated list
One marketplace can expose a single plugin while you’re testing, then grow into a larger catalog:
- Scaffold a plugin with
$plugin-creator— it generates the manifest and can create a local marketplace entry. - Add more plugins to the same marketplace file as you build them.
- The marketplace appears as a selectable source in the plugin directory.
- Restart Codex after changes. The plugin directory picks up marketplace file changes on restart.
What this means for platform builders
The plugin architecture makes several design choices worth noting:
- JSON manifests, not code packages. Plugins are declarative — they point to components rather than executing initialization code. This makes them inspectable and safe to install.
- Marketplaces are separate from plugins. A plugin doesn’t know about marketplaces. Marketplaces point to plugins. This decoupling means the same plugin can appear in multiple catalogs.
- Cache-based installation. Codex copies plugins into a versioned cache rather than running them from source. This prevents marketplace changes from silently affecting installed plugins.
- Progressive capability. The minimal plugin is one skill in a directory. You add apps, MCP servers, and hooks as needed. The architecture scales from personal workflow to team infrastructure.
Plugins bundle four component types
Skills, apps, MCP servers, and lifecycle hooks — all pointed to by a single JSON manifest. Only the manifest is required; everything else is optional.
Marketplaces are JSON catalogs, not stores
A marketplace file lists plugins with source locations, install policies, and display metadata. One marketplace can expose one plugin or a curated collection.
Cache-based installation prevents silent changes
Codex copies plugins into a versioned cache on install. Marketplace updates don't affect installed plugins — users must re-install to pick up changes.
Security is layered, not binary
Installation policy, approval settings, app authentication, and sandbox mode combine. No single switch makes a plugin safe or dangerous.
Skills author, plugins distribute
The development path: iterate locally as a skill, package as a plugin when stable. The architecture supports this progression naturally.