Appearance
Driver Manifest
The driver manifest is the metadata file that describes an OS-local driver package. It controls how HOS displays your integration in the UI, generates the setup form, builds the command catalog, and launches the driver at runtime.
This page covers the OS-local package path — drivers uploaded as a ZIP through the Integration Manager. If you are building an external WebSocket driver (using the SDK), you do not need a manifest; see Getting Started.
Package Structure
An uploadable driver package is a ZIP file containing:
my-driver.zip
├── my-driver.driver.json ← manifest (required, exactly one *.driver.json)
├── driver.js ← implementation (required, one of .js / .py / .lua)
└── README.md ← optional documentationA
package.jsonmay be included for JavaScript drivers that require external npm dependencies. Prefer dependency-free packages for v1 — use Node 20+ built-ins (fetch,net,dgram,readline) where possible.
Runtime Targets
| Runtime | File extension | Notes |
|---|---|---|
javascript | .js | First-class local driver. Node-compatible CommonJS, newline-delimited JSON over stdin/stdout. |
python | .py | Same JSON-line process contract as JavaScript. |
lua | .lua | Command-oriented local runtime. |
typescript | compiled .js | Authoring option only — raw .ts is not accepted in ZIP uploads. Compile to .js first. |
Manifest Fields
Top-level
jsonc
{
"driverKey": "MY_DEVICE", // Required. Uppercase [A-Z0-9_], 2-64 chars
"driverType": "javascript", // Required. "javascript" | "python" | "lua"
"driverFile": "driver.js", // Required. Points to the implementation file
"name": "My Device Integration", // Display name in Integration Manager
"version": "1.0.0", // Semver version string
"description": "Controls My Device via HTTP API",
"author": "Your Name",
"properties": [ ... ], // Setup form fields (see below)
"commands": [ ... ], // User-visible command catalog (see below)
"io": { ... }, // Integration topology (see below)
"envMap": { ... } // Maps setup properties → env vars (see below)
}properties — Setup Form
properties defines the fields shown in the Integration Manager setup form when a user installs your driver. Each entry becomes an environment variable available to the driver at runtime (via envMap).
jsonc
"properties": [
{
"key": "DEVICE_IP",
"label": "Device IP Address",
"type": "text",
"required": true,
"placeholder": "192.168.1.100",
"description": "Local IP address of the device on your network"
},
{
"key": "API_KEY",
"label": "API Key",
"type": "password",
"required": true
},
{
"key": "POLL_INTERVAL",
"label": "Poll Interval (seconds)",
"type": "number",
"required": false,
"default": "5"
}
]Field types: text, password, number, boolean, select
commands — Command Catalog
commands defines the user-visible actions exposed in the HOS mobile app and admin UI. These must correspond to ACTION keys your driver handles.
jsonc
"commands": [
{
"key": "turn_on",
"label": "Turn On",
"description": "Power on the device"
},
{
"key": "set_brightness",
"label": "Set Brightness",
"description": "Set brightness 0-100",
"payloadSchema": {
"type": "object",
"properties": {
"level": { "type": "number", "minimum": 0, "maximum": 100 }
},
"required": ["level"]
}
}
]io — Integration Topology
io describes the integration's inputs and outputs for display in the topology/wiring UI.
jsonc
"io": {
"inputs": [
{ "key": "trigger", "label": "Trigger", "type": "event" }
],
"outputs": [
{ "key": "state", "label": "Device State", "type": "state" }
]
}envMap — Property → Environment Variable Mapping
envMap maps properties keys to the environment variable names your driver reads at runtime. This keeps credentials out of source code.
jsonc
"envMap": {
"DEVICE_IP": "DEVICE_IP",
"API_KEY": "MY_DEVICE_API_KEY",
"POLL_INTERVAL": "POLL_INTERVAL_SECS"
}At runtime, your driver reads these as process.env.DEVICE_IP, process.env.MY_DEVICE_API_KEY, etc.
Complete Example
jsonc
{
"driverKey": "SMART_BULB",
"driverType": "javascript",
"driverFile": "driver.js",
"name": "Smart Bulb",
"version": "1.0.0",
"description": "Controls Smart Bulb lights via local HTTP API",
"author": "Haptique",
"properties": [
{
"key": "BRIDGE_IP",
"label": "Bridge IP",
"type": "text",
"required": true,
"placeholder": "192.168.1.100"
},
{
"key": "BRIDGE_KEY",
"label": "Bridge API Key",
"type": "password",
"required": true
}
],
"commands": [
{ "key": "turn_on", "label": "Turn On" },
{ "key": "turn_off", "label": "Turn Off" },
{
"key": "set_brightness",
"label": "Set Brightness",
"payloadSchema": {
"type": "object",
"properties": {
"level": { "type": "number", "minimum": 0, "maximum": 100 }
},
"required": ["level"]
}
}
],
"io": {
"inputs": [],
"outputs": [
{ "key": "state", "label": "Light State", "type": "state" }
]
},
"envMap": {
"BRIDGE_IP": "BRIDGE_IP",
"BRIDGE_KEY": "BRIDGE_API_KEY"
}
}JavaScript Driver Protocol
JavaScript local drivers use newline-delimited JSON over stdin/stdout — the same protocol contract as Python drivers.
From HOS to driver (stdin):
json
{"event":"ACTION","device_id":"bulb-001","data":{"action":"turn_on","requestId":"req-123"}}From driver to HOS (stdout):
json
{"event":"DEVICE_DISCOVERED","device_id":"bulb-001","data":{"name":"Bedroom Bulb","deviceType":"light","properties":{"commandCatalog":[{"key":"turn_on","label":"Turn On"}]}}}
{"event":"STATE_UPDATE","device_id":"bulb-001","data":{"power":false,"brightness":0}}
{"event":"ACTION_RESULT","device_id":"bulb-001","data":{"success":true,"requestId":"req-123"}}Each line is a complete JSON object. Do not emit multi-line JSON.
AI Driver Builder
The AI Driver Builder can generate a complete driver package — manifest + implementation + README — from a plain-language description of the device protocol. This is the fastest path if you are building a net-new integration.
What's Next
- AI Driver Builder MCP — Generate driver packages with AI assistance
- Domain Reference — Standard commands and state fields per device domain
- Troubleshooting — Common errors during driver development