DOMShell

Navega por la web con comandos del sistema de archivos. 38 herramientas MCP permiten a los agentes de IA ejecutar ls, cd, grep, clic y escritura a través de Chrome mediante una extensión de Chrome.

Documentación

DOMShell

           | |
        ___|_|___
       |___|_|___|
       |   | |   |
       |___|_|___|
        /  | |  \
       /   | |   \
      |____|_|____|
      |           |
      |  DOMSHELL |
      |           |
      |___________|
      |###########|
      |###########|
       \#########/
        \_______/
 
  ██   ██ ██ ███████
  ██   ██ ██   ███
  ███████ ██   ██
  ██░░░██ ██   ██
  ██   ██ ██   ██
  ░░   ░░ ░░   ░░
   ███████ ██   ██ ███████
     ███   ███████ ██░░░░░
     ███   ██░░░██ █████
     ███   ██   ██ ██░░░
     ███   ██   ██ ███████
     ░░░   ░░   ░░ ░░░░░░░
   ██████   ██████  ███    ███  ██
   ██   ██ ██    ██ ████  ████  ██
   ██   ██ ██    ██ ██ ████ ██  ██
   ██   ██ ██    ██ ██  ██  ██  ░░
   ██████   ██████  ██      ██  ██
   ░░░░░░   ░░░░░░  ░░      ░░  ░░

El navegador es tu sistema de archivos. Una extensión de Chrome que permite a los agentes de IA (y a los humanos) navegar por la web usando comandos estándar de Linux — ls, cd, cat, grep, click — a través de una terminal en el Panel Lateral de Chrome.

Instalar desde Chrome Web Store | paquete npm | Leer el artículo del blog | Página del proyecto

DOMShell mapea el navegador en un sistema de archivos virtual. Las ventanas y pestañas se convierten en directorios de nivel superior (~). El Árbol de Accesibilidad de cada pestaña se convierte en un sistema de archivos anidado donde los elementos contenedores son directorios y los botones, enlaces e inputs son archivos. Navega por Chrome de la misma manera en que navegarías por /usr/local/bin.

Por qué

Los agentes de IA que interactúan con sitios web suelen depender de capturas de pantalla, coordenadas de píxeles o selectores CSS frágiles. DOMShell adopta un enfoque diferente: expone el propio Árbol de Accesibilidad del navegador como una metáfora familiar de sistema de archivos.

Esto significa que un agente puede:

  • Navegar por pestañas con ls ~/tabs/ y cambiar con cd ~/tabs/123 en lugar de adivinar qué pestaña está activa
  • Explorar una página con ls y tree en lugar de analizar capturas de pantalla
  • Navegar hacia secciones con cd navigation/ en lugar de adivinar coordenadas
  • Actuar sobre elementos con click submit_btn en lugar de consultas DOM frágiles
  • Leer contenido con cat o extraer en masa con text en lugar de raspar innerHTML
  • Buscar elementos con find --type combobox en lugar de escribir selectores

La abstracción del sistema de archivos es determinista, semántica y funciona en cualquier sitio web — no se necesitan adaptadores específicos por sitio.

Instalación

Chrome Web Store (Recomendado)

Instala DOMShell directamente desde la Chrome Web Store. No se requiere paso de compilación.

Desde el código fuente

git clone https://github.com/apireno/DOMShell.git
cd DOMShell
npm install
npm run build

Cargar en Chrome

  1. Abre chrome://extensions/
  2. Activa Modo desarrollador (interruptor en la esquina superior derecha)
  3. Haz clic en Cargar descomprimida
  4. Selecciona la carpeta dist/
  5. Haz clic en el icono de DOMShell en tu barra de herramientas — se abre el panel lateral

Uso

Primeros pasos

Abre cualquier página web y luego abre el panel lateral de DOMShell. Verás una terminal:

╔══════════════════════════════════════╗
║   DOMShell v1.1.0                    ║
║   The browser is your filesystem.    ║
╚══════════════════════════════════════╝

Type 'help' to see available commands.
Type 'tabs' to see open browser tabs, then 'cd tabs/<id>' to enter one.

dom@shell:~$

Comienzas en ~ (la raíz del navegador). Salta directamente a la pestaña activa con here, o explora:

dom@shell:~$ ls
  windows/       (2 windows)
  tabs/          (5 tabs)

dom@shell:~$ here
✓ Entered tab 123
  Title: Google
  URL:   https://google.com
  AX Nodes: 247

Navegación por pestañas y ventanas

# List all open tabs
dom@shell:~$ tabs
  ID     TITLE                       URL                        WIN
  123    Google                       google.com                 1
  124    GitHub - apireno             github.com/apireno         1
  125    Wikipedia                    en.wikipedia.org                 2

# Switch to a tab by ID
dom@shell:~$ cd tabs/125
✓ Entered tab 125
  Title: Wikipedia
  URL:   https://en.wikipedia.org
  AX Nodes: 312

# You're now inside the tab's DOM tree
dom@shell:~$ pwd
~/tabs/125

# Go back to browser level
dom@shell:~$ cd ~
dom@shell:~$

# Or use substring matching
dom@shell:~$ cd tabs/github
✓ Entered tab 124 (GitHub - apireno)

# List windows (shows tabs grouped under each window)
dom@shell:~$ windows
Window 1 (focused)
├── *123   Google                        google.com
├──  124   GitHub - apireno              github.com/apireno
└──  125   Wikipedia                     en.wikipedia.org

Window 2
├── *126   Stack Overflow                stackoverflow.com
└──  127   MDN Web Docs                  developer.mozilla.org

# Browse a specific window's tabs
dom@shell:~$ cd windows/2
dom@shell:~/windows/2$ ls
  ID     TITLE                       URL
  125    Wikipedia                    en.wikipedia.org
  126    LinkedIn                     linkedin.com

También puedes navegar o abrir nuevas pestañas:

# Navigate the current tab to a URL (requires being inside a tab)
dom@shell:~$ navigate https://example.com

# Open a URL in a new tab (works from anywhere)
dom@shell:~$ open https://github.com
✓ Opened new tab
  URL:   https://github.com
  Title: GitHub
  AX Nodes: 412

Grupos de pestañas (aislamiento)

Por defecto, DOMShell opera en tu navegador general — modo compartido, exactamente como antes. El comando group coloca una sesión en su propio grupo de pestañas aislado de Chrome, de modo que el agente trabaje en un carril claramente marcado mientras tú sigues navegando libremente en otras pestañas:

# Create an isolated tab group and work inside it
dom@shell:~$ group new research
✓ Created isolated group '🐚 research'  [id 4]
  Working tab: 312

# While isolated, every command is confined to the group's tabs —
# entering a tab outside the group is rejected:
dom@shell:~$ cd tabs/126
cd: tab 126 is outside the session group (id 4). ...

# Show the current mode and group
dom@shell:~$ group
Group mode: isolated
  Group: 🐚 research  [id 4]
  Tabs:  1

# Leave the group (it stays open) — back to shared mode
dom@shell:~$ group detach

# Close the group's DOMShell tabs (your own tabs are kept)
dom@shell:~$ group close

Subcomandos: group (estado), group new [name], group attach <id>, group detach, group close, group list. El modo aislado mantiene al agente fuera de tus otras pestañas; el modo compartido es el predeterminado y no ha cambiado.

Cuando un cliente MCP se conecta, DOMShell automáticamente le da a esa sesión su propio grupo 🐚 agent nuevo. El grupo se deja abierto cuando la sesión se desconecta (no destructivo) — se instruye al agente para que pregunte si deseas que se cierre antes de finalizar, y siempre puedes limpiar los restos tú mismo con group close.

Multi-sesión. Cada cliente de DOMShell obtiene su propio carril de sesión — cada ventana del panel lateral, cada conexión MCP, aisladas por separado. Dos paneles laterales en dos ventanas de Chrome mantienen posiciones independientes; múltiples agentes MCP concurrentes trabajan cada uno en su propio grupo 🐚 agent con su propio cursor. Ejecuta group list en cualquier momento para ver todos los carriles activos; group close <id> para cerrar uno.

Múltiples agentes en una conexión MCP. Algunos clientes MCP (por ejemplo, Claude Desktop) comparten una conexión entre todos los chats — por lo que por defecto dos chats en el mismo cliente caerían en un mismo carril. Cada chat puede crear su propio carril pasando el parámetro group_id a domshell_execute: pasa "new" para crear uno nuevo (su id se devuelve al final de la respuesta como [lane: <id>]), y luego pasa ese id en cada llamada posterior. Dos chats → dos carriles → sin colisiones. Los agentes también pueden usar esto para transferencia — un agente informa su id de carril, el siguiente agente lo pasa como group_id y continúa en el mismo estado. Se instruye a los agentes para que cierren cualquier carril que hayan creado cuando la tarea esté completa.

Navegación por el DOM

Una vez que estás dentro de una pestaña, el Árbol de Accesibilidad aparece como un sistema de archivos:

# List children of the current node
dom@shell:~$ ls
navigation/
main/
complementary/
contentinfo/
skip_to_content_link
logo_link

# Long format shows type prefixes and roles
dom@shell:~$ ls -l
[d] navigation     navigation/
[d] main           main/
[x] link           skip_to_content_link
[x] link           logo_link

# Filter by type
dom@shell:~$ ls --type link
skip_to_content_link
logo_link

# Show DOM metadata (href, src, id) inline — great for finding URLs
dom@shell:~$ ls --meta --type link
[x] link           skip_to_content_link  href=https://example.com/#content <a>
[x] link           logo_link             href=https://example.com/ <a>

# Paginate large directories
dom@shell:~$ ls -n 10              # First 10 items
dom@shell:~$ ls -n 10 --offset 10  # Items 11-20

# Count children by type
dom@shell:~$ ls --count
45 total (12 [d], 28 [x], 5 [-])

# Enter a directory (container element)
dom@shell:~$ cd navigation

# See where you are
dom@shell:~$ pwd
~/tabs/125/navigation

# Go back up
dom@shell:~$ cd ..

# Jump to browser root
dom@shell:~$ cd ~

# Multi-level paths work too
dom@shell:~$ cd main/article/form

# Path variable: %here% expands to the focused tab (via its window)
dom@shell:~$ cd %here%           # Enter the active tab
dom@shell:~$ cd %here%/..        # Go to the window containing the active tab
dom@shell:~$ cd %here%/main      # Enter the active tab and cd into main

Prefijos de tipo

Cada nodo tiene un prefijo de tipo que comunica metadatos sin depender solo del color:

PrefijoSignificadoEjemplos
[d]Directorio (contenedor, se puede hacer cd)navigation/, form/, main/
[x]Interactivo (clicable/enfocable)botones, enlaces, inputs, casillas de verificación
[-]Estático (solo lectura)encabezados, imágenes, texto

Lectura de contenido

# Inspect an element — cat shows full AX + DOM metadata
dom@shell:~$ cat submit_btn
--- submit_btn ---
  Role:  button
  Type:  [x] interactive
  AXID:  42
  DOM:   backend#187
  Tag:   <button>
  ID:    submit-form
  Class: btn btn-primary
  Text:  Submit Form
  HTML:  <button id="submit-form" class="btn btn-primary">Submit Form</button>

# cat on a link reveals the href URL
dom@shell:~$ cat Read_more
--- Read_more ---
  Role:  link
  Type:  [x] interactive
  AXID:  98
  DOM:   backend#312
  Tag:   <a>
  URL:   https://en.wikipedia.org/wiki/Article_Title
  Text:  Read more
  HTML:  <a href="https://en.wikipedia.org/wiki/Article_Title">Read more</a>

# Navigate to parent to find its properties (e.g. span inside a link)
dom@shell:~$ cd ..
dom@shell:~$ cat parent_link

# Bulk extract ALL text from a section (one call instead of 50+ cat calls)
dom@shell:/main$ text
[textContent of /main — 4,821 chars]
Heading: Welcome to Our Site
Today we announce the launch of our new product...
(full article text continues)

# Extract text from a specific child
dom@shell:~$text main
[textContent of main — 4,821 chars]

# Limit output length
dom@shell:~$text main -n 500

# Include link URLs inline as markdown [text](url)
dom@shell:~$text --links main/article/paragraph_2978
--- Text (with links): paragraph_2978 ---
Artificial intelligence (AI) is the capability of [computational systems](https://en.wikipedia.org/wiki/Computer)
to perform tasks typically associated with [human intelligence](https://en.wikipedia.org/wiki/Human_intelligence),
such as [learning](https://en.wikipedia.org/wiki/Learning), [reasoning](https://en.wikipedia.org/wiki/Reason)...
(text + link URLs in a single call)

# Get a tree view (default depth: 2)
dom@shell:~$tree
navigation/
├── [x] home_link
├── [x] about_link
├── [x] products_link
└── [x] contact_link

# Deeper tree
dom@shell:~$tree 4

Búsqueda

# Search current directory
dom@shell:~$grep login
[x] login_btn (button)
[d] login_form (form)
[x] login_link (link)

# Recursive search across all descendants
dom@shell:~$grep -r search
[x] search_search (combobox)
[x] search_btn (button)

# Limit results
dom@shell:~$grep -r -n 5 link

# Deep search with full paths (like Unix find)
dom@shell:~$find search
[x] /search_2/search_search (combobox)
[x] /search_2/search_btn (button)

# Find by role type
dom@shell:~$find --type combobox
[x] /search_2/search_search (combobox)

dom@shell:~$find --type textbox
[x] /main/form/email_input (textbox)
[x] /main/form/name_input (textbox)

# Limit results
dom@shell:~$find --type link -n 5

# Find all links with their URLs (great for content extraction)
dom@shell:~$find --type link --meta
[x] /nav/home_link (link)  href=https://example.com/ <a>
[x] /main/Read_more (link)  href=https://example.com/article <a>

Encadenamiento de comandos (composición estilo Bash)

DOMShell funciona como un sistema de archivos — usa el mismo modelo mental que para buscar archivos en disco. grep descubre dónde vive el contenido (como grep -r en bash), cd delimita tu contexto, y text/cat/find lee el contenido (como cat/head/less). El operador de tubería (|) filtra la salida, igual que en bash.

El patrón es: grep (localizar) → cd (delimitar) → extract (leer).

# Workflow 1: Find and read an article section
dom@shell:~$ grep -r article
[d] article (article)  →  ./main/article/
dom@shell:~$ cd main/article
dom@shell:~/main/article$ text
[full article content in one call]

# Workflow 2: Find a section and extract its links
dom@shell:~$ grep -r references
[d] references (region)  →  ./main/article/references/
dom@shell:~$ cd main/article/references
dom@shell:~/main/article/references$ find --type link --meta
[x] /wiki_link (link)  href=https://en.wikipedia.org/... <a>
[x] /paper_link (link)  href=https://arxiv.org/... <a>

# Workflow 3: Find a table and extract structured data
dom@shell:~$ grep -r table
[d] table_4091 (table)  →  ./main/section/table_4091/
dom@shell:~$ extract_table table_4091
| Name   | Value  | Date       |
|--------|--------|------------|
| Alpha  | 42     | 2025-01-15 |
| Beta   | 87     | 2025-02-20 |

# Workflow 4: Discover sections, then drill into one
dom@shell:~$ grep -r heading
[−] Introduction_heading (heading)  →  ./main/article/Introduction_heading
[−] Methods_heading (heading)  →  ./main/article/Methods_heading
[−] Results_heading (heading)  →  ./main/article/Results_heading
dom@shell:~$ cd main/article/Results_heading
dom@shell:~/main/article/Results_heading$ text
[text content of the Results section]

# Workflow 5: Find elements by visible text (not just name)
dom@shell:~$ grep -r --content "sign up"
[x] get_started_btn (button)  →  ./main/hero/get_started_btn
# The button's NAME is "get_started_btn" but its displayed text says "Sign Up Free"
dom@shell:~$ click get_started_btn

Operador de tubería

El operador de tubería (|) te permite filtrar la salida de comandos, igual que en bash:

# Filter find results to only GitHub links
dom@shell:~$ find --type link --meta | grep github
[x] /main/repo_link (link)  href=https://github.com/example <a>

# Filter ls output to elements mentioning "login"
dom@shell:~$ ls --text | grep login
[x] login_btn  "Log in to your account"

# Limit results with head
dom@shell:~$ find --type heading | head -n 3
[−] /main/intro_heading (heading)
[−] /main/features_heading (heading)
[−] /main/pricing_heading (heading)

# Chain multiple pipes
dom@shell:~$ find --type link --meta | grep docs | head -n 5

Resolución de rutas

Todos los comandos aceptan rutas relativas, eliminando la necesidad de hacer cd primero:

# Read text from a nested element directly
dom@shell:~$ text main/article/paragraph_2971

# Click a button inside a form without cd'ing
dom@shell:~$ click main/form/submit_btn

# Inspect a link in the nav
dom@shell:~$ cat navigation/home_link

Navegación entre hermanos

Usa las banderas --after y --before en ls para encontrar contenido relativo a un punto de referencia:

# Show the 3 elements after a heading
dom@shell:~$ ls --after See_also_heading -n 3 --text
[d] related_topics_list  "Machine Learning, Deep Learning, Neural..."
[−] paragraph_4512       "For more information on these topics..."
[x] Read_more_link       "Read more on Wikipedia"

# Find links after a specific section heading
dom@shell:~$ ls --after References_heading --type link --meta
[x] source_1_link (link)  href=https://arxiv.org/... <a>
[x] source_2_link (link)  href=https://doi.org/... <a>

La idea clave: la salida de grep alimenta a cd, y cd delimita todo lo demás. Cuando no sabes dónde vive el contenido en una página, primero haz grep, luego delimita, y luego extrae.

Interacción con elementos

# Click a button or link
dom@shell:~$click submit_btn
✓ Clicked: submit_btn (button)
(tree will auto-refresh on next command)

# Focus an input field
dom@shell:~$focus email_input
✓ Focused: email_input

# Type into the focused field
dom@shell:~$type hello@example.com
✓ Typed 17 characters

# Navigate to a URL (current tab)
dom@shell:~$navigate https://example.com
✓ Navigated to https://example.com

# Open a URL in a new tab
dom@shell:~$open https://github.com
✓ Opened new tab → https://github.com

Actualización automática ante cambios en el DOM

DOMShell detecta automáticamente cuando la página cambia — navegación, mutaciones del DOM o actualizaciones de contenido por clics. Ya no necesitas ejecutar refresh manualmente:

dom@shell:~$click search_btn
✓ Clicked: search_btn (button)
(tree will auto-refresh on next command)

dom@shell:~$ls
(page changed — tree refreshed, 312 nodes, path reset to tab root)
main/
navigation/
search_results/
...

Si la página navegó, el CWD se restablece a la raíz de la pestaña. Si el DOM solo se actualizó en su lugar, tu CWD se conserva. Aún puedes forzar una actualización manual:

dom@shell:~$refresh
✓ Refreshed. 312 AX nodes loaded.

Autocompletado con tabulador

Presiona Tab para autocompletar comandos y nombres de elementos — funciona como bash:

dom@shell:$ ta<Tab>
# completes to: tabs

dom@shell:$ cd nav<Tab>
# completes to: cd navigation/

dom@shell:$ click sub<Tab>
# if multiple matches, shows options:
#   submit_btn
#   subscribe_link
  • Coincidencia única: autocompleta en línea
  • Múltiples coincidencias: muestra opciones debajo, completa el prefijo común más largo
  • cd solo completa directorios; otros comandos completan todos los elementos

Soporte de pegado

Cmd+V (Mac) / Ctrl+V (Windows/Linux) pega texto directamente en la terminal. Los pegados de varias líneas se aplastan a una sola línea.

Comandos del sistema

# Check if you're authenticated (reads cookies)
dom@shell:~$whoami
URL: https://example.com
Status: Authenticated
Via: session_id
Expires: 2025-12-31T00:00:00.000Z
Total cookies: 12

# Environment variables
dom@shell:~$env
SHELL=/bin/domshell
TERM=xterm-256color

# Set a variable
dom@shell:~$export API_KEY=sk-abc123

# Debug the raw AX tree
dom@shell:~$debug stats
--- Debug Stats ---
  Total AX nodes:   247
  Ignored nodes:    83
  Generic nodes:    41
  With children:    62
  Iframes:          2

Obtener ayuda

Cada comando admite --help:

dom@shell:$ ls --help
ls — List children of the current node

Usage: ls [options]

Options:
  -l, --long      Long format: type prefix, role, and name
  -r, --recursive Show nested children (one level deep)
  -n N            Limit output to first N entries
  --offset N      Skip first N entries (for pagination)
  --type ROLE     Filter by AX role (e.g. --type button)
  --count         Show count of children only
...

Referencia de comandos

Nivel de navegador

ComandoDescripción
tabsLista todas las pestañas abiertas (atajo para ls ~/tabs/)
windowsLista todas las ventanas con sus pestañas agrupadas debajo
hereSalta a la pestaña activa en la ventana enfocada
cd ~Ir a la raíz del navegador
cd ~/tabs/<id>Cambiar a una pestaña por ID (entra automáticamente)
cd ~/tabs/<pattern>Cambiar a una pestaña por coincidencia de subcadena en título/URL
cd ~/windows/<id>Explorar las pestañas de una ventana
navigate <url>Navegar la pestaña actual a una URL
open <url>Abrir una URL en una pestaña nueva y entrar en ella
backRetroceder en el historial del navegador (como el botón atrás)
forwardAvanzar en el historial del navegador
close [tab-id]Cerrar la pestaña actual (o una pestaña específica por ID)

Árbol DOM

ComandoDescripción
ls [options]Listar hijos (-l, --meta, --text, -r, -n N, --offset N, --type ROLE, --count, --after NAME, --before NAME, --json)
cd <path>Navegar (.., ~ o / para la raíz del navegador, %here% para la pestaña enfocada, main/form para múltiples niveles)
pwdImprimir la ruta actual (ruta DOM o ruta del navegador)
tree [depth]Vista de árbol del nodo actual (profundidad predeterminada: 2)
cat <name> [--json]Metadatos completos del elemento: información AX + propiedades DOM (tag, href, src, id, class, outerHTML)
text [name] [-n N] [--links]Extraer en masa todo el texto de una sección (--links inserta URLs como [text](url))
read [name] [opts]Extracción estructurada de subárbol (--meta, --text, -d N profundidad) — árbol y contenido en una sola llamada
grep [opts] <pattern>Buscar por nombre/rol/valor (-r recursivo, --content coincidir texto visible, -n N límite)
find [opts] <pattern>Búsqueda recursiva profunda (--type ROLE con alias difusos: input, dropdown, nav, toggle, modal, image, etc.; --meta, --text, --content, -n N, --json)
extract_links [name]Extraer todos los enlaces en formato [text](url) (límite -n N)
extract_table <name>Extraer tabla como markdown o CSV (--format csv, límite de filas -n N)
click <name>Hacer clic en un elemento (con respaldo a clic por coordenadas)
focus <name>Enfocar un elemento de entrada
type <text>Escribir texto en el elemento enfocado
submit <input> <val>Relleno atómico de formularios: enfocar + limpiar + escribir + enviar (--submit btn o Enter)
scroll [down|up] [N]Desplazar la página por N alturas de viewport (predeterminado: 1). Devuelve el porcentaje de posición de desplazamiento.
scroll <name>Desplazar un elemento específico al centro del viewport
js <code>Ejecutar JavaScript en el contexto de la pestaña. Devuelve resultado serializado en JSON. Admite async/await.
screenshotCapturar una captura de pantalla PNG de la pestaña actual (devuelve imagen vía MCP, base64 en shell)
select <name> <value>Seleccionar una opción de lista desplegable por valor o texto visible (despacha eventos change/input)
wait <pattern> [--type ROLE] [--timeout N]Esperar a que aparezca un elemento que coincida con el patrón (sondea el árbol AX, tiempo de espera predeterminado 5s, máximo 30s)
eval <expr>Evaluar una expresión JS (solo lectura, no se necesita --allow-write). Igual que js pero en nivel de Lectura.
diff [--json]Comparar el árbol AX contra una instantánea previa a la acción. Muestra elementos añadidos/eliminados/cambiados después de clic/enviar/navegar.
refreshForzar la recuperación del Árbol de Accesibilidad

Automatización

ComandoDescripción
watch <cmd> [--interval N] [--times N] [--until-change]Re-ejecutar un comando periódicamente. --until-change se detiene cuando la salida difiere. Limitado a 28s.
for <source-cmd> : <action-tpl>Iterar sobre líneas de salida. {} se reemplaza con cada línea. Limitado a 50 elementos / 28s.
script list|save|show|run|deleteGuardar y ejecutar scripts de múltiples comandos. script run name arg1 reemplaza a $1 en comandos guardados. Persistente.
each [--pattern FILTER] <cmd>Ejecutar un comando en todas las pestañas que coincidan. Restaura la pestaña original después.
functions [pattern] [--json]Listar funciones JS globales invocables en la página con nombre, aridad, parámetros.
call <funcName> [arg1] [arg2] ...Invocar una función JS global por nombre. Los argumentos se auto-analizan (JSON o cadena). Nivel de escritura.

Sistema

ComandoDescripción
whoamiVerificar cookies de sesión/autenticación de la página actual
envMostrar variables de entorno
export K=VEstablecer una variable de entorno
history [-n N]Mostrar historial de comandos. history clear para restablecer. !N para recuperar el comando N.
bookmark [name] [path]Guardar/listar rutas nombradas. bookmark inbox guarda la ruta actual. cd @inbox regresa. bookmark --delete name elimina.
debug [sub]Inspeccionar árbol AX sin procesar (stats, raw, node <id>)
connect <token>Conectar a un servidor MCP mediante puente WebSocket
disconnectDesconectar del servidor MCP, limpiar token
helpMostrar todos los comandos disponibles
clearLimpiar la terminal

Cómo Funciona el Mapeo del Sistema de Archivos

DOMShell mapea el navegador en un sistema de archivos virtual de dos niveles:

Nivel del Navegador (~)

El navegador en sí se convierte en la parte superior de la jerarquía del sistema de archivos:

~                              (browser root)
├── windows/                   (all Chrome windows)
│   ├── <window-id>/           (tabs in that window)
│   │   ├── <tab-id>           (cd into = enter AX tree)
│   │   └── ...
│   └── ...
└── tabs/                      (flat listing of ALL tabs)
    ├── <tab-id>               (cd into = enter AX tree)
    └── ...

Hacer cd en una pestaña adjunta transparentemente CDP y te lleva a su árbol DOM.

Nivel DOM (dentro de una pestaña)

El Árbol de Accesibilidad (AXTree) de cada pestaña se lee mediante el Protocolo de Chrome DevTools. Cada nodo AX se mapea a un archivo o directorio virtual:

Directorios (roles contenedores): navigation/, main/, form/, search/, list/, region/, dialog/, menu/, table/, Iframe/, etc.

Archivos (roles interactivos/hoja): submit_btn, home_link, email_input, agree_chk, theme_switch, etc.

cd .. desde la raíz del DOM sale de vuelta a la lista de pestañas. cd ~ regresa a la raíz del navegador desde cualquier lugar.

Heurística de Nombres

Los nombres se generan a partir del nombre accesible y el rol del nodo:

Nodo AXNombre Generado
role=button, name="Submit"submit_btn
role=link, name="Contact Us"contact_us_link
role=textbox, name="Email"email_input
role=checkbox, name="I agree"i_agree_chk
role=navigationnavigation/
role=generic, no name, 1 child(aplanado — el hijo se promueve hacia arriba)

Los nombres duplicados se desambiguizan automáticamente con _2, _3, etc.

Aplanamiento de Nodos

El árbol AX contiene muchos nodos "envoltorio" — nodos ignorados, genéricos sin nombre y elementos con role=none que añaden ruido estructural sin significado semántico. DOMShell aplana recursivamente a través de ellos, promoviendo sus hijos hacia arriba para que veas los elementos significativos sin navegar por capas de divs invisibles.

Soporte de Iframes

DOMShell descubre iframes mediante Page.getFrameTree y obtiene el árbol AX de cada iframe por separado. Los nodos de iframes se fusionan en el árbol principal con IDs prefijados para evitar colisiones, de modo que los elementos dentro de los iframes aparecen naturalmente en el sistema de archivos.

Codificación de Colores

ColorSignificado
Azul (negrita)Directorios (contenedores)
Verde (negrita)Botones
Magenta (negrita)Enlaces
Amarillo (negrita)Campos de texto / cuadros de búsqueda
Cian (negrita)Casillas de verificación / radios / interruptores
BlancoOtros elementos
GrisImágenes, metadatos

Arquitectura

┌────────────────────┐
│  Claude Desktop    │──┐
└────────────────────┘  │
┌────────────────────┐  │  HTTP POST/GET/DELETE              ┌─────────────────────┐
│  Claude CLI        │──┼─ localhost:3001/mcp ──┐            │  Side Panel (UI)    │
└────────────────────┘  │  (Bearer token auth)  │            │                     │
┌────────────────────┐  │                       │            │  React + Xterm.js   │
│  Cursor / Other    │──┘                       │            │  - Paste support    │
└────────────────────┘                          ▼            │  - Tab completion   │
                               ┌─────────────────────┐      │  - Command history  │
                               │  MCP Server          │      └─────────┬───────────┘
                               │  (mcp-server/)       │                │
                               │                      │       chrome.runtime
                               │  Express HTTP server  │       .connect()
                               │  Per-session MCP      │                │
                               │  Security layer:     │      ┌─────────▼───────────┐
                               │  - Auth token        │      │  Background Worker  │
                               │  - Command tiers     │      │   (Shell Kernel)    │
                               │  - Domain allowlist  │      │                     │
                               │  - Audit log         │      │  Browser hierarchy  │
                               └──────────┬───────────┘      │  (~, tabs, windows) │
                                          │                  │  Command parser     │
                               WebSocket (localhost:9876)     │  Shell state (CWD)  │
                               + auth token                  │  VFS mapper         │
                               + alarm keepalive             │  CDP client         │
                                          │                  │  DOM change detect  │
                                          └─────────────────►│  WebSocket bridge   │
                                                             └─────────┬───────────┘
                                                                       │
                                                              chrome.debugger
                                                              (CDP 1.3)
                                                                       │
                                                             ┌─────────▼───────────┐
                                                             │   Active Tab        │
                                                             │   Accessibility     │
                                                             │   Tree + iframes    │
                                                             │                     │
                                                             │   DOM events ──────►│
                                                             │   (auto-refresh)    │
                                                             └─────────────────────┘

El servidor MCP se ejecuta como un servicio HTTP independiente al que cualquier número de clientes MCP puede conectarse simultáneamente. Expone dos puertos: un endpoint HTTP para clientes MCP (por defecto 3001) y un puente WebSocket para la extensión de Chrome (por defecto 9876).

La extensión sigue un modelo de Cliente Ligero / Host Pesado. El panel lateral es una terminal tonta — captura pulsaciones de teclas, maneja el pegado y renderiza texto con colores ANSI. Toda la lógica vive en el service worker en segundo plano: análisis de comandos, recorrido del árbol AX, mapeo del sistema de archivos, interacción CDP, navegación de la jerarquía del navegador y detección de cambios en el DOM.

Estructura del Código Fuente

src/
  background/
    index.ts        # Shell kernel — commands, state, message router, auto-refresh, WS bridge
    cdp_client.ts   # Promise-wrapped chrome.debugger API + iframe discovery
    vfs_mapper.ts   # Accessibility Tree → virtual filesystem mapping
  sidepanel/
    index.html      # Side panel entry HTML
    index.tsx        # React entry point
    Terminal.tsx     # Xterm.js terminal (paste, tab completion, history)
  shared/
    types.ts        # Message types, AXNode interfaces, role constants
public/
  manifest.json     # Chrome Manifest V3
  options.html      # Extension settings page (MCP bridge config)
mcp-server/
  index.ts          # MCP server — standalone Express HTTP + StreamableHTTP, WebSocket bridge, security
  proxy.ts          # Stdio↔HTTP bridge for clients that require command/args (e.g. Claude Desktop)
  package.json      # MCP server dependencies
  tsconfig.json     # MCP server TypeScript config

Stack Tecnológico

  • React + TypeScript — UI del panel lateral
  • Xterm.js (@xterm/xterm) — Emulador de terminal con esquema de colores Tokyo Night
  • Vite — Herramienta de compilación con soporte multi-entrada para extensiones de Chrome
  • Protocolo de Chrome DevTools (CDP 1.3) mediante chrome.debugger — Acceso al árbol AX, interacción con elementos, descubrimiento de iframes, eventos de mutación del DOM
  • Chrome Manifest V3 — Permisos sidePanel, debugger, activeTab, cookies, storage, alarms

Desarrollo

# Watch mode (rebuilds on file changes)
npm run dev

# One-time production build
npm run build

# Type checking
npm run typecheck

Después de compilar, recarga la extensión en chrome://extensions/ y vuelve a abrir el panel lateral para aplicar los cambios.

Conexión de Clientes MCP (Claude Desktop, CLI, Cursor, etc.)

DOMShell incluye un servidor MCP reforzado que permite que cualquier cliente compatible con MCP controle el navegador mediante comandos de DOMShell. El servidor se ejecuta como un servicio HTTP independiente — varios clientes pueden conectarse simultáneamente.

Tres rutas de instalación

El servidor MCP de DOMShell admite tres rutas de instalación — elige la que se ajuste a tu configuración. La ruta 1 es el valor predeterminado documentado y lo que la mayoría de los usuarios quiere. Las rutas 2 y 3 son opcionales y existen para usuarios que quieren aislamiento de contenedores o gestión del ciclo de vida.

RutaQué ejecutasComportamiento al reiniciarCuándo elegirla
1. Nativa (npx)npx @apireno/domshell --allow-write --token <token>Sobrevive naturalmente — el cliente MCP (Claude Desktop, Cursor, …) lo inicia bajo demandaQuieres la instalación más simple — sin Docker, sin herramientas adicionales
2. Dockerizada (compose)docker compose up -d desde mcp-server/ con un archivo .envSobrevive con el interruptor "Iniciar al iniciar sesión" de Docker Desktop (restart: unless-stopped)Quieres aislamiento de contenedores pero no necesitas un supervisor multi-MCP
3. Gestionada por ToolHive (thv)thv run + un agente launchd de inicio automático únicoSobrevive mediante launchd → thv restart --allEstás ejecutando varios servidores MCP y quieres un solo lugar para thv list / thv logs todos ellos

Instrucciones completas de la Ruta 2 / Ruta 3 (compilación, patrón de instalación .env, plantilla de inicio automático launchd, recuperación tras reinicio): docs/deploy/container-and-toolhive.md. El resto de este README cubre la Ruta 1 — la más simple y recomendada por defecto.

Instalación mediante npm (Ruta 1 — predeterminada)

npm install -g @apireno/domshell

O ejecuta directamente sin instalar:

npx @apireno/domshell --allow-write --token my-secret-token

Arquitectura

User starts independently:
  npx @apireno/domshell --allow-write --token xyz
    → HTTP on :3001/mcp  (MCP clients)
    → WebSocket on :9876  (Chrome extension)

Claude Desktop spawns (stdio proxy):                    ┐
  npx domshell-proxy --port 3001 --token xyz            ├─► HTTP :3001/mcp
Claude CLI connects directly:                           │
  url: http://localhost:3001/mcp?token=xyz              │
Gemini CLI connects directly:                           │
  url: http://localhost:3001/mcp?token=xyz              ┘

El servidor MCP es un servicio HTTP independiente — lo inicias por separado, y cualquier número de clientes MCP se conecta a él. Ningún cliente "posee" el proceso del servidor. Para clientes que requieren stdio (como Claude Desktop), un pequeño proxy conecta stdio al servidor HTTP en ejecución.

Configuración

Configuración rápida (recomendada):

npx @apireno/domshell init

El asistente detecta los clientes MCP instalados (Claude Desktop, Cursor, Windsurf), genera un token compartido y escribe la configuración de cada cliente. Luego inicias el servidor una vez en una terminal — todos los clientes se conectan a él.

Usa --yes para el modo no interactivo con valores predeterminados sensatos:

npx @apireno/domshell init --yes

Configuración manual:

1. Inicia el servidor MCP:

npx @apireno/domshell --allow-write --token my-secret-token

El servidor inicia dos listeners:

  • HTTP en http://127.0.0.1:3001/mcp — endpoint del cliente MCP
  • WebSocket en ws://127.0.0.1:9876 — puente de la extensión de Chrome

Consejo: Usa --token para establecer un token conocido y poder preconfigurar los clientes. Si se omite, se genera un token aleatorio y se imprime al inicio.

2. Conecta los clientes MCP:

Claude CLI / Gemini CLI / Cursor (HTTP directo — recomendado):

http://localhost:3001/mcp?token=my-secret-token

Claude Desktop (requiere stdio — usa el proxy):

Añade a ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "domshell": {
      "command": "npx",
      "args": ["-y", "@apireno/domshell", "--allow-write", "--token", "my-secret-token"]
    }
  }
}

Reinicia Claude Desktop. Las herramientas de DOMShell aparecerán.

3. Conecta la extensión (Página de Opciones):

  1. Ve a chrome://extensions/
  2. Encuentra DOMShell y haz clic en Opciones (o haz clic derecho en el icono de la extensión → Opciones)
  3. Activa el interruptor Puente MCP
  4. Pega el mismo token que usaste en la configuración de Claude Desktop (my-secret-token)
  5. Haz clic en Guardar — el indicador de estado se vuelve verde cuando está conectado

La página de opciones muestra el estado de conexión en vivo: Deshabilitado, Conectando, Conectado o Desconectado.

Alternativa: Conectar mediante terminal

También puedes conectarte desde la terminal de DOMShell en lugar de la página de opciones:

dom@shell:$ connect my-secret-token

4. Pruébalo:

Pregunta a Claude: "Lista mis pestañas abiertas y dime qué hay en la primera."

Seguridad

El servidor MCP está reforzado con múltiples capas de seguridad. Por defecto, es de solo lectura — Claude puede navegar pero no hacer clic ni escribir.

Niveles de Comandos

NivelComandosPredeterminadoHabilitar con
Lecturals, cd, pwd, cat, text, grep, find, tree, refresh, tabs, windows, here, screenshot, wait, eval, diff, history, bookmark, functions, watch, for, script, eachHabilitado(siempre activo)
Navegaciónnavigate, goto, open, back, forwardDeshabilitado--allow-write
Escrituraclick, focus, type, scroll, js, select, close, callDeshabilitado--allow-write
Sensiblewhoami (expone cookies)Deshabilitado--allow-sensitive

El nivel Navegación está separado de Escritura porque navegar equivale a escribir una URL — requiere --allow-write pero omite el mensaje de confirmación interactivo. Esto es importante para Claude Desktop donde /dev/tty no está disponible.

Banderas de Seguridad

BanderaDescripción
--allow-writeHabilitar comandos de clic/enfoque/escritura/desplazamiento/js/selección/cierre/navegación/atrás/adelante
--allow-sensitiveHabilitar whoami (acceso a cookies)
--allow-allAbreviatura para ambos
--confirmOptar por mensajes de sí/no por acción en la terminal del servidor antes de cada escritura. Desactivado por defecto.
--no-confirmSin operación (se mantiene por compatibilidad hacia atrás — los mensajes por acción están desactivados por defecto).
--domains example.com,app.example.comRestringir comandos a dominios específicos
--expose-cookiesMostrar valores completos de cookies (predeterminado: redactados)
--mcp-port NPuerto del endpoint HTTP de MCP (predeterminado: 3001)
--port NPuerto del puente WebSocket (predeterminado: 9876)
--log-file PATHArchivo de registro de auditoría (predeterminado: audit.log)

Confirmación por Acción (opt-in)

Los mensajes de terminal por acción están desactivados por defecto — la terminal del servidor MCP está separada de donde realmente se ejecutan el agente y el panel lateral, por lo que el mensaje es incómodo de responder en cualquier configuración iniciada por GUI (Claude Desktop, Cursor, el entorno de CLI-Anything). El registro de auditoría captura cada comando, y las banderas de nivel (--allow-write, --allow-sensitive) más --domains siguen siendo los límites de seguridad reales.

Si inicias el servidor en tu propia terminal y quieres un mensaje de sí/no antes de cada escritura, añade --confirm:

[DOMShell] Claude wants to: click submit_btn
Allow? (y/n):

--no-confirm se conserva como una operación sin efecto (coincide con el valor predeterminado), por lo que cualquier configuración existente que lo pase seguirá funcionando sin cambios.

Token de Autenticación

  • Usa --token para establecer un token conocido en la configuración del servidor MCP, o deja que el servidor genere uno aleatorio al inicio
  • La extensión debe presentar este token (mediante la página de opciones o connect <token>) antes de que el puente funcione
  • Las conexiones WebSocket sin un token válido se rechazan
  • El token se almacena en chrome.storage.local — sobrevive a los reinicios del service worker

Lista de Dominios Permitidos

Con --domains, los comandos solo se ejecutan cuando la URL de la pestaña activa coincide:

npx tsx index.ts --allow-write --domains "github.com,docs.google.com"

Registro de Auditoría

Cada comando se registra con marcas de tiempo en audit.log (o --log-file):

[2026-02-07T12:00:00.000Z] EXECUTE: ls -l
[2026-02-07T12:00:01.000Z] RESULT: 12 items
[2026-02-07T12:00:05.000Z] [WRITE] EXECUTE: click submit_btn
[2026-02-07T12:00:05.500Z] [WRITE] RESULT: ✓ Clicked: submit_btn (button)

Desconexión

Desactiva el interruptor del Puente MCP en la página de opciones de la extensión, o ejecuta disconnect en la terminal de DOMShell:

dom@shell:$ disconnect
✓ Disconnected from MCP server.

La interfaz domshell_execute

El servidor MCP de DOMShell expone una única herramienta por defecto — domshell_execute — la forma recomendada de manejar DOMShell. Pasas una cadena de comando, exactamente como la escribirías en la terminal de DOMShell:

domshell_execute("ls")
domshell_execute("cd tabs/4815")
domshell_execute("find --type link --meta")

Llamadas con múltiples comandos. Pasa varios comandos separados por saltos de línea y se ejecutan en secuencia, con la salida combinada devuelta — un flujo de trabajo completo en una sola llamada de herramienta:

domshell_execute("open https://example.com
cd main
text")

Un solo viaje de ida y vuelta en lugar de tres, y menos ciclos de llamadas de herramienta.

Semántica multilínea. Cada línea se ejecuta en orden en la misma sesión y carril de MCP, por lo que cwd, el entorno y el historial persisten entre líneas (el cd main de la segunda línea es relativo a la pestaña recién abierta de la primera línea). Un error en cualquier línea individual no detiene el resto — su mensaje de error se incluye en la salida combinada y las líneas posteriores aún se ejecutan. Esa es la forma correcta para modismos de líneas de limpieza como "cd path\ngrep pattern\ncd back" donde la restauración final debe ejecutarse incluso si el paso intermedio falla. Implementación: mcp-server/index.ts:1115-1136.

Dos modos:

ModoHerramientas expuestasÚsalo cuando
Herramienta única (por defecto)Solo domshell_executeUso normal. Una aprobación cubre toda la sesión — sin avisos por comando.
Granular (--granular)38 herramientas por comando (domshell_ls, domshell_click, …)Quieres que tu cliente MCP solicite aprobación por tipo de operación — supervisión humana más fina en la capa del cliente.

Inicia el servidor con --granular para las herramientas por comando:

npx @apireno/domshell --granular

La seguridad es idéntica en ambos modos. Los niveles del lado del servidor de DOMShell (write / sensitive — establecidos por --allow-write, --allow-sensitive, con --confirm opcional para avisos de terminal del servidor por acción) controlan las operaciones riesgosas independientemente de qué herramienta emitió el comando. El modo granular no añade seguridad — añade un aviso de aprobación adicional en tu cliente MCP por tipo de operación. Eso es más supervisión humana, no más protección.

Referencia de Herramientas MCP (modo --granular)

La tabla siguiente enumera las herramientas por comando expuestas cuando el servidor se ejecuta con --granular. En el modo de herramienta única por defecto, ejecuta los mismos comandos a través de domshell_execute — la columna Maps To muestra la cadena de comando.

Herramienta MCPSe asigna aNivel
domshell_tabstabs (listar todas las pestañas)Lectura
domshell_herehere (saltar a la pestaña activa)Lectura
domshell_lsls [options] (nivel DOM o navegador)Lectura
domshell_cdcd <path> (~, ~/tabs/, /, ..)Lectura
domshell_pwdpwdLectura
domshell_catcat <name>Lectura
domshell_texttext [name] [-n N] [--links] (texto masivo; links=true inserta URLs)Lectura
domshell_readread [name] [--meta] [--text] [-d N] (subárbol estructurado)Lectura
domshell_findfind [pattern] [--type ROLE/alias] [--meta] [--text] [-n N] (el tipo acepta alias difusos: input, dropdown, nav, etc.)Lectura
domshell_grepgrep [-r] [-n N] [--content] <pattern> (descubrimiento de secciones)Lectura
domshell_treetree [depth]Lectura
domshell_extract_linksextract_links [name] [-n N] (todos los enlaces como [text](url))Lectura
domshell_extract_tableextract_table <name> [--format csv] (tabla → markdown/CSV)Lectura
domshell_refreshrefreshLectura
domshell_navigatenavigate <url> (pestaña actual)Navegación
domshell_openopen <url> (nueva pestaña)Navegación
domshell_clickclick <name>Escritura
domshell_focusfocus <name>Escritura
domshell_scrollscroll [down|up] [N] o scroll <target>Escritura
domshell_jsjs <code> (ejecución arbitraria de JavaScript)Escritura
domshell_typetype <text>Escritura
domshell_submitsubmit <input> <value> [--submit btn] (relleno atómico de formularios)Escritura
domshell_backback (retroceder en el historial del navegador)Navegación
domshell_forwardforward (avanzar en el historial del navegador)Navegación
domshell_closeclose [tab-id] (cerrar una pestaña)Escritura
domshell_screenshotscreenshot (capturar pestaña como imagen PNG)Lectura
domshell_selectselect <name> <value> (selección en lista desplegable)Escritura
domshell_waitwait <pattern> [--type ROLE] [--timeout N] (esperar un elemento)Lectura
domshell_evaleval <expression> (evaluación JS de solo lectura, sin --allow-write necesario)Lectura
domshell_diffdiff [--json] (comparar árbol contra instantánea previa a la acción)Lectura
domshell_whoamiwhoamiSensible
domshell_functionsfunctions [pattern] [--json] (listar funciones de página invocables)Lectura
domshell_callcall <funcName> [args] (llamar una función JS global)Escritura
domshell_watchwatch <cmd> [--interval N] [--times N] [--until-change] (re-ejecución periódica)Lectura
domshell_forfor <source> : <template> (iterar sobre líneas de salida, {} reemplazado)Lectura
domshell_scriptscript list|save|show|run|delete (scripts con sustitución de $1)Lectura
domshell_eacheach [--pattern FILTER] <cmd> (operaciones entre pestañas)Lectura
domshell_execute(cualquier comando)Varía

Hoja de ruta

Distribución e instalación

  • Listado en Chrome Web Storeen vivo en Chrome Web Store
  • Lanzamiento en GitHub con .crxlanzamiento v1.1.1 con zip de extensión
  • Asistente de configuración MCPnpx @apireno/domshell init detecta clientes MCP instalados, genera un token y escribe la configuración automáticamente
  • Soporte para otros clientes MCP — Gemini Desktop, OpenAI ChatGPT desktop, Cursor, Windsurf y otros hosts compatibles con MCP

Nuevos comandos

  • watch — re-ejecución periódica de un comando (p. ej. watch ls --times 3 --interval 1 para sondear cambios en el DOM)
  • history — historial de comandos con recuperación (history, !n para re-ejecutar)
  • back / forward — navegación de historial estilo navegador dentro de la pestaña actual
  • close — cerrar la pestaña actual (close o close <tab-id>)
  • screenshot — capturar una captura de pantalla de la pestaña actual (útil para verificación visual junto con la inspección del árbol AX)
  • pipe / | — canalizar salida entre comandos (p. ej. find --type link | grep login)
  • select <name> — seleccionar una opción de una lista desplegable <select> por valor o texto visible
  • scroll — desplazarse por la página o un elemento específico (scroll down, scroll up, scroll <name>)
  • wait — esperar a que aparezca un elemento específico (p. ej. wait submit_btn se bloquea hasta que exista en el árbol)
  • Bucle for — iterar sobre líneas de salida de comandos (p. ej. for "find --type heading -n 3" : text {}) — reemplaza la iteración manual
  • Comando script — guardar y ejecutar scripts de múltiples comandos (p. ej. script save scrape open url ; cd main ; text) para flujos de trabajo repetibles

Capa de JavaScript

  • Comando js — ejecutar JavaScript arbitrario en el contexto de la pestaña y devolver el resultado
  • functions + callfunctions [pattern] lista funciones JS globales invocables con nombre/aridad/parámetros; call funcName arg1 arg2 las invoca. call es de nivel de escritura.
  • eval <expr> — evaluación rápida de expresiones (p. ej. eval document.title, eval window.location.href)

Ergonomía para agentes

  • Indicador --text — mostrar vistas previas de texto visible en línea con ls y find usando .innerText (solo texto renderizado, respeta la visibilidad CSS); longitud configurable mediante --textlen N; cat también muestra VisibleText por separado de textContent
  • Indicador --meta — mostrar propiedades DOM (href, src, id, tag) en línea con la salida de ls, find y read — esencial para extraer URLs sin llamadas cat separadas
  • Coincidencia --content — buscar por contenido de texto visible con grep --content y find --content (o find --text "pattern") — encuentra elementos por lo que muestran, no solo por su nombre AX
  • Resolución de rutas — todos los comandos aceptan rutas relativas (p. ej. text main/article/paragraph, click form/submit_btn) — elimina viajes de ida y vuelta cd innecesarios
  • Navegación entre hermanos — indicadores --after/--before en ls para dividir hijos en relación con un elemento de referencia (p. ej. ls --after heading --type link --meta)
  • Indicador --links en text — incluir URLs de hipervínculos en línea como [text](url) markdown en la salida de texto; extrae tanto el contenido como los destinos de los enlaces en una sola llamada (p. ej. text --links main/paragraph)
  • Alias de tipo difusos para findfind --type acepta alias en lenguaje natural (input, dropdown, nav, toggle, modal, image, btn, sidebar, etc.) que se expanden a roles AX coincidentes — elimina llamadas de herramienta desperdiciadas al adivinar nombres de roles exactos
  • Caché de texto visible — caché perezosa para resultados de innerText, claveada por backendDOMNodeId, limpiada al reconstruir el árbol — elimina llamadas CDP redundantes durante la coincidencia --content en grep/find
  • bookmark / alias — guardar rutas con nombre para navegación rápida (p. ej. bookmark inbox ~/tabs/gmail/main/inbox_list, cd @inbox)
  • each (multi-pestaña) — ejecutar un comando en múltiples pestañas (p. ej. each --pattern wiki text para extraer texto de cada pestaña de Wikipedia)
  • Modo de salida estructurada — indicador --json en comandos para salida analizable por máquina (p. ej. ls --json, cat --json, find --json, diff --json)
  • Persistencia de sesión — guardar y restaurar el estado del shell (ruta, variables de entorno, marcadores, historial) entre reinicios del service worker mediante chrome.storage.local
  • diff — comparar instantáneas del árbol AX para ver qué cambió después de una acción (instantáneas automáticas antes de click/submit/navigate)
  • Aislamiento de grupos de pestañas por sesión — las pestañas de cada sesión se colocan en un grupo de pestañas de Chrome etiquetado y cada comando se limita a ese grupo, de modo que el agente trabaje en su propio carril mientras sigues navegando libremente en otras pestañas de la misma ventana (#32)
  • DOMShell multi-sesión — cada consola del panel lateral y cada conexión MCP obtiene su propia sesión de shell independiente (su propio directorio actual, pestaña y cursor DOM), de modo que múltiples consolas humanas y agentes concurrentes trabajen cada uno en un carril aislado en lugar de compartir un cursor global (#33)
  • Sesiones declaradas por el agente — un group_id opcional en domshell_execute permite a un agente dirigirse a un carril específico: omítelo para el carril actual, "new" para uno nuevo, o pasa un id para unirse a un carril existente — de modo que dos chats de agentes que comparten una conexión MCP permanezcan aislados, y un agente pueda entregar una sesión a otro (#34)

Plataforma

  • Navegador headless independiente — distribuir DOMShell como un proceso Chromium headless autocontenido (mediante Chrome for Testing o Chromium embebido) que los agentes lancen directamente — sin instalación de extensión, sin perfil de Chrome del usuario; solo npx @apireno/domshell --headless y conectar vía MCP. Ideal para pipelines de CI, automatización del lado del servidor y flujos de trabajo de agente-en-bucle donde no se necesita un navegador visible
  • Extensión para Firefox — portar a Firefox usando la API WebExtensions + protocolo de depuración remota
  • Backend Playwright/Puppeteer — alternativa a la extensión de Chrome para flujos de trabajo headless de agentes
  • Modo API REST — exponer comandos de DOMShell sobre HTTP para integraciones no MCP
  • Compilación WASM — compilar DOMShell a WebAssembly para que pueda integrarse directamente en un sitio web para demostraciones interactivas sin requerir la instalación de una extensión de Chrome

Experimentos

  • Nexa: DOMShell vs HTML crudo — mismo modelo (Qwen3-4B), mismas tareas: comparar la interfaz de texto/árbol AX de DOMShell contra el raspado de HTML crudo. Pruebas en los backends de nexa serve y Ollama. Se encontró una interacción cruzada: Ollama+DOMShell y Nexa+HTML son igualmente los mejores (promedio 1.20). Ver experiments/nexa_ollama/.
  • Nexa vs Claude (tamaño del modelo) — se compararon Qwen3-1.7B/4B en tareas progresivas. Límite de capacidad en T3 (extracción de párrafos). El 4B muestra mejor recuperación de errores. Ver experiments/nexa_claude/.
  • Competencia de modelos — se compararon Qwen3-4B, Hermes3-3B, Granite4-Tiny, Llama3.2-3B en Ollama+DOMShell. Qwen3-4B sigue siendo el mejor (8/15), único modelo que supera el límite de T3. Llama3.2-3B es un cercano segundo (7/15, cero alucinaciones). Ver experiments/model_shootout/.
  • Benchmark de costo de tokens — medir el total de tokens de entrada/salida por tarea entre DOMShell y la navegación basada en capturas de pantalla (CiC). Extender el experiments/claude_domshell_vs_cic/ existente con el conteo de tokens. Hipótesis: el texto estructurado (2-3KB por respuesta) frente a capturas de pantalla en base64 (500KB+) debería mostrar un ahorro de tokens de >2x además de la reducción de 2x en el número de llamadas ya medida

Integraciones

Nexa AI (LLM local)

Ejecuta DOMShell con modelos locales a través de nexa-sdk — automatización del navegador completamente en el dispositivo sin necesidad de API en la nube. Usa el mismo protocolo MCP que Claude Desktop, pero impulsado por inferencia local (Granite-4-Micro, Qwen3, etc.).

python integrations/nexa/agent.py --task "Open wikipedia.org/wiki/AI and extract the first paragraph" --verbose

Consulta integrations/nexa/ para la configuración y el uso.

Cómo se construyó este proyecto

La especificación técnica de DOMShell fue escrita por Google Gemini, diseñada como un prompt integral que podría entregarse directamente a un agente de codificación para construir todo el proyecto desde cero. La especificación original completa se conserva en intitial_project_prompt.md.

La implementación fue luego construida por Claude (Anthropic) a través de Claude Code, trabajando a partir de esa especificación.

Un proyecto diseñado por IA, construido por otra IA, destinado a que los agentes de IA lo usen. Son agentes hasta el final.

Enlaces

Licencia

MIT