Configurei um Plugin do WordPress Sem Tocar no Navegador

Configurei um plugin WordPress de produção sem abrir o navegador uma única vez. Login, configurações, posicionamento de widgets, upload de plugin, limpeza de cache, debugging – tudo pelo Claude Code.

Precisei configurar um plugin multilíngue no nosso blog WordPress de produção. O plugin é CM Multilingual, que construí com Claude Code em 2 dias. Isso normalmente significa: abrir o admin, fazer login, navegar até as configurações, clicar nas abas, configurar idiomas, adicionar widgets, testar o frontend, voltar, ajustar, testar novamente.

Em vez disso, digitei isto no Claude Code:

vamos adicionar o seletor de idioma e mostrar apenas posts daquele idioma na home

E o Claude fez o resto. Não gerando um script – mas usando o navegador de verdade.

Como o Chrome DevTools MCP lê a página

O Chrome DevTools MCP dá ao Claude acesso ao seu navegador através do Chrome DevTools Protocol. O Claude pode navegar páginas, ler o DOM como uma árvore de acessibilidade, clicar elementos, preencher formulários, fazer upload de arquivos, tirar screenshots e executar JavaScript.

Aqui está como a interação realmente funciona. Eu disse:

ei claude eu quero que você passe por todo o processo com este plugin, temos um tema preparado para ele. Você pode usar chrome devtools mcp

Claude começou listando as páginas abertas do navegador:

chrome-devtools - list_pages
⎿ ## Pages
   1: chrome://new-tab-page/ [selected]

Nenhum WordPress aberto ainda. Então o Claude navegou para a página de login, tirou um snapshot do formulário:

chrome-devtools - take_snapshot
⎿ uid=2_5 textbox "Username or Email Address"
  uid=2_7 textbox "Password"
  uid=2_11 button "Log In"

Então preencheu os campos e clicou em login:

chrome-devtools - fill (uid: "2_5", value: "edy@codeminer42.com")
chrome-devtools - fill (uid: "2_7", value: "supersecretpassword123")
chrome-devtools - click (uid: "1_11")

Terminal do Claude Code mostrando os comandos MCP fill com UIDs dos elementos

Formulário de login do WordPress preenchido pelo Claude via MCP

É isso. Sem seletores CSS. Sem XPath. O Claude lê a árvore de acessibilidade (a mesma estrutura que leitores de tela usam) e identifica elementos pelo seu papel semântico e conteúdo.

Configurando idiomas em produção

Claude navegou para Settings > CM Multilingual. Um take_snapshot revelou o formulário de configurações. Claude selecionou “English” de um dropdown referenciando uid=2_134, clicou “Add Language”, viu o aviso sobre posts não atribuídos, clicou “Assign all to English”, então adicionou Portuguese.

Pude acompanhar através dos screenshots que Claude tirou a cada passo. Mas não precisei. Claude reportou o que encontrou e o que fez.

Após configurar ambos os idiomas, disse:

gostaria de ver você traduzindo um post usando IA, também quero que adicione um seletor de idioma na home page.

Claude navegou para a página Widgets, encontrou o widget “Language Switcher” na lista de widgets disponíveis (uid=1_322), clicou para expandir, selecionou “Sidebar” como destino, e clicou “Add Widget”. O widget apareceu com bandeiras e nomes dos idiomas.

Quando disse que o seletor deveria estar no topo da sidebar, não no final, Claude usou os controles de movimento na interface de widgets do WordPress para reordená-lo.

Fazendo upload de atualizações do plugin

Precisei fazer deploy de uma correção de código. Claude:

  1. Executou npm run build para compilar o JS
  2. Criou um arquivo zip com zip -r ~/Downloads/cm-multilingual.zip ...
  3. Navegou para Plugins > Add Plugin > Upload Plugin
  4. Fez upload do arquivo zip da minha pasta Downloads
chrome-devtools - upload_file (uid: "6_272", filePath: "/Users/edy/Downloads/cm-multilingual.zip")
⎿ File uploaded from /Users/edy/Downloads/cm-multilingual.zip.
  1. Clicou “Install Now”, depois “Replace current with uploaded”
  2. Limpou o cache via dropdown Caching na barra de ferramentas admin

Sem FTP. Sem SSH. Sem gerenciador de arquivos. Claude pegou um arquivo local, fez upload através da interface do WordPress, e substituiu o plugin rodando. Fizemos isso cinco vezes em uma sessão enquanto iterávamos nas correções.

O diagnóstico que não consegui encontrar sozinho

A homepage estava mostrando posts em português misturados com posts em inglês. Estava travado. Quando testei localmente com uma instalação limpa do WordPress (mesmo tema, apenas o plugin), tudo funcionou bem. Mas produção tinha dezenas de plugins, configurações de blocos customizadas, e camadas de caching. Encontrar onde a query estava sendo modificada naquele ambiente era um problema diferente. Disse:

está aparecendo em https://blog.codeminer42.com/

Claude navegou para a página Reading Settings e descobriu que o site usa uma página estática como front page (página #6982). Então abriu aquela página no editor de blocos e executou JavaScript para extrair a configuração do bloco Query Loop:

() => {
  const content = wp.data.select('core/editor').getEditedPostContent();
  return content.substring(0, 1000);
}

Claude Code executando query wp.data para extrair configuração do bloco

Editor de blocos da homepage mostrando o bloco de banner Dev Weekly

A resposta revelou que a homepage tem dois blocos Query Loop:

  • Bloco 1: taxQuery: {"category": [465]} – Banner Dev Weekly (1 post)
  • Bloco 2: taxQuery: {"category": [21]} – Listagem principal de posts (apenas categoria “Posts”)

Nosso plugin estava substituindo o tax_query do bloco com o filtro de idioma, apagando o filtro de categoria. É por isso que posts Dev Weekly apareciam – a exclusão de categoria havia sumido.

É isso que faz o MCP funcionar. Uma instalação local limpa é fácil de navegar. Um site WordPress de produção com dezenas de plugins e blocos customizados é uma fera diferente. Claude navegou a bagunça, inspecionou o estado interno do editor de blocos através do wp.data, e encontrou a causa raiz em uma query. Aprendeu onde as coisas estavam mais rápido do que eu conseguiria.

Como um cookie oculto sobrescreveu silenciosamente a detecção de idioma

Após fazer deploy do filtro de idioma, a homepage começou a mostrar apenas posts em português. Disse:

a home page ainda está mostrando posts em português, você tem certeza que isso não pode ser configurado na página?

Claude verificou os cookies:

() => {
  const cookies = document.cookie.split(';').map(c => c.trim());
  return cookies.find(c => c.startsWith('cm_ml_lang='));
}
// Resultado: "cm_ml_lang=pt_BR"

Um cookie cm_ml_lang de uma visita anterior a /pt-br/ estava sobrescrevendo a detecção de idioma baseada em URL. Claude limpou o cookie, recarregou, e confirmou a correção. Atualizamos o código para usar detecção baseada apenas em URL para queries secundárias da front-page.

A configuração oculta

O link do seletor de idioma inglês estava apontando para /en/ em vez de /. Claude navegou para Settings > CM Multilingual > URLs:

chrome-devtools - take_screenshot
⎿ [Screenshot mostrando "Hide language prefix for default language" DESMARCADO]

Uma checkbox. Só isso. A configuração estava desmarcada em produção, mesmo estando marcada no nosso ambiente de dev local. Claude marcou, clicou “Save Changes”, e tanto os links do seletor quanto a detecção de idioma da homepage começaram a funcionar corretamente.

Sem MCP, eu estaria alternando Alt-Tab entre terminal e navegador, verificando páginas de configurações manualmente. Com MCP, Claude navegou diretamente para a configuração e leu o estado do formulário.

Testando o que o Facebook realmente vê vs. o que o navegador renderiza

Alguém compartilhou nossa homepage /pt-br/ e o preview mostrou o título e imagem de um post aleatório. Disse:

quando compartilho o link https://blog.codeminer42.com/pt-br/ ele mostra o preview de um post, não deveria ser assim

Claude começou inspecionando as meta tags OG no DOM via evaluate_script. Isso confirmou o problema – mas aí veio o insight chave: crawlers sociais não executam JavaScript. Precisávamos testar o que o Facebook realmente vê:

curl -s https://blog.codeminer42.com/pt-br/ 
  -H 'User-Agent: facebookexternalhit/1.1' | grep -E 'og:title|og:image'

A correção passou por três iterações, cada uma seguindo o mesmo loop: editar PHP localmente, executar testes, buildar zip, upload via página Plugins (Claude fez o upload toda vez), limpar cache, curl para verificar. Primeiro o título/descrição, depois descobrindo que AIOSEO não tem filtro para og:image, então usando output buffering para substituir a URL da imagem no HTML bruto.

O que eu realmente digito

Aqui está o que as pessoas perguntam: escrevo prompts detalhados? Não. Aqui estão coisas reais que digitei durante a sessão:

  • “vamos adicionar o seletor de idioma e mostrar apenas posts daquele idioma na home”
  • “o seletor de idioma deve aparecer no início da sidebar, não no final. os leitores devem vê-lo”
  • “acabei de publicar o post pt br, posso te dizer. está aparecendo em https://blog.codeminer42.com/
  • “não, não é. seletor de idioma, quando clico em English, vai para /en, deveria ser /”
  • “faça” (quando Claude perguntou se deveria fazer upload)

Claude descobre o resto. Lê a página, identifica o que precisa acontecer, e executa. Quando algo não funciona, descrevo o sintoma e Claude diagnostica.

O que faz isso diferente de automação de navegador

Já usei Puppeteer, Playwright, Selenium. Isso não é automação – é colaboração.

Com Puppeteer, você escreve um script que assume que a estrutura da página não mudará. Se a interface admin for atualizada, seu script quebra. Com MCP, Claude lê a página a cada execução, adapta-se a mudanças na UI, e lida com diálogos inesperados. Para algo como “verificar o customizer do tema por opções de exclusão de categoria”, você precisaria codificar todo caminho DOM com antecedência no Puppeteer. Claude navegou lá, abriu cada seção, leu as opções, e reportou que não havia nenhuma.

Combinado com edição de código. Na mesma sessão, Claude editou arquivos PHP localmente, executou 156 testes PHPUnit, buildou o plugin, E fez upload para produção através do navegador. O loop de feedback entre escrever código e ver funcionando é instantâneo.

Árvore de acessibilidade, não seletores. Elementos são identificados por papel semântico e conteúdo (uid=1_11 button "Log In"), não por classes CSS ou caminhos DOM que quebram quando a página muda.

Configurando

O servidor MCP está em github.com/anthropics/anthropic-mcp-tools/chrome-devtools. Instale-o:

npm install -g @anthropic/chrome-devtools-mcp

Então adicione à sua configuração MCP do Claude Code (.claude/settings.json ou .claude/settings.local.json):

{
  "mcpServers": {
    "chrome-devtools": {
      "command": "npx",
      "args": ["-y", "@anthropic/chrome-devtools-mcp"]
    }
  }
}

Chrome precisa estar rodando com DevTools Protocol habilitado na porta 9222. Você pode iniciar manualmente:

open -na 'Google Chrome' --args 
  --remote-debugging-port=9222 
  --user-data-dir=/tmp/chrome-debug-profile 
  --no-first-run 
  --no-default-browser-check

Mas aqui está o problema – você vai esquecer. Sempre. E quando Claude tenta usar uma ferramenta chrome-devtools sem uma instância de debug rodando, falha silenciosamente ou gera um erro incompreensível. Então adicionei um hook do Claude Code que auto-inicia Chrome antes de qualquer chamada de ferramenta MCP:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__chrome-devtools__",
        "hooks": [
          {
            "type": "command",
            "command": "if ! lsof -i :9222 -sTCP:LISTEN 2>/dev/null | grep -q '^Google'; then open -na 'Google Chrome' --args --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug-profile --no-first-run --no-default-browser-check >/dev/null 2>&1 & sleep 2; fi",
            "timeout": 10,
            "statusMessage": "Garantindo que Chrome debug está rodando..."
          }
        ]
      }
    ]
  }
}

Isso vai no seu ~/.claude/settings.json sob a chave hooks. O matcher garante que só executa quando Claude está prestes a usar uma ferramenta chrome-devtools. O comando verifica se a porta 9222 já está escutando – se não, inicia uma instância Chrome debug fresca e aguarda 2 segundos para iniciar.

Problemas que enfrentei

O Chrome DevTools MCP ainda é relativamente novo. Aqui está o que realmente deu errado durante minhas sessões.

Screenshots muito grandes. O MCP tira screenshots constantemente para entender a página. Algumas páginas admin do WordPress produzem screenshots tão grandes que Claude dá erro com algo como “image too large”. Isso não aconteceu frequentemente, mas quando aconteceu tive que voltar a um ponto anterior na conversa, antes do screenshot gigante. Às vezes isso também não funcionava e tive que reabrir Claude Code completamente.

Pop-ups perdidos. Claude executa uma ação, um pop-up ou toast de erro aparece por um segundo, mas Claude estava executando um comando sleep ou esperando outra coisa. Quando verifica a página novamente, o pop-up sumiu e Claude não tem ideia do que aconteceu. Tive que intervir e dizer “apareceu um pop-up de erro” ou “verifique o console” para voltar ao rumo.

Esquecendo de verificar Network/Console. Claude nem sempre pensa em olhar as requisições de rede do navegador ou logs do console. Foca na página visível. Quando algo falhava silenciosamente – nenhum erro visível, apenas comportamento errado – tive que cutucá-lo: “verifique o console”, “verifique a aba network”, “olhe os logs.”

Funciona bem. Claude não preenche campos mais rápido que você, e também não “vê” a página mais rápido. Mas funciona numa velocidade boa o suficiente, e a vantagem real é que cada passo está integrado com o agente de codificação. Se Claude clica um botão e nada acontece, tenta outra coisa. Pode ler o console e já verificar o código para descobrir o que está acontecendo. Enquanto está fazendo sua coisa, você pode focar em outros trabalhos.

Quando fica perdido – perdeu um pop-up, esqueceu de verificar o console – você redireciona. Pense em pair programming onde você é o navegador, e Claude está dirigindo o browser. Não precisa assistir cada segundo, mas você verifica de vez em quando.

Por que continuo usando

O loop. Claude edita código, roda testes, builda um zip, faz upload para produção, limpa o cache, navega para a página, verifica se funciona, e se não, diagnostica por quê – tudo numa conversa. “A homepage está mostrando posts em português” leva a inspecionar cookies, limpá-los, verificar a correção, atualizar o código, e fazer redeploy. Sem Alt-Tab, sem esquecer o que estava debugando.

Obrigado pela leitura!

We want to work with you. Check out our Services page!

Edy Silva

I own a computer

View all posts by Edy Silva →