# Dashboard layout > Part of [Web UI](README.md). See also: > [Shape (shared)](shape.md) · [Per-agent page](agent.md) This page covers the per-hive UI that hive-c0re serves. Swarm-wide surfaces — the agent roster, agent creation, linking external forge and matrix accounts, the controller's job graph — are on the [swarm UI](../swarm/ui.md). hive-c0re serves the dashboard at `/`. It has a fixed chrome header at the top and a `
` that shows exactly one tab pane at a time. The URL hash (`#agents`, `#rebuild`, `#meta`, `#buildlogs`, `#kept`) drives which pane is active; hash changes don't reload the page. FL0W and ST4TS are standalone pages reached from the pages menu, not from the dashboard tab strip. **Chrome header** (fixed, overlays the active tab pane): - **Pages menu**: a `☰` button at the left of the chrome (`links-menu.js`) opening a popover with links to **flow** (`/flow.html`), **stats** (`/stats.html`), **api docs** (`/api/docs/`) and **swarm** (the swarm UI at the swarm apex domain, opened in a new tab). The swarm entry comes from `state.swarm_public_url`, which hive-c0re reads from `HIVE_SWARM_PUBLIC_URL` (set from `services.hyperhive.swarm.domain`); with no domain set there is no swarm entry. The standalone pages link back to `/`. - **Tab strip**: `◆ 4G3NTS ◆`, `◆ R3BU1LD QU3U3 ◆`, `◆ M3T4 1NPUTS ◆`, `◆ BUILD L0GS ◆`, `◆ K3PT ST4T3 ◆`. In-page tabs only — FL0W / ST4TS live on their own pages, reached from the pages menu. Count pills on 4G3NTS (stale containers), R3BU1LD QU3U3 (rebuilds in flight) and K3PT ST4T3 (kept-state entries). - **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`) — sits below the tab strip. - **No warning banner.** No page shows hive-level warnings (host disk pressure, failing background sweeps, forge boot failures, agents that need a claude login). They live in a push-based registry (`hive-c0re`'s `warnings.rs`): any subsystem raises or clears its own entry through an RAII guard, and each raise logs one `hive warning raised` line. The operator sees the registry as metrics and Grafana alerts: see [Hive-scoped metrics](../scheduler/observability.md#hive-scoped-metrics-hive-c0re). A container crash is a swarm-level Grafana alert on the crash watcher's own log line, so a hive with no otel export has no operator-visible warning signal beyond `/health/ready`. - **Browser tab title** — `hyperhive // h1ve-c0re` by default; updated to ` / // h1ve-c0re` once `hive_name` / `swarm_name` arrive in the state snapshot. The FL0W page uses a slim header (a `← dashboard` back-link + the page title) rather than the dashboard tab strip — it's a standalone surface, not a tab pane. ## 4G3NTS tab **C0NTAINERS** — live containers as a flat list, one row per container, sorted alphabetically by agent name; every container the rescan reports gets a row. Pulsing red banner at the top of this section if any two sub-agents hash to the same port (`port_conflicts` from `/api/state`): the operator must rename one of them and rebuild. `lifecycle::{spawn,rebuild}` also preflight this and refuse with a clear error message naming the conflicting agent. `↻ UPD4TE 4LL` button appears above the containers list when any agent is stale. ## K3PT ST4T3 tab Passive / rare-interaction state. `kept.js` renders it from the `/api/state` snapshot and keeps it live from the `tombstones_changed` stream event. (Rebuild queue and meta inputs are dashboard tabs too — see below.) Per-container CPU, memory and disk load isn't shown in the hive UI. The same figures go out as OTEL metrics and appear in Grafana (see [observability](../scheduler/observability.md)). An agent's CPU and memory caps live per agent in the swarm UI. **K3PT ST4T3** — agents with kept state and **no container** (size + age + claude-creds badge). One action: `PURG3` (wipes state + applied dirs; `POST /api/purge-tombstone/{name}`). ⚠️ **Not only *destroyed* agents.** Nothing records a destroy: `Provision` writes every definition-side artifact (state subvolume, proposed + applied repos, meta registration, topology entry) *before* the container exists, and that artifact set survives `lifecycle::destroy`. An agent part-way through a spawn is byte-identical on disk to a tombstone, and the pane lists both. The pane carries a standing warning to that effect, and the row badge says `offline` rather than `destroyed` — the absence of a container is all hive-c0re can actually prove. Fixing it properly needs a recorded destroy — **deferred** to the swarm-controller / snapshot-storage rework where the problem changes shape. ## Build tabs (`#rebuild`, `#meta`, `#buildlogs`) The build lifecycle — rebuild queue, live build log, meta inputs, and build log history — is three tabs of the dashboard: **R3BU1LD QU3U3** (`#rebuild`), **M3T4 1NPUTS** (`#meta`) and **BUILD L0GS** (`#buildlogs`). They live in `builds.js`, which `tabs.js` imports: the dashboard's one tab strip, `/api/state` snapshot and `/api/dashboard/stream` subscription serve them, with `rebuild_queue_changed`, `meta_inputs_changed` and `meta_update_running` on the stream alongside the dashboard's other kinds. The count pill on R3BU1LD QU3U3 is the number of rebuilds in flight. The 4G3NTS tab does **not** read the graph endpoint, by design — the swarm view stays independent of job-queue internals. Its per-agent pending badges are transient-only, and its queue-summary banner reads the much narrower `GET /api/jobq/rollup` instead (see Container row, below) — a handful of pre-tallied counts, not the graph. The banner's "view queue →" link goes to the `#rebuild` tab. **R3BU1LD QU3U3** — pending, in-flight, and recently settled container operations: rebuilds, meta-update cascades, and first-spawns. One operation runs at a time; the worker drains FIFO. **Is a mounted `JobqGraph`** (the shared generic graph-viewer Preact component, `@hive/shared/jobq-graph.js` — the same one swarm-ui uses) — `builds.js` doesn't render the queue itself; it just mounts the component (`mountJobqGraph(container, props)`, since this page has no JSX pipeline) with an `onUpdate` callback to drive the two things below it that the generic view doesn't show. The component owns fetching, cold and live: `GET /api/jobq/graph` on mount, and a refetch via the mount handle's `.refresh()` on every `rebuild_queue_changed` SSE tick (that event is a bare `{ seq }` trigger carrying no queue payload; both dashboard pages treat the tick as a pure refetch trigger). Each row is one root graph node (`parent: null`); a multi-step op's per-agent subgraphs and sub-steps render as nodes within that one entry (structural `parent` edges define the tree; sibling order is array order, unchanged from the wire). A row shows a state glyph (`⏸` pending / `▶` running / `◐` finishing — own work done, a sub-node still running / `✔` done / `✖` failed / `⊘` cancelled / `·` skipped) and each step's own label/agent. A `Node`-kind dep on a sibling shows as a plain "waits on: `