Python Starter Template
Beginner-friendly plugin template in Python with clear, readable code.
Overview
The Python starter template provides an easy-to-understand foundation for building HyperHQ plugins:
- Simple, readable Python syntax
- Basic stdin/stdout communication (can be extended with Socket.IO)
- Easy debugging with print statements and logs
- PyInstaller support for creating executables
- Cross-platform compatible
Prerequisites
- Python 3.8 or later
- pip (Python package installer)
- Basic understanding of Python
Quick Start
1. Get the Template
Download the python starter and extract the archive. Open a terminal in the extracted folder:
cd python-starter
Use Build and install on Linux for Linux. The numbered build and install example below targets Windows.
2. Install Dependencies (Optional)
For Socket.IO support, install python-socketio:
pip install python-socketio[client]
For building executables:
pip install pyinstaller
Configure the Transport
The download's Python code reads stdin and writes JSON to stdout. Its bundled manifest still prefers Socket.IO. Before installing the unchanged Python code, replace the communication block with:
"communication": {
"preferred": "stdio",
"stdio": { "enabled": true },
"socketio": { "enabled": false }
}
Remove the required Socket.IO capability from the manifest. Installing python-socketio alone does not add a Socket.IO implementation to plugin.py. Keep diagnostics on stderr so stdout contains only protocol messages.
3. Test Locally
# Test with stdin/stdout
echo '{"id":"test","method":"test","data":{}}' | python plugin.py
4. Build Executable
pyinstaller --onefile plugin.py
The executable will be in dist/plugin.exe (Windows) or dist/plugin (macOS/Linux).
5. Install in HyperHQ on Windows
Use the HyperSpin root shown in Settings, Paths. Replace this example with your configured plugin folder.
$pluginDir = 'C:/ProgramData/HyperSpin/plugins/my-python-plugin'
New-Item -ItemType Directory -Force -Path $pluginDir
Copy-Item -Path 'dist/plugin.exe' -Destination $pluginDir
Copy-Item -LiteralPath 'plugin.json' -Destination $pluginDir
Build and install on Linux
Run these commands inside the extracted starter directory on Linux:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install pyinstaller 'python-socketio[client]'
python -m PyInstaller --onefile plugin.py
Set executableProviders.linux to plugin in plugin.json.
plugin_dir="/absolute/path/to/plugins/my-python-plugin"
mkdir -p "$plugin_dir"
cp dist/plugin plugin.json "$plugin_dir/"
chmod +x "$plugin_dir/plugin"
Build frozen executables on the target operating system and test on the oldest supported Linux distribution.
Replace the example directory with your configured plugin path. Restart or reload the plugin in HyperHQ and verify authentication, an action, and shutdown. Follow the Linux release requirements before publishing.
Key Features
Class-Based Structure
Clean, object-oriented design:
class MyPlugin:
def __init__(self):
self.settings = {}
self.plugin_data_dir = os.getenv('PLUGIN_DATA_DIR', './data')
self.debug_mode = os.getenv('PLUGIN_DEBUG', 'false').lower() == 'true'
def initialize(self, data):
self.settings = data.get('settings', {})
return "initialized"
def execute(self, data):
action = data.get('action', 'default')
# Handle actions...
Debug Logging
Built-in debug logging:
def debug_log(self, message):
if self.debug_mode:
with open('plugin-debug.log', 'a') as f:
f.write(f"DEBUG: {message}\n")
Standard Plugin Methods
All required methods included:
def initialize(self, data):
"""Initialize plugin with settings from HyperHQ"""
pass
def execute(self, data):
"""Main plugin execution method"""
pass
def test(self, data):
"""Health check for the plugin"""
pass
def shutdown(self, data):
"""Clean up before plugin exits"""
pass
Template Structure
python-starter/
├── plugin.py # Main plugin code
├── plugin.json # Plugin manifest
├── requirements.txt # Python dependencies (optional)
└── build.sh/bat # Build scripts
Customization
1. Update Plugin Metadata
Edit plugin.json:
{
"id": "my-python-plugin",
"name": "My Python Plugin",
"version": "1.0.0",
"executableProviders": {
"windows": "plugin.exe",
"linux": "plugin"
}
}
2. Add Custom Actions
def execute(self, data):
action = data.get('action', 'default')
if action == 'my_custom_action':
return self.handle_my_action(data)
elif action == 'process_data':
return self.process_data(data)
else:
return {"error": f"Unknown action: {action}"}
def handle_my_action(self, data):
# Your custom logic here
return {"success": True, "message": "Action completed"}
3. Add Dependencies
Create requirements.txt:
python-socketio[client]==5.10.0
requests==2.31.0
Install:
pip install -r requirements.txt
Adding Socket.IO Support
For real-time communication, add Socket.IO:
import os
import socketio
class MyPlugin:
def __init__(self):
self.sio = socketio.Client()
self.plugin_id = os.getenv('HYPERHQ_PLUGIN_ID')
self.auth_challenge = os.getenv('HYPERHQ_AUTH_CHALLENGE')
self.session_token = None
def connect_socketio(self):
@self.sio.event
def connect():
print('Connected to HyperHQ')
# Authenticate
self.sio.emit('authenticate', {
'pluginId': self.plugin_id,
'challenge': self.auth_challenge
})
@self.sio.on('authenticated')
def on_authenticated(data):
if data.get('success'):
self.session_token = data.get('sessionToken')
print('Authentication successful')
self.sio.emit('statusUpdate', {
'status': 'ready',
'message': 'Python plugin authenticated and ready'
})
# Connect to HyperHQ
socket_port = os.environ['HYPERHQ_SOCKET_PORT']
self.sio.connect(f'http://localhost:{socket_port}')
Building for Production
Basic Build
pyinstaller --onefile plugin.py
Optimized Build
pyinstaller --onefile \
--clean \
--noconfirm \
--log-level WARN \
plugin.py
Include Data Files
pyinstaller --onefile \
--add-data "config.json:." \
--add-data "templates:templates" \
plugin.py
Performance Tips
- Use generators for large datasets
- Cache results when appropriate
- Async I/O with
asynciofor concurrent operations - Profile with cProfile to find bottlenecks
Troubleshooting
"ModuleNotFoundError"
Install missing module:
pip install module-name
Or add to PyInstaller:
pyinstaller --onefile --hidden-import=module_name plugin.py
Executable too large
Use --exclude-module to remove unused packages:
pyinstaller --onefile \
--exclude-module matplotlib \
--exclude-module scipy \
plugin.py
"Failed to execute script"
- Test script directly:
python plugin.py - Check for missing dependencies
- Use
--debug allwith PyInstaller
Common Patterns
Reading Configuration
import json
def load_config(self):
config_path = os.path.join(self.plugin_data_dir, 'config.json')
if os.path.exists(config_path):
with open(config_path, 'r') as f:
return json.load(f)
return {}
HTTP Requests
import requests
def fetch_data(self, url):
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
return response.json()
except requests.RequestException as e:
self.debug_log(f"Request failed: {e}")
return None
File Processing
def scan_files(self, directory):
files = []
for root, dirs, filenames in os.walk(directory):
for filename in filenames:
if filename.endswith('.xml'):
files.append(os.path.join(root, filename))
return files