> ## Documentation Index
> Fetch the complete documentation index at: https://docs.open4rena.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins and marketplaces

> Install plugins that add commands, skills, agents, and more.

A plugin is a folder that bundles things o4 can use: slash commands, skills,
subagent definitions, workflows, and, in some formats, MCP servers. Install a
plugin to share a team's commands and skills, or to use a set someone else
has published. A marketplace is a catalog of plugins that you can install by
name.

## Install a plugin

Install from a local folder, a GitHub repository, or any git URL:

```bash theme={null}
o4 plugin install ./team-tools
o4 plugin install acme/o4-team-tools
o4 plugin install https://git.example.com/acme/o4-team-tools.git
```

`owner/repo` is short for `https://github.com/owner/repo.git`. o4 clones the
repository or copies the folder into its plugins folder:

```text theme={null}
$ o4 plugin install ./team-tools
Installed plugin 'team-tools' v1.0.0 (1 commands, 1 agents, 1 skills)
```

The plugin's commands show up as slash commands, and its skills and agents
become available to the model. A plugin you install with `o4 plugin install`
loads in your next session. A plugin you install from `/plugins` in a
session is available in that session right away. o4 then restarts your MCP
servers, so the plugin's MCP servers start too.

<Warning>
  A plugin can give the model new instructions and can start programs on your
  machine. Install plugins only from sources you trust.
</Warning>

### Global and project plugins

By default a plugin is installed globally, in `~/.o4/plugins`, and is
available in every workspace. Use `--project` to install it into the current
project's `.o4/plugins` instead:

```bash theme={null}
o4 plugin install --project ./team-tools
```

Project plugins only load in a trusted workspace, and `--project` refuses to
install into an untrusted one. Run `o4 trust` in the project first. See
[Workspace trust](/safety/workspace-trust).

You can have the same plugin in both places. They're listed separately.

### List and remove plugins

```text theme={null}
$ o4 plugin list
team-tools v1.0.0 [global] — Shared commands and skills for our team
team-tools v1.0.0 [project] — Shared commands and skills for our team
```

`o4 plugin list` also warns when the current project has plugins that aren't
loaded because the workspace isn't trusted.

```bash theme={null}
o4 plugin remove team-tools
```

`o4 plugin remove` removes the project copy if there is one, and otherwise the
global one. It also removes any permissions you granted the plugin.

## Marketplaces

A marketplace is a git repository or folder with a `marketplace.json` catalog.
Register one, and you can install its plugins by name:

```bash theme={null}
o4 plugin marketplace add acme/o4-marketplace
o4 plugin install hello
```

If two marketplaces list a plugin with the same name, pick one with
`name@marketplace`:

```bash theme={null}
o4 plugin install hello@acme
```

| Command | What it does |
| - | - |
| `o4 plugin marketplace add <source>` | Register a marketplace from `owner/repo`, a git URL, or a local folder |
| `o4 plugin marketplace list` | List registered marketplaces and how many plugins each has |
| `o4 plugin marketplace refresh [name]` | Fetch the latest catalog for one marketplace, or all of them |
| `o4 plugin marketplace remove <name>` | Unregister a marketplace |

o4 keeps marketplace data in `~/.o4/marketplaces`.

On the first interactive launch, if you haven't registered any marketplaces,
o4 tries once to register an official marketplace. If that fails, for example
because you're offline, o4 doesn't try again, and you can add marketplaces
yourself.

### Create a marketplace

Put a `marketplace.json` at the root of a repository or folder, or in
`.o4-plugin/marketplace.json`:

```json theme={null}
{
  "name": "acme",
  "description": "Acme's internal plugins",
  "owner": { "name": "Acme" },
  "plugins": [
    {
      "name": "hello",
      "source": "./plugins/hello",
      "description": "A /hello command",
      "version": "1.0.0",
      "category": "examples",
      "tags": ["starter"]
    }
  ]
}
```

Each plugin's `source` is one of:

* A path inside the marketplace that starts with `./`, for a plugin kept in
  the same repository. The path can't lead outside the marketplace.
* `owner/repo`, for a plugin in its own GitHub repository.
* A full git URL.
* A path to a folder elsewhere on your machine, only in a marketplace you
  added from a local folder.

The marketplace needs a `name`, and each plugin entry needs a `name` and a
`source`. The **Discover** tab of `/plugins` shows each plugin's `description`
and `category`, and its filter searches them along with the plugin and
marketplace names. `owner`, if present, needs a `name` and can have a `url`,
but o4 doesn't show it. A plugin entry's `version` and `tags` are accepted but
not used.

## Manage plugins in a session

`/plugins` opens the plugin browser. It has four tabs:

* **Discover**: plugins from your marketplaces. Select one to install it.
* **Installed**: your plugins. Select one to update it (pull the latest
  changes from its source), validate its files, remove it, or revoke a saved
  capability grant (the `granted:` rows). Parts of the plugin that were
  skipped are listed as `disabled component` rows. The first row,
  **Install plugin**, installs from a git URL, `owner/repo`, or path, globally
  or for the project.
* **Marketplaces**: your marketplaces. Add, refresh, or remove them here.
* **Errors**: plugins or plugin files that failed to load, with the reason.

You can also go straight to an action with a subcommand:

| Command | What it does |
| - | - |
| `/plugins` or `/plugins list` | Open the plugin browser |
| `/plugins install` | Open the **Install plugin** form |
| `/plugins install <source> [--project]` | Install a plugin by marketplace name, `owner/repo`, git URL or path |
| `/plugins update <name>` | Pull the latest version of a plugin installed from git |
| `/plugins remove <name>` | Remove a plugin |
| `/plugins validate [name]` | Check one plugin's files, or all plugins', for errors |
| `/plugins new <name>` | Create a plugin skeleton in the project's `.o4/plugins` |
| `/plugins marketplace` or `/plugins marketplace list` | List your marketplaces |
| `/plugins marketplace add <source>` | Register a marketplace |
| `/plugins marketplace refresh [name]` | Refresh marketplace catalogs |
| `/plugins marketplace remove <name>` | Unregister a marketplace |

A plugin copied from a local folder can't be updated. Install it again to
pick up changes.

While the model is working, you can still open the browser, validate plugins
and revoke grants, but installing, updating or removing a plugin and
refreshing or removing a marketplace are refused: o4 closes the browser and
shows `Wait for the current turn to finish before making this change.` Typed
commands that change plugins, such as `/plugins install <source>` and
`/plugins remove <name>`, wait for the turn to finish instead.

The **Plugins** tab in `/config` (run `/config plugins` to go straight to it)
has one row, **Open plugin browser**. It opens the same plugin browser as
`/plugins`. The browser starts on **Discover**, or on **Installed** when you
have plugins, and returns to the tab you last used in the session.

## What a plugin can contain

| Folder | What it adds |
| - | - |
| `commands/` | Slash commands, one Markdown file each |
| `skills/` | Skills, one folder with a `SKILL.md` each. See [Skills](/extend/skills). |
| `agents/` | Subagent definitions, one Markdown file each. See [Subagents](/guides/subagents). |
| `workflows/` | Workflows that run several commands in stages, as `.yaml` or `.yml` files |
| `tools/` | Tools the model can call, defined in Markdown files |

A plugin's skills can include hooks in their front matter; those run while
the skill is active (see [Hooks in skills](/extend/hooks#hooks-in-skills)).
Plugins in the portable, Codex, Claude Code, and Cursor formats can also
declare MCP servers. See [Plugin formats](#plugin-formats).

o4 reads at most 256 files from each component folder, and 256 plugins from
each plugins folder. A file that fails to load is listed on the **Errors**
tab of `/plugins`; the rest of the plugin still loads.

Print mode (`o4 -p`) doesn't load plugin commands, skills, subagents or
tools. It does start the MCP servers that plugins declare.

### Commands

A command is a Markdown file in `commands/`. The file name is the command
name, unless the front matter sets `name`:

```markdown theme={null}
---
description: Draft a changelog entry for the current branch
argument-hint: "[version]"
---
Draft a changelog entry for version $ARGUMENTS from the commits on this branch.
```

When you run `/changelog 2.4.0`, o4 sends the body to the model, with these
replaced:

| Placeholder | Replaced with |
| - | - |
| `$ARGUMENTS` | The text after the command |
| `$CWD` | The current working directory |
| `$O4_PLUGIN_ROOT` | The plugin's folder |

Built-in slash commands and your own skills take precedence over a plugin's
commands with the same name.

### Workflows

A workflow runs a plugin's commands one after another as stages. Define it in
`workflows/<name>.yaml`:

```yaml theme={null}
schema: 1
name: release
description: Prepare and check a release
entry: plan
stages:
  - plan
  - build
  - verify
commands:
  plan: release-plan
  build: release-build
  verify: release-verify
agents: {}
state:
  path: .o4/state/plugins/team-tools/release
```

`commands` maps each stage to one of the plugin's commands. `entry` is the
command for the first stage if `commands` doesn't list one. `agents` can map a
stage to one of the plugin's agents, whose instructions are used for that
stage. When `state.path` is set, o4 saves the workflow's progress there, so a
later run continues from the next stage. The path must be inside
`.o4/state/plugins/<plugin-name>/`.

Run workflows with `/workflow`:

```text theme={null}
/workflow list
/workflow run release 2.4.0
/workflow run release --stage verify
```

`--stage` starts from a given stage. Text after the workflow name (and the
stage) is passed to each stage's command as `$ARGUMENTS`.

### Tools

A plugin tool is a Markdown file in `tools/` whose YAML front matter defines
a tool the model can call. The body of the file isn't used.

```markdown theme={null}
---
name: count-lines
description: Count the lines in a file of this project
parameters:
  type: object
  properties:
    path:
      type: string
  required: [path]
binding:
  type: command
  argv-template: ["wc", "-l", "{path}"]
  timeout-ms: 10000
---
```

| Field | Meaning |
| - | - |
| `name` | The tool's name. Required, and unique within the plugin. |
| `description` | What the model sees about the tool. |
| `parameters` | A JSON Schema for the tool's input, with `type: object`. Required. |
| `binding` | What happens when the model calls the tool. See below. |
| `required-grants` | Capabilities the tool needs: `exec`, `network`, `path:<path>` or `tool:<name>`. |

A `binding` has one of two types:

* `command` runs a program. `argv-template` is the program and its
  arguments; each `{parameter}` in them is replaced with the value the model
  passed. o4 runs the program directly, not through a shell, in o4's sandbox,
  from the plugin's folder, with a minimal environment. The program must be
  inside the plugin's folder or in `/usr/bin`, `/bin`, `/usr/sbin` or
  `/sbin`. `timeout-ms` defaults to `30000`. The tool returns the program's
  standard output, or its standard error if it fails.
* `template` returns `text`, with each `{parameter}` replaced, without
  running anything.

A tool with the same name as a built-in tool, or as a tool from another
plugin, isn't loaded.

#### Approving plugin tools

o4 asks for your approval each time the model calls a plugin tool. A tool
also needs each capability it uses; a `command` tool always needs `exec`. The
first time, o4 asks you to grant the capability to the plugin: allow it once
(`y`), allow it always (`a`), or deny it (`n`). An "always" grant is saved in
`~/.o4/settings.json` and tied to the plugin's current files, so o4 asks
again after the plugin is updated or changed. To revoke a grant, open the
plugin in `/plugins`; each saved grant is listed as a `granted:` row that you
can select to revoke. See [Permissions](/safety/permissions).

The sandbox blocks the program's network access unless the tool has the
`network` grant, and `exec` alone doesn't let it write files. In o4 0.2.74,
a tool that requires a `path:` grant always fails with "plugin path
capabilities are disabled".

## Create a plugin

`/plugins new team-tools` creates a starter plugin in `.o4/plugins/team-tools`
with a manifest, a `/main` command, a `main` workflow, and a README. o4
lowercases the name and turns other characters into `-`. The plugin loads
right away. Edit the files, then start a new session to load your changes.
The workspace must be trusted, because project plugins only load there.

To build one by hand, make a folder with a manifest and any of the component
folders:

```text theme={null}
team-tools/
  .o4-plugin/
    plugin.json
  commands/
    changelog.md
  skills/
    deploy-check/
      SKILL.md
  agents/
    reviewer.md
```

The manifest, `.o4-plugin/plugin.json`:

```json theme={null}
{
  "name": "team-tools",
  "version": "1.0.0",
  "description": "Shared commands and skills for our team",
  "author": "Platform team"
}
```

`name` and `version` are required. The name can use letters, digits, `.`,
`_`, and `-`, up to 128 characters. `author` can be a string or an object
with a `name`.

The manifest can also have `capabilities` and `permissions`:

```json theme={null}
{
  "name": "team-tools",
  "version": "1.0.0",
  "capabilities": { "commands": true, "skills": true },
  "permissions": {
    "tools": ["read", "grep", "bash"],
    "paths": [],
    "network": false
  }
}
```

* `capabilities` lists what the plugin provides, as `true` or `false` for
  `commands`, `agents`, `skills`, `workflows`, `state`, `ui` and `hooks`.
  It's descriptive only: it doesn't turn anything on or off.
* `permissions` limits what the plugin's parts may use. A command whose
  `allowed-tools`, a subagent whose `tools`, or a skill whose
  `allowed-tools` names a tool outside `permissions.tools` isn't loaded. A
  plugin tool whose `required-grants` asks for a tool outside
  `permissions.tools`, a path outside `permissions.paths`, or the network
  when `network` is `false`, isn't loaded either. Each skipped part is listed
  on the **Errors** tab and as a `disabled component` row in the plugin's
  details in `/plugins`, and `o4 plugin list` prints a warning for it. Tool
  names match without regard to case or punctuation.

Without `permissions`, none of these checks apply. o4 reads `capabilities`
and `permissions` only from `.o4-plugin/plugin.json`.

Install it from its folder to test it:

```bash theme={null}
o4 plugin install ./team-tools
```

To share it, push the folder to a git repository and install it with
`o4 plugin install owner/repo`, or list it in a marketplace.

### Plugin formats

o4 looks for a manifest in this order and uses the first one it finds:

| Manifest | Format |
| - | - |
| `.o4-plugin/plugin.json` | o4's own format |
| `plugin.json` with a `$schema` from `agent-plugins.org` | The portable Agent Plugins format |
| `.codex-plugin/plugin.json` | Codex plugins |
| `.claude-plugin/plugin.json` | Claude Code plugins |
| `.cursor-plugin/plugin.json` | Cursor plugins |

So you can often install a plugin written for another agent as is.

The portable format is stricter than o4's own:

* `$schema` must be `https://agent-plugins.org/schemas/1.0.0/plugin.schema.json`.
  o4 refuses other schema versions with `unsupported Agent Plugins schema`.
* `name` can use lowercase letters, digits, `.` and `-`, up to 64 characters.
  It must start and end with a letter or digit, and can't contain `--` or `..`.
* `version` is optional. o4 lists a plugin without one as `unversioned`.
* `author` must be an object with only `name`, `email` and `url`.
* `version`, `description`, `author` and `homepage` can't be `null`.

The Codex, Claude Code, and Cursor manifests can point to skill folders with
`skills` and to an MCP configuration with `mcpServers`. These paths must start
with `./` and stay inside the plugin folder, or o4 refuses the plugin.
`mcpServers` can also list the servers inline.

MCP servers from plugins come from the portable format, which reads them from
`mcp.json` in the plugin folder, and from the other agents' formats, which
read the manifest's `mcpServers`, or `.mcp.json` in the plugin folder when the
manifest has none. A plugin's MCP servers start
with your own servers. If a server in your `.mcp.json` has the same name, yours
is used. See [MCP servers](/extend/mcp).
