Skip to content

Config schema reference

The runtime config is split across:

FileRole
/etc/hal0/hal0.tomlMain daemon config (API, paths, upstreams, update).
/etc/hal0/capabilities.tomlUser-facing capability config (embed / voice / img / NPU rollups).
/etc/hal0/slots/<name>.tomlPer-slot lower-layer config.
/etc/hal0/proxmox.jsonOptional PVE API token + endpoint for the Proxmox host-pressure integration. 0600, redacted in logs.

The schema is defined in Pydantic (src/hal0/config/schema.py) and exported as JSON Schema for clients that want machine-readable references.

Every read of hal0.toml goes through pydantic.model_validate. A failed validation raises a structured config.invalid error with details.path pointing at the offending field. The dashboard surfaces this inline; the CLI prints it with the same code.

hal0 config validate runs the schema check without writing anything, so it’s safe to run at any time.

SectionPurpose
[api]API listen host/port, request limits, telemetry toggle.
[paths]FHS path overrides for unusual deployments.
[slots.<name>]One block per slot — see below.
[upstreams]External OpenAI-compatible providers (optional).
[update]Update channel + cosign signer identity.
[openwebui]Bundled UI configuration knobs.

Every slot entry has at minimum:

[slots.primary]
provider = "llama.cpp" # one of: llama.cpp, flm, moonshine, kokoro, comfyui
model = "qwen2.5-0.5b-instruct-q4_k_m" # registry ref (install-time seed; runtime swap writes env override)
port = 8081 # 8081-8099, must be unique
idle_timeout_seconds = 600 # ready -> idle transition threshold

Provider-specific knobs go under [slots.<name>.options]. The five built-in slots (primary, embed, stt, tts, img) cannot be removed; their provider, model, and port fields are still freely editable.

[model] default in a per-slot TOML is the install-time seed only. Once the slot is provisioned, model swaps go through the env layer and the TOML stays stale by design. To swap a slot’s model at runtime use hal0 slot swap <name> --model <ref> or the dashboard’s picker.

Defaults match the FHS layout (PLAN §2):

PathDefault
Install root/usr/lib/hal0/current/
Config dir/etc/hal0/
State dir/var/lib/hal0/
Model registry/var/lib/hal0/models/
Per-slot state file/var/lib/hal0/slots/<name>/state.json
OpenWebUI state/var/lib/hal0/openwebui/

HAL0_HOME overrides all of the above as a single root. Useful for dev installs that don’t want to touch system dirs.

Every config write goes through the NamedTemporaryFile → fsync → os.replace() pattern. A failed write leaves the previous file intact. The same pattern applies to per-slot env files at /etc/hal0/slots/<name>.env.

/etc/hal0/hardware.json is not part of hal0.toml. It’s probe output, regenerated by hal0 probe, consumed by the slot loader. Don’t hand-edit it.

  • Embedded JSON Schema dump on this page, generated from the Pydantic model at build time.
  • Per-field anchor links for direct deep-linking from error messages.
  • Drop-in fragment support — /etc/hal0/conf.d/*.toml merged on load.