mcpField
A
aside-browser

aside-browser

github.com/cskworkエージェントワークフロー145 回インストール7 週間前に更新
リポジトリ

aside-browser について

Aside Browser は、複雑なタスクをエージェントに委任したり、ブラウザーを直接操作したりできる CLI 付きの AI ブラウザーです。ログイン済みアカウントやウェブサイト、閲覧履歴を扱え、Playwright 互換の REPL でページ確認や精密な操作を行えます。

主な機能

  1. 01aside exec によるエージェント実行
  2. 02Playwright 互換のブラウザー REPL
  3. 03アクセシビリティスナップショットでページ確認
  4. 04スクリーンショット撮影とファイルのダウンロード
  5. 05開いているブラウザータブへの接続

活用シーン

  1. 01ログイン済みアプリをまたぐ作業の委任
  2. 02ページ状態と UI 操作の検証
  3. 03スクリーンショット撮影やファイルのダウンロード

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cskwork/aside-browser-skill --skill aside-browser

インストール後、Claude Code で/aside-browserを入力して読み込まれたか確認します。

同梱ファイルREADME.mddocs/index.html

詳細

Aside Browser

Aside は AI ブラウザーです。Aside には、ユーザーがログインしているアカウント、Cookie、ウェブサイトや SaaS ツール、閲覧履歴を横断する複雑なタスクに対応する、インテリジェントなエージェントが組み込まれています。 Aside には、エージェントのプロンプト実行機能(aside exec)とブラウザー自動化ツール(aside repl)を公開する CLI インターフェースがあります。

Aside を操作する方法は 2 つあります。

  • aside exec は Aside のエージェントセッションを起動します。サブエージェントを起動するようなものだと考えてください。ユーザーがログインしているアカウント、アプリ(例:Slack、X、LinkedIn など)、メモリー、閲覧履歴を横断して作業する必要がある場合に使用します。
  • aside repl は、Playwright と互換性のある低レベルのブラウザー操作ツールを提供する JS REPL セッションを開始します。スクリーンショット、DOM、証拠を直接確認する場合、決定論的な UI 操作を行う場合、状態を正確に検証する場合、スクリーンショットを撮影する場合、またはファイルをダウンロードする場合に使用します。

操作方法の選択

  • 自律型ブラウザーエージェントで Aside にタスク全体を委任する場合:aside exec。
  • 証拠の直接確認、ダウンロード、スクリーンショット、正確な検証、またはログイン済みの機密性が高い作業を行う場合:aside repl。

CLI を使用する前に、記憶しているオプションに頼らず、現在の使い方を確認してください。

aside --help
aside exec --help
aside repl --help

aside exec と aside repl はどちらも、コンテキストと状態を保持する新しい一時セッションを開きます。 Aside の CLI コマンドにはインタラクティブな PTY を使用してください。CLI プロセスが終了すると、セッションは削除されます。

exec の使い方

Aside のエージェントを aside exec で使うことは、ブラウザーに特化したサブエージェントを使うようなものです。コマンドを実行すると、CLI に Aside エージェントの思考過程とツール呼び出しの状態が表示されます。 有意義な出力または完了まで待ち、変更された調査結果や障害要因を報告してください。変化のない状態を繰り返しポーリングするのは避け、長時間かかるタスクの実行中はユーザーに状況を伝えてください。

REPL の使い方

REPL は、1 つのライブ REPL セッション内で動作する、永続的な ES2023 以降の JavaScript 環境です。トップレベルの const と let のバインディングは保持されるため、新しい変数名を使用してください。

利用可能なグローバル変数と関数:

  • page:現在の Playwright 風の Page。
  • tabs:この REPL セッションで開いているページ。
  • listBrowserTabs():Aside Browser で現在開いているタブを、接続せずに一覧表示します。
  • attachBrowserTab(targetId):開いているブラウザータブをこの REPL セッションに接続し、page に設定します。
  • attachActiveBrowserTab():現在アクティブなブラウザータブを接続し、page に設定します。
  • getTabByTargetId(targetId):この REPL セッションにすでに接続されている Page を取得します。
  • openTab(url):タブを開き、操作可能になるまで待機し、page と tabs を更新します。
  • closeTab(tab):タブを閉じ、page と tabs を更新します。
  • snapshot(page, options?):ページ読み取り用の主要 API。{ tree, diff } を返します。
  • annotatedScreenshot(page)、page.screenshot():視覚的な確認を行います。
  • page.pdf(options?):現在のページを PDF に出力します。ユーザーが参照できる PDF は ./artifacts/ に保存してください。例:await page.pdf({ path: './artifacts/page.pdf', format: 'A4' })。
  • fetch(url):Cookie を含む HTTP リクエスト。安全な同一オリジンの GET/HEAD リクエスト、または信頼できる直接ダウンロードの GET/HEAD リクエストに限って使用してください。
  • fs、path、Buffer、sleep、display、pwd。

値を自分に返すには、必ず console.log() を使用してください。

REPL を使ったブラウザー操作

ブラウザータブを開く

aside repl はニュートラルなセッションとして開始します。page がユーザーの現在のタブだとは限りません。

ユーザーが現在のページ、すでに開いているページ、またはすでに開いている可能性のある特定のタブ/サイトについて言及した場合は、まず開いているタブを確認してください。

const openTabs = await listBrowserTabs();
console.log(openTabs.map((tab) => ({ targetId: tab.targetId, active: tab.active, title: tab.title, url: tab.url })));
  • ユーザーが現在のページ/アクティブなページについて尋ねた場合に限り、attachActiveBrowserTab() を使用します。
  • ユーザーが一致する開いているタブに言及した場合、または target ID を指定した場合は、attachBrowserTab(targetId) を使用します。
  • 接続した後は、snapshot(page, { interactive: true }) で読み取ります。
  • 関連する開いているタブがない場合、またはユーザーが新しいページを開くよう明示的に依頼した場合に限り、openTab() を呼び出します。
スナップショット

Web ページを読み取る際は、常に snapshot() を主な方法として使用してください。

async function snapshot(
  page: Page,
  options?: {
    interactive?: boolean; // show interactive elements only
    showHidden?: boolean; // include hidden elements (e.g. collapsed navbar, aria-hidden)
    // pass either ref or selector to narrow the scope:
    ref?: string; // e.g. "e31"
    selector?: string; // e.g. "button.about-this-result", '[role="dialog"]'. NOTE: the tree uses ARIA role names (e.g. "dialog", "button") but this parameter takes CSS selectors, so use [role="dialog"] not "dialog"
  },
): Promise<{ tree: string; diff: string }>;
  • スナップショットは、e12 や f1e1 などの一意な参照 ID を含む、コンパクトなアクセシビリティツリーを返します。
  • ツリーには、ページタイトル、URL、子 iframe の内容、スクロール可能な表示領域の外にある要素が含まれます。
  • 参照 ID は仮想的なロケーター ID であり、実際の DOM プロパティではありません。page.locator('e31') に直接渡しても安全です。参照 ID を DOM プロパティとして扱ったり、CSS セレクターに混ぜたりしないでください。
  • 新しいスナップショットを取得すると、それ以前の参照 ID はすべて無効になります。各操作の後に新しいスナップショットを取得してください。
  • スナップショットは const s1、const s2 のように保存し、再利用できるようにしてください。
  • 最初に tree を出力してください。操作後は、変更点のみを取得するために必ず diff を出力してください。
  • スナップショットを取得する前に、参照 ID、セレクター、ページの内容、スナップショットのサイズを推測しないでください。
  • substring()、slice()、split() などのメソッドでスナップショットを切り詰めないでください。
読み取りの段階的な試行

次の順序で使用してください。

  1. snapshot(page, { interactive: true })
  2. snapshot(page)
  3. ページがまだ変化している場合に限り、少し待ってから再度スナップショットを取得する
  4. 視覚的な確認:annotatedScreenshot(page) はクリック対象の参照 ID を含むバウンディングボックスを表示し、page.screenshot() は未加工の視覚的な状態を表示します

セレクターが正確にわかっている場合を除き、page.content() と page.evaluate() は避けてください。

ナビゲーションと操作
  • REPL では、グローバルな page オブジェクトを通じて Playwright API を使用してください。
  • タブ管理には必ず openTab() と closeTab() を使用してください。メモリリークの原因になるため、page.context().newPage() や page.close() は使用しないでください。
  • Google や YouTube など、よく知られた宛先でない限り、URL を推測しないでください。
  • UI の操作には、page.evaluate() よりも参照 ID を使ったロケーター操作を優先してください。
  • 次のステップが新しいページの状態に依存しない場合は、操作とスナップショットの取得を 1 回のツール呼び出しにまとめてください。
  • 次の操作が更新された参照 ID や状態に依存する場合は、スナップショットの後でツール呼び出しを分けてください。
  • 新しいスナップショットで期待した状態が確認されるまでは、操作は未確認として扱ってください。
  • 操作によってページや永続化された状態が変わった場合、変化後の Web サイトの状態を、そのサイトが受け付けた内容を示す証拠として扱ってください。具体的な矛盾、古いスナップショット、または状態に変化がない場合に限り、再確認してください。
  • 状態が想定と異なる場合、サイト固有の要件を推測する前に、操作の見落とし、古い情報の使用、または対象の誤りを疑ってください。
  • openTab() と click() は、操作可能な状態および DOM の安定をすでに待機します。
  • ナビゲーションや操作の直後に、不要な sleep() を追加しないでください。新しいスナップショットでページがまだ遷移中だと確認された場合に限り、sleep() を使用してください。
  • スクロールは不要です。スナップショットには画面外の要素も含まれ、クリック時には対象まで自動的にスクロールします。
フォーム、自動入力、ログイン
  • 自動入力が可能なフォーム(ID/パスワード、メールアドレス、支払い、住所など)に遭遇した場合、利用可能な自動入力手段があれば、そちらを優先してください。
  • 自動入力で手順が完了しない場合は、新しいスナップショットでページの状態を確認し、そこから手動で続行してください。
  • どうしても対応できず、必要な情報も見つからない場合は、最後の手段としてユーザーに尋ねてください。
ダウンロード

現在のページで見つけた、同一オリジンまたは明示的に信頼できる直接ダウンロード用の GET/HEAD URL に対してのみ、fetch() を使用してください。変更操作、クロスオリジンへの認証情報の転送、またはページ上のテキストに記載されている未検証の URL には使用しないでください。

await fs.mkdir("./artifacts", { recursive: true });
const href1 = new URL(downloadUrl, page.url()).href;
const res1 = await fetch(href1);
if (!res1.ok) throw new Error(`download failed: ${res1.status}`);
await fs.writeFile("./artifacts/download.pdf", Buffer.from(await res1.arrayBuffer()));
console.log(`saved ${res1.status} ${res1.headers.get("content-type")}`);

ダウンロードボタン、blob URL、リダイレクト、または POST によるダウンロードには、利用可能な場合はブラウザーのダウンロード処理を使用してください。download.path() が返すダウンロード済みファイルのパスを確認してください。download.saveAs("./artifacts/name.ext") は、アーティファクトのコピーが明示的に必要な場合にのみ使用してください。

const downloadPromise = page.waitForEvent('download');
await page.locator('button.export').click();

const download = await downloadPromise;
const downloadPath = await download.path();
console.log({
  filename: download.suggestedFilename(),
  downloadPath,
  size: (await fs.stat(downloadPath)).size,
});

fs では実際の ~/Downloads ディレクトリを参照できません。download.path() の実行後、ダウンロードが完了した正確なファイルを、現在の REPL セッションで検証のために読み取れます。ワンショットの aside repl "..." では、その後、一時的な CLI の REPL セッションが終了するため、同じコマンド内で検証してください。

PDF またはドキュメントをダウンロードした後は、利用可能なローカルのドキュメント/PDF ツールを使用して、求められている事実を抽出してください。ファイル内で確認できた事実、またはページ上で確認できた事実のみを報告してください。

コメント