Repository navigation
Releases
Releases · rhizomatics/homeassistant-repl
v0.14.1
🐛 Bug Fixes
- The live server loads again on Home Assistant 2026.8.x. 0.14.0 imported
probatio, which Home Assistant only ships from 2026.9
📚 Documentation
- Replaced references to HACS with 'Marketplace'
What's Changed
- Bump the uv group with 2 updates by @dependabot[bot] in #14
- Update uv-build requirement from <0.13.0,>=0.9.18 to >=0.9.18,<0.14.0 by @dependabot[bot] in #15
- Bump ruff from 0.17.1 to 0.17.2 in the astral group by @dependabot[bot] in #13
- Get pre-commit.ci green: codespell typo, skip ty there, hooks on 3.14 by @jeyrb in #16
- CI: publish badges and docs only on push to main by @jeyrb in #19
- Quality Scale: add quality_scale.yaml, owner, parallel updates, removal docs by @jeyrb in #18
- Load on Home Assistant 2026.8: import voluptuous, not probatio by @jeyrb in #17
Full Changelog: v0.14.0...v0.14.1
v0.14.0
This release brings auto-complete for code and the object tree, integrated help/source-code lookup, much improved CLI history and lots more.
✨ Enhancements
Shell History
- A whole statement or block is edited and kept in history as one entry, in live and API modes alike
- Up brings back a complete
forloop,deforwithblock, and any line of it can be changed before running it again - Enter runs the code once it's complete, and the cursor is at the end. Otherwise it starts a new line, indented to match, one level deeper after a
:and one shallower afterreturn,pass,break,continueorraise - A block is ended by an empty line, as before. Alt-Enter (Esc then Enter) runs what's there straight away
- Entries already in the history file from earlier versions are still there, a line each
- Up brings back a complete
Cancel Operations
- Ctrl-C while a command runs stops it, rather than the shell
- Code running inside Home Assistant is stopped there, and its traceback shows where it had got to. A second Ctrl-C stops waiting for it
- Local code stuck in a blocking call is interrupted by a second Ctrl-C
- Also in API mode, for its local code
- Stopping code inside Home Assistant needs the server component at this version
Live Server Controls
- Completion's limits, 500 items and 500 milliseconds an answer by default, are options on the Configure form
- New Stop running code button on the integration's device, stopping whatever is running in every live session
- New
ha_repl_server/cancelwebsocket command, which Ctrl-C in the shell sends - Every command is written to the Home Assistant log at
warning, so it shows by default, with the user who sent it- On a logger of its own,
custom_components.ha_repl_server.commands, to quieten without hiding other warnings - The code run, then its outcome: the value or error, how much output, and how long it took
- Each SQL query, and its row count and time, or its error
- Each stop and reset
- On a logger of its own,
Auto-Completion
- Tab completes names, attributes and keys in both shells, and a menu opens by itself after a
., in a key, and after two letters of a name (RFC 0002, steps 2 and 3)- Nothing is run to complete: no property, call, or lookup in anything but a plain
dict,listortuple, or the object tree - return and property annotations are followed instead obj["completes paths, and entity ids at the root, andobj.find("paths- In live mode, a statement using
hass,objor a variable living in Home Assistant is completed by Home Assistant, from the session itself, even while code runs there. Needs the server component at this version - Local code the walk can't follow, such as a loop variable, is completed by jedi, now a dependency
- What's typed matches anywhere in a name, in any case - names starting with it first
- Inside a call, its signature is shown under the prompt with the argument being typed in bold, and its parameters not yet given complete as
name=(step 5)
- Nothing is run to complete: no property, call, or lookup in anything but a plain
Help
- IPython style help in both shells (step 6)
?on its own: what the shell offers in its mode, and its keysthing?:help(thing), run wherethinglives, sohass?is answered by Home Assistant. Never calls anything to get therething??: file and line of its source, and a link to that line on GitHub at the version running - Home Assistant's release or beta tag, this project's, or Python's- For an attribute its class declares or documents,
thing?gives its declared type and what the class's docstring says about it, rather than help on the value's type -sql.tables?no longer describeslist - Ctrl-Space (or Ctrl-Shift-Space) describes the name under the cursor, or the call it's in - signature and docstring - above the prompt, without running anything
- New
ha-repl inspect EXPR, the same description for an agent, routed asexecis:--jsongives it with the source location,--sourceadds the location to plain text - New
ha_repl_server/completewebsocket command, for completions, signatures (kind: "signature") and source locations (kind: "source"), andha_repl_server/infolists the commands a server has
Object Tree
obj["completes paths, and entity ids at the root, in IPython, Jupyter and Marimo, forobjfromconnect()as well as in live mode (step 1 of RFC 0002)- A registry entry's keys complete as attributes there too:
entity.registry_entry.uni<TAB>
🐛 Fixes
- A connection lost while the shell is open - Home Assistant restarting, say - is reported as
Connection closed, rather than a traceback from the HTTP library, and leaving the shell still works - If
nanoarrowcan't be loaded for SQL results, the live server component will continue to load and onlyhassusage.
📚 Documentation
- RFC 0002 has the results of its step 0 spike, and where
ha-replwould still differ from the Debug console once it's done - New Debug Console page, comparing
ha-replwith the Debug console that Home Assistant 2026.11 adds
What's Changed
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #2
- Potential fix for code scanning alert no. 12: Clear-text logging of sensitive information by @jeyrb in #3
- ci: pin shared admin workflows to rhizomatics/.github 1.0.0 by @jeyrb in #4
- Bump coverage from 7.15.4 to 7.16.2 in the uv group by @dependabot[bot] in #6
- Gitignore personal Claude Code settings by @jeyrb in #7
- Bump certifi to 2026.10.19 for eMudhra distrust by @jeyrb in #8
- Override Home Assistant's uv pin with >=0.13.4 by @jeyrb in #9
- Bump gitpython from 3.2.0 to 3.2.1 in the uv-security group across 1 directory by @dependabot[bot] in #10
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #11
- Declare integration categories in manifest by @jeyrb in #12
New Contributors
- @jeyrb made their first contribution in #3
- @dependabot[bot] made their first contribution in #6
Full Changelog: v0.13.0...v0.14.0
v0.13.0
✨ Enhancements
SQL
- A result column of a Recorder table comes back as what it holds, going by how
db_schemadeclares it- A
_tscolumn (TIMESTAMP_TYPE) and aDATETIME_TYPEcolumn as adatetimein UTC, in place of seconds since the epoch or text context_id_binandcontext_parent_id_binas the ULID text ofcontext.id, andcontext_user_id_binas the user id, in place of bytessql("...", raw=True)leaves every value as the database has it- Needs both the client and the server component at this version
- A
- A result has the
queryit came from
Object Tree
- Actions (services) are in the tree, in an
actionlevel beside each integration's entity domains -obj["/mqtt/action/publish"]- Call one to run it, with its data as keyword arguments and
targetfor what it acts on:obj["/light/action/turn_on"](target={"entity_id": "light.shed"}, brightness=128) - What an action that answers gives back is returned
name,description,fieldsandsupports_responsedescribe it, as doesobj.show(path), with the names and descriptions the frontend shows for the action and each of its fields- The find methods go through actions as well as entities:
obj.find_names(domain="action")gives every action, and a search with nodomainnow gives both object_type="entity"orobject_type="action"keeps a find to the one kind."device"is accepted, for when devices are in the tree- In live, exec and API mode alike. An integration with actions and no entities is now in the tree
- Live mode needs the server component at this version
- Call one to run it, with its data as keyword arguments and
Live Mode
- New
rebind(), to put back any of the shell's own names -hass,obj,sql,hass_api,show,help,MODE,SERVER- that has been assigned over, and run the plugins againrebind(plugins=False)leaves the plugins alone- Also in
ha-repl execand API mode
Live Server
hassandsqlcan each be given a time limit, in minutes, from the integration's Configure form, after which that one is switched off again- Left empty, it stays on, as before
- The limit survives a restart of Home Assistant, and one that ran out while it was stopped is applied when it starts
- Configure shows the minutes left on a running limit, to change or clear
Full Changelog: v0.12.0...v0.13.0
v0.12.0
✨ Enhancements
SQL
- New virtual tables, to query as if they were real ones, in place of the join almost every query on these tables needs
state_historyisstateswith each row'sentity_idas the first columnevent_historyiseventswith each row'sevent_typestatistics_historyandstatistics_short_term_historyarestatisticsandstatistics_short_termwith each row'sstatistic_idsql("select * from state_history where entity_id = 'sensor.outside_temperature'")- They leave out the legacy columns and the join key
- Nothing is created in the Home Assistant database - a virtual table is added to the query as a
withclause when the query mentions it sql.tableslists them, each as aVirtualTableobject rather than aTable, with avirtualflag and the query it stands for as itsdefinition- Needs both the client and the server component at this version
Live Mode
- New
show(thing), to look inside an object that otherwise prints as little more than its class name: its attributes and their values, in colour, one to a lineshow(hass.config),show(hass.states.get("sun.sun"))- Names starting with an underscore are left out unless
private=True, and methods unlessmethods=True - Anything enormous is cut short, with a count of what was left out, so
show(hass.data)is safe -max_items,max_stringanddepthset how much is shown - Nothing new is installed in Home Assistant: the server sends a description of the object, and the shell draws it
- Works on local objects too, and in
ha-repl exec, where it comes back as text
📚 Documentation
- The agent skill and Examples cover querying state history, events and long term statistics, and looking inside objects with
show()
Full Changelog: v0.11.1...v0.12.0
v0.11.1
🐛 Fixes
Live Mode
- A name used only in a type annotation no longer decides which side a statement runs on, and no longer stops it running inside Home Assistant because it "only exists in the local session"
- A bare declaration, such as
hass: HomeAssistant, is no longer treated as an assignment
✨ Enhancements
Plugins
homeassistant_repl.plugindeclaresMODE,SERVER,hass,obj,sqlandhass_apifor linters and type checkers, to import underTYPE_CHECKING- The package now carries a
py.typedmarker
📚 Documentation
- Plugins covers importing a component's own classes, and type checking a plugin
- A link is given to the example Supernotify ha-repl plugin code
Full Changelog: v0.11.0...v0.11.1
v0.11.0
✨ Enhancements
Configuration
- Implementation of RFC-0001: Persistent Config
- Servers can be named in
~/.config/ha-repl/config.tomland chosen with--server NAMEorHASS_SERVER=NAME, withdefaultpicking one when neither is given.--serverstill takes a URL- A server's token comes from the file, from a command (
token_command, for a secrets manager) or from a named environment variable (token_env) HASS_TOKENis only used with a URL, never with a named serverha-repl serverslists the servers configured, without their tokens
- A server's token comes from the file, from a command (
- Python files in
~/.config/ha-repl/plugins/are run at the start of every session, includingha-repl exec, for helper functions and bookmarked expressions.--no-pluginsskips themMODE("live","exec"or"api") andSERVER(the configured server's name) are set, so one file can adapt to where it is running
- A repo can carry its own
.ha-repl/directory, layered over the one in the home directory. It is ignored until allowed withha-repl trust, and again whenever its contents change session,ttlandauto_awaitcan be given defaults inconfig.toml.--auto-awaitis new, to turn it back on for one runhomeassistant_repl.connect()accepts a server name, e.g.connect("house")- See the new Configuration and Plugins pages
API Mode
ApiEntityis closer to the realEntity, so more code works unchanged in bothapiandlivemoderegistryis renamedregistry_entry, and can be read by attribute as well as by key:e.registry_entry.unique_idplatformis still the integration's name as a string, and also hasplatform_nameanddomain- New properties with the real
Entitynames:unique_id,available,enabled,device_class,unit_of_measurement,icon,entity_picture,supported_features,assumed_state,attribution,entity_category,has_entity_nameandtranslation_key - The same applies to
obj.mode("api")in live mode, so the server component needs updating too
📚 Documentation
- Reorganized and improved the configuration and installation
Full Changelog: v0.10.0...v0.11.0
v0.10.0
✨ Enhancements
Help
help()on something local -objin API mode,sqland its results, tables and rows - now gives a short summary of what it is for, its methods, properties and attributes, as it already did for objects inside Home Assistant. Special methods, inherited members, data descriptors and the method resolution order are left outhelp(thing, full=True)gives Python's own full help page, on either sidehelp(obj)explains how to use the object tree- Type annotations in the summary are no longer shown in quotes
SQL
sql.table("states")returns theTableobject for a single table, by nameTableobjects haveclass_nameanddescription, the name and docstring of the class the Recorder maps to the table, e.g.StatesandState change history.- Legacy columns - those Home Assistant marks
UNUSED_LEGACY_COLUMN, still in a table but no longer written to - are now told apartColumnobjects have alegacyflagcolumnsandcolumn_nameson aTableleave them out, unless the table came fromsql.table("states", legacy=True)- A query result keeps them out of view - in
show(), rows, dataframes and exports - unless the query names them orsql(..., legacy=True)is used. Settinglegacy = Trueon the result afterwards brings them into view without a new query
show()on a result no longer cuts off at 6 columns by default, so it shows the same columns as a row fromresult[0]. Usemax_colsto cap them- Indexing a result with a row number, e.g.
sql("select count(*) from events")[0], returns aRowobject - its values, readable by position or column name, with its column names andTable columnsandcolumn_nameson aTableobject are now properties, not methods
📚 Documentation
- Added help on using
ha-replfrom the Studio Code Server and Advanced SSH Home Assistant apps (aka addons), and usingttyd - Lots more examples of how to use all the builtins
Full Changelog: v0.9.0...v0.10.0
v0.9.0
Live Server
- No longer needs
homeassistant-api:hass_apiis the shell's own local REST client, and is no longer also bound inside Home Assistant
Live Shell
- A variable assigned inside Home Assistant now comes back, and is local afterwards, when it holds plain data - so
names = obj.find_names(...)can be followed by local code usingnames. See Mixing Both Sides in the live mode docs - A statement using
sqlorhass_apitogether withhassorobjis refused with an explanation, rather than failing inside Home Assistant ha-repl --json execreports a plain-data value from inside Home Assistant as data, not as its printed form
Full Changelog: v0.8.0...v0.9.0
v0.8.0
Live Server
- No longer uses
rich, so installing no longer upgrades the much olderrichbundled with Home Assistant 2026.10 - which could fail setup withcannot import name 'SyntaxPosition' from 'rich.syntax'until a second restart- Values and errors are now sent to the client as data, and rendered there
- Needs a matching client: an older
ha-replstill works, but shows plain values and tracebacks
Live Shell
- Fix for a class whose body calls something (e.g. a
dataclasses.field()default) failing with'await' outside function
What's Changed
- [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci[bot] in #1
New Contributors
- @pre-commit-ci[bot] made their first contribution in #1
Full Changelog: v0.7.0...v0.8.0
v0.7.0
Live Shell
- The live mode is now local first, so arbitrary local imports can be made.
objandhassare the only fake objects, redirecting their inputs and outputs to the real equivalents inside the live server- Both these objects are limited to accepting local primitive values only as arguments, and can't be combined in a single statement
SQL
- Results object has new features:
- It can now be sliced like a list, e.g.
[:-10]for last 10 rows,[:10]for first 10 project()method which takes a list of columns and produces same table with just those columnssample()returns a random sample of rows from the table, defaulting to 20, overridable withcount=export_csv()method, with same keyword arguments ascsv.writerlen()can be called on result set to get size, subject to row limits- The results can be iterated over with a list of values per row
for e in sql('select * from events'): print(e[0],e[5]) - The Apache Arrow / Feather data is available as
arrow()using the PyCapsule interface for max compatibility - Internally the data is more efficiently stored, as single native Arrow object
- It can now be sliced like a list, e.g.
- Queries all executed under
read_onlysession scope so no commits expected (this is not a security measure)
Live Server
- Config switches now to optionally switch off
sqland/orhassaccess
Full Changelog: v0.6.0...v0.7.0