The Web UI
The CLI is one face of stax. The other is a browser UI that renders the same live run — flamegraph, top-N functions, timeline, annotated disassembly — and updates continuously as samples land.
The WebSocket endpoint
stax-server listens on two transports. The CLI uses a Unix domain socket;
the browser uses a WebSocket:
ws://127.0.0.1:8080Both speak the same vox RPC services. The
WebSocket is bound automatically when stax-server starts — there is no
separate command to launch it.
Override the bind address with STAX_SERVER_WS_BIND:
STAX_SERVER_WS_BIND =127.0.0.1:9000 stax-server Bind to loopback. The default
127.0.0.1keeps the endpoint local to your machine. There is no authentication on the WebSocket; do not bind it to a public interface.
Running the frontend
The UI lives in the repo under frontend/ — a Vite + React + TypeScript app
(stax-live-frontend). Run it with pnpm:
cd frontend
pnpm install
pnpm dev # Vite dev server on http://localhost:5173 pnpm build produces a static bundle in dist/ if you'd rather serve it
some other way; pnpm preview serves that bundle locally.
By default the UI connects to ws://127.0.0.1:8080. Point it elsewhere with
a ?ws= query parameter — http://localhost:5173/?ws=ws://127.0.0.1:9000.
What the UI shows
The UI connects to the Profiler service and subscribes to a stream per
panel, so every view refreshes on its own while a recording is in progress —
there is nothing to reload. The layout, top to bottom:
- Topbar — connection status, a pause toggle for ingestion, a thread switcher, a symbol search (substring or regex), display-mode pills (on-CPU / off-CPU / wall), PMU-metric pills (IPC / L1-d misses / branch mispredicts), a binary-kind filter, and a light/dark toggle.
- Timeline — per-bucket wall time, with drag-to-brush time-range selection that scopes every other panel.
- Off-CPU reason legend and a wakers panel — what threads were blocked on, and who woke them.
- Flamegraph — the on-CPU call tree, the same data as
stax flame, rendered as a zoomable graph with focus / drop-symbol / Esc keyboard shortcuts and off-CPU reason stripes. - Top-N table — the hot-leaf leaderboard, the same data as
stax top, sortable by self or total. - A tabbed detail pane — disassembly (cost-annotated, source-headed,
the same data as
stax annotate), family tree (callers/callees around a symbol), and intervals (the individual off-CPU intervals, with reasons and wakers).
The UI and the CLI are interchangeable: a run started from the CLI shows up in the browser, and vice versa. They are both just clients of the same daemon.
Regenerating the RPC bindings
The frontend talks to stax-server through generated TypeScript bindings in
frontend/src/generated/ — vox generates them from the Rust service
definitions, so the types never drift. After changing the protocol:
pnpm codegen # runs `cargo run -p xtask -- codegen` Generated code is generated. Don't hand-edit anything under
frontend/src/generated/— change the Rust protocol and re-run codegen. See Programmatic Usage.