Volver a actualizaciones
Nuevo releaseJul 26, 2026

kuri v0.4.14

Automatización de navegadores, rastreo web y control de dispositivos iOS y Android para agentes de IA. Instantáneas CDP nativas en Zig y eficientes en tokens, grabación HAR, cliente nativo del protocolo de cable adb y un descargador independiente.

Compartir

Kuri

Kuri 🌰

Stable release License Zig node_modules status

Instalación```sh

curl -fsSL https://kuri.trilok.ai/download | sh

macOS arm64/x86_64 y Linux x86_64/arm64. Un único binario, sin dependencias de runtime.

Descargas directas: [macOS arm64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-aarch64-macos.tar.gz) · [macOS x86_64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-x86_64-macos.tar.gz) · [Linux x86_64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-x86_64-linux.tar.gz) · [Linux arm64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-aarch64-linux.tar.gz)

---

**Automatización de navegador y rastreo web para agentes de IA. Escrito en Zig. Cero Node.js.**

Automatización CDP · Instantáneas A11y · Grabación HAR · Descargador independiente · Navegador de terminal interactivo · CLI agéntico · Pruebas de seguridad · Control de dispositivos iOS y Android

[Inicio rápido](#-quick-start) · [Benchmarks](#-benchmarks) · [kuri-agent](#-kuri-agent) · [Pruebas de seguridad](#-security-testing) · [API](#-http-api) · [Habilidades](#-skills) · [Registro de cambios](https://github.com/justrach/kuri/blob/HEAD/CHANGELOG.md)

> **Por qué los equipos cambian a Kuri:** las compilaciones actuales de Apple Silicon con `ReleaseFast` siguen por debajo de 2 MB por binario, y una nueva ejecución de Google Flights del 23 de abril de 2026 midió **3,392 tokens** para un bucle completo de `kuri-agent` (`go→snap→click→snap→eval`). Las diferencias entre herramientas deben volver a ejecutarse en el mismo entorno antes de citar un porcentaje.

---

## Por qué Kuri gana para los agentes

La mayoría de las herramientas de navegador se crearon para ingenieros de QA. Kuri está construida para bucles de agente: lee la página, mantén bajo el coste de tokens, actúa sobre referencias estables y sigue adelante.

- **135 endpoints HTTP** — total paridad con agent-browser y browser-use, desde la inspección de React hasta Core Web Vitals.
- **7-12% menos tokens** que agent-browser en páginas reales gracias al formato de ref `@eN` y al renderizado sin prefijo.
- **Observaciones 44 veces más ligeras** con `/page/state` (48 tokens) frente a la instantánea completa (2,124 tokens) para la misma página de Google Flights.
- **Ejecución por lotes** — `POST /batch` envía N comandos en una sola llamada HTTP, eliminando N-1 round-trips y N-1 turnos de LLM.
- **Compatible con React** — los eventos de ratón CDP fiables y los eventos de tecla por carácter disparan `onClick` y `onChange` de React 18/19.

### Tokens de instantánea: Google Flights `SIN → TPE`

Nueva ejecución el 24 de mayo de 2026 en este espacio de trabajo, medida con `wc -c` y la aproximación `chars/4`.

| Herramienta / Modo | Caracteres | ~Tokens | Nota |
|---|---:|---:|---|
| `kuri snap` (completo) | 8,499 | **2,124** | Todos los nodos + refs interactivas |
| `kuri snap` (solo interactivo) | ~3,000 | **~750** | Lo mejor para bucles de agente |
| `kuri /page/state` | 190 | **48** | Observación ligera (url, título, scroll%, recuentos) |
| agent-browser snap (estimado) | ~9,183 | **~2,295** | Sobrecarga del formato `[ref=e0]` |

### Eficiencia de tokens: kuri vs agent-browser

| Página | tokens de kuri | tokens de agent-browser | Ahorro |
|---|---:|---:|---|
| example.com | 40 | 35 | -13% (página trivial, agent-browser omite la raíz) |
| Hacker News | 386 | ~440 | **12% menos** |
| Google Flights SIN→TPE | 2,124 | ~2,295 | **7% menos** |

El ahorro proviene del formato compacto de kuri:
- refs `@e0` (3 caracteres) frente a `[ref=e0]` (9 caracteres)
- Sin prefijo `- ` por línea (ahorra 2 caracteres × número de líneas)
- La misma sangría, el mismo filtrado de nodos

### Coste del flujo de trabajo completo: `go → snap → click → snap → eval`

| Herramienta | Tokens por ciclo |
|---|---:|
| **kuri-agent** | **~3,400** |
| Con `/page/state` en lugar del segundo snap | **~1,700** |
| Con `POST /batch` (todo en una llamada) | **~1,700** (mismos tokens, 1 llamada HTTP en lugar de 5) |

### kuri vs libretto

[libretto](https://github.com/saffron-health/libretto) (Playwright + Node) es el competidor más cercano en coste de tokens por paso. Medido cara a cara el 4 de julio de 2026 — mismo Chrome, misma pestaña, recuentos reales de `tiktoken` `o200k_base` (metodología completa y reproducción: **[benchmarks/libretto_comparison.md](https://github.com/justrach/kuri/blob/HEAD/benchmarks/libretto_comparison.md)**). El desglose honesto:

| Eje | Ganador | Detalle |
|---|---|---|
| Latencia por llamada | **kuri** | 4–117 ms frente a 1,344–1,500 ms (**13–376× más rápida** — servidor persistente frente a Node por comando) |
| Tokens de instantánea, página típica | **kuri** | simple 61 frente a 151 (2.5×), artículo 265 frente a 363 (1.37×) — gramática más ajustada |
| Tokens de instantánea, lista grande | dividido | kuri por defecto 4,424 frente a 813 — kuri emite los 259 refs, libretto trunca por defecto. Con `limit=5` kuri genera 555 tokens (**1.46× por debajo de libretto**), 34 refs + marcadores `… +45 more` |
| Trayectoria (feed, 9 clics) | **kuri**, por poco | 898 frente a 939 tokens (`limit=5` base + bucle de diff frente a bucle exec) — paridad con ligera ventaja; la pérdida de 5.1× de la mañana fue la base sin truncar |
| Ejecuciones repetidas | **libretto** | compila las trayectorias a un script de Playwright → reproducciones de 0 tokens; kuri vuelve a pagar el bucle en cada ejecución |

**Lo que kuri aprendió al estudiar libretto** (todo incluido en esta versión): un bucle de diff primero (`take_snapshot_diff`, ~38 tokens/paso); un diff adaptativo que recurre a una instantánea completa con un encabezado `! page replaced` al navegar; líneas de eliminación solo por identidad; capturas de pantalla escritas en disco (se devuelve la ruta, los bytes nunca entran en el contexto); `get_page_state` a través de MCP; y — después de reescribir `parseA11yNodes` como un recorrido real de árbol DFS — **truncamiento de listas opt-in** (`/snapshot?limit=N`, una línea `… +K more` por ejecución limitada), **recaptura con alcance** (`scope=@ref`) y **sangría jerárquica**, también expuestas como `uid`/`limit` en `take_snapshot` de MCP. La trayectoria de feed de 9 clics que costaba 44,285 tokens con reintentos completos ingenuos cuesta **898** con una base truncada + diffs — 49× más barata, y por debajo de los 939 de libretto.

> Las tablas anteriores usan una aproximación de tokens `chars/4`; la comparación con libretto usa recuentos reales de `tiktoken`. Vuelve a ejecutar las cifras entre herramientas en tu propio entorno antes de citar un porcentaje.

### Tamaño del binario y memoria

Medido en Apple M4 Pro, macOS 26.4.1. Los binarios actuales se compilaron con `-Doptimize=ReleaseFast`.

| Binario | Tamaño actual |
|---|---:|
| `kuri` | 1,093,840 B (1.04 MiB) |
| `kuri-agent` | 629,904 B (615 KiB) |
| `kuri-browse` | 1,089,120 B (1.04 MiB) |
| `kuri-fetch` | 2,063,488 B (1.97 MiB) |

### El RSS se mantuvo estable durante la migración a Zig 0.16

Medido contra la compilación actual `v0.4.3` `ReleaseFast` con `/usr/bin/time -l`.

| Comando | RSS máximo medio `v0.4.3` |
|---|---:|
| `kuri-fetch --version` | ~2.45 MiB |
| `kuri-browse --version` | ~2.45 MiB |
| `kuri-fetch --quiet --dump markdown http://example.com/` | ~9.17 MiB |

## El problema

Toda herramienta de automatización de navegador arrastra Playwright (~300 MB), un runtime de Node.js y una cascada de dependencias npm. Tu agente de IA solo quiere leer una página, hacer clic en un botón y seguir adelante.
**Kuri es un único binario de Zig.** Cuatro modos, cero runtime:```
kuri           →  CDP server (Chrome automation, a11y snapshots, HAR)
kuri-fetch     →  standalone fetcher (no Chrome, QuickJS for JS, ~2 MB)
kuri-browse    →  interactive terminal browser (navigate, follow links, search)
kuri-agent     →  agentic CLI (scriptable Chrome automation + security testing)

📦 Instalación

Instalación en una línea (macOS / Linux)```sh

curl -fsSL https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/install.sh | sh

Detecta tu plataforma, descarga el binario correcto y lo instala en `~/.local/bin`.
Las descargas provienen de la rama `release-channel` administrada por Kuri. Los binarios de macOS están firmados localmente con un certificado de Developer ID. Los recursos de GitHub Release reflejan estos mismos tarballs.

### bun / npm```sh
bun install -g kuri-agent
# or: npm install -g kuri-agent

Descarga el binario nativo correcto para tu plataforma en el momento de la instalación.

Canal de lanzamiento

Los binarios estables de Kuri viven en la rama release-channel y se sirven directamente desde las URLs raw de GitHub.

  • Instalador estable: https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/install.sh
  • Manifiesto estable: https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/latest.json
  • Vista de la rama: https://github.com/justrach/kuri/tree/release-channel/stable
  • Patrón de descarga directa: https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/<version>/kuri-<version>-<target>.tar.gz

Manual

Descarga el tarball para tu plataforma desde el manifiesto de lanzamiento estable o desde la página de lanzamientos de GitHub y descomprímelo en tu $PATH.

URL de instalación estable:```sh curl -fsSL https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/install.sh | sh

El manifiesto incluye URLs exactas de los recursos y sumas de comprobación SHA-256 para `aarch64-linux`, `x86_64-linux`, `aarch64-macos` y `x86_64-macos`.

### Soporte de plataformas

| Plataforma | Estado |
|---|---|
| macOS (`aarch64`, `x86_64`) | Binarios precompilados, firmados y notarizados |
| Linux (`aarch64`, `x86_64`) | Binarios precompilados |
| Windows (`x86_64`) | **Experimental — solo compilación cruzada.** `zig build -Dtarget=x86_64-windows-gnu` está verificado por CI, pero la automatización de Chrome, la daemonización, el apagado basado en señales, la grabación de HAR y el almacén de autenticación respaldado por archivos están todos implementados como stubs con `error.UnsupportedOnWindows` en tiempo de ejecución. Usa **WSL2** si necesitas el conjunto de características real. Seguimiento en [#153](https://github.com/justrach/kuri/issues/153). |

Kuri se apoya en primitivas POSIX (`fork`, `clock_gettime`, sockets crudos) en varios puntos, por lo que un puerto nativo completo para Windows es un trabajo considerable. La línea base de compilación anterior permite que las rutas `--version`/`--help` y las operaciones puramente en memoria funcionen; las partes complicadas (Chrome, sockets, daemonización) necesitan implementaciones Win32 reales antes de salir de la lista de stubs. Si quieres encargarte de alguna de ellas, deja un +1 en [#153](https://github.com/justrach/kuri/issues/153) o abre un PR.

### Compilar desde el código fuente

Requiere [Zig ≥ 0.16.0](https://ziglang.org/download/).```bash
git clone https://github.com/justrach/kuri.git
cd kuri
zig build -Doptimize=ReleaseFast
# Binaries in zig-out/bin/: kuri  kuri-agent  kuri-fetch  kuri-browse

⚡ Inicio rápido

Requisitos: Zig ≥ 0.16.0 · Chrome/Chromium (para el modo CDP)```bash git clone https://github.com/justrach/kuri.git cd kuri

zig build # build everything zig build test # run 252+ tests

CDP mode — launches Chrome automatically

./zig-out/bin/kuri

Standalone mode — no Chrome needed

./zig-out/bin/kuri-fetch https://example.com

Interactive browser — browse from your terminal

./zig-out/bin/kuri-browse https://example.com

Experimental standalone browser runtime — separate build, not production

(cd kuri-browser && zig build run -- render https://example.com) (cd kuri-browser && zig build run -- bench --offline)

### Primera ejecución, camino más corto```bash
# start the server; if CDP_URL is unset, kuri launches managed Chrome for you
./zig-out/bin/kuri

# discover tabs from that managed browser
curl -s http://127.0.0.1:8080/discover

# inspect the discovered tab list
curl -s http://127.0.0.1:8080/tabs

Bucle de agente con sesión prioritaria

Para uso HTTP de estilo agente, prefiere un encabezado de sesión junto con /tab/new, /page/info y /snapshot en lugar de repetir tab_id en cada llamada.```bash SESSION=hn-demo BASE=http://127.0.0.1:8080

curl -s -H "X-Kuri-Session: $SESSION"
"$BASE/tab/new?url=https%3A%2F%2Fnews.ycombinator.com"

curl -s -H "X-Kuri-Session: $SESSION" "$BASE/page/info" SNAP=$(curl -s -H "X-Kuri-Session: $SESSION" "$BASE/snapshot?filter=interactive&format=compact") MORE_REF=$(printf '%s' "$SNAP" | python3 -c 'import re,sys; print(re.search(r""More" @(e\d+)", sys.stdin.read()).group(1))') curl -s -H "X-Kuri-Session: $SESSION" "$BASE/action?action=click&ref=$MORE_REF" curl -s -H "X-Kuri-Session: $SESSION" "$BASE/page/info"

También hay un wrapper experimental ligero en `tools/kuri_harness.py` si quieres helpers de Python sobre la misma superficie HTTP.

Si ya tienes Chrome ejecutándose con depuración remota, establece `CDP_URL` a cualquiera de los endpoints WebSocket o HTTP:```bash
CDP_URL=ws://127.0.0.1:9222/devtools/browser/... ./zig-out/bin/kuri
# or
CDP_URL=http://127.0.0.1:9222 ./zig-out/bin/kuri

1. Discover Chrome tabs

curl -s http://localhost:8080/discover

→ {"discovered":1,"total_tabs":1}

2. Get tab ID

curl -s http://localhost:8080/tabs

→ [{"id":"ABC123","url":"chrome://newtab/","title":"New Tab"}]

3. Navigate

curl -s "http://localhost:8080/navigate?tab_id=ABC123&url=https://vercel.com"

4. Get accessibility snapshot (token-optimized for LLMs)

curl -s "http://localhost:8080/snapshot?tab_id=ABC123&filter=interactive"

→ [{"ref":"e0","role":"link","name":"VercelLogotype"},

{"ref":"e1","role":"button","name":"Ask AI"}, ...]

---

## 🌐 HTTP API

Todos los endpoints devuelven JSON. Autenticación opcional mediante la variable de entorno `KURI_SECRET`. **135 endpoints** — paridad completa con agent-browser y browser-use.

### Core

| Path | Description |
|------|-------------|
| `GET /health` | Estado del servidor, número de pestañas, versión |
| `GET /tabs` | Listar todas las pestañas registradas |
| `GET /discover` | Descubrir automáticamente pestañas de Chrome vía CDP |
| `GET /tab/current` | Obtener o establecer la pestaña actual para una `X-Kuri-Session` |
| `GET /page/info` | URL/título/ready-state/viewport/scroll en vivo para la pestaña activa |
| `GET /page/state` | Observación compacta de la página: url, título, scroll%, viewport, recuentos de formularios/enlaces/imágenes/inputs |
| `POST /batch` | Ejecutar múltiples comandos en una sola llamada HTTP — devuelve un array de resultados |
| `GET /browdie` | 🌰 (huevo de pascua) |

### Browser Control

| Path | Params | Description |
|------|--------|-------------|
| `GET /navigate` | `tab_id`, `url` | Navegar la pestaña a una URL |
| `GET /tab/new` | `url`, `activate`, `wait` | Crear una nueva pestaña y opcionalmente hidratar/establecer la pestaña actual |
| `GET /tab/close` | `tab_id` | Cerrar una pestaña |
| `GET /window/new` | `url`, `activate`, `wait` | Crear un nuevo objetivo de ventana/pestaña |
| `GET /snapshot` | `tab_id`, `filter`, `format` | Instantánea del árbol A11y con referencias `eN`. Usa `filter=interactive&format=compact` para bucles de agente de bajo consumo de tokens. |
| `GET /text` | `tab_id` | Extraer texto de la página |
| `GET /screenshot` | `tab_id`, `format`, `quality`, `save` | Capturar captura de pantalla (base64); `save=true` escribe el PNG en `STATE_DIR/screenshots` y en su lugar devuelve `{path,bytes}` |
| `GET /screenshot/annotated` | `tab_id` | Captura de pantalla con etiquetas numéricas de elementos |
| `GET /screenshot/diff` | `tab_id`, `baseline` | Diferencia visual entre la captura actual y la de referencia |
| `GET /action` | `tab_id`, `ref`, `action`, `value` | Hacer clic/escribir/rellenar/seleccionar/desplazar/pasar el cursor/doble clic/marcar/desmarcar/desenfocar por ref |
| `GET /evaluate` | `tab_id`, `expression` | Ejecutar JavaScript |
| `GET /evalhandle` | `tab_id`, `expression` | Ejecutar JS, devolver el handle objectId (no el valor) |
| `GET /close` | `tab_id` | Cerrar pestaña + limpieza |
| `GET /bringtofront` | `tab_id` | Traer la pestaña al frente |

### Actions

| Path | Params | Description |
|------|--------|-------------|
| `GET /clear` | `ref` | Borrar el valor del campo de entrada |
| `GET /selectall` | `ref` | Seleccionar todo el texto en input/contenteditable |
| `GET /setvalue` | `ref`, `value` | Establecer el valor de entrada directamente (omite los eventos de teclado) |
| `GET /dispatch` | `ref`, `type` | Despachar un evento DOM personalizado en el elemento |
| `GET /boundingbox` | `ref` | Obtener el rectángulo delimitador del elemento (x, y, width, height, centerX, centerY) |
| `GET /getattribute` | `ref`, `name` | Obtener el atributo del elemento por nombre |
| `GET /inputvalue` | `ref` | Obtener el valor actual del elemento de entrada |
| `GET /element/state` | `ref`, `check` | Booleano rápido: `exists`, `visible`, `enabled`, `checked` |
| `GET /find-element` | `text`/`role`/`label`/`placeholder`/`testid` | Localizador semántico — encontrar elemento sin snapshot |
| `GET /highlight` | `ref` or `selector` | Resaltar elemento con superposición |

### Mouse & Touch

| Path | Params | Description |
|------|--------|-------------|
| `GET /mouse/move` | `x`, `y` | Mover el ratón a las coordenadas |
| `GET /mouse/down` | `x`, `y`, `button` | Presionar botón del ratón |
| `GET /mouse/up` | `x`, `y`, `button` | Soltar botón del ratón |
| `GET /mouse/wheel` | `x`, `y`, `deltaX`, `deltaY` | Desplazamiento con la rueda del ratón |
| `GET /tap` | `x`, `y` | Toque táctil (touchStart + touchEnd) |
| `GET /swipe` | `startX`, `startY`, `endX`, `endY` | Gesto de deslizamiento táctil |
| `GET /drag` | `src_ref`, `tgt_ref` | Arrastrar elemento al objetivo |

### Keyboard

| Path | Params | Description |
|------|--------|-------------|
| `GET /keyboard/type` | `tab_id`, `text` | Escribir texto mediante eventos de teclado |
| `GET /keyboard/inserttext` | `tab_id`, `text` | Insertar texto directamente |
| `GET /keydown` | `tab_id`, `key` | Evento de tecla presionada |
| `GET /keyup` | `tab_id`, `key` | Evento de tecla liberada |

### Content Extraction

| Path | Description |
|------|-------------|
| `GET /markdown` | Convertir página a Markdown |
| `GET /links` | Extraer todos los enlaces |
| `GET /dom/query` | Consulta de selector CSS |
| `GET /dom/html` | Obtener el HTML del elemento |
| `GET /dom/attributes` | Obtener los atributos del elemento |
| `GET /pdf` | Imprimir página a PDF |
| `GET /find` | Búsqueda de texto en la página |

### Waiting

| Path | Params | Description |
|------|--------|-------------|
| `GET /wait` | `selector`, `text`, `url`, `state`, `visible`, `timeout` | Esperar selector/texto/patrón de URL/networkidle/estado de carga |
| `GET /wait/function` | `expression`, `timeout` | Esperar a que una expresión JS arbitraria sea verdadera |
| `GET /wait/download` | `timeout` | Esperar a que se complete la descarga del archivo |

### Dialog Handling

| Path | Description |
|------|-------------|
| `GET /dialog/auto` | Manejar automáticamente todos los diálogos JS (aceptar o descartar) |
| `GET /dialog/accept` | Aceptar el diálogo actual (con texto de aviso opcional) |
| `GET /dialog/dismiss` | Descartar el diálogo actual |

### Network & HAR

| Path | Description |
|------|-------------|
| `GET /har/start` | Comenzar a grabar tráfico de red |
| `GET /har/stop` | Detener + devolver JSON HAR 1.2 |
| `GET /har/status` | Estado de grabación + número de entradas |
| `GET /har/replay` | Mapa de API con fragmentos de código curl/fetch/python |
| `GET /cookies` | Obtener cookies |
| `GET /cookies/set` | Establecer cookies |
| `GET /cookies/delete` | Eliminar cookies |
| `GET /cookies/clear` | Borrar todas las cookies |
| `GET /headers` | Establecer cabeceras de solicitud personalizadas |
| `GET /intercept/start` | Comenzar la intercepción de solicitudes |
| `GET /intercept/stop` | Detener la intercepción de solicitudes |
| `GET /intercept/requests` | Listar solicitudes interceptadas |
| `GET /request/detail` | Obtener el cuerpo de la respuesta para un ID de solicitud |
| `GET /response/body` | Obtener URL y devolver el cuerpo de la respuesta |
| `GET /network` | Estadísticas de tráfico de red |
| `GET /download` | Activar descarga de archivo |

### Navigation & State

| Path | Description |
|------|-------------|
| `GET /back` | Volver en el navegador |
| `GET /forward` | Avanzar en el navegador |
| `GET /reload` | Recargar página |
| `GET /stop` | Detener la carga de la página |
| `GET /pushstate` | Navegación SPA mediante history.pushState |
| `GET /storage/local` | Obtener/establecer localStorage |
| `GET /storage/session` | Obtener/establecer sessionStorage |
| `GET /storage/local/clear` | Borrar localStorage |
| `GET /storage/session/clear` | Borrar sessionStorage |
| `GET /session/save` | Guardar sesión del navegador |
| `GET /session/load` | Restaurar sesión del navegador |
| `GET /session/list` | Listar sesiones guardadas |
| `GET /setcontent` | Establecer el HTML de la página directamente (POST) |

### Auth Profiles

| Path | Description |
|------|-------------|
| `GET /auth/profile/save` | Guardar cookies + almacenamiento como un perfil de autenticación con nombre |
| `GET /auth/profile/load` | Restaurar un perfil de autenticación con nombre en una pestaña |
| `GET /auth/profile/list` | Listar perfiles de autenticación guardados |
| `GET /auth/profile/delete` | Eliminar un perfil de autenticación guardado |
| `GET /auth/extract` | Extraer tokens de autenticación (JWT, cookies, cabeceras) |
| `GET /set/credentials` | Establecer credenciales de autenticación básica HTTP |

En macOS, los secretos de los perfiles de autenticación se almacenan en el Keychain del usuario.

### Emulation

| Path | Params | Description |
|------|--------|-------------|
| `GET /emulate` | tipo de dispositivo, tamaño de pantalla | Emulación de dispositivo |
| `GET /set/viewport` | `width`, `height` | Establecer el tamaño del viewport |
| `GET /set/useragent` | `ua` | Establecer el user agent |
| `GET /set/media` | `media` | Emular tipo de medio |
| `GET /set/offline` | `offline` | Alternar modo sin conexión |
| `GET /geolocation` | `lat`, `lng` | Anular la geolocalización |
| `GET /timezone` | `timezone` | Anular la zona horaria (p. ej. `America/New_York`) |
| `GET /locale` | `locale` | Anular la configuración regional (p. ej. `en-US`) |
| `GET /permissions` | `name`, `state` | Conceder/denegar permisos (geolocalización, notificaciones, portapapeles) |

### Scripts & Injection

| Path | Description |
|------|-------------|
| `GET /script/inject` | Inyectar JavaScript en la página (persiste entre navegaciones) |
| `GET /initscript/remove` | Eliminar un script de inicialización previamente inyectado |
| `GET /addstyle` | Inyectar hoja de estilos CSS |
| `GET /expose` | Exponer una función con nombre al contexto JS de la página |

### React Inspection

| Path | Description |
|------|-------------|
| `GET /react/tree` | Árbol de componentes React mediante el hook de DevTools |
| `GET /react/inspect` | Props y estado de componentes React |
| `GET /react/renders` | Seguimiento de renderizado React (iniciar/detener) |
| `GET /react/suspense` | Estado del límite de Suspense de React |

### Recording & Performance

| Path | Description |
|------|-------------|
| `GET /recording/start` | Grabar acciones del usuario (click, input, navigate) |
| `GET /recording/stop` | Detener grabación + devolver registro de acciones |
| `GET /vitals` | Core Web Vitals (LCP, CLS, FID, TTFB, FCP, domInteractive) |
| `GET /perf/lcp` | Tiempo de Largest Contentful Paint |
| `GET /trace/start` | Iniciar traza de rendimiento |
| `GET /trace/stop` | Detener traza |
| `GET /profiler/start` | Iniciar perfilador JS |
| `GET /profiler/stop` | Detener perfilador |

### Debugging

| Path | Description |
|------|-------------|
| `GET /debug/enable` | Activar HUD de depuración en la página y modo de congelación opcional |
| `GET /debug/disable` | Desactivar HUD de depuración en la página |
| `GET /inspect` | Inspección de elementos |
| `GET /errors` | Recopilar errores JS |
| `GET /console` | Leer registros de consola |
| `GET /frames` | Listar frames de la página |
| `GET /frame` | Cambiar al contexto de iframe por nombre o URL |
| `GET /mainframe` | Volver al frame principal |
| `GET /diff/snapshot` | Diff compacto `+`/`~`/`-` frente a la llamada anterior de esta pestaña — el bucle de acciones eficiente en tokens (alias de `/snapshot/changes`). Recurre a una instantánea completa con una cabecera `! page replaced` en cambios masivos. |
| `GET /diff/url` | Comparar dos URLs una al lado de la otra (navigate, snapshot, diff) |

### Streaming

| Path | Description |
|------|-------------|
| `GET /screencast/start` | Iniciar grabación de pantalla |
| `GET /screencast/stop` | Detener grabación de pantalla |
| `GET /video/start` | Iniciar captura de video |
| `GET /video/stop` | Detener captura de video |
| `GET /ws/start` | Iniciar túnel WebSocket |
| `GET /ws/stop` | Detener túnel WebSocket |

### Agent-friendly loop

El bucle de servidor de menor fricción es:

1. `GET /tab/new?url=...`
2. `GET /page/state` (ligero) o `GET /snapshot?filter=interactive&format=compact` (completo)
3. `GET /action?action=click&ref=eN`
4. Repetir — o usar `POST /batch` para operaciones de varios pasos en una sola llamada

Los parámetros de consulta `url` y `expression` se decodifican (percent-decoding). Envía `X-Kuri-Session: my-agent` para conservar el contexto de la pestaña en el servidor.

---

## 🧠 Skills

El repositorio incluye un área de skills extensible por el usuario:

- `skills/kuri-skill.md` es el skill base del agente HTTP Kuri
- `skills/custom/` está reservado para tus propias skills específicas del proyecto
- `skills/custom/hackernews-page-2.md` es un ejemplo concreto de skill personalizada
- `.claude/skills/kuri-server/SKILL.md` se mantiene sincronizado para skills de repositorio estilo Claude

El skill base ahora también explica qué ruta de navegador usar:

- `kuri` HTTP API: automatización Chrome/CDP en producción con sesiones, instantáneas, acciones, HAR, cookies y capturas de pantalla
- `kuri-fetch`: extracción de fetch/texto independiente, sin Chrome
- `kuri-browse`: navegación interactiva por terminal
- `kuri-agent`: automatización CLI programable contra el servidor Kuri
- `kuri-browser/`: runtime de navegador experimental independiente nativo en Zig para trabajos de paridad

Para la CLI de navegador experimental:```bash
cd kuri-browser
zig build run -- render https://news.ycombinator.com --selector ".titleline a" --dump text
zig build run -- render https://todomvc.com/examples/react/dist/ --js --wait-eval "document.querySelectorAll('.todo-list li').length >= 1"
zig build run -- parity --offline
zig build run -- bench --offline
zig build run -- serve-cdp --port 9333

kuri-browser serve-cdp expone el descubrimiento HTTP estilo Chrome además de un enrutador mínimo de JSON-RPC sobre WebSocket para pruebas de humo del protocolo. La evaluación en tiempo de ejecución devuelve objetos remotos CDP con forma de V8 respaldados por QuickJS; esto no añade una dependencia de V8 y aún no es compatibilidad completa con Playwright/Puppeteer.

Las capturas de pantalla en kuri-browser actualmente delegan en el renderizador principal de Kuri/CDP. Inicia primero ./zig-out/bin/kuri y luego:```bash cd kuri-browser zig build run -- screenshot https://example.com --out example.jpg --compress --kuri-base http://127.0.0.1:8080

`--compress` captura una línea base PNG y un candidato JPEG, escribe el archivo más pequeño e informa el ahorro de bytes. Medición local actual en `https://example.com`: `20,523` bytes PNG a `18,183` bytes JPEG calidad 50, ahorrando `2,340` bytes o `11%`.

### Avanzado

| Path | Description |
|------|-------------|
| `GET /diff/snapshot` | Delta compacto `+`/`~`/`-` frente a la instantánea anterior (bucle de acciones del agente) |
| `GET /emulate` | Emulación de dispositivo |
| `GET /geolocation` | Establecer geolocalización |
| `POST /upload` | Subida de archivo |
| `GET /script/inject` | Inyectar JavaScript |
| `GET /intercept/start` | Iniciar interceptación de solicitudes |
| `GET /intercept/stop` | Detener interceptación |
| `GET /screenshot/annotated` | Captura de pantalla con anotaciones de elementos |
| `GET /screenshot/diff` | Diferencia visual entre capturas de pantalla |
| `GET /screencast/start` | Iniciar screencast |
| `GET /screencast/stop` | Detener screencast |
| `GET /video/start` | Iniciar grabación de video |
| `GET /video/stop` | Detener grabación de video |
| `GET /console` | Obtener mensajes de consola |
| `GET /stop` | Detener la carga de la página |
| `GET /get` | Obtención HTTP directa (del lado del servidor) |
| `GET /scrollintoview` | Desplazar un elemento referenciado a la vista |
| `GET /drag` | Arrastrar de una referencia a otra |
| `GET /keyboard/type` | Escribir texto con eventos de teclado |
| `GET /keyboard/inserttext` | Insertar texto directamente |
| `GET /keydown` | Despachar un evento keydown |
| `GET /keyup` | Despachar un evento keyup |
| `GET /wait` | Esperar el estado ready o condiciones de elementos |
| `GET /tab/close` | Cerrar una pestaña |
| `GET /highlight` | Resaltar un elemento por referencia o selector |
| `GET /errors` | Obtener errores de página/tiempo de ejecución |
| `GET /set/offline` | Alternar emulación de red sin conexión |
| `GET /set/media` | Establecer características de medios emulados |
| `GET /set/credentials` | Establecer credenciales de autenticación básica HTTP |
| `GET /find` | Buscar coincidencias de texto en la página actual |
| `GET /trace/start` | Iniciar traza de Chrome |
| `GET /trace/stop` | Detener la traza y devolver los datos de la traza |
| `GET /profiler/start` | Iniciar el perfilador de JS |
| `GET /profiler/stop` | Detener el perfilador de JS |
| `GET /inspect` | Inspeccionar un elemento o el estado de la página |
| `GET /set/viewport` | Establecer el tamaño del viewport |
| `GET /set/useragent` | Anular el user agent |
| `GET /dom/attributes` | Obtener atributos de elementos |
| `GET /frames` | Listar el árbol de frames |
| `GET /network` | Inspeccionar el estado/solicitudes de red |

---

## 🛡️ Sigilo y evasión de bots

Kuri aplica parches antidetección automáticamente al iniciar: no se necesita configuración manual.

### Qué se aplica

- **`Page.addScriptToEvaluateOnNewDocument`** — los parches de sigilo se ejecutan antes de cualquier JS de la página
- **navigator.webdriver = false** — oculta la marca de automatización a nivel de Chromium (`--disable-blink-features=AutomationControlled`)
- **Suplantación de WebGL/Canvas/AudioContext** — derrota la detección basada en huellas digitales
- **Rotación de UA** — 5 user agents realistas de Chrome/Safari/Firefox
- **chrome.csi/chrome.loadTimes** — stubs para comprobaciones específicas de Akamai

### Detección de bloqueo de bots

Navigate detecta automáticamente los bloqueos y devuelve un fallback estructurado:```bash
curl -s "http://localhost:8080/navigate?tab_id=ABC&url=https://protected-site.com"
# If blocked:
# {"blocked":true,"blocker":"akamai","ref_code":"0.7d...",
#  "fallback":{"suggestions":["Open URL directly in browser","Use KURI_PROXY"]}}
# If ok: normal CDP response

Detecta: Akamai, Cloudflare, PerimeterX, DataDome, captcha genérico.

Soporte de proxy```bash

KURI_PROXY=socks5://user:pass@residential-proxy:1080 ./zig-out/bin/kuri KURI_PROXY=http://proxy:8080 ./zig-out/bin/kuri

### Sitios probados

| Sitio | Protección | Resultado |
|------|-----------|--------|
| Singapore Airlines | Akamai WAF | ✅ Evadido (estaba bloqueado antes de v0.4.0) |
| Shopee SG | Antifraude personalizado | ✅ La página carga, redirige al inicio de sesión |
| Google Flights | Ninguna | ✅ Interacción completa |
| Booking.com | PerimeterX | ⚠️ Necesita proxy |

---

## 🔧 kuri-fetch

Fetcher HTTP independiente: sin Chrome, sin Playwright, sin npm. Se distribuye como un binario de ~2 MB con QuickJS integrado para ejecución de JS.```bash
zig build fetch    # build + run

# Default: convert to Markdown
kuri-fetch https://example.com

# Extract links
kuri-fetch -d links https://news.ycombinator.com

# Structured JSON output
kuri-fetch --json https://example.com

# Execute inline scripts via QuickJS
kuri-fetch --js https://example.com

# Write to file, quiet mode
kuri-fetch -o page.md -q https://example.com

# Pipe-friendly: content → stdout, status → stderr
kuri-fetch -d text https://example.com | wc -w

Características

  • 5 modos de salidamarkdown, html, links, text, json
  • Motor JS QuickJS--js ejecuta etiquetas <script> en línea
  • Stubs DOMdocument.querySelector, getElementById, window.location, document.title, console.log, setTimeout (estilo SSR)
  • Defensa contra SSRF — bloquea IPs privadas, endpoints de metadatos, esquemas no HTTP
  • Salida de color — respeta NO_COLOR, TERM=dumb, --no-color, detección de TTY
  • Salida a archivo-o / --output con recuento de bytes + resumen de tiempo
  • UA personalizado — opción --user-agent
  • Modo silencioso-q suprime el estado de stderr

🌐 kuri-browse

Navegador de terminal interactivo — navega por la web desde tu terminal. No necesitas Chrome.```bash zig build browse # build + run

kuri-browse https://example.com

I don't see any content to translate. The input after "INPUT:" is empty. Please provide the Markdown chunk you'd like translated.```
🌰 kuri-browse — terminal browser
→ loading https://example.com

# Example Domain
This domain is for use in documentation examples...
Learn more [1]

───── Links ─────
  [1] https://iana.org/domains/example

✓ 528 bytes, 1 links (133ms)
[nav] https://example.com> 1     ← type 1 to follow the link

Commands

CommandAction
<number>Seguir enlace [N]
<url>Navegar (si contiene .)
:go <url>Navegar a URL
:back, :bVolver en el historial
:forward, :fAvanzar
:reload, :rRecargar la página actual
:links, :lMostrar índice de enlaces
/<term>Buscar en la página (resalta coincidencias)
:search <t>Buscar en la página
:n, :nextVolver a resaltar la búsqueda
:historyMostrar historial de navegación
:help, :hMostrar todos los comandos
:quit, :qSalir

Features

  • Renderizado de markdown en color — encabezados, enlaces, bloques de código, negrita, citas
  • Enlaces numerados — cada enlace recibe [N], escribe el número para seguirlo
  • Historial de navegación — atrás/adelante como en un navegador real
  • Búsqueda en la página/term resalta todas las coincidencias
  • Resolución de URL relativas — sigue enlaces de forma natural entre páginas
  • Filtrado inteligente — omite los href javascript: y mailto:

🤖 kuri-agent

CLI programable para la automatización de Chrome: controla el navegador comando por comando desde tu terminal o scripts de shell. Comparte el estado de la sesión entre invocaciones a través de ~/.kuri/session.json.```bash zig build agent # build kuri-agent

1. Find a Chrome tab

kuri-agent tabs

→ ws://127.0.0.1:9222/devtools/page/ABC123 https://example.com

2. Attach to it

kuri-agent use ws://127.0.0.1:9222/devtools/page/ABC123

3. Navigate + interact

kuri-agent go https://example.com kuri-agent snap --interactive # → [{"ref":"e0","role":"link","name":"More info"}] kuri-agent click e0 kuri-agent shot # saves ~/.kuri/screenshots/.png

### Comandos

| Comando | Descripción |
|---------|-------------|
| `tabs [--port N]` | Lista las pestañas de Chrome |
| `use <ws_url>` | Conecta a una pestaña (guarda la sesión) |
| `open [url] [--port N]` | Abre una nueva pestaña (navegando opcionalmente a url) |
| `status` | Muestra la sesión actual |
| `go <url>` | Navega a la URL |
| `snap [--interactive] [--json] [--text] [--depth N]` | Instantánea de accesibilidad (A11y), guarda las referencias `eN` |
| `click <ref>` | Haz clic en el elemento por ref (eventos de ratón CDP, compatible con React) |
| `type <ref> <text>` | Escribe en el elemento (eventos de tecla por carácter, compatible con React) |
| `fill <ref> <text>` | Rellena el valor del input |
| `select <ref> <value>` | Selecciona la opción del menú desplegable |
| `hover <ref>` | Pasa el cursor sobre el elemento |
| `focus <ref>` | Enfoca el elemento |
| `scroll` | Desplaza la página |
| `viewport [width height]` | Obtiene o establece las dimensiones del viewport |
| `eval <js>` | Evalúa JavaScript |
| `text [selector]` | Obtiene el texto de la página |
| `shot [--out file.png]` | Captura de pantalla |
| `back` | Navega hacia atrás |
| `forward` | Navega hacia adelante |
| `reload` | Recarga la página actual |
| `cookies` | Lista las cookies con flags de seguridad |
| `headers` | Comprueba las cabeceras de seguridad de la respuesta |
| `audit` | Auditoría de seguridad completa |
| `storage [local\|session\|all]` | Vuelca localStorage / sessionStorage |
| `jwt` | Extrae y decodifica los JWT de las cookies y del almacenamiento |
| `fetch <method> <url> [--data <json>]` | Fetch autenticado usando las cookies de la página |
| `probe <url-template> <start> <end>` | Sondeo IDOR: itera los IDs numéricos en la URL |
| `grab <ref>` | Haz clic en ref, intercepta `window.open`, sigue la redirección en la pestaña |
| `wait-for-tab [--port N]` | Sondea una nueva pestaña, cambia de sesión automáticamente |
| `stealth` | Aplica parches anti-detección |
| `set-header <name> <value>` | Añade una cabecera personalizada a todas las peticiones |
| `show-headers` | Muestra las cabeceras adicionales almacenadas |
| `clear-headers` | Elimina todas las cabeceras adicionales |
---

## 📱 kuri-mobile (iOS + Android)

CLI nativa en Zig para controlar simuladores de iOS, iPhones reales (listado + inicio/terminación) y dispositivos/emuladores Android — inspirada en [`mobile-device-mcp`](https://github.com/srmorete/mobile-device-mcp), reimplementada en Zig sin Bun/Node/Gradle/Xcode en la ruta de compilación.```bash
cd kuri-mobile && zig build && cp zig-out/bin/kuri-mobile ../zig-out/bin/

# The main `kuri` binary forwards android/ios subcommands to kuri-mobile:
kuri ios list-devices                              # sims + real devices (usbmuxd, native)
kuri ios openurl https://example.com               # navigate Safari
kuri ios screenshot out.png                        # auto-picks booted sim
kuri ios launch com.apple.Preferences

kuri android list-devices                          # native Zig adb wire-protocol client
kuri android tap 540 1200
kuri android swipe 100 1500 100 500
kuri android screenshot phone.png
kuri android uitree                                # flat element list via uiautomator dump

Qué es nativo de Zig: protocolo host de adb (sockets libc, tramas de 4 hex sobre host:transport:/shell:/exec:), analizador del árbol XML de la UI de Android, cliente plist ListDevices de usbmuxd. Qué se ejecuta vía shell: xcrun simctl (iOS Simulator), xcrun devicectl (lanzar/terminar en dispositivos iOS reales). Sin driver por diseño: no se instala ninguna app en el dispositivo, por lo que los sandboxes de run_code y el tap/uitree respaldado por XCUITest en dispositivos iOS reales están intencionadamente no disponibles. Consulta kuri-mobile/README.md para la matriz de paridad completa frente a upstream.


🔒 Pruebas de Seguridad

kuri-agent soporta trayectorias de seguridad nativas del navegador: inicia sesión una vez y luego ejecuta reconocimiento y auditorías de cabeceras/cookies sin salir de la terminal.

Trayectorias

Enumerar → Inspeccionar — tras la autenticación, vuelca las cookies de auth y comprueba los flags de seguridad:```bash kuri-agent go https://target.example.com/login kuri-agent snap --interactive kuri-agent fill e2 myuser kuri-agent fill e3 mypassword kuri-agent click e4 # submit login

kuri-agent cookies

cookies (3):

session_id domain=.example.com path=/ [Secure] [HttpOnly] [SameSite=Strict]

csrf_token domain=.example.com path=/ [Secure] [!HttpOnly]

tracking domain=.example.com path=/ [!Secure] [!HttpOnly]

**Auditoría de cabeceras** — comprueba qué cabeceras de seguridad envía el objetivo:```bash
kuri-agent go https://target.example.com
kuri-agent headers
# → {"url":"https://...","status":200,"headers":{
#     "content-security-policy":"default-src 'self'",
#     "strict-transport-security":"max-age=31536000",
#     "x-frame-options":"(missing)",
#     "x-content-type-options":"nosniff", ...}}

Auditoría completa — HTTPS, cabeceras faltantes, cookies visibles en JS de una sola vez:```bash kuri-agent audit

→ {"protocol":"https:","url":"https://...","score":6,

"issues":["MISSING:x-frame-options","COOKIES_EXPOSED_TO_JS:2"],

"headers":{"content-security-policy":"default-src 'self'", ...}}

**Trayectoria entre cuentas** — usar `eval` para reproducir llamadas a la API con diferentes tokens:```bash
# After login, grab the auth token from localStorage
kuri-agent eval "localStorage.getItem('token')"

# Probe a resource ID with the current session
kuri-agent eval "fetch('/api/assessments/42').then(r=>r.status)"

# Check for IDOR: does a different user's resource return 200 or 403?
kuri-agent eval "fetch('/api/assessments/99').then(r=>r.status)"

Formato de informe de trayectoria

kuri-agent genera JSON apto para la integración en pipelines. Cada comando de seguridad emite una única línea JSON — pásala por jq para el triaje:```bash kuri-agent audit | jq '.issues[]' kuri-agent cookies | head -20 kuri-agent headers | jq '.headers | to_entries[] | select(.value == "(missing)") | .key'

---


## 🏗 Arquitectura```
┌──────────────────────────────────────────────────────────┐
│                     HTTP API Layer                        │
│         (std.http.Server, thread-per-connection)          │
├──────────────┬──────────────────┬────────────────────────┤
│   Browser    │  Crawler Engine  │   kuri-fetch / browse   │
│   Bridge     │                  │   (standalone CLIs)     │
├──────────────┼──────────────────┼────────────────────────┤
│ CDP Client   │ URL Validator    │ std.http.Client         │
│ Tab Registry │ HTML→Markdown    │ QuickJS JS Engine       │
│ A11y Snapshot│ Link Extractor   │ DOM Stubs (Layer 3)     │
│ Ref Cache    │ Text Extractor   │ SSRF Validator          │
│ HAR Recorder │                  │ Colored Renderer        │
│ Stealth JS   │                  │ History + REPL          │
├──────────────┴──────────────────┴────────────────────────┤
│  Chrome Lifecycle Manager                                 │
│  (launch, health-check, auto-restart, port detection)     │
└──────────────────────────────────────────────────────────┘

Memory Model

  • Arena por solicitud — toda la memoria por solicitud se libera en una sola llamada deinit()
  • Sin GCGeneralPurposeAllocator en modo debug detecta cada fuga
  • Cadenas de limpieza adecuadasLauncher → Bridge → CdpClients → HarRecorders → Snapshots → Tabs
  • Guardas errdefer — los fallos parciales se revierten limpiamente

Chrome Lifecycle

ModoComportamiento
Gestionado (sin CDP_URL)Lanza Chrome headless, encuentra un puerto CDP libre, lo supervisa, se reinicia automáticamente ante fallos (máx. 3 reintentos), y lo cierra al apagarse
Externo (CDP_URL configurado)Se conecta a un Chrome existente, verifica el estado mediante /json/version, NO lo cierra al apagarse

📁 Estructura```

kuri/ ├── build.zig # Build system (Zig 0.16.0) ├── build.zig.zon # Package manifest + QuickJS dep ├── src/ │ ├── main.zig # CDP server entry point │ ├── fetch_main.zig # kuri-fetch CLI entry point │ ├── browse_main.zig # kuri-browse CLI entry point │ ├── js_engine.zig # QuickJS wrapper + DOM stubs │ ├── bench.zig # Benchmark harness │ ├── chrome/ │ │ └── launcher.zig # Chrome lifecycle manager │ ├── server/ │ │ ├── router.zig # HTTP route dispatch (40+ endpoints) │ │ ├── middleware.zig # Auth (constant-time comparison) │ │ └── response.zig # JSON response helpers │ ├── bridge/ │ │ ├── bridge.zig # Central state (tabs, CDP, HAR, snapshots) │ │ └── config.zig # Env var configuration │ ├── cdp/ │ │ ├── client.zig # CDP WebSocket client │ │ ├── websocket.zig # WebSocket frame codec │ │ ├── protocol.zig # CDP method constants │ │ ├── actions.zig # High-level CDP actions │ │ ├── stealth.zig # Bot detection bypass │ │ └── har.zig # HAR 1.2 recorder │ ├── snapshot/ │ │ ├── a11y.zig # A11y tree with interactive filter │ │ ├── diff.zig # Snapshot delta diffing │ │ └── ref_cache.zig # eN ref → node ID cache │ ├── crawler/ │ │ ├── validator.zig # SSRF defense, URL validation │ │ ├── markdown.zig # HTML → Markdown (SIMD tag counting) │ │ ├── fetcher.zig # Page fetching │ │ ├── extractor.zig # Readability extraction │ │ └── pipeline.zig # Parallel crawl pipeline │ ├── storage/ │ │ ├── local.zig # Local file writer │ │ └── r2.zig # R2/S3 uploader │ ├── util/ │ │ └── json.zig # JSON helpers │ └── test/ │ ├── harness.zig # Test HTTP client │ ├── integration.zig # Integration tests │ └── merjs_e2e.zig # E2E tests ├── js/ │ ├── stealth.js # Bot detection bypass │ └── readability.js # Content extraction ├── kuri-browser/ # Native Zig rendering experiments └── kuri-mobile/ # iOS + Android device control (Zig-native adb + usbmuxd) ├── src/ │ ├── common/ # io helpers, unified UI tree parser │ ├── android/ # adb wire protocol client, driver, CLI │ └── ios/ # simctl, usbmuxd, devicectl, CLI └── README.md # Full parity matrix vs mobile-device-mcp

---

## ⚙️ Configuración

| Variable de entorno | Predeterminado | Descripción |
|---------|---------|-------------|
| `HOST` | `127.0.0.1` | Dirección de enlace del servidor |
| `PORT` | `8080` | Puerto del servidor |
| `CDP_URL` | *(none)* | Conectar a un Chrome existente (`ws://...` o `http://127.0.0.1:9222`) |
| `KURI_SECRET` | *(none)* | Secreto de autenticación para solicitudes API |
| `STATE_DIR` | `.kuri` | Directorio de estado de la sesión |
| `REQUEST_TIMEOUT_MS` | `30000` | Tiempo de espera de solicitud HTTP |
| `NAVIGATE_TIMEOUT_MS` | `30000` | Tiempo de espera de navegación |
| `STALE_TAB_INTERVAL_S` | `30` | Intervalo de limpieza de pestañas obsoletas |
| `NO_COLOR` | *(none)* | Deshabilitar salida CLI de colores |

---

## 💰 Costo de tokens

Para una tarea de monitoreo de 50 páginas (de los puntos de referencia de Pinchtab):

| Método | Tokens | Costo ($) | Mejor para |
|--------|--------|----------|----------|
| `/text` | ~40,000 | $0.20 | Lectura intensiva (13× más barato que las capturas de pantalla) |
| `/snapshot?filter=interactive&format=compact` | ~40,000 | $0.20 | Interacción con elementos de bajo consumo de tokens |
| `/snapshot` (completo) | ~525,000 | $2.63 | Comprensión completa de la página |
| `/screenshot` | ~100,000 | $1.00 | Verificación visual |

---

## 🤝 Contribuciones

Abre un issue antes de enviar un PR grande para que podamos alinear el enfoque.```bash
git clone https://github.com/justrach/kuri.git
cd kuri
zig build test         # 252+ tests must pass
zig build test-fetch   # kuri-fetch tests (69 tests)
zig build test-browse  # kuri-browse tests (22 tests)

Consulta CONTRIBUTORS.md para obtener las directrices.


Créditos

ProyectoQué hemos tomado prestado
agent-browserSistema de referencia @eN, comparación de instantáneas, patrones de grabación HAR
PinchtabArquitectura de control de navegador para agentes de IA
PathikPatrones de rastreo de alto rendimiento
QuickJS-ng vía mitchellh/zig-quickjs-ngMotor JS para kuri-fetch
LightpandaPionero de navegadores headless nativos de Zig, patrones de compatibilidad con CDP
Zig 0.16.0Todo el stack

Licencia

Apache-2.0

Categorías