Install hal0 (hal0 docs)

hal0 installs from a single command. The bootstrap script is the trust
boundary: it fetches the release manifest, verifies the tarball, unpacks
it, and hands off to the real installer (installer/install.sh).

curl -fsSL https://hal0.dev/install.sh | sudo bash

Channels

By default the bootstrap fetches the latest stable release manifest.
Pick a different channel with HAL0_CHANNEL:

HAL0_CHANNEL=preview curl -fsSL https://hal0.dev/install.sh | sudo bash

Accepted values: stable (default), preview, nightly.

Requirements

  • curl and ca-certificates — the one-liner needs them to fetch the
    bootstrap at all. Minimal cloud/LXC images, including a stock Ubuntu 24.04
    Proxmox container, ship without curl:
    apt-get update && apt-get install -y curl ca-certificates (or the
    equivalent for your distro). The bootstrap then checks for tar,
    sha256sum, jq and python3, installs any that are missing with the
    system package manager, and fetches its own pinned cosign.
  • Linux, x86_64 — hal0 ships amd64-only binaries (the FastFlowLM
    .deb and the runner container images). ARM and macOS/Windows are not
    supported.
  • systemd — systemctl must be on PATH (outside --dev mode).
  • Python 3.12 to 3.14 — hal0 requires >=3.12 and is tested on 3.12, 3.13 and 3.14. If the default python3 is older, the installer uses python3.14, python3.13 or python3.12 when one is already on PATH, and otherwise tries to install python3.12 through apt or dnf. If none can be found or installed it stops with a remediation hint (HAL0_PYTHON=python3.12).
  • Python for the memory engine — the Hindsight memory engine builds its own venv and accepts Python 3.11 to 3.14. The installer picks one (installing it when it can) before it does anything else, so a host with none finds out up front. If none is usable, the memory engine is skipped for that run and the rest of the install continues; point HAL0_HINDSIGHT_PYTHON at a 3.11-3.14 interpreter and re-run to add it.
  • Network for the first Hermes build — the bundled Hermes agent builds on its own Python 3.14, never on hal0’s interpreter. It uses a uv-managed CPython kept under /var/lib/hal0/hermes/python/, or a suitable system interpreter. The first build downloads Hermes’s dependencies (and the interpreter, when uv-managed), so the host needs internet access when Hermes is provisioned.
  • A container runtime — every inference slot runs in a container.
    The installer prefers podman (auto-installed if neither podman nor
    docker is found); docker is accepted if already present.
  • Node.js — only needed to build the dashboard UI from a source/git
    checkout. Signed release tarballs ship a prebuilt ui/dist and skip
    this requirement entirely; the installer auto-provisions Node when it’s
    needed and can’t find a suitable version.

What the installer does

The bootstrap hands off to installer/install.sh, which runs 15 steps,
in order:

  1. Pre-flight checks — architecture, systemd, Python, container
    runtime, disk space, free ports.
  2. System user — creates the hal0 service account.
  3. Filesystem layout — creates the FHS directory tree (or the --dev
    tree under $PWD/.hal0ai).
  4. Python environment — builds the shared venv and pip installs
    hal0 into it.
  5. Node.js toolchain — provisions Node only if this tree ships the
    dashboard’s npm project.
  6. Dashboard UI — builds ui/dist (or reuses a release’s prebuilt
    copy).
  7. Configuration — writes /etc/hal0/hal0.toml, api.env,
    upstreams.toml, openwebui.env — never overwriting existing files.
  8. Systemd units — writes and enables hal0-api.service and
    hal0-openwebui.service (unless --no-start).
  9. Container slot seeds — copies default slot TOMLs into
    /etc/hal0/slots/ (never overwriting operator edits).
  10. Hardware probe — detects CPU/RAM/GPU/NPU and writes
    /etc/hal0/hardware.json.
  11. Steward + agent models — seeds a hardware-recommended slot and
    profile, then offers the optional agent model and a starter image
    model (see Starter image model).
  12. NPU prerequisites — installs the FastFlowLM runtime on
    AMDXDNA/apt hosts (fail-soft elsewhere).
  13. Bundle picker manifests — writes the dashboard’s first-run bundle
    catalog.
  14. Bundled agent skills — installs the shipped agent skill set.
  15. Service start — starts hal0-api and hal0-openwebui (unless
    --no-start), waits up to 60 s for /api/health to answer before the post-install checks run, stands up the Hindsight memory engine, then provisions the bundled Hermes agent (skip with HAL0_SKIP_HERMES=1; install later with hal0 agent install hermes). Hermes provisioning builds a release and can take a few minutes.

The installer is idempotent — safe to re-run after a partial failure,
or just to pick up new configuration defaults. Existing config files are
never clobbered, and a unit you disabled or masked (for example
hermes-gateway.service) is left off on re-run; the installer prints the
systemctl command to turn it back on.

Starter image model

On a box that can run the ComfyUI image engine (it needs a ROCm lane: /dev/kfd
and a render node), step 11 also offers a starter image model. Other boxes are
not asked, and the installer says why. The menu lists the image models the API
can render, each with the GB still to download and the time per image, and marks
the one that suits the box’s memory as [recommended]: Stable Diffusion 1.5
below 16 GB, SDXL Lightning from 16 GB, Qwen-Image Lightning from 96 GB. The
memory counted is the RAM the system sees (MemTotal, which inside an LXC guest
is the guest’s limit), or the container’s memory cap when that is lower, because
the image engine loads the weights into memory the guest is charged for.

Answer with menu numbers, catalog ids or recommended, separated by commas or
spaces, or press Enter to download nothing. A bad answer is asked again. The
first model that finishes downloading becomes the img capability’s model,
and the installer starts the image slot with it, which downloads the ComfyUI
runtime on first start and can take several minutes. Open WebUI’s environment
is re-rendered to match: a running Open WebUI restarts to pick it up, and one
you skipped or stopped stays down. If an image model is already selected it
stays selected, and the installer starts nothing. --no-start skips the step,
since it starts the image slot, and the installer prints how to do it later. A
failed download is reported and the install carries on; install a model later
with hal0 comfyui models install <id> or from the dashboard.

An unattended install (no terminal, or HAL0_NONINTERACTIVE=1) downloads
nothing unless HAL0_IMAGE_MODELS is set. Set it to recommended or a list of
ids to opt in, and to none to skip even on a terminal; see
Install-time overrides.

Flags and environment variables

curl -fsSL https://hal0.dev/install.sh | sudo bash -s -- --no-start --models-dir=/mnt/ai-models
Flag Effect
--dev Local-only editable install under $PWD/.hal0ai — no systemd, no host package changes
--no-start Set everything up but do not enable/start the units
--models-dir=PATH Absolute path where Hugging Face pulls land (same as HAL0_MODELS_DIR)
--summary-json=PATH Write a versioned, machine-readable install summary to PATH once the install finishes (see below)
--no-owui Skip Open WebUI (same as HAL0_SKIP_OPENWEBUI=1)
--no-comfyui Skip the starter image models (same as HAL0_IMAGE_MODELS=none); the img slot still exists, parked. Left on, the installer offers the starter image-model menu, whose default is none, so Enter downloads nothing
--no-hermes Skip the Hermes agent and the Operator Board that goes with it (same as HAL0_SKIP_HERMES=1)
--no-pi Skip the Pi agent (same as HAL0_SKIP_PI=1)
--no-agents Skip both agents; same as --no-hermes --no-pi
--no-memory Skip the Hindsight memory service (same as HAL0_SKIP_HINDSIGHT=1)
--no-brain-model Skip the brain model pull (same as HAL0_SKIP_BRAIN_MODEL=1)
--bare, --bare-inference Synonyms: turn every optional component above off. On a terminal a bare install still asks for the models dir, the Hugging Face token and the optional agent model [y/N]; set HAL0_PULL_AGENT_MODEL=0 and HAL0_NONINTERACTIVE=1 for a prompt-free bare install
Variable Default Purpose
HAL0_PREFIX /usr/lib/hal0 Installation root (versioned dir + current symlink)
HAL0_PORT 8080 API bind port
HAL0_PYTHON python3 Python interpreter to build the venv from
HAL0_MODELS_DIR /var/lib/hal0/models Where Hugging Face pulls land
HAL0_NONINTERACTIVE (unset) Set to 1 to force flag/env values everywhere instead of prompting on a terminal
HAL0_NO_PROBE (unset) Set to 1 to skip the hardware probe / first-run seeding
HAL0_SKIP_HINDSIGHT (unset) Set to 1 to skip installing the Hindsight memory service
HAL0_PY_AUTOINSTALL (unset) The installer already sets this itself when the default Python is below 3.12, so you rarely need it; it allows installing python3.12 via apt or dnf when no 3.12-3.14 is on PATH. Other distros need HAL0_PYTHON pointed at a newer interpreter
HAL0_HINDSIGHT_PYTHON (auto) Interpreter (Python 3.11-3.14) for the Hindsight memory engine venv; use it when the installer reports none usable
HAL0_SKIP_HERMES (unset) Set to 1 to skip provisioning the bundled Hermes agent; install it later with hal0 agent install hermes
HAL0_INSTALL_PI (unset) Set to 1 to install the Pi agent unattended; the checklist sets it when the Pi row is on
HAL0_IMAGE_MODELS (unset) Starter image models to download without a prompt: recommended or a list of ids; none skips the step

Choosing components

On an interactive fresh install the installer shows a checklist of the six
optional components before it installs them:

  • Open WebUI: on
  • ComfyUI (starter image models): on (the starter image-model menu is offered; its default is none, so Enter downloads nothing)
  • Hermes agent: on
  • Pi agent: off
  • Hindsight memory: on
  • Brain model: on

Flags and the checklist apply at install time only. They never remove a
component that is already installed.

Pick a preset: a keeps the defaults, b is bare inference (everything off),
p lets you pick row by row. Enter alone is a. A row whose precondition
fails on this machine is shown greyed with the reason and cannot be turned on.

The answer on screen wins over the environment: a row toggled on overrides an env
knob that would have skipped it (the installer unsets the matching
HAL0_SKIP_<X>, or HAL0_IMAGE_MODELS=none for ComfyUI). HAL0_SKIP_SETUP=1 is
not a per-row knob: it skips the brain and image-model steps whatever those rows
say, so the checklist shows the Brain model and ComfyUI rows greyed as unavailable
(HAL0_SKIP_SETUP=1) and they cannot be ticked on. The chosen set is written to the install log as one line.

The checklist does not appear on an upgrade, with --dev or --no-start,
without a terminal, with HAL0_NONINTERACTIVE=1, or when you pass any
component flag; those installs use the flags and variables above.

Like every other installer prompt, the checklist needs stdin to be a terminal.
curl … | sudo bash never shows it, even when typed at a terminal: stdin is
the pipe, so the install takes the defaults. To get the checklist, download the
script and run sudo bash install.sh, or pass the flags above.

To add a skipped component later:
hal0 app install openwebui, hal0 agent install hermes,
sudo hal0 agent install pi, hal0 comfyui models install <id>, and
hal0 model pull <id> for the brain model. Hindsight memory has no deferred
install command; re-run the installer to add it. A re-run also re-enables the
other components you skipped, except Pi, which stays opt-in, unless you repeat
the opt-outs, for example
sudo bash install.sh --no-owui --no-comfyui --no-hermes --no-brain-model.

Install log and failure reports

Every run tees its full output to /var/log/hal0/install-<ts>-<random>.log
(/tmp/hal0-install-<random>.log when not root) — the path is printed at the
start and end, and hal0 doctor bundle includes the latest one. If the
installer aborts, it also writes a redacted hal0-install-report-<ts>-<random>.txt
next to the log (environment, failed units, Podman state, port owners, unit
status, redacted config, hardware summary, log tail, hal0-api journal) and
prints its path. Secret values are masked throughout the report, not only
where their key names them. See installer/README.md for the full
breakdown of what each report contains.

--summary-json

sudo bash installer/install.sh --summary-json=/tmp/hal0-install-summary.json

Writes a schema: "hal0.install-summary.v1" JSON document — hal0 version,
--dev/--no-start flags, models dir, network bind info, the detected
hardware class, which brain model was pulled, the components map, a warning/error count, and
measured per-step durations — atomically, so a script polling for the file
never reads a half-written one. Full field reference and an example payload
are in installer/README.md.

Production filesystem layout

${HAL0_PREFIX}/hal0-<version>   # versioned code tree
${HAL0_PREFIX}/current          # symlink hal0 update swaps atomically
/etc/hal0                       # config: hal0.toml, slots/, profiles.toml
/var/lib/hal0                   # state: models, registry, slots, openwebui, cache

Under --dev, all of the above lands under $PWD/.hal0ai/ instead.

Verify the install

hal0 status
hal0 slot list
curl http://localhost:8080/api/health
journalctl -fu hal0-api

hal0 status reports system + slot + memory health; hal0 slot list
shows configured slots; the /api/health curl is a lightweight liveness
probe (200 the moment the API is serving); journalctl -fu hal0-api
tails the control-plane log if something looks wrong. The installer itself
waits up to 60 s for /api/health after starting hal0-api. For the full
six-step “did it work” checklist — health, model list, first chat,
dashboard, logs, and hal0 doctor verify — see
Verify the install.

Uninstall

hal0 uninstall              # conservative: keep /etc/hal0 + models/registry
hal0 uninstall --purge      # clean slate: also wipe config, data, user, images

The conservative default stops services and removes code, units, venvs,
binaries, and every hal0 podman container, but keeps /etc/hal0 (config)
and the data directory (models, registry, OpenWebUI state) so a re-install
reuses them. --purge additionally removes the
config and data directories, the hal0 system user and group, and all
hal0 runner and OpenWebUI podman images — it prompts for a typed DELETE confirmation
unless you pass --force (or set HAL0_FORCE=1).

Next steps

  • Pull a model and assign it to a slot — see
    Load your first model.
  • Open the dashboard at http://<host>:8080/ to manage slots, profiles,
    and stacks.