High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph — average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.
WebKit verification browser for agent tools
Hwatu runs a warm WebKit browser as a daemon so agents can check pages quickly instead of guessing from screenshots. It exposes the browser through CLI commands and MCP, with built-in verification primitives like `check`, `diff`, `motion`, `snapshot`, `expect`, and live event watching.

Builders who want their agent to verify UI changes with real browser checks instead of relying on a screenshot and a hunch.
You can make your agent prove visible, interactive, and persisted page states in a few milliseconds, then hand the same session to a human when needed.
What it does
One-call verification checks
`hwatu check` loads a page, runs JavaScript, takes a screenshot, and returns structured output in one call.
Pixel diff scoring
`diff` compares pages with match percentages, diff regions, and heatmaps that an agent can improve against.
Motion capture
`motion` reports animation timing, easing, and velocity as numbers instead of raw pixels.
Human hand-off
A live session can be focused into the desktop window manager with `focus` without losing state.
Event subscriptions
`watch` streams load, console, request, and window events as JSON lines or MCP notifications.
MCP and CLI access
The same browser service is available through a plain CLI, MCP server, and a one-line JSON socket protocol.
Tiling-WM browser mode
The browser is designed to be a daily driver in tiling window managers like Hyprland, sway, and niri.
How to get it
- 1Run
curl -fsSL https://raw.githubusercontent.com/hongnoul/hwatu/main/scripts/install.sh | bash
- 2Then pick your door, or take both
hwatu setup # agent: detect Claude Code, Cursor, Jcode, or MCP hwatu localhost:3000 # human: open a window like you open a terminal
README
hwatu is a visual verification harness for coding agents, built as a WebKit daemon. Instead of "looks right to me", your agent gets one-call verified page checks in ~35 ms, pixel-diff scores it can climb, animations as numbers, and headless windows that never steal your focus, at any parallelism.
For human-in-the-loop tasks (e.g. Captcha), hwatu features a lightweight visual verification frontend renderer written in WebKit and a caller function. For tiling WMs (Hyprland, sway, niri, i3), hwatu is intended to replace your primary daily browser. Our current goal is to provide scrolling short-form content experience in mobile-level framerate.
Documents
- Vision: durable product principles, native platform strategy, swarm model
- Agent guide: protocol, primitives, verification loops
- Human guide: daily driving hwatu in a tiling WM, keybinds, media, hand-off
- Benchmarks: every number, measured, with methodology
- Roadmap: portfolio priorities and product boundaries
- Continuous improvement: activation metric, feedback loop, weekly cadence
- Launch kit: reusable copy, channels, and measurement plan
Install
curl -fsSL https://raw.githubusercontent.com/hongnoul/hwatu/main/scripts/install.sh | bash
One static binary plus your distro's webkitgtk-6.0 (the installer
checks). On Arch: yay -S hwatu. From source: cargo build --release.
Then pick your door, or take both:
hwatu setup # agent: detect Claude Code, Cursor, Jcode, or MCP
hwatu localhost:3000 # human: open a window like you open a terminal
Real eyes for your coding agent
- STOP your agent claiming "pixel-perfect." Make it prove 97.49%.
- STOP paying 5 tool calls per page check.
hwatu checkis one call, ~35 ms (beats warm-server Playwright ~9x). - STOP browser windows stealing your focus. Headless by default, you keep typing.
- STOP shipping 170 MB of Chromium. One static binary + your distro's webkitgtk.
hwatu setup detects supported coding agents and prints the
available connections without changing their config. Choose a client
explicitly when you are ready:
hwatu doctor
hwatu setup --client claude --scope project --dry-run
hwatu setup --client claude --scope project
hwatu demo
Setup is previewable, idempotent, and reversible with the same client
and scope plus --undo. Manual MCP configuration remains one
portable entry:
{ "mcpServers": { "hwatu": { "command": "hwatu", "args": ["mcp"] } } }
Or skip MCP entirely: every command is a short CLI call or one newline-delimited JSON line over a Unix socket.
Connecting hwatu makes its tools available; a project instruction
tells the agent when to use them. Add this to AGENTS.md,
CLAUDE.md, Cursor rules, or the equivalent for your harness:
## Frontend verification
Use Hwatu after frontend changes. Exercise the affected user journey and
verify its intended visible, navigational, or persisted result with `expect`.
A successful click or clean console is not proof of success. Check `console`
for additional JavaScript and request failures after verifying the outcome.
Then make the task's proof concrete:
Implement display-name editing on /settings. Use Hwatu to enter “Test User,”
save it, verify the visible success state, reload, confirm persistence, and
report any console errors.
The verification loop, real commands, real output:
hwatu --headless localhost:3000 # its window; you never see it
hwatu --headless staging.example.com # the reference
hwatu diff --id 2 --other 1 --heatmap /tmp/heat.png
# {"match_percent":85.13,"regions":[{"x":0,"y":160,"w":2048,...}]}
hwatu motion --id 1 # the reference's animations, as numbers
# easing cubic-bezier(0.25,1,0.5,1), 300ms, marquee 29.78px/s ...
# ...agent edits code...
hwatu diff --id 2 --other 1
# {"match_percent":97.49} # climbing beats guessing
We ran this loop against a clone of stripe.com's landing page: an agent took it from 85.1% to 98.8% pixel match. Reproduce it: scripts/demo/. A second, real-agent scenario against AIUC (four responsive viewport diffs followed by live human hand-off) is reproducible with evidence manifests from scripts/demo-aiuc/.
A full verification pass (open, load, eval, screenshot, close) is one command, one tool call, ~35 ms median (benchmarks):
hwatu check localhost:5173 --eval 'document.title' --shot=/tmp/after.png
# {"title":"My App","eval":"My App","shot":"/tmp/after.png",
# "console":[...],"load_ms":13,"total_ms":35}
For a repeatable repo-level contract that also owns the preflight, local dev server, responsive screenshots, source-staleness check, and evidence report:
hwatu verify .hwatu/about.verify.json
The same executor is exposed to MCP clients as verify_ui, so different agent
harnesses do not need to rebuild the orchestration loop. See the
agent guide.
Generated HTML in hand and no server? hwatu render is the same
one-call pass with the markup as input: no temp file, no
python3 -m http.server:
echo '<h1>generated</h1>' | hwatu render --stdin --shot=/tmp/gen.png
# {"rendered":true,"shot":"/tmp/gen.png","load_ms":5,"total_ms":28}
# React to load, console, download, and window events without polling.
hwatu watch --kinds load,console
# {"event":"load","seq":1,"window_id":7,"data":{"state":"started",...}}
MCP clients can call subscribe_events for the same stream as
notifications/hwatu/event. See the full agent guide,
including a larger copy-paste policy and verification loops.
Everywhere else, headless is decided at launch and a human can never see the session at any price. In hwatu it's a window property, switchable live, in both directions. And because hwatu is also the browser you already live in, the hand-off lands in a window that behaves like every other window on your desk, not a viewer bolted on for emergencies.
challenge is detection and hand-off only, by design: no solver
APIs, no token injection, no fingerprint games.
Agents loop, you watch some reels
The hand-off works because hwatu is also a real browser, one built
for tiling WMs. hwatu <url> opens a window like your terminal opens
a shell (your WM is the tab bar, there is none in the window), with
mainstream keybinds (ctrl+l, ctrl+f, ctrl+k palette, all
rebindable via dotfile), native ad blocking (~119k EasyList rules
compiled into WebKit's content-extension engine, zero JS in the
request path), Chromium-curve scrolling, unmuted autoplay, a
blur-shield that took Shorts from ~34 to ~95 fps, and one shortform
control scheme (arrows snap exactly one video, Space pauses, hold
ArrowRight for 2x) across Reels, Shorts, and TikTok. High framerates
help oneshotting websites with complicated scroll-anchored animation
logic (e.g. scale.com). Because of this reason, hwatu is optimized for
consuming short-form content with much less resources than what you
would have needed with Chromium or Firefox. The demo video below shows
why hwatu is an excellent alternative browser option for your system,
especially for tiling WMs:
Every window shares the one warm daemon (~56 MB per extra window), suspends when unfocused, and crash-restores at its last URL. Honest gaps: no Widevine or passkeys in WebKitGTK, so keep a fallback bound for Netflix. Ready-made WM configs (hyprland, sway, niri), the full keybind table, and setup: docs/human.md.
Features
- Headless / background / focused as a per-window property, switchable live
- Human hand-off:
hwatu focus <id>drops the live session into your tiling WM - Pixel-diff scoring: match percent + diff regions + heatmap (
diff) - Animations as numbers: duration, easing, velocity (
motion) - Deterministic animation frames: pin all animations at time t (
seek) - Page state as JSON, tokens not pixels (
snapshot) - Real input events with structured errors (
click/type/scroll/upload) - JS errors, console output, failed requests (
console) - Push event subscriptions as JSON lines or MCP notifications (
watch) - One-call page assertions with polling (
expect) - CAPTCHA / anti-bot detection with structured wait/resume (
challenge) - MCP server, plain CLI, and a 1-line JSON socket protocol
- A real browser for humans: mainstream keybinds, media-correct video, native ad blocking, crash restore
Why not Playwright or chrome-devtools-mcp?
There are three ways to give an agent a browser, and two of them are bad at it:
| How it runs | What it costs the agent loop | |
|---|---|---|
| Cold library (Playwright, launched per task) | engine starts when the script does | fast to call, slow to run: every check pays engine startup; no state survives between tasks |
| Warm browser (your Chrome + devtools-mcp) | a full human browser stays resident | resources spent on tabs, extensions, sync, UI you never render, and its windows steal your focus while you work |
| hwatu | "the coldest warm daemon": engine hot, everything else absent | 8 ms spawns, 35 ms verified checks, invisible until you ask to see it (focus), interruptible in both directions |
hwatu keeps exactly what makes checks instant (engine, GPU context, compiled adblock, a prewarmed WebView) and nothing that serves a human sitting in front of it unless that human asked for a window. That's why it idles warm without a tab bar, and why a kept-warm Playwright server driven the same way still costs 341 ms per client to hwatu's 39 (benchmarks).
The second difference is what comes back. Playwright and chrome-devtools-mcp are, at their core, automation APIs: they let an agent drive a browser, then hand back raw screenshots and DOM for the agent to eyeball. hwatu is a verification browser: the measurement primitives are built in, and the browser itself is a warm daemon where a window costs 13 ms and headless is a window property, not a launch mode.
The same pass through Playwright's warm in-process CDP connection, its best case, is 82 ms and five API calls. Shaped like hwatu actually runs (a fresh client each check against a kept-warm engine), Playwright's pass is 341 ms vs hwatu's 39: hwatu is a warm daemon by design, Playwright is a library you have to keep warm yourself.
How hwatu compares
Legend: ✅ Yes / built-in · 🟡 Partial / limited · ❌ No
| Capability | Playwright | chrome-devtools-mcp | hwatu |
|---|---|---|---|
| Verify pass (load + eval + screenshot), warm in-process | 82 ms | n/a | 35 ms |
| Verify pass as a warm service (fresh client per check) | 341 ms | n/a | 39 ms |
| Tool calls per verify pass | 5 | 5 | 1 |
| Pixel-diff score + regions + heatmap | 🟡 1 | ❌ | ✅ |
| Animations as numbers, pinned mid-flight | ❌ 2 | 🟡 3 | ✅ |
| Headless ↔ headed on a live session | ❌ | ❌ | ✅ |
| Human hand-off mid-session, state intact | ❌ | ❌ | ✅ |
| No focus stealing at N parallel agents | 🟡 4 | 🟡 4 | ✅ |
| CAPTCHA detection + structured wait/resume | ❌ | ❌ | ✅ |
| No Node, no per-version browser download | ❌ | ❌ | ✅ |
1 toHaveScreenshot compares against stored goldens: pass/fail for
test suites, not a score an agent can climb.
2 Standard practice is to disable animations or fast-forward to the end state to avoid flakes.
3 Raw CDP can query animation state, but there is no numeric summary of easing/velocity/keyframes.
4 Fine headless; every headed window pops and takes focus.
Comparison reflects each project at the time of writing; corrections are welcome. Honest caveats: Playwright still wins cold start (190 vs 435 ms, paid once per boot) and memory; hwatu renders WebKit not Chromium (keep a Playwright matrix in CI for engine-specific bugs), and it is Linux-only today. Full head-to-head data and methodology: docs/benchmarks.md.
What about Claude in Chrome? Different category. Claude in
Chrome is Claude driving your Chrome through a browser extension:
one agent product, one browser, sharing your profile, tabs, and
focus. hwatu is a client-agnostic daemon any agent (Claude Code,
Cursor, or a shell script) calls over CLI/MCP, with its own warm
WebKit engine, headless by default, and verification primitives
(check, pixel diff, motion capture) built in. Speed is not really
comparable: claude-in-chrome's loop is extension messaging inside a
full human browser and is not callable by other tools, while hwatu
is a purpose-built verification service (~35 ms per check). Use
Claude in Chrome to let Claude browse alongside you; use hwatu when
agents need cheap, repeated, measurable page checks.
Feedback
Tried hwatu? A successful check, a failed install, a missing keybind, and a site that broke are all useful signals. Share a two-minute use report or report a bug.
AGPL-3.0 licensed. Linux. WebKitGTK 6.
Files in the repo
- .astrophile
- .github
- crates
- docs
- examples
- packaging
- scripts
- .dockerignore
- .gitignore
- Cargo.lock
- Cargo.toml
- CONTRIBUTING.md
- deny.toml
- docker-entrypoint.sh
- Dockerfile
- glama.json
- LICENSE
- llms.txt
- README.md
- SECURITY.md
- server.json
- VISION.md
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More connectors

Universal provider proxy for OpenAI Codex & Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code
Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300µs in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.
Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.
Stop your AI from making things up — it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.
20 MB lightweight cross-platform database client for 90+ databases, including MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, SQL Server, and Dameng. Built-in AI, MCP Server, CLI, desktop and Docker. | 轻量级跨平台数据库管理工具,支持 MySQL、PostgreSQL、SQLite、Redis、MongoDB、达梦等 90+ 数据库,提供桌面端、Docker、CLI、内置 AI 助手和 MCP Server。
