Skip to main content

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:

Terminal
pip install python-socketio[client]

For building executables:

Terminal
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​

Terminal
# Test with stdin/stdout
echo '{"id":"test","method":"test","data":{}}' | python plugin.py

4. Build Executable​

Terminal
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:

plugin.py
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:

plugin.py
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:

plugin.py
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:

plugin.json
{
"id": "my-python-plugin",
"name": "My Python Plugin",
"version": "1.0.0",
"executableProviders": {
"windows": "plugin.exe",
"linux": "plugin"
}
}

2. Add Custom Actions​

plugin.py
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:

Terminal
pip install -r requirements.txt

Adding Socket.IO Support​

For real-time communication, add Socket.IO:

plugin.py
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​

Terminal
pyinstaller --onefile plugin.py

Optimized Build​

Terminal
pyinstaller --onefile \
--clean \
--noconfirm \
--log-level WARN \
plugin.py

Include Data Files​

Terminal
pyinstaller --onefile \
--add-data "config.json:." \
--add-data "templates:templates" \
plugin.py

Performance Tips​

  1. Use generators for large datasets
  2. Cache results when appropriate
  3. Async I/O with asyncio for concurrent operations
  4. Profile with cProfile to find bottlenecks

Troubleshooting​

"ModuleNotFoundError"​

Install missing module:

Terminal
pip install module-name

Or add to PyInstaller:

Terminal
pyinstaller --onefile --hidden-import=module_name plugin.py

Executable too large​

Use --exclude-module to remove unused packages:

Terminal
pyinstaller --onefile \
--exclude-module matplotlib \
--exclude-module scipy \
plugin.py

"Failed to execute script"​

  1. Test script directly: python plugin.py
  2. Check for missing dependencies
  3. Use --debug all with PyInstaller

Common Patterns​

Reading Configuration​

plugin.py
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​

plugin.py
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​

plugin.py
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

Learn More​