DeepSeek Harness plugin

dsh-smarthome

Home Assistant control behind an approval gate: read entity states, query history, and call services.

Jump to install

Source facts

Repository
YLifeOnlyOnce/dsh-smarthome
Latest update
Aug 19, 2026
Category
Tools & Capabilities
GitHub stars
5
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/YLifeOnlyOnce/dsh-smarthome
Plugin: dsh-smarthome
Author: YLifeOnlyOnce

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

<p align="center"> <img src="docs/assets/banner.png" alt="dsh-smarthome" width="820"> </p>

<p align="center"> <b>Home Assistant control for <a href="https://github.com/deepseek-ai/deepseek-harness">DeepSeek Harness</a> agents.</b><br> Read entity states · query history · call services — every state-changing call sits behind a human approval gate. </p>

<p align="center"> <a href="README.zh.md">中文</a> · <a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/dsh--plugin-ecosystem-4d7cfe" alt="dsh-plugin"></a> · <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT"></a> · <a href="https://github.com/YLifeOnlyOnce/dsh-smarthome/actions/workflows/ci.yml"><img src="https://github.com/YLifeOnlyOnce/dsh-smarthome/actions/workflows/ci.yml/badge.svg" alt="CI"></a> </p>

<p align="center">Zero runtime dependencies beyond the harness itself. Uses Home Assistant's built-in REST API — no MQTT, no WebSocket, no extra daemon.</p>

---

✨ What it looks like

Click any image to open the live demo — [docs/demo.html](docs/demo.html) simulates the full DSH conversation, and its live console talks to the bundled HA emulator (no real Home Assistant needed).

① Ask② Approval gate③ Done — state changed
<img src="docs/assets/demo-start.png" width="380" alt="start"><img src="docs/assets/demo-approval.png" width="380" alt="approval"><img src="docs/assets/demo-final.png" width="380" alt="final">
The agent lists your lights with ha_list_entities.ha_call_service pauses for a human approval dialog.Approved — ha_get_state confirms the light turned on.

And the Web UI dashboard card — call ha_dashboard and get a live snapshot of the whole home rendered right in the conversation:

<p align="center"><img src="docs/assets/dashboard.png" width="420" alt="home dashboard"></p>

The Home Assistant it plugs into — a typical smart-home dashboard like this one (illustration):

<p align="center"><img src="docs/assets/ha-mockup.png" width="680" alt="Home Assistant dashboard illustration"></p>

🎯 What can it do?

Talk to your home the way you talk to an assistant — every write goes through a human approval gate first.

You sayWhat happens
"Check the whole house — which devices are still on?"Agent scans with ha_list_entities / ha_get_state and summarizes
"Show me the home dashboard."ha_dashboard renders a live dashboard card in the conversation — devices, scenes and recent changes at a glance
"Wait until the washer finishes, then tell me on my phone."ha_wait_for_state polls to completion → ha_notify pushes to HA
"What's the weather tomorrow — should I take an umbrella?"ha_weather returns a structured forecast
"Set the bedroom light to 200 brightness."ha_call_serviceapproval dialog → executes → state updates instantly
"Turn off every light in the living room."Area targeting — one call controls the whole room
"Start cinema mode."Scene activation: dimmed lights + TV on — a whole cascade of devices in one shot (ha_events shows each change live)
"What changed in the house in the last hour?"Real-time state_changed events from the WebSocket feed
"Is the living room warm enough? Compare with the bedroom."ha_get_state / ha_render_template over sensors
"Turn everything off, I'm leaving."One scene (scene.away) or a multi-entity service call

💡 Why it's good — how useful is it?

  • One-line install: dsh plugin --profile web add dsh-smarthome, then just talk to the agent.
  • Safe by default: every state-changing call stops for human approval; allowedDomains is a second deny-list belt. The agent can never touch your home without you saying yes.
  • Natural language control: no apps to fiddle with, no API docs to memorize — "dim the lights" just works.
  • Always current: state changes reach the agent in real time over WebSocket, so it never "thinks" the light is still on when you switched it off.
  • Lightweight: zero runtime dependencies — plain REST + Node's built-in WebSocket. No MQTT broker, no extra daemon.
  • Try it without Home Assistant: the repo ships a demo emulator + interactive demo page — 5 minutes to a full feel of the plugin.
  • Engineered, not hacked together: 36 tests including a full real agent-loop end-to-end suite, strict TypeScript, CI.

💻 Your computer is the control center

dsh-smarthome runs right where dsh runs — on your computer. No phone app, no separate bridge, no context switch:

  • 👀 Monitor while you work — the dashboard card (ha_dashboard) and the real-time event feed (ha_events) keep the whole house visible next to your editor: what's on, what just changed.
  • 🎙️ Control by voice — add a community voice plugin to dsh (search the dsh-plugin topic for voice; e.g. dsh-voice does zero-key speech input + read-aloud, dsh-voice-chat does real-time speech) and just speak: "turn the bedroom light to 200" → approval → done. Hands-free while you keep typing.
  • 🖥️ Everything in one window — code, watch the house, and control devices without ever leaving dsh. Every state-changing call still waits for your approval.

🛠 Features

ToolDescriptionApproval
ha_healthVerify the connection; return instance name, version, timezone, WebSocket statusread
ha_list_entitiesList entities, filter by domain (light, switch, sensor…) and textread
ha_list_areasList rooms (areas) via the WebSocket API, e.g. living_roomread
ha_list_devicesList physical devices via the WebSocket device registryread
ha_get_stateFull state + attributes of one entityread
ha_historyState-change timeline over a time windowread
ha_eventsRecent real-time state changes buffered from the WebSocketread
ha_list_scenesList one-click scenes (cinema, goodnight, away…)read
ha_dashboardFull home snapshot rendered as a dashboard card in the Web UIread
ha_wait_for_statePoll until an entity matches / stops matching a state (washer done, temperature reached…)read
ha_notifySend a notification via Home Assistant (persistent / phone / speaker)no gate
ha_weatherCurrent weather + structured forecast from the weather entityread
ha_call_serviceCall any service — by entity, by area (whole room), by device, or sceneask
ha_render_templateRender a Jinja2 template server-sideask

Example prompts:

> "Check that Home Assistant is reachable, then list the lights in the living room." > > "Set the living room light to 60% brightness." (triggers an approval request) > > "Show me the boiler switch history for the last 24 hours." > > "Turn off every light in the bedroom." (area targeting — one call, whole room) > > "Start cinema mode." (scene activation — lights dim, TV turns on) > > "What changed in the house in the last hour?" (real-time ha_events)

📦 Install

Requires dsh ≥ 0.1.0-rc.6 (current npm latest).

# From npm (recommended — prebuilt):
dsh plugin --profile web add dsh-smarthome

# Or from GitHub (source install — pnpm builds on the fly):
# dsh plugin --profile web add github:YLifeOnlyOnce/dsh-smarthome
# If pnpm refuses to run the prepare build on a git dependency, allow it once:
#   add this to <profile>/pnpm-workspace.yaml, then re-run the add:
#     allowBuilds:
#       dsh-smarthome: true

Restart dsh --profile web after installing. Manage it in Settings → Plugins.

🧪 Try it without Home Assistant (demo mode)

No HA instance? The repo ships a fake HA emulator with a small living demo home whose state actually changes when you call services — perfect for trying the plugin before wiring up real hardware.

git clone https://github.com/YLifeOnlyOnce/dsh-smarthome
cd dsh-smarthome
pnpm install
pnpm demo:ha          # serves a fake Home Assistant at http://127.0.0.1:8124

In another terminal, configure the plugin (add to your profile's cordis.patch.yml):

- id: smarthome
  config:
    baseUrl: http://127.0.0.1:8124
    tokenEnv: HOME_ASSISTANT_TOKEN

Then start dsh and try:

HOME_ASSISTANT_TOKEN=demo-token dsh --profile web

> "Check that Home Assistant is reachable, then list the lights." > > "Turn on the bedroom light at 200 brightness." — an approval request pops up; approve it, and ha_get_state will show the light is actually on with brightness: 200. > > "Turn off every light in the living room." — area targeting via the WebSocket area registry. > > "What changed in the last minute?" — real-time state_changed events from the WebSocket feed.

The emulator also drifts the temperature sensor every few seconds, so ha_history and ha_events always have fresh data. Any Bearer token works; demo-token is just the convention.

Want to preview the UI without running dsh at all? Open [docs/demo.html](docs/demo.html) in a browser: it replays a simulated DSH conversation (tool cards + the approval dialog), and its live console talks to the emulator directly when it's running.

Ready-to-paste configs (demo / real HA / no-approval) live in [examples/cordis.patch.yml](examples/cordis.patch.yml).

⚙️ Configuration

Create a long-lived access token in Home Assistant: Profile → Security → Long-lived access tokens.

Override the plugin row in your profile's cordis.patch.yml (later layers win):

- id: smarthome
  config:
    baseUrl: http://192.168.1.10:8123   # your Home Assistant instance
    token: ''                           # prefer tokenEnv over committing a token
    tokenEnv: HOME_ASSISTANT_TOKEN      # env var holding the token
    timeoutMs: 15000
    requireApproval: true               # human approval for state-changing calls
    allowedDomains: []                  # e.g. ["light", "switch"]; empty = all domains
    maxHistoryEvents: 200
    wsEnabled: true                     # real-time events + area registry (WebSocket)
    eventBufferSize: 50                 # rolling ha_events buffer size

Then run dsh with the variable set:

HOME_ASSISTANT_TOKEN=<token> dsh --profile web

baseUrl defaults to http://homeassistant.local:8123 (the standard Home Assistant mDNS host). If no token is configured the plugin still loads — every tool call fails with a clear "not configured" message instead of crashing the harness.

How the token is resolved

tokenEnv is a credential reference resolved through the harness's credential seam: when the credentials service is present, the value is read from its layered sources (process environment → <cwd>/.env$DSH_HOME/.env), falling back to process.env directly otherwise. The token is re-resolved per request / per socket connection, so a rotated credential reaches the very next call without a restart.

🔒 Security

  • A Home Assistant token can control everything in your instance — there is no per-entity scope. That is why requireApproval defaults to true and ha_call_service / ha_render_template always route through the harness approval seam.
  • allowedDomains is a second belt: when set, service calls on other domains are denied outright.
  • Prefer tokenEnv over token so the secret never lands in a committed config file.

🛠 Development

pnpm install
pnpm typecheck   # strict TS against the published @deepseek-ai/* types
pnpm build       # bundle lib/ (ESM + d.ts)
pnpm test        # 24 tests: client suite + real ToolRuntime integration + full agent-loop E2E
node scripts/capture-demo.mjs   # regenerate the README screenshots

📋 Compatibility

Real Home Assistant compatibility

  • Uses the v1 REST API (/api/states, /api/services/…, /api/history/…, /api/template, /api/config) and the WebSocket API (/api/websocket: auth, subscribe_events, config/area_registry/list, config/device_registry/list) — the same protocols the official HA frontend speaks.
  • Requires a long-lived access token (Profile → Security → Long-lived access tokens).
  • Caveats: self-signed HTTPS certificates are not supported (use http:// or a valid cert); a restricted token that cannot call services will fail ha_call_service.

DeepSeek Harness is in developer preview and changes fast. This plugin is verified against the published @deepseek-ai/dsh@0.1.0-rc.7 line; if a harness update breaks it, please open an issue.

📄 License

MIT