7CF Style Tokyo

1999, つまり世紀末マインドで気ままにWEB技術で遊ぼうというコンセプトです

Chrome拡張機能を自作してローカルLLMと繋げる

公開日: 2026/03/13 / 更新日: 2026/03/28

WEB
AI

PC外部への通信を一切行わずに、現在開いている Web ページの本文を抽出してローカル LLM に要約させる Chrome 拡張機能を作ってみる。

具体的な機能

  1. 拡張機能を起動するとポップアップが出現する
  2. ポップアップの「要約する」を押すと
  3. 要約結果がポップアップに表示される

要約は、現在のタブの本文を抽出する→抽出した本文をローカルLLMに送る→要約結果を返す、という流れで行う。

Chrome拡張機能の実装に関するルール

デベロッパーモードで個人的に使用するだけなら、細かいことは気にしなくても問題なく動作するらしいが、今回はChromeウェブストアに公開する際の審査基準を可能な限り満たせるような実装を目指している(なお実際に通過するかは不明)。

  • Manifest V3(現行のChrome 拡張機能はこれが標準)を使う
  • 権限は activeTab scripting のみ
  • <all_urls> は使わない
  • API 通信は background 側でのみ行う
  • innerHTML eval() のような危険な処理は使わない
  • 通信先は http://localhost:1234/ に限定する

つまり、拡張機能として必要なことだけを許可して、それ以外の拡張性?は極力持たせない方針。

技術スタック

  • Vite + React + TypeScript
  • CRXJSviteのプラグインでChrome拡張機能作成が便利になるやつ。)

Viteを土台にしてReact + TypeScriptで本体を作り、CRXJSでChrome拡張機能としてビルド。

実装の手順

1. LM Studio でローカル LLM サーバーを起動する

この拡張は LM Studio の OpenAI 互換 API を叩くようにするため、先に LM Studio 側で任意のモデルをロードしてサーバーを起動しておく。(LM Studioの基本的なセットアップは割愛。)

適当なCLI から以下のコマンドを実行していく。

  1. lms ls
  2. lms load ロードしたいモデル名
  3. lms server start("--port 1234"のようにポート番号を指定してもいいが、何もつけなくても1234になった。)

すると以下のようになる。

lms ls

You have 3 models, taking up 12.19 GB of disk space.

LLM                             PARAMS    ARCH     SIZE       DEVICE    
dolphin3.0-llama3.1-8b          8B        Llama    4.69 GB    Local     
wizard-vicuna-13b-uncensored    13B       Llama    7.41 GB    Local     

EMBEDDING                               PARAMS    ARCH          SIZE        DEVICE    
text-embedding-nomic-embed-text-v1.5              Nomic BERT    84.11 MB    Local     

lms load dolphin3.0-llama3.1-8b

Model loaded successfully in 1.64s.
(4.37 GiB)
To use the model in the API/SDK, use the identifier "dolphin3.0-llama3.1-8b".
lms server start
Success! Server is now running on port 1234

今回は、dolphin3.0-llama3.1-8bという無修正モデルをロードした。このモデルは80億パラメーターの4ビット量子化でサイズは4GBちょっと、一般的には8GB以上のメモリがあればローアルで快適に動作すると言われている。(今回はM1 MacBook Pro 16GB)

これでLLMサーバーが localhost:1234 で待ち構えてくれるようになった。

2. 拡張機能を実装する

構成

.
├─ index.html
├─ manifest.json
├─ package.json
├─ package-lock.json
├─ tsconfig.json
├─ vite.config.ts
└─ src
   ├─ App.tsx
   ├─ background.ts
   ├─ content.ts
   ├─ main.tsx
   ├─ styles.css
   └─ vite-env.d.ts

処理の流れ

→ 拡張アイコンが押されると index.html が開き main.tsx が読み込まれて App.tsx が表示される
App.tsx で要約実行ボタンが押される
App.tsx background に指示を出す
background.ts が処理を開始して今のタブを特定する
background.ts content.ts をそのページ上で実行する
content.ts がページの本文を工夫しながら抜き出す
background.ts が抽出結果を受け取りプロンプトを組み立ててLLMサーバーに送る
background.ts が要約結果を App.tsx に返す
App.tsx が結果を表示する

App.tsx はポップアップUIの描画と状態管理に専念、background.ts は処理の進行役で content.ts は、service workerである background.ts が読めないページの中身を見にいく係。私は現代っ子なので、それぞれのコードの細かい中身については、優秀なコーディングエージェントに丁重にお任せした。

manifest.jsonについて(Chromeはこれをみて拡張機能の動作範囲を制御する)

{
  "manifest_version": 3,
  "name": "web analyzer",
  "version": "1.0.0",
  "description": "Analyze the current page with a local LLM running in LM Studio.",
  "permissions": ["activeTab", "scripting"],
  "host_permissions": ["http://localhost:1234/*"],
  "action": {
    "default_title": "web analyzer",
    "default_popup": "index.html"
  },
  "background": {
    "service_worker": "src/background.ts",
    "type": "module"
  },
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'; connect-src http://localhost:1234"
  }
}

ポイント1:権限は必要最小限。

  • 関数は、"activeTab"(今ユーザーが開いていて拡張を使用したタブ内で)と"scripting"(そのタブでのスクリプト実行)のみを許可
  • 通信は、http://localhost:1234/(ローカルLLMサーバー)のみ許可

ポイント2:backgroundservice workerとしてbackground.tsを登録する

  • Mnifest V3ではイベント駆動型service workerとして処理を実行する仕様。

3. ビルドする

package.jsonvite.config.tsにCRXJSに関する設定を書いていれば以下のコマンドでChrome拡張機能ようにビルドされる。

npm install
npm run build

4. Chrome から動作確認する

  1. chrome://extensions を開く
  2. デベロッパー モード”をオンにする
  3. パッケージ化されていない拡張機能を読み込む”を押す
  4. dist/ を選ぶ
  5. 普通の Web ページを開いて(Chrome ウェブストア上では動かなかった)拡張機能から"web analyzer"を選ぶ
  6. 要約する”を押して結果を確認する

総括

この度は、LLMを使ってブラウザで開いた内容の解析をChromeの拡張機能からPC外部への通信なしにして実行できることが確認できた。今回LLMに頼んだのは簡単な要約だった(今回のモデルでは1000字程度を要約するのに10秒ほどかかっている)が、より高度なLLMと接続することで可能性が広がる。例えば、内容を構造化して別のデータと比較させたり、対話型のUIを実装することで自分だけのChrome専用引きこもりコパイロットへ進化させることもできそうだ。

ライター

HARLYA

無能アリ

趣味でフルスタック開発をしている。巨人の肩に乗りまくりで四捨五入すればエンドユーザー。

関連記事

Webページをダークモードに切り替えるChrome拡張機能を自作

更新日: 2026/04/08

WEB

Geminiにロゴを生成してもらいたい

更新日: 2026/04/08

日常
AI

入力したテキストを四国めたんが読み上げるフローを完全ローカルで構築

更新日: 2026/03/28

WEB