Skip to content

Testing & Publishing

The fastest way to test a plugin during development:

  1. Place the plugin in the local directory

    Terminal window
    # Your plugin should be at:
    ~/.recursive/plugins/local/my-plugin/
  2. Enable it

    plugin_toggle({ id: "my-plugin", enabled: true })
  3. Test tools via chat

    Open the Recursive dashboard, start a workspace chat, and call your tools directly.

  4. Check the tool catalog

    tool_catalog()

    Verify your tools appear with the correct names, descriptions, and audience.

  5. Test with an agent session

    Create a session and verify agents can discover and use your tools correctly.

For reliable plugin development, write tests using Vitest:

tests/my-tool.test.ts
import { describe, it, expect, beforeAll } from 'vitest';
describe('widget_create tool', () => {
it('creates a widget with required fields', async () => {
const result = await callTool('widget_create', {
title: 'Test Widget',
});
expect(result.error).toBeUndefined();
expect(result.id).toBeDefined();
expect(result.title).toBe('Test Widget');
});
it('returns INVALID_INPUT for missing title', async () => {
const result = await callTool('widget_create', {});
expect(result.error).toBe(true);
expect(result.code).toBe('INVALID_INPUT');
expect(result.retryable).toBe(true);
});
});

Before publishing, verify:

  • All tools appear in tool_catalog() with correct metadata
  • Required parameters are validated and return INVALID_INPUT when missing
  • Not-found cases return NOT_FOUND with a helpful fix message
  • Success responses include a human-readable summary field
  • SSE events fire correctly and the dashboard updates in real time
  • Skills load correctly and include accurate file paths
  • Rules are injected into agent contexts when the plugin is enabled
  • Workflows execute end-to-end without stalling
  • UI components render correctly in both dark and light themes
  • Plugin disabling cleanly removes all tools, routes, and UI elements

The recommended way to share plugins:

  1. Create a GitHub repository for your plugin

    Terminal window
    cd ~/.recursive/plugins/local/my-plugin
    git init
    git add .
    git commit -m "Initial plugin release"
    gh repo create my-plugin --public --push
  2. Others install via the plugin manager

    plugin_install({ repo: "your-username/my-plugin" })

    This clones the repo to ~/.recursive/plugins/installed/my-plugin/.

  3. Updating

    plugin_update({ id: "my-plugin" })

    Pulls the latest changes from the repository.

Use semantic versioning in your plugin.json:

{
"version": "1.2.3"
}
  • Patch (1.2.x): Bug fixes, no API changes
  • Minor (1.x.0): New features, backward compatible
  • Major (x.0.0): Breaking changes to tool schemas or behavior

High-quality plugins follow these patterns:

  1. Every tool has validation — never trust input, always use ctx.V
  2. Structured errors — use error codes, not generic messages
  3. Human-readable summaries — every success response includes a summary
  4. Scoped naming — prefix tool names with your plugin ID to avoid collisions
  5. Minimal dependencies — plugins should be self-contained
  6. Documentation — include a README with usage examples
  7. Auto-detection — use detect so the plugin enables itself for matching projects