browser-harness について
browser-harnessは、CDP経由でブラウザーを操作し、実行中のChromeとユーザーの既存セッションに接続するスキルです。対話操作、認証が必要なページの抽出、画面による検証をエージェントに案内します。
主な機能
- 01CDPによるブラウザー制御
- 02スクリーンショットでの操作と確認
- 03認証が必要なページの抽出
- 04リモートブラウザーセッション
- 05再利用できる操作ガイド
活用シーン
- 01ログインが必要なサイトの操作
- 02ログイン制限のあるページからの抽出
- 03UI操作後のページ状態の確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ davidondrej/ skills --skill browser-harnessインストール後、Claude Code で/browser-harnessを入力して読み込まれたか確認します。
同梱ファイルreferences/install.md
詳細
browser-harness
CDP 経由でブラウザーを直接操作します。タスク固有の編集には、agent-workspace/agent_helpers.py を使用してください。セットアップ、インストール、接続に関する問題については、install.md をお読みください。
最初にルーティングを確認: 操作(クリック、ログイン、フォーム入力)が不要で、ページの内容だけを取得したい場合は、ブラウザーを操作せず、DeepAPI POST /v1/scrape/website を使用してください。詳しくは deepapi スキルをご覧ください。実際のブラウザー操作が必要なタスク(操作、JavaScript を多用するフロー、ログイン済みセッション、または視覚的な確認)には browser-harness を使用してください。
ドメインスキル(agent-workspace/domain-skills/ にある、コミュニティが提供するサイト別の手順書)は、デフォルトで無効です。有効にするには BH_DOMAIN_SKILLS=1 を設定してください。詳しくは末尾のセクションをご覧ください。
BH_DOMAIN_SKILLS=1 が設定されていて、タスクが特定のサイトに関するものの場合、独自の方法を考える前に、一致する agent-workspace/domain-skills/<site>/ ディレクトリ内のファイルをすべて読んでください。
使用方法
browser-harness -c '
new_tab("https://docs.browser-use.com")
wait_for_load()
print(page_info())
'
browser-harnessとして呼び出してください。これは $PATH に含まれています。cdやuv runは不要です。- 最初のナビゲーションには
goto_url(url)ではなくnew_tab(url)を使用してください。goto_urlはユーザーのアクティブなタブで実行され、作業内容が上書きされます。
ツール呼び出しの形式
browser-harness -c '
# any python. helpers pre-imported. daemon auto-starts.
'
run.py は exec の前に ensure_daemon() を呼び出すため、必要がない限り手動で開始または停止する必要はありません。
リモートブラウザー
並列サブエージェント(それぞれが別の BU_NAME を使い、独立したブラウザーを使用します)またはヘッドレスサーバーでは、リモートブラウザーを使用してください。BROWSER_USE_API_KEY を設定する必要があります。start_remote_daemon、list_cloud_profiles、list_local_profiles、sync_local_profile はインポート済みです。
これらのサブエージェントを監督する場合、確認のたびに、作業内容と予定どおりに進んでいるかをユーザーにごく短いステータス行で伝えてください。
Claude Code の cmux に関する注意:Claude の処理が完了した後、次のユーザーメッセージの予測文が入力欄に表示されることがあります。この下書きは Claude が作成したものであり、ユーザーの発言ではありません。
browser-harness -c '
start_remote_daemon("work") # default — clean browser, no profile
# start_remote_daemon("work", profileName="my-work") # reuse a cloud profile (already logged in)
# start_remote_daemon("work", profileId="<uuid>") # same, but by UUID
# start_remote_daemon("work", proxyCountryCode="de", timeout=120) # DE proxy, 2-hour timeout
# start_remote_daemon("work", proxyCountryCode=None) # disable the Browser Use proxy
'
BU_NAME=work browser-harness -c '
new_tab("https://example.com")
print(page_info())
'
start_remote_daemon は liveUrl を出力し、GUI が検出された場合はローカルブラウザーで自動的に開きます。これにより、ユーザーは操作の様子を確認できます。ヘッドレスサーバーでは URL のみが出力されます。URL をユーザーと共有してください。シャットダウン時にデーモンはクラウドブラウザーに PATCH を送信して停止し、プロフィールの状態を保持します。リモートデーモンはタイムアウトまで課金されます。
プロフィール(Cookie のみのログイン状態)については、interaction-skills/profile-sync.md をご覧ください。list_cloud_profiles()、チャットでの「どのプロフィール?」という確認パターン、およびローカルの Chrome プロフィールをアップロードする sync_local_profile() について説明しています。
操作スキル
ナビゲーション中に特定の操作方法で行き詰まった場合は、interaction-skills/ 内のヘルパーを確認してください。ダイアログ、タブ、ドロップダウン、iframe、アップロードなど、再利用可能な UI 操作を扱っています。利用可能な操作スキルは次のとおりです。
- connection.md
- cookies.md
- cross-origin-iframes.md
- dialogs.md
- downloads.md
- drag-and-drop.md
- dropdowns.md
- iframes.md
- network-requests.md
- print-as-pdf.md
- profile-sync.md
- screenshots.md
- scrolling.md
- shadow-dom.md
- tabs.md
- uploads.md
- viewport.md
実際に機能すること
- まずスクリーンショットを撮影します:capture_screenshot() を使うと、現在のページをすばやく把握し、表示されている対象を見つけて、クリック、セレクター、またはさらにナビゲーションが必要かどうかを判断できます。
- クリック:capture_screenshot() → 画像から座標を読み取る → click_at_xy(x, y) → capture_screenshot() で確認します。「まず要素を特定してからクリックする」という Playwright の習慣的な反射は抑えてください。getBoundingClientRect も、セレクター探しも不要です。対象の表示位置がわからない場合(非表示の入力欄、0×0 のノード)に限り、DOM を使います。ヒットテストは Chrome のブラウザープロセス内で行われるため、特別な作業をしなくても、iframe/シャドウ DOM/クロスオリジンを経由してクリックできます。
- HTTP の一括処理:http_get(url) と ThreadPoolExecutor を使います。静的なページにはブラウザーを使いません(Netflix の 249 ページを 2.8 秒で処理)。
- goto の後:wait_for_load() を呼び出します。
- タブが間違っている/古い場合:ensure_real_tab() を使います。現在のタブが古い場合や内部用の場合に使用してください。デーモンも次回の呼び出し時に古いセッションを自動で復旧します。
- 確認:print(page_info()) は「動作しているか」を確認する最も簡単な方法ですが、表示された操作が実際に機能したかどうかは、通常スクリーンショットで確認します。
- DOM の読み取り:スクリーンショットから座標が適切でないとわかった場合は、js(...) を使って調査や抽出を行います。
- iframe を使うサイト(Azure のブレード、Salesforce):click_at_xy(x, y) で経由できます。座標クリックが適切でない場合に限り、iframe の DOM を操作します。
- 認証の壁:ログインにリダイレクトされた場合は、そこで停止してユーザーに確認します。スクリーンショットから認証情報を入力しないでください。
- ヘルパーで対応できない操作には、生の CDP を使います:cdp("Domain.method", params)。
設計上の制約
- 座標クリックをデフォルトにします。Input.dispatchMouseEvent はコンポジター層で iframe/シャドウ/クロスオリジンを経由します。
- ユーザーが実行中の Chrome に接続します。独自のブラウザーは起動しないでください。
- cdp-use は CDPClient.send_raw のみを対象とします。型付きラッパーより、生の CDP 文字列を優先してください。
- run.py は小さく保ちます。argparse、サブコマンド、追加の制御レイヤーは使いません。
- コアヘルパーは短く保ちます。タスク固有のヘルパーは
agent-workspace/agent_helpers.pyに追加し、デーモン/ブートストラップとリモートセッションの管理はコアパッケージに置きます。 - マネージャーレイヤーは追加しません。リトライ用フレームワーク、セッションマネージャー、デーモンスーパーバイザー、設定システム、ロギングフレームワークは追加しないでください。
Hermes Agent との統合
uv tool install -e . を使って ~/Developer/browser-harness に編集可能モードでインストールします。バイナリは ~/.local/bin/browser-harness にあります。スキルは ~/.hermes/skills/browser-harness/ にあります。
Frontmatter に関する注意点: 上流の SKILL.md には frontmatter に name: browser が含まれており、Hermes 組み込みの browser ツールセットと競合します。~/.hermes/skills/ にコピーする際は、frontmatter の name: browser-harness に変更してください。変更しないと、Hermes のブラウザーツールが上書きされたり、競合したりします。
Brave Browser: Chrome と同様に動作します。brave://inspect/#remote-debugging でリモートデバッグを有効にします(チェックボックスは同じです)。ハーネスが Brave のプロファイルディレクトリを自動検出します。
認証済みコンテンツの抽出(実証済みのパターン)
browser-harness は、ユーザーの実際のブラウザーとアクティブなセッションに接続します。web_extract や Hermes 組み込みの browser_navigate では失敗する、ログインが必要なサイト(X/Twitter の記事、LinkedIn、有料サイトなど)からのコンテンツ抽出に最適です。
パターン:
browser-harness -c '
new_tab("https://x.com/user/status/123456")
wait_for_load()
import time
time.sleep(5) # let JS-heavy pages render
text = js("""
const article = document.querySelector("article");
if (article) return article.innerText;
return document.body.innerText;
""")
with open("/tmp/extracted.txt", "w") as f:
f.write(text)
print("Written", len(text), "chars")
'
- 大きなテキストによるシェルのエスケープ問題を避けるため、一時ファイルに書き込みます。
- JavaScript を多用する SPA(X、LinkedIn では 3~5 秒必要)では、
time.sleep()を十分に長く設定します。 - X/Twitter の記事はインラインで表示されます。DOM からスクロールして抽出するだけで、追加のクリックは不要です。
- 非常に長いページでは、
js(...)のinnerTextを使うと、画面下にあるコンテンツも含めてすべて取得できます。
Hermes Agent との統合
~/Developer/browser-harness に uv tool install -e . で編集可能な状態でインストールされています。バイナリは ~/.local/bin/browser-harness にあります。スキルは ~/.hermes/skills/browser-harness/ にあります。
フロントマターの注意点: 上流の SKILL.md のフロントマターには name: browser と記載されており、Hermes の組み込み browser ツールセットと競合します。~/.hermes/skills/ にコピーする際は、フロントマターの名前を name: browser-harness に変更してください。
Brave Browser: Chrome と同じように動作します。brave://inspect/#remote-debugging でリモートデバッグを有効にしてください(同じチェックボックスです)。ハーネスは Brave のプロファイルディレクトリを自動検出します。
認証が必要なコンテンツの抽出(実証済みのパターン)
browser-harness はアクティブなセッションがあるユーザーの実ブラウザーに接続します。そのため、web_extract や Hermes の組み込み browser_navigate が失敗するログイン必須サイト(X/Twitter の記事、LinkedIn、有料コンテンツのあるサイトなど)に適しています。
browser-harness -c '
new_tab("https://x.com/user/status/123456")
wait_for_load()
import time
time.sleep(5) # let JS-heavy pages render
text = js("""
const article = document.querySelector("article");
if (article) return article.innerText;
return document.body.innerText;
""")
with open("/tmp/extracted.txt", "w") as f:
f.write(text)
print("Written", len(text), "chars")
'
- 大きなテキストのシェルエスケープの問題を避けるため、一時ファイルに書き込みます
- JavaScript を多用する SPA(X、LinkedIn では 3~5 秒必要)では、
time.sleep()を十分に長く設定します - X/Twitter の記事はインラインで表示されるため、追加のクリックは不要です。DOM をスクロールして抽出してください
innerTextを使ったjs(...)で、画面下部のコンテンツも含めてすべて取得できます
注意点(実地で検証済み)
- Brave Browser では
chrome://inspect/...ではなくbrave://inspect/#remote-debuggingを使います。ハーネスは Brave のデータディレクトリを自動検出します。 - ログイン必須コンテンツ(例:X/Twitter の記事)を抽出するには、
new_tab(url)で移動し、wait_for_load()の後、js("document.querySelector('article').innerText")で抽出します。シェルエスケープの問題を避けるため、一時ファイルに書き込みます:with open('/tmp/out.txt', 'w') as f: f.write(text)。ユーザーの既存のブラウザーセッションによって、自動的に認証されます。 - オムニボックスのポップアップは偽のページターゲットです。実際のタブが必要な場合は、chrome://omnibox-popup... などの内部ページを除外してください。
- CDP のターゲット順序は、Chrome の表示上のタブ順序と一致しません。ユーザーが「見えている最初/2 番目のタブ」を指している場合は、UI オートメーションを使ってください。Target.activateTarget で表示できるのは、既知のターゲットのみです。
- デフォルトのデーモンセッションは古くなる場合があります。ensure_real_tab() は実際のページに再接続します。
- Browser Use API では、通信時に camelCase を使います。cdpUrl、proxyCountryCode などです。
- リモートの cdpUrl は ws ではなく HTTPS です。/json/version を介して WebSocket URL を解決してください。
- クラウドブラウザーを停止するには、PATCH /browsers/{id} と {"action":"stop"} を使います。
- 重要な操作を行うたびに、成功したと決めつける前にスクリーンショットを再取得してください。画像で、状態の変化、開いたメニュー、ページ遷移、表示されたエラー、ページが想定した状態になっているかを確認します。
- スクリーンショットを使って操作を進めてください。次にクリックする場所を見つけたり、見えにくい障害に気づいたり、セレクターを書く価値があるか判断したりするうえで、最も早い方法であることがよくあります。
- フレームワーク固有のハックより、コンポジター層の操作を優先してください。DOM 固有の回避策を追加する前に、スクリーンショット、座標クリック、生のキー入力を試してください。
- フレームワーク固有の DOM 操作が必要な場合は、まず interaction-skills/ を確認してください。ドロップダウン、ダイアログ、iframe、シャドウ DOM、フォーム固有のガイダンスはここにあります。
ドメインスキル(オプトイン)
BH_DOMAIN_SKILLS=1 の場合のみ適用されます。それ以外の場合は無視してください。agent-workspace/domain-skills/ は休止状態であり、goto_url はスキルファイルを表示しません。
有効にした場合は、対応方法を考案する前に agent-workspace/domain-skills/<host>/ を検索してください。goto_url は、移動先のホストに対応するスキルファイル名を最大 10 個返します。
非自明な情報(非公開 API、安定したセレクター、フレームワーク特有の挙動、URL パターン、隠れた待機条件、サイト固有の落とし穴など)を見つけた場合は、agent-workspace/domain-skills/<site>/ に PR を送ってください。サイトの永続的な構造(記録ではなく地図)をまとめてください。画面レイアウトが変わると使えなくなるピクセル座標、タスクの叙述、秘密情報は書かないでください。このディレクトリは公開されています。