OPEN SOURCE · MIT · LOCAL-FIRST

You say it.
Witness proves it.

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.

$
↑ hand this to your AI agent — it installs and records for you
installs the wit CLI — recorder · renderer · MCP in one · Node 18+ · system Edge/Chrome · no keys
00:00REC
01 · The problem

Agents can't see what you see.

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.

00:18
02 · Watch it happen

One click. Every consequence, filed.

This is a real recorded session — speech, marking, the dead click, the save. The Pay button below produces nothing, and that absence is captured as fact.

localhost:5173/checkout
RECORDED WITH PLAYWRIGHT · ONE TAKE
3recording tracks
10MCP tools
0cloud keys needed
17tests green
MITopen source
03 · How it works

Three recording lines, one timeline.

wit start <dev-url> opens a managed browser. From that moment, three streams run in parallel — zero manual work:

01 / VOICE

Your voice

Continuous audio + true streaming ASR (doubao-web → doubao-ime → browser SR, auto-fallback). Live subtitles under the toolbar as you speak — one take, many issues, no need to split.
02 / OPS

Operations + causal bursts

Every click captures its ~1.8s aftermath: requests, responses, console errors, DOM changes. A click with no aftermath is itself evidence.
03 / STATE

Page evolution

rrweb full-DOM replay + event-driven screenshots + periodic DOM snapshots. Rewind the exact page state at any second.
wit start <url>→browse + talk→Ctrl+click / M to mark→■ stop→evidence package
01:12
04 · The output

Your words become evidence anchors.

Each spoken fragment becomes a block on a timeline with the causal facts of that moment attached — the “causal burst”. Click a quote:

session.md — interactiveclick a quote to expand its evidence
SCROLLy=3936
MUTbutton.feedback · data-collapsed: false → true
MUTbutton.feedback · data-collapsed: true → false
└─ attribute flapping on the boundary
CLICKbutton#submit “提交” · @482,701
└─ page showed no reaction for 1.8s after the click — that itself is evidence
CLICKa[href="/orders"] “订单”
NET →GET /api/orders?page=1
NET ←200 /api/orders · items: []
└─ response body captured → bodies/req_0041.json
01:48SAY ×3
05 · Two audiences

Humans get a replay. Agents get a structure.

For humans

For AI agents

06 · Pull, don't push

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_says

Every spoken fragment with timestamps — the issue anchors.

events_around

Raw events in a time window, filtered by kind.

get_dom_state

Full DOM HTML nearest to a timestamp.

get_errors

Console errors, page errors, HTTP ≥ 400.

get_shot / get_body

Screenshot frames and response payloads on demand.

session_md

The rendered timeline when the agent wants it all.

get_asr / set_asr

The agent checks and flips the live speech engine itself — no human in the config loop.
02:31STOP ■
07 · Principles

Evidence never lies.

Local-first, zero config

System Edge/Chrome + free streaming ASR (doubao-web → doubao-ime → browser SR, switchable via wit config asr). No API key needed; LLM polish is an optional layer, never the pipeline.

Words are never rewritten

Your speech lands verbatim in events.jsonl. Merging, correction and association are display-layer suggestions — the raw testimony stays auditable.

Evidence ≠ intent

Clicks and scrolls are facts, not complaints. Without a spoken anchor, agents are told explicitly: never infer a bug from behavior alone.

Privacy engineered in

Password fields masked in four channels; POST bodies redact credential fields; P freezes everything, mic included; WIT_NO_BODIES for sensitive apps.
08 · Get started

Three sentences. That's the whole loop.

You give instructions; your agent runs the commands. Witness is a CLI (wit) that agents drive — it opens a managed browser, records, and hands back a local evidence package: review.html for you, session.md/PROMPT.md/wit mcp for the agent. Node 18+, system Edge/Chrome, no cloud, no keys.

you×agent
install witness
npm i -g github:wookat/witness
record http://localhost:5173 for me
wit start ✓ · managed browser opens, waiting on you
you use the product — say what you see, mark problems, press ■
fix the issues from that recording
reads session.md → echoes the issue list → you confirm → fixes