by hongnoul
Fast, interruptible verification browser for AI coding agents: 35 ms checks, pixel diffs, live human hand-off
# Add to your Claude Code skills
git clone https://github.com/hongnoul/hwatuhwatu is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by hongnoul. Fast, interruptible verification browser for AI coding agents: 35 ms checks, pixel diffs, live human hand-off. It has 54 GitHub stars.
hwatu's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/hongnoul/hwatu" and add it to your Claude Code skills directory (see the Installation section above).
hwatu is primarily written in Rust. It is open-source under hongnoul on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh hwatu against similar tools.
No comments yet. Be the first to share your thoughts!
Unlocks once the catalog security scan passes (runs nightly).
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
Make your agent harness loop instantly faster by giving it real eyes
hwatu check is one call, ~35 ms (beats warm-server Playwright ~9x).Install → Detect workflow → Connect agent → Verify page → Hand off to human
curl -fsSL https://raw.githubusercontent.com/hongnoul/hwatu/main/scripts/install.sh | bash
hwatu setup
One static binary plus your distro's webkitgtk-6.0 (the installer
checks). On Arch: yay -S hwatu. From source: cargo build --release.
The installer installs binaries only. 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
doctor or demo.Setup is previewable, idempotent, and reversible with the same client and
scope plus --undo. Project scope creates shareable configuration; user scope
keeps it personal. Claude Code asks each user to approve project-scoped MCP
servers when it next starts.
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.
hwatu localhost:3000 # open a window like you open a terminal
Tried hwatu? A successful check, a failed install, and a missing workflow are all useful signals. Share a two-minute use report or report a bug.
diff)motion)seek)snapshot)click / type / scroll / upload)console)watch)expect)hwatu focus <id> drops the live session into your tiling WMchallenge)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. 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 different. It 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.
That is why the loop looks like this, 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 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}
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. Each connection gets a strictly monotonic
sequence starting at zero; closing or stalling the connection drops its
subscription without blocking the daemon.
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.
And when the agent hits a CAPTCHA or a judgment call, hwatu focus
materializes its live session, cookies and state intact, in your
tiling WM. You act for ten seconds. It takes back over. This is
the adjective no other tool gets to claim: interruptible.
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.
The speed follows from the same design decision: hwatu is a warm daemon, not a library you launch. The engine, the GPU context, the compiled adblock ruleset, and a prewarmed WebView outlive every task, so a check starts from a hot pipeline instead of a cold process. Playwright is a library and cold by nature. Keeping it warm is something you build (a server process, connection management, context pooling); hwatu ships warm as the default and the only mode.
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 downlo |