Drive this engine live: open the ASCII seat on the Test Bench →

ASCII

ascii Light — runs anywhere

A face made of typed characters — nine rows of monospace text that blink, glance, talk and think.

Renders into a DOM <pre> element. No canvas, no WebGL, no images — the face is real selectable text.

What it can express

Moods: 25 protocol moods, folded onto two scalars — a smile bend and a brow lift — then resolved by the glyph table into roughly six distinguishable faces. A real mood layer, but a coarse one.

What it costs a device

measured on this box375×6671440×900
cold mount → first frame362 ms410 ms
rAF fps — idle6060
rAF fps — speaking6060
CPU cores busy — idle0.100.12
CPU cores busy — speaking0.130.12
worst frame gap (p95)16.8 ms16.8 ms
over the wire299 KB299 KB
JS heap10 MB10 MB

The empty control page on this box costs 0.08 / 0.10 cores. ASCII costs 0.10 / 0.12 — inside the noise of an empty page, at a locked 60 fps. It is the cheapest thing the estate can put on a screen.

Why light: It costs what an empty page costs. Nothing rebuilds geometry — the whole face is one diffed string assignment per frame into a <pre>, and the browser skips the write entirely when the text has not changed.

Dials it really exposes today

fontSizethe whole face scales with the type sizeany CSS size; default '16px'
colorink colour for the entire face#rgb or #rrggbb only — anything else falls back to inherit
setTranscript(word)pushes a spoken word onto the ribbon under the facetruncated to 40 characters per word
setAgentState(state)drives cheeks, hair, thought bubble and caption rowidle · listening · thinking · speaking · interrupted
setMood(mood, {intensity})bends the mouth and lifts the browsany of the 25 moods; null clears
setAudioLevel(level)opens the mouth from live audio energy0–1 scalar, or {level, wide, round} for vowel colour; stale after 350 ms

Try it

Universal Stage — ASCII beside the other fouropen/alive-site/universal-stage.html Freestyle Stage — the agent draws its own ASCIIopen/alive-site/freestyle-stage.html

Honest limits

Numbers are software-renderer numbers. Measured 2026-08-04 on the estate box (18 vCPU, load 2.8–5.3 during the run) under chromium_headless_shell-1232 + SwiftShader, 3 runs per cell, median reported. SwiftShader rasterizes on the CPU, so a real phone GPU changes the picture — most of all for 3D. Read the ordering between engines, not the absolute figures. Evidence for every claim: CARD-FACTS.md. Harness: work/measure-engines.mjs.