Apus can install plugins from four external ecosystems: the vendor-neutral Agent Plugins standard, plus Codex, Claude, and Cursor. These are called bundles - content and metadata packs that Apus maps into native features like skills, hooks, and MCP tools.

Bundles are not the same as native Apus plugins. Native plugins run in-process and can register any capability. Bundles are content packs with selective feature mapping and a narrower trust boundary.

Why bundles exist

Many useful plugins are published in the Agent Plugins, Codex, Claude, or Cursor format. Instead of requiring authors to rewrite them as native Apus plugins, Apus detects these formats and maps their supported content into the native feature set. You can install an Agent Plugins package, a Claude command pack, or a Codex skill bundle and use it immediately.

Install a bundle

Install from a directory, archive, or marketplace

```bash
# Local directory
apus plugins install ./my-bundle

# Archive
apus plugins install ./my-bundle.tgz

# Claude marketplace
apus plugins marketplace list <source>
apus plugins install <plugin> --marketplace <source>
```

`<source>` is a local marketplace path/repo or a git/GitHub source.

Verify detection

```bash
apus plugins list
apus plugins inspect <id>
```

Bundles show `Format: bundle` plus a `Bundle format:` value of
`agent (Agent Plugins)`, `codex`, `claude`, or `cursor`.

Use the bundle

<a id="restart-and-use" />
Installation applies to the running local Gateway without restarting it.
Start the Gateway if it was stopped. See
[Apply changes and inspect](/plugins/manage-plugins#apply-changes-and-inspect).
Mapped features (skills, hooks, MCP tools, LSP defaults) are available in the next session.

What Apus maps from bundles

Not every bundle feature runs in Apus. Here is what works and what is detected but not wired.

Supported now

Feature How it maps Applies to
Skill content Bundle skill roots load as normal Apus skills All formats
Commands commands/ and .cursor/commands/ treated as skill roots Claude, Cursor
Agents and output styles Claude agents/ and output-styles/ treated as skill roots Claude
Hook packs Apus-style HOOK.md + handler.ts layouts Claude, Codex
MCP tools Bundle MCP config merged into embedded Apus settings; supported stdio and HTTP servers loaded All formats
Env contract PLUGIN_ROOT and PLUGIN_DATA env vars plus placeholder expansion for stdio MCP servers Agent Plugins
LSP servers Claude .lsp.json and manifest-declared lspServers merged into embedded Apus LSP defaults Claude
Settings Claude settings.json imported as embedded Apus defaults Claude

Skill content

Claude markdown command files and Cursor command markdown both work through the normal Apus skill loader.

Hook packs

Bundle hook roots are collection directories. Put each hook's HOOK.md and handler.ts or handler.js in its own child directory, such as hooks/my-hook/, and declare hooks/ as the root. Declaring the hook's leaf directory directly does not load it.

Plugin inspection lists these hook packs separately from detected JSON automation. Claude hooks/hooks.json remains in the declared capabilities, but does not appear as a supported hook. A bundle containing both layouts keeps its Apus hook packs. Inspection does not execute handlers or prove that the running Gateway loaded them.

Embedded Apus settings

Claude settings.json is imported as default embedded Apus settings when the bundle is enabled. Apus sanitizes shell override keys before applying them:

Embedded Apus LSP

Detected but not executed

These are recognized and shown in diagnostics, but Apus does not run them:

MCP for embedded Apus

Transports

MCP servers can use stdio or HTTP transport.

Stdio launches a child process:

{
  "mcp": {
    "servers": {
      "my-server": {
        "command": "node",
        "args": ["server.js"],
        "env": { "PORT": "3000" }
      }
    }
  }
}

HTTP connects to a running MCP server, defaulting to sse unless streamable-http is requested:

{
  "mcp": {
    "servers": {
      "my-server": {
        "url": "http://localhost:3100/mcp",
        "transport": "streamable-http",
        "headers": {
          "Authorization": "Bearer ${MY_SECRET_TOKEN}"
        },
        "connectionTimeoutMs": 30000
      }
    }
  }
}

Tool naming

Apus registers bundle MCP tools with provider-safe names in the form serverName__toolName. For example, a server keyed "vigil-harbor" exposing a memory_search tool registers as vigil-harbor__memory_search.

Bundle formats

Agent Plugins bundles
Marker: `plugin.json` at the package root, per the open
[Agent Plugins 1.0.0 standard](https://agent-plugins.org)

Optional content: `skills/`, `mcp.json`

Format behavior:

- The manifest is strict JSON (not JSON5). Apus requires a non-empty
  `name`; other manifest fields are optional and unknown fields are ignored
- Immediate child directories of `skills/` that contain a `SKILL.md` load as
  skills; children without one are skipped with a warning, and deeper
  directories are not scanned
- `mcp.json` must declare the 1.0.0 `$schema` and an `mcpServers` object
  only; `stdio`, `streamable-http`, and legacy `sse` transports are
  supported
- stdio servers launch with `PLUGIN_ROOT` (the plugin root) and
  `PLUGIN_DATA` (a persistent per-plugin data directory Apus creates
  under its state dir) in their environment; `${PLUGIN_ROOT}` and
  `${PLUGIN_DATA}` placeholders expand in `args`, `env` values, and `cwd`
  in a single pass
- A stdio `command` must be a bare executable name or a `./`-relative path
  inside the plugin; `cwd` must stay inside `PLUGIN_ROOT` or `PLUGIN_DATA`
- Invalid `mcp.json` disables MCP for the plugin with a diagnostic while
  skills keep loading; invalid individual server entries are skipped
- `.mcp.json` (dot-prefixed) and inline manifest `mcpServers` are **not**
  read for this format; the standard's closed schema wins
- Apus reads `extensions["ai.apus"]`; it supports only
  `activation` with the same semantics as other bundle manifests
- Other manifest extension namespaces are ignored and reserved for their
  clients
- Reverse-domain client directories are ignored and reserved
Codex bundles
Markers: `.codex-plugin/plugin.json`

Optional content: `skills/`, `hooks/`, `.mcp.json`, `.app.json`

Codex bundles fit Apus best when they use skill roots and Apus-style
hook-pack directories (`HOOK.md` + `handler.ts`).
Claude bundles
Two detection modes:

- **Manifest-based:** `.claude-plugin/plugin.json`
- **Manifestless:** default Claude layout (`skills/`, `commands/`, `agents/`, `hooks/`, `.mcp.json`, `.lsp.json`, `settings.json`)

`output-styles/` is not a detection marker. A bundle whose only content is
`output-styles/` is not recognized as a Claude bundle. Add
`.claude-plugin/plugin.json`, or one of the markers above, so detection
succeeds. Detection runs before manifest loading, so an undetected
directory never reaches the component paths below.

Claude-specific behavior:

- `commands/`, `agents/`, and `output-styles/` are treated as skill content
- `settings.json` is imported into embedded Apus settings (shell override keys are sanitized)
- `.mcp.json` exposes supported stdio tools to embedded Apus
- `.lsp.json` plus manifest-declared `lspServers` paths load into embedded Apus LSP defaults
- `hooks/hooks.json` is detected but not executed
- Custom component paths in the manifest are additive; they extend defaults, not replace them
Cursor bundles
Markers: `.cursor-plugin/plugin.json`

Optional content: `skills/`, `.cursor/commands/`, `.cursor/agents/`, `.cursor/rules/`, `.cursor/hooks.json`, `.mcp.json`

- `.cursor/commands/` is treated as skill content
- `.cursor/rules/`, `.cursor/agents/`, and `.cursor/hooks.json` are detect-only

Detection precedence

Apus checks for native plugin format first:

  1. apus.plugin.json or a valid package.json with apus.extensions - treated as a native plugin
  2. Client-specific bundle markers (.codex-plugin/, .cursor-plugin/, .claude-plugin/) - treated as a bundle in that format
  3. A root plugin.json - treated as an Agent Plugins bundle
  4. Default manifestless Claude layout (skills/, commands/, .mcp.json, ...) - treated as a Claude bundle

If a package carries both a client-specific marker and a root plugin.json, the client-specific format wins so its richer mappings (commands, hooks, settings) are preserved. If a directory contains both a native manifest and bundle markers, Apus uses the native path. This prevents dual-format packages from being partially installed as bundles.

Runtime dependencies and cleanup

Security

Bundles have a narrower trust boundary than native plugins:

This makes bundles safer by default, but you should still treat third-party bundles as trusted content for the features they do expose.

Troubleshooting

Bundle is detected but capabilities do not run
Run `apus plugins inspect <id>`. If a capability is listed but marked as
not wired, that is a product limit, not a broken install.
Claude command, agent, or output-style files do not appear
Make sure the bundle is enabled and the markdown files are inside a detected
`skills/`, `commands/`, `agents/`, or `output-styles/` root. All four load
through the same skill loader.
Claude settings do not apply
Only embedded Apus settings from `settings.json` are supported. Apus does
not treat bundle settings as raw config patches.
Claude hooks do not execute
`hooks/hooks.json` is detect-only. If you need runnable hooks, use the
Apus hook-pack layout or ship a native plugin.

Related