Files
openclaw/docs/plugins/manifest.md
Onur Solmaz 047485dda6 docs: improve plugin manifest reference (#52393)
* docs: improve plugin manifest reference

* docs: clarify manifest field semantics
2026-03-22 18:29:20 +01:00

13 KiB

summary, read_when, title
summary read_when title
Plugin manifest + JSON schema requirements (strict config validation)
You are building an OpenClaw plugin
You need to ship a plugin config schema or debug plugin validation errors
Plugin Manifest

Plugin manifest (openclaw.plugin.json)

This page is for the native OpenClaw plugin manifest only.

For compatible bundle layouts, see Plugin bundles.

Compatible bundle formats use different manifest files:

  • Codex bundle: .codex-plugin/plugin.json
  • Claude bundle: .claude-plugin/plugin.json or the default Claude component layout without a manifest
  • Cursor bundle: .cursor-plugin/plugin.json

OpenClaw auto-detects those bundle layouts too, but they are not validated against the openclaw.plugin.json schema described here.

For compatible bundles, OpenClaw currently reads bundle metadata plus declared skill roots, Claude command roots, Claude bundle settings.json defaults, and supported hook packs when the layout matches OpenClaw runtime expectations.

Every native OpenClaw plugin must ship a openclaw.plugin.json file in the plugin root. OpenClaw uses this manifest to validate configuration without executing plugin code. Missing or invalid manifests are treated as plugin errors and block config validation.

See the full plugin system guide: Plugins. For the native capability model and current external-compatibility guidance: Capability model.

What this file does

openclaw.plugin.json is the metadata OpenClaw reads before it loads your plugin code.

Use it for:

  • plugin identity
  • config validation
  • auth and onboarding metadata that should be available without booting plugin runtime
  • config UI hints

Do not use it for:

  • registering runtime behavior
  • declaring code entrypoints
  • npm install metadata

Those belong in your plugin code and package.json.

Minimal example

{
  "id": "voice-call",
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {}
  }
}

Rich example

{
  "id": "openrouter",
  "name": "OpenRouter",
  "description": "OpenRouter provider plugin",
  "version": "1.0.0",
  "providers": ["openrouter"],
  "providerAuthEnvVars": {
    "openrouter": ["OPENROUTER_API_KEY"]
  },
  "providerAuthChoices": [
    {
      "provider": "openrouter",
      "method": "api-key",
      "choiceId": "openrouter-api-key",
      "choiceLabel": "OpenRouter API key",
      "groupId": "openrouter",
      "groupLabel": "OpenRouter",
      "optionKey": "openrouterApiKey",
      "cliFlag": "--openrouter-api-key",
      "cliOption": "--openrouter-api-key <key>",
      "cliDescription": "OpenRouter API key",
      "onboardingScopes": ["text-inference"]
    }
  ],
  "uiHints": {
    "apiKey": {
      "label": "API key",
      "placeholder": "sk-or-v1-...",
      "sensitive": true
    }
  },
  "configSchema": {
    "type": "object",
    "additionalProperties": false,
    "properties": {
      "apiKey": {
        "type": "string"
      }
    }
  }
}

Top-level field reference

Field Required Type What it means
id Yes string Canonical plugin id. This is the id used in plugins.entries.<id>.
configSchema Yes object Inline JSON Schema for this plugin's config.
enabledByDefault No true Marks a bundled plugin as enabled by default. Omit it, or set any non-true value, to leave the plugin disabled by default.
kind No "memory" | "context-engine" Declares an exclusive plugin kind used by plugins.slots.*.
channels No string[] Channel ids owned by this plugin. Used for discovery and config validation.
providers No string[] Provider ids owned by this plugin.
providerAuthEnvVars No Record<string, string[]> Cheap provider-auth env metadata that OpenClaw can inspect without loading plugin code.
providerAuthChoices No object[] Cheap auth-choice metadata for onboarding pickers, preferred-provider resolution, and simple CLI flag wiring.
skills No string[] Skill directories to load, relative to the plugin root.
name No string Human-readable plugin name.
description No string Short summary shown in plugin surfaces.
version No string Informational plugin version.
uiHints No Record<string, object> UI labels, placeholders, and sensitivity hints for config fields.

providerAuthChoices reference

Each providerAuthChoices entry describes one onboarding or auth choice. OpenClaw reads this before provider runtime loads.

Field Required Type What it means
provider Yes string Provider id this choice belongs to.
method Yes string Auth method id to dispatch to.
choiceId Yes string Stable auth-choice id used by onboarding and CLI flows.
choiceLabel No string User-facing label. If omitted, OpenClaw falls back to choiceId.
choiceHint No string Short helper text for the picker.
groupId No string Optional group id for grouping related choices.
groupLabel No string User-facing label for that group.
groupHint No string Short helper text for the group.
optionKey No string Internal option key for simple one-flag auth flows.
cliFlag No string CLI flag name, such as --openrouter-api-key.
cliOption No string Full CLI option shape, such as --openrouter-api-key <key>.
cliDescription No string Description used in CLI help.
onboardingScopes No Array<"text-inference" | "image-generation"> Which onboarding surfaces this choice should appear in. If omitted, it defaults to ["text-inference"].

uiHints reference

uiHints is a map from config field names to small rendering hints.

{
  "uiHints": {
    "apiKey": {
      "label": "API key",
      "help": "Used for OpenRouter requests",
      "placeholder": "sk-or-v1-...",
      "sensitive": true
    }
  }
}

Each field hint can include:

Field Type What it means
label string User-facing field label.
help string Short helper text.
tags string[] Optional UI tags.
advanced boolean Marks the field as advanced.
sensitive boolean Marks the field as secret or sensitive.
placeholder string Placeholder text for form inputs.

Manifest versus package.json

The two files serve different jobs:

File Use it for
openclaw.plugin.json Discovery, config validation, auth-choice metadata, and UI hints that must exist before plugin code runs
package.json npm metadata, dependency installation, and the openclaw block used for entrypoints and setup or catalog metadata

If you are unsure where a piece of metadata belongs, use this rule:

  • if OpenClaw must know it before loading plugin code, put it in openclaw.plugin.json
  • if it is about packaging, entry files, or npm install behavior, put it in package.json

JSON Schema requirements

  • Every plugin must ship a JSON Schema, even if it accepts no config.
  • An empty schema is acceptable (for example, { "type": "object", "additionalProperties": false }).
  • Schemas are validated at config read/write time, not at runtime.

Validation behavior

  • Unknown channels.* keys are errors, unless the channel id is declared by a plugin manifest.
  • plugins.entries.<id>, plugins.allow, plugins.deny, and plugins.slots.* must reference discoverable plugin ids. Unknown ids are errors.
  • If a plugin is installed but has a broken or missing manifest or schema, validation fails and Doctor reports the plugin error.
  • If plugin config exists but the plugin is disabled, the config is kept and a warning is surfaced in Doctor + logs.

See Configuration reference for the full plugins.* schema.

Notes

  • The manifest is required for native OpenClaw plugins, including local filesystem loads.
  • Runtime still loads the plugin module separately; the manifest is only for discovery + validation.
  • Only documented manifest fields are read by the manifest loader. Avoid adding custom top-level keys here.
  • providerAuthEnvVars is the cheap metadata path for auth probes, env-marker validation, and similar provider-auth surfaces that should not boot plugin runtime just to inspect env names.
  • providerAuthChoices is the cheap metadata path for auth-choice pickers, --auth-choice resolution, preferred-provider mapping, and simple onboarding CLI flag registration before provider runtime loads. For runtime wizard metadata that requires provider code, see Provider runtime hooks.
  • Exclusive plugin kinds are selected through plugins.slots.*.
    • kind: "memory" is selected by plugins.slots.memory.
    • kind: "context-engine" is selected by plugins.slots.contextEngine (default: built-in legacy).
  • channels, providers, and skills can be omitted when a plugin does not need them.
  • If your plugin depends on native modules, document the build steps and any package-manager allowlist requirements (for example, pnpm allow-build-scripts
    • pnpm rebuild <package>).