Repository navigation
v0.60.0
This release completes the Log Identity milestone (milestone 17, design). Every app instance now has one name you choose, and that name drives its logger names and owner identity. Every log line records who wrote it, which app it is about, and which handler or job run produced it, as separate facts. Log views default to your apps' lines plus Hassette's errors. The rest are one opt-in away, and framework lines are marked. The milestone's breaking changes are listed first; the Upgrading page has the migration steps. Instance Identity, which re-keys stored history and routes on the instance name, comes next.
Breaking Changes
instance_nameis required and unique — a configured app instance withoutinstance_namenow fails at config load, and so does a duplicate name anywhere in the config. A valid name starts with a lowercase letter, contains only lowercase letters, digits and_, doesn't end in_, and is at most 128 characters. Old generated defaults likeMyApp.0are gone, so cache keys, eventsourcecomparisons and logger names built from them change.AppTestHarnessnow requires aconfigthat setsinstance_name. Addinstance_nameto every[hassette.apps.<key>]entry (and every multi-instance entry) and update anything that matched the old names. (#3146)- App loggers are now
hassette.apps.<instance_name>— lifecycle lines about an app (starting, stopping, hook failures, readiness) come fromhassette.apps.<instance_name>.Lifecycle, followlogging.app_handlerinstead of the app'slog_level, and are markedframeworkrather thanapp. Setlogging.app_handler = "DEBUG"to see an app's lifecycle detail at DEBUG. Update any logging config or filters that target the old logger names. (#3173, #3146) source_tieron log records is nowauthor—LogEntry.source_tier(wire,GET /api/logs/recent,GET /api/executions/{execution_id}) is nowLogEntry.author,"app"or"framework". Thesource_tierquery parameter on the log routes is replaced byauthor(all,apporframework); a straysource_tieris ignored and the default view applies.HassetteClient.get_recent_logs(source_tier=...)is nowauthor=...,get_execution_logsacceptsauthor, and the client requires API schema 3.hassette log --source-tieris now--author, andhassette executionaccepts--author. Existing log history keeps its meaning through an automatic one-way migration. (#3197)- Log views hide Hassette's routine lines by default — with no
author, log queries,hassette log, and every web UI log view return app-authored lines plus framework lines at ERROR and above, where they previously returned everything. Passauthor=all(API and client),--author all(CLI), or tick "all framework lines" in a log view's footer (web UI) to see the rest. (#3197) - App autodetection is removed —
apps.autodetectandapps.exclude_dirsare gone, soHASSETTE__APPS__AUTODETECTandHASSETTE__APPS__EXCLUDE_DIRSnow fail startup as unknown keys; delete them. Every app needs a[hassette.apps.<key>]entry, including apps built on a shared base class, or it won't run. An autodetected app's history stays under its old key (<apps dir name>.<module path>.<ClassName>, e.g.apps.lights.LightsApp, the key the Apps page shows) and is listed as not in the current config until retention clears it. To keep that history, reuse the old key as a quoted table name, e.g.[hassette.apps."apps.lights.LightsApp"]. Theauto_loadedfield in app API responses is deprecated and alwaysfalse; it will be removed in a future release (#3161). (#3158)
For App Authors: You Can Now Delete
- Raising
logging.bus_service,logging.scheduler_serviceand similar globally to debug one app — setframework_log_levelon that app's config to see Hassette's lines about just that app. (#3178) - Workarounds for
get_state_value()andget_attribute()underAppTestHarness— code that was rewritten to callget_state(), or tests that hand-mocked those two calls, can go back to the natural calls, async or viaself.api.sync. (#3132) - Hand-mocked
get_state_raw()andget_states_raw()in tests — seed the entities and read them throughRecordingApi. (#3130)
Logging
- Each log line now records its author (your app's code, or Hassette), its subject (the app instance it is about) and its execution (the handler or job run) independently. Author comes from the logger that wrote the line, never from the subject, so Hassette's lines about your app (lifecycle, hook failures, executor errors) are no longer shown as the app's own output. Warnings raised by Hassette packages are framework-authored; your own warnings stay yours. (#3173)
- Console log lines drop the
key=valuetail and print one identity column before the message: the instance name,hassette:<instance_name>when the framework wrote a line about that app, or the logger name for lines with no app. During a handler or job run it ends in@plus the last 8 characters of the execution ID, the same short ID the web UI shows. Everything the column drops is still in JSON output and the telemetry database. (#3203) - New
log_format = "compact"prints the console layout with anHH:MM:SStimestamp and no level padding. The Home Assistant add-on uses it so the Supervisor Log tab reads on a phone.autonever picks it. (#3203) - New
framework_log_levelonAppConfigsets the level for every Hassette logger one app instance owns: its lifecycle logger and its Bus, Scheduler, Api, StateManager and TaskBucket loggers.log_levelstill governs only the app's own logger. Unset, nothing changes. Shared services such asCommandExecutorhave no owning app and keep theirlogging.*levels. (#3178) - Web UI: the All / Apps / Framework toggle and its
?tier=URL parameter are replaced by one persisted "all framework lines" checkbox shared by every log view. Framework-authored lines carry a "Framework" badge, and the CLI log tables gain an Author column. (#3197) - Docs: the log-levels page explains which logger and level field governs each kind of line about an app, how to read the console identity column, restarts, and the API port. (#3182)
Apps & Configuration
- At startup, Hassette scans the apps directory without importing anything and warns about each
Appsubclass no entry configures, with a paste-ready[hassette.apps.<key>]section. Suggested keys avoid configured keys and each other, so pasting every snippet gives a config that loads. Setapps.warn_unconfigured = falseto turn it off. (#3158) - A live config reload that moves an instance name between apps now stops everything it replaces before creating anything, and a reload into a config with duplicate names is rejected while the running config stays in place. (#3146)
Test Utilities
RecordingApisupportsget_state_value()andget_attribute()(with dot paths, returningMISSING_VALUEfor absent attributes), andget_state_raw()andget_states_raw(), which return deep copies of the seeded state. All raiseEntityNotFoundErrorfor unseeded entities. (#3132, #3130)
State Models
self.states.scheduleandself.states.groupresolve to typed models (ScheduleStatewithnext_event, andGroupStatefor legacygroup.*entities) instead ofBaseState. (#3131)
CLI
- Status and health values in the
hassette status,app,app activityanddashboardtables are colored on a terminal and plain when piped;--jsonis unaffected. (#3126, #3150) hassette logtables keep their When, Level, App, Instance and Function columns readable when a message spans several lines, such as a traceback. The Message column now wraps instead of squeezing the others to nothing. (#3147)
Documentation
- Clarified CLI global flag placement, log persistence,
--dev-mode, reload settings, per-app developer overrides, heartbeat timing, and where the web UI token lives. (#3171, #3179, #3159) - Corrected which
call_servicefailureswait_for_acksurfaces (a nonexistent entity ID is only logged by Home Assistant), describedget_state().valueas a converted, domain-typed value, fixed theget_attributedot-path example, and showed the fullAppSynccover example. (#3165, #3180, #3202) - Fixed the First Automation test steps and expected log output, split the cross-app bus example into real modules, and corrected the scheduler migration page's examples. (#3181)
- Added zsh
fpathsetup so shell completion loads. (#3183)