ego lite

人と AI エージェントが並行作業する Chromium ブラウザと、任意のエージェント CLI から呼べる ego-browser ハーネス — citrolabs/ego-lite

1 — 概要

ego lite は、ユーザーと AI エージェントが並行して使えるように設計された Chromium ベースのブラウザ。エージェントは自分専用の隔離された Space で複数のブラウザタスクを走らせ、ユーザーのタブはそのまま維持される。エージェントはユーザーの実際のログイン状態やタブに ego-browser 経由で常時到達できる。

従来の browser-use や agent-browser はブラウザ自動化フレームワークで、駆動用に別のブラウザを必要とし、ログインがうまく引き継がれず、ユーザーとエージェントが同じタブを奪い合いがちだった。ego lite は最初から「2 者が 1 つのブラウザを共有する」前提で作られている。macOS で動作し、Windows と Linux はロードマップ上にある。

最大 2.5×agent-browser 比の高速化
1 回Bash 実行に処理をまとめる
Spaceエージェントごとに隔離
MITハーネスとスキルのライセンス

公開されているこのリポジトリは、ego lite アプリ本体ではなく、オープンソースの ego-browser ハーネスとエージェント向けスキルパッケージを含む。ブラウザ本体(クローズドソース)は自前の ego-browser バイナリを同梱し、そこにこのランタイムが埋め込まれている。

ego lite がエージェントに公開する機能は、エージェントが直接呼ぶ JavaScript 関数として提供される。エージェントは複数ステップのタスクを 1 つの出力に構成でき、「2 コマンド叩いて結果を見てまた 2 コマンド」というループに陥らない。複雑なワークフローは従来の CLI 型より最大 2.5× 速く、成功率が高く、タスクあたりのツール呼び出しが大幅に少ない。

カーネルレベルのカスタマイズにより、テキストモデルがページを「見て」操作するための Snapshot を高品質に生成する。深くネストした iframe のような難しいケースでも安定して扱える。

各 Space はそれぞれ別のエージェントやタスクを持ち、同時に走る。10 個の Space で 10 件のリードを処理しつつ、別の 5 Space で 5 サイトを収集、といった並行作業でも互いに衝突せず、ユーザーのタブやマウス位置を奪わない。

ego-browser は、任意のエージェント CLI(Claude Code、Codex、Cursor、独自実装)と ego lite をつなぐ接続層。ブラウザをページ内 JavaScript ツール群(snapshot / fill / click / wait / navigate / capture)として公開し、エージェントが書いた JavaScript を 1 パスでページ上に実行する。

2 — 仕組み

ego-browser は Node.js の CDP ブラウザ自動化ハーネスで、ego lite アプリが提供する globalThis.ego バインディングを通してブラウザを駆動する。エージェントの heredoc から入った JavaScript は、ヘルパー群を経由してブラウザランタイム/CDP に渡り、Snapshot や DOM/AX 解決、必要なら site ツールを通って console.log(...) で出力される。

stdin の JS → runMain() → helperContext() ヘルパー → ブラウザランタイム / CDP → Snapshot・DOM/AX 解決 → site ツール(任意) → console.log()
  • src/index.ts — エントリポイント。CLI として直接実行すると runMain()(stdin の JS を実行)、モジュールとして読み込まれると installEgoSdk(globalThis)(アプリが埋め込む経路)。両経路とも同じヘルパー面を公開する。
  • src/helpers.ts — helperContext() がエージェントの呼べる面(help() や agent_helpers.js 拡張を含む)を組み立てる単一の正。
  • src/browser-runtime.ts — ego.sendCDPMessage 上の CDP トランスポート、セッションの attach とキャッシュ(2 秒 TTL・自動再 attach)、バッファ付きイベントキュー(1 万件上限)、JS ダイアログ追跡を担う。
  • src/element-resolver.ts — @N ref、loc=css:/loc=role:/loc=href:、xpath=、生 CSS のすべてを解決し、失敗を transient(再試行可)/permanent に分類する。
  • src/ref-map.ts + src/ref-state.ts — ref は数値の backendNodeId(@21 であって @e21 ではない)。マップは Snapshot ごとに再構築され、空のときに ref を使うと自動再 Snapshot が走る。これが heredoc をまたいで ref を機能させる。
  • src/driver/ — nav(タブ・遷移)、pointer(クリック・スクロール・ドラッグ)、keyboard、observe(snapshot・screenshot)、waits、files(アップロード)、element-ops、load。
  • src/learning/ — サイト別スキルの発見・検証・実行。learnings/<site>/manifest.json から runSiteTool/runSiteBrowserTool/learnContext を提供する。
ドキュメントは JSDoc 由来: src/help-runtime.ts がビルド済みバンドルの JSDoc を acorn で実行時にパースして help() を駆動する。公開ヘルパーの JSDoc はそのままユーザー向けドキュメントになる。
3 — セットアップと最初のタスク

インストール方法は 3 通り。どれを選んでも、ego lite は自分のマシン上の各エージェントの skills ディレクトリに ego-browser スキルを追加する。

1

Apple Silicon / Intel 版の .dmg をダウンロードして開き、インストールする。初回起動時に Chrome データを移行するか一度だけ聞かれ、はいと答えると既存のログイン・Cookie・拡張・ブックマークをエージェントが引き継ぐ。

2
shell
npx skills add citrolabs/ego-lite

エージェントが初めてブラウザタスクを走らせるとき、ego lite アプリのインストールを案内する。

3

エージェントに ego lite のセットアップを依頼し、skills/ego-browser/references/install.md を読ませて手順どおりに導入させる。

エージェント CLI で /ego-browser に続けて、やりたいことを自然言語で書く。エージェントは ego-browser スキルを拾い、専用の Space でページを開き、Snapshot を読み、操作して結果を報告する。その間ユーザーのタブは触られない。閲覧データは端末に残り、ego lite が記録するのは Chrome 移行に同意したかどうかだけ。

ブラウザ作業は Bash ツールから ego-browser nodejs <<'EOF' ... EOF の形で実行する。heredoc に JavaScript を直接置き、.js ファイルを作らず、Playwright を import せず、別のブラウザを起動しない。page・page.locator(...)・browser・taskSpaces・site・fetch・cdp がプリロード済みで使える。

ego-browser nodejs(heredoc)
ego-browser nodejs <<'EOF'
const task = await taskSpaces.useOrCreate('inspect example page')
await browser.openOrReuseTab('https://example.com', { wait: true, timeout: 20000 })

const heading = await page.getByRole('heading').first().innerText()
const info = await page.info()
if (!heading || !('url' in info)) throw new Error('Example page was not ready')

const result = { taskSpaceId: task.id, heading, url: info.url }
console.log(JSON.stringify(result, null, 2))
EOF

予測できる観測・操作・待機・抽出・検証は、すべてスクリプト内に書ききってからタスクを完了させる。最終結果は console.log(...) で出す。

4 — ego-browser ランタイム

プリロードされるファサードは Playwright スタイルの名前と呼び出し形に従う。taskSpaces・site・fetch・cdp は ego-browser 固有の機能を提供する。

ファサード主な責務
page遷移と状態(goto, reload, url, title, info)、セマンティックロケータ、待機、snapshot, screenshot, screencast, evaluate, keyboard, mouse, ダウンロード、イベント排出。
page.locator(selector)チェーンとフィルタ、first/nth/last、click・hover・dragTo・scrollIntoViewIfNeeded、フォーム、キーボード、アップロード、状態読み取り、コレクション、要素評価、スクリーンショット、待機。
browserlistTabs, currentTab, switchTab, openOrReuseTab, closeTab, ensureRealTab, iframeTarget。
taskSpaceslist, switch, new, useOrCreate, claim, complete, handOff, takeOver, waitForAgentControl。
fetchfetch.server は Node 側リクエスト、fetch.browser は現在ページのオリジンでのリクエスト。
cdpファサードで覆えない機能のためのエスケープハッチ。
console.log出力チャネル。署名が不明なときは help('page') や help('locator') を出力して確認する。
  • セマンティック(snapshot + ロケータ): 通常の DOM ページ向け。page.snapshot() で観測し、セマンティックロケータ・現コマンドの @N ref・安定した loc=... 値で操作する。
  • ビジュアル(screenshot + mouse/keyboard): canvas・仮想化エディタ・表計算・地図・AX の弱い面向け。本格編集の前に小さな書き込みプローブを打ち、スクリーンショットや readback で検証する。
  • 直接 DOM/CDP: 要素コレクションは locator.evaluateAll(fn, arg)、ページ全体の状態は page.evaluate(fn, arg)。ファサードで覆えない能力にだけ生 CDP を使う。

次の入力がスクリプト内で得られる限り、これらの経路は同じ Bash 実行の中で組み合わせる。

5 — 実行の原則

heredoc は JavaScript の容器にすぎず、Bash の呼び出しが実行の 1 ラウンド。ブラウザタスク全体を既定で 1 回の Bash 実行にまとめる。各 await は内部操作でありステップ境界ではない。起動前に、予測できる観測・操作・待機・抽出・検証・限定的な代替手段をすべてスクリプトに書き込む。中間出力を見たり次の手を計画したりするためだけに抜けない。別コマンドを始めるのは、ユーザー/外部制御が要るとき、スクリプト内でできない目視検査が要るとき、スクリプトが回復できないプロセスレベルの失敗のときに限る。

  • page.url() は非同期。常に await page.url() を使う。page.waitForURL(...) の述語は URL オブジェクトを受け取るので url.href / url.pathname / url.searchParams を見る。
  • waitForURL / waitForLoadState / waitForSelector / ロケータの waitFor / waitForFunction はタイムアウト時に falsy を返す。結果を確認するか、続行前に必要な状態を検証する。
  • request / response / navigation の待機は、それを引き起こすアクションの前に登録する。状態ベースの待機を優先し、waitForTimeout(...) は軽い表示落ち着き用にとどめ 2000ms 以下にする。
  • 安定したセマンティックロケータを優先する。構造が不明なときは evaluateAll / allInnerTexts で候補を一度に集め、次の手を JavaScript で導き、同じ heredoc 内で続ける。
すでに満たされた事後条件は完了扱い: 「set」「select」「ensure」などは、ユーザーが遷移そのものを要求しているか操作自体がテスト対象でない限り、必要な最終状態を指す。一致していれば、エディタを開き直したり操作を再生したりしない。@N ref は最新 Snapshot 以降のみ有効で、コマンドが終わると再 Snapshot が必要。
6 — Task Space と制御ハンドオフ

Task Space は自分のタブを持つ隔離ブラウジングコンテキストで、ユーザーのログイン状態を継承する。最初のスクリプト冒頭で taskSpaces.useOrCreate(nameOrId) により一度選ぶ。以降のコマンドでは同じ数値 task.id か同一の短いゴール名を使い、別ゴールのときだけ新規に作る。各 Space は ownership: 'agent' | 'agentDelegatedToUser' | 'user' を持つ。

user 所有 Space への操作挙動
taskSpaces.switchthrow する(agent 所有の Space だけ切り替える)
taskSpaces.claim所有権を agent へ移し、その Space を選ぶ
handOff / complete(..., { keep: true }){ done: false, skipped: 'user-owned' } でスキップ
complete(..., { keep: false })claim してから Space を閉じる
takeOver / waitForAgentControl所有権チェックを行わない

完了はブラウザ実行とは別の終端コミットとして扱う。作業側の Bash 実行は、最終 URL・値・その他の証拠を出力してから完了させずに終える。その出力を見て、要求された事後条件と必要な範囲・網羅境界がすべて証明されていれば、page や browser を触らない専用の最終 Bash 実行で taskSpaces.complete(nameOrId, { keep }) を一度だけ呼び、done を確認する。未達・未証明なら、同じ Task Space で作業を続ける。keep は必須で既定は false、ユーザーが完成ページを残したい・手動操作が要る・URL やファイルで結果を渡せないときだけ true にする。

制御ハンドオフ: 「user is controlling」「inactive」「not assigned」エラーはタスク全体のハードストップ。自動で takeOver せずユーザーに尋ねて待つ。ログインや captcha などの手動ステップでは、安全な準備を済ませて taskSpaces.handOff([nameOrId]) を呼び、done を確認し、ユーザーに手順を伝える。明示的な確認の後にだけ takeOver/claim で再開する。
7 — 既存プロダクトとの比較

多くのツールはブラウザを自動化できる。問われるのは、エージェントが得るブラウザは何か、ユーザーが同時に作業を続けられるか、そのツールが手持ちのエージェント向けか組み込みエージェント向けか、である。ブラウザ自動化フレームワーク(Browser-Use、Vercel の agent-browser)はエージェントが呼ぶライブラリで、自前のブラウザを持たず駆動用に別ブラウザが要りログインが引き継がれにくい。AI ブラウザ(ChatGPT Atlas、Perplexity Comet)は組み込みエージェントを積み、そのエージェントしか駆動できない。ego lite は、最初から人と任意のエージェントが共有する 1 つのブラウザ。

能力ego liteBrowser-Useagent-browserChatGPT AtlasPerplexity Comet
並行マルチタスク✓————
再利用できるスキル✓————
Chrome データを継承✓——✓✓
同じブラウザ・別ワークスペース✓————
圧縮したセマンティック入力✓—✓——
外部エージェントから制御可✓✓✓——
データをローカル保存✓✓✓——
ログイン摩擦なし✓——✓✓
日常使いのブラウザ✓——✓✓
無料✓✓✓——
ベンチマーク: 4 つの複雑なブラウザ自動化タスクで Vercel の agent-browser と比較し、ego lite は各タスクを最大 2.5× 速く、トークン消費も大幅に少なく完了した。タスクが難しいほど差が広がる。

スキルの正は ego lite リポジトリ内の skills/ego-browser/SKILL.md(エージェント向けの利用契約)。ハーネスの構成やヘルパー面は package/ego-browser/README.md と AGENTS.md に詳しい。