Install a plugin
Install from a local folder, a GitHub repository, or any git URL:owner/repo is short for https://github.com/owner/repo.git. o4 clones the
repository or copies the folder into its plugins folder:
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.
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:
--project refuses to
install into an untrusted one. Run o4 trust in the project first. See
Workspace trust.
You can have the same plugin in both places. They’re listed separately.
List and remove plugins
o4 plugin list also warns when the current project has plugins that aren’t
loaded because the workspace isn’t trusted.
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 amarketplace.json catalog.
Register one, and you can install its plugins by name:
name@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 amarketplace.json at the root of a repository or folder, or in
.o4-plugin/marketplace.json:
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.
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 asdisabled componentrows. 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.
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
A plugin’s skills can include hooks in their front matter; those run while
the skill is active (see Hooks in skills).
Plugins in the portable, Codex, Claude Code, and Cursor formats can also
declare MCP servers. See 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 incommands/. The file name is the command
name, unless the front matter sets name:
/changelog 2.4.0, o4 sends the body to the model, with these
replaced:
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 inworkflows/<name>.yaml:
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:
--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 intools/ whose YAML front matter defines
a tool the model can call. The body of the file isn’t used.
A
binding has one of two types:
commandruns a program.argv-templateis 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/sbinor/sbin.timeout-msdefaults to30000. The tool returns the program’s standard output, or its standard error if it fails.templatereturnstext, with each{parameter}replaced, without running anything.
Approving plugin tools
o4 asks for your approval each time the model calls a plugin tool. A tool also needs each capability it uses; acommand 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.
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:
.o4-plugin/plugin.json:
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:
capabilitieslists what the plugin provides, astrueorfalseforcommands,agents,skills,workflows,state,uiandhooks. It’s descriptive only: it doesn’t turn anything on or off.permissionslimits what the plugin’s parts may use. A command whoseallowed-tools, a subagent whosetools, or a skill whoseallowed-toolsnames a tool outsidepermissions.toolsisn’t loaded. A plugin tool whoserequired-grantsasks for a tool outsidepermissions.tools, a path outsidepermissions.paths, or the network whennetworkisfalse, isn’t loaded either. Each skipped part is listed on the Errors tab and as adisabled componentrow in the plugin’s details in/plugins, ando4 plugin listprints a warning for it. Tool names match without regard to case or punctuation.
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:
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:
So you can often install a plugin written for another agent as is.
The portable format is stricter than o4’s own:
$schemamust behttps://agent-plugins.org/schemas/1.0.0/plugin.schema.json. o4 refuses other schema versions withunsupported Agent Plugins schema.namecan use lowercase letters, digits,.and-, up to 64 characters. It must start and end with a letter or digit, and can’t contain--or...versionis optional. o4 lists a plugin without one asunversioned.authormust be an object with onlyname,emailandurl.version,description,authorandhomepagecan’t benull.
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.