# Find your way around the dashboard

**URL:** <https://forum.hal0.dev/t/find-your-way-around-the-dashboard/103>\
**Category:** Guides\
**Created:** [August 29, 2026, 4:42pm UTC](https://forum.hal0.dev/t/find-your-way-around-the-dashboard/103 "2026-08-29T16:42:19Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![system](https://forum.hal0.dev/user_avatar/forum.hal0.dev/system/32/37_2.png) [@system](https://forum.hal0.dev/u/system)\
**Post date:** [August 29, 2026, 4:42pm UTC](https://forum.hal0.dev/t/find-your-way-around-the-dashboard/103/1 "2026-08-29T16:42:19Z")

</div>

The dashboard has two layers: a shell that’s on screen no matter what page  
you’re looking at, and the pages themselves. This guide maps the shell —  
the command palette, the notifications bell, the Agent Chat launcher, the  
sidebar, and the dock — then explains the memory figures the dashboard  
shows, and walks every page under **Settings** , so nothing in the operator  
surface is a surprise.

## The chrome

### Command palette

Press **⌘K** (or **Ctrl+K** ) anywhere in the dashboard to open the command  
palette — a fuzzy-search launcher over everything the dashboard knows  
about. On mobile, the same surface opens from the **Quick actions** row in  
the nav drawer.

Typing filters a grouped list:

- **Routes** — jump to Dashboard, Slots, Runner Images, Models, Profiles,  
Operator Board, Benchmarks, Hardware, Logs, Agent, or Settings.
- **Slots** — every configured slot, live; selecting one opens its edit  
drawer.
- **Models** — every catalogue and installed model; selecting one opens  
the Models page.
- **Settings** — a deep link straight into most Settings pages (see  
below) — the palette has an entry for every page except **Model  
Defaults**, which has no deep link.
- **Actions** — global actions that are always live: Create slot, Add  
model from HF, Open Chat Pro UI (when OpenWebUI is reachable), and Open  
docs. A Cancel download action appears only while a model pull is  
actually running.
- **Copy** — clipboard utilities for hitting the API directly, currently  
just Copy API base URL. Rendered as its own group, separate from  
Actions.
- **Slot actions** — per-slot verbs (Restart, Stop or Start, View logs,  
Copy curl) that only show up once you type a verb or a slot name — they  
stay out of the default list to keep it uncluttered.

Arrow keys move the selection, Enter runs it, Escape closes the palette.

### Notifications bell

The bell in the top bar aggregates everything that needs your attention  
into one panel, grouped into sections:

- **needs attention** — pending agent tool-call approvals and slots that  
have failed and need a restart.
- **downloads** — active and failed model pulls, with cancel/retry  
controls and a link to the full downloads pane.
- **updates** — an available hal0 release, slots running a pre-update  
config that need a restart, and any model updates available on  
Hugging Face.
- **messages** — developer/system notices pushed into the dashboard at  
runtime.

The badge shows a live count; when nothing needs you, the panel says so.

### Agent Chat drawer

The **Agent Chat** button in the top bar (the two-hemisphere brain icon)  
toggles a slide-out drawer — the UI surface for talking to hal0’s brain.  
This page only covers the drawer as a piece of chrome; for what the brain  
is and how it’s configured, see [Brain](https://forum.hal0.dev/t/brain-hal0-docs/102).

### Documentation and sidebar

The book icon next to Agent Chat opens the hosted docs in a new tab. The  
sidebar below it lists the primary destinations — Overview, Slots (with  
Endpoints, Runner Images, and Stacks as sub-pages), Models (with  
Profiles), Benchmarks, Agents (with Memory, when the memory subsystem is  
enabled, and MCP), Services, Logs, and Settings — plus a **Services**  
zone pinned to the bottom of the sidebar with quick external launchers:  
**Kanban** (the in-app Operator Board, the Hermes kanban proxied through hal0-api; also reachable with ⌘B),  
**OpenWebUI** , and **Hermes Dash** — the latter two only appear when the  
backend reports them reachable.

### Slots: the Image Gen tab

The Slots page splits into **Inference** and **Image Gen** tabs, beside  
Endpoints, Runner Images and Stacks. Image Gen is the ComfyUI engine’s pane,  
three sub-tabs directly under the tabs, **Generate** , **Models** and **Engine** ,  
at `#slots/image/generate`, `#slots/image/models` and `#slots/image/engine`. The  
pane draws no memory gauges of its own: a model’s fit meter reads the same  
memory budget as the figures below. Installing models, generating and reading  
the GPU’s state are in [Generate images](https://forum.hal0.dev/t/generate-images/36). What the  
GPU is doing, what an image costs chat and the buttons that fit live in the  
dock on every page (see [The dock](#the-dock)); the paused slots’ cards on the  
Inference tab keep their `paused · image mode` chip, and the  
[slot rail](#slot-rail) beside the Inference pane shows them hollow-blue.

### Services

The **Services** page is the management surface for hal0’s companion  
processes — OpenWebUI, ComfyUI, Hermes, and Hindsight — all four sourced  
from one server-side catalog (`hal0.services.registry.SERVICES`), so the  
page and the dock’s services pip group can never disagree about which  
services exist. Each card shows:

- a real up/down state (never a placeholder) — ComfyUI via its own  
`/system_stats` + `/queue` probe, OpenWebUI via a loopback `GET /health`,  
and Hermes/Hindsight via their systemd unit state, distinguishing a  
deliberate stop (grey, “stopped — starts on demand”) from a crash (red,  
“crashed — systemd unit failed”);

- the systemd unit, browser URL (when one exists — Hermes and Hindsight are  
loopback-only; ComfyUI’s link opens from anywhere while it binds the LAN, the  
default, and under `[network].comfyui_listen = "loopback"` only from a page on  
the box itself, disabled anywhere else beside an SSH tunnel command), and mDNS  
`.local` URL when advertised;

- lifecycle buttons (Restart/Start/Stop) limited to the verbs that service  
actually permits — ComfyUI exposes Start/Restart only, since a raw  
`systemctl start` would bypass the GPU-arbiter switchover that hands the  
iGPU back from inference mode;

- a journald logs drawer.

A service the backend has no real probe for (nothing in the current  
catalog, but a future extension-provided service could arrive this way)  
reports honestly as unmonitored rather than a fabricated “up” — the same  
rule the Overview card’s services pip group and the dock’s ready count  
follow.

The **Discovery (mDNS)** card at the top shows whether `avahi-daemon` is  
active, the dashboard’s own `<hostname>.local` announcement, and lets you  
advertise or withdraw the addon services (OpenWebUI; ComfyUI listens on  
loopback and is not announced) as their own `<name>.local` entries. The  
installer writes the base `hal0.service` avahi file itself when avahi is  
present, alongside the same permission fix-up that lets the daemon (running as the unprivileged `hal0` user) write the  
addon files — so both announcements come up out of the box, not just the  
addons.

### The dock

The dock is the console’s one status surface, at the bottom of every page. It  
pushes the page up when it opens and never covers it. Always visible, one row  
shows:

- the **GPU segment** — a headline and a one-line detail from the GPU arbiter  
(`GPU · chat mode`, `Rendering · <model> · step n/N`, …) and up to two  
buttons for what fits right now (Hold, Keep, Unpin, Stop image mode, Cancel,  
Restart engine, Dismiss). Click the headline for the **gpu** tab. A box with  
no GPU pool reading or no image engine shows no segment,
- a **slots** group — one pip per active slot (colored by state) and a  
ready count,
- a **services** group — one pip per backing service and a ready count  
(a single warn-toned “services unknown” pip appears if the health  
check itself hasn’t answered, rather than falsely reporting all-green),
- an update chip when a new hal0 release is available,
- the **dock** toggle, with a `+N` badge for the events that arrived while it  
was closed.

Under the row, a two-row ticker shows the newest events, newest at the bottom.  
The toggle expands the dock into three tabs:

- **events** — journal lines (tagged `J`) merged with activity actions (tagged  
`A`) in one timeline, newest last. Filter by stream (all, journal,  
activity), severity, source and slot, or search. Click an activity row for  
its action, target, outcome and before/after. **Export** downloads the  
activity trail with the severity, source and slot filters; journal lines are on the  
[Logs page](https://forum.hal0.dev/t/observe-the-system/37).
- **gpu** — the full status with its step chips and render progress, every  
action that applies (including **Restart engine** , **Logs** , **Open  
editor **, which needs an editor link, and** Cancel**, which needs a run  
started in this browser), and a grid of facts: mode, phase, engine and gate, queue, chat waiting, GPU pool,  
slots, and the last image made in this browser.
- **downloads** — active, queued, completed and failed model pulls with  
cancel, retry and clear controls.

### Slot rail

On the **Inference** tab, the right column is the slot rail: every slot,  
grouped by device (GPU · vulkan, GPU · rocm, NPU, CPU), with its state dot,  
device chip, tok/s or state, model and loaded GB. The header reads `N / M ready`, the same fraction as the dock’s slots group, and the rail’s footer shows the  
GB loaded and the pool’s free GB. A row flashes when an event for that slot  
lands in the dock’s feed; click a row to jump to its card. The Image Gen tab  
has no side column, so its pane takes the full width.

## Memory figures

The Slots page opens with a telemetry bar, the Overview page carries a health  
strip and a **Unified memory** card, and **Settings ▸ Overview** has a live  
hardware panel. They all take their pool, RAM and per-owner figures from one  
place, the `memory` block of `GET /api/stats/hardware`, so two screens cannot  
show two answers. The block holds two budgets that are never added together,  
because they are different resources:

- **GPU pool · shared** is what the GPU loads models into on a unified-memory  
machine: a pool shared with the host and with every other guest on the same  
GPU. The ruler under the telemetry bar is titled “memory · GPU pool · shared”,  
and its total and usage are the kernel’s own live counters. On a discrete card  
the pool is **VRAM** and the ruler is titled “memory · VRAM”. When the box has  
no usable GPU, or the kernel’s counters for the pool cannot be read, there is  
no pool figure: the ruler is titled “memory · RAM” and measures this box’s RAM  
instead.
- **RAM (this box)** is the memory this machine may use. The “CPU · RAM” cell  
shows RAM in use over this box’s RAM limit, and the Overview health strip’s  
“RAM” cell and the “RAM” row in Settings ▸ Overview show the same figure.  
When hal0 runs in a container or under a cgroup limit, the cell reads  
“/ N GB limit” and the other two say “container limit”; on a plain machine it  
reads “/ N GB”, the machine’s total. hal0 reads the limit on every refresh,  
from the machine’s total and from every cgroup limit between the service and  
the root, and takes the smallest, so a cap on a systemd slice or an LXC guest  
counts. RAM in use  
leaves out reclaimable page cache. It is system-wide, so under a cap below the  
machine’s total it can read above the limit. If hal0 cannot read RAM, these  
cells show “—” and no figure. hal0 treats GPU pool memory as not charged to a  
container’s RAM limit, so unloading GPU slots frees little RAM.

The ruler splits the pool’s usage by who holds it. Each of this box’s GPU slots  
is a segment named for the slot, sized by hal0’s estimate of the memory it  
holds (the tooltip says “estimated”). **image engine** is the memory ComfyUI  
reports for its own device on a unified pool, or the `img` slot’s estimate when  
ComfyUI does not answer; on a discrete card it is always the `img` slot’s  
estimate, because ComfyUI’s reading covers the whole card. The tooltip says  
“estimated” whenever it is the estimate. **other guests** is the striped block for whatever the pool holds that  
nothing on this box accounts for, such as a second guest on the same GPU, and it  
appears only when that is more than zero. On a box with no GPU pool, the  
**Unified memory** card shows “system” in that place instead: RAM in use beyond  
what loaded models hold. Estimates can add up to more than the counter. The  
total always comes from the counter, so the ruler scales its segments to fit  
the bar, the API reports the difference as `attribution_excess_gb`, and a real  
second guest can hide inside the overshoot.

“free” is the pool’s total less its usage. “headroom” is what is free in the  
resource that binds, less a 2 GB safety margin: the pool, this box’s RAM when  
there is no pool, or the Proxmox host when one is configured and has less free.  
“limited by” names which one bound it.

For the field list behind these figures, see the  
[Memory budget API reference](https://forum.hal0.dev/t/memory-budget-api-reference/123);  
the design is recorded in  
[ADR-0039](https://github.com/Hal0ai/hal0/blob/main/docs/adr/0039-memory-figures-have-one-owner.md).

## Settings

Settings groups its pages into four sections in the left rail. Several  
pages are the primary documentation surface for another guide — those get  
one line and a link here rather than a repeat.

### GENERAL

- **Overview** — the landing page: overall health status, per-service  
health, live hardware/power counters, the `/v1` request rollup, and the  
telemetry opt-in.
- **Security** — auth posture only (never a key value): whether auth is  
required, whether an admin key is set, and the tier; rotates the admin  
or client key; shows the live route-exposure table. See  
[Auth](https://forum.hal0.dev/t/authentication-hal0-docs/43).
- **Network** — the browser origins hal0 accepts on top of the installer’s  
list: the reverse-proxy **Public URL** and **Extra origins** , saved to  
`hal0.toml` `[network]` and applied on the next request. Same as  
`hal0 network`. See [Allow the public URL](https://forum.hal0.dev/t/authentication-hal0-docs/43#allow-the-public-url).
- **Doctor** — runs and renders `hal0 doctor`’s typed diagnoses (id,  
severity, evidence, next steps) over HTTP. Every fail/warn row carries at  
least one real next step, not just a description of the problem: a  
`command` step shows the exact command in mono and offers **Copy** , plus  
**Run** when it maps onto an existing repair action (restarting the  
affected systemd service, or restarting a named runner slot); a `doc` step  
opens the relevant guide; a `manual` step expands inline. A diagnosis with  
two or more steps also gets a **Steps** button that opens a numbered  
drawer with the same actions.

### MODELS & INFERENCE

- **Loaded Models** , **Model Defaults** , and **AI Capabilities** (TTS,  
STT, embeddings, reranking, image generation, plus the NPU anchor) —  
see [Choose models](https://forum.hal0.dev/t/choose-models-hal0-docs/31) for the catalogue and  
the per-model file facts (Model Defaults edits the chat template only; tunes  
live on profiles), and  
[Generate images](https://forum.hal0.dev/t/generate-images/36) (the Image panel also sets  
the default image size and steps) /  
[Speech to text and text to speech](https://forum.hal0.dev/t/speech-to-text-and-text-to-speech/42) for  
the capability slots.

### SYSTEM

- **Hardware & Runtimes** — read-only evidence: detected hardware,  
available backends, and the runner-image registry per slot. See  
[Manage slots](https://forum.hal0.dev/t/manage-slots-hal0-docs/38) and  
[Manage runner images](https://forum.hal0.dev/t/manage-runner-images/104) for what  
actually controls what a slot runs on.
- **Storage** — where hal0 reads and writes model files on disk. Covered  
in detail below.
- **Memory** — the memory engine, graph extraction, and reranker. The  
graph panel’s **Engine model** picker chooses a local slot or an upstream  
model for the engine and applies without a restart; the agents Memory tab  
carries the same picker. See [Enable memory](https://forum.hal0.dev/t/enable-memory-hal0-docs/35).
- **Updates** — signed self-update plus version/license identity. See  
[Update and roll back](https://forum.hal0.dev/t/update-and-roll-back/41).
- **Advanced** — low-level dispatcher and activity-log tuning rendered  
straight from the server’s settings schema, plus a hal0-api restart  
control.

### INTEGRATIONS

- **Secrets** — provider keys, pull-auth, and custom env vars. This is  
**not** an encrypted store: values are persisted as plaintext  
double-quoted `KEY="value"` lines in `/etc/hal0/api.env`, root-only at  
mode `0600` — the same systemd `EnvironmentFile=` `hal0-api` reads at  
start. Includes a dedicated `HF_TOKEN` field that applies live (no  
restart) so a gated or large pull can authenticate right away. See  
[REST API: secrets and Proxmox credentials](https://forum.hal0.dev/t/rest-api-secrets-and-proxmox-credentials/128#secrets-apisecrets)  
for the write path.
- **Agent Chat** — the `[brain_chat]` policy surface: kill switch,  
read-only guardrail, chat model override, tool-routing model, and loop  
knobs. `tool_model` (where a tool-calling round reroutes when the chat  
model can’t emit tool calls this runtime parses) has its own picker  
here, with a warning banner when the saved value has no loaded slot to  
route to — the shipped `hal0/agent` default on a fresh install, before  
a model is pulled into that slot. See [Brain](https://forum.hal0.dev/t/brain-hal0-docs/102).
- **Realtime** — the `[realtime]` WS voice-endpoint surface: kill switch,  
sample rate, which slots serve speech-to-text/text-to-speech, the  
energy-VAD turn-detection thresholds, and output framing. Every key  
applies on the next connection — no restart.

Agent Chat and Realtime save through **Review & save** , which shows the exact  
per-key diff from `POST /api/settings/preview` before Apply writes it.

## Settings ▸ Storage, in detail

Storage holds one field: **Storage location** , an absolute directory that  
every model consumer — the pull engine, the registry, slots — resolves  
through. Alongside it:

- **Current state** — a live probe of the effective path: whether it  
exists, file count, bytes used, bytes free, and whether it’s writable.
- **Suggested locations** — clickable preset paths, each labeled with its  
current state.
- **Auto-scan on start** — whether hal0-api walks the storage path at  
startup and registers any new files it finds.
- **File extensions** — read-only; edit via `hal0 config edit`.

### Changing the location: the migration flow

If you change **Storage location** to a path that doesn’t yet hold your  
existing model files, Saving doesn’t move anything right away. hal0 first  
does a dry run and shows a confirmation dialog: it will move a specific  
number of files (with a total size) from the old path to the new one. If  
source and target are on the same filesystem the move is effectively  
instant; across filesystems it’s a real copy and can take a while. Only  
after you confirm does hal0 actually touch disk.

On confirm, hal0 moves the files first and persists the new path to  
`hal0.toml` second — deliberately in that order, so a failed move leaves  
your prior config and your files exactly where they were; you can safely  
re-run the move. Once the new path is saved, hal0 immediately rescans it  
and registers any files it finds, so newly-visible models show up in the  
registry without waiting for a restart.

> [@](#):
>
> **Caution**
> 
> Moving files does **not** touch already-running slots. A slot that has a  
> model loaded keeps serving it from memory against the old path — nothing  
> interrupts an in-flight request. What changes is the _next_ time each  
> slot’s container restarts: only then does it observe the new storage  
> path. The Storage location row carries an amber “requires restarting  
> slots to take effect” badge for exactly this reason. If you want every  
> slot serving from the new location immediately, restart them yourself  
> afterward — from the Slots page, or with **Restart \<slot\>** in the  
> command palette.

If a move partially fails, the files that already moved are **not**  
rolled back — the operator can re-run the same move (now effectively a  
no-op for what already succeeded) to finish it safely.
