🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
6.4 KiB
Plugin Architecture Instructions
Overview
Dangerous Pi uses a plugin system that supports:
- Remote installation from GitHub releases
- Automatic pip dependency management
- Hardware access (GPIO, I2C, SPI, serial) with permission enforcement
- WebSocket broadcasting for real-time updates
- Header widgets for UI notifications
- Permission declarations with user consent at install time
Plugin Distribution Model
Each plugin lives in its own GitHub repo (e.g., org/dangerous-pi-multi-flasher).
Registry Format
A central registry repo (dangerous-pi-plugin-registry) contains plugins.json:
{
"version": "1.0.0",
"plugins": [
{
"id": "plugin_id",
"name": "Plugin Name",
"repo": "org/repo-name",
"description": "Description",
"author": "Author",
"latest_version": "1.0.0"
}
]
}
Plugin Release Format
Each plugin repo publishes GitHub releases with:
plugin.tar.gz- The plugin archiveplugin.json- Metadata with checksum and dependencies
plugin.json Schema
{
"id": "plugin_id",
"name": "Plugin Name",
"version": "1.0.0",
"description": "Description",
"author": "Author",
"checksum": "sha256:...",
"dependencies": ["package>=1.0.0"],
"permissions": ["gpio", "i2c", "network_access"],
"min_app_version": "1.0.0"
}
Plugin Directory Structure
app/plugins/{plugin_id}/
plugin.json # Metadata manifest
main.py # Entry point (extends PluginBase)
services/ # Business logic
__init__.py
{service}.py
api/ # FastAPI router (optional)
__init__.py
router.py
Creating a Plugin
1. Extend PluginBase
from backend.managers.plugin_manager import PluginBase, PluginMetadata
class MyPlugin(PluginBase):
async def on_load(self):
# Initialize services
pass
async def on_enable(self):
# Register hooks, start functionality
self.register_hook("hook_name", self.my_callback)
async def on_disable(self):
# Stop functionality
pass
async def on_unload(self):
# Cleanup resources
pass
2. Register Hooks
Available hooks:
pm3_command- Triggered on Proxmark3 commandsupdate_check- Triggered on system update checks- Custom hooks can be added
3. Add API Routes (Optional)
Plugins can expose their own FastAPI routers mounted under /api/plugins/{plugin_id}/
4. Register Header Widgets
Display notifications in the UI header:
from backend.managers.plugin_manager import WidgetSeverity
class MyPlugin(PluginBase):
async def on_enable(self):
# Register a header widget
self.register_widget(
widget_id="status", # Becomes "plugin.my_plugin.status"
severity=WidgetSeverity.INFO,
message="Plugin is active",
icon="🔌",
dismissible=True,
action_label="Settings", # Optional
action_url="/settings#plugins"
)
async def on_disable(self):
# Clean up widget
self.unregister_widget("status")
Widget severity levels: INFO, WARNING, ERROR, SUCCESS
5. Broadcast WebSocket Events
Send real-time updates to connected clients (requires websocket permission):
class MyPlugin(PluginBase):
async def some_operation(self):
# Broadcast event to all connected clients
# Event type becomes: "plugin.my_plugin.progress"
await self.broadcast_event("progress", {
"percent": 50,
"message": "Processing..."
})
WebSocket events are rate-limited to 10 events/second per plugin.
6. Access Hardware
Get controlled access to hardware interfaces (requires permissions in plugin.json):
class MyPlugin(PluginBase):
def setup_hardware(self):
# Requires "i2c" permission
i2c = self.get_i2c(bus=1)
# Requires "gpio" permission
gpio = self.get_gpio()
# Requires "spi" permission
spi = self.get_spi(bus=0, device=0)
# Requires "serial" permission
serial = self.get_serial("/dev/ttyUSB0", baudrate=9600)
Available Permissions
| Permission | Description | Methods Unlocked |
|---|---|---|
gpio |
Access GPIO pins | get_gpio() |
i2c |
Access I2C bus | get_i2c() |
spi |
Access SPI bus | get_spi() |
serial |
Access serial ports | get_serial() |
websocket |
Broadcast WebSocket events | broadcast_event() |
camera |
Access camera | (future) |
network_access |
Make network requests | (unrestricted) |
pm3_flash |
Flash PM3 devices | (via hooks) |
script_execution |
Execute user scripts | (sandboxed) |
Note: Hardware permissions (gpio, i2c, spi, serial) require user consent at install time.
Attempting to use hardware methods without the required permission raises PermissionError.
Hardware Libraries
Plugins can depend on these for hardware access:
RPi.GPIO- GPIO pin controlsmbus2- I2C communicationspidev- SPI communicationgpiozero- Higher-level GPIO abstractionpyserial- Serial/UART communicationopencv-python-headless- Camera/image processing
Key Files
| File | Purpose |
|---|---|
app/backend/managers/plugin_manager.py |
Core plugin framework, widgets, permissions |
app/backend/services/hardware_service.py |
Hardware access layer (I2C, GPIO, SPI, Serial) |
app/backend/websocket/notifications.py |
WebSocket event broadcasting |
app/backend/api/plugins.py |
Plugin API endpoints |
app/backend/api/system.py |
Widget API endpoints (/api/system/widgets) |
app/frontend/app/components/HeaderWidgets.tsx |
Widget UI component |
app/plugins/hello_world/ |
Reference implementation |
Installation Sources
- From registry - Browse webstore → select plugin → auto-install
- Direct URL - Install from any GitHub release URL
Security Guidelines
- Verify SHA256 checksums before extraction
- Only install pip packages from PyPI
- Sandbox script execution (no os, sys, subprocess access)
- Display permissions to user before installation
- Log all plugin installations
Related Plans
See /home/work/.claude/plans/tranquil-toasting-clover.md for the full implementation plan including:
- Multi-Flasher Plugin (parallel PM3 firmware flashing)
- Color Detector Plugin (webcam color detection + WebREPL)