DOMShell
Navegue pela web com comandos de sistema de arquivos. 38 ferramentas MCP permitem que agentes de IA executem ls, cd, grep, clique e digitação através do Chrome por meio de uma Extensão do Chrome.
Documentação
DOMShell
| |
___|_|___
|___|_|___|
| | | |
|___|_|___|
/ | | \
/ | | \
|____|_|____|
| |
| DOMSHELL |
| |
|___________|
|###########|
|###########|
\#########/
\_______/
██ ██ ██ ███████
██ ██ ██ ███
███████ ██ ██
██░░░██ ██ ██
██ ██ ██ ██
░░ ░░ ░░ ░░
███████ ██ ██ ███████
███ ███████ ██░░░░░
███ ██░░░██ █████
███ ██ ██ ██░░░
███ ██ ██ ███████
░░░ ░░ ░░ ░░░░░░░
██████ ██████ ███ ███ ██
██ ██ ██ ██ ████ ████ ██
██ ██ ██ ██ ██ ████ ██ ██
██ ██ ██ ██ ██ ██ ██ ░░
██████ ██████ ██ ██ ██
░░░░░░ ░░░░░░ ░░ ░░ ░░
O navegador é o seu sistema de arquivos. Uma extensão do Chrome que permite que agentes de IA (e humanos) naveguem na web usando comandos Linux padrão — ls, cd, cat, grep, click — por meio de um terminal no Painel Lateral do Chrome.
Instalar pela Chrome Web Store | pacote npm | Leia o post no blog | Página do projeto
O DOMShell mapeia o navegador em um sistema de arquivos virtual. Janelas e abas tornam-se diretórios de nível superior (~). A Árvore de Acessibilidade de cada aba torna-se um sistema de arquivos aninhado, onde elementos contêiner são diretórios e botões, links e campos de entrada são arquivos. Navegue pelo Chrome da mesma forma que navegaria pelo /usr/local/bin.
Por quê
Agentes de IA que interagem com sites normalmente dependem de capturas de tela, coordenadas de pixels ou seletores CSS frágeis. O DOMShell adota uma abordagem diferente: ele expõe a própria Árvore de Acessibilidade do navegador como uma metáfora familiar de sistema de arquivos.
Isso significa que um agente pode:
- Navegar pelas abas com
ls ~/tabs/e alternar comcd ~/tabs/123em vez de adivinhar qual aba está ativa - Explorar uma página com
lsetreeem vez de analisar capturas de tela - Navegar para seções com
cd navigation/em vez de adivinhar coordenadas - Agir sobre elementos com
click submit_btnem vez de consultas DOM frágeis - Ler conteúdo com
catou extrair em massa comtextem vez de raspar innerHTML - Buscar elementos com
find --type comboboxem vez de escrever seletores
A abstração de sistema de arquivos é determinística, semântica e funciona em qualquer site — sem necessidade de adaptadores específicos por site.
Instalação
Chrome Web Store (Recomendado)
Instale o DOMShell diretamente da Chrome Web Store. Nenhuma etapa de build é necessária.
A partir do código-fonte
git clone https://github.com/apireno/DOMShell.git
cd DOMShell
npm install
npm run build
Carregar no Chrome
- Abra
chrome://extensions/ - Ative o Modo desenvolvedor (alternância no canto superior direito)
- Clique em Carregar sem compactação
- Selecione a pasta
dist/ - Clique no ícone do DOMShell na sua barra de ferramentas — o painel lateral abre
Uso
Primeiros passos
Abra qualquer página da web e, em seguida, abra o painel lateral do DOMShell. Você verá um 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:~$
Você começa em ~ (a raiz do navegador). Vá direto para a aba ativa com here, ou explore:
dom@shell:~$ ls
windows/ (2 windows)
tabs/ (5 tabs)
dom@shell:~$ here
✓ Entered tab 123
Title: Google
URL: https://google.com
AX Nodes: 247
Navegando por abas e janelas
# 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
Você também pode navegar ou abrir novas abas:
# 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 abas (isolamento)
Por padrão, o DOMShell opera no seu navegador geral — modo compartilhado, exatamente como antes. O comando group coloca uma sessão em seu próprio grupo de abas isolado do Chrome, para que o agente trabalhe em uma faixa claramente demarcada enquanto você continua navegando livremente em outras abas:
# 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 (status), group new [name], group attach <id>, group detach, group close, group list. O modo isolado mantém o agente fora das suas outras abas; o modo compartilhado é o padrão e permanece inalterado.
Quando um cliente MCP se conecta, o DOMShell automaticamente dá a essa sessão seu próprio grupo 🐚 agent novo. O grupo é deixado aberto quando a sessão se desconecta (não destrutivo) — o agente é instruído a perguntar se você gostaria que ele fosse fechado antes de encerrar, e você sempre pode limpar os resíduos manualmente com group close.
Multissessão. Cada cliente DOMShell recebe sua própria faixa de sessão — cada janela do painel lateral, cada conexão MCP, isoladas separadamente. Dois painéis laterais em duas janelas do Chrome mantêm posições independentes; múltiplos agentes MCP simultâneos trabalham cada um em seu próprio grupo 🐚 agent com seu próprio cursor. Execute group list a qualquer momento para ver todas as faixas ativas; group close <id> para fechar uma.
Múltiplos agentes em uma única conexão MCP. Alguns clientes MCP (por exemplo, Claude Desktop) compartilham uma conexão entre todos os chats — então, por padrão, dois chats no mesmo cliente cairiam na mesma faixa. Cada chat pode reservar sua própria faixa passando o parâmetro group_id para domshell_execute: passe "new" para criar uma nova (seu id é retornado ao final da resposta como [lane: <id>]) e, em seguida, passe esse id em todas as chamadas posteriores. Dois chats → duas faixas → sem colisão. Os agentes também podem usar isso para transferência — um agente reporta seu id de faixa, o próximo agente o passa como group_id e continua no mesmo estado. Os agentes são instruídos a fechar qualquer faixa que criarem quando a tarefa for concluída.
Navegando pelo DOM
Uma vez dentro de uma aba, a Árvore de Acessibilidade aparece como um sistema de arquivos:
# 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
Prefixos de tipo
Cada nó tem um prefixo de tipo que comunica metadados sem depender apenas de cor:
| Prefixo | Significado | Exemplos |
|---|---|---|
[d] | Diretório (contêiner, pode receber cd) | navigation/, form/, main/ |
[x] | Interativo (clicável/focalizável) | botões, links, campos de entrada, caixas de seleção |
[-] | Estático (somente leitura) | títulos, imagens, texto |
Lendo conteúdo
# 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
Buscando
# 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>
Encadeamento de comandos (composição estilo Bash)
O DOMShell funciona como um sistema de arquivos — use o mesmo modelo mental de buscar arquivos no disco. grep descobre onde o conteúdo vive (como grep -r no bash), cd define o escopo do seu contexto, e text/cat/find lê o conteúdo (como cat/head/less). O operador pipe (|) filtra a saída, exatamente como no bash.
O padrão é: grep (localizar) → cd (definir escopo) → extrair (ler).
# 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 pipe
O operador pipe (|) permite filtrar a saída de comandos, exatamente como no 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
Resolução de caminhos
Todos os comandos aceitam caminhos relativos, eliminando a necessidade de cd primeiro:
# 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
Navegação entre irmãos
Use os sinalizadores --after e --before em ls para encontrar conteúdo relativo a um ponto de referência:
# 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>
A percepção fundamental: a saída de grep alimenta cd, e cd define o escopo de todo o resto. Quando você não sabe onde o conteúdo vive em uma página, sempre faça grep primeiro, depois defina o escopo e, por fim, extraia.
Interagindo com 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
Atualização automática em mudanças do DOM
O DOMShell detecta automaticamente quando a página muda — navegação, mutações do DOM ou atualizações de conteúdo provenientes de cliques. Você não precisa mais executar 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/
...
Se a página navegou, o CWD é redefinido para a raiz da aba. Se o DOM apenas foi atualizado no lugar, seu CWD é preservado. Você ainda pode forçar uma atualização manual:
dom@shell:~$refresh
✓ Refreshed. 312 AX nodes loaded.
Autocompletar com Tab
Pressione Tab para autocompletar comandos e nomes de elementos — funciona como no 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
- Correspondência única: autocompleta inline
- Múltiplas correspondências: mostra opções abaixo, preenche o prefixo comum mais longo
cdcompleta apenas diretórios; outros comandos completam todos os elementos
Suporte a colar
Cmd+V (Mac) / Ctrl+V (Windows/Linux) cola texto diretamente no terminal. Colagens de múltiplas linhas são achatadas em uma única linha.
Comandos do 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
Obtendo ajuda
Todo comando suporta --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
...
Referência de comandos
Nível do navegador
| Comando | Descrição |
|---|---|
tabs | Lista todas as abas abertas (atalho para ls ~/tabs/) |
windows | Lista todas as janelas com suas abas agrupadas abaixo |
here | Vai para a aba ativa na janela em foco |
cd ~ | Vai para a raiz do navegador |
cd ~/tabs/<id> | Alterna para uma aba por ID (entra automaticamente) |
cd ~/tabs/<pattern> | Alterna para uma aba por correspondência de substring no título/URL |
cd ~/windows/<id> | Navega pelas abas de uma janela |
navigate <url> | Navega a aba atual para uma URL |
open <url> | Abre uma URL em uma nova aba e entra nela |
back | Volta no histórico do navegador (como o botão voltar) |
forward | Avança no histórico do navegador |
close [tab-id] | Fecha a aba atual (ou uma aba específica por ID) |
Árvore do DOM
| Comando | Descrição |
|---|---|
ls [options] | Lista filhos (-l, --meta, --text, -r, -n N, --offset N, --type ROLE, --count, --after NAME, --before NAME, --json) |
cd <path> | Navega (.., ~ ou / para a raiz do navegador, %here% para a aba em foco, main/form para múltiplos níveis) |
pwd | Imprime o caminho atual (caminho do DOM ou caminho do navegador) |
tree [depth] | Visualização em árvore do nó atual (profundidade padrão: 2) |
cat <name> [--json] | Metadados completos do elemento: informações de AX + propriedades do DOM (tag, href, src, id, class, outerHTML) |
text [name] [-n N] [--links] | Extrai em massa todo o texto de uma seção (--links insere URLs inline como [text](url)) |
read [name] [opts] | Extração estruturada de subárvore (--meta, --text, -d N profundidade) — árvore + conteúdo em uma única chamada |
grep [opts] <pattern> | Busca por nome/role/valor (-r recursivo, --content corresponde ao texto visível, -n N limite) |
find [opts] <pattern> | Busca recursiva profunda (--type ROLE com aliases difusos: input, dropdown, nav, toggle, modal, image, etc.; --meta, --text, --content, -n N, --json) |
extract_links [name] | Extrai todos os links no formato [text](url) (limite de -n N) |
extract_table <name> | Extrai tabela como markdown ou CSV (--format csv, limite de linhas -n N) |
click <name> | Clica em um elemento (recorre a clique baseado em coordenadas) |
focus <name> | Focaliza um elemento de entrada |
type <text> | Digita texto no elemento em foco |
submit <input> <val> | Preenchimento atômico de formulário: focalizar + limpar + digitar + enviar (--submit btn ou Enter) |
scroll [down|up] [N] | Rola a página por N alturas de viewport (padrão: 1). Retorna a porcentagem da posição de rolagem. |
scroll <name> | Rola um elemento específico para o centro do viewport |
js <code> | Executa JavaScript no contexto da aba. Retorna resultado serializado em JSON. Suporta async/await. |
screenshot | Captura uma captura de tela PNG da aba atual (retorna imagem via MCP, base64 no shell) |
select <name> <value> | Seleciona uma opção de menu suspenso por valor ou texto visível (dispara eventos change/input) |
wait <pattern> [--type ROLE] [--timeout N] | Aguarda um elemento correspondente ao padrão aparecer (verifica a árvore AX, timeout padrão de 5s, máximo de 30s) |
eval <expr> | Avalia uma expressão JS (somente leitura, sem necessidade de --allow-write). Igual a js, mas no nível de Leitura. |
diff [--json] | Compara a árvore AX com o snapshot pré-ação. Mostra elementos adicionados/removidos/alterados após clique/envio/navegação. |
refresh | Força a reobtenção da Árvore de Acessibilidade |
Automação
| Comando | Descrição |
|---|---|
watch <cmd> [--interval N] [--times N] [--until-change] | Reexecuta um comando periodicamente. --until-change para quando a saída difere. Limitado a 28s. |
for <source-cmd> : <action-tpl> | Itera sobre linhas de saída. {} é substituído por cada linha. Limitado a 50 itens / 28s. |
script list|save|show|run|delete | Salva e executa scripts de múltiplos comandos. script run name arg1 substitui $1 nos comandos salvos. Persistido. |
each [--pattern FILTER] <cmd> | Executa um comando em todas as abas correspondentes. Restaura a aba original depois. |
functions [pattern] [--json] | Lista funções JS globais chamáveis na página com nome, aridade, parâmetros. |
call <funcName> [arg1] [arg2] ... | Chama uma função JS global pelo nome. Argumentos analisados automaticamente (JSON ou string). Nível de escrita. |
Sistema
| Comando | Descrição |
|---|---|
whoami | Verificar cookies de sessão/auth da página atual |
env | Mostrar variáveis de ambiente |
export K=V | Definir uma variável de ambiente |
history [-n N] | Mostrar histórico de comandos. history clear para redefinir. !N para recuperar o comando N. |
bookmark [name] [path] | Salvar/listar caminhos nomeados. bookmark inbox salva o caminho atual. cd @inbox volta. bookmark --delete name remove. |
debug [sub] | Inspecionar árvore AX bruta (stats, raw, node <id>) |
connect <token> | Conectar a um servidor MCP via ponte WebSocket |
disconnect | Desconectar do servidor MCP, limpar token |
help | Mostrar todos os comandos disponíveis |
clear | Limpar o terminal |
Como Funciona o Mapeamento do Sistema de Arquivos
O DOMShell mapeia o navegador em um sistema de arquivos virtual de dois níveis:
Nível do Navegador (~)
O próprio navegador se torna o topo da hierarquia do sistema de arquivos:
~ (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)
└── ...
Entrar (cd) em uma aba anexa o CDP de forma transparente e o leva para a árvore DOM dela.
Nível do DOM (dentro de uma aba)
A Árvore de Acessibilidade (AXTree) de cada aba é lida via Chrome DevTools Protocol. Cada nó AX é mapeado para um arquivo ou diretório virtual:
Diretórios (papéis de contêiner): navigation/, main/, form/, search/, list/, region/, dialog/, menu/, table/, Iframe/, etc.
Arquivos (papéis interativos/folha): submit_btn, home_link, email_input, agree_chk, theme_switch, etc.
cd .. a partir da raiz do DOM volta para a listagem de abas. cd ~ retorna à raiz do navegador de qualquer lugar.
Heurística de Nomenclatura
Os nomes são gerados a partir do nome acessível e do papel do nó:
| Nó AX | Nome Gerado |
|---|---|
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=navigation | navigation/ |
role=generic, no name, 1 child | (achatado — filho promovido para cima) |
Nomes duplicados são automaticamente desambiguados com _2, _3, etc.
Achatamento de Nós
A árvore AX contém muitos nós "wrapper" — nós ignorados, genéricos sem nome e elementos com role=none que adicionam ruído estrutural sem significado semântico. O DOMShell achata recursivamente esses nós, promovendo seus filhos para cima, para que você veja os elementos significativos sem navegar por camadas de divs invisíveis.
Suporte a Iframes
O DOMShell descobre iframes via Page.getFrameTree e busca a árvore AX de cada iframe separadamente. Os nós de iframe são mesclados à árvore principal com IDs prefixados para evitar colisões, então elementos dentro de iframes aparecem naturalmente no sistema de arquivos.
Codificação de Cores
| Cor | Significado |
|---|---|
| Azul (negrito) | Diretórios (contêineres) |
| Verde (negrito) | Botões |
| Magenta (negrito) | Links |
| Amarelo (negrito) | Campos de texto / caixas de busca |
| Ciano (negrito) | Caixas de seleção / botões de opção / interruptores |
| Branco | Outros elementos |
| Cinza | Imagens, metadados |
Arquitetura
┌────────────────────┐
│ 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) │
└─────────────────────┘
O servidor MCP roda como um serviço HTTP autônomo ao qual qualquer número de clientes MCP pode se conectar simultaneamente. Ele expõe duas portas: um endpoint HTTP para clientes MCP (padrão 3001) e uma ponte WebSocket para a extensão do Chrome (padrão 9876).
A extensão segue um modelo Cliente Leve / Host Pesado. O painel lateral é um terminal "burro" — ele captura teclas, lida com colagem e renderiza texto colorido ANSI. Toda a lógica vive no service worker em segundo plano: análise de comandos, travessia da árvore AX, mapeamento do sistema de arquivos, interação com CDP, navegação na hierarquia do navegador e detecção de mudanças no DOM.
Estrutura do Código-Fonte
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
Pilha Tecnológica
- React + TypeScript — UI do painel lateral
- Xterm.js (
@xterm/xterm) — Emulador de terminal com esquema de cores Tokyo Night - Vite — Ferramenta de build com suporte a múltiplas entradas para extensões do Chrome
- Chrome DevTools Protocol (CDP 1.3) via
chrome.debugger— acesso à árvore AX, interação com elementos, descoberta de iframes, eventos de mutação do DOM - Chrome Manifest V3 — permissões
sidePanel,debugger,activeTab,cookies,storage,alarms
Desenvolvimento
# Watch mode (rebuilds on file changes)
npm run dev
# One-time production build
npm run build
# Type checking
npm run typecheck
Após o build, recarregue a extensão em chrome://extensions/ e reabra o painel lateral para aplicar as alterações.
Conectando Clientes MCP (Claude Desktop, CLI, Cursor, etc.)
O DOMShell inclui um servidor MCP endurecido que permite que qualquer cliente compatível com MCP controle o navegador por meio de comandos do DOMShell. O servidor roda como um serviço HTTP autônomo — vários clientes podem se conectar simultaneamente.
Três caminhos de instalação
O servidor MCP do DOMShell suporta três caminhos de instalação — escolha o que melhor se adequa à sua configuração. O Caminho 1 é o padrão documentado e o que a maioria dos usuários quer. Os Caminhos 2 e 3 são opcionais e existem para usuários que desejam isolamento de contêiner ou gerenciamento de ciclo de vida.
| Caminho | O que você executa | Comportamento na reinicialização | Quando escolher |
|---|---|---|---|
| 1. Nativo (npx) | npx @apireno/domshell --allow-write --token <token> | Sobrevive naturalmente — o cliente MCP (Claude Desktop, Cursor, …) o inicia sob demanda | Você quer a instalação mais simples — sem Docker, sem ferramentas extras |
| 2. Dockerizado (compose) | docker compose up -d a partir de mcp-server/ com um arquivo .env | Sobrevive com a opção "Iniciar no login" do Docker Desktop (restart: unless-stopped) | Você quer isolamento de contêiner, mas não precisa de um supervisor multi-MCP |
| 3. Gerenciado pelo ToolHive (thv) | thv run + um agente de inicialização automática launchd único | Sobrevive via launchd → thv restart --all | Você está executando vários servidores MCP e quer um único lugar para thv list / thv logs todos eles |
Instruções completas dos Caminhos 2 / 3 (build, padrão de instalação .env, template de inicialização automática launchd, recuperação após reinicialização): docs/deploy/container-and-toolhive.md. O restante deste README cobre o Caminho 1 — o padrão mais simples e recomendado.
Instalação via npm (Caminho 1 — padrão)
npm install -g @apireno/domshell
Ou execute diretamente sem instalar:
npx @apireno/domshell --allow-write --token my-secret-token
Arquitetura
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 ┘
O servidor MCP é um serviço HTTP autônomo — você o inicia de forma independente, e qualquer número de clientes MCP se conecta a ele. Nenhum cliente individual "possui" o processo do servidor. Para clientes que exigem stdio (como o Claude Desktop), um pequeno proxy faz a ponte entre stdio e o servidor HTTP em execução.
Configuração
Configuração rápida (recomendada):
npx @apireno/domshell init
O assistente detecta clientes MCP instalados (Claude Desktop, Cursor, Windsurf), gera um token compartilhado e grava a configuração de cada cliente. Você então inicia o servidor uma vez em um terminal — todos os clientes se conectam a ele.
Use --yes para o modo não interativo com padrões sensatos:
npx @apireno/domshell init --yes
Configuração manual:
1. Inicie o servidor MCP:
npx @apireno/domshell --allow-write --token my-secret-token
O servidor inicia dois listeners:
- HTTP em
http://127.0.0.1:3001/mcp— endpoint do cliente MCP - WebSocket em
ws://127.0.0.1:9876— ponte da extensão do Chrome
Dica: Use
--tokenpara definir um token conhecido e pré-configurar os clientes. Se omitido, um token aleatório é gerado e exibido na inicialização.
2. Conecte os clientes MCP:
Claude CLI / Gemini CLI / Cursor (HTTP direto — recomendado):
http://localhost:3001/mcp?token=my-secret-token
Claude Desktop (exige stdio — use o proxy):
Adicione em ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"domshell": {
"command": "npx",
"args": ["-y", "@apireno/domshell", "--allow-write", "--token", "my-secret-token"]
}
}
}
Reinicie o Claude Desktop. As ferramentas do DOMShell aparecerão.
3. Conecte a extensão (Página de Opções):
- Vá para
chrome://extensions/ - Encontre DOMShell e clique em Options (ou clique com o botão direito no ícone da extensão → Options)
- Ative a opção MCP Bridge
- Cole o mesmo token que você usou na configuração do Claude Desktop (
my-secret-token) - Clique em Save — o indicador de status fica verde quando conectado
A página de opções mostra o status de conexão em tempo real: Disabled, Connecting, Connected ou Disconnected.
Alternativa: Conecte via terminal
Você também pode conectar pelo terminal do DOMShell em vez da página de opções:
dom@shell:$ connect my-secret-token
4. Teste:
Pergunte ao Claude: "Liste minhas abas abertas e me diga o que há na primeira."
Segurança
O servidor MCP é endurecido com múltiplas camadas de segurança. Por padrão, é somente leitura — o Claude pode navegar, mas não clicar ou digitar.
Níveis de Comandos
| Nível | Comandos | Padrão | Ativar Com |
|---|---|---|---|
| Leitura | ls, cd, pwd, cat, text, grep, find, tree, refresh, tabs, windows, here, screenshot, wait, eval, diff, history, bookmark, functions, watch, for, script, each | Ativado | (sempre ativo) |
| Navegação | navigate, goto, open, back, forward | Desativado | --allow-write |
| Escrita | click, focus, type, scroll, js, select, close, call | Desativado | --allow-write |
| Sensível | whoami (expõe cookies) | Desativado | --allow-sensitive |
O nível Navegação é separado do de Escrita porque navegar equivale a digitar uma URL — exige --allow-write, mas pula o prompt de confirmação interativo. Isso é importante para o Claude Desktop, onde /dev/tty não está disponível.
Flags de Segurança
| Flag | Descrição |
|---|---|
--allow-write | Ativar comandos de clique/foco/digitação/rolagem/js/seleção/fechar/navegar/voltar/avançar |
--allow-sensitive | Ativar whoami (acesso a cookies) |
--allow-all | Atalho para ambos |
--confirm | Optar por prompts y/n por ação no terminal do servidor antes de cada escrita. Desativado por padrão. |
--no-confirm | No-op (mantido para compatibilidade retroativa — prompts por ação estão desativados por padrão). |
--domains example.com,app.example.com | Restringir comandos a domínios específicos |
--expose-cookies | Mostrar valores completos de cookies (padrão: ocultos) |
--mcp-port N | Porta do endpoint HTTP MCP (padrão: 3001) |
--port N | Porta da ponte WebSocket (padrão: 9876) |
--log-file PATH | Arquivo de log de auditoria (padrão: audit.log) |
Confirmação por Ação (opt-in)
Os prompts de terminal por ação estão desativados por padrão — o terminal do servidor MCP é separado de onde o agente e o painel lateral realmente rodam, então o prompt é difícil de responder em qualquer configuração iniciada por GUI (Claude Desktop, Cursor, harness do CLI-Anything). O log de auditoria captura todos os comandos, e as flags de nível (--allow-write, --allow-sensitive) mais --domains continuam sendo os limites reais de segurança.
Se você iniciar o servidor no seu próprio terminal e quiser um prompt y/n antes de cada escrita, adicione --confirm:
[DOMShell] Claude wants to: click submit_btn
Allow? (y/n):
--no-confirm é preservado como no-op (corresponde ao padrão), então qualquer configuração existente que o use continua funcionando sem alterações.
Token de Autenticação
- Use
--tokenpara definir um token conhecido na configuração do servidor MCP, ou deixe o servidor gerar um aleatório na inicialização - A extensão deve apresentar esse token (via página de opções ou
connect <token>) antes que a ponte funcione - Conexões WebSocket sem um token válido são rejeitadas
- O token é armazenado em
chrome.storage.local— sobrevive a reinicializações do service worker
Lista de Domínios Permitidos
Com --domains, os comandos só são executados quando a URL da aba ativa corresponde:
npx tsx index.ts --allow-write --domains "github.com,docs.google.com"
Log de Auditoria
Cada comando é registrado com timestamps em audit.log (ou --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)
Desconectando
Desative a opção MCP Bridge na página de opções da extensão, ou execute disconnect no terminal do DOMShell:
dom@shell:$ disconnect
✓ Disconnected from MCP server.
A interface domshell_execute
O servidor MCP do DOMShell expõe uma única ferramenta por padrão — domshell_execute — a forma recomendada de usar o DOMShell. Você passa uma string de comando, exatamente como digitaria no terminal do DOMShell:
domshell_execute("ls")
domshell_execute("cd tabs/4815")
domshell_execute("find --type link --meta")
Chamadas com múltiplos comandos. Passe vários comandos separados por novas linhas e eles serão executados em sequência, com a saída combinada retornada — um fluxo de trabalho inteiro em uma única chamada de ferramenta:
domshell_execute("open https://example.com
cd main
text")
Uma única ida e volta em vez de três, e menos ciclos de chamadas de ferramenta.
Semântica de múltiplas linhas. Cada linha é executada em ordem na mesma sessão e faixa do MCP, então cwd, env e histórico persistem entre as linhas (o cd main da segunda linha é relativo à aba recém-aberta da primeira linha). Um erro em qualquer linha individual não interrompe o restante — sua mensagem de erro é incluída na saída combinada e as linhas subsequentes ainda são executadas. Esse é o formato certo para expressões idiomáticas de linha de limpeza como "cd path\ngrep pattern\ncd back", onde a restauração final deve ser executada mesmo se a etapa intermediária falhar. Implementação: mcp-server/index.ts:1115-1136.
Dois modos:
| Modo | Ferramentas expostas | Use quando |
|---|---|---|
| Ferramenta única (padrão) | Somente domshell_execute | Uso normal. Uma aprovação cobre a sessão inteira — sem prompts por comando. |
Granular (--granular) | 38 ferramentas por comando (domshell_ls, domshell_click, …) | Você quer que seu cliente MCP solicite aprovação por tipo de operação — supervisão humana mais refinada na camada do cliente. |
Inicie o servidor com --granular para as ferramentas por comando:
npx @apireno/domshell --granular
A segurança é idêntica em ambos os modos. Os níveis do lado do servidor do DOMShell (write / sensitive — definidos por --allow-write, --allow-sensitive, com --confirm opcional para prompts do terminal do servidor por ação) controlam operações arriscadas independentemente de qual ferramenta emitiu o comando. O modo granular não adiciona segurança — ele adiciona um prompt de aprovação extra no seu cliente MCP por tipo de operação. Isso é mais supervisão humana, não mais proteção.
Referência de Ferramentas MCP (modo --granular)
A tabela abaixo lista as ferramentas por comando expostas quando o servidor é executado com --granular. No modo de ferramenta única padrão, execute os mesmos comandos por meio de domshell_execute — a coluna Maps To mostra a string de comando.
| Ferramenta MCP | Mapeia para | Nível |
|---|---|---|
domshell_tabs | tabs (listar todas as abas) | Leitura |
domshell_here | here (ir para a aba ativa) | Leitura |
domshell_ls | ls [options] (nível DOM ou navegador) | Leitura |
domshell_cd | cd <path> (~, ~/tabs/, /, ..) | Leitura |
domshell_pwd | pwd | Leitura |
domshell_cat | cat <name> | Leitura |
domshell_text | text [name] [-n N] [--links] (texto em massa; links=true incorpora URLs) | Leitura |
domshell_read | read [name] [--meta] [--text] [-d N] (subárvore estruturada) | Leitura |
domshell_find | find [pattern] [--type ROLE/alias] [--meta] [--text] [-n N] (o tipo aceita aliases difusos: input, dropdown, nav, etc.) | Leitura |
domshell_grep | grep [-r] [-n N] [--content] <pattern> (descoberta de seções) | Leitura |
domshell_tree | tree [depth] | Leitura |
domshell_extract_links | extract_links [name] [-n N] (todos os links como [text](url)) | Leitura |
domshell_extract_table | extract_table <name> [--format csv] (tabela → markdown/CSV) | Leitura |
domshell_refresh | refresh | Leitura |
domshell_navigate | navigate <url> (aba atual) | Navegação |
domshell_open | open <url> (nova aba) | Navegação |
domshell_click | click <name> | Escrita |
domshell_focus | focus <name> | Escrita |
domshell_scroll | scroll [down|up] [N] ou scroll <target> | Escrita |
domshell_js | js <code> (execução arbitrária de JavaScript) | Escrita |
domshell_type | type <text> | Escrita |
domshell_submit | submit <input> <value> [--submit btn] (preenchimento atômico de formulário) | Escrita |
domshell_back | back (voltar no histórico do navegador) | Navegação |
domshell_forward | forward (avançar no histórico do navegador) | Navegação |
domshell_close | close [tab-id] (fechar uma aba) | Escrita |
domshell_screenshot | screenshot (capturar aba como imagem PNG) | Leitura |
domshell_select | select <name> <value> (seleção em dropdown) | Escrita |
domshell_wait | wait <pattern> [--type ROLE] [--timeout N] (aguardar por elemento) | Leitura |
domshell_eval | eval <expression> (avaliação JS somente leitura, sem --allow-write necessário) | Leitura |
domshell_diff | diff [--json] (comparar árvore com snapshot pré-ação) | Leitura |
domshell_whoami | whoami | Sensível |
domshell_functions | functions [pattern] [--json] (listar funções de página chamáveis) | Leitura |
domshell_call | call <funcName> [args] (chamar uma função JS global) | Escrita |
domshell_watch | watch <cmd> [--interval N] [--times N] [--until-change] (re-execução periódica) | Leitura |
domshell_for | for <source> : <template> (iterar sobre linhas de saída, {} substituído) | Leitura |
domshell_script | script list|save|show|run|delete (scripts com substituição de $1) | Leitura |
domshell_each | each [--pattern FILTER] <cmd> (operações entre abas) | Leitura |
domshell_execute | (qualquer comando) | Variável |
Roteiro
Distribuição e Configuração
- Listagem na Chrome Web Store — disponível na Chrome Web Store
- Lançamento no GitHub com .crx — lançamento v1.1.1 com zip da extensão
- Assistente de configuração MCP —
npx @apireno/domshell initdetecta clientes MCP instalados, gera um token e grava a configuração automaticamente - Suporte para outros clientes MCP — Gemini Desktop, OpenAI ChatGPT desktop, Cursor, Windsurf e outros hosts compatíveis com MCP
Novos Comandos
-
watch— re-execução periódica de um comando (ex.:watch ls --times 3 --interval 1para verificar mudanças no DOM) -
history— histórico de comandos com recall (history,!npara re-executar) -
back/forward— navegação de histórico no estilo navegador dentro da aba atual -
close— fechar a aba atual (closeouclose <tab-id>) -
screenshot— capturar uma captura de tela da aba atual (útil para verificação visual junto com a inspeção da árvore AX) -
pipe/|— canalizar saída entre comandos (ex.:find --type link | grep login) -
select <name>— selecionar uma opção de um dropdown<select>por valor ou texto visível -
scroll— rolar a página ou um elemento específico (scroll down,scroll up,scroll <name>) -
wait— aguardar um elemento específico aparecer (ex.:wait submit_btnbloqueia até que ele exista na árvore) - Loop
for— iterar sobre linhas de saída de comando (ex.:for "find --type heading -n 3" : text {}) — substitui a iteração manual - Comando
script— salvar e executar scripts de múltiplos comandos (ex.:script save scrape open url ; cd main ; text) para fluxos de trabalho repetíveis
Camada JavaScript
- Comando
js— executar JavaScript arbitrário no contexto da aba e retornar o resultado -
functions+call—functions [pattern]lista funções JS globais chamáveis com nome/aridade/parâmetros;call funcName arg1 arg2as invoca.callé do nível de escrita. -
eval <expr>— avaliação rápida de expressões (ex.:eval document.title,eval window.location.href)
Ergonomia para Agentes
- Flag
--text— mostrar pré-visualizações de texto visível inline comlsefindusando.innerText(somente texto renderizado, respeita a visibilidade CSS); comprimento configurável via--textlen N;cattambém mostra VisibleText separadamente do textContent - Flag
--meta— mostrar propriedades DOM (href, src, id, tag) inline com a saída dels,finderead— essencial para extrair URLs sem chamadascatseparadas - Correspondência
--content— pesquisar por conteúdo de texto visível comgrep --contentefind --content(oufind --text "pattern") — encontra elementos pelo que eles exibem, não apenas pelo nome AX - Resolução de caminhos — todos os comandos aceitam caminhos relativos (ex.:
text main/article/paragraph,click form/submit_btn) — elimina idas e voltascddesnecessárias - Navegação entre irmãos — flags
--after/--beforeemlspara fatiar filhos relativos a um elemento de referência (ex.:ls --after heading --type link --meta) - Flag
--linksemtext— incluir URLs de hiperlinks inline como[text](url)markdown na saída de texto; extrai tanto o conteúdo quanto os destinos dos links em uma única chamada (ex.:text --links main/paragraph) - Aliases de tipo difusos para
find—find --typeaceita aliases em linguagem natural (input, dropdown, nav, toggle, modal, image, btn, sidebar, etc.) que se expandem para papéis AX correspondentes — elimina chamadas de ferramenta desperdiçadas ao adivinhar nomes exatos de papéis - Cache de texto visível — cache preguiçoso para resultados de
innerText, indexado porbackendDOMNodeId, limpo na reconstrução da árvore — elimina chamadas CDP redundantes durante a correspondência--contentemgrep/find -
bookmark/alias— salvar caminhos nomeados para navegação rápida (ex.:bookmark inbox ~/tabs/gmail/main/inbox_list,cd @inbox) -
each(multi-aba) — executar um comando em várias abas (ex.:each --pattern wiki textpara extrair texto de todas as abas da Wikipédia) - Modo de saída estruturada — flag
--jsonem comandos para saída analisável por máquina (ex.:ls --json,cat --json,find --json,diff --json) - Persistência de sessão — salvar e restaurar o estado do shell (caminho, variáveis de ambiente, favoritos, histórico) entre reinicializações do service worker via
chrome.storage.local -
diff— comparar snapshots da árvore AX para ver o que mudou após uma ação (snapshots automáticos antes de clicar/enviar/navegar) - Isolamento de grupo de abas por sessão — as abas de cada sessão são colocadas em um grupo de abas do Chrome rotulado e cada comando é confinado a esse grupo, para que o agente trabalhe em sua própria faixa enquanto você continua navegando livremente em outras abas da mesma janela (#32)
- DOMShell multi-sessão — cada console do painel lateral e cada conexão MCP obtém sua própria sessão de shell independente (seu próprio diretório atual, aba e cursor DOM), para que vários consoles humanos e agentes concorrentes trabalhem cada um em uma faixa isolada em vez de compartilhar um cursor global (#33)
- Sessões declaradas por agente — um
group_idopcional emdomshell_executepermite que um agente se dirija a uma faixa específica: omita-o para a faixa atual,"new"para uma nova, ou passe um id para entrar em uma faixa existente — para que dois chats de agentes compartilhando uma conexão MCP permaneçam isolados, e um agente possa entregar uma sessão a outro (#34)
Plataforma
- Navegador headless autônomo — distribuir o DOMShell como um processo Chromium headless autônomo (via Chrome for Testing ou Chromium incorporado) que os agentes iniciam diretamente — sem instalação de extensão, sem perfil do Chrome do usuário; apenas
npx @apireno/domshell --headlesse conectar via MCP. Ideal para pipelines de CI, automação no lado do servidor e fluxos de trabalho agente-em-loop onde um navegador visível não é necessário - Extensão para Firefox — portar para Firefox usando a API WebExtensions + protocolo de depuração remota
- Backend Playwright/Puppeteer — alternativa à extensão do Chrome para fluxos de trabalho headless de agentes
- Modo API REST — expor comandos do DOMShell via HTTP para integrações não-MCP
- Build WASM — compilar o DOMShell para WebAssembly para que possa ser incorporado diretamente em um site para demonstrações interativas sem exigir instalação de extensão do Chrome
Experimentos
- Nexa: DOMShell vs HTML bruto — mesmo modelo (Qwen3-4B), mesmas tarefas: compare a interface de texto/árvore AX do DOMShell com a raspagem de HTML bruto. Testes em ambos os backends nexa serve e Ollama. Encontrei uma interação cruzada: Ollama+DOMShell e Nexa+HTML são igualmente melhores (média de 1,20). Veja
experiments/nexa_ollama/. - Nexa vs Claude (tamanho do modelo) — comparei Qwen3-1.7B/4B em tarefas progressivas. Limite de capacidade em T3 (extração de parágrafos). O 4B mostra melhor recuperação de erros. Veja
experiments/nexa_claude/. - Disputa de modelos — comparei Qwen3-4B, Hermes3-3B, Granite4-Tiny, Llama3.2-3B em Ollama+DOMShell. Qwen3-4B continua sendo o melhor (8/15), único modelo a quebrar o limite T3. Llama3.2-3B em segundo lugar (7/15, zero alucinações). Veja
experiments/model_shootout/. - Benchmark de custo de tokens — medir o total de tokens de entrada/saída por tarefa entre DOMShell e navegação baseada em captura de tela (CiC). Estender o
experiments/claude_domshell_vs_cic/existente com contagem de tokens. Hipótese: texto estruturado (2-3KB por resposta) vs capturas de tela em base64 (500KB+) deve mostrar economia de tokens >2x além da redução de 2x na contagem de chamadas já medida
Integrações
Nexa AI (LLM local)
Execute o DOMShell com modelos locais via nexa-sdk — automação de navegador totalmente no dispositivo, sem necessidade de API em nuvem. Usa o mesmo protocolo MCP do Claude Desktop, mas alimentado por inferência local (Granite-4-Micro, Qwen3, etc.).
python integrations/nexa/agent.py --task "Open wikipedia.org/wiki/AI and extract the first paragraph" --verbose
Veja integrations/nexa/ para configuração e uso.
Como Este Projeto Foi Construído
A especificação técnica do DOMShell foi escrita pelo Google Gemini, projetada como um prompt abrangente que poderia ser entregue diretamente a um agente de codificação para construir e estruturar todo o projeto do zero. A especificação original completa está preservada em intitial_project_prompt.md.
A implementação foi então construída pelo Claude (Anthropic) via Claude Code, trabalhando a partir dessa especificação.
Um projeto projetado por IA, construído por outra IA, destinado ao uso por agentes de IA. São agentes até o fim.
Links
- Chrome Web Store
- npm: @apireno/domshell
- Registro de Servidores MCP
- mcpservers.org
- Glama
- Blog: Por que construí um sistema de arquivos para o navegador
- Página inicial do projeto e política de privacidade
- Construído por Pireno
Licença
MIT