Skip to content

Plugins

A plugin is a distribution and composition unit for a cohesive, stable capability. It is not the place to begin authoring a workflow and not a generic folder for every agent-related file in an organization.

When to create a plugin

Start with a repo-local skill or configuration while one team is still learning the workflow. Create a plugin when at least one of these is true:

  • multiple repositories or teams need to install and update the capability;
  • multiple related skills need one namespace and release lifecycle;
  • a workflow must ship with MCP configuration, connectors/apps, lifecycle hooks, or presentation assets;
  • consumers need a marketplace, workspace installation, or controlled version rather than copied files.

Keep local configuration when the workflow is experimental, repo-specific, or personal. Packaging too early turns every routing adjustment into a release and hides whether the workflow itself is useful.

OpenAI plugin layout

my-plugin/
├── .codex-plugin/
│ └── plugin.json
├── skills/
│ └── my-skill/SKILL.md
├── hooks/
│ └── hooks.json
├── .mcp.json
├── .app.json
└── assets/

Only plugin.json belongs inside .codex-plugin/. The other components stay at the plugin root. A minimal manifest is:

{
"name": "my-plugin",
"version": "1.0.0",
"description": "One cohesive reusable capability",
"skills": "./skills/"
}

Use a stable kebab-case name because it becomes the plugin identifier and component namespace. Paths are relative to the plugin root and should begin with ./. Published plugins should also identify the author, repository, license, interface copy, and appropriate visual or policy links.

OpenAI plugins can package:

  • one or more skills;
  • lifecycle hooks;
  • MCP server configuration through .mcp.json;
  • ChatGPT app or connector mappings through .app.json;
  • browser capabilities and scheduled-task templates where the target surface supports them;
  • install-surface metadata and assets.

An enabled plugin’s default hook path is hooks/hooks.json; a manifest hooks entry can instead specify one or more paths or inline objects. Installing a plugin does not automatically trust its command hooks—the current definitions must still be reviewed.

Anthropic plugin layout

Anthropic uses .claude-plugin/plugin.json and likewise keeps components at the plugin root. Its documented component set additionally includes custom agents, language-server configuration, background monitors, executables added to the agent shell path, and limited default settings.

my-plugin/
├── .claude-plugin/plugin.json
├── skills/
├── agents/
├── hooks/hooks.json
├── monitors/monitors.json
├── bin/
├── .mcp.json
├── .lsp.json
└── settings.json

The manifest is optional when standard locations are sufficient, but a shared EOS release should normally keep one for identity and ownership. At the time reviewed, settings.json supports only agent and subagentStatusLine; unknown keys are ignored, so validate effective behaviour rather than JSON shape alone.

Do not force those components into an OpenAI manifest that does not document them. For a dual-client package, use two manifests over one cohesive root, share portable skills and scripts, and keep client-specific hooks, agent profiles, or integration metadata explicit.

MCP and connector packaging

OpenAI’s .mcp.json may contain a direct server map:

{
"docs": {
"command": "docs-mcp",
"args": ["--stdio"]
}
}

or a map wrapped in mcp_servers. .app.json points to ChatGPT app/connector mappings. Packaging configuration does not remove the need to review server authentication, exposed tools, network destinations, data sensitivity, approval behavior, and failure modes.

Distribution

Anthropic development plugins can be loaded with --plugin-dir, combined by repeating the flag, and refreshed with /reload-plugins. A local copy takes precedence over an installed plugin of the same name unless managed policy forces the state. Marketplace installations are copied into a versioned local cache; old versions remain for a documented seven-day grace period so active sessions do not break, and installed symlinks must resolve inside the plugin directory.

OpenAI supports repository and personal marketplace catalogues at:

  • $REPO_ROOT/.agents/plugins/marketplace.json;
  • ~/.agents/plugins/marketplace.json.

Repository marketplace entries often point to ./plugins/<name>. Git-backed entries should use an intentional ref or commit; package-registry sources need an equally explicit version policy. Workspace sharing is appropriate when selected teammates install through the desktop app; a marketplace is appropriate for repo/CLI distribution and curated lists.

Anthropic uses marketplace metadata under .claude-plugin/. Maintain one release identity across catalogues, but validate installation separately for each client.

Test and release

Before release:

  1. validate both manifest shape and every relative path;
  2. test each skill’s explicit invocation, routing, and output independently;
  3. test each hook event with fixtures and in the client;
  4. start MCP servers in a clean environment and verify auth and tool schemas;
  5. review all scripts, binaries, remote sources, and network behavior as executable supply-chain inputs;
  6. verify hook trust prompts and project trust behavior;
  7. install from the actual marketplace path in a clean workspace;
  8. verify upgrade, rollback, disable, and uninstall behavior;
  9. publish ownership, compatibility, changelog, and retirement policy.

Also verify the activation boundary: OpenAI CLI and IDE installations require a new task or chat before bundled capabilities are available, while Anthropic supports explicit plugin reload. If a plugin needs a connector, authentication and revocation are separate from package installation.

When migrating local definitions into a plugin, remove or disable the originals after validation so duplicate skills and hooks do not both load.

Sources: OpenAI Build plugins, OpenAI Build skills, and Anthropic plugins.