hwatu

Visual verification browser for coding agents: daemon-based headless WebKit with snapshot, click/type, console capture, screenshots, and pixel-diff scoring. One static binary, Linux/Wayland. MCP server via `hwatu mcp` (stdio).

Documentación

hwatu

Latest Release License: MIT CI

Verificación headless de interfaces para agentes de codificación

An agent verifies aiuc.com with hwatu: one command returns pixel-match scores for four responsive viewports, then the live page pops into view for human hand-off

hwatu es un arnés de verificación headless para agentes de codificación: un daemon WebKit cálido controlado por CLI, MCP o una línea JSON por conexión de socket Unix. En lugar de "se ve bien para mí", el agente obtiene verificaciones de página en una sola llamada en ~35 ms, puntuaciones de diff de píxeles que puede mejorar, animaciones como números y ventanas headless que nunca roban el foco, a cualquier paralelismo. Jcode lo impulsa de forma nativa como su backend browser. Cuando una verificación necesita a un humano (un CAPTCHA, una decisión subjetiva), hwatu focus <id> materializa la misma sesión en vivo como una ventana real.

Documentos

Instalación

curl -fsSL https://raw.githubusercontent.com/hongnoul/hwatu/main/scripts/install.sh | bash

Un binario estático más el webkitgtk-6.0 de tu distribución (el instalador lo verifica). En Arch: yay -S hwatu. Desde el código fuente: cargo build --release.

Luego conecta un agente:

hwatu setup             # detect Claude Code, Cursor, Jcode, or MCP

Verificación, no vibraciones

  • "Pixel-perfect" es una afirmación. match_percent: 97.49 es una medición.
  • Una llamada de herramienta por verificación de página, ~35 ms. El mismo pase con Playwright en servidor cálido son 5 llamadas y ~9x más lento.
  • Headless por defecto. Sin ventanas emergentes, sin robo de foco, sigues escribiendo.
  • Un binario estático + webkitgtk de tu distribución. Sin Node, sin descarga de Chromium de 170 MB.

hwatu setup detecta agentes de codificación compatibles sin cambiar su configuración. Elige un cliente explícitamente:

hwatu doctor
hwatu setup --client claude --scope project --dry-run
hwatu setup --client claude --scope project
hwatu demo

La configuración es previsualizable (--dry-run), idempotente y reversible (--undo). La configuración manual de MCP es una entrada portátil:

{ "mcpServers": { "hwatu": { "command": "hwatu", "args": ["mcp"] } } }

O salta MCP: cada comando es una llamada CLI corta o una línea JSON delimitada por nueva línea sobre un socket Unix.

Conectar hwatu hace que sus herramientas estén disponibles; una instrucción de proyecto le dice al agente cuándo usarlas. Añade esto a AGENTS.md, CLAUDE.md o reglas de Cursor:

## 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.

Luego haz concreta la prueba de la tarea:

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.

El bucle de verificación:

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

Este bucle llevó un clon de la página de inicio de stripe.com de 85.1% a 98.8% de coincidencia de píxeles. Reprodúcelo: scripts/demo/. Un segundo escenario real de agente (cuatro diffs de viewport responsivo, luego traspaso humano en vivo) con manifiestos de evidencia: scripts/demo-aiuc/.

Un pase de verificación completo (abrir, cargar, evaluar, captura, cerrar) es un comando, una llamada de herramienta, ~35 ms de mediana (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}

Para un contrato de repositorio repetible que también gestiona el preflight, el servidor de desarrollo local, las capturas responsivas, la verificación de código fuente desactualizado y el informe de evidencia:

hwatu verify .hwatu/about.verify.json

El mismo ejecutor se expone a los clientes MCP como verify_ui, por lo que los arneses de agentes no reconstruyen el bucle de orquestación. Consulta la guía del agente.

¿HTML generado en mano y sin servidor? hwatu render es el mismo pase de una llamada con el marcado como entrada: sin archivo temporal, sin 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",...}}

Los clientes MCP llaman a subscribe_events para el mismo flujo que notifications/hwatu/event. Protocolo completo y bucles de verificación: guía del agente.

En otros lugares, headless se decide en el lanzamiento y un humano nunca puede ver la sesión. En hwatu es una propiedad de ventana, cambiable en vivo, en ambas direcciones: hwatu focus <id> promueve cualquier sesión headless a una ventana real para el humano, con el estado intacto.

challenge es solo detección y traspaso, por diseño: sin APIs de resolución, sin inyección de tokens, sin juegos de huellas.

El destino del traspaso

El traspaso funciona porque hwatu también es un navegador real, construido para WMs de mosaico. hwatu <url> abre una ventana como tu terminal abre un shell (tu WM es la barra de pestañas, no hay ninguna en la ventana): atajos de teclado convencionales (ctrl+l, ctrl+f, paleta ctrl+k, reconfigurables), bloqueo de anuncios nativo (~119k reglas EasyList compiladas en el motor de extensiones de contenido de WebKit, cero JS en la ruta de solicitud), desplazamiento estilo Chromium y controles unificados de formato corto. Cada ventana comparte el único daemon cálido (~56 MB por ventana extra), se suspende cuando no está enfocada y restaura tras un fallo en su última URL. Brechas honestas: sin Widevine ni passkeys en WebKitGTK. Configuraciones de WM (hyprland, sway, niri), atajos de teclado y configuración: docs/human.md.

hwatu as the hand-off destination: quarter-width window spawns and Chromium-curve scrolling in a tiling WM

Características

  • Headless / fondo / enfocado como propiedad por ventana, cambiable en vivo
  • Traspaso humano: hwatu focus <id> deja la sesión en vivo en tu WM de mosaico
  • Puntuación de diff de píxeles: porcentaje de coincidencia + regiones de diff + mapa de calor (diff)
  • Animaciones como números: duración, easing, velocidad (motion)
  • Fotogramas de animación deterministas: fija todas las animaciones en el tiempo t (seek)
  • Estado de página como JSON, tokens no píxeles (snapshot)
  • Eventos de entrada reales con errores estructurados (click / type / scroll / upload)
  • Errores de JS, salida de consola, solicitudes fallidas (console)
  • Suscripciones a eventos push como líneas JSON o notificaciones MCP (watch)
  • Aserciones de página en una llamada con polling (expect)
  • Detección de CAPTCHA / anti-bot con espera/reanudación estructurada (challenge)
  • Servidor MCP, CLI simple y protocolo de socket JSON de 1 línea
  • Un navegador real como destino de traspaso: atajos de teclado, medios, bloqueo de anuncios, restauración tras fallos

¿Por qué no Playwright o chrome-devtools-mcp?

Tres formas de darle un navegador a un agente:

Cómo se ejecutaQué le cuesta al bucle del agente
Biblioteca fría (Playwright, lanzada por tarea)el motor arranca cuando el script lo hacerápido de llamar, lento de ejecutar: cada verificación paga el arranque del motor; no sobrevive estado entre tareas
Navegador cálido (tu Chrome + devtools-mcp)un navegador humano completo permanece residenterecursos gastados en pestañas, extensiones, sincronización, UI que nunca renderizas, y sus ventanas roban tu foco mientras trabajas
hwatu"el daemon cálido más frío": motor caliente, todo lo demás ausentespawns de 8 ms, verificaciones de 35 ms, invisible hasta que tú pides verlo (focus), interrumpible en ambas direcciones

hwatu conserva exactamente lo que hace instantáneas las verificaciones (motor, contexto GPU, adblock compilado, una WebView precalentada) y nada que sirva a un humano a menos que ese humano pida una ventana. Por eso está inactivo cálido sin barra de pestañas, y por eso un servidor Playwright mantenido cálido impulsado de la misma manera cuesta 341 ms por cliente frente a los 39 de hwatu (benchmarks).

La segunda diferencia es lo que devuelve. Playwright y chrome-devtools-mcp son APIs de automatización: dejan que un agente conduzca un navegador, luego devuelven capturas y DOM crudos para inspeccionar. hwatu es un navegador de verificación: las primitivas de medición (check, diff, motion, expect) están integradas, una ventana cuesta 13 ms, y headless es una propiedad de ventana, no un modo de lanzamiento.

Cómo se compara hwatu

Leyenda: ✅ Sí / integrado · 🟡 Parcial / limitado · ❌ No

CapacidadPlaywrightchrome-devtools-mcphwatu
Pase de verificación (cargar + evaluar + captura), cálido en proceso82 msn/a35 ms
Pase de verificación como servicio cálido (cliente nuevo por verificación)341 msn/a39 ms
Llamadas de herramienta por pase de verificación551
Puntuación de diff de píxeles + regiones + mapa de calor🟡 1❌✅
Animaciones como números, fijadas a mitad de vuelo❌ 2🟡 3✅
Headless ↔ con ventana en una sesión en vivo❌❌✅
Traspaso humano a mitad de sesión, estado intacto❌❌✅
Sin robo de foco con N agentes paralelos🟡 4🟡 4✅
Detección de CAPTCHA + espera/reanudación estructurada❌❌✅
Sin Node, sin descarga de navegador por versión❌❌✅

1 toHaveScreenshot compara contra goldens almacenados: pasa/falla para suites de pruebas, no una puntuación que un agente pueda mejorar.

2 La práctica estándar es deshabilitar animaciones o avanzar rápido al estado final para evitar fallos intermitentes.

3 CDP crudo puede consultar el estado de animación, pero no hay resumen numérico de easing/velocidad/keyframes.

4 Bien headless; cada ventana con ventana emerge y toma el foco.

La comparación refleja cada proyecto al momento de escribir; las correcciones son bienvenidas. Advertencias honestas: Playwright aún gana en arranque en frío (190 vs 435 ms, pagado una vez por arranque) y memoria; hwatu renderiza WebKit no Chromium (mantén una matriz de Playwright en CI para errores específicos del motor), y es solo Linux hoy. Datos completos cara a cara y metodología: docs/benchmarks.md.

¿Qué pasa con Claude en Chrome? Categoría diferente. Claude en Chrome es un producto de agente que impulsa tu Chrome a través de una extensión, compartiendo tu perfil, pestañas y foco, no invocable por nada más. hwatu es un daemon agnóstico al cliente que cualquier agente llama por CLI/MCP, con su propio motor WebKit cálido, headless por defecto y primitivas de verificación integradas. Usa Claude en Chrome para que Claude navegue junto a ti; usa hwatu cuando los agentes necesiten verificaciones de página baratas, repetidas y medibles.

Retroalimentación

Una verificación exitosa, una instalación fallida, un atajo de teclado faltante y un sitio que se rompió son señales útiles. Comparte un informe de uso de dos minutos o reporta un error.


Licencia MIT. Linux. WebKitGTK 6.