CLI Reference¶
The ts-ha CLI inspects and manages a running engine instance via its debug API, and can boot a local engine with ts-ha run. It is provided by the @ts-ha/cli package (installed separately from the @ts-ha/core library).
Run¶
Boot a local engine in the current process — the only first-party engine runner (there is no separate standalone entry point):
ts-ha run # loads ./automations
ts-ha run --automations /etc/automations
ts-ha run --automations ./auto # resolved against the working directory
- The automations directory defaults to
./automationsrelative to the current working directory; relative option values resolve the same way. - No example automations ship with the packages. If the resolved directory does not exist, the command logs an explicit warning and startup continues with zero automations (create the directory and add your own).
SIGINT/SIGTERMtrigger a graceful engine shutdown before exit.- When
WEB_UI_ENABLED=true,rundynamic-imports@ts-ha/web-ui, lets that package parseWEB_UI_ENABLED/WEB_UI_PATH, and registers the plugin using the core config's resolvedHTTP_TOKENas its auth token.@ts-ha/web-uiis an optional peer: install it explicitly if you enable the UI undernpxor a global install.
Global options¶
| Option | Description |
|---|---|
--host <host:port> |
Override the target host (default: from saved config) |
--token <token> |
Override the auth token (default: from saved config) |
--json |
Output raw JSON instead of formatted text |
--help |
Show help |
Saved targets¶
Target configurations (host + token pairs) are stored in ~/.config/ts-ha/config.json. A local target pointing to localhost:8080 is created by default.
# List all saved targets (* = active)
ts-ha config list
ts-ha c list # short alias
# Add a remote target
ts-ha config add prod 192.168.1.100:8080 my-secret-token
# Switch to a target
ts-ha config use prod
# Remove a target
ts-ha config remove prod
ts-ha config rm prod # rm / del also accepted
Override for a single command¶
Automations¶
# List all registered automations
ts-ha automations list
ts-ha a ls # short alias
# Get details for a specific automation
ts-ha automations get motion-light-schedule
Example output:
NAME TRIGGERS
motion-light-schedule mqtt(2)
contact-sensor-alarm mqtt(3)
shortcut-button-timer mqtt(1)
3 automation(s)
Trigger¶
Manually fire an automation with a synthetic context — useful for testing:
# MQTT trigger (trigger / t both accepted)
ts-ha a trigger motion-light '{"type":"mqtt","topic":"zigbee2mqtt/sensor","payload":{"occupancy":true}}'
ts-ha a t motion-light '{"type":"mqtt","topic":"zigbee2mqtt/sensor","payload":{"occupancy":true}}'
# Cron trigger (defaults filled automatically)
ts-ha a trigger scheduled-report '{"type":"cron"}'
# State trigger
ts-ha a trigger night-reaction '{"type":"state","key":"night_mode","newValue":true,"oldValue":false}'
# Webhook trigger
ts-ha a trigger deploy-hook '{"type":"webhook","method":"POST","body":{"service":"api"}}'
Logs¶
# Last 50 entries (default)
ts-ha logs
# Filter by automation name
ts-ha logs --automation motion-light-schedule
# Filter by minimum level
ts-ha logs --level error
# Combine filters
ts-ha logs --automation contact-sensor-alarm --level warn --limit 20
# JSON output for scripting
ts-ha --json logs | jq '.entries[] | select(.msg | contains("ALARM"))'
Example output:
07:04:17.033 INFO [motion-light-schedule] Motion detected
07:04:17.035 INFO [motion-light-schedule] Turning on lamps
07:09:17.040 INFO [motion-light-schedule] No recent motion, turning off
Follow mode¶
Stream new log entries continuously (like tail -f):
ts-ha logs -f
ts-ha logs --follow --automation contact-sensor-alarm
ts-ha logs -f --level error --interval 1 # poll every 1s
ts-ha --json logs -f | jq .msg # JSON per line
Press Ctrl+C to stop.
State¶
# List all state keys and values
ts-ha state list
ts-ha s ls # short alias
# Read a single value
ts-ha state get night_mode
# Write a value (JSON-parsed: booleans, numbers, strings, objects)
ts-ha state set night_mode true
ts-ha state set motion_count 42
ts-ha state set config '{"threshold": 30}'
# Delete a key
ts-ha state delete temporary_flag
ts-ha s rm old_key # short alias
Setting state via the CLI fires state triggers in the running engine — it is equivalent to calling this.state.set() inside an automation.
Devices¶
Inspect Zigbee2MQTT devices tracked by the device registry. Requires DEVICE_REGISTRY_ENABLED=true on the running engine.
# List all tracked devices
ts-ha devices list
ts-ha dv ls # short alias
# Get full detail for a single device
ts-ha devices get living_room_bulb
ts-ha dv get living_room_bulb # short alias
Example output for ts-ha devices list:
NICE NAME TYPE INTERVIEW STATE KEYS
Living Room Lamp Router SUCCESSFUL 8
Kitchen Motion Sensor EndDevice SUCCESSFUL 3
Hallway Plug Router SUCCESSFUL 5
3 devices
Example output for ts-ha devices get living_room_bulb:
Nice Name: Living Room Lamp
Friendly: living_room_bulb
IEEE: 0x00158d0001ab1234
Type: Router
Supported: true
Interview: SUCCESSFUL
Power: Mains
Model: LCA001 (Philips, Hue White and color ambiance)
State (8 keys):
state ON
brightness 200
color_temp 4000
color_mode color_temp
linkquality 92
update_available false
When the registry is disabled, both commands print a clear message and exit with code 1. Use --json to output raw JSON for scripting.
Dashboard¶
Interactive terminal dashboard (TUI) showing all tabs in real time:
Tabs¶
| Tab | Key | Features |
|---|---|---|
| Overview | 1 |
Engine/MQTT/HomeKit status, uptime, automation + state summary, recent logs |
| Automations | 2 |
List with expand (trigger details) and manual trigger |
| Devices | 3 |
Tracked Zigbee devices — expand for state + metadata (DEVICE_REGISTRY_ENABLED=true) |
| State | 4 |
List with inline edit, add, delete |
| Logs | 5 |
Scrollable viewer with level + automation filter |
| HomeKit | 6 |
Bridge running state, accessory count, full configuration — hidden hint when not configured |
Keyboard shortcuts¶
| Key | Action |
|---|---|
1–6 |
Switch tabs |
q / Esc |
Quit |
r |
Force refresh |
? |
Toggle help modal |
Enter |
Expand row / edit state value |
t |
Trigger selected automation |
n / d |
New / delete state key |
↑ / ↓ |
Navigate log entries |
l |
Cycle log level filter |
f |
Free-text filter |
c |
Clear log filters |
Nanoleaf¶
Pair a Nanoleaf device to generate an auth token for use with the NanoleafService:
ts-ha nanoleaf pair 192.168.1.60 # by IP address
ts-ha nanoleaf pair nanoleaf-panels.local # by mDNS hostname
- Run the command — it will prompt you to press and hold the power button on the Nanoleaf device until the LEDs start flashing, then press Enter
- The command retries up to 5 times with a 2-second delay between attempts
- On success it prints the auth token and a ready-to-use registration snippet:
const nanoleaf = engine.services.getOrThrow("nanoleaf");
nanoleaf.register("panels", {
host: "192.168.1.60",
token: "<printed-token>",
});
Save the token in your .env or config file — it does not expire.
Authentication¶
When HTTP_TOKEN is set on the engine, the CLI must supply the same token:
# Save token with the target
ts-ha config add prod 192.168.1.100:8080 my-secret-token
ts-ha config use prod
# Or pass it per command
ts-ha --host 192.168.1.100:8080 --token my-secret-token state list
Health probe endpoints (/healthz, /readyz) are always unauthenticated.