CtrlK
BlogDocsLog inGet started
Tessl Logo

jbaruch/hubitat-dev

Context for developing and debugging Hubitat Elevation apps, drivers, and hub environment — sandbox constraints, lifecycle idioms, capability contracts, plus grounded deploy/log-tail/lint mechanisms.

74

Quality

93%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

SKILL.mdskills/device-removal/

name:
device-removal
description:
Safely remove a Hubitat device — enumerate where it's used, warn about the blast radius before deleting, verify references cleared after, and re-wire them onto a replacement device. Use when the user wants to remove, delete, retire, or replace a device, or asks what a device is used by before deleting it.
argument-hint:
[device-id or name] [--hub <name>]

Device-Removal Skill

Process steps in order. Do not skip ahead.

Removing a device is effectively irreversible, and a replacement gets a new device id that strands every prior reference (rules/device-lifecycle.md). This skill enumerates usage, warns before the delete, verifies after, and restores references onto a replacement.

Step 1 — Enumerate the device's usage

Read the hub's own usage list. Pass the device id, or --name "<display name>" to let the script resolve the id from /hub2/devicesList (exact match — it fails clearly on zero or multiple matches; do not resolve the name yourself):

python3 .tessl/plugins/jbaruch/hubitat-dev/skills/_scripts/hub_device_usage.py --device <id> --ip <addr>
python3 .tessl/plugins/jbaruch/hubitat-dev/skills/_scripts/hub_device_usage.py --name "<display name>" --ip <addr>

Use --hub <name> instead of --ip to resolve via hubs.json (hub-config skill). Argument and output contract: skills/_scripts/hub_device_usage.py module docstring. The report splits appsUsing by the app's enabled/disabled switch state and lists dashboards, parentApp, and child devices. This is the reference blast radius. Enabled does not prove a live consumer. Proceed to Step 2.

Step 2 — Warn with the concrete blast radius

State the actual references, never a bare count — name every enabled and disabled app reference, dashboard, parent app, and child device. Describe enabled/disabled as app switch state, not liveness. If deciding which configured reference currently drives behavior, rerun Step 1 with --live. Its unknown verdict must stay unknown. If nothing references the device, say so and proceed. Do not delete anything in this step. Proceed to Step 3.

Step 3 — Branch on retire vs replace

Ask whether the device is being retired (gone for good) or replaced (new hardware stands in). On replace, the Step 1 report is the capture of memberships to restore — keep it.

Retiring — proceed to Step 4.

Replacing — move the references now, before the delete in Step 4: Skill(skill: "device-migration"). Settings → Swap Device needs the old device to still exist, and this skill's Step 4 destroys it. Migrating after the delete forfeits the swap and forces the virtual/manual fallback (rules/device-lifecycle.md).

Where the hardware forces the old device out first — a radio exclusion, or reusing its physical slot — the replacement cannot exist yet, so there is nothing to swap to: device-migration parks the references on a virtual device instead. Take that path there, then return here. Proceed to Step 4 once the references are off the old device.

Step 4 — Guide the removal

Deletion is irreversible — the user performs it, not the agent. Navigate to the device's remove control with Playwright and read the "in use by N apps" confirm dialog (skills/_reference/playwright-ui.md), then have the user confirm the final removal. A radio (Z-Wave/Zigbee) device also needs a physical exclusion/factory-reset only the user can do (rules/zwave-zigbee-mesh.md). An app with removeButton:false (e.g. HubiThings Replica) is remove-not-automatable — tell the user. Proceed to Step 5.

Step 5 — Verify references cleared

Re-run the Step 1 command. Do not assume the hub auto-pruned — a reference that survives the delete (a dashboard tile, a device input, a parent/child link) is a dangling pointer to fix on the referencing app. Report what cleared and what did not. If retiring, finish here.

Step 6 — Land a parked migration

Only when Step 3 parked the references on a virtual device. The replacement now exists, so the references still sitting on the virtual have to reach it: return to Skill(skill: "device-migration") for the second hop and its verification, and delete the virtual device once it is empty.

If Step 3 migrated the references directly, they are already on the replacement and Step 5 verified them — nothing is left here. Finish here.

README.md

tile.json