
Llevar Chrome DevTools al terminal no es nuevo. Puppeteer, Playwright, `chrome --remote-debugging-port`... herramientas que funcionan bien pero que requieren escribir código, gestionar dependencias y mantener scripts. La CLI de `chrome-devtools-mcp` toma otro camino: un daemon persistente y un único binario que expone algunas de las herramientas de DevTools como subcomandos de shell.

Es experimental, pero ya cubre suficientes casos de uso para que valga la pena tenerla instalada.

## Instalación

```sh
npm i chrome-devtools-mcp@latest -g
chrome-devtools status
```

El daemon arranca automáticamente la primera vez que ejecutas cualquier comando. A partir de ahí, el mismo proceso de Chrome se reutiliza en todas las llamadas siguientes: las páginas abiertas, las cookies y el estado de la sesión persisten entre comandos.

```sh
# Parar el daemon cuando hayas terminado
chrome-devtools stop
```

Por defecto opera en modo `headless` y con contexto aislado. Si necesitamos un perfil de usuario real, lo podemos hacer así:

```sh
chrome-devtools start --no-headless --userDataDir ~/Library/Application\ Support/Google/Chrome
```

---

## Navegación

Los comandos de navegación son el punto de entrada para cualquier flujo automatizado.

```sh
# Abrir una nueva pestaña
chrome-devtools new_page "https://joanleon.dev"

# Navegar en la pestaña activa
chrome-devtools navigate_page --type url --url "https://web.dev"

# Recargar ignorando la caché
chrome-devtools navigate_page --type reload --ignoreCache

# Historial: atrás y adelante
chrome-devtools navigate_page --type back
chrome-devtools navigate_page --type forward

# Ver todas las pestañas abiertas
chrome-devtools list_pages

# Cambiar de pestaña activa
chrome-devtools select_page 2

# Cerrar una pestaña
chrome-devtools close_page 2
```

`navigate_page` admite un `initScript`: JavaScript que se inyecta en cada documento nuevo antes de que cargue cualquier otro script. Útil para interceptar APIs o modificar el entorno antes de que llegue el código de la página.

```sh
chrome-devtools navigate_page --type url --url "https://joanleon.dev" \
  --initScript "window.__PERF_MARK = Date.now()"
```

---

## Emulación

La emulación permite cambiar las condiciones de la página sin tocar el navegador manualmente.

```sh
# Emular red lenta
chrome-devtools emulate --networkConditions "Slow 3G"

# Throttling de CPU (factor 4x)
chrome-devtools emulate --cpuThrottlingRate 4

# Emular dispositivo móvil (viewport + touch)
chrome-devtools emulate --viewport "390x844x3,mobile,touch"

# Dark mode
chrome-devtools emulate --colorScheme dark

# Geolocalización (Madrid)
chrome-devtools emulate --geolocation "40.4168x-3.7038"

# User agent personalizado
chrome-devtools emulate --userAgent "Mozilla/5.0 (iPhone; ...)"

# Resetear todas las emulaciones
chrome-devtools emulate --networkConditions ""

# Cambiar tamaño de la ventana
chrome-devtools resize_page --width 1440 --height 900
```

Combinar throttling de red + CPU antes de ejecutar una auditoría reproduce con más fidelidad la experiencia en dispositivos de gama media, que es donde suelen aparecer los problemas de rendimiento reales.

---

## Interacción y automatización de input

Para interactuar con la página, primero necesitas los UIDs de los elementos. `take_snapshot` devuelve el árbol de accesibilidad con un identificador único para cada elemento.

```sh
# Obtener el árbol de accesibilidad con UIDs
chrome-devtools take_snapshot

# Hacer clic en un elemento
chrome-devtools click "element-uid-123"

# Doble clic
chrome-devtools click "element-uid-123" --dblClick

# Hover (útil para menús y tooltips)
chrome-devtools hover "element-uid-456"

# Rellenar un input
chrome-devtools fill "input-uid-789" "texto de búsqueda"

# Pulsar Enter después de rellenar
chrome-devtools press_key "Enter"

# Shortcut de teclado
chrome-devtools press_key "Control+Shift+R"

# Escribir texto en un input ya enfocado
chrome-devtools type_text "query" --submitKey "Enter"

# Subir un fichero
chrome-devtools upload_file --filePath "/ruta/archivo.png" --uid "input-file-uid"

# Aceptar o descartar diálogos del navegador
chrome-devtools handle_dialog "accept"
```

`take_snapshot` es preferible a `take_screenshot` cuando el objetivo es interactuar: el árbol de accesibilidad es más ligero y da los UIDs directamente. `take_screenshot` tiene sentido para capturas visuales o para comparar estados.

---

## Depuración

### Consola

`list_console_messages` expone los mensajes del panel Console sin abrir el navegador. Útil para detectar errores de JavaScript, warnings de terceros o logs de rendimiento después de una navegación automatizada.

```sh
# Listar todos los mensajes de consola
chrome-devtools list_console_messages

# Solo errores
chrome-devtools list_console_messages --types '["error"]'

# Obtener un mensaje concreto por ID
chrome-devtools get_console_message 42

# Incluir mensajes de las últimas 3 navegaciones
chrome-devtools list_console_messages --includePreservedMessages
```

### Ejecutar JavaScript

`evaluate_script` ejecuta una función en el contexto de la página y devuelve el resultado como JSON:

```sh
# Título de la página
chrome-devtools evaluate_script "() => document.title"

# Número de imágenes sin atributo alt
chrome-devtools evaluate_script "() => document.querySelectorAll('img:not([alt])').length"

# Tamaño del DOM
chrome-devtools evaluate_script "() => document.querySelectorAll('*').length"
```

Los scripts inline funcionan para casos simples, pero no escalan. La CLI no incluye un flag `--file` nativo por el momento ([issue #1775](https://github.com/ChromeDevTools/chrome-devtools-mcp/issues/1775)), pero la sustitución de comandos de shell resuelve exactamente eso:

```sh
# Ejecutar un script desde un archivo local
chrome-devtools evaluate_script "() => { $(cat scripts/medir-lcp.js) }"

# Ejecutar cualquier script del repositorio WebPerf Snippets
chrome-devtools evaluate_script "() => { $(cat ~/.claude/skills/webperf-core-web-vitals/scripts/LCP.js) }"
```

`evaluate_script` espera una función, no un bloque de código suelto. El wrapper `() => { ... }` es necesario cuando el script contiene múltiples sentencias.

Este es el comando que conecta directamente con los [WebPerf Snippets](https://webperf-snippets.nucliweb.net/). Cualquier snippet del repositorio puede leerse con `$(cat)` y pasarse a `evaluate_script` sin copiar su contenido ni abrir DevTools.

El flujo que describe el post [WebPerf Snippets y Agent SKILLs](/posts/webperf-snippets-agent-skills) usa exactamente esta mecánica: el agente lee el script del SKILL (por ejemplo `scripts/LCP.js`) y lo ejecuta vía `evaluate_script` en la página que está analizando. La diferencia entre hacerlo desde un agente y hacerlo desde la shell es mínima.

### Capturas

`take_screenshot` guarda el estado visual de la página en disco. Sirve para documentar resultados de auditorías, comparar estados antes y después de un cambio, o capturar elementos concretos por UID.

```sh
# Screenshot del viewport
chrome-devtools take_screenshot --filePath screenshot.png

# Página completa
chrome-devtools take_screenshot --filePath full.png --fullPage

# Solo un elemento (por UID)
chrome-devtools take_screenshot --filePath element.png --uid "hero-image-uid"

# Formato y calidad
chrome-devtools take_screenshot --filePath compressed.webp --format webp --quality 80
```

### Lighthouse

`lighthouse_audit` lanza una auditoría completa desde la terminal. Por defecto recarga la página en modo navegación, aunque también puede analizar el estado actual sin recargar.

```sh
# Auditoría en modo navegación (recarga la página)
chrome-devtools lighthouse_audit

# Auditoría del estado actual sin recargar
chrome-devtools lighthouse_audit --mode snapshot

# En móvil
chrome-devtools lighthouse_audit --device mobile

# Guardar el reporte en una carpeta
chrome-devtools lighthouse_audit --outputDirPath ./reports
```

> Importante: `lighthouse_audit` cubre accesibilidad, SEO y mejores prácticas. Para métricas de rendimiento (Core Web Vitals, LCP, INP, CLS) hay que usar las tools de Performance.

---

## Red

Analizar las peticiones de red desde la terminal es útil para detectar recursos sin caché, third-parties inesperados o respuestas lentas, sin necesidad de abrir el panel Network de DevTools.

```sh
# Listar todas las peticiones de red desde la última navegación
chrome-devtools list_network_requests

# Solo imágenes
chrome-devtools list_network_requests --resourceTypes '["image"]'

# Solo scripts y estilos
chrome-devtools list_network_requests --resourceTypes '["script","stylesheet"]'

# Paginación (100 primeras)
chrome-devtools list_network_requests --pageSize 100 --pageIdx 0

# Incluir peticiones de las últimas 3 navegaciones
chrome-devtools list_network_requests --includePreservedRequests

# Detalles de una petición concreta (por reqid)
chrome-devtools get_network_request 15

# Guardar la respuesta en disco
chrome-devtools get_network_request 15 --responseFilePath response.json
```

---

## Performance

Performance es el área con más profundidad de análisis: traza completa, insights automáticos y métricas Core Web Vitals desde la terminal.

```sh
# Navegar primero a la URL que quieres analizar
chrome-devtools navigate_page --type url --url "https://joanleon.dev"

# Iniciar la traza (con recarga automática)
chrome-devtools performance_start_trace --reload --autoStop

# O controlar manualmente cuándo parar
chrome-devtools performance_start_trace --reload
# ... interactuar con la página ...
chrome-devtools performance_stop_trace

# Guardar la traza en disco
chrome-devtools performance_stop_trace --filePath trace.json.gz
```

Una vez finalizada la traza, `performance_analyze_insight` da detalle sobre cada insight detectado:

```sh
# El resultado de performance_stop_trace incluye los insight sets disponibles
# Analizar un insight concreto
chrome-devtools performance_analyze_insight "LCPBreakdown" --insightSetId "set-id-del-resultado"
chrome-devtools performance_analyze_insight "DocumentLatency" --insightSetId "set-id-del-resultado"
```

Los insights incluyen métricas como `LCPBreakdown`, `DocumentLatency`, `RenderBlocking`, `SlowCSSSelector` y otras que corresponden exactamente a lo que Chrome DevTools muestra en el panel Performance Insights.

### Memoria

`take_memory_snapshot` genera una captura del heap de JavaScript en disco. El archivo resultante puede abrirse directamente en Chrome DevTools (panel Memory > Load) para analizar la distribución de objetos y detectar fugas de memoria sin haber tenido el navegador abierto durante la sesión.

```sh
# Captura del heap de JavaScript
chrome-devtools take_memory_snapshot --filePath heap.heapsnapshot
```

---

## Conexión con WebPerf Snippets y el WebPerf Skill

La CLI de `chrome-devtools-mcp` y los [WebPerf Snippets](https://webperf-snippets.nucliweb.net/) resuelven el mismo problema desde ángulos distintos.

En el post [WebPerf Snippets + WebMCP](/posts/webperf-snippets-webmcp) describí cómo los snippets pueden exponerse como herramientas estructuradas para agentes de IA vía WebMCP. En [WebPerf Snippets y Agent SKILLs](/posts/webperf-snippets-agent-skills) detallé cómo los SKILLs convierten esos mismos scripts en capacidades autónomas que un agente ejecuta en el navegador con Chrome DevTools MCP.

La CLI cierra el ciclo para uso manual: los mismos scripts que un agente lee del SKILL pueden ejecutarse directamente desde la shell con `evaluate_script`, sin necesidad de un LLM de por medio.

```sh
# Ejemplo: medir el LCP desde la terminal usando el script del SKILL
chrome-devtools navigate_page --type url --url "https://joanleon.dev"
chrome-devtools evaluate_script "() => { $(cat ~/.claude/skills/webperf-core-web-vitals/scripts/LCP.js) }"
```

El WebPerf Skill actúa como capa de orquestación cuando tienes un agente. La CLI actúa como capa de ejecución directa cuando trabajas sin agente. La lógica de medición, los umbrales y los scripts son los mismos en ambos casos.

---

## Salida en JSON y composición

La mayoría de comandos devuelven texto formateado por defecto. Con `--output-format=json` la salida es parseable, lo que permite componerla con `jq` o alimentar otros scripts de análisis.

```sh
chrome-devtools list_pages --output-format=json
chrome-devtools list_network_requests --output-format=json | jq '.[] | select(.status >= 400)'
```

---

## Depuración de la propia CLI

Si la CLI se queda colgada o no conecta al daemon:

```sh
chrome-devtools stop
chrome-devtools status
```

Para ver logs detallados:

```sh
DEBUG=* chrome-devtools list_pages
```

---

## Conclusión

La CLI de `chrome-devtools-mcp` no reemplaza Puppeteer ni Playwright para flujos de automatización complejos. Pero para inspección rápida, auditorías puntuales y scripts de CI ligeros, elimina casi todo el boilerplate: un daemon persistente, subcomandos directos y salida JSON cuando la necesitas.

En combinación con los WebPerf Snippets y el WebPerf Skill, tienes tres capas de acceso al mismo conjunto de herramientas de medición: la CLI para uso manual desde la terminal, los SKILLs para flujos autónomos con agentes, y WebMCP para cuando el estándar W3C madure en los navegadores.
