⚡ Alpha v0.1.0-alpha.1 MIT HACS Custom

Signal Deck

The oscilloscope for Home Assistant. A safe Python REPL embedded in Lovelace with built-in AI analyst, ECharts visualisations, and deep state exploration — powered by WebAssembly, runs entirely in your browser.

Signal Deck — Python REPL inside Home Assistant

Features

🐍

Python REPL

Real Python running in WebAssembly via Monty. Safe, sandboxed, instant — no backend required.

📊

ECharts Visualisations

History timelines, binary sensor lanes, and custom charts rendered with Apache ECharts.

🤖

AI Analyst

Built-in analyst powered by HA Conversation. Ask “why did this happen?” in plain English.

🔍

Deep State Exploration

Browse entities, attributes, rooms, and areas. Auto-resolve short names like kitchen_temp.

📅

Calendar Events

Query calendar events with events(). Rich auto-rendering with colour-coded timelines.

Rich Auto-render

Entity cards, state tables, and charts render automatically. Just type an expression — the REPL picks the best view.

🔒

Safe by Default

Read-only state access. Service calls require explicit arming. No filesystem, no network, no eval.

⚙️

Rust Shell Engine

Command parsing, data transforms, and render-spec generation in Rust compiled to WASM. Fast and tiny.

Signal Deck — ECharts pie chart visualisation
ECharts visualisations
Signal Deck — Sparkline history chart
History sparklines
Signal Deck — AI Signal Analyst conversation
AI Signal Analyst
Signal Deck — Overlay console mode
Overlay console

Installation

HACS (Recommended)

  1. Open HACS → Frontend → three-dot menu → Custom repositories
  2. Add https://github.com/rsr5/signal-deck as category Dashboard
  3. Search for Signal Deck and click Install
  4. Reload your browser

Manual

  1. Download signal-deck.js from the latest release
  2. Copy it to config/www/signal-deck.js
  3. In HA → Settings → Dashboards → Resources, add /local/signal-deck.js as JavaScript Module
  4. Reload your browser

Quick Start

Add a new card to any dashboard and paste this YAML:

type: custom:signal-deck
mode: embedded     # or "overlay" for floating panel
height: 420

Once the card loads, try these commands in the REPL:

# List all entities
ls()

# Inspect a sensor
get("sensor.living_room_temperature")

# View 6 hours of history
history("sensor.living_room_temperature", "6h")

# Upcoming calendar events
events("calendar.home", "24h")

Card Configuration

OptionTypeDefaultDescription
modestring"embedded""embedded" (inline card) or "overlay" (floating panel)
heightnumber420Card height in pixels (embedded mode)
font_sizenumber13REPL font size in pixels
startupstring[][]Python commands to run on card load
analyst_entitystringConversation agent entity for AI analyst
Signal Deck — Overlay console mode floating over a dashboard
Overlay console mode

Using the REPL

Signal Deck gives you a Python prompt inside your dashboard. Type any expression and press Enter to evaluate it. Results are automatically rendered as rich cards, tables, or charts when possible.

Magic Commands

Prefix commands with % for shell-level operations:

CommandDescription
%lsList entities (with optional domain/pattern filter)
%get <entity>Inspect a single entity with all attributes
%history <entity> <period>Fetch and chart entity history
%events <calendar> <period>List upcoming calendar events
%roomsShow rooms/areas and their entities
%services <domain>List available services for a domain
%histShow command history
%fmt <format>Set output format (table, json, csv)
%clearClear the REPL output
:helpShow the built-in help reference

Auto-resolve

You don't need to type full entity IDs. Signal Deck fuzzy-matches short names:

# These all work:
get("kitchen_temp")           # matches sensor.kitchen_temperature
get("living_room_motion")     # matches binary_sensor.living_room_motion
history("front_door", "12h")  # matches lock.front_door

Keyboard Shortcuts

KeyAction
EnterExecute current line
Up / DownNavigate command history
Ctrl+LClear output
Ctrl+CCancel / clear input
TabAuto-complete entity names

Python API Reference

All functions are available at the top level — no imports needed.

State & Entities

FunctionDescription
ls()List all entities. Optional: ls("sensor") to filter by domain.
get(entity)Get full state + attributes for an entity. Supports auto-resolve.
state(entity)Get just the state value as a string.
attrs(entity)Get just the attributes dict.
attr(entity, key)Get a single attribute value.
show(value)Explicitly render any value with rich auto-display.

History & Diagnostics

FunctionDescription
history(entity, period)Fetch state history. Period: "1h", "6h", "1d", "7d".
changed(entity, period)List state changes with timestamps.
last_changed(entity)When the entity last changed state.
Auto-render Calling history() on a numeric sensor automatically renders an ECharts timeline. Binary sensors get lane-style charts.

Calendar Events

FunctionDescription
events(calendar, period)Fetch upcoming events. Period: "24h", "7d", etc.

Returns a list of CalendarEvent objects with these fields:

FieldTypeDescription
summarystrEvent title
startstrStart time (ISO 8601 or date)
endstrEnd time (ISO 8601 or date)
descriptionstr or NoneEvent description
locationstr or NoneEvent location
all_dayboolWhether this is an all-day event
# Upcoming 24 hours
events("calendar.home", "24h")

# Next 7 days from work calendar
events("calendar.work", "7d")

# Auto-renders as a colour-coded event timeline
Rich rendering Calendar events auto-render with colour-coded cards showing time, summary, location, and an all-day badge where applicable.

Rooms & Services

FunctionDescription
rooms()List all rooms/areas and their entity counts.
room(name)List all entities in a room.
services(domain)List available services. services("light")

Utilities

FunctionDescription
ago(period)Convert period string to datetime. ago("6h")
now()Current datetime.
count(domain)Count entities in a domain.
domains()List all entity domains.
find(pattern)Fuzzy search entities by name/ID.

Charts

FunctionDescription
chart(entity, period)Explicit chart rendering for an entity.
compare([entities], period)Multi-entity overlay chart.
# Compare two sensors on one chart
compare(["sensor.indoor_temp", "sensor.outdoor_temp"], "24h")

# Explicit chart for a binary sensor
chart("binary_sensor.front_door", "12h")

AI Analyst

Signal Deck includes a built-in AI analyst that connects to any HA Conversation agent (Ollama, OpenAI, Google, local models). It can read your entity states and answer questions about your home.

Configure the analyst entity in your card YAML:

type: custom:signal-deck
analyst_entity: conversation.ollama  # or any conversation agent

Then use the analyst button in the REPL toolbar, or ask directly:

# The analyst sees your current HA state and can run commands
# to investigate. It works best with questions like:
# "Why is the kitchen temperature rising?"
# "Which lights are on right now?"
# "Show me the front door history for today"
Works with any Conversation agent The analyst uses HA Conversation, so it works with whichever LLM you already have configured — cloud or local.
Signal Deck — AI Signal Analyst conversation
AI Signal Analyst conversation

Architecture

Signal Deck is built in three layers with strict boundaries:

┌────────────────────────────────────────────────┐ │ TypeScript (Lit Element) │ │ Lovelace card · HA WebSocket · UI rendering │ │ Event subscriptions · Security · Auth │ ├────────────────────────────────────────────────┤ │ Rust Shell Engine (compiled to WASM) │ │ REPL state · Command parsing · Magics │ │ Output shaping · Render specs · Data transforms │ ├────────────────────────────────────────────────┤ │ Monty (Python runtime, sandboxed) │ │ Executes user Python snippets only │ │ Called by Rust · No direct HA access │ └────────────────────────────────────────────────┘

Data Flow

  1. User types a command in the REPL
  2. TypeScript passes input to the Rust WASM engine
  3. Rust parses, determines if HA data is needed, returns a host call request
  4. TypeScript fetches data via HA WebSocket API
  5. Rust processes data and returns a render spec (JSON)
  6. TypeScript renders the spec as cards, tables, or ECharts

Security Model

  • Read-only by default — all state access is read-only
  • No direct HA access from WASM — all I/O goes through TypeScript host functions
  • No filesystem or network — the WASM sandbox prevents all external access
  • Service calls require armingha.arm() must be called before any service call
  • Auth stays in TypeScript — HA auth tokens never reach WASM

Development

Prerequisites

  • Rust (stable) + wasm-pack
  • Node.js ≥ 18 + npm
  • A Home Assistant instance for testing

Building

# Clone the repo
git clone https://github.com/rsr5/signal-deck.git
cd signal-deck

# Install JS dependencies
npm install

# Build WASM + TypeScript
npm run build

# Or build each layer separately:
npm run build:wasm    # Rust/WASM only
npm run build:ts      # TypeScript/Rollup only

Dev Mode

# Watch mode (rebuilds on change)
npm run dev

# Copy dist/signal-deck.js to your HA config/www/ folder
# and add as a resource in Lovelace

Testing

# Run all tests
npm run test:all

# Rust tests (144 tests)
npm run test:rust

# TypeScript tests (19 tests)
npm run test

Project Structure

signal-deck/
  crates/shell-engine/     # Rust WASM engine
    src/
      lib.rs               # Entry point + host ABI
      eval.rs              # Expression evaluator
      magic.rs             # Magic commands + :help
      render.rs            # Render spec generation
      calendar.rs          # Calendar event handling
  src/                     # TypeScript
    card.ts                # Lovelace card element
    repl.ts                # REPL UI component
    renderers/             # Render spec renderers
    assistant/             # AI analyst integration
  docs/                    # This documentation site
  dist/                    # Built output

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Three-layer rule Signal Deck has strict architectural boundaries. REPL logic belongs in Rust. HA I/O belongs in TypeScript. Python execution belongs in Monty. Please read Architecture before submitting a PR.

FAQ

How big is the bundle?

The JS bundle is ~2 MB and the WASM module is ~3.1 MB. Both are loaded lazily and cached by the browser. The WASM file uses content-hash cache busting for reliable updates.

Does it need a backend?

No. Signal Deck runs entirely in the browser using the HA WebSocket API. There is no custom integration or backend component to install.

Is it safe?

Yes. All Python runs in a WebAssembly sandbox with no filesystem or network access. State access is read-only by default. Service calls require explicit arming.

Which Python version does Monty support?

Monty implements a subset of Python 3 sufficient for data exploration — variables, functions, loops, list comprehensions, dicts, f-strings, and more. It is not a full CPython.

Can I use it with my existing dashboards?

Absolutely. Signal Deck is a standard Lovelace card. Add it to any view alongside your existing cards. The overlay mode gives you a floating panel that doesn't take up card space.

Does the AI analyst send data to the cloud?

That depends on your Conversation agent. If you use a local model (Ollama, llama.cpp), everything stays local. Cloud-based agents (OpenAI, Google) will process data on their servers.

Which Home Assistant version do I need?

Signal Deck requires Home Assistant 2024.1.0 or later for WebSocket API compatibility.

Can I run automations from the REPL?

Service calls are supported but gated behind an arming mechanism for safety. You must call ha.arm() before any service call, and a confirmation dialog is shown.

Changelog

See CHANGELOG.md for the full release history.

v0.1.0-alpha.1

Initial alpha release with:

  • Embedded Python REPL (Monty via WebAssembly)
  • Rust shell engine with magic commands and render specs
  • Full Python API: state, history, calendar events, rooms, services, charts
  • ECharts visualisations with auto-render
  • AI analyst integration via HA Conversation
  • Embedded and overlay display modes
  • Entity auto-resolve and rich entity cards
  • HACS-compatible packaging
⚠️ Early Development Signal Deck is in early alpha. APIs, commands, and configuration may change between releases. It is not yet battle-tested and should not be relied upon for critical automations.

Disclaimer: Signal Deck can interact with your Home Assistant instance, including calling services that control devices. Use at your own risk. The authors are not responsible for any damage, data loss, or unintended actions resulting from its use. See the MIT License for full terms.