Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/content/docs/blog/whats-new-in-the-v0-7-line.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ tags:

import { Aside } from '@astrojs/starlight/components';

<Aside type="note" title="Historical post">
This post covers **v0.7.3-beta.1**, a prior beta line. The current line is
**v0.8.2b4** — see [What's new in the v0.8 line](/blog/whats-new-in-the-v0-8-line)
for the latest features.
</Aside>

<Aside type="caution" title="Pre-release">
hal0 is pre-1.0. **v0.7.3-beta.1** is a *beta* — the current development line,
not a GA release. Expect breaking changes between cuts. See the
Expand Down
105 changes: 105 additions & 0 deletions src/content/docs/blog/whats-new-in-the-v0-8-line.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
title: "What's new in the v0.8 line: declarative config, voice, and Hermes autonomy"
date: 2026-07-04T12:00:00
authors: hal0
excerpt: >-
Declarative Stacks replace the flag soup, voice (TTS + STT) lands
end-to-end on the NPU, Hermes owns its own config, and hal0-api can
finally drop root. A look at v0.8.2b4, the current beta line.
tags:
- release
- stacks
- voice
- hermes
- beta
---

import { Aside } from '@astrojs/starlight/components';

<Aside type="caution" title="Pre-release">
hal0 is pre-1.0. **v0.8.2b4** is a *beta* — the current development line,
not a GA release. Expect breaking changes between cuts. See the
[releases page](/releases) for the stable-vs-next split, and the
[full changelog](/changelog#v0.8.0-beta.1) for the complete list.
</Aside>

`v0.8.2b4` is the current beta line. The headline is **declarative
configuration** — Stacks replace the launch-flag soup with a single source
of truth — plus **voice** on the NPU, **Hermes autonomy**, and the
long-awaited ability to run `hal0-api` without root. Everything below
traces to the [changelog](/changelog#v0.8.0-beta.1) — no roadmap promises,
just what landed.

## Stacks: declarative config, finally

The slot config tangle — base flags, profile overrides, per-slot
`extra_args`, and the diverging launch commands they produce — is now a
single `StackConfig`. A `StackApplyEngine` plans changesets, applies them
atomically with rollback, and converges the live slot set in one pass.
Content-hash drift detection tracks when reality diverges from intent,
and seeded stacks (saber / forge / pi) are derived from the bench so
you start from a known-good baseline.

![Stack config editor](/screenshots/dashboard-overview.png)

Flag provenance is no longer guesswork. Every slot exposes its resolved
command at `GET /api/slots/{name}/resolved`, and the Edit drawer badges
each flag with its source — base, profile, or `extra_args`. No more
hunting through three files to figure out which one set `--ctx-size`.

## Voice: TTS + STT on the NPU

The voice stack works end-to-end. `voice_wire` is fixed, Open WebUI Call
mode is wired through the NPU trio, and STT auto-provisions alongside the
FLM slot. The NPU occupancy grid now carries voice activity alongside
inference — when Call mode is active, you see it breathe.

## Hermes owns its own config

Hermes is no longer pinned to a hal0-rendered `config.yaml` snapshot.
A `config-set` overlay layers hal0's keys over Hermes's self-managed
config, so Hermes can self-migrate across versions while hal0 guarantees
the integration keys stay right. A real upgrade path (`hal0 agent upgrade
hermes`) replaces the old tear-down-and-pray cycle.

Two systemd units now: `hal0-agent@hermes` (the core runtime, loopback
only) and `hermes-gateway` (the messaging platform gateway — Telegram,
Discord — on `0.0.0.0:8644`). The gateway is a first-class service with
its own lifecycle.

## hal0-api drops root (opt-in)

Set `HAL0_USER=hal0` and the API runs unprivileged. A declarative
ownership table (auditable via `hal0 doctor perms`) plus a narrow `sudo`
seam (`hal0-slotctl`) keeps the unprivileged API in control of slot units
and container lifecycle while the process itself can't write config it
shouldn't. Slot containers stay rootful — the container is the sandbox
boundary. Default `HAL0_USER=root` is unchanged, so existing installs
don't break.

## The quality-of-life layer

The less flashy changes that operators live with every day:

- **Capability-based fallback.** When a slot's `model.default` isn't
locally servable, `load()` falls back to the best registered model
matching the slot's capability — no more dead slots because a file
moved.
- **q8_0 KV cache everywhere.** Main and MTP-draft KV caches are now
`q8_0` across slots — near-lossless and keeps fused FlashAttention
on AMD HIP.
- **Breaking rename — `hal0/primary` → `hal0/chat`, `hal0/flm` → `hal0/npu`.**
Virtual model names now map 1:1 to their resolution chains. Slot-name
back-compat is intentionally kept.
- **Chat-template render-validation.** A broken template can no longer
ship silently — every template in the catalog is validated at build time.

## Try it

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

Already running an older line? `hal0 update --channel stable` (or
`nightly`), and `hal0 update --rollback` reverts atomically. Full notes
on the [releases page](/releases).
7 changes: 4 additions & 3 deletions src/content/docs/docs/concepts/architecture.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@ state changes to the dashboard footer. These are shared across all requests —
the API is a thin layer over them.

<Aside type="note">
hal0 ships with **no built-in authentication or TLS**. The API is open on the
local network by design. See [Security](/docs/concepts/security) for the
reverse-proxy pattern you put in front of it.
hal0 ships with authentication and HTTPS **off by default** — pass `--auth=basic`
at install to bring up Caddy with basic_auth, bearer tokens, and automatic HTTPS.
When left off, the API is open on the local network. See
[Security](/docs/concepts/security) for both postures.
</Aside>

## Slots: where models actually run
Expand Down
24 changes: 13 additions & 11 deletions src/content/docs/docs/concepts/security.mdx
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
---
title: Security posture
description: hal0 ships no built-in auth or TLS — open on your LAN by design. Learn the threat model, the reverse-proxy pattern, and the MCP host and origin allowlists.
description: Auth is opt-in at install time and off by default for trusted-LAN use. Learn both postures, the --auth=basic flag, the reverse-proxy pattern, and the MCP host and origin allowlists.
sidebar:
order: 70
---

import { Aside, Card, CardGrid, LinkCard, Steps } from '@astrojs/starlight/components';

hal0 makes one security decision explicit and central: it does **not** ship
built-in authentication or TLS. The API binds `0.0.0.0:8080` and every endpoint
is open to anything that can reach that port. This is a deliberate design choice
(ADR-0012), and the rest of your security posture is built on top of it rather
than inside it.
hal0 makes one security decision explicit and central: authentication and TLS are
**opt-in at install time** and **off by default**. Pass `hal0 install --auth=basic`
to bring up Caddy as a reverse proxy with basic_auth, bearer tokens, and
automatic HTTPS. Without it, the API binds `0.0.0.0:8080` and every endpoint is
open to anything that can reach that port — the right posture for a
trusted home LAN.

<Aside type="caution">
Do not expose hal0-api directly to the public internet. It has no auth gate —
anyone who can reach the port can load models, run inference, drive agents, and
read activity. Keep it on a trusted network, and put a reverse proxy in front of
it for anything beyond a single trusted LAN.
**Without `--auth=basic`**, do not expose hal0-api directly to the public
internet — anyone who can reach the port can load models, run inference, drive
agents, and read activity. Keep it on a trusted network, or install with
`hal0 install --auth=basic` to enable Caddy with basic_auth, bearer tokens, and
automatic HTTPS.
</Aside>

## Why no built-in auth?
## Why auth is opt-in

Earlier designs bundled an auth layer and a TLS-terminating proxy. That was
removed (ADR-0012) because it duplicated, badly, what every operator already
Expand Down
20 changes: 11 additions & 9 deletions src/content/docs/docs/getting-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ OpenAI-compatible `/v1/*` requests to the right slot, and serves the
dashboard. There is no shared inference daemon to babysit.

<Aside type="note" title="Current release">
This documentation tracks the **hal0 v0.7.x beta** line — the container-runtime
era, where each slot (`chat`, `embed`, `rerank`, `stt`, `tts`, `img`, `vision`,
and `agent` — plus the NPU-conditional slots `stt-npu` and `embed-npu` when
FastFlowLM is installed) runs in a dedicated podman container. See the
This documentation tracks the **hal0 v0.8.x beta** line — the container-runtime
era, where each slot (`agent`, `code`, `img`, `npu`, `rerank`, `tts`, and
`utility`) runs in a dedicated podman container behind an OpenAI-compatible
API on port 8080. See the
[changelog](/changelog) for the exact current version.
</Aside>

Expand Down Expand Up @@ -69,9 +69,11 @@ FastFlowLM is installed) runs in a dedicated podman container. See the
/>
</CardGrid>

<Aside type="caution" title="No built-in auth or TLS">
`hal0-api` binds `0.0.0.0:8080` and treats every request as authenticated
by network reachability — the right posture for a trusted LAN appliance.
If hal0 is reachable from anywhere you do not control, front it with a
reverse proxy that owns auth and TLS.
<Aside type="caution" title="Auth is opt-in — trusted LAN by default">
`hal0-api` binds `0.0.0.0:8080` and, by default, treats every request
as authenticated by network reachability — the right posture for a
trusted home LAN. To safely expose hal0 beyond that, install with
`--auth=basic` to enable a Caddy reverse proxy with HTTPS, basic_auth
at the edge, and bearer tokens for the API. See
[Security](/docs/concepts/security) for both postures.
</Aside>
14 changes: 10 additions & 4 deletions src/content/docs/docs/guides/connect-mcp.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@ servers, mounted on the API as Streamable-HTTP sub-apps:
server.

<Aside type="caution">
hal0 has **no built-in network auth** (ADR-0012). The MCP mounts are
reachable to anything that can reach the API. Run hal0 on a trusted LAN
or behind your own reverse proxy — do not expose `/mcp/*` to the
internet.
hal0 has **no built-in network auth by default** (ADR-0012). Without
`--auth=basic`, the MCP mounts are reachable to anything that can reach
the API. Run hal0 on a trusted LAN or behind your own reverse proxy —
do not expose `/mcp/*` to the internet.

When `--auth=basic` is active, the MCP mounts sit behind the same Caddy
instance as the rest of the API — they inherit Caddy's TLS and basic_auth
gating automatically. The host and origin allowlists below still apply
at the MCP transport layer, but the outer auth gate is already handled.
See [Security](/docs/concepts/security) for the two deployment postures.
</Aside>

## Connect
Expand Down
26 changes: 19 additions & 7 deletions src/content/docs/docs/guides/voice-stt-tts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ hal0 exposes two voice directions through OpenAI-compatible endpoints:
- **Speech-to-text** (`POST /v1/audio/transcriptions`) — `whisper-v3:turbo` served by
FastFlowLM (FLM) on the XDNA NPU, co-loaded with the chat model in one FLM process
(the "NPU trio": chat + STT + embed).
- **Text-to-speech** (`POST /v1/audio/speech`) — Kokoro-82M ONNX container on CPU,
54 voices, MP3 by default (default voice: `af_heart`).
- **Text-to-speech** (`POST /v1/audio/speech`) — two backends:
- **Qwen3-TTS** (ROCm, GPU): natural speech with voice cloning. Default on Strix Halo.
- **Kokoro-82M** (CPU, ONNX): lightweight, 54 voices, MP3 by default (default voice: `af_heart`). Runs without GPU.

Both are children of the **`voice`** capability: `voice.stt` maps to the
`stt` slot and `voice.tts` maps to the `tts` slot.
Expand All @@ -33,6 +34,15 @@ curl -X POST http://localhost:8080/api/capabilities/voice/stt \
-d '{"enabled": true, "backend": "npu"}'
```

</TabItem>
<TabItem label="Text-to-speech (GPU, ROCm — Qwen3-TTS)">

```sh
curl -X POST http://localhost:8080/api/capabilities/voice/tts \
-H 'Content-Type: application/json' \
-d '{"enabled": true, "backend": "rocm", "provider": "qwen3-tts"}'
```

</TabItem>
<TabItem label="Text-to-speech (CPU, Kokoro)">

Expand All @@ -49,7 +59,9 @@ The response is `{ "ok": true, "selection": { ...current selection... } }`.

<Aside type="note">
STT runs on the XDNA NPU via the FLM container — not on CPU. There is no CPU
whisper.cpp backend in hal0. Kokoro TTS runs on CPU (ONNX). Neither uses ROCm.
whisper.cpp backend in hal0. TTS has two options: Qwen3-TTS on ROCm (GPU, voice
cloning, default on Strix Halo) and Kokoro-82M on CPU (ONNX, lightweight, 54
voices). Neither STT backend uses ROCm.
</Aside>

### How the NPU STT path works
Expand Down Expand Up @@ -96,10 +108,10 @@ As with transcription, `model` is required — a missing or empty `model`
returns **400** (`request.missing_model`).

<Aside type="note">
Kokoro weights are operator-staged on the configured model store. The Kokoro
toolbox is a containerized server managed by hal0 as a podman slot — no manual
container management needed. It implements `POST /v1/audio/speech`,
`GET /v1/models`, and `GET /health`.
TTS weights are operator-staged on the configured model store. Both Qwen3-TTS
(ROCm) and Kokoro (CPU) run as containerized servers managed by hal0 as podman
slots — no manual container management needed. Each implements `POST
/v1/audio/speech`, `GET /v1/models`, and `GET /health`.
</Aside>

## See also
Expand Down
Loading