Experience your product and talk naturally — “this button does nothing”. Witness welds every word to the causal evidence of that exact second, then hands the package to your AI coding agent.
A human notices “the button fades weirdly when I scroll” in two seconds. Writing that up for an AI agent takes ten minutes of screenshots, element selectors and prompt crafting — and the result still loses the why. Voice is the cheapest annotation channel there is; it just never had a recorder.
wit start <dev-url> opens a managed browser. From that moment, three streams run in parallel — zero manual work:
Continuous audio + live speech-to-text. Say everything on your mind — one take, many issues, no need to split.
Every click captures its ~1.8s aftermath: requests, responses, console errors, DOM changes. A click with no aftermath is itself evidence.
rrweb full-DOM replay + event-driven screenshots + periodic DOM snapshots. Rewind the exact page state at any second.
Each spoken fragment becomes a block on a timeline with the causal facts of that moment attached — the “causal burst”. This is what your agent actually reads:
### 00:09 · SAY > [00:15] "the button fades and shrinks when I scroll" - `00:08` SCROLL y=3936 - `00:08` MUT `button.feedback` data-collapsed: false → true - `00:11` MUT `button.feedback` data-collapsed: true → false ← flapping on the boundary ### 00:34 · SAY > [00:34] "the submit button does nothing" - `00:33` CLICK `button#submit` “提交” · @482,701 └─ (page did nothing for 1.8s after the click — that itself is evidence) ### 01:02 · SAY > [01:02] "the orders API returns wrong data" - `01:01` CLICK `a[href="/orders"]` “订单” - `01:01` NET → GET /api/orders?page=1 - `01:01` NET ← **200** /api/orders · [body](bodies/req_0041.json) ← items: []
wit mcp — evidence as an API.Instead of a static dump, the session becomes a stdio MCP server. Point any MCP-capable agent at it and it queries exactly the evidence it needs:
list_saysEvery spoken fragment with timestamps — the issue anchors.
events_aroundRaw events in a time window, filtered by kind.
get_dom_stateFull DOM HTML nearest to a timestamp.
get_errorsConsole errors, page errors, HTTP ≥ 400.
get_shot / get_bodyScreenshot frames and response payloads on demand.
session_mdThe rendered timeline when the agent wants it all.
System Edge/Chrome + Edge SpeechRecognition — free real-time transcription, no API key, works anywhere. Cloud ASR and LLM polish are optional layers, never the pipeline.
Your speech lands verbatim in events.jsonl. Merging, correction and association are display-layer suggestions — the raw testimony stays auditable.
Clicks and scrolls are facts, not complaints. Without a spoken anchor, agents are told explicitly: never infer a bug from behavior alone.
Password fields masked in four channels; POST bodies redact credential fields; P freezes everything, mic included; WIT_NO_BODIES for sensitive apps.
# needs Node 18+ and system Edge/Chrome — no downloads, no keys npm i -g github:wookat/witness wit start http://localhost:5173 # managed browser opens — talk & click # stop → .witness/sessions/<ts>/ — feed PROMPT.md + dir to your agent wit list # your sessions wit mcp # serve the latest as an MCP server