opção

chrome-extension

samber/cc-skills samber/cc-skills

Guia completo para a criação de extensões do Chrome com o Manifest V3. Utilize essa habilidade sempre que o usuário mencionar extensão do Chrome, extensão de navegador, manifest.json, script de conteúdo, service worker (no contexto de extensão), pop-up, painel lateral, chrome.runtime, chrome.tabs, chrome.storage, chrome.scripting, script em segundo plano, MV3, Manifest V3 ou qualquer API de extensão do Chrome. Também acione esta habilidade quando o usuário quiser injetar scripts em páginas da web, estabelecer comunicação entre a página e o fundo ou contornar a CSP a partir de um conteúdo

...Expandir tudo
10
Tempo atualizado 25 de Agosto de 2026

Sobre chrome-extension

Um guia abrangente para criar, depurar e publicar extensões do Chrome com o Manifest V3, estruturado como um documento de roteamento. O arquivo principal é lido primeiro para compreender a arquitetura e os pontos de decisão; em seguida, apenas o arquivo de referência relevante e independente é carregado para obter detalhes de implementação. Os arquivos de referência abrangem a configuração e o controle de versões do manifest.json, o ciclo de vida do service worker e a persistência de estado, scripts de conteúdo e injeção isolada versus injeção no ambiente principal, camadas de mensagens e RPC, interfaces de usuário (janela pop-up, página de opções, painel lateral, menus de contexto, comandos, notificações, omnibox, painel de ferramentas de desenvolvimento), uso e cotas do chrome.storage, gerenciamento de rede e CSP, permissões, recursos acessíveis pela web, configuração de compilação do TypeScript, publicação na Chrome Web Store, diagramas de fluxo do contexto de execução e erros comuns de depuração. O curso é voltado para programadores de IA e requer git e node, com ferramentas declaradas que abrangem edições de arquivos e comandos do git, gh e npm.

A visão geral da arquitetura explica que uma extensão possui até cinco contextos de execução que se comunicam por meio da passagem de mensagens: o service worker (em segundo plano, sem DOM, efêmero, com acesso a todas as APIs chrome.* ), o pop-up, a página de opções e o painel lateral (todos com DOM completo e APIs) e, na própria página da web, o script de conteúdo em um mundo isolado e um script do mundo principal no contexto da página. Os diagramas mostram que o script de conteúdo compartilha o DOM, mas possui seu próprio escopo de JS e acesso a chrome.runtime e chrome.storage, estando sujeito à CSP apenas para a rede, enquanto o script do mundo principal tem acesso total à página, mas não possui APIs chrome.* e está totalmente sujeito à CSP. Os dois se comunicam via window.postMessage por meio do DOM compartilhado.

Os padrões de comunicação estão resumidos nas tabelas: chrome.runtime.sendMessage para solicitação/resposta única de qualquer contexto de extensão para o service worker (o caso mais comum), chrome.tabs.sendMessage para enviar dados do service worker para uma aba específica por meio do tabId, chrome.runtime.connect ports para streaming bidirecional e acompanhamento de progresso (incluindo do service worker para pop-up) e window.postMessage para conectar os mundos na mesma página. Como o service worker é efêmero e não pode enviar dados diretamente para páginas de extensões, o guia orienta os leitores a utilizarem as portas ou o chrome.storage.onChanged, que é disparado em todos os contextos simultaneamente, e indica a referência de contextos de execução para diagramas de fluxo mais detalhados e análises de recursos e limites por contexto. A habilidade afirma explicitamente que não deve ser usada para perguntas específicas sobre frameworks.

Perguntas frequentes

Qual versão do manifesto de extensões do Chrome esta habilidade abrange?

Manifesto V3 (MV3). Abrange a configuração e modificação do `manifest.json`, a configuração de ícones e o controle de versões, juntamente com a arquitetura mais ampla do MV3, o envio de mensagens e o processo de publicação.

Como a habilidade está organizada?

Como um documento de roteamento. Você lê primeiro o arquivo principal SKILL.md para conhecer a arquitetura e os pontos de decisão e, em seguida, carrega apenas o arquivo de referência relevante e independente (por exemplo, service-worker.md, content-scripts.md ou messaging-rpc.md) para obter detalhes de implementação.

Quais são os contextos de execução de uma extensão do Chrome de acordo com este guia?

Até cinco contextos que se comunicam por meio de passagem de mensagens: o service worker (em segundo plano), o pop-up, a página de opções e o painel lateral dentro do processo da extensão, além do script de conteúdo (mundo isolado) e do script do mundo principal na página da web.

Qual método de mensagens devo usar para uma solicitação/resposta típica?

chrome.runtime.sendMessage de qualquer contexto da extensão para o service worker, que, conforme observa o guia, lida com cerca de noventa por cento dos casos. Para enviar para uma aba específica, use chrome.tabs.sendMessage; e para streaming bidirecional, use as portas chrome.runtime.connect.

Quais são os pré-requisitos para usar essa habilidade?

Ela foi projetada para o Claude Code ou agentes de codificação de IA semelhantes e requer git e node (os metadados listam git, node e npm). Não se destina a perguntas específicas sobre frameworks.

Todos os arquivos

14arquivosreferences/content-scripts.md12,5KBNotarreferences/execution-contexts.md18,3KBNotarreferences/messaging-rpc.md19,4KBNotarreferences/permissions.md8,0KBNotarreferences/service-worker.md 10,9KB Visualizar references/typescript-build.md 7,9KB Visualizar references/debugging-mistakes.md 9,2KB Visualizar references/manifest-v3.md 7,2KB Visualizar references/network-csp.md 9,9KB Visualizar references/publishing.md6,4KBVer referências/storage.md9,0KBVer referências/ui-surfaces.md9,7KBVer referências/web-accessible-resources.md3,1KBVer SKILL.md16,0 KBVer
Ver no GitHub

This skill covers everything needed to build, debug, and publish Chrome extensions with MV3. It is organized as a routing document: read this file first to understand the architecture and decision points, then load the relevant reference file for implementation details.

Reference files

Read only the reference files relevant to the current task. Each file is self-contained.

FileWhen to read
references/manifest-v3.mdSetting up or modifying manifest.json, configuring icons, versioning
references/service-worker.mdBackground logic, lifecycle, state persistence, alarms, events
references/content-scripts.mdInjecting code into pages, isolated/main world, dynamic injection, SPA handling, orphaning
references/messaging-rpc.mdCommunication between any contexts, typed protocols, RPC layer, async handler patterns
references/ui-surfaces.mdPopup, options page, side panel, context menus, commands, notifications, omnibox, devtools panel
references/storage.mdchrome.storage (local/sync/session), quotas, reactive patterns, framework hooks
references/network-csp.mdHTTP requests from content scripts, CSP bypass relay, declarativeNetRequest, offscreen docs, CORS
references/permissions.mdRequired/optional permissions, host permissions, activeTab, runtime request flow
references/web-accessible-resources.mdExposing extension files to web pages, security implications
references/typescript-build.mdTypeScript setup, project structure, build tools comparison, bundling
references/publishing.mdChrome Web Store submission, review process, rejection reasons, updates, privacy policy
references/execution-contexts.mdCommunication flow diagrams, per-context capabilities/limits, choosing the right messaging method
references/debugging-mistakes.mdDevTools for extensions, testing SW termination, common gotchas, error patterns

Architecture overview

A Chrome extension has up to 5 execution contexts that communicate via message passing:

┌──────────────────────────────────────────────────────────┐│ Extension Process                                        ││  ┌─────────────────┐  ┌───────┐  ┌─────────┐  ┌──────┐ ││  │ Service Worker   │  │ Popup │  │ Options │  │ Side │ ││  │ (background)     │  │       │  │  Page   │  │Panel │ ││  │ - No DOM         │  │ Full  │  │  Full   │  │ Full │ ││  │ - Ephemeral      │  │ DOM   │  │  DOM    │  │ DOM  │ ││  │ - All chrome.*   │  │ All   │  │  All    │  │ All  │ ││  │   APIs           │  │ APIs  │  │  APIs   │  │ APIs │ ││  └────────┬─────────┘  └───┬───┘  └────┬────┘  └──┬───┘ ││           │ chrome.runtime.sendMessage / connect   │     │└───────────┼────────────────┼───────────┼──────────┼──────┘            │                │           │          │    chrome.tabs.sendMessage  │           │          │            │                │           │          │┌───────────┼────────────────┼───────────┼──────────┼──────┐│ Web Page  ▼                                              ││  ┌──────────────────┐    ┌──────────────────┐            ││  │ Content Script    │    │ Main World Script │            ││  │ (isolated world)  │◄──►│ (page context)    │            ││  │ - Shared DOM      │    │ - Shared DOM      │            ││  │ - Own JS scope    │    │ - Page JS scope   │            ││  │ - chrome.runtime  │    │ - No chrome.* API │            ││  │ - chrome.storage  │    │ - Full page access│            ││  │ - Subject to CSP  │    │ - Subject to CSP  │            ││  │   (network only)  │    │   (fully)         │            ││  └──────────────────┘    └──────────────────┘            ││           ▲ window.postMessage                           ││           │ (through shared DOM)                         │└──────────────────────────────────────────────────────────┘

Communication flows (labeled channels)

┌───────────────────────────────────────────────────────────────────────────┐│ Extension Process                                                         ││                                                                           ││  ┌─────────────────┐  chrome.runtime   ┌───────┐  ┌─────────┐  ┌──────┐ ││  │ Service Worker   │◄─.sendMessage()──│ Popup │  │ Options │  │ Side │ ││  │ (background)     │◄─.connect()──────│       │  │  Page   │  │Panel │ ││  │                  │                  └───────┘  └─────────┘  └──────┘ ││  │ - No DOM         │  ┌────────────────────────────────────────────┐   ││  │ - Ephemeral 30s  │  │ SW cannot push to these pages.             │   ││  │ - All chrome.*   │  │ Use: ports (.connect) or storage.onChanged │   ││  └────────┬─────────┘  └────────────────────────────────────────────┘   ││           │                                                              ││  chrome.storage.onChanged ◄── fires across ALL contexts simultaneously  ││                                                                           │└───────────┼──────────────────────────────────────────────────────────────┘            │ chrome.tabs.sendMessage(tabId, ...) [SW must know tabId]            │┌───────────┼──────────────────────────────────────────────────────────────┐│ Web Page  ▼                                                              ││  ┌──────────────────┐  window.postMessage  ┌──────────────────┐         ││  │ Content Script    │◄───────────────────►│ Main World Script │         ││  │ (isolated world)  │  Custom DOM events  │ (page context)    │         ││  │                   │                     │                   │         ││  │ chrome.runtime ───┼── to/from SW        │ No chrome.* APIs  │         ││  │ chrome.storage    │                     │ Full page JS      │         ││  │ Shared DOM        │                     │ Shared DOM        │         ││  │ Page CSP (network)│                     │ Page CSP (full)   │         ││  └──────────────────┘                     └──────────────────┘         │└──────────────────────────────────────────────────────────────────────────┘

For detailed flow diagrams (three-layer bridge, cross-extension, storage broadcast) and a per-context breakdown of permissions, limits, and workarounds: → Read references/execution-contexts.md

Communication methods at a glance

MethodDirectionBest for
chrome.runtime.sendMessageAny ext context → SWOne-shot request/response (90% of cases)
chrome.tabs.sendMessageSW → content script (by tabId)Pushing data to a specific tab
chrome.runtime.connect (Port)BidirectionalStreaming, progress, SW ↔ popup
window.postMessageBetween worlds on same pagePage JS ↔ content script bridge
chrome.storage.onChangedBroadcast to all contextsSettings sync, no messaging needed

→ Full matrix with limits and edge cases: references/execution-contexts.md → Implementation patterns, typed protocols, RPC layer: references/messaging-rpc.md

Key architectural rules

  1. Service worker is ephemeral. It terminates after 30s of inactivity. All state must be persisted to chrome.storage. All event listeners must be registered synchronously at the top level. Never use setTimeout/setInterval for anything beyond a few seconds. → Read references/service-worker.md

  2. Content scripts run in the page's origin. Network requests from content scripts are subject to the page's CSP and CORS. To bypass, relay through the service worker. → Read references/network-csp.md

  3. Messaging is the backbone. Every cross-context interaction uses chrome.runtime messaging. The #1 bug: forgetting to return true from async message listeners. → Read references/messaging-rpc.md

  4. Permissions determine CWS review speed. Broad host_permissions trigger manual review (weeks). activeTab + optional permissions = fast automated review. → Read references/permissions.md

  5. Popup is destroyed on blur. Side panel persists. Choose based on interaction duration. → Read references/ui-surfaces.md

Decision tree: which context handles what?

"I need to run code when the user visits a page"

→ Content script. Static (manifest) for known URL patterns, dynamic (chrome.scripting) for user-triggered injection. Default to isolated world unless you need page JS access. → Read references/content-scripts.md

"I need to make an HTTP request to my API"

  • From popup/options/side panel: direct fetch() works (extension origin, no CSP issues)
  • From content script on a page with restrictive CSP: relay through service worker
  • From service worker: direct fetch() works (requires host_permissions for the target domain) → Read references/network-csp.md

"I need to store user settings"

  • Settings that sync across devices: chrome.storage.sync (100KB limit)
  • Large data or caches: chrome.storage.local (10MB, or unlimited with permission)
  • Ephemeral state surviving SW restarts: chrome.storage.session → Read references/storage.md

"I need to modify HTTP headers or block requests"

→ declarativeNetRequest (NOT webRequest, which lost blocking in MV3) → Read references/network-csp.md

"I need the page's JavaScript to talk to my extension"

→ Three-layer bridge: page (window.postMessage) → content script → service worker → Read references/messaging-rpc.md

"I need to understand what each context can and cannot do"

→ Read references/execution-contexts.md — per-context cards listing chrome.* access, DOM, network, storage, lifetime, hard limits, and practical workarounds.

"I need periodic background tasks"

→ chrome.alarms (minimum 30s interval). NOT setTimeout. → Read references/service-worker.md

"I need DOM APIs in the background" (DOMParser, Canvas, Audio)

→ Offscreen document. One per extension, only chrome.runtime available. → Read references/network-csp.md

"I need to authenticate with OAuth"

→ chrome.identity.launchWebAuthFlow() or chrome.identity.getAuthToken() (Google only) → Read references/service-worker.md (identity section)

Workflow: new extension from scratch

  1. Define the manifest with minimum permissions. Start with activeTab + scripting. → Read references/manifest-v3.md

  2. Set up TypeScript and build tooling (or use CRXJS for Vite-based dev). → Read references/typescript-build.md

  3. Implement the service worker with all event listeners at the top level. → Read references/service-worker.md

  4. Add content scripts if you need page interaction. → Read references/content-scripts.md

  5. Build UI surfaces (popup, options, side panel) as needed. → Read references/ui-surfaces.md

  6. Wire up messaging between all contexts. → Read references/messaging-rpc.md

  7. Test with DevTools, specifically test service worker termination. → Read references/debugging-mistakes.md

  8. Publish to Chrome Web Store. → Read references/publishing.md

Workflow: adding a feature to an existing extension

  1. Identify which context the feature belongs to (see decision tree above).
  2. Read the relevant reference file(s) for that context.
  3. Check if new permissions are needed. Prefer optional_permissions for new capabilities. → Read references/permissions.md
  4. Update the manifest if adding new content scripts, UI surfaces, or permissions.
  5. Handle extension updates gracefully (content script orphaning). → Read references/content-scripts.md (orphaning section)

Minimal manifest.json template

{  "manifest_version": 3,  "name": "My Extension",  "version": "1.0.0",  "description": "What it does in one sentence",  "permissions": ["storage", "activeTab", "scripting"],  "action": {    "default_popup": "popup.html",    "default_icon": {      "16": "icons/icon16.png",      "48": "icons/icon48.png",      "128": "icons/icon128.png"    }  },  "background": {    "service_worker": "background.js",    "type": "module"  },  "icons": {    "16": "icons/icon16.png",    "48": "icons/icon48.png",    "128": "icons/icon128.png"  }}

→ For the full manifest reference with all fields: references/manifest-v3.md

Code patterns quick reference

Async message handler (the safe pattern)

// Wrap async handlers to avoid the return-true trapfunction asyncHandler(  fn: (msg: any, sender: chrome.runtime.MessageSender) => Promise<any>,) {  return (    message: any,    sender: chrome.runtime.MessageSender,    sendResponse: (r: any) => void,  ) => {    fn(message, sender)      .then(sendResponse)      .catch((e) => sendResponse({ __error: true, message: e.message }));    return true; // literal true, not Promise<true>  };}chrome.runtime.onMessage.addListener(  asyncHandler(async (msg, sender) => {    if (msg.type === "FETCH") {      const res = await fetch(msg.url);      return { ok: res.ok, data: await res.text() };    }  }),);

CSP bypass relay (content script → service worker → API)

// content-script.tsasync function apiCall(endpoint: string, options?: RequestInit) {  return chrome.runtime.sendMessage({ type: "API_RELAY", endpoint, options });}// background.tsconst ALLOWED_ENDPOINTS = ["https://api.example.com"];chrome.runtime.onMessage.addListener(  asyncHandler(async (msg) => {    if (msg.type !== "API_RELAY") return;    if (!ALLOWED_ENDPOINTS.some((e) => msg.endpoint.startsWith(e))) {      throw new Error("Blocked endpoint");    }    const res = await fetch(msg.endpoint, msg.options);    return { ok: res.ok, status: res.status, data: await res.text() };  }),);

Persist state across SW restarts

// Use chrome.storage.session for ephemeral statechrome.storage.session.setAccessLevel({  accessLevel: "TRUSTED_AND_UNTRUSTED_CONTEXTS",});async function getState<T>(key: string, fallback: T): Promise<T> {  const result = await chrome.storage.session.get(key);  return result[key] ?? fallback;}async function setState<T>(key: string, value: T): Promise<void> {  await chrome.storage.session.set({ [key]: value });}

Orphaned content script detection

function isExtensionContextValid(): boolean {  try {    return !!chrome.runtime?.id;  } catch {    return false;  }}// Before any chrome.runtime callif (!isExtensionContextValid()) {  showRefreshBanner();  return;}

What NOT to do

  • Do NOT use eval(), new Function(), or load remote scripts. MV3 forbids it.
  • Do NOT use setTimeout/setInterval for anything > 5s in service workers.
  • Do NOT register event listeners inside callbacks or async functions.
  • Do NOT use <all_urls> host permission unless absolutely necessary.
  • Do NOT rely on DevTools keeping the service worker alive during testing.
  • Do NOT forget return true in async message listeners.
  • Do NOT use localStorage or sessionStorage in service workers (they don't exist there).
  • Do NOT assume content scripts survive extension updates.
  • Do NOT use webRequest blocking (removed in MV3). Use declarativeNetRequest.
  • Do NOT use chrome.extension.getBackgroundPage() (removed in MV3).

Instalar chrome-extension

Baixe e descompacte os arquivos de habilidades no diretório .claude/skills/.

Baixar ZIP

Clone o repositório e copie os arquivos da habilidade para o seu projeto.

git clone https://github.com/samber/cc-skills/blob/main/skills/chrome-extension/SKILL.md # Copy SKILL.md to your .claude/skills/ directory

Copiar Copiar
Configuração rápida: Copie a pasta da habilidade para .claude/skills/. O Claude detectará e utilizará automaticamente a habilidade
Repositório samber/cc-skills

Habilidades relacionadas

playwright-cli
Tempo atualizado 29 de Junho de 2026
frontend-testing-best-practices
Tempo atualizado 7 de Julho de 2026
Playwright Browser Automation
Tempo atualizado 29 de Junho de 2026
playwright-generate-test
Tempo atualizado 29 de Junho de 2026
OR