Criar uma extensão do Chrome com IA é um dos jeitos mais fáceis de entrar no vibe coding: uma extensão são poucos arquivos pequenos, você testa no seu próprio navegador sem nenhum servidor, e agentes de código como o Claude Code ou o Codex conhecem bem a estrutura do Manifest V3. A parte difícil não é o código; é escolher a peça certa (content script, service worker, popup), pedir o mínimo de permissões e nunca colocar chaves de API dentro da extensão. Este post mostra o caminho que eu sigo de uma pasta vazia até a Chrome Web Store.
Como exemplo, vamos criar algo pequeno, mas real: uma extensão que resume o artigo da página atual com uma API de IA. Com vibe coding você tem uma primeira versão numa tarde; a versão que você publica precisa de mais algumas regras.
Conheça as peças primeiro
Para dizer ao agente o que você quer, basta conhecer os quatro blocos de uma extensão do Chrome:
manifest.json: A identidade da extensão. Nome, versão, qual arquivo faz o quê e quais permissões ela pede. Extensões novas usam o Manifest V3.- Content script: JavaScript que roda dentro da página que você visita. Ele pode ler o texto da página, adicionar um botão, esconder um elemento. Não consegue acessar diretamente as variáveis JavaScript da própria página; roda num “mundo” isolado.
- Service worker (background): Código que roda independente de qualquer página. Ele reage a eventos como um clique no ícone da barra de ferramentas, mudanças de aba ou alarmes, e faz requisições de rede. Uma propriedade importante: o Chrome o desliga quando está ocioso, então qualquer coisa guardada numa variável global pode sumir.
- Popup e página de opções: A janelinha que abre quando você clica no ícone e uma página separada para as configurações. As duas são páginas HTML comuns.
Essas peças conversam entre si com chrome.runtime.sendMessage e chrome.tabs.sendMessage. Quando algo que o agente escreveu “não funciona”, a causa muitas vezes é código rodando na peça errada, por exemplo tentar usar document no service worker.
1. Preparação e estrutura do projeto
O que você precisa: Chrome (ou outro navegador Chromium), Git, um editor de código e um agente de código. Uma ferramenta de build não é obrigatória para a primeira extensão; JavaScript puro basta. Se o projeto crescer, frameworks de extensão baseados em Vite, como o WXT, adicionam TypeScript e recarregamento automático, mas eu pularia essa camada extra na primeira versão. Sem ela, os erros do agente ficam mais fáceis de ver.
mkdir page-summarizer && cd page-summarizer
git init
Depois coloque na raiz do projeto um arquivo curto de regras que o agente lê em toda sessão (CLAUDE.md ou AGENTS.md):
# Page Summarizer (Chrome extension)
- Manifest V3, plain JavaScript, no build step.
- Minimal permissions: activeTab, scripting, storage. No <all_urls>.
- No remote code; no eval, no remote <script>.
- No API key in the extension; requests go to our own server.
- Persistent state in chrome.storage, not in service worker globals.
- Ask before adding a permission or a package.
2. O primeiro prompt
Na primeira mensagem, eu peço ao agente para explicar o que vai criar e quais arquivos vai gerar, e só depois escrever o código:
Read CLAUDE.md. Build a Manifest V3 Chrome extension:
- Clicking the toolbar icon opens a popup with a "Summarize" button.
- Pressing it grabs the article text from the active tab (use activeTab +
scripting and inject the content script only at that moment).
- The text goes to the service worker, which POSTs it to
https://api.my-server.example/summarize.
- Show the summary in the popup; on error show a readable message.
- Keep the last 10 summaries in chrome.storage.local.
First list the files and what each one does, then create them.
Finish with step-by-step instructions to load and test it.
O manifest.json que o agente gera deve ficar mais ou menos assim:
{
"manifest_version": 3,
"name": "Page Summarizer",
"version": "0.1.0",
"description": "Summarizes the article on the current page in one click.",
"action": { "default_popup": "popup.html" },
"background": { "service_worker": "background.js" },
"permissions": ["activeTab", "scripting", "storage"],
"host_permissions": ["https://api.my-server.example/*"]
}
O que eu confiro aqui é a lista de permissões. O activeTab dá acesso temporário só à aba atual quando o usuário clica no ícone. Os agentes muitas vezes adicionam "<all_urls>" ou "tabs" por conveniência; isso mostra um aviso assustador aos usuários e deixa a revisão da loja mais lenta.
3. Carregue, teste, depure
Antes de chegar perto da loja, teste a extensão no seu próprio navegador:
- Abra
chrome://extensions. - Ative o Developer mode no canto superior direito.
- Clique em Load unpacked e escolha a pasta do projeto.
- Fixe o ícone na barra de ferramentas e teste num artigo.
Depois de mudar o código, pressione o botão de recarregar no card da extensão em chrome://extensions. Se um content script mudou, recarregue também a página em que está testando.
Os três lugares que mais ajudam na depuração:
- Service worker: O link “service worker” no card da extensão abre um DevTools próprio. Requisições de rede e erros de background aparecem aqui.
- Popup: Com o popup aberto, clique com o botão direito nele e escolha Inspect.
- Content script: Os logs aparecem no console do DevTools da própria página; você pode escolher a sua extensão no seletor de contexto no topo do console.
Se o card da extensão mostrar um botão Errors, copie o conteúdo do jeito que está e entregue ao agente:
I loaded the extension. Pressing "Summarize" in the popup shows this error:
[error text]
The service worker console also shows:
[log]
Explain the cause, fix it, and list what you changed in which file.
Dizer onde quebrou, no que você clicou e o que cada console mostra permite ao agente corrigir o problema em vez de chutar.
4. Armazenamento: escolha o lugar certo
chrome.storage.local: Dados neste dispositivo, como o histórico de resumos.chrome.storage.sync: Sincronizado entre dispositivos pelo perfil do Chrome do usuário. A cota é pequena; use só para configurações.chrome.storage.session: Apagado quando o navegador fecha; bom para estado temporário que precisa sobreviver ao reinício do service worker.
Não existe localStorage num service worker. Se o agente tentar usar, é por isso que falha. E não esqueça a permissão storage no manifest.json.
5. Mantenha as chaves de API fora da extensão
Esse é o erro que eu mais vejo em extensões feitas com IA. O agente escreve “cole sua chave da OpenAI aqui” e coloca uma constante no background.js. Uma extensão publicada é um arquivo ZIP; qualquer pessoa pode baixá-lo, descompactar e ler a sua chave. Minificar ou ofuscar não muda isso.
A estrutura certa é um pequeno proxy:
- A extensão chama o seu próprio servidor (
https://api.my-server.example/summarize). - O servidor guarda a chave no ambiente dele e chama a API de IA real.
- O servidor limita a taxa de requisições (por usuário ou IP) e rejeita textos grandes demais.
Abra um projeto separado para esse servidor e diga ao agente:
Write a small HTTP service: POST /summarize takes { text } in the body.
Cap the text at 20,000 characters, call the AI API with the key from an
environment variable, return { summary }. Allow CORS only for the
chrome-extension://<EXTENSION_ID> origin. Add a simple rate limit.
Never log the key. Create a .env.example file.
O ID da extensão aparece em chrome://extensions quando você a carrega sem empacotar; depois de publicada na loja, ele pode ser diferente. Atualize a configuração de CORS antes de publicar. Se os usuários usam a própria chave (comum em ferramentas para desenvolvedores), peça a chave na página de opções e guarde no chrome.storage.local; nunca envie a sua.
O que a IA erra
- Escrever código Manifest V2.
background.page,chrome.browserAction, uma background page persistente ouwebRequestBlockingvêm de exemplos antigos. Diga ao agente “use o equivalente do Manifest V3”. - Achar que o service worker está sempre rodando. Um contador numa variável global ou um
setIntervalpara depois de um tempo. Usechrome.alarmspara trabalho agendado echrome.storagepara o estado. - Pedir permissões demais.
<all_urls>,tabsehistorygeralmente são desnecessárias. Peça ao agente para justificar cada permissão numa frase; remova as que ele não conseguir justificar. - Carregar código remoto. Puxar uma biblioteca de um CDN com
<script>ou usarevalnão é permitido no Manifest V3. Coloque a biblioteca dentro do pacote. - Tentar acessar variáveis da página a partir de um content script. Como ele roda num mundo isolado, não enxerga
window.someApp; precisa trabalhar pelo DOM. - Esquecer respostas assíncronas nas mensagens. Se um listener
onMessageresponde de forma assíncrona, ele precisa fazerreturn true, senão o popup recebe uma resposta vazia. - Achar que todo site tem o mesmo HTML. Para pegar o texto do artigo, procure primeiro um elemento
articleoumaine tenha uma alternativa sensata. Teste em três sites diferentes.
Segurança
- Os segredos ficam no
.env, no servidor. Nada de.envna pasta da extensão; ele acabaria no ZIP. - Nunca cole chaves de API no chat. O agente precisa do nome da variável, não da chave.
- Leia os comandos que o agente executa. Principalmente instalações de pacotes e qualquer coisa como
curl … | sh. - Não confie nos dados da página. Não renderize no popup com
innerHTMLo texto que o content script leu; usetextContent. Senão uma página maliciosa pode injetar código na sua extensão. - Verifique de quem vem uma mensagem. Se você não precisa de mensagens de fora, não adicione
externally_connectable; se precisa, mantenha as origens permitidas restritas. - Colete só o necessário. Se o texto da página vai para o seu servidor, diga isso com clareza e não o armazene lá.
6. Publicação na Chrome Web Store
Em linhas gerais, a publicação é assim:
- Crie uma conta de desenvolvedor. Cadastre-se no painel de desenvolvedor da Chrome Web Store; há uma taxa de cadastro única.
- Empacote. Compacte a pasta do projeto num ZIP com o manifest na raiz. Deixe de fora
.git,node_modules, arquivos de teste e.env. - Preencha a página da loja. Descrição, capturas de tela, ícones, categoria.
- Preencha a seção de privacidade. Informe o propósito único da extensão, justifique cada permissão e declare quais dados de usuário você coleta. Se você coleta dados, precisa de uma URL pública de política de privacidade.
- Envie para revisão. O tempo varia. Permissões amplas de host e código difícil de ler podem atrasar; se for rejeitada, o e-mail diz qual política você violou.
O agente ajuda aqui também:
I'm submitting this extension to the Chrome Web Store. For each
permission in manifest.json, write a one-sentence justification for the
store form, write the single-purpose description and list the user data
we collect. Tell me if any permission looks unnecessary. Give me a command
that builds the release ZIP without .git, .env and test files.
Para atualizações, aumente a version no manifest.json. Adicionar uma permissão nova pode desativar a extensão para os usuários atuais até que eles a aprovem, então pense duas vezes antes de adicionar uma.
Como eu faço isso com o AgentVera
Dá para criar uma extensão com um terminal e um navegador. Eu uso o AgentVera quando estou criando a extensão e o servidor proxy ao mesmo tempo:
- Dois agentes, dois trabalhos. No workspace eu abro um agente Claude Code para a extensão e um agente Codex para o servidor proxy, cada um na própria pasta ou git worktree.
- Testando o servidor. O cliente de API consegue achar os endpoints do servidor a partir do código; eu testo o
/summarizeali antes de ligá-lo à extensão. - Enviando erros ao agente. Eu mando a saída de erro de um terminal para o agente escolhido com o Send to agent em vez de copiar e colar.
- Revisão antes do merge. O code review confere cada turno concluído, e o painel Git mostra o diff. Uma permissão extra ou uma chave embutida geralmente é pega aqui.
- Acompanhamento de tokens. Cada painel mostra o tamanho do contexto em tempo real; uma extensão pequena não precisa de uma sessão inchada.
Carregar a extensão no Chrome e testá-la continua sendo com você; o AgentVera não faz isso por você.
Conclusão
Para criar uma extensão do Chrome com IA, aprenda as peças (manifest, content script, service worker, popup), dê ao agente regras por escrito, comece com permissões mínimas, carregue sem empacotar e depure no console certo, e mantenha as chaves de API atrás de um servidor proxy. Antes de enviar para a loja, garanta que você consegue justificar cada permissão. Para saber mais sobre como conferir o que os agentes produzem, leia code review com IA e, para escolher ferramentas, as melhores ferramentas de CLI para programar com IA.