aside-browser について
Aside Browser は、複雑なタスクをエージェントに委任したり、ブラウザーを直接操作したりできる CLI 付きの AI ブラウザーです。ログイン済みアカウントやウェブサイト、閲覧履歴を扱え、Playwright 互換の REPL でページ確認や精密な操作を行えます。
主な機能
- 01aside exec によるエージェント実行
- 02Playwright 互換のブラウザー REPL
- 03アクセシビリティスナップショットでページ確認
- 04スクリーンショット撮影とファイルのダウンロード
- 05開いているブラウザータブへの接続
活用シーン
- 01ログイン済みアプリをまたぐ作業の委任
- 02ページ状態と UI 操作の検証
- 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()などのメソッドでスナップショットを切り詰めないでください。
読み取りの段階的な試行
次の順序で使用してください。
snapshot(page, { interactive: true })snapshot(page)- ページがまだ変化している場合に限り、少し待ってから再度スナップショットを取得する
- 視覚的な確認:
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 ツールを使用して、求められている事実を抽出してください。ファイル内で確認できた事実、またはページ上で確認できた事実のみを報告してください。