build-chrome-extension について
Chrome Manifest V3拡張機能の構築、デバッグ、検証、パッケージ化を支援するスキルです。サービスワーカーのライフサイクル、コンテンツスクリプトの分離、最小権限、Web Store審査準備を重視します。
主な機能
- 01Manifest V3拡張機能のワークフロー
- 02サービスワーカーのライフサイクル指針
- 03コンテンツスクリプトの分離パターン
- 04最小権限の計画
- 05ビルド検証とパッケージ化
活用シーン
- 01新しいChrome拡張機能の作成
- 02拡張機能のMV2からMV3への移行
- 03サービスワーカーやメッセージの問題解決
- 04Web Store審査用ビルドの準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yigitkonur/ skills-by-yigitkonur --skill build-chrome-extensionインストール後、Claude Code で/build-chrome-extensionを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdagents/openai.yamlreferences/apis/core-apis.mdmessaging.mdstorage.mdreferences/frameworks/comparison.mdreferences/patterns/content-scripts.mddesktop-ipc.mdservice-worker.mdui-surfaces.mdreferences/publishing/web-store.mdreferences/testing/debugging.mdtesting-guide.mdscripts/check-mv3-manifest.mdcheck-mv3-manifest.shpreflight-extension.mdpreflight-extension.sh詳細
Chrome 拡張機能を構築する
Chrome Manifest V3 拡張機能を構築、デバッグ、パッケージ化し、公開します。再起動に耐えるサービスワーカー、分離されたコンテンツスクリプト、最小権限、Web Store の審査への準備を重視します。
使用する場面
次のいずれかに該当するリクエストで使用します。
- 新しい Chrome MV3 拡張機能を作成する場合や、フレームワーク(WXT、Plasmo、CRXJS、Vite)からひな形を生成する場合
manifest.jsonの編集または生成で、manifest_version: 3、service_worker、content_scripts、host_permissions、action、side_panelフィールドを扱う場合chrome.runtime、chrome.storage、chrome.alarms、chrome.scripting、chrome.tabs、chrome.declarativeNetRequest、chrome.sidePanel、chrome.offscreenAPI を実装またはデバッグする場合- Chrome 拡張機能をデスクトップアプリやローカルデーモン(Raycast Companion、ローカル WebSocket サーバー、Native Messaging ホスト)に接続する場合
- MV3 のサービスワーカーのライフサイクルに関する問題(アイドル時の終了、トップレベルでのリスナー登録、非同期の
onMessageの戻り値、chrome.alarmsとsetIntervalの使い分け)を修正する場合 - ISOLATED と MAIN の各ワールド間でコンテンツスクリプトを橋渡しする場合や、クロスオリジンのホスト権限を利用するためにサービスワーカー経由でフェッチを行う場合
- MV2 拡張機能を MV3 に移行する場合(バックグラウンドページ → サービスワーカー、ブロッキングの
webRequest→declarativeNetRequest、browser_action → action) - ビルド済みの
dist/または.output/chrome-mv3/フォルダーを検証する場合、Web Store 用の zip をパッケージ化する場合、プライバシーや権限の正当性を説明する場合、審査用のメモを準備する場合 - 新しいプロジェクト向けに Chrome MV3 フレームワークを選択または比較する場合
次の場合はこのスキルを使用しないでください。
- 対象が Firefox、Safari、またはクロスブラウザーのポリフィル(
browser.*名前空間、web-extツール、Safari App Extensions)の場合 - 拡張機能のコンテキスト外で、一般的なブラウザー自動化を行うリクエストの場合 —
run-agent-browserに振り分けます - 通常の npm パッケージやライブラリを公開する場合 —
publish-npm-packageに振り分けます - 別のプラットフォームの拡張機能(Raycast のスクリプトコマンド、VS Code 拡張機能、Edge のエンタープライズポリシーパッケージ)を構築する場合 — 該当するプラットフォームのスキルに振り分けます
固定のデフォルト — コードを生成する前に適用
| 項目 | デフォルト |
|---|---|
| Manifest の対象 | manifest_version: 3 のみ。MV2 は生成しない |
| 新規プロジェクトのフレームワーク | リポジトリですでに別の MV3 ツールを選択している場合を除き、WXT |
| 永続状態 | chrome.storage.local。一時的で再起動に耐える状態には chrome.storage.session |
| バックグラウンドモデル | イベント駆動型のサービスワーカー。リスナーはトップレベルで同期的に登録 |
| 定期処理 | chrome.alarms。バックグラウンドのスケジューリングに setTimeout/setInterval は使用しない |
| ネットワークの変更 | chrome.declarativeNetRequest。ブロッキングの webRequest は使用しない |
| 権限 | 最小権限。chrome.permissions.request で付与する optional_permissions と optional_host_permissions を優先 |
| 読み込むフォルダー | ビルド済みの出力のみ:WXT .output/chrome-mv3-dev/ または .output/chrome-mv3/、Plasmo build/chrome-mv3-*、CRXJS/Vite dist/ |
| デスクトップ IPC の通信方式 | 権限を必要としないデーモンにはローカル WebSocket、インストーラーが必要なシステムツールには Native Messaging |
| パッケージ化前の事前確認 | zip 化する前に、本番ビルドを対象として scripts/check-mv3-manifest.sh と scripts/preflight-extension.sh を実行 |
MV3 の落とし穴 — 常に意識しておくこと
MV3 のビルドでは、次の問題が繰り返し発生します。コードを書く前に頭に入れておいてください。
- サービスワーカーはアイドル状態になると停止します(デフォルトで約30秒)。モジュールのグローバルスコープにある状態は、イベント間で失われます。各
awaitの前に永続化し、イベント開始時に再読み込みしてください。 chrome.runtime.onMessage、onInstalled、onStartup、アラーム、タブの各リスナーは、トップレベルで同期的に登録してください。登録が遅れると、起動イベントを取りこぼします。setTimeout/setIntervalではサービスワーカーを稼働状態に保てず、アイドルサイクルをまたいで確実に実行されることもありません。periodInMinutes >= 0.5を指定してchrome.alarms.createを使用してください。- Chrome 148 以降では、
chrome.runtime.onMessageリスナーはPromiseの返却またはasyncの使用をネイティブでサポートします。後方互換性(148 未満およびクロスブラウザー)を保つには、非同期ハンドラーは同期的にreturn trueを返し、処理完了時にsendResponseを呼び出す必要があります。そうしないと、メッセージチャネルがすぐに閉じ、送信側はundefinedを受け取るか、"The message port closed before a response was received" で拒否されます。 - サービスワーカー内のローカル WebSocket 接続は、約30秒間通信がないと切断されます。Chrome 116 以降のアイドルタイマーをリセットするには、アクティブなハートビート ping(間隔は30秒未満、たとえば24秒)を維持する必要があります。アイドル状態のソケットを開いたままにしても、ワーカーの稼働は維持されません。
- 127.0.0.1 でリッスンするローカル WebSocket は、悪意のあるウェブページからのクロスサイト WebSocket ハイジャック(CSWSH)の危険にさらされます。デーモンは
Originヘッダーがchrome-extension://<id>と一致することを必ず検証し、HTTP Upgrade 時に認証トークンを要求してください。 - Native Messaging ホストは、デバッグログや書式化されていない出力を標準出力(
stdout)に絶対に書き込んではいけません。フレーム化されていないstdout出力は32ビットの長さプレフィックスを破損させ、接続をクラッシュさせます。ログはstderrに送信してください。 - Native Messaging ホストから Chrome に送信するメッセージは、厳密に1 MBまでに制限されています。1 MBを超えると、プロセスはただちに終了します。
- コンテンツスクリプトは、デフォルトで分離されたワールドで実行されます。ページの JS、フレームワーク、
window.*グローバルにはアクセスできません。ページの JS にアクセスする場合に限りworld: "MAIN"を使用し、その後、postMessageと同一オリジンのトークンを使ってブリッジしてください。 - 拡張機能オリジンからの
fetchには、一致するhost_permissionsが必要です。コンテンツスクリプトからのfetchはページのオリジンと CORS ルールに従います。特権が必要なリクエストは、chrome.runtime.sendMessageを介してサービスワーカーにルーティングしてください。 - MV3 の CSP では、拡張機能ページ内のインライン
<script>、eval()、new Function()、リモートの実行可能コードが禁止されています。すべてをバンドルし、CDN からスクリプトを読み込まないでください。(例外はmanifest.sandbox内のサンドボックスページのみで、unsafe-evalが許可されています。) - 手書きの
manifest.jsonのパスは、ビルド済みの成果物(例:background.js、content.js、popup.html)を指す必要があります。src/*.tsや未ビルドのソースを指定してはいけません。 - インストール時に
<all_urls>や広範なホスト権限を要求すると、ウェブストアの審査が厳しくなります。activeTabと任意のホスト権限の付与を優先してください。
判断ルール
| 判断項目 | デフォルト | 次の場合は再検討 |
|---|---|---|
| バックグラウンドの状態 | chrome.storage.session/local | トランザクション、大規模なインデックス、バイナリデータ → IndexedDB |
| 定期処理 | chrome.alarms | リアルタイムストリーム → 再接続とキューを設計 |
| ネットワークの変更 | declarativeNetRequest | 読み取り専用の監視 → ノンブロッキングの webRequest |
| ページデータの取得 | ホスト権限を使ったサービスワーカーの fetch | ページのオリジンで十分 → コンテンツスクリプトの fetch |
| ページの JS へのアクセス | ペイロードを検証する world: "MAIN" ブリッジ | DOM のみへのアクセス → ISOLATED ワールドを使用 |
| UI 状態の永続化 | chrome.storage.session | ブラウザーの再起動後も保持する必要がある → local または sync |
| ホストへのアクセス | activeTab または任意のホスト権限 | インストール時のホストアクセスがないと拡張機能が機能しない |
| サイドパネルとポップアップ | 常時表示するコンパニオン UI にはサイドパネル | クイックアクションや短いフォーム → ポップアップ |
| オフスクリーンドキュメント | サービスワーカーから DOM/キャンバス/クリップボード/オーディオ/Worker を利用 | ポップアップ/オプションページ/コンテンツスクリプトで対応できる → 使用しない |
| デスクトップとの通信 | CSWSH 対策を施したローカル WebSocket(ws://127.0.0.1:<port>) | OS との深い統合/エンタープライズ配布/ローカルポートの露出をゼロにする必要がある → chrome.runtime.connectNative |
ルーティングの境界
| リクエストの内容 | 対応 |
|---|---|
| 「Chrome 拡張機能を作る」 | このスキルを使用し、MV3 を対象にする |
| 「Chrome と Firefox 向けに作る」 | ここでは Chrome MV3 に限定する。クロスブラウザー層は対象外 |
| 「ブラウザーでウェブサイトを自動化する」 | run-agent-browser に振り分ける |
| 「拡張機能の Playwright テストを書く」 | 拡張機能の起動/読み込みに関する注意事項はここを参照する。より広範な Playwright のテスト作成は、このパックの対象外 |
| 「npm に公開する」 | publish-npm-package に振り分ける |
| 「Chrome ウェブストアに申請する」 | このスキルを使用し、references/publishing/web-store.md を読む |
| 「エンタープライズポリシーでデプロイする」 | 専用のエンタープライズスキルがない限り対象外 |
ワークフロー
1. 拡張機能の範囲を決める
次のように尋ねます:「どの拡張機能の画面や機能があり、どの Chrome API が必要で、どの権限を実行時まで先送りできますか?」
- 必要な画面や機能を列挙します:ポップアップ、オプションページ、サイドパネル、コンテンツスクリプト、サービスワーカー、オフスクリーンドキュメント、devtools。
- 必要な Chrome API と、それに伴う権限を列挙します。
- インストール時に必要な権限と
optional_permissions/optional_host_permissionsを切り分けます。 - フレームワークを選択します。
references/frameworks/comparison.mdを参照してください。 - Chrome が読み込むビルド出力フォルダーを記録します。
2. 雛形を作成する、または既存の構成に合わせる
次のように尋ねます:「新規開発ですか、既存フレームワークのビルドを使いますか、それとも manifest を手書きしますか?」
- 新規開発のデフォルト:WXT。
- 既存の Vite アプリを拡張機能にする場合:CRXJS。
- カスタムビルドパイプラインや明示的な制御が必要な場合:vanilla + Vite。
- 既存のリポジトリの場合:そのフレームワークと出力の規約に従います。
Chrome が読み込むのはビルド済みの出力フォルダーです。src/ やバンドルされていない TypeScript は読み込めません。
3. 拡張機能のコンテキストを実装する
次のように尋ねます:「どのコンテキストが状態を管理し、どのコンテキストが DOM を管理し、どのメッセージが境界を越えますか?」
コードを書く前に、該当するリファレンスを読みます。
- サービスワーカーのライフサイクル、永続化、アラーム、オフスクリーン →
references/patterns/service-worker.md - コンテンツスクリプト、ワールド分離、冪等性、クロスオリジンのルーティング →
references/patterns/content-scripts.md - ポップアップ、オプションページ、サイドパネル、devtools、新しいタブの画面 →
references/patterns/ui-surfaces.md - 1 回限りのメッセージ、ポート、外部/ネイティブメッセージング、ページブリッジ →
references/apis/messaging.md - デスクトップとの通信、Raycast Companion、Native Messaging →
references/patterns/desktop-ipc.md chrome.storageの領域、クォータ、型付きラッパー、移行 →references/apis/storage.md- タブ、スクリプティング、アラーム、DNR、サイドパネル、オフスクリーン、ランタイム →
references/apis/core-apis.md - Manifest、権限、MV2 の移行に関する判断は、この
SKILL.mdの固定デフォルトとガードレールで扱います。
境界を越えるすべてのペイロードを検証します。対象は、メッセージ、ストレージの読み取り値、外部 API の応答、MAIN ワールドブリッジのデータです。
4. ビルド成果物を検証する
次の点を確認します。「Chrome でこのフォルダーをそのまま読み込めますか? また、manifest 内のパスはすべて存在しますか?」
skill ディレクトリから、ビルドフォルダーを対象に実行します。
scripts/check-mv3-manifest.sh dist
scripts/preflight-extension.sh dist
フレームワークに応じてパスを調整します。
| フレームワーク | 開発用出力 | 本番用出力 |
|---|---|---|
| WXT | .output/chrome-mv3-dev/ | .output/chrome-mv3/ |
| Plasmo | build/chrome-mv3-dev/ | build/chrome-mv3-prod/ |
| CRXJS | dist/ | dist/ |
| Vanilla Vite | dist/ | dist/ |
いずれかのスクリプトを変更する前に、scripts/check-mv3-manifest.md と scripts/preflight-extension.md を読んでください。
5. 拡張機能の動作をテストする
次の点を確認します。「Chrome が拡張機能を読み込んだときに初めて現れる障害は何ですか?」
- 純粋なロジックとメッセージ/ストレージのヘルパーをユニットテストし、
chrome.*は境界でのみモックします。 chrome://extensions→ 「パッケージ化されていない拡張機能を読み込む」から、ビルド成果物を手動で読み込みます。- 拡張機能のページからサービスワーカーを調べ、アイドル状態への移行と再起動のサイクルを実行します。
- 許可された URL と許可されていない URL で、コンテンツスクリプトの注入をテストします。
- ホストへの呼び出し前に、実行時の権限リクエスト UX(
chrome.permissions.request)を確認します。
拡張機能固有のテストについては references/testing/testing-guide.md を、サービスワーカー、ポップアップ、コンテンツスクリプト、権限、ストレージのデバッグについては references/testing/debugging.md を読んでください。
6. Web Store 審査用にパッケージ化する
次の点を確認します。「審査担当者は、単一の目的、各権限が必要な理由、データの使用方法、リモートコードに関する方針を、それぞれ一文で説明できますか?」
- 本番用の出力をビルドします。
- その本番ビルドに対して、同梱された両方のスクリプトを実行します。
- zip 化する前に不要なファイルを除去します。ソースマップ(意図的に同梱する場合を除く)、テスト、
.DS_Store、__MACOSX、フレームワークのキャッシュが対象です。 - ビルド成果物のフォルダー内から zip を作成します(
manifest.jsonが zip のルートに配置されるようにします)。 - 次の項目を準備します。プライバシーに関する取り組み、権限ごとの正当な理由、リモートコードの開示、データ使用の認証、審査担当者向けのテスト手順。
- 提出前に
references/publishing/web-store.mdを読んでください。
最小限のビルド証跡
作業を終了する前に、タスクに応じた証跡をそろえます。
| タスク | 証跡 |
|---|---|
| 新しいスキャフォールド | ビルド成果物のパス + check-mv3-manifest.sh の結果 |
| 機能の変更 | 関連するユニット/統合テスト + Chrome の動作を変更した場合は手動読み込みの記録 |
| manifest/権限の変更 | check-mv3-manifest.sh の結果 + 権限の正当な理由 |
| コンテンツスクリプトの変更 | 許可 URL への注入結果 + 許可されていない URL への注入結果 |
| サービスワーカーの変更 | 再起動時の耐性に関する記録、または明示的な「未テスト」の注記 |
| パッケージ/Web Store の作業 | preflight-extension.sh の結果 + zip のパス + 審査担当者向けの注記 |
出力要件
最終報告には次の項目を含めます。
- 読み込んだビルドディレクトリ
- zip のパス(パッケージ化した場合)
- 手動テストを行った場合は、手動読み込みに使用した Chrome のバージョン
- 権限の概要とホスト権限の正当な理由
- Web Store ポリシーへの準拠状況:単一の目的、データ使用、リモートコード、MV3 への準拠
- 実行したスクリプト/テストと、その失敗
- 残っている手動確認事項についての審査担当者向け注記
ガードレール
- 新しい作業で Manifest V2 を生成したり、そのまま維持したりしてはいけません。
- フレームワークが読み込み可能なコードを明示的に出力する場合を除き、Chrome に
src/を読み込ませてはいけません。 - サービスワーカー内のモジュールスコープのグローバル変数に、永続化が必要な状態を保持してはいけません。
- サービスワーカーを存続させるために
setTimeout/setIntervalに依存してはいけません。 - MV3 で通常のネットワーク変更を行うために、ブロッキング型の
webRequestを使用してはいけません。 - 機能レベルの正当な理由と、より範囲の狭い代替手段の記録がない限り、
<all_urls>をリクエストしてはいけません。 - 認証されていないコンテンツスクリプトのメッセージを介して、任意のバックグラウンド
fetchを公開してはいけません。 - リモートの実行可能コードや、宣言されていないリモートコードの動作を同梱してはいけません。
- 完了を報告する前に、ビルド成果物のパスを
manifest.jsonと照合して、必ず検証します。 - 各権限について、一文で説明できるようにします。
要点
MV3では、サービスワーカーの状態の消失、リスナーの登録の遅れ、タイマーに依存したスケジューリング、隔離されたワールドによる予期しない動作、広すぎる権限、ビルド済みの出力ではなくsrc/を出荷するといった同じ過ちが繰り返し問題になります。固定されたデフォルトを適用し、詳細は参照資料に誘導し、ビルド済みフォルダーに対して同梱のスクリプトを実行して、レビューに適した証拠を用意してください。