This guide provides comprehensive instructions for creating new plugins for the Beyond Better (BB) ecosystem. Each plugin can contain one or more tools and/or datasources, packaged in a structured .bbplugin directory.
BB plugins use a structured directory format that enables:
- Easy distribution and installation
- Multiple tools and datasources in a single package
- Clear metadata and versioning
- OS-level file association for double-click installation
Note: The standalone .tool directory structure is deprecated but still supported. All new development should use the .bbplugin structure.
your-plugin.bbplugin/
├── manifest.json # Required: Plugin metadata
├── your-tool.tool/ # Tool directory
│ ├── tool.ts # Tool implementation
│ ├── info.json # Tool metadata
│ ├── formatter.browser.tsx # Browser formatting
│ ├── formatter.console.ts # Console formatting
│ └── tool.test.ts # Tool tests
└── another-tool.tool/ # Additional tools (optional)
├── tool.ts
├── info.json
├── formatter.browser.tsx
├── formatter.console.ts
└── tool.test.ts
advanced-plugin.bbplugin/
├── manifest.json # Required: Plugin metadata
├── search-tool.tool/ # Tool component
│ ├── tool.ts
│ ├── info.json
│ └── ...
└── api-datasource.datasource/ # Datasource component (future support)
├── datasource.ts
├── info.json
└── ...
-
Choose a Reference Plugin
- Select an existing plugin similar to your planned functionality
- Use it as a template throughout development
-
Gather Information
// Plugin Planning Template { pluginName: string; // Plugin package name version: string; // Semantic version description: string; // Plugin purpose author: string; // Creator name license: string; // License type tools: { toolName: string; // Tool name description: string; // Tool purpose inputSchema: JSONSchema4; // Parameters expectedOutput: string; // Return value requiredActions: string[]; // Functionality errorScenarios: string[]; // Error cases }[]; datasources?: {...}[]; // Future datasource components }
-
Create Plugin Package Structure
mkdir -p your-plugin.bbplugin/your-tool.tool
-
Create Plugin Manifest (
manifest.json){ "name": "your-plugin", "version": "1.0.0", "author": "Your Name", "description": "A collection of useful tools for...", "license": "MIT", "tools": ["your-tool.tool", "another-tool.tool"], "datasources": [], "bbVersion": ">=0.9.0" }See Plugin Manifest Schema for complete specification.
-
Create Tool Metadata (
your-tool.tool/info.json){ "name": "your_tool", "description": "Detailed description of your tool...", "version": "1.0.0", "author": "Your Name", "license": "MIT", "examples": [ { "description": "Example usage description", "input": { "param1": "value1" } } ] } -
Implement Core Components
import LLMTool, { type IConversationInteraction, type IProjectEditor, type LLMAnswerToolUse, type LLMToolInputSchema, type LLMToolLogEntryFormattedResult, type LLMToolRunResult, } from '@beyondbetter/tools'; class YourTool extends LLMTool { get inputSchema() { return { type: 'object', properties: { // Define parameters }, required: [], }; } async runTool( interaction: IConversationInteraction, toolUse: LLMAnswerToolUse, projectEditor: IProjectEditor, ): Promise<LLMToolRunResult> { // Implement tool functionality } formatLogEntryToolUse(toolInput, format) { return format === 'console' ? formatLogEntryToolUseConsole(toolInput) : formatLogEntryToolUseBrowser(toolInput); } formatLogEntryToolResult(resultContent, format) { return format === 'console' ? formatLogEntryToolResultConsole(resultContent) : formatLogEntryToolResultBrowser(resultContent); } }
-
Implement Formatters
Browser (formatter.browser.tsx):
/** @jsxImportSource preact */ import LLMTool, { type LLMToolInputSchema, type LLMToolLogEntryFormattedResult, } from '@beyondbetter/tools'; export function formatLogEntryToolUse( toolInput: LLMToolInputSchema, ): LLMToolLogEntryFormattedResult { return { title: LLMTool.TOOL_TAGS_BROWSER.content.title('Tool Use', 'Your Tool'), subtitle: LLMTool.TOOL_TAGS_BROWSER.content.subtitle('Processing...'), content: LLMTool.TOOL_TAGS_BROWSER.base.container( <> {LLMTool.TOOL_TAGS_BROWSER.base.label('Parameters')} {LLMTool.TOOL_TAGS_BROWSER.base.list([ // Format parameters ])} </>, ), preview: 'Tool execution preview', }; }
Console (formatter.console.ts):
import { stripIndents } from 'common-tags'; import LLMTool, { type LLMToolInputSchema, type LLMToolLogEntryFormattedResult, } from '@beyondbetter/tools'; export function formatLogEntryToolUse( toolInput: LLMToolInputSchema, ): LLMToolLogEntryFormattedResult { return { title: LLMTool.TOOL_STYLES_CONSOLE.content.title('Tool Use', 'Your Tool'), subtitle: LLMTool.TOOL_STYLES_CONSOLE.content.subtitle('Processing...'), content: stripIndents` ${LLMTool.TOOL_STYLES_CONSOLE.base.label('Parameters')} ${ LLMTool.TOOL_STYLES_CONSOLE.base.list([ // Format parameters ]).join('\n') }`, preview: 'Tool execution preview', }; }
The manifest.json file is required at the root of every .bbplugin package. It provides metadata about the plugin and lists all included components.
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "BB Plugin Manifest",
"type": "object",
"required": ["name", "version", "description", "tools"],
"properties": {
"name": {
"type": "string",
"description": "Plugin package name (kebab-case recommended)",
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
"examples": ["my-plugin", "search-tools"]
},
"version": {
"type": "string",
"description": "Semantic version number",
"pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$",
"examples": ["1.0.0", "2.1.0-beta.1"]
},
"author": {
"type": "string",
"description": "Plugin creator name or organization",
"examples": ["Your Name", "Your Organization"]
},
"description": {
"type": "string",
"description": "Brief description of plugin functionality",
"minLength": 10,
"maxLength": 500
},
"license": {
"type": "string",
"description": "License identifier (SPDX format recommended)",
"examples": ["MIT", "Apache-2.0", "GPL-3.0"]
},
"tools": {
"type": "array",
"description": "List of tool directories included in plugin",
"items": {
"type": "string",
"pattern": "^[a-z0-9_-]+\\.tool$",
"examples": ["search-tool.tool", "format-tool.tool"]
},
"minItems": 0
},
"datasources": {
"type": "array",
"description": "List of datasource directories included in plugin",
"items": {
"type": "string",
"pattern": "^[a-z0-9_-]+\\.datasource$",
"examples": ["api-datasource.datasource"]
},
"minItems": 0,
"default": []
},
"bbVersion": {
"type": "string",
"description": "Minimum BB version required (semver range)",
"examples": [">=0.9.0", "^1.0.0"],
"default": ">=0.9.0"
},
"homepage": {
"type": "string",
"format": "uri",
"description": "Plugin homepage or repository URL"
},
"repository": {
"type": "object",
"description": "Repository information",
"properties": {
"type": {
"type": "string",
"enum": ["git", "svn", "hg"]
},
"url": {
"type": "string",
"format": "uri"
}
}
},
"keywords": {
"type": "array",
"description": "Keywords for plugin discovery",
"items": {
"type": "string"
}
}
}
}Simple Plugin with One Tool:
{
"name": "search-plugin",
"version": "1.0.0",
"author": "John Doe",
"description": "Advanced search capabilities for BB",
"license": "MIT",
"tools": ["search-tool.tool"],
"datasources": [],
"bbVersion": ">=0.9.0"
}Multi-Tool Plugin:
{
"name": "dev-tools",
"version": "2.1.0",
"author": "Dev Team",
"description": "Collection of development utilities",
"license": "Apache-2.0",
"tools": [
"search-tool.tool",
"format-tool.tool",
"lint-tool.tool"
],
"datasources": [],
"bbVersion": ">=1.0.0",
"homepage": "https://github.com/user/dev-tools",
"keywords": ["development", "utilities", "formatting"]
}Plugin with Tools and Datasources:
{
"name": "api-integration",
"version": "1.5.0",
"author": "API Corp",
"description": "Tools and datasources for API integration",
"license": "MIT",
"tools": ["api-query.tool", "api-test.tool"],
"datasources": ["rest-api.datasource"],
"bbVersion": ">=0.9.0",
"repository": {
"type": "git",
"url": "https://github.com/apicorp/bb-api-integration"
}
}- Plugin Name: Must be kebab-case, lowercase alphanumeric with hyphens
- Version: Must follow semantic versioning (major.minor.patch)
- Component Lists: All listed tools/datasources must exist as directories
- Directory Names: Must match the pattern in manifest exactly
- BB Version: Should specify minimum compatible version
- Always validate paths with
isPathWithinProject - Use
ProjectEditormethods when possible - Handle file operations carefully
- Consider impact on project structure
- Implement proper error handling
- Consider performance implications
- Handle rate limiting where applicable
- Validate and sanitize inputs
- Implement proper timeouts
- Sanitize inputs carefully
- Handle errors gracefully
- Consider security implications
-
Use structured error types
if (!isPathWithinProject(path)) { throw new Error(`Access denied: ${path} is outside project`); }
-
Provide clear error messages
-
Handle both expected and unexpected errors
-
Clean up resources in error cases
See TESTING.md for detailed testing guidelines. Key points:
- Create comprehensive tests
- Test both success and failure cases
- Test formatters for both browser and console
- Follow existing test patterns
- Clean up test resources properly
-
Include JSDoc comments
/** * Performs specific tool functionality * @param {string} input - Description of input * @returns {Promise<r>} Description of result * @throws {Error} Description of error cases */
-
Update tool documentation
-
Include usage examples
-
Document error scenarios
-
Double-Click Installation (macOS/Windows)
- Users can double-click
.bbpluginfiles - OS file association opens BB DUI
- Installation dialog shows plugin details
- Plugin copied to configured directory
- Requires BB API restart to load
- Users can double-click
-
Manual Installation
- Copy
.bbplugindirectory to plugin directory - Default locations:
- macOS:
~/.config/bb/plugins - Windows:
%APPDATA%/bb/plugins - Linux:
~/.config/bb/plugins
- macOS:
- Custom locations via
config.yaml:api: userPluginDirectories: - ./my-plugins - /absolute/path/to/plugins
- Copy
-
Plugin Discovery
- BB scans plugin directories on startup
- Loads tools from:
plugins/*.bbplugin/*.tool - Also supports legacy:
plugins/*.tool(deprecated) - Tools registered with LLM for use
- Plugin versions follow semantic versioning
- BB detects version conflicts during installation
- Warns on downgrades or duplicate versions
- Users can choose to upgrade/replace existing plugins
-
Prepare Package
- Ensure all files are present
- Validate manifest.json
- Test all tools locally
- Include README.md with usage instructions
-
Distribution Options
- Direct file sharing (
.bbplugindirectory) - Archive formats (
.zip,.tar.gz) - Version control repositories
- Future: BB plugin marketplace
- Direct file sharing (
-
Best Practices
- Include comprehensive documentation
- Provide usage examples
- List dependencies and requirements
- Specify BB version compatibility
- Include license information
-
Plugin Organization
- Group related tools in a single plugin
- Use clear, descriptive plugin names
- Keep manifest.json accurate and complete
- Version plugins semantically
- Document all included components
-
Code Organization
- Keep related code together within each tool
- Use clear file structure (tool.ts, info.json, formatters)
- Follow naming conventions (kebab-case for directories)
- Maintain consistent formatting across all tools
- Separate tool-specific types into types.ts
-
Implementation
- Follow existing patterns from example tools
- Keep methods focused and single-purpose
- Handle errors gracefully with clear messages
- Clean up resources properly
- Consider performance implications
-
Testing
- Write comprehensive tests for each tool
- Test edge cases and boundary conditions
- Test error scenarios thoroughly
- Maintain test consistency across plugin
- Test installation and discovery process
-
Documentation
- Keep manifest.json and info.json up to date
- Include examples in tool info.json files
- Document errors and edge cases
- Explain complex logic with comments
- Provide plugin-level README with overview
-
Formatting
- Use TOOL_TAGS_BROWSER for browser output
- Use TOOL_STYLES_CONSOLE for console output
- Use JSX fragments (<>...</>) for browser components
- Use stripIndents for console formatting
- Provide clear labels and structure
- Handle success and error states consistently
-
Compatibility
- Specify minimum BB version in manifest
- Test with target BB versions
- Avoid BB internal APIs unless necessary
- Handle version differences gracefully
- Document any version-specific features
Note: The standalone .tool directory structure is deprecated. While BB still supports it for backward compatibility, all new development should use the .bbplugin structure.
plugins/
├── search-tool.tool/ # Standalone tool (deprecated)
│ ├── tool.ts
│ ├── info.json
│ └── ...
└── format-tool.tool/ # Another standalone tool (deprecated)
├── tool.ts
└── ...
plugins/
├── search-plugin.bbplugin/ # Plugin package (current)
│ ├── manifest.json
│ ├── search-tool.tool/
│ │ ├── tool.ts
│ │ └── ...
│ └── format-tool.tool/
│ ├── tool.ts
│ └── ...
└── other-plugin.bbplugin/ # Another plugin
├── manifest.json
└── ...
Why Migrate?
- Improved organization and discoverability
- Support for multiple components (tools + datasources)
- Better version management
- Enable double-click installation
- Prepare for plugin marketplace
- Future: digital signatures and security
Migration Steps:
- Create new
.bbplugindirectory - Move
.tooldirectories into plugin directory - Create
manifest.jsonwith metadata - Test plugin discovery and loading
- Update distribution method
Backward Compatibility:
- BB continues to discover standalone
.tooldirectories - No immediate migration required
- Consider migration for new features and better UX
- README.md - Package overview
- TESTING.md - Testing guidelines
- tools.md - Tool reference
- Plugin Installation Guide - BB plugin installation documentation