# colibri's chat UI
One page (`index.html`, no build step) and a small server (`server.py`, Python's standard
library only) in front of a colibri gateway.
```
coli serve --model ~/colibri-models/qwen36-35b # the gateway, on 127.0.0.1:8000
coli ui # the UI on http://127.0.0.1:8790, the browser opened on it
```
`coli ui --backend http://HOST:PORT` points it at a gateway elsewhere (`coli web` is the older
dashboard the gateway serves itself). The server proxies
`/v1/`, `/health`, `/profile` and `/experts` to the gateway, so the page and the API share
one origin (the gateway sends no CORS headers); a chat stream passes through chunk by chunk,
and when the page stops a request the upstream connection closes, which stops the engine.
## What it does
- **Chat**: streaming, the reasoning in its own block (open or closed while it streams, the
choice kept), Markdown, copy, regenerate and continue, conversations kept in the browser.
A turn stopped while it was still reasoning continues inside its open block (Qwen3.6 and
Qwen3.8). HTML code blocks open as a page in the right panel.
- **Pictures**: "attach an image" appears only when the model card lists image input, which
the gateway does only when the engine loaded its vision tower; pictures are resized to
1280 px in the browser.
- **Expert map**: one card per transformer block, its experts in a grid, colored by where
they live (RAM or VRAM) and by what this answer used. Engines that send per-step frames
light the experts each step routes (`/experts?since=N`).
- **Monitor**: the turn in flight (reading the prompt or writing, tokens, tok/s over the
last 32 tokens) and the box (RAM, the engine's RSS and CPU, load), from `/health`.
- **Profiling**: where each turn's time went, from `/profile`.
- **System One**: a decision with a probability, `POST /v1/systemone`.
- **Coding agents** (Settings, "Agents"): Pi, Codex, Claude Code, opencode, OpenClaw and
Hermes, found on this machine and opened in a new terminal window already pointed at
colibri, through their own options and environment (Windows and WSL for now). Codex speaks
only the Responses API: `responses_shim.py` translates it to the gateway's chat API.
- **Web search**: the chat can search and read pages before it answers (`web.py`): results
from a SearXNG instance when `coli ui --searx URL` names one, else DuckDuckGo's plain HTML
results (no key); the pages' readable text only, at public addresses only.
- **Mascot**: the hummingbird follows the turn (reading, reasoning, writing, done, stopped).
- **Models**: what fits the machine the gateway runs on and how fast it would go, each model
three ways (all in RAM, with the GPU, the experts streamed from the SSD); the models on its
disk, our catalog and a search over the GGUFs on Hugging Face that colibri reads, with each
variant's own estimate (`models.py`).
## The Models page
Everything on it is read on the machine that runs it: the CPU, the RAM, the GPUs and the free
disk from colibri's own probe (the one `coli setup` uses), the RAM bandwidth (numpy, when it is
there) and the SSD's random direct reads (Linux) measured there; "Measure again" repeats both
while the engine is idle. A speed is either **measured**, the median of the gateway's own
finished turns with that model, on the CPU or with the GPU, or an **estimate**: the bytes a
token reads (the dense part plus k of E experts, from the tensor headers, read over HTTP without
downloading anything) over the measured bandwidth. A dedicated GPU gets no estimate until it is
measured; an integrated one only for the engines `coli setup` runs on it, with the ratio
measured on a Radeon 780M on that GPU alone.
It runs inside `coli ui` when the gateway is on the same machine (`--backend` on 127.0.0.1, the
default). Models are looked for in `--models-dir` (repeatable), else in the folder `coli setup`
uses (`~/colibri-models`), and in the folder of the model the gateway serves; downloads go to the
first. With the gateway on another machine, run the service there and point `coli ui` at it:
```
python3 ui/models.py --backend http://127.0.0.1:8000 # on the engine's machine, 127.0.0.1:8791
coli ui --backend http://BOX:8000 --models-backend http://127.0.0.1:8791 # through an ssh tunnel
```
"Use" restarts the running `coli serve` with its own command, folder and environment, only
`--model` changed ("Use with the GPU" and "Use the CPU only" turn the GPU on or off); when the new
model does not start, the previous one is started again. The process is found through /proc,
so switching works on Linux (and WSL); elsewhere the page says how to restart it by hand.
## Safety
The server listens on 127.0.0.1. `/agents` answers only this page (its own Host and Origin,
and a header of its own on a POST), and launches only an agent from its list, with a model
the gateway lists, a folder that exists and an API key of plain characters. `/web/` and
`/models/` answer only this page too; `/web/` opens public addresses only, and `/models/`
switches only to a folder under its models folders and stops only a `coli serve` process. API keys stay in the browser and in the
agents' own environment. What leaves the machine: the chat to the gateway, and with web search
on, the query to the search engine and the pages the model chooses to read.