Skip to main content

HAAnim

CI hacs_badge PyPI Documentation License

Write Home Assistant automations in Python. An automation is a folder with a main.py; decorators say when its functions run, and the haa object reaches entities, services, storage and the automation's own dashboard card.

from haanim import StateEvent, TimeEvent, haa, on_state, on_time


@on_state("sensor.temperature > 30")
async def high_temperature(event: StateEvent):
    await haa.service.notify.mobile_app(message=f"It is {float(haa.entity.sensor.temperature)}°C")


@on_time("09:00", day_of_week="weekdays", when="person.john == 'home'")
async def morning(event: TimeEvent):
    await haa.service.light.turn_on(entity_id="light.bedroom", brightness=150)

What you get

  • Triggers: time (including sunrise and sunset), interval, cron, Home Assistant events and state expressions, each with optional constraints (time of day, date range, day of week, state).
  • Actions that can be run by hand, by a service, by another automation or by a trigger, with DROP, QUEUE and CANCEL execution modes, timeouts and a concurrency limit.
  • haa: entity access, service calls, sleep and wait_for, persistent variables, assets, calling and controlling other automations.
  • A sensor per automation (sensor.haanim_<id>: on, off, error) with status attributes.
  • A dashboard card (custom:haanim-card) that the automation titles and fills with text, images, values, live entities and buttons, plus a management panel in the sidebar with each automation's controls, actions and log.
  • Hot reload: edit a file and the automation is reloaded.
  • A test harness: test an automation with pytest, with no Home Assistant running.

The interpreter keeps automations from blocking Home Assistant by accident (no blocking I/O, an import allowlist, loops that yield). It is a guard rail, not a sandbox: an automation can do whatever Home Assistant can. Only install automations you trust.

Installation

HAAnim needs Home Assistant 2026.9 or newer.

  1. Install the integration with HACS: HACS → ⋮ → Custom repositories, add https://github.com/valsr/haanim as an Integration, then download HAAnim.
  2. Restart Home Assistant.
  3. Settings → Devices & services → Add integration → HAAnim.

That is all: a release of the integration has the HAAnim engine in it, so no Python package has to be installed into Home Assistant.

To install by hand, download haanim.zip from a release and unpack it into <config>/custom_components/haanim. Copying custom_components/haanim out of a checkout of the repository is not enough, because the engine is not in that folder there; build the folder to copy with python scripts/build-integration.py --folder OUT.

Automations live in /config/haanim/automations/ by default. The folder, the rescan interval, the limits and the import options are set under Configure on the integration.

Your first automation

Create /config/haanim/automations/hello/main.py:

from haanim import ActionEvent, action, haa, startup


@startup
def ready(event: ActionEvent):
    haa.card.add_element(haa.card.create_text("hello", "## Hello\nPress the button."))
    haa.card.add_element(haa.card.create_button("greet", label="Greet", action="greet"))


@action
async def greet(event: ActionEvent):
    await haa.service.persistent_notification.create(message="Hello from HAAnim")

Within the rescan interval the automation is running: sensor.haanim_hello is on, and the action can be run from the HAAnim panel, with the haanim.run_action service, or from the automation's card:

type: custom:haanim-card
automation_id: hello

The automation guide covers everything an automation can do, and examples/ has complete automations with tests, among them a demo for each part of HAAnim. The same documentation is built for Read the Docs from docs/ (mkdocs.yml).

Testing an automation

The engine is also a Python package, haanim, for your own machine: it gives your editor completion and types for from haanim import ..., and the test harness. It is not needed in Home Assistant.

pip install haanim pytest pytest-asyncio

The package needs Python 3.14, the Python that Home Assistant 2026.9 runs on.

from haanim.testing import AutomationHarness


async def test_greeting():
    async with AutomationHarness("automations/hello") as automation:
        await automation.press("greet")
        assert automation.service_calls("persistent_notification.create")[0].data == {
            "message": "Hello from HAAnim"
        }

The harness runs the automation with the same interpreter and triggers as Home Assistant, against a fake Home Assistant whose clock only moves when the test moves it. Installing the package does not install Home Assistant.

Services

Service Data What it does
haanim.run_action automation_id, action, data Runs an action; returns its result as response data
haanim.enable automation_id Enables and starts the automation
haanim.disable automation_id Stops and disables the automation
haanim.start automation_id Starts the automation
haanim.stop automation_id Stops the automation
haanim.restart automation_id Restarts the automation
haanim.reload automation_id (optional) Rescans now and reloads one automation, or all
haanim.list_automations - Returns ID, name, state and enabled flag of every one
haanim.list_actions automation_id Returns the automation's actions
haanim.clear_log automation_id (optional) Empties the log HAAnim keeps for one automation, or all
haanim.set_log_level automation_id, level Sets the automation's log level; default takes it away

Development

git clone https://github.com/valsr/haanim.git
cd haanim
uv sync --all-extras

uv run pytest                                         # Python tests, frontend tests and the coverage gate
uv run python scripts/check-public-api-coverage.py    # the automation-facing API must be at 100%
scripts/test-frontend.sh                              # only the JavaScript tests (needs node 22+)
uv run black --check . && uv run pylint custom_components src
uv run mypy custom_components src && uv run pyright src custom_components examples

A Home Assistant with the integration, the package and the examples, in a container:

./build-and-run.sh                     # http://localhost:8123, user admin, password admin
uv run python scripts/e2e-smoke.py     # end-to-end checks against that container

The engine has one source, src/haanim. In a checkout the integration imports it as the installed haanim package (uv sync installs it in place). A release carries a copy of it inside the integration:

uv run python scripts/build-integration.py    # dist/haanim.zip: what a GitHub release attaches and HACS installs

The repository:

Path What is there
src/haanim/ The engine: interpreter, triggers, dispatcher, haa. No Home Assistant imports
src/haanim/testing/ The test harness and the fakes it is built on
custom_components/haanim/ The integration: entity, services, options, websocket commands, frontend
examples/ Example automations and their harness tests
tests/ engine/ (no Home Assistant), integration/, frontend/
docs/ The documentation (built with MkDocs) and notes on the development environment

See CONTRIBUTING.md before sending a pull request.

License

MIT, see LICENSE. HAAnim is a custom integration and is not supported by the Home Assistant project.

Metadata

Release files for haanim 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for haanim 0.2.0
File Size Uploaded
haanim-0.2.0.tar.gz 138.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for haanim 0.2.0
File Interpreter ABI Platform
haanim-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 307.2 kB

Release files / haanim-0.2.0.tar.gz

Download URL haanim-0.2.0.tar.gz
Size 138.0 kB
Tags Source
SHA-256 checksum
How to use checksums
e7891f36f99b3341a63b84979d8efc9c6ba9df7ff6c50a117de18daec07dcd7c
BLAKE2b-256 checksum
How to use checksums
325b32285b8a1ca329af459b16de980eb2e97c974bacadde88f23305b19157be
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / haanim-0.2.0-py3-none-any.whl

Download URL haanim-0.2.0-py3-none-any.whl
Size 169.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8db1c8034aef6de7bba3f8bfbddba1ac93a22dc06a1431fd33454c96ae94378
BLAKE2b-256 checksum
How to use checksums
865503874b43f43c3823b7e0dfce2d4d03191da3b526a8734fc2788159ce309d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page