// Concept
Capabilities, not variants
There is no edition of Halbert to choose, no licence tier that unlocks a feature, and no list of flags to set before a feature will work. What this machine can do is decided by looking for the thing: a capability is a named question with a cheap answer, and the feature that depends on it is on when the answer is yes.
The practical consequence is that “can it do X on my machine” is not a question the documentation can answer for you. Start it and look at what is offered: the list of capabilities this machine answered yes to is the same list the product consults.
One gate
Section titled “One gate”Every feature in the product is gated by the same function, has_capability(), called at
twenty-two places across fifteen modules. A feature that decides for itself, by consulting
something else, is a bug rather than a variation.
That matters more than it sounds. A second way to answer the same question is a second answer waiting to disagree with the first, and the disagreement will be found by a user rather than by a test: one screen offering something another screen has already decided this machine cannot do.
How an answer is reached
Section titled “How an answer is reached”Three steps, in this order, for every capability:
- An explicit entry under
capabilities:inbeing.ymlwins outright. - A probe, where one exists — the actual look for the actual thing.
- The install preset’s default, otherwise.
The probes are deliberately cheap: a config file that exists, a token that is set, an address that is configured. None of them is a network call, because this runs at every start and a start that waits on a remote host is a start that hangs.
Here is a machine given the home preset and nothing else. The preset defaults config_watcher off
and ha_connection on; the probes answer differently, and the probes win:
applescript Falseaudio Falseconfig_watcher True <- preset says off; a config registry is presentdiscovery Falseha_connection False <- preset says on; no Home Assistant is configuredingestion Falselocal_llm Falsemcp_client Falsescheduler Falsesecure_model Falsesecure_model_allowed Falsesourceprep Falseterminal Falseweb FalseAdd two lines to that machine’s being.yml:
capabilities: terminal: trueand terminal reads True on the next start, with nothing else changed. That is the whole of the
override mechanism, and it is the reason a machine never has to lie about what it is in order to do
one extra thing.
The label is a preset, not a gate
Section titled “The label is a preset, not a gate”An installation carries a variant — the shape it was set up as. It chooses the starting defaults and stops there: no backend feature asks the label when it is deciding what to do, and with one deliberate exception below the label does not overrule a probe.
This replaced a system where the label was the gate: a node labelled for the house could not run a terminal, a scheduler, ingestion or a local model, by definition, whatever hardware it had. A capable machine doing two jobs at once had no way to say so. The presets survive because defaults are useful; the gate did not survive because it was answering a question about labels when the question was about hardware.
_is_home_variant is what is left of it. It is legacy, it survives in exactly three files, and the
only one of those in shipping code is a function that nothing calls — the other two are comments in
tests recording that the patches they name are dead. Nothing should add a fourth.
One capability departs from the order above, deliberately: on a home-variant node sourceprep
stays off even when the probe would find a daemon, so that an inherited environment variable cannot
quietly switch it on. An explicit capabilities: {sourceprep: true} still opts that node in.
Where the label still decides something you can see
Section titled “Where the label still decides something you can see”One place, and it is in the interface rather than the backend: the model picker filters its rows by variant, so a home instance is not offered the secure slot at all. The backend gate on that same feature is a capability, as everything else is. If you are on a home instance and looking for a row the documentation mentions, that is why it is not there.
What this means when you use it
Section titled “What this means when you use it”- Configure the thing, then restart. Capabilities are probed once at start and cached. Connect a local model, or point at Home Assistant, and the capability follows at the next start rather than at the next second. Exactly one setting re-probes as you flip it, and that is the web-search switch, because it governs egress and a delay there is a different kind of wrong.
- A capability is not a permission. It says the feature may exist here, not that any particular
action is allowed.
applescriptlets the tool surface register; a per-call switch still gates every execution.weballows a search to leave the machine; it is off unless you turn it on and no preset ever turns it on. - The reference is generated from the registry. The capability reference is emitted from the same file the probes live in, so it cannot drift from what the machine actually checks.
What is not there yet
Section titled “What is not there yet”- No command prints your capability list. The dashboard reads the registry and the reference page lists what exists, but there is no CLI subcommand that tells you what this machine answered yes to. The start-up log records it once, as an enabled and a disabled set.
Model locality and the secure tier is a decision with the same shape — one judge, no second opinion — on a question where the wrong answer has a cost you cannot take back. Connect a local model turns a capability on by configuring the thing it probes for.