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
12MCP 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
the whole remote — that's all of it.
talk+browse the primary input — just narrate
Ctrl+click mark an element: selector + component chain + framed shot
M inspect mode: hover-pick, or drag to region-select
N cut a new issue boundary — many issues per take
P pause/resume: evidence and mic freeze entirely
■/Alt+Shift+R stop — the evidence packet hits disk
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.

…of 12 registered tools — the session is a queryable API, not a dump.

The packet is self-describing and lock-in free. Two paths, picked per agent capability:

PROMPT.md → paste

Every session ships a handoff file: format spec, page vocabulary, fixing rules. Paste it into any agent that can run commands — it knows how to read the evidence and echo before it fixes.

wit mcp → plug

MCP-capable agents connect to the stdio server: 12 tools to query evidence on demand, no context stuffing. Devin also gets a native skill that drives the whole loop.
works with DevinClaude CodeCursorCodexWindsurfany MCP client
02:31STOP ■
08 · 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.
03:05

You could type the bug report, or attach a video. Here's where each approach actually lands:

A written reportA screen recordingWitness
Cost to file one issue≈10 min: shots, crops, careful wordsa few min — but rewatched every readsay it once, evidence attached
Agent can act on itonly what you remembered to writepixels — a human re-derives contextsession.md + events.jsonl + MCP
“Clicked → nothing”easy to forgetinvisible on videocaptured as evidence
Causal burst per click——req / res / console / DOM in ~1.8s
Rewind the page state—video ≠ DOMrrweb full-DOM replay
Stays on your disk—depends where it uploadsalways — .witness/sessions
10 · Who it's for

For anyone whose eyes are the last QA layer.

Solo dev × agent

You built it, you click through it, you narrate. The agent gets a fix-ready packet and the whole find→fix loop stays inside one sitting.

Design & motion review

Jank, flicker, layout shifts — the things that never screenshot well. Say what moved; the DOM mutations are already attached.

QA & product passes

One take per feature, issue boundaries with N. Hand the session to an agent, or attach review.html to the ticket.

OSS maintainers

Ask reporters for a wit session instead of a screenshot: selector, console and network arrive in one self-describing folder.
04:02SAY ×8
11 · FAQ

Asked before you did.

What do I need installed?

Node 18+ and a system Edge or Chrome — Witness prefers your real browser and only falls back to bundled chromium. npm i -g github:wookat/witness, done.

Does anything leave my machine?

The evidence packet stays in .witness/sessions/ on your disk, gitignored by default. Live captions stream mic audio to the ASR engine you pick (doubao-web by default); --asr sr uses the OS/browser recognizer, --asr off skips live text entirely. The final transcript goes to bcut (free) or whisper with your own OPENAI_API_KEY — --no-transcribe skips that too. Optional LLM layers (correction, association) only run when you pass the flag and set a key.

Which agents does it work with?

Any agent that can run a CLI can read session.md + PROMPT.md. MCP-capable ones (Devin, Claude Code, Cursor, Codex…) connect to wit mcp — 12 tools to query evidence on demand instead of one static dump. Devin also gets a native skill that drives the whole recording flow.

What if a password is on screen?

Password fields are masked across four channels, POST bodies redact credential fields, P freezes everything mid-session including the mic, and WIT_NO_BODIES=1 drops response capture entirely for sensitive apps.

What languages can I speak?

--lang sets the recognition language (zh-CN default, e.g. en-US). Your words always land verbatim — ASR mistakes stay auditable; LLM correction is an opt-in display layer.

Only localhost, or any site?

Any URL — it's a real managed browser you drive normally, so logins work. It's sharpest on local dev, where the agent can see the source while it fixes.

It crashed / I killed it — is the take gone?

events.jsonl streams to disk line by line; at most the last few hundred milliseconds are lost. wit recover <dir> rebuilds session.md, review.html and PROMPT.md from the stream.

Is it free?

MIT, no accounts, no required keys. Free ASR engines are the default path; paid-model hooks are bring-your-own-key and optional.

12 · 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