HASSL: Home Assistant Simple Scripting Language
Project description
HASSL
Home Assistant Simple Scripting Language
HASSL is a human-friendly domain-specific language (DSL) for building loop-safe, deterministic, and composable automations for Home Assistant.
It compiles lightweight .hassl scripts into fully functional YAML packages that plug directly into Home Assistant, replacing complex automations with a clean, readable syntax.
🚀 Features
- Readable DSL → write logic like natural language (
if motion && lux < 50 then light = on) - Sync devices → keep switches, dimmers, and fans perfectly in sync
- Schedules → declare time-based gates (
enable from 08:00 until 19:00) - Weekday/weekend/holiday schedules → full support for Home Assistant’s Workday integration (v0.3.1)
- Loop-safe → context ID tracking prevents feedback loops
- Per-rule enable gates →
disable ruleorenable ruledynamically - Inline waits →
wait (!motion for 10m)works like native HA triggers - Color temperature in Kelvin →
light.kelvin = 2700 - Modular packages/imports → split automations across files with public/private exports
- Auto-reload resilience → schedules re-evaluate automatically on HA restart
🧰 Example
Basic standalone script
alias light = light.wesley_lamp
alias motion = binary_sensor.wesley_motion_motion
alias lux = sensor.wesley_motion_illuminance
schedule wake_hours:
enable from 08:00 until 19:00;
rule wesley_motion_light:
schedule use wake_hours;
if (motion && lux < 50)
then light = on;
wait (!motion for 10m) light = off
rule landing_manual_off:
if (light == off) not_by any_hassl
then disable rule wesley_motion_light for 3m
Produces a complete Home Assistant package with:
- Helpers (
input_boolean,input_text,input_number) - Context-aware writer scripts
- Sync automations for linked devices
- Rule-based automations with schedules and
not_byguards
Using imports across packages
# packages/std/shared.hassl
package std.shared
alias light = light.wesley_lamp
alias motion = binary_sensor.wesley_motion_motion
alias lux = sensor.wesley_motion_illuminance
schedule wake_hours:
enable from 08:00 until 19:00;
# packages/home/landing.hassl
package home.landing
import std.shared.*
rule wesley_motion_light:
schedule use wake_hours;
if (motion && lux < 50)
then light = on;
wait (!motion for 10m) light = off
rule landing_manual_off:
if (light == off) not_by any_hassl
then disable rule wesley_motion_light for 3m
This setup produces:
- One shared package defining reusable aliases and schedules
- A landing package importing and reusing those exports
Together, they generate:
- ✅ Shared schedule sensor (
binary_sensor.hassl_schedule_std_shared_wake_hours_active) - ✅ Cross-package rule automations gated by that schedule
- ✅ Context-safe helpers and syncs for both packages
🏗 Installation
git clone https://github.com/adanowitz/hassl.git
cd hassl
pip install -e .
Verify:
hasslc --help
⚙️ Usage
- Create a
.hasslscript (e.g.,living_room.hassl). - Compile it into a Home Assistant package:
hasslc living_room.hassl -o ./packages/living_room/
- Copy the package into
/config/packages/and reload automations.
Each .hassl file compiles into an isolated package — no naming collisions, no shared helpers.
📦 Output Files
| File | Description |
|---|---|
helpers_<pkg>.yaml |
Defines all helpers (booleans, text, numbers) |
scripts_<pkg>.yaml |
Writer scripts with context stamping |
sync_<pkg>_*.yaml |
Sync automations for each property |
rules_bundled_<pkg>.yaml |
Rule logic automations + schedules |
schedules_<pkg>.yaml |
Time/sun-based schedule sensors (v0.3.1) |
🧠 Concepts
| Concept | Description |
|---|---|
| Alias | Maps short names to HA entities (alias light = light.kitchen) |
| Sync | Keeps multiple devices aligned across on/off, brightness, etc. |
| Rule | Defines reactive logic with guards, waits, and control flow. |
| Schedule | Defines active time windows, reusable across rules. |
| Tag | Lightweight metadata stored in input_text helpers. |
🔒 Loop Safety & Context Tracking
HASSL automatically writes the parent context ID into helper entities before performing actions.
This ensures not_by any_hassl and not_by rule("name") guards work flawlessly, preventing infinite feedback.
🕒 Schedules That Survive Restarts
All schedules are restart-safe:
binary_sensor.hassl_schedule_<package>_<name>_activeautomatically re-evaluates on startup.- Clock and sun-based windows update continuously through HA’s template engine.
- Missed events (like mid-day restarts) are recovered automatically.
🗓️ Holiday & Workday Integration (v0.3.1)
HASSL now supports holidays <id>: schedules tied to Home Assistant’s Workday integration.
To enable holiday and weekday/weekend-aware schedules:
1️⃣ Create two Workday sensors in Home Assistant
You must create two Workday integrations through the Home Assistant UI.
Sensor 1 — binary_sensor.hassl_<id>_workday
- Workdays: Mon–Fri
- Excludes:
holiday - Meaning: ON only on real workdays (Mon–Fri that are not holidays).
Sensor 2 — binary_sensor.hassl_<id>_not_holiday
- Workdays: Mon–Sun
- Excludes:
holiday - Meaning: ON every day except official holidays (including weekends).
In both, set your Country and optional Province/Region as needed for your locale (e.g.,
US,CA,GB, etc.).
After setup, rename the entity IDs to exactly match:
binary_sensor.hassl_<id>_workdaybinary_sensor.hassl_<id>_not_holiday
where<id>matches the identifier used in your.hasslfile (e.g.,us_ca).
HASSL derives:
binary_sensor.hassl_holiday_<id>→ ON on holidays (even when they fall on weekends).
Truth table
| Day type | hassl_<id>_workday |
hassl_<id>_not_holiday |
hassl_holiday_<id> (derived) |
|---|---|---|---|
| Tue (normal) | on | on | off |
| Sat (normal weekend) | off | on | off |
| Mon that’s an official holiday | off | off | on |
| Sat that’s an official holiday | off | off | on |
This distinction lets you build precise schedules like:
holidays us_ca:
country="US", province="CA"
schedule master_wake:
on weekdays 06:00–22:00 except holidays us_ca;
on weekends 08:00–22:00;
on holidays us_ca 09:00–22:00;
🧩 Note:
Both sensors must be created manually in the Home Assistant UI — integrations can’t be defined in YAML.
Once created, HASSL automatically references them in generated automations.
⚗️ Experimental: Date & Month Range Schedules
HASSL v0.3.1 includes early support for:
on months Jun–Aug 07:00–22:00;
on dates 12-24..01-02 06:00–20:00;
These may compile successfully but are not yet validated in production.
They’re marked experimental and will be verified after template automation support (v0.4 milestone).
📚 Documentation
🧩 Contributing
Contributions, tests, and ideas welcome!
To run tests locally:
pytest tests/
Please open pull requests for grammar improvements, new device domains, or scheduling logic.
📄 License
MIT License © 2025
Created and maintained by @adanowitz
HASSL — simple, reliable, human-readable automations for Home Assistant.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hassl-0.3.1.tar.gz.
File metadata
- Download URL: hassl-0.3.1.tar.gz
- Upload date:
- Size: 50.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d93491297d61f7bbdd6eb12b41fa9cd2878f1aff913f38f540418ace92eadcaf
|
|
| MD5 |
8183387650d9b3a8b8e75723058b7098
|
|
| BLAKE2b-256 |
d87e946eb14cb4b0f82f6312328d8a299e3ca584bb39f4879915b75490f9dde1
|
File details
Details for the file hassl-0.3.1-py3-none-any.whl.
File metadata
- Download URL: hassl-0.3.1-py3-none-any.whl
- Upload date:
- Size: 46.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c5a3c1e9b80dc0a0d8610c4ea1e703d866cd83ccacce7ac7717732d6f93087a
|
|
| MD5 |
331e350aed257280b0c356372de6dc16
|
|
| BLAKE2b-256 |
998ae98a3c5d54ab5ed1e1fd9e262f2814c53f6febcd4600a6b8fdce9725d5b4
|