| title | BB Plugin Framework Guidelines |
|---|---|
| project | bb-tools |
| version | 1.1.0 |
| created | 2025-11-02 |
| updated | 2025-11-04 |
| purpose | Guidelines for LLM collaboration on bb-tools framework development |
| note | Project may be renamed to bb-plugins in future |
bb-tools (@beyondbetter/tools) is the core framework/library for building plugins that work with the Beyond Better (BB) AI assistant. This project provides base classes, interfaces, types, and utilities needed to create properly structured BB plugins containing tools and datasources.
IMPORTANT: These guidelines are for working on the bb-tools framework itself, NOT for users/consumers of the framework. The audience is the LLM assisting with framework development, maintenance, and enhancement.
NOTE: This project may be renamed to bb-plugins in the future to better reflect its purpose.
- Provide robust base classes (LLMTool) for tool creation
- Define standardized plugin structure (.bbplugin format with manifest.json)
- Support both tool and datasource components within plugins
- Define standardized interfaces (IProjectEditor, IConversationInteraction)
- Supply formatting utilities for browser (JSX/Preact) and console (ANSI)
- Maintain comprehensive type definitions
- Demonstrate best practices through working examples
- Enable publishing to JSR for Deno ecosystem
- Clean, maintainable TypeScript code following Deno standards
- Clear documentation for framework consumers
- Working example tools that demonstrate framework capabilities
- Type-safe interfaces and implementations
- Consistent code organization and structure
In Scope:
- Framework core classes and utilities
- Plugin structure definition (.bbplugin format)
- Plugin manifest schema and validation
- Type definitions and interfaces
- Example plugins demonstrating framework usage
- Documentation for plugin creators
- JSR publishing configuration
Out of Scope:
- Individual plugins created by framework consumers
- Beyond Better (BB) main application code
- Plugin runtime environment (handled by BB)
- Plugin distribution marketplace (future BB feature)
Primary Data Source: bb-tools (filesystem)
- Type: Filesystem
- Capabilities: Read, Write, Delete
- Root:
$WORKING_DIR/bb-tools - Access: Full read/write access to all files and directories
mod.ts # Main module exports
llm_tool.ts # LLMTool base class implementation
llm_tool_tags.tsx # Browser/console formatting utilities (JSX)
types.ts # Core type definitions
project_editor.ts # IProjectEditor interface and types
conversation.ts # IConversationInteraction interface
message.ts # Message formatting utilities
deno.json # Deno project configuration & JSR publish settings
import_map.json # Import mappings
deno.lock # Dependency lock file
.gitignore # Git ignore patterns
CREATING_TOOLS.md # Guide for plugin creators (consumers)
TESTING.md # Testing guidelines for plugins
tools.md # Comprehensive framework reference
plugin-manifest-schema.json # JSON schema for manifest.json
mod.ts # Examples module exports
search-plugin.bbplugin/
├── manifest.json # Plugin metadata
└── search-project.tool/
├── tool.ts # Tool implementation
├── formatter.browser.tsx # Browser formatting
├── formatter.console.ts # Console formatting
├── info.json # Tool metadata
├── types.ts # Tool-specific types
├── tool.test.ts # Tool tests
└── README.md # Tool documentation
browser-plugin.bbplugin/
├── manifest.json
└── open-in-browser.tool/
└── (same structure)
# Legacy (deprecated, for backward compatibility):
search_project.tool/
open_in_browser.tool/
README.md # Project README
GUIDELINES.md # Project Guidelines (this file)
LICENSE # MIT License
.github/workflows/ # GitHub Actions (JSR publishing)
-
Framework Core Modifications
- Read existing implementation first
- Consider backward compatibility
- Update type definitions if interfaces change
- Test with example tools after changes
-
Example Plugin Development
- Create .bbplugin directory with manifest.json
- Follow established plugin and tool structure
- Include all standard files (manifest.json, tool.ts, formatters, tests, README, info.json)
- Use framework utilities consistently
- Demonstrate specific framework features
- Show both single-tool and multi-tool plugin patterns
-
Documentation Updates
- Keep in sync with code changes
- Update examples when APIs change
- Maintain consistency across all docs
- Reference actual code examples
-
Configuration Changes
- Verify JSR publish settings in deno.json
- Update version numbers appropriately
- Maintain import map consistency
- Language: TypeScript (Deno flavor)
- Runtime: Deno (required dependency)
- Style: Standard Deno TypeScript conventions
- Module System: ES modules with explicit extensions
-
File Naming
- Use lowercase with underscores:
llm_tool.ts - Browser formatters:
formatter.browser.tsx(JSX/Preact) - Console formatters:
formatter.console.ts - Tests:
tool.test.tsor*.test.ts - Types:
types.ts(when tool-specific types needed)
- Use lowercase with underscores:
-
Module Exports
- Export public API through
mod.ts - Use explicit exports, avoid wildcard re-exports when clarity is needed
- Maintain clean separation of concerns
- Export public API through
-
Type Safety
- Strong typing throughout
- Explicit return types for public methods
- Proper interface implementation
- No
anytypes without justification
Framework Core:
- No tests currently exist for the framework itself
- Framework reliability demonstrated through example tools
Example Tools:
- Each example tool MUST include comprehensive tests
- Test files:
tool.test.ts - Test coverage should include:
- Basic functionality
- Input validation
- Browser formatter output
- Console formatter output
- Error handling
- Use Deno's built-in test framework
- Mock interfaces (IProjectEditor, IConversationInteraction) as needed
- Published to JSR (JavaScript Registry)
- Version management in
deno.json - GitHub Actions workflow handles publishing
- Follow semantic versioning
When creating example plugins or documenting plugin patterns:
plugin-name.bbplugin/
├── manifest.json # Required: Plugin metadata
├── tool-name.tool/
│ ├── tool.ts # Tool implementation (extends LLMTool)
│ ├── formatter.browser.tsx # Browser UI formatting (JSX/Preact)
│ ├── formatter.console.ts # Console output formatting (ANSI)
│ ├── info.json # Tool metadata and examples
│ ├── types.ts # Tool-specific types (if needed)
│ ├── tool.test.ts # Comprehensive tests
│ └── README.md # Tool documentation
└── another-tool.tool/ # Additional tools (optional)
└── (same structure)
tool_name.tool/ # Standalone tool (deprecated)
├── tool.ts
├── formatter.browser.tsx
├── formatter.console.ts
├── info.json
├── types.ts
├── tool.test.ts
└── README.md
Note: While BB still supports standalone .tool directories for backward compatibility, all new development should use the .bbplugin structure.
manifest.json at plugin root:
- name: Plugin package name (kebab-case)
- version: Semantic version (major.minor.patch)
- author: Creator name or organization
- description: Brief plugin description
- license: License identifier (e.g., MIT, Apache-2.0)
- tools: Array of tool directory names (e.g., ["search-tool.tool"])
- datasources: Array of datasource directory names (optional, future support)
- bbVersion: Minimum BB version (e.g., ">=0.9.0")
See Plugin Manifest Schema for complete specification.
-
Tool Class (within each .tool directory)
- Extend
LLMToolbase class - Implement
inputSchemagetter (JSON Schema) - Implement
runToolmethod - Implement
formatLogEntryToolUseandformatLogEntryToolResult - Set tool features using
LLMToolFeaturesinterface:mutates: boolean - Tool modifies resourcesstateful: boolean - Tool maintains state between callsasync: boolean - Tool runs asynchronouslyidempotent: boolean - Multiple runs produce same resultresourceIntensive: boolean - Tool needs significant resourcesrequiresNetwork: boolean - Tool needs internet access
- Extend
-
Browser Formatter (
formatter.browser.tsx)- Use Preact JSX syntax
- Import:
/** @jsxImportSource preact */ - Use
LLMTool.TOOL_TAGS_BROWSERutilities - Return
LLMToolLogEntryFormattedResultwith title, subtitle, content, preview
-
Console Formatter (
formatter.console.ts)- Use ANSI color codes via framework utilities
- Use
LLMTool.TOOL_STYLES_CONSOLEutilities - Use
common-tagsstripIndents for clean formatting - Return
LLMToolLogEntryFormattedResultwith title, subtitle, content, preview
-
Info File (
info.json)- Include: name, description, version, author, license
- Provide usage examples with sample inputs
- Document expected behavior
-
Tests (
tool.test.ts)- Test tool execution
- Validate input schema
- Test both formatters
- Cover error scenarios
When creating or working with tools, understand these common patterns:
1. File System Tools
- Tools that interact with project files
- MUST validate paths with
isPathWithinProjectutility - Should use
ProjectEditormethods for file operations - Need careful error handling for file operations
- Consider impact on project structure
Example pattern:
if (!isPathWithinProject(projectEditor.projectRoot, filePath)) {
throw new Error(`Access denied: ${filePath} is outside project`);
}2. Data Processing Tools
- Tools that process or analyze data
- Handle data validation early
- Consider performance implications for large datasets
- Implement proper error handling
- Support both sync and async operations
3. Network Tools
- Tools that interact with external resources
- Set
requiresNetwork: truein features - Handle network errors gracefully
- Implement timeouts
- Consider rate limiting
- Validate external resources
Tools return LLMToolRunResult with these components:
interface LLMToolRunResult {
toolResults: LLMToolRunResultContent; // Main results
toolResponse: LLMToolRunToolResponse; // Response message
bbResponse: LLMToolRunBbResponse; // BB-specific data
finalizeCallback?: (messageId: string) => void; // Optional cleanup
}When planning a new tool (for documentation or discussion), use this template:
{
toolName: string; // Descriptive name
description: string; // Brief purpose
inputSchema: JSONSchema4; // Parameter definitions
expectedOutput: string; // What tool returns
requiredActions: string[]; // Main functionality
errorScenarios: string[]; // Error handling cases
}When working with framework code, understand these key utilities:
1. TOOL_TAGS_BROWSER (JSX formatting for browser UI)
Base Components:
container: Wraps content in styled containerlabel: Displays styled label textlist: Creates styled list of itemslistItem: Individual list item stylingtext: Basic text styling
Content Components:
title: Tool title with optional categorysubtitle: Secondary title or descriptionstatus: Status indicators (completed, error, etc.)error: Error message stylingsuccess: Success message stylingfilename: File path stylingurl: URL stylingcode: Code snippet stylingdate: Date formattingsize: File size formattingboolean: Boolean value formattingregex: Regular expression formatting
2. TOOL_STYLES_CONSOLE (ANSI formatting for console output)
Base Components:
label: Styled text labelslistItem: Indented list items with bulletstext: Basic text styling
Content Components:
title: Tool title with optional categorysubtitle: Secondary title or descriptionstatus: Status indicators with colorserror: Error message styling (red)success: Success message styling (green)filename: File path stylingurl: URL stylingcode: Code snippet stylingdate: Date formattingsize: File size formattingboolean: Boolean value formattingregex: Regular expression formatting
3. Core Interfaces
IProjectEditor: File operations, project context, path validationIConversationInteraction: Conversation management, file handlingLLMToolInputSchema: JSON Schema for input validationLLMToolRunResult: Standardized tool output structureLLMToolFeatures: Tool capability declarations
- No specific security or privacy concerns for this project
- Framework is for tool creation, not for handling sensitive data
- Tools created with framework may have their own security requirements
- No approval required for changes
- Human user (cng) is sole maintainer
- Implement requested changes directly
- Suggest improvements proactively
- All files are modifiable (no read-only restrictions)
- Always review current content before modifications
- Consider backward compatibility for framework changes
- Update related files when making changes (e.g., types + implementation)
When suggesting or implementing changes that affect the public API:
- Clearly identify the breaking change
- Explain impact on existing tools
- Suggest migration path if needed
- Consider version bump requirements
Ask the human user when:
- Requirements are unclear or ambiguous
- Multiple valid approaches exist with different tradeoffs
- Breaking changes would affect framework consumers
- Significant architectural decisions are needed
- Uncertainty about project direction or priorities
Proceed autonomously when:
- Implementing specific, clear requests
- Fixing obvious bugs or typos
- Improving code clarity or documentation
- Following established patterns
- Making non-breaking enhancements
Always suggest when you identify:
- Better/easier solutions the human may have missed
- Performance improvements
- Code clarity enhancements
- Consistency improvements across the codebase
- Potential issues or edge cases
- Opportunities to reduce duplication
Suggestion format:
- Acknowledge the request
- Present the suggested alternative
- Explain the benefits
- Ask for preference if uncertain
Batching vs Incremental:
- Use whichever approach makes sense for the task
- Batch changes when: Multiple related files need updates, refactoring across the codebase, consistent pattern application
- Incremental changes when: Iterating on design, testing changes step-by-step, complex modifications with checkpoints
- Discuss approach if uncertain
Change Process:
- Load and review current file content
- Show planned changes in thinking
- Implement complete, working changes
- Update related files if needed (types, docs, examples)
- Suggest testing approach
When reviewing or modifying framework code:
- Consider how tool creators will use this API
- Think about edge cases and error handling
- Maintain consistency with existing patterns
- Prioritize clarity over cleverness
- Document complex logic
- Consider performance for common operations
- Identify scope: Core class, interface, utility, or type
- Check existing patterns: Follow established conventions
- Update implementation: Add the feature
- Update types: Ensure type safety
- Update documentation: Reflect new capability
- Consider examples: Should example tools demonstrate this?
- Test with examples: Verify examples still work
- Create plugin directory:
examples/plugin-name.bbplugin/ - Create manifest.json: Plugin metadata with name, version, author, description, tools list
- Create tool directory:
examples/plugin-name.bbplugin/tool-name.tool/ - Implement tool.ts: Extend LLMTool, implement required methods
- Create formatters: Both browser.tsx and console.ts
- Add info.json: Tool metadata and examples
- Write tests: Comprehensive coverage for each tool
- Document in README: Plugin overview and tool usage
- Export from examples/mod.ts: Make available to framework users
- Identify affected docs: README, docs/*, example READMEs
- Update code examples: Ensure accuracy
- Verify consistency: Cross-reference related documentation
- Check completeness: All new features documented?
- Update version: If significant doc changes
- Plan the refactor: Identify scope and goals
- Check example usage: How do examples use current API?
- Make changes: Implement refactoring
- Update examples: Ensure examples still work
- Update types: Reflect any interface changes
- Update docs: Document new patterns
- Verify exports: Check mod.ts exports
The manifest.json schema is defined in docs/plugin-manifest-schema.json. Key requirements:
Required Fields:
name: Kebab-case plugin identifierversion: Semantic version stringdescription: Plugin description (10-500 chars)tools: Array of tool directory names
Optional Fields:
author: Creator name/organizationlicense: License identifier (SPDX format)datasources: Array of datasource directory namesbbVersion: Minimum BB version (semver range)homepage: Plugin homepage URLrepository: Repository information objectkeywords: Array of discovery keywords
Validation:
- All listed tools must exist as directories
- Directory names must match exactly (case-sensitive)
- Version must follow semver format
- Plugin name must be valid kebab-case
Core Concepts:
- Plugin Package: .bbplugin directory containing manifest and components
- Plugin Manifest: manifest.json with metadata and component lists
- LLMTool: Base class providing common functionality
- Tool Components: Individual .tool directories within plugin
- Datasource Components: Individual .datasource directories (future support)
- IProjectEditor: Interface for file/project operations (consumed by tools)
- IConversationInteraction: Interface for conversation context (consumed by tools)
- Formatters: Dual formatting for browser UI and console output
- Tool Metadata: info.json provides tool information to BB
Plugin Lifecycle:
- Plugin discovered in configured directories
- Manifest validated by BB
- Tools registered with BB from plugin
- LLM decides to use tool based on capabilities
- BB validates input against
inputSchema - Tool's
runToolmethod executes - Results formatted for display (browser or console)
- Results returned to LLM
When modifying the framework:
- Existing tools should continue to work without changes
- Add new optional parameters rather than breaking existing ones
- Deprecate features rather than removing them suddenly
- Provide clear migration paths for breaking changes
- Consider semantic versioning implications
- Package published to
@beyondbetter/tools - Version in
deno.jsonmust be bumped for releases - Ensure all exports in
mod.tsare intentional - No private implementation details should leak through exports
- GitHub Actions handles publishing on push to main
Pitfall: Forgetting file extensions in imports
// ❌ Wrong
import { LLMTool } from './llm_tool';
// ✅ Correct
import { LLMTool } from './llm_tool.ts';Pitfall: Mixing JSX without proper setup
// ❌ Wrong - missing JSX directive
import { h } from 'preact';
// ✅ Correct
/** @jsxImportSource preact */
import type { JSX } from 'preact';Pitfall: Not implementing all required methods
// ❌ Wrong - missing formatters
class MyTool extends LLMTool {
get inputSchema() { /* ... */ }
async runTool() { /* ... */ }
// Missing: formatLogEntryToolUse, formatLogEntryToolResult
}
// ✅ Correct - all methods implemented
class MyTool extends LLMTool {
get inputSchema() { /* ... */ }
async runTool() { /* ... */ }
formatLogEntryToolUse() { /* ... */ }
formatLogEntryToolResult() { /* ... */ }
}Pitfall: Inconsistent formatting utilities
// ❌ Wrong - using raw JSX without utilities
return <div style="color: blue">{text}</div>;
// ✅ Correct - using framework utilities
return LLMTool.TOOL_TAGS_BROWSER.content.text(text);Pitfall: Not mocking interfaces properly
// ❌ Wrong - using real implementations
const tool = new MyTool();
await tool.runTool(realInteraction, toolUse, realEditor);
// ✅ Correct - mocking interfaces
const mockInteraction = {
projectEditor: mockEditor,
conversationLogger: mockLogger,
// ... other required properties
};
await tool.runTool(mockInteraction, toolUse, mockEditor);Pitfall: Not using test utilities
// ❌ Wrong - manual temp directory management
const tempDir = await Deno.makeTempDir();
try {
// test code
} finally {
await Deno.remove(tempDir, { recursive: true });
}
// ✅ Correct - using withTestProject helper
import { withTestProject } from '@beyondbetter/tools/testing';
await withTestProject(async (projectEditor) => {
// test code - cleanup handled automatically
});Pitfall: Not cleaning up resources
// ❌ Wrong - no cleanup on error
async runTool() {
const resource = await acquireResource();
// operations that might throw
await releaseResource(resource);
}
// ✅ Correct - cleanup with try/finally
async runTool() {
const resource = await acquireResource();
try {
// operations
return result;
} finally {
await releaseResource(resource);
}
}```
## Quick Reference
### Essential Commands
```bash
# Run tests
deno test
# Run specific test file
deno test examples/search_project.tool/tool.test.ts
# Run tests with coverage
deno test --coverage
# Format code
deno fmt
# Lint code
deno lint
# Check types
deno check mod.tsMinimal Tool Implementation:
See examples/search_project.tool/ for complete reference implementation.
Minimal Test with Test Utilities:
import { assertEquals } from '@std/assert';
import { withTestProject } from '@beyondbetter/tools/testing';
import { MyTool } from './tool.ts';
Deno.test({
name: 'MyTool - basic functionality',
async fn() {
await withTestProject(async (projectEditor) => {
const tool = new MyTool();
const mockInteraction = {
projectEditor,
// ... other required properties
};
const result = await tool.runTool(
mockInteraction,
mockToolUse,
projectEditor
);
assertEquals(result.toolResults, expectedResults);
});
},
});Mock Objects Pattern:
// Mock conversation interaction
const mockInteraction: IConversationInteraction = {
getFileMetadata: () => mockMetadata,
readProjectFileContent: async () => mockContent,
// ... other required methods
};
// Mock tool use
const mockToolUse: LLMAnswerToolUse = {
id: 'test-id',
name: 'your-tool',
toolInput: {
// Tool-specific parameters
},
};// From mod.ts
export { default as LLMTool } from './llm_tool.ts';
export type {
IConversationInteraction,
IProjectEditor,
LLMToolInputSchema,
LLMToolRunResult,
LLMAnswerToolUse,
// ... other types
} from './types.ts';README.md- Project overview and quick startdocs/CREATING_TOOLS.md- Comprehensive guide for tool creatorsdocs/TESTING.md- Testing guidelines and best practicesdocs/tools.md- Framework reference documentationexamples/search_project.tool/README.md- Example tool walkthrough
- JSR Package - Published package
- Beyond Better - Main BB project
- Deno Documentation - Deno runtime docs
- Preact Documentation - JSX framework for browser formatting
@beyondbetter/types- Shared types across BB projects- Beyond Better main application - Tool runtime environment
Each example tool must test:
- Core functionality - All public methods
- Input validation - Schema compliance
- Edge cases - Boundary conditions, invalid inputs
- Error handling - Expected errors, resource limits
- Formatters - Both browser and console output
- Styling - Proper use of TOOL_TAGS_BROWSER and TOOL_STYLES_CONSOLE
withTestProject: Helper for temporary project setup
export async function withTestProject(
fn: (projectEditor: IProjectEditor) => Promise<void>,
) {
const tempDir = await Deno.makeTempDir();
try {
const projectEditor = createTestProjectEditor(tempDir);
await fn(projectEditor);
} finally {
await Deno.remove(tempDir, { recursive: true });
}
}// Browser formatter test
Deno.test({
name: 'MyTool - Browser formatter',
fn() {
const tool = new MyTool();
const result = tool.formatLogEntryToolUse(mockInput, 'browser');
// Verify structure
assertEquals(
result.title,
LLMTool.TOOL_TAGS_BROWSER.content.title('Tool Use', 'My Tool')
);
// Verify content components
const content = result.content as JSX.Element;
assertNotEquals(
content.props.children.find(
(child) => child.type === LLMTool.TOOL_TAGS_BROWSER.base.label
),
undefined
);
},
});
// Console formatter test
Deno.test({
name: 'MyTool - Console formatter',
fn() {
const tool = new MyTool();
const result = tool.formatLogEntryToolUse(mockInput, 'console');
// Verify structure
assertEquals(
result.title,
LLMTool.TOOL_STYLES_CONSOLE.content.title('Tool Use', 'My Tool')
);
// Verify styled content
assertStringIncludes(
result.content,
LLMTool.TOOL_STYLES_CONSOLE.base.label('Parameters')
);
},
});- Updated for new .bbplugin plugin structure
- Added plugin manifest requirements and schema
- Documented plugin packaging and distribution
- Updated all documentation for plugin-first approach
- Added plugin-manifest-schema.json
- Marked standalone .tool structure as deprecated
- Added datasource component support (future)
- Updated example structure to show plugin packages
- Note: Project may be renamed to bb-plugins
- Enhanced with details from docs/CREATING_TOOLS.md
- Added tool types and patterns (File System, Data Processing, Network)
- Expanded styling components reference
- Added tool planning template
- Included testing utilities (withTestProject)
- Added comprehensive formatter testing patterns
- Included resource management best practices
- Initial guidelines created
- Documented framework structure and development standards
- Established collaboration workflow
- Defined testing and publishing processes