The viewer is your home base: browse scenarios, run them, watch each step live, and debug failures — all locally.
Launch
npx @unotest/web viewerIt starts a localhost HTTP + WebSocket server and opens your browser. Set
UNOTEST_VIEWER_NO_OPEN=1 to start without opening a tab, and
UNOTEST_VIEWER_HOST / UNOTEST_VIEWER_PORT to bind somewhere other than
localhost and an OS-picked free port. Your agent can also launch it via the
open_viewer MCP tool.
The project at a glance
Home is the first tab and it is always there: pinned, never closable, and where “Close All” leaves you. It shows one tile per scenario, filled by the status of its last run — or, with the last run | schedule toggle above the field flipped to schedule, by whether and how often the scenario runs on its own. Tile size is computed from the window, so the whole suite fits on one screen without scrolling — red patches are visible from across the room.
- Hover a tile for the scenario name, when it last ran, how long it took, and a strip of its recent outcomes.
- Click a tile to open that scenario in a tab.
- The counters along the top (scenarios / passed / failed / never run) double as filters for the field.
- A scenario running right now breathes: its tile fades in and out under a warm ring, and holds still while the run is paused. The legend names the state only while something is in it.
- Colour fades as a result ages — a bright tile ran just now, a pale one is stale. The legend spells that out too.
- A scenario marked
// @expect-failwhose last run failed as intended shows the expected status — its own colour and its own filter, not part of the failed count.
Tiles reflect the active env overlay: with overlays defined
(unotest/.env.<name>), the env switcher in the Variables panel — the
same one the status bar shows as env overlay — picks which overlay’s run
history fills the field; each overlay has its own (see below).
What it is
- Local-only. No cloud, no account. It reads run artifacts from
unotest/.runs/(per-environment roots likeunotest/.runs.staging/for runs started with--env staging) and your scenarios/helpers/collections from disk. - Read + run. Browse and run; results stream live over WebSocket.
- Environment-aware. One switcher — env in the Variables panel,
env overlay in the status bar — picks the active
.env.<name>overlay: it scopes the variables layers, the Home/Runs history and which overlay new runs spawn into. All open tabs follow the switch. On a box, the tree header additionally names the project and environment this viewer serves, and switches between them. - Single source of truth. Breakpoints and variables are files on disk, so the CLI, the agent and the viewer all agree.
On a hosted viewer the status bar also carries a bundle badge — the test
bundle this environment is running (wip when it came from a tree with
uncommitted changes), with the pushed bundles in its menu — and the Runs
section offers this bundle only to hide the runs of other bundles.
Behind a proxy
On localhost the viewer trusts whoever reaches it, and everything is
available. When something fronts it — a box’s guard — the viewer asks
GET /api/session and reads the x-unotest-viewer-session header the proxy
stamps: an identity for display (user, role, environment) and four
capabilities the proxy can only lower — canRun, canEditFiles,
canTerminal, canBrowseFs. The UI then stops offering what the proxy would
refuse: Run / Debug, Save in the editor (with the hint Not available in a read-only session), the terminal toggle. The status bar names the session
— the user, then role · env beside it — with log out in its menu when
the proxy offers one. Enforcement stays in the proxy: a forged header buys a
smaller UI and nothing else.
Next
- Tour — the activity bar and panels
- Running tests
- Step debugger