Skip to main content

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, Claude bundle LSP 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
  • alias and auto-enable metadata that should resolve before plugin runtime loads
  • shorthand model-family ownership metadata that should auto-activate the plugin before runtime loads
  • static capability ownership snapshots used for bundled compat wiring and contract coverage
  • channel-specific config metadata that should merge into catalog and validation surfaces without loading 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"],
  "modelSupport": {
    "modelPrefixes": ["router-"]
  },
  "cliBackends": ["openrouter-cli"],
  "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

FieldRequiredTypeWhat it means
idYesstringCanonical plugin id. This is the id used in plugins.entries.<id>.
configSchemaYesobjectInline JSON Schema for this plugin’s config.
enabledByDefaultNotrueMarks a bundled plugin as enabled by default. Omit it, or set any non-true value, to leave the plugin disabled by default.
legacyPluginIdsNostring[]Legacy ids that normalize to this canonical plugin id.
autoEnableWhenConfiguredProvidersNostring[]Provider ids that should auto-enable this plugin when auth, config, or model refs mention them.
kindNo"memory" | "context-engine"Declares an exclusive plugin kind used by plugins.slots.*.
channelsNostring[]Channel ids owned by this plugin. Used for discovery and config validation.
providersNostring[]Provider ids owned by this plugin.
modelSupportNoobjectManifest-owned shorthand model-family metadata used to auto-load the plugin before runtime.
cliBackendsNostring[]CLI inference backend ids owned by this plugin. Used for startup auto-activation from explicit config refs.
providerAuthEnvVarsNoRecord<string, string[]>Cheap provider-auth env metadata that OpenClaw can inspect without loading plugin code.
providerAuthChoicesNoobject[]Cheap auth-choice metadata for onboarding pickers, preferred-provider resolution, and simple CLI flag wiring.
contractsNoobjectStatic bundled capability snapshot for speech, realtime transcription, realtime voice, media-understanding, image-generation, video-generation, web-fetch, web search, and tool ownership.
channelConfigsNoRecord<string, object>Manifest-owned channel config metadata merged into discovery and validation surfaces before runtime loads.
skillsNostring[]Skill directories to load, relative to the plugin root.
nameNostringHuman-readable plugin name.
descriptionNostringShort summary shown in plugin surfaces.
versionNostringInformational plugin version.
uiHintsNoRecord<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.
FieldRequiredTypeWhat it means
providerYesstringProvider id this choice belongs to.
methodYesstringAuth method id to dispatch to.
choiceIdYesstringStable auth-choice id used by onboarding and CLI flows.
choiceLabelNostringUser-facing label. If omitted, OpenClaw falls back to choiceId.
choiceHintNostringShort helper text for the picker.
assistantPriorityNonumberLower values sort earlier in assistant-driven interactive pickers.
assistantVisibilityNo"visible" | "manual-only"Hide the choice from assistant pickers while still allowing manual CLI selection.
deprecatedChoiceIdsNostring[]Legacy choice ids that should redirect users to this replacement choice.
groupIdNostringOptional group id for grouping related choices.
groupLabelNostringUser-facing label for that group.
groupHintNostringShort helper text for the group.
optionKeyNostringInternal option key for simple one-flag auth flows.
cliFlagNostringCLI flag name, such as --openrouter-api-key.
cliOptionNostringFull CLI option shape, such as --openrouter-api-key <key>.
cliDescriptionNostringDescription used in CLI help.
onboardingScopesNoArray<"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:
FieldTypeWhat it means
labelstringUser-facing field label.
helpstringShort helper text.
tagsstring[]Optional UI tags.
advancedbooleanMarks the field as advanced.
sensitivebooleanMarks the field as secret or sensitive.
placeholderstringPlaceholder text for form inputs.

contracts reference

Use contracts only for static capability ownership metadata that OpenClaw can read without importing the plugin runtime.
{
  "contracts": {
    "speechProviders": ["openai"],
    "realtimeTranscriptionProviders": ["openai"],
    "realtimeVoiceProviders": ["openai"],
    "mediaUnderstandingProviders": ["openai", "openai-codex"],
    "imageGenerationProviders": ["openai"],
    "videoGenerationProviders": ["qwen"],
    "webFetchProviders": ["firecrawl"],
    "webSearchProviders": ["gemini"],
    "tools": ["firecrawl_search", "firecrawl_scrape"]
  }
}
Each list is optional:
FieldTypeWhat it means
speechProvidersstring[]Speech provider ids this plugin owns.
realtimeTranscriptionProvidersstring[]Realtime-transcription provider ids this plugin owns.
realtimeVoiceProvidersstring[]Realtime-voice provider ids this plugin owns.
mediaUnderstandingProvidersstring[]Media-understanding provider ids this plugin owns.
imageGenerationProvidersstring[]Image-generation provider ids this plugin owns.
videoGenerationProvidersstring[]Video-generation provider ids this plugin owns.
webFetchProvidersstring[]Web-fetch provider ids this plugin owns.
webSearchProvidersstring[]Web-search provider ids this plugin owns.
toolsstring[]Agent tool names this plugin owns for bundled contract checks.

channelConfigs reference

Use channelConfigs when a channel plugin needs cheap config metadata before runtime loads.
{
  "channelConfigs": {
    "matrix": {
      "schema": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "homeserverUrl": { "type": "string" }
        }
      },
      "uiHints": {
        "homeserverUrl": {
          "label": "Homeserver URL",
          "placeholder": "https://matrix.example.com"
        }
      },
      "label": "Matrix",
      "description": "Matrix homeserver connection",
      "preferOver": ["matrix-legacy"]
    }
  }
}
Each channel entry can include:
FieldTypeWhat it means
schemaobjectJSON Schema for channels.<id>. Required for each declared channel config entry.
uiHintsRecord<string, object>Optional UI labels/placeholders/sensitive hints for that channel config section.
labelstringChannel label merged into picker and inspect surfaces when runtime metadata is not ready.
descriptionstringShort channel description for inspect and catalog surfaces.
preferOverstring[]Legacy or lower-priority plugin ids this channel should outrank in selection surfaces.

modelSupport reference

Use modelSupport when OpenClaw should infer your provider plugin from shorthand model ids like gpt-5.4 or claude-sonnet-4.6 before plugin runtime loads.
{
  "modelSupport": {
    "modelPrefixes": ["gpt-", "o1", "o3", "o4"],
    "modelPatterns": ["^computer-use-preview"]
  }
}
OpenClaw applies this precedence:
  • explicit provider/model refs use the owning providers manifest metadata
  • modelPatterns beat modelPrefixes
  • if one non-bundled plugin and one bundled plugin both match, the non-bundled plugin wins
  • remaining ambiguity is ignored until the user or config specifies a provider
Fields:
FieldTypeWhat it means
modelPrefixesstring[]Prefixes matched with startsWith against shorthand model ids.
modelPatternsstring[]Regex sources matched against shorthand model ids after profile suffix removal.
Legacy top-level capability keys are deprecated. Use openclaw doctor --fix to move speechProviders, realtimeTranscriptionProviders, realtimeVoiceProviders, mediaUnderstandingProviders, imageGenerationProviders, videoGenerationProviders, webFetchProviders, and webSearchProviders under contracts; normal manifest loading no longer treats those top-level fields as capability ownership.

Manifest versus package.json

The two files serve different jobs:
FileUse it for
openclaw.plugin.jsonDiscovery, config validation, auth-choice metadata, and UI hints that must exist before plugin code runs
package.jsonnpm metadata, dependency installation, and the openclaw block used for entrypoints, install gating, 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

package.json fields that affect discovery

Some pre-runtime plugin metadata intentionally lives in package.json under the openclaw block instead of openclaw.plugin.json. Important examples:
FieldWhat it means
openclaw.extensionsDeclares native plugin entrypoints.
openclaw.setupEntryLightweight setup-only entrypoint used during onboarding and deferred channel startup.
openclaw.channelCheap channel catalog metadata like labels, docs paths, aliases, and selection copy.
openclaw.install.npmSpec / openclaw.install.localPathInstall/update hints for bundled and externally published plugins.
openclaw.install.defaultChoicePreferred install path when multiple install sources are available.
openclaw.install.minHostVersionMinimum supported OpenClaw host version, using a semver floor like >=2026.3.22.
openclaw.install.allowInvalidConfigRecoveryAllows a narrow bundled-plugin reinstall recovery path when config is invalid.
openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListenLets setup-only channel surfaces load before the full channel plugin during startup.
openclaw.install.minHostVersion is enforced during install and manifest registry loading. Invalid values are rejected; newer-but-valid values skip the plugin on older hosts. openclaw.install.allowInvalidConfigRecovery is intentionally narrow. It does not make arbitrary broken configs installable. Today it only allows install flows to recover from specific stale bundled-plugin upgrade failures, such as a missing bundled plugin path or a stale channels.<id> entry for that same bundled plugin. Unrelated config errors still block install and send operators to openclaw doctor --fix.

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.
  • Native manifests are parsed with JSON5, so comments, trailing commas, and unquoted keys are accepted as long as the final value is still an object.
  • 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, cliBackends, 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>).