オプション

chrome-extension

samber/cc-skills samber/cc-skills

Manifest V3 を使用した Chrome 拡張機能の開発に関する総合ガイド。 ユーザーが「Chrome拡張機能」、「ブラウザ拡張機能」、「manifest.json」、「コンテンツスクリプト」、「サービスワーカー(拡張機能の文脈において)」、「ポップアップ」、「サイドパネル」、「chrome.runtime」、「chrome.tabs」、「chrome.storage」、「chrome.scripting」、「バックグラウンドスクリプト」、「MV3」、「Manifest V3」、またはその他のChrome拡張機能APIについて言及した際には、このスキルをご利用ください。 また、ユーザーがWebページにスクリプトを挿入したい場合、ページとバックグラウンド間で通信したい場合、コンテンツからCSPをバイパスしたい場合にもこのスキルを発動させてください。

...すべて拡張します
10
更新された時間 2026年8月25日

概要chrome-extension

Manifest V3 を使用した Chrome 拡張機能の構築、デバッグ、公開に関する包括的なガイドです。本ガイドはルーティングドキュメント形式で構成されています。まずメインファイルを読んでアーキテクチャと意思決定ポイントを理解し、その後、実装の詳細については関連する独立したリファレンスファイルのみを読み込んでください。 リファレンスファイルでは、manifest.jsonの設定とバージョン管理、サービスワーカーのライフサイクルと状態の永続化、コンテンツスクリプトと「isolated」環境と「main」環境へのインジェクションの違い、メッセージングとRPCレイヤー、UI要素(ポップアップ、オプションページ、サイドパネル、コンテキストメニュー、コマンド、通知、オムニボックス、デベロッパーツールパネル)、 chrome.storageの使用法とクォータ、ネットワークおよびCSPの処理、権限、Webからアクセス可能なリソース、TypeScriptのビルド設定、Chrome Web Storeへの公開、実行コンテキストのフロー図、およびよくあるデバッグ上のミス。 本ガイドはAIコーディングエージェントを対象としており、gitとnodeが必要です。使用されるツールには、ファイル編集やgit、gh、npmコマンドなどが含まれます。

アーキテクチャの概要では、拡張機能には最大5つの実行コンテキストがあり、メッセージパッシングによって通信を行うことが説明されています。具体的には、サービスワーカー(バックグラウンド、DOMなし、一時的、すべてのchrome.* API)へのアクセス権を持つ)、ポップアップ、オプションページ、サイドパネル(いずれも完全なDOMとAPIを備える)、そしてWebページ自体では、隔離されたワールド内のコンテンツスクリプトと、ページコンテキスト内のメインワールドスクリプトです。 図によると、コンテンツスクリプトはDOMを共有するが、独自のJSスコープを持ち、chrome.runtimeおよびchrome.storageにアクセスできる一方で、ネットワークに関してはCSPの対象となる。一方、メインワールドスクリプトはページ全体にアクセスできるが、chrome.* APIにはアクセスできず、CSPの対象となる。この2つは、共有DOMを介してwindow.postMessage経由で通信する。

通信パターンは以下の表にまとめられています。拡張機能の任意のコンテキストからサービスワーカーへの単発のリクエスト/レスポンスには `chrome.runtime.sendMessage`(最も一般的なケース)、 chrome.tabs.sendMessage は、サービスワーカーから tabId 指定の特定のタブへデータをプッシュするために使用されます。chrome.runtime.connect ポートは、双方向ストリーミングおよび進行状況の通知(サービスワーカーからポップアップへの通信を含む)に使用されます。また、window.postMessage は、同一ページ上の異なるコンテキスト間を橋渡しするために使用されます。 サービスワーカーは一時的なものであり、拡張機能のページに直接データをプッシュすることはできないため、このガイドではポートまたはすべてのコンテキストで同時に発火する `chrome.storage.onChanged` の利用を推奨しています。また、より詳細なフロー図やコンテキストごとの機能・制限の解説については、execution-contexts リファレンスを参照するよう案内しています。 このスキルは、フレームワーク固有の質問には使用すべきではないと明示しています。

FAQ

このガイドは、どのバージョンの Chrome 拡張機能マニフェストを対象としていますか?

マニフェスト V3 (MV3) です。manifest.json の設定と変更、アイコンの設定、バージョン管理に加え、より広範な MV3 のアーキテクチャ、メッセージング、公開プロセスについて網羅しています。

このスキルはどのように構成されていますか?

ルーティングドキュメントとして構成されています。まずメインの SKILL.md を読んでアーキテクチャと決定ポイントを確認し、その後、実装の詳細については、関連する独立したリファレンスファイル(例:service-worker.md、content-scripts.md、messaging-rpc.md など)のみを読み込みます。

このガイドによると、Chrome拡張機能にはどのような実行コンテキストがありますか?

メッセージパッシングを介して通信する最大5つのコンテキストがあります。具体的には、拡張機能プロセス内のサービスワーカー(バックグラウンド)、ポップアップ、オプションページ、サイドパネルに加え、コンテンツスクリプト(隔離された環境)およびWebページ上のメインワールドスクリプトです。

一般的なリクエスト/レスポンスには、どのメッセージング方式を使用すべきですか?

どの拡張機能コンテキストからでもサービスワーカーへの `chrome.runtime.sendMessage` を使用します。ガイドによると、これによりケースの約90%を処理できるとされています。特定のタブへの送信には `chrome.tabs.sendMessage` を、双方向ストリーミングには `chrome.runtime.connect` のポートを使用します。

このスキルを使用するための前提条件は何ですか?

このスキルは、Claude Code や類似の AI コーディングエージェント向けに設計されており、git および node が必要です(メタデータには git、node、npm が記載されています)。特定のフレームワークに関する質問には対応していません。

すべてのファイル

14ファイルreferences/content-scripts.md12.5KB表示references/execution-contexts.md18.3KB表示references/messaging-rpc.md19.4KB表示references/permissions.md8.0KB表示references/service-worker.md 10.9KB 表示 references/typescript-build.md 7.9KB 表示 references/debugging-mistakes.md 9.2KB 表示 references/manifest-v3.md 7.2KB 表示 references/network-csp.md 9.9KB 表示 references/publishing.md6.4KB 参照を表示 /storage.md9.0KB 参照を表示 /ui-surfaces.md9.7KB 参照を表示 /web-accessible-resources.md3.1 KB 参照を表示SKILL.md16.0 KB 参照を表示
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).

chrome-extensionをインストール

スキルファイルをダウンロードし、.claude/skills/ ディレクトリに解凍してください。

ZIPをダウンロード

リポジトリをクローンし、スキルファイルをプロジェクトにコピーしてください。

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

コピー コピー
クイックセットアップ: スキルフォルダを .claude/skills/ にコピーしてください。Claude が自動的にスキルを検出して使用します。
リポジトリ samber/cc-skills

関連スキル

playwright-cli
更新された時間 2026年6月29日
frontend-testing-best-practices
更新された時間 2026年7月7日
Playwright Browser Automation
更新された時間 2026年6月29日
playwright-generate-test
更新された時間 2026年6月29日
OR