chrome-relay について
chrome-relayは、ブラウザー拡張機能とローカルのネイティブホストを通じて、実際のChromeを操作するスキルです。操作可能な要素参照付きのページスナップショットやタブ操作コマンドを提供し、既存のログイン状態が必要な場面で役立ちます。
主な機能
- 01Chromeタブの操作
- 02操作可能な参照付きページスナップショット
- 03クリック、入力、待機
- 04ページテキスト、ネットワーク、コンソールの確認
- 05スクリーンショットと録画
活用シーン
- 01ログイン済みブラウザーでのワークフロー自動化
- 02Webページの入力欄の確認と更新
- 03ページ操作や読み込みの問題調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ kiluazen/ chrome-relay --skill chrome-relayインストール後、Claude Code で/chrome-relayを入力して読み込まれたか確認します。
同梱ファイルreferences/patterns.mdreferences/troubleshooting.md
詳細
Chrome Relay
Chrome 拡張機能とローカルネイティブホストを通じて、ユーザーが実際に使用している Chrome を操作します。ログイン済みのブラウザーの状態(認証 Cookie、セッション、インストール済み拡張機能)が重要な場合に適しています。
セットアップ
- Chrome 拡張機能
- CLI:
pnpm add -g chrome-relay chrome-relay install chrome-relay doctor
CLI が 0.7.0 以上であることを確認してください。wait/get/batch/snapshot --diff はこのバージョンで追加されました(0.6.0 では snapshot/@ref のループが導入され、0.5.20 以上では Radix/React-Aria の UI で発生していたクリックが無反応になるバグが修正されました)。
chrome-relay --version
基本的なループ
chrome-relay tabs # find or create a tab
chrome-relay navigate "https://kushalsm.com" --new # background tab by default
chrome-relay snapshot --tab 1234 -i # see the page: actionable elements get @refs
chrome-relay click @e12 # act on refs — no --tab, no selector
chrome-relay fill @e14 "hello"
chrome-relay wait --text "Saved" --tab 1234 # block until the page reacts
chrome-relay snapshot --tab 1234 --diff # print only what changed (~100 tokens)
スナップショットの出力は簡潔なインデント付きテキストです(ほとんどのページで約 1〜15 KB)。そのまま読み取れるため、jq は不要です。
- link "Hacker News" [ref=e4]
- textbox "Search" [ref=e41]: current value
- checkbox "Remember me" [checked, ref=e42]
- clickable "Open card" [ref=e88] ← cursor-pointer div the AX tree missed
Ref はそれぞれ自身のタブを参照します。 click @e12 は e12 を生成したタブを操作し、アクティブなタブは操作しません。ユーザーがブラウジングを続けていても安全です。これと矛盾する --tab を指定すると、target_conflict エラーが発生します。
Ref の有効期間。 Ref は同じページ内での DOM の変化を経ても有効です(キャッシュされた backendNodeId を使用し、ノードが置き換わった場合はロールと名前で再検索して補正します)が、実際にページ遷移すると無効になります。無効な Ref を使うと error.code = stale_ref が返されます。その場合は snapshot を再実行してください。
インターセプト。 Ref によるクリックでは、最初に指定位置の要素を判定します。オーバーレイ/固定ヘッダー/モーダルがその位置を占有している場合、インターセプトした要素を示す error.code = click_intercepted が返されます。インターセプト要素を閉じるかスクロールしてから再試行してください。クリックは実行されていません。fill/type ではこの確認を省略するため、覆われている入力欄にも書き込めます。
ツール一覧
| コマンド | 機能 |
|---|---|
tabs | ウィンドウとタブを、それぞれの tabId とともに一覧表示します |
navigate <url> | 現在のタブで開きます。--new はバックグラウンドタブで開きます(デフォルト)。--active はタブを前面に表示します。--tab <id> は既存のタブを対象にします。 |
snapshot --tab <id> -i | 操作可能な @refs を含むページスナップショットを取得します。アクセシビリティツリーとカーソル操作可能な要素のスイープを、1つの参照空間で簡潔なテキストとして表示します。-d N は深さの上限、-s <css> はサブツリーに対象を限定、-u は href を含める指定、--diff は前回のスナップショットからの変更のみを出力、--json は refs マップを含む構造化エンベロープを出力します。 |
wait <css|@ref> / wait --text / --url <glob> / --load networkidle / --fn <js> | 条件が満たされるまで待機します(1回の呼び出しにつき1条件、デフォルト10秒、最大25秒)。wait 1500 は単にスリープします。タイムアウト時のエラーには現在のページ状態が含まれます。 |
get text|value|attr|count|title|url <target> | 値を1つだけ取得し、そのまま stdout に出力します。フルスナップショットは取得しません。get text @e12、get attr @e7 href、get count ".row" のように指定します。 |
batch '[{"name":"chrome_...","args":{...}}, ...]' | 1回の往復でN個のツール呼び出しを順番に実行します。デフォルトではエラー時に中断します。wire ツール名を使用してください。 |
skills get core | インストール済みバイナリのバージョンに対応した、このプレイブックを出力します。 |
click <@ref | selector> --tab <id> | 要素の中央で、信頼されたホバー、押下、解放を行います(pointerType: "mouse")。refs の場合は --tab は不要です。 |
click --x N --y N --tab <id> | 座標モードでクリックします。DOM ハンドルのない canvas/SVG チャート内部に使用します。 |
hover <@ref | selector | --x --y> | ポインターを移動するだけで、:hover スタイルを発動させます。 |
fill <@ref | selector> <value> | <input>/<textarea>/<select> に値をアトミックに書き込みます。React の値トラッカーをバイパスします。refs は shadow DOM 内にも到達できます(セレクターでは到達できません)。 |
type <text> [-s <@ref | selector>] | CDP の Input.insertText を使用します。contenteditable/Draft.js/Lexical/ProseMirror で使用します。キャレット位置に追記されます。入力欄に値がある場合は、先に消去してください。 |
keys <chord> --tab <id> | 単一のキーまたはキーの組み合わせを入力します。例:Enter、Tab、Escape、Cmd+K、Shift+ArrowDown。 |
js <code> --tab <id> | MAIN world で Runtime.evaluate を実行します。値を取得するには return を使用します。トップレベルの await が使えます。 |
screenshot --tab <id> -o <path> | PNG を取得します。--full はビューポート外もキャプチャします。--max-edge N はサイズを変更します。 |
screencast --tab <id> -o <path> | CDP 経由でタブを録画します(描画に連動)。アクティブなタブが必要です。 |
network --tab <id> | HTTP リクエスト/レスポンスのリングバッファを表示します。タブごとに直近200件です。本文を取得するには network read --request-id <id> を使用します。 |
console --tab <id> | console.log/warn/error とページ例外を表示します。直近200件です。 |
viewport | デバイスのビューポート、DPR、モバイルフラグ、タッチ、UA をエミュレートします。 |
workspace / group | 名前付きウィンドウ/タブグループを管理し、複数のエージェントが別々のウィンドウを操作できるようにします。 |
switch <tabId> / close <tabIds...> | タブをアクティブにするか、閉じます |
self-reload | 再ビルド後に拡張機能のサービスワーカーを再起動します |
release-notes --since <ver> / update | 検索可能な変更履歴を取得します。エージェントが読み取れる JSON 形式です。 |
call <tool> [json] | 任意の内部ツールに生のまま渡します。 |
read / ax / click-ax | 非推奨 — snapshot/click @ref のエイリアスです。削除予定のため、新しい作業では使用しないでください。 |
適切なテキスト入力ツールの選び方
| 対象要素 | ツール |
|---|---|
<input>、<textarea>、<select>(React の制御下にあるもの、shadow DOM を含む) | fill @ref |
[contenteditable]、role="textbox"、Draft.js/Lexical/ProseMirror、X の投稿作成欄、LinkedIn の DM、新しい Reddit の投稿作成欄 | type |
| 送信、メニューの移動、修飾キーを使ったショートカット | keys |
| コンボボックス/オートコンプリートのオプション選択 | フィルターに type → keys ArrowDown → keys Enter(理由) |
| フレームワーク内部への操作、スクレイピング、カスタムウィジェット | js |
要素の指定 — フォールバックの優先順位
snapshot -iの@ref— デフォルトです。ボタン/リンク/入力欄、名前付きコンテンツ、カーソルポインターの div の集合体(スイープ)、シャドウ DOM に対応します。- CSS セレクター — セレクターが静的に分かっていて、スナップショットが不要な場合に使います。
jsによる調査 → 座標クリック — canvas の内部要素や SVG グラフのセグメント(匿名の<path>要素には、どこにも DOM ハンドルがありません):chrome-relay js --tab 1234 "const r = document.querySelector('svg path').getBoundingClientRect(); return {x: r.x + r.width/2, y: r.y + r.height/2}" chrome-relay click --tab 1234 --x 312 --y 218
ポーリングせず、待機する
操作のたびにスナップショットを取得すると、ターンが無駄になります。変化するページでは、次の軽量なループを使います。
chrome-relay click @e12
chrome-relay wait --text "Saved" --tab 1234 # or wait <selector> / --url / --load
chrome-relay snapshot --tab 1234 --diff # only the changes, refs included
主な注意点
snapshot -iは情報の抽出ではなく、操作のためのものです。refを持つ要素のみが出力されます。操作対象ではない値(ダッシュボードの指標、段落のテキスト、グラフのラベルなど)は省かれます。実測では、Cloudflare Pages の指標ページですべての数値が-iによって消えました。情報を読み取るには、完全なsnapshot、get text <target>、またはjsによるプロジェクションを使ってください。typeは追記します — カーソル位置に挿入します。入力欄に値がすでにある場合(自動保存された下書きやデフォルトのテキストなど)は、先にjsまたはkeys(Cmd+A の後に Backspace)で消去してください。- ページ遷移で
refは無効になります —stale_refは、ページが変化したことを意味します。スナップショットを取り直してください。同じrefを再試行しないでください。 - 座標はすぐに古くなります —
getBoundingClientRectで読み取った後にスクロールや再レイアウトが発生すると、クリック位置がずれて別の要素を押してしまいます。特にオートコンプリートのポップアップでは、座標クリックではなくキーボード操作を使ってください。 - クリックは「成功」したのに何も起きない — まず
document.elementFromPoint(x, y)で確認してください。ラッパーやフォームの背景が返された場合、座標が間違っています。正しい要素が返されても状態が変わらない場合は、chrome-relay <0.5.20 を使っている可能性が高いため、アップグレードしてください。
その他のレシピ:references/patterns.md 失敗時の対処方法:references/troubleshooting.md
運用ガイダンス
- すぐに諦めないでください。 クリックの失敗は停止の合図ではなく、情報です。
capture:trueを指定してドキュメントレベルのリスナーを登録し、どのイベントが発生するか確認してください。chrome-relay js --tab 1234 " ['pointerdown','mousedown','click'].forEach(t => document.addEventListener(t, e => console.log(t, e.target.tagName, e.target.className), {capture:true}) ); return 'listening' " # do the action, then: chrome-relay console --tab 1234 - シークレットを出力しないでください。
jsでトークン/API キーを取得する場合は、結果を直接ファイルに書き込んでください。echo $TOKENを実行したり、シェル文字列に埋め込んだりしないでください。スクロールバック、ログ、ツールのトランスクリプトに残ってしまいます。 networkの出力はマスキングしてください。 リクエスト/レスポンスのヘッダーには、Cookie、認証/CSRF トークン、アカウント ID、プロジェクト ID が含まれます。chrome-relay networkの出力をそのままチャット、ドキュメント、Issue、コミットに貼り付けないでください。必要なフィールド(url、status、timings)だけに絞るか、先にヘッダーをマスキングしてください。- 取り消せない操作(フォームの送信、メッセージの送信、アカウントの変更)を行う前にキャプチャしてください。スクリーンショットのパスを保存してください。
ガードレール
- エラーは構造化されています。メッセージのテキストではなく、
relayError.code(stale_ref、click_intercepted、element_not_found、target_conflict、timeout)に基づいて分岐してください。 - フラグが不明な場合は、
chrome-relay <command> --helpの内容を正としてください。ドキュメントは最新でないことがあります。