option

chrome-extension

samber/cc-skills samber/cc-skills

Guide complet pour créer des extensions Chrome avec Manifest V3. Utilisez cette compétence chaque fois que l’utilisateur mentionne « extension Chrome », « extension de navigateur », « manifest.json », « script de contenu », « service worker » (dans le contexte d’une extension), « fenêtre contextuelle », « panneau latéral », « chrome.runtime », « chrome.tabs », « chrome.storage », « chrome.scripting », « script d’arrière-plan », « MV3 », « Manifest V3 » ou toute API d’extension Chrome. Déclenchez-la également lorsque l'utilisateur souhaite injecter des scripts dans des pages Web, établir une communication entre la page et l'arrière-plan, ou contourner la politique de sécurité du contenu (CSP) à partir d'un script de contenu.

...Développer tout
10
Heure mise à jour 25 août 2026

À propos chrome-extension

Un guide complet pour créer, déboguer et publier des extensions Chrome avec Manifest V3, structuré comme un document de routage. Le fichier principal est lu en premier afin de comprendre l'architecture et les points de décision, après quoi seul le fichier de référence pertinent et autonome est chargé pour les détails de mise en œuvre. Les fichiers de référence couvrent la configuration et la gestion des versions de manifest.json, le cycle de vie des service workers et la persistance de l’état, les scripts de contenu et l’injection dans l’environnement isolé par opposition à l’environnement principal, les couches de messagerie et de RPC, les interfaces utilisateur (fenêtres contextuelles, page d’options, panneau latéral, menus contextuels, commandes, notifications, omnibox, panneau des outils de développement), l'utilisation et les quotas de `chrome.storage`, la gestion du réseau et de la CSP, les autorisations, les ressources accessibles via le Web, la configuration de la compilation TypeScript, la publication sur le Chrome Web Store, les diagrammes de flux du contexte d'exécution, ainsi que les erreurs courantes de débogage. Il s’adresse aux développeurs d’IA et nécessite git et node ; les outils mentionnés couvrent la modification de fichiers ainsi que les commandes git, gh et npm.

La présentation de l’architecture explique qu’une extension dispose de jusqu’à cinq contextes d’exécution qui communiquent par échange de messages : le service worker (en arrière-plan, sans DOM, éphémère, avec accès à toutes les API chrome.* ), la fenêtre contextuelle, la page d’options et le panneau latéral (tous dotés d’un DOM complet et d’API), ainsi que, sur la page Web elle-même, le script de contenu dans un environnement isolé et un script principal dans le contexte de la page. Les schémas montrent que le script de contenu partage le DOM mais dispose de sa propre portée JS et d’un accès à chrome.runtime et chrome.storage tout en étant soumis à la CSP uniquement au niveau du réseau, tandis que le script principal dispose d’un accès complet à la page mais n’a pas accès aux API chrome.* et est entièrement soumis à la CSP. Les deux communiquent via window.postMessage à travers le DOM partagé.

Les modèles de communication sont résumés dans des tableaux : chrome.runtime.sendMessage pour une requête/réponse ponctuelle depuis n’importe quel contexte d’extension vers le service worker (le cas le plus courant), chrome.tabs.sendMessage pour envoyer des données depuis le service worker vers un onglet spécifique via son tabId, les ports chrome.runtime.connect pour le streaming bidirectionnel et le suivi de progression (y compris du service worker vers une fenêtre contextuelle), et window.postMessage pour établir une passerelle entre les mondes sur une même page. Le service worker étant éphémère et ne pouvant pas envoyer directement de données vers les pages d’extension, le guide oriente les lecteurs vers les ports ou vers chrome.storage.onChanged, qui se déclenche simultanément dans tous les contextes, et renvoie à la référence sur les contextes d’exécution pour des diagrammes de flux plus détaillés ainsi qu’une analyse des capacités et des limites par contexte. La compétence précise explicitement qu’elle ne doit pas être utilisée pour des questions spécifiques à un framework.

FAQ

Quelle version du manifeste d’extension Chrome est couverte par ce guide ?

Le manifeste V3 (MV3). Elle couvre la configuration et la modification du fichier manifest.json, la configuration des icônes et la gestion des versions, ainsi que l’architecture MV3 au sens large, la messagerie et le processus de publication.

Comment la compétence est-elle organisée ?

Sous la forme d’un document de routage. Vous lisez d’abord le fichier principal SKILL.md pour comprendre l’architecture et les points de décision, puis vous chargez uniquement le fichier de référence pertinent et autonome (par exemple service-worker.md, content-scripts.md ou messaging-rpc.md) pour les détails de mise en œuvre.

Quels sont les contextes d’exécution d’une extension Chrome selon ce guide ?

Jusqu’à cinq contextes qui communiquent par échange de messages : le service worker (en arrière-plan), la fenêtre contextuelle, la page d’options et le panneau latéral au sein du processus de l’extension, ainsi que le script de contenu (environnement isolé) et le script principal sur la page Web.

Quelle méthode de messagerie dois-je utiliser pour une requête/réponse classique ?

chrome.runtime.sendMessage depuis n’importe quel contexte d’extension vers le service worker, ce qui, selon le guide, couvre environ 90 % des cas. Pour envoyer des données vers un onglet spécifique, utilisez chrome.tabs.sendMessage, et pour le streaming bidirectionnel, utilisez les ports chrome.runtime.connect.

Quelles sont les conditions préalables à l’utilisation de cette compétence ?

Elle est conçue pour Claude Code ou des agents de codage IA similaires et nécessite Git et Node (les métadonnées mentionnent Git, Node et npm). Elle n’est pas destinée aux questions spécifiques à un framework.

Tous les fichiers

14fichiersreferences/content-scripts.md12,5KoAfficherreferences/execution-contexts.md18,3KoAfficherreferences/messaging-rpc.md19,4KoAfficherreferences/permissions.md8,0KoAfficherreferences/service-worker.md 10,9Ko Afficher references/typescript-build.md 7,9Ko Afficher references/debugging-mistakes.md 9,2Ko Afficher references/manifest-v3.md 7,2Ko Afficher references/network-csp.md 9,9Ko Afficher references/publishing.md6,4 KoAfficherles références/storage.md9,0KoAfficher les références/ui-surfaces.md9,7KoAfficherles références/web-accessible-resources.md3,1KoAfficher SKILL.md16,0 KoAfficher
Voir sur 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).

Installer chrome-extension

Téléchargez et décompressez les fichiers de compétences dans votre répertoire .claude/skills/.

Télécharger le ZIP

Clonez le dépôt et copiez les fichiers de compétence dans votre projet.

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

Copier Copier
Configuration rapide: Copiez le dossier de la compétence dans .claude/skills/ Claude détectera automatiquement la compétence et l'utilisera

Compétences similaires

playwright-cli
Heure mise à jour 29 juin 2026
frontend-testing-best-practices
Heure mise à jour 7 juillet 2026
Playwright Browser Automation
Heure mise à jour 29 juin 2026
playwright-generate-test
Heure mise à jour 29 juin 2026
OR