Skip to content
PricingReleases

plugin.json Manifest Reference

The plugin.json file is the only required file in a plugin. It declares what the plugin provides and how Recursive should load it.

{
"id": "my-plugin",
"name": "My Plugin",
"version": "0.1.0",
"description": "What this plugin does."
}

Unknown fields are ignored with a warning in the plugin’s health panel (typos like skilss get a did-you-mean suggestion); wrong-typed fields are dropped with a warning. Only a missing id prevents the plugin from loading. Validate anytime with the plugin_validate tool.

FieldTypeRequiredDescription
idstringYesUnique kebab-case plugin identifier.
namestringNoDisplay name (falls back to id).
versionstringNoSemver version, compared against the registry for update checks.
descriptionstringNoOne-line summary shown in the plugins UI and registry.
authorstring | objectNoAuthor attribution — a string or { name, url }.
homepagestringNoProject homepage or docs URL.
colorstringNoHex color for the icon badge.
iconstringNoIcon name from the Recursive icon set.
thumbnailstringNoPath to a thumbnail image within the plugin.
categorystringNoMarketplace category.
tagsstring[]NoMarketplace search tags.
appScopestringNoWhich app the plugin applies to: recursive, financial, or shared.
privatebooleanNoExcluded from registry publishing.
platformsstring[]NoOS allowlist (e.g. [“darwin”]); omit for all platforms.
min_recursive_versionstringNoMinimum Recursive version this plugin supports; enforced at install.

Each points to a directory or file (relative to the plugin root) that Recursive loads. A string can be a directory (ending in /) or a single file; an array mixes both. When the field is omitted, a conventional directory of the same name is picked up automatically.

FieldTypeRequiredDescription
toolsstring | string[]NoMCP tool handler modules (JS/TS).
routesstring | string[]NoHTTP route handler modules.
adaptersstring | string[]NoAgent CLI adapter modules (JS/TS).
skillsstring | string[]NoSkill directories containing SKILL.md subfolders.
rulesstring | string[]NoAgent rule markdown files.
workflowsstring | string[]NoWorkflow markdown files.
automationsstring | string[]NoAutomation definitions.
hooksstring | string[]NoServer lifecycle hook handler modules.
mcpstring | string[]NoExternal MCP server configuration (JSON).
themesstring | string[]NoTheme JSON files.
soundsstring | string[]NoSound pack audio files (mp3/wav/ogg/m4a/aac/aiff).
commsstring | string[]NoComms templates directory.
FieldTypeRequiredDescription
uiobjectNoUI extensions: views, panels, commands, chat renderers, components.
settingsobjectNoSettings schema and defaults rendered in the plugin settings page.
detectobjectNoProject auto-detection: file patterns that suggest enabling this plugin.
dataobjectNoData directory scopes the plugin persists into (global/workspace/project).
providesobjectNoStructured provider declarations (sync_provider, data_provider).
triggersobjectNoDeclares the plugin as an event trigger source: module (exports verify/normalize), a non-empty events[] of { type, label, filters }, optional setupSkill and requiredSettings.
lifecycleobjectNoServer lifecycle hook handlers keyed by event name.
client_lifecycleobjectNoClient (renderer) lifecycle hook handlers keyed by event name.
soundDefaultsRecord<string, string>NoSound packs: notification event → sound slug mapping.
dependenciesstring[]NoPlugin ids this plugin requires.
bundledOptInbooleanNoBundled copy is marketplace-only until explicitly installed.
corebooleanNoCore platform plugin — boot-synced, cannot be disabled.
npmobjectNonpm install behavior — set { "scripts": true } to allow lifecycle scripts (disclosed at install).
FieldTypeRequiredDescription
loginCommandstringNoCommand that (re)authenticates the plugin’s CLI.
setupCommandstringNoFirst-time configuration command.
diagnoseCommandstringNoHealth-check / repair command.
installCommandstringNoCommand that installs the CLI itself.
installUrlstringNoDocs or download URL for installing the CLI.
cliobjectNoHow to probe whether the CLI is installed (bin, versionArgs).
appobjectNoDesktop-app provider config (name, downloadUrl, healthUrl).
setupSequenceobject[]NoOrdered getting-started steps shown after install.
onboardingobjectNoDeclarative onboarding steps (fields, verify, links).

The ui field is an object that declares frontend components and behaviors.

Array of view definitions that add new pages to the dashboard.

{
"ui": {
"views": [
{
"id": "my-view",
"label": "My View",
"icon": "layers",
"route": "my-view",
"component": "./ui/MyView.svelte",
"detailPanel": "./ui/MyDetailPanel.svelte"
}
]
}
}
FieldTypeDescription
idstringUnique view identifier.
labelstringDisplay name in navigation.
iconstringIcon name.
routestringURL route segment (e.g., my-view/my-view).
componentstringPath to the main Svelte component.
detailPanelstringOptional path to a detail panel component.

Array of navigation entries added to the sidebar.

{
"ui": {
"nav": [
{
"route": "my-view",
"label": "My View",
"icon": "layers",
"shortcut": "Mod+5",
"order": 50,
"surface": "sidebar.nav.my-view"
}
]
}
}

Array of command palette entries.

{
"ui": {
"commands": [
{
"id": "nav-my-view",
"label": "Go to My View",
"icon": "layers",
"section": "Navigation",
"type": "navigate",
"route": "my-view",
"shortcut": "Mod+5",
"keywords": ["custom", "view"]
}
]
}
}

Panels added to the workspace detail area (alongside file viewer, preview, etc.).

Panels added to the task detail view.

Custom renderers for specific tool call results in the chat feed.

{
"ui": {
"chatRenderers": [
{
"kind": "goal_create",
"component": "./ui/GoalCreateRenderer.svelte"
}
]
}
}

Register custom entity types for mention resolution and search.

{
"ui": {
"entityTypes": [
{
"type": "goal",
"storeKey": "allGoals",
"nameKey": "title"
}
]
}
}

SSE event channels that the plugin’s store should listen to.

Frontend stores are discovered by convention, not declared: any ui/*-store.ts module in a bundled plugin is auto-registered, its load<Name>() export is called on mount, and SSE events matching the plugin id (or declared via ui.sseEvents) re-invoke it.

Map of named components that other parts of the UI can reference.

Plugin configuration with defaults and a schema for the settings UI.

{
"settings": {
"defaults": {
"api_key": "",
"enabled_features": ["basic"]
},
"schema": [
{
"key": "api_key",
"type": "string",
"label": "API Key",
"description": "Your service API key.",
"section": "Authentication"
},
{
"key": "enabled_features",
"type": "multi-select",
"label": "Features",
"options": ["basic", "advanced", "experimental"],
"section": "Features"
}
]
}
}

Auto-detection rules that enable the plugin when a project matches.

{
"detect": {
"files": ["package.json", "tsconfig.json"],
"strategy": "all"
}
}
FieldTypeDefaultDescription
filesstring[]File patterns to check in the project root.
strategy"any" | "all""any"Whether any file match suffices or all must be present.

Server-side lifecycle event handlers. Keys are event names, values define the handler.

{
"lifecycle": {
"session.complete": {
"handler": "./hooks/on-session-complete.ts",
"priority": 10,
"type": "action"
}
}
}

Client-side lifecycle event handlers. Same structure as lifecycle but handlers run in the browser.

{
"client_lifecycle": {
"session.complete": {
"handler": "./hooks/client-on-complete.ts",
"priority": 10
}
}
}

Declares the plugin as an event trigger source for event-mode automations. See Building a Trigger Plugin for the full contract.

{
"triggers": {
"module": "./triggers/index.js",
"setupSkill": "connecting-my-provider",
"requiredSettings": ["signing_secret"],
"events": [
{ "type": "issue.created", "label": "Issue created", "filters": ["project"] }
]
}
}
FieldRequiredDescription
moduleYesPath to the file exporting verify(rawBody, headers, connection) and normalize(payload, headers, connection). Without it the whole block is dropped (with a warning).
eventsYesNon-empty array of { type, label, description?, filters? }. type (non-empty string) is matched against automations’ event_type; label is shown in the automation editor. A zero-event source is skipped by the trigger catalog — the validator warns about it.
setupSkillNoSkill id that walks the user through connecting the provider. Should correspond to a skill this plugin ships — plugin_validate warns when skills/<name>/SKILL.md is missing.
requiredSettingsNoSettings keys (from settings.schema) that must be non-empty for the source to show as “Connected”. Defaults to every password-type setting.

These two fields solve different problems — don’t mix them up:

  • onboarding is declarative plugin setup: a subtitle plus steps of kind link (open an external console), field (save a settings value, optionally secret), and verify (confirm required credentials are present), rendered in the plugin’s settings page. Use it for integrations that need credentials — trigger sources, API-backed tools.
  • setupSequence is adapter/CLI onboarding only: ordered terminal-action steps (install / auth / setup / diagnose, falling back to installCommand / loginCommand / setupCommand / diagnoseCommand) shown after installing a provider CLI plugin. Use it when the plugin wraps a CLI that must be installed and authenticated.
{
"onboarding": {
"subtitle": "Connect your workspace so agents pick up events.",
"steps": [
{ "kind": "link", "title": "Create an app", "url": "https://example.com/apps", "actionLabel": "Open console" },
{ "kind": "field", "title": "Add your Signing Secret", "field": { "key": "signing_secret", "secret": true }, "actionLabel": "Save" },
{ "kind": "verify", "title": "Verify setup", "actionLabel": "Verify" }
]
}
}