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
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Process steps in order. Do not skip ahead.
The always-on Hubitat rules (sandbox-constraints, app-lifecycle, driver-lifecycle, logging-conventions, state-vs-attributes, groovy-gotchas) are already in context — apply them while generating. The capability contract lives in skills/_reference/capabilities.json; the import allow-list in skills/_reference/allowed-imports.txt.
Establish, asking the user only for what is not already clear:
name, namespace (unique — typically the user's handle), authormenu to file it under. Emit definition().menu explicitly (it is not category, and omitting it defaults to Apps and misfiles the app — rules/app-lifecycle.md)Integrations; device / time / presence automation → Automations; utility, manager, or dashboard → AppsProceed to Step 2.
For a driver, for each declared capability read its required commands and attributes from skills/_reference/capabilities.json (capabilities.<Name>.commands[].name, .attributes[].name). Every required command becomes a Groovy method. Marker capabilities (Actuator, Sensor) add no methods.
For an app, decide the preference inputs (see skills/_reference/input-types.md) and the events to subscribe to.
Proceed to Step 3.
Emit one Groovy file wiring in, per the rules:
metadata { definition(...) { capability lines, custom command/attribute } preferences { logEnable/txtEnable } }; installed(), updated() (with runIn(1800, logsOff) when logging), logsOff(); a method for every required command; configure()/refresh() if those capabilities are declared; a parse(String description) with the protocol-appropriate decode and a log.debug of raw input when a protocol is involved.definition(...) with an explicit menu: (Apps | Automations | Integrations, per Step 1 — never let it default), preferences { page { section { inputs } } }, installed() { updated() }, updated() { unsubscribe(); initialize() }, initialize() with the subscriptions, and a handler method for each subscription. Guard chatty logs on logEnable/txtEnable.Write the file to the path the user wants (default <name>.groovy). Proceed to Step 4.
Run the sandbox linter on the generated file and resolve anything it flags:
python3 .tessl/plugins/jbaruch/hubitat-dev/skills/_scripts/hub_lint.py <file.groovy>Contract and finding shape: skills/_scripts/hub_lint.py module docstring. A correct skeleton should lint clean; if a missing-command or unresolved-handler appears, a required method or handler is absent — add it. If no findings, say so and proceed.
The skeleton exists locally but is not on any hub. Offer to deploy it with Skill(skill: "deploy"). Finish here.