Plugin Anatomy
A Recursive plugin is a directory with a plugin.json manifest at the root. Everything else is optional — you include only the capabilities your plugin needs.
Directory structure
Section titled “Directory structure”Here’s a fully-featured plugin that provides every capability type:
Directorymy-plugin/
- plugin.json — manifest (required)
Directorytools/ — MCP tool handlers
- create-widget.ts
- list-widgets.ts
Directoryroutes/ — HTTP API endpoints
- widgets.ts
Directoryadapters/ — agent CLI adapters
- my-adapter.ts
Directoryskills/ — agent skill definitions
Directorybuilding-widgets/
- SKILL.md
Directoryrules/ — agent behavior rules
- widget-conventions.md
Directoryworkflows/ — pipeline definitions
- widget-pipeline.md
Directoryautomations/ — scheduled tasks
- daily-widget-check.md
Directoryhooks/ — lifecycle event handlers
- on-session-complete.ts
Directoryui/ — frontend components
- WidgetView.svelte
- widget-store.ts
Capability types
Section titled “Capability types”Each manifest key maps to a capability type. Here’s what each one does:
MCP tools that agents can call. Each file exports a schema and a handler.
Tools are the primary way agents interact with your plugin. They follow the Model Context Protocol and appear in the agent’s tool list.
{ "tools": "./tools/" }routes
Section titled “routes”Server-side HTTP endpoints mounted under /api/plugins/{pluginId}/. Useful for custom APIs that the dashboard UI or external services consume.
{ "routes": "./routes/" }adapters
Section titled “adapters”Agent execution adapters that wrap CLI tools (e.g., claude, cursor, codex). Each adapter defines how to spawn, communicate with, and manage an agent process.
{ "adapters": "./adapters/" }skills
Section titled “skills”Agent skill definitions — structured knowledge that agents load when performing specific tasks. Each skill is a directory with a SKILL.md file.
{ "skills": "./skills/" }Behavioral rules injected into agent contexts. Rules are markdown files that get included in agent system prompts.
{ "rules": "./rules/" }workflows
Section titled “workflows”Pipeline definitions that orchestrate multi-step agent work. Workflows define steps, gates, and retry logic.
{ "workflows": "./workflows/" }automations
Section titled “automations”Scheduled or triggered automation definitions.
{ "automations": "./automations/" }Lifecycle event handlers that run server-side when specific events occur (e.g., session complete, task status change).
{ "hooks": "./hooks/" }Frontend components and configuration that extend the Recursive dashboard. Includes Svelte components, stores, navigation items, commands, and more.
{ "ui": { "views": [...], "nav": [...], "commands": [...], "panels": [...], "store": "./ui/my-store.ts" }}Plugin metadata
Section titled “Plugin metadata”The manifest also contains metadata used in the dashboard and registry:
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier. Must be kebab-case. |
name | string | Display name shown in the UI. |
version | string | Semver version string. |
description | string | One-line description for the plugin list. |
author | string | object | Author name or { name, url } object. |
color | string | Hex color for the plugin icon badge. |
icon | string | Icon name from the Recursive icon set. |
thumbnail | string | Path to a thumbnail image. |
Auto-detection
Section titled “Auto-detection”Plugins can declare file patterns that trigger automatic enablement when a project matches:
{ "detect": { "files": ["Package.swift", "*.xcodeproj"], "strategy": "any" }}When Recursive opens a project containing any of those files, the plugin is automatically enabled. The strategy can be "any" (default) or "all".
Settings
Section titled “Settings”Plugins can declare configurable settings with defaults and a schema for the settings UI:
{ "settings": { "defaults": { "auto_greet": true, "greeting_style": "formal" }, "schema": [ { "key": "auto_greet", "type": "boolean", "label": "Auto-greet on session start", "section": "General" }, { "key": "greeting_style", "type": "select", "label": "Greeting style", "options": ["formal", "casual", "pirate"], "section": "General" } ] }}