A Cookiecutter template for creating FlukeBase plugins using the open-source flukebase-sdk.
# Install cookiecutter if you haven't
pip install cookiecutter
# Create a new plugin from this template
cookiecutter gh:flukebase/flukebase-plugin-templateYou'll be prompted for:
| Variable | Description | Example |
|---|---|---|
plugin_name |
Package name (PyPI) | flukebase-my-plugin |
module_name |
Python module name | my_plugin |
display_name |
Human-readable name | My Plugin |
description |
Brief description | A plugin that does X |
author |
Your name | Jane Developer |
author_email |
Your email | jane@example.com |
github_username |
GitHub username | janedev |
version |
Initial version | 0.1.0 |
category |
Plugin category | integration |
flukebase-my-plugin/
├── pyproject.toml # Package config with entry point
├── src/my_plugin/
│ ├── __init__.py # Package exports
│ └── plugin.py # BasePlugin implementation
├── tests/
│ └── test_plugin.py # Example tests
├── README.md # Documentation template
├── LICENSE # MIT license
└── .gitignore
cookiecutter gh:flukebase/flukebase-plugin-template
cd flukebase-my-pluginpip install -e ".[dev]"Edit src/my_plugin/plugin.py:
from flukebase_sdk import (
BasePlugin,
PluginMetadata,
PluginType,
PluginMaturity,
ToolDefinition,
ToolAnnotations,
)
class MyPlugin(BasePlugin):
def get_metadata(self) -> PluginMetadata:
return PluginMetadata(
name="flukebase-my-plugin",
display_name="My Plugin",
version="1.0.0",
description="Does something useful",
plugin_type=PluginType.TOOL,
maturity=PluginMaturity.MVP,
)
def get_tools(self) -> list[ToolDefinition]:
return [
ToolDefinition(
name="my_plugin_do_thing",
description="Does something useful",
input_schema={
"type": "object",
"properties": {
"param": {"type": "string", "description": "A parameter"}
},
"required": ["param"],
},
handler_method="handle_do_thing",
),
]
async def handle_do_thing(self, args: dict) -> str:
param = args.get("param")
# Your implementation here
return f"Did the thing with {param}"# Run tests
pytest
# Test with FlukeBase Connect
# Add to ~/.flukebase-connect/config.toml:
# [plugins]
# enabled = ["flukebase-my-plugin"]
# Then reload
fb_reload# Build
python -m build
# Upload (requires PyPI account)
twine upload dist/*- Fork flukebase_connect
- Add your plugin to
flukebase_connect/marketplace/registry.json:
{
"name": "flukebase-my-plugin",
"display_name": "My Plugin",
"description": "A plugin that does X",
"version": "0.1.0",
"author": "Jane Developer",
"pypi_package": "flukebase-my-plugin",
"repository": "https://github.com/janedev/flukebase-my-plugin",
"category": "integration",
"status": "pending"
}- Open a Pull Request
Follow FlukeBase naming conventions (NAMING-008):
- Use a consistent prefix:
myplugin_* - Lowercase with underscores
- Be descriptive but concise
Good examples:
slack_send_messagegithub_list_issuesanalytics_generate_report
| Category | PluginType Enum | Description |
|---|---|---|
ai_provider |
PluginType.AI_PROVIDER |
AI service integrations |
integration |
PluginType.INTEGRATION |
External service integrations (Slack, GitHub, etc.) |
tool |
PluginType.TOOL |
General utility tools |
| Maturity | PluginMaturity Enum | Description |
|---|---|---|
conceptual |
PluginMaturity.CONCEPTUAL |
Idea phase, not fully functional |
mvp |
PluginMaturity.MVP |
Basic functionality, limited testing |
beta |
PluginMaturity.BETA |
Feature complete, testing in progress |
production |
PluginMaturity.PRODUCTION |
Full featured, tested, stable |
Plugins can access these shared services via self.get_service():
| Service | Description | Protocol |
|---|---|---|
flukebase_client |
FlukeBase API client | FlukeBaseClientProtocol |
env_manager |
Environment variable management | EnvManagerProtocol |
memory |
Persistent memory store | MemoryStoreProtocol |
wedo |
WeDo task manager | WedoManagerProtocol |
config |
Configuration access | ConfigProtocol |
Example with type hints:
from flukebase_sdk import (
BasePlugin,
FlukeBaseClientProtocol,
MemoryStoreProtocol,
)
class MyPlugin(BasePlugin):
async def initialize(self, config: dict, services: dict) -> None:
await super().initialize(config, services)
# Type-safe service access
self.client: FlukeBaseClientProtocol = self.get_service("flukebase_client")
self.memory: MemoryStoreProtocol = self.get_service("memory")
async def my_tool_handler(self, args: dict) -> str:
# IDE provides autocomplete for protocol methods
memories = await self.memory.recall("test query")
return f"Found {len(memories)} memories"For full SDK documentation, see:
MIT