Deployment Methods#
Method 1: File Drop (Simplest)#
Drop a .py file in the appropriate directory:
| Plugin Type | Directory |
|---|---|
| Server module | modules/ |
| Transport | plugins/transports/ |
| Tools module | plugins/agentless/ |
| Agent package | plugins/agent_packages/ |
Then trigger a refresh:
| |
No packaging needed — the framework discovers your plugin on the next scan.
Method 2: Plugin Inbox#
Drop a .py or .whl file into the plugin inbox directory (plugin_inbox_dir config):
.pyfiles: Auto-detected by type and moved to the correct plugin directory.whlfiles: Pip-installed into the running environment, then registered via entry points
The inbox is scanned every bg_plugin_watcher_interval seconds (default: 30).
If a .py file fails to load, it’s moved to inbox/failed/ with an error log.
Method 3: Python Wheel (Recommended for Distribution)#
Package your plugin as a standard Python wheel with entry points.
Packaging as a Wheel#
Project Structure#
| |
pyproject.toml#
| |
Entry Points by Plugin Type#
Server Module#
| |
Transport Plugin#
| |
Tools Module#
| |
Agent Package (Three Entry Points)#
Agent packages require three separate entry points — one for each component:
| |
Entry point names (left side of =) must match the plugin_name() return value.
Building#
| |
Installing#
| |
Hot-Reload#
All plugin types support hot-reload without server restart:
File-Based Plugins#
The framework tracks file modification times (mtime). When a file changes:
- The old plugin class is unregistered
- The file is re-imported
- New plugin classes are discovered and registered
Trigger manually:
| |
Or wait for the plugin watcher (runs every bg_plugin_watcher_interval seconds).
Wheel-Based Plugins#
Re-install the updated wheel:
| |
Then trigger a refresh — the framework re-scans entry points.
Plugin Naming#
plugin_name()must be globally unique across all plugins of the same type- Use lowercase with underscores:
my_module,dns_transport,shinobi_agent - For agent packages, ensure consistency between package name, crypto provider name, and codec name
Dependencies#
Declared Dependencies#
Modules can declare pip dependencies in their metadata:
| |
Missing packages are auto-installed at discovery time.
Failed Dependencies#
If installation fails, the module is marked as unavailable. Query unavailable modules:
| |
The module won’t appear in list_modules() but its failure reason is tracked.
Testing Your Plugin#
Unit Testing#
| |
Integration Testing#
| |
Distribution Checklist#
-
plugin_name()is unique and descriptive -
plugin_type()returns the correct type string - Entry point names match
plugin_name()return values - Dependencies are declared in both
pyproject.tomland metadata - Plugin works after
pip installfrom wheel - Plugin works via file drop into appropriate directory
- Plugin works via inbox drop (both
.pyand.whl) - Hot-reload works (modify file, refresh, verify changes)