Add the Home Assistant CLI on personal hosts - #135
Draft
gtbuchanan wants to merge 1 commit into
Draft
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
hass-cli is pinned in mise's global namespace rather than installed per-platform. It earns that exception by not being a dev toolchain: no project mise.toml would pin a user-facing application, so nothing downstream can be shadowed by it. uv is pinned alongside it as the engine mise's pipx backend installs through. To keep the pin Renovate-tracked without hand-maintained annotations, the global config moves from a single android-only config.toml to plain-TOML fragments under conf.d/, gated per-platform by their own .chezmoiignore. Renovate's built-in mise manager parses those directly, so the only wiring is a file pattern for the chezmoi dot_config path. Staying template-free is what buys that, which is why the platform split had to move out of the files and into the ignore. Credentials come from mise [env] rather than a shell wrapper. hass-cli reads its server and token from the environment on every invocation and has no config file, so a wrapper looked natural -- but one only exists in shells that loaded a profile, leaving agents and scripts to resolve the mise shim with nothing set. [env] is applied by the shim too, so every caller is covered by one mechanism. The resolver reads the vault and caches the pair under DPAPI, mirroring the existing bw-session cache, because mise's computed-env cache does not engage on the shims-only path that non-interactive callers take. Lookups fail soft, so a locked vault cannot break every mise command on the host. Only `check` is safe to run by hand; `token` and `server` print a credential for mise to capture. Windows only for now -- the other platforms install the CLI but have no resolver yet, so the credential fragment is not deployed there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gtbuchanan
force-pushed
the
feature/home-assistant-cli
branch
from
August 24, 2026 13:26
070ba79 to
9417ce0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Installs
hass-clion personal hosts and wires its credentials from the Bitwarden vault on Windows.Install
Pinned in mise's global namespace as
pipx:homeassistant-clirather than installed per-platform. That namespace is otherwise reserved — dev toolchains stay in each project'smise.toml— and a user-facing application earns the exception: no project would ever pin it, so nothing downstream can be shadowed.uvis pinned alongside as the engine mise'spipx:backend installs through. On Termux aqua ships no android asset for uv, so thepkgbuild serves from PATH instead.conf.d fragments
The global mise config moves from a single android-only
config.tomlto plain-TOML fragments underconf.d/, gated per-platform by their own.chezmoiignore.The point of the split is Renovate. Its built-in
misemanager parses these files directly and resolves both thepipx:(PyPI) andcoredatasources, so no version here needs a hand-written# renovate:annotation or a custom regex manager. Go template directives would make a file unparseable, which is why the platform split had to move out of the files and into the ignore. The manager needs one nudge — its built-in patterns key on a literal.config/mise/conf.d, which the chezmoidot_configsource path doesn't match — andmanagerFilePatternsis additive, so the repo-rootmise.tomlkeeps matching by default.The
disable_toolsrationale now sits beside each entry rather than in one block above the list, so a comment can't drift from the tool it explains.Credentials
hass-cli reads its server and token from the environment on every invocation and has no config file, so something has to put them there. That something is mise's
[env], not a shell wrapper.A wrapper is the obvious design and it doesn't work: a function named
hass-clionly exists in shells that loaded a profile, so agent harnesses, scripts, and any non-interactive shell resolve the mise shim instead, get nothing, and fall through to zeroconf discovery —Found no Home Assistant on local network. That's the common case, not an edge case. mise applies[env]in the shim path too, so activated shells,mise exec, scripts, Git Bash, and agents are all covered by one mechanism.Two traps ruled out along the way, both recorded in the docs:
mise exec -- hass-clilooks tidier and is worse. In an activated shellmiseis itself a function, and forwarding through it drops the standalone--, so mise's parser claims the first hass-cli flag colliding with one of its own (error: unexpected argument '--timeout' found). It fails only on colliding arguments, so it looks fine until it doesn't.--server/--tokenas flags would put a long-lived token in the command line, readable from any process listing.hass-vaultresolves the pair from the vault and caches it under DPAPI, mirroring the existingbw-session-windows.ps1scheme — same protection, sliding idle window, expiry bound as the entropy. The cache is load-bearing: mise's computed-env cache is session-scoped and does not engage on the shims-only path non-interactive callers take, so an uncached resolver would pay a full vault round trip on every command, twice over (oneexec()per variable).Lookups end in
|| exit 0so a locked vault, a renamed item, or an offlinebwcan't fail every mise command on the host. The tradeoff is that failure is quiet, since mise swallows an[env]exec's stderr —hass-vault checkexists to diagnose that. Onlycheckis safe to run by hand;tokenandserverprint a credential to stdout for mise to capture, so running one to test the setup would persist a long-lived token in a terminal, a log, or an agent transcript.The vault item is found by search rather than a fixed id, so it stays renameable and no vault identifier is committed. An ambiguous match is refused rather than guessed.
Scope
Windows only for the credential half — the other platforms install the CLI but have no resolver yet, so the credential fragment isn't deployed there. That's unimplemented, not opted out: each platform needs its own resolver because the at-rest wrapping is bound to a platform API, and the fragment's gate widens as each one lands.
A gated note in user-level
AGENTS.mdtells agents the CLI is pre-authenticated, since the local doc doesn't reach agents working in other repos.Verification
Exercised end to end on personal Windows against a live instance — PowerShell (activated and
-NoProfile) and Git Bash, cold and warm cache, plus the fail-soft path with a deliberately bad item.hk check --allpasses.Android is unverified — the uv/pipx path there is reasoned from Termux's package index, not run.
🤖 Generated with Claude Code