scriptc v0.4.9
→ Typed-array loops 1.83x faster
→ 10M console.log lines in 0.54s
→ No-change rebuilds in 17ms
→ Windows hello world: 146KB, from 1.8MB
Plus node:dns, more child_process, and a lot more TypeScript compiles
npm i -g scriptc
github.com/vercel-labs/scriptc/releases/tag/v0.4.9
72 likes · 3 reposts · 3,353 views
In less than a week, agent-desktop went from 1.8K to 16.4K stars
It's now the 5th most popular Vercel Labs repo
Congrats @mdlahfir
Star it: vercel-labs/agent-desktop t.co
125 likes · 3 reposts · 5,235 views
スクショを使わずにデスクトップアプリを操作する agent-desktop の仕組み
グラレコ
!agent-desktop の要点をまとめたグラレコ。部品の木を読む、ref で指す、読む→操作→読み直す、迷ったら止まる、マウスを奪わない、やり直してよいかの判断、大きいアプリは骨組みから、3つの OS と MCP の8項目と、基本の流れ
最初に、この記事の内容を1枚の絵にまとめました。①〜⑧が本文で取り上げる話題に、下の矢印が基本の使い方の流れに対応しています。
はじめに
agent-desktop は、Vercel Labs が公開しているオープンソースのツールです。AI エージェントが macOS・Windows・Linux のデスクトップアプリを「見て」「操作する」ための CLI と C ライブラリで、Rust で書かれています。
特徴は、スクリーンショットやピクセルの照合を使わないところです。OS が持っているアクセシビリティツリー(画面の部品を木の形に並べた情報で、スクリーンリーダーが読み上げに使うものと同じです)を読み、JSON にして返します。操作できる部品には ref という番号が付き、エージェントはその番号を指定してクリックや入力をします。
もう1つの特徴は、agent-desktop の中に言語モデルが入っていないことです。「読む → 操作する → 読み直して確かめる」というループを回すのは、呼び出す側のエージェントやスクリプトです。agent-desktop は、そのループの中で呼ばれる道具という位置づけです。
| 項目 | 内容 |
| --------------- | ------------------------------------------------------------------- |
| 提供 | Vercel Labs(GitHub: vercel-labs/agent-desktop) |
| 形態 | CLI(agent-desktop)と C ライブラリ(libagent_desktop_ffi) |
| 対応 OS | macOS 13 以降 / Windows 10 1809 以降 / Ubuntu 24.04 以降 |
| ライセンス | Apache-2.0 |
| 最新版 | 1.2.0(2026-11-05)。このリリースで MCP サーバーが加わりました |
| GitHub のスター | 約1.6万(2026年11月5日時点) |
この記事では、README・公式ドキュメント・同梱のスキル(エージェント向けの手引き)をもとに、仕組みと使い方を整理します。筆者の手元で動かした記録ではなく、ドキュメントを読んで分かったことのまとめです 📚。AI エージェントにデスクトップアプリを触らせたい方や、computer use の実装方式に関心のある方に向けて書いています。
スクリーンショット方式との違い 📸
デスクトップを AI に操作させる方法としてよく知られているのは、画面のスクリーンショットをモデルに見せて、クリックする座標を答えさせるやり方です。agent-desktop は、そこを OS の部品情報に置き換えています。
次の図は、2つの方式で「ボタンを押す」までの流れを並べたものです。
flowchart LR
A1["画面を撮影"] --> A2["モデルが画像を見る"] --> A3["ボタンの座標を推測"] --> A4["座標をクリック"]
B1["部品の一覧を読む<br>snapshot"] --> B2["JSON で受け取る<br>ボタンに ref"] --> B3["ref を指定<br>click"] --> B4["部品に用意された<br>操作を呼ぶ"]
上の段がスクリーンショット方式、下の段が agent-desktop です。下の段には「座標を推測する」工程がなく、エージェントは JSON に書かれた ref をそのまま指定します。
違いを表にまとめると、次のようになります。
| 観点 | スクリーンショット方式 | agent-desktop |
| ------------ | ------------------------ | ----------------------------------------- |
| 何を見るか | 画面の画像 | OS のアクセシビリティツリー(JSON) |
| どう指すか | 画面上の座標 | 部品ごとの ref(例: @s8f3k2p9:e8) |
| 操作の手段 | マウスとキーボードの入力 | 既定では部品に用意された操作を API で呼ぶ |
| 見えないもの | 画面に映っていないもの | アクセシビリティツリーを公開していない UI |
最後の行は、使う前に知っておきたい制約です。agent-desktop はピクセルを見ないので、アクセシビリティツリーを公開していないアプリは見えません(スクリーンショットを撮る screenshot コマンドはありますが、ref を使う操作とは別物です)。
また、対象はデスクトップアプリだけで、Web ページの自動操作は守備範囲の外です。Web ページには同じ Vercel Labs の agent-browser を使います。Chromium や Electron 製のアプリを agent-desktop から起動した場合は、DevTools のポートを開いて、Web の中身を agent-browser から操作できるようにする連携も用意されています。
仕組み:エージェントから OS の API まで 🧱
全体の構成を図にしました。上から下に向かって呼び出しが進みます。
!agent-desktop の構成図。呼び出し側のエージェントが CLI か C ライブラリを呼び、どちらも agent-desktop-core を通る。core は PlatformAdapter だけを通して OS に触れ、ビルド時に選ばれた macOS・Windows・Linux のいずれかの実装が、AX API・UI Automation・AT-SPI で対象アプリのアクセシビリティツリーを読む
図の読み方は次のとおりです。
- 入口は2つあります。CLI は1回の実行ごとに JSON を1つ出力して終わります。C ライブラリは、自分のプログラムの中から同じ機能を呼ぶためのものです。1.2.0 からは agent-desktop mcp で MCP サーバーとしても動きます。
- agent-desktop-core には、コマンドの処理、スナップショットの作成、ref の保存(RefStore)が入っています。
- PlatformAdapter(オレンジの枠)は、core が OS に触れるための唯一の窓口です。core は OS ごとの実装を直接読み込まず、必ずここを通ります。
- OS ごとの実装は、ビルド時にどれか1つだけが組み込まれます。点線の矢印はその意味です。そのため、配布されるバイナリは「macOS 用」「Windows 用」のように OS ごとに分かれています。
それぞれの OS で使うアクセシビリティ API と、動作の条件は次の表のとおりです。
| OS | 必要な環境 | 使う API |
| ------- | ----------------------------------------------------------------------------------------------------- | ------------- |
| macOS | macOS 13 以降(Intel / Apple Silicon)。agent-desktop を起動するアプリにアクセシビリティの権限が必要 | AX API |
| Windows | Windows 10 1809 以降、または Windows Server 2019 以降(x64 / ARM64) | UI Automation |
| Linux | Ubuntu 24.04 以降(x86_64 / aarch64、glibc 2.35 以上)、X11 か Wayland、AT-SPI が動いているセッション | AT-SPI |
コマンド名は3つの OS で共通です。ただし、どの操作が画面に触れずにできるかは OS ごとに違うので、公式ドキュメントには OS 別のページがあります。
基本のループ:読む → 操作する → 読み直す 🔁
README のクイックスタートは、次の3行です(Finder を例にしています)。
agent-desktop snapshot --app Finder -i # 操作できる部品を、ref 付きで読む
agent-desktop click @s8f3k2p9:e8 # そのスナップショットの ref を指定して押す
agent-desktop snapshot --app Finder -i # もう一度読んで、結果を確かめる
-i は、ref の付かない末端の部品を省いて、操作できる部品とその親だけを残すオプションです。1回目の snapshot は、次のような JSON を返します(README に載っている例をそのまま引用しています。README の時点で一部が省略されています)。
{
"version": "2.6",
"ok": true,
"command": "snapshot",
"data": {
"app": "Finder",
"snapshot_id": "s8f3k2p9",
"ref_count": 59,
"complete": true,
"tree": {
"role": "window",
"name": "Downloads",
"children": [
{ "role": "treeitem", "name": "Documents", "ref_id": "@s8f3k2p9:e8", "available_actions": ["Click"] }
]
}
}
}
role が部品の種類、name が部品の名前、ref_id がエージェントが指定する番号です。available_actions を見れば、その部品で何ができるかも分かります。人間が画面を見て「Documents という項目がある」と判断する部分を、エージェントはこの JSON から読み取ります。
1回の操作でエージェントと agent-desktop がどうやり取りするかを、シーケンス図にしました。
sequenceDiagram
participant E as エージェント
participant D as agent-desktop
participant P as 対象アプリ<br>(OS の API 経由)
E->>D: snapshot --app Finder -i
D->>P: アクセシビリティツリーを読む
D-->>E: JSON(部品と ref)
E->>D: click @s8f3k2p9:e8
D->>P: ref の部品を探し直して押す
D-->>E: JSON(結果と disposition)
E->>D: snapshot または wait
D->>P: もう一度読む
D-->>E: JSON(変わった後の画面)
Note over E: 期待どおりなら次へ<br>違えば判断し直す
図の最後で、エージェントはもう一度画面を読んでいます。公式ドキュメントには「アクションが成功したという返事は、UI が変わったことの証明にはならない。だからループは読み直しで終わる」という趣旨の説明があります。押したつもりでも画面が変わっていないことはあるので、確認までを1セットにしています。
公式ドキュメントの導入ページには、電卓アプリで「7」を押して表示を確かめる、4つのコマンドの例も載っています。
agent-desktop snapshot --app gnome-calculator --skeleton -i --compact # 1. 全体の骨組みを読む
agent-desktop snapshot --root @s2txcl95uvubmn:e1 -i --compact # 2. 一部分を詳しく読む
agent-desktop click @s2txcl95uvubmn:e11 # 3. 「7」のボタンを押す
agent-desktop wait --element @s2txcl95uvubmn:e6 --predicate value --value 7 # 4. 表示が 7 になるのを待つ
4行目の wait は、条件を満たすまで待つコマンドです。決め打ちの sleep で待つと、アプリの反応が遅いときに確認がずれてしまうので、同梱のスキルでも wait を使うように書かれています。
ref の決まりごと 🏷️
ref は @<スナップショットID>:e<番号> という形をしています。@s8f3k2p9:e8 なら「スナップショット s8f3k2p9 で8番目に ref が付いた部品」という意味です(ref は木を深さ優先でたどる順に振られます)。番号だけの @e8 を渡すと、INVALID_ARGS で受け付けてもらえません。
ref が付くのは、基本的には操作できる部品です。ボタン・テキスト入力欄・チェックボックス・リンク・メニュー項目・タブ・スライダーなどの種類か、主な操作を持っている部品が対象で、ただの文字や何の操作も持たない入れ物には付きません。例外は、後で出てくる「骨組み」の読み方で途中まで読んだ入れ物で、掘り下げる先として ref が付くことがあります。
ref はそれを発行したスナップショットの中でだけ使えます。画面が変わったあとに古い ref を使うと、次のように扱われます。
flowchart TD
A["snapshot で ref を発行"] --> B["ref を指定して操作"]
B --> C{"部品を探し直す"}
C -->|1つに決まる| D["操作を実行"]
C -->|見つからない| E["STALE_REF"]
C -->|候補が複数| F["AMBIGUOUS_TARGET"]
E --> G["新しい snapshot を取って<br>その ref で操作し直す"]
F --> H["別の部品・ウィンドウを<br>指定して取り直す"]
ここで効いているのが、操作の直前に部品を探し直す仕組みです。agent-desktop は、ref が指していた部品が今も同じものかを確かめてから操作します。確信が持てないときは、推測で別の部品を押したりせず、エラーを返して止まります。
確かめ方は OS で違います。macOS では、ref が部品そのものの参照を持っているので、見た目がそっくりな部品が並んでいても1つずつ区別できます。Windows と Linux では、スナップショットを撮った時点でウィンドウの中に1つしかなかった部品で、今も1つだけ一致するものに限って操作します。そっくりな部品が複数あると AMBIGUOUS_TARGET になるので、別の手段を考えることになります(同梱のスキルでは、ウィンドウの中で他と区別できる部品を操作するように書かれています)。
もう1つ、ref を使った操作には待ち合わせが組み込まれています。対象の部品が操作できる状態になるまで、既定で最大5秒(type は1文字ごとに30ミリ秒を足した時間)待ってから実行し、間に合わなければ TIMEOUT を返します。--timeout-ms 0 を付けると、待たずに1回だけ試します。
大きなアプリは骨組みから読む 🗺️
Electron 製のアプリや IDE のように部品の多いアプリだと、アクセシビリティツリーの部品が数千個になることがあります。全部を一度に読むと時間がかかり、エージェントに渡すトークンも増えます。そこで agent-desktop には、「まず骨組みだけ読んで、必要な場所だけ掘り下げる」読み方が用意されています。
flowchart TD
S["snapshot --skeleton -i --compact<br>深さ3までの骨組みを読む"] --> P["children_count と ref_id の<br>両方を持つ部品を選ぶ"]
P --> R["snapshot --root その ref -i --compact<br>その部分だけ読む"]
R --> A["読んだ ref で操作する"]
A --> V["wait / get / 同じ --root で<br>読み直して確かめる"]
V -->|別の場所が必要| R
V -->|レイアウトが変わった| S
--skeleton を付けると、読む深さが3段までになります。そこで打ち切られた入れ物には children_count(子の数)が付くので、どこに中身があるかが分かります。次に --root でその入れ物を指定すると、その部分の部品が同じスナップショットに追加されます。
小さいアプリなら、骨組みを経由せずに snapshot -i で全体を読めば十分です。探したい部品の種類や名前が決まっているなら、find で直接探す方法もあります。
なお、--root で読む量そのものが減るのは macOS だけです。Windows と Linux では、部品を探し直すためにウィンドウ全体を読み直したうえで、その部分だけを返します。ただし、エージェントが受け取る JSON はどの OS でも指定した部分だけなので、トークンを抑える効果は同じように得られます。
画面を奪わない:既定は画面に触れないモード 🖱️
agent-desktop の ref 操作は、既定では headless(画面に触れないモード)で動きます。部品に用意された操作をアクセシビリティ API で呼ぶだけで、フォーカスを奪わず、マウスカーソルも動かさず、キー入力の合成やクリップボードも使いません。人がパソコンを使っている横で動かしても邪魔をしない、という考え方です。
物理的な入力(カーソルを動かす、キーを打つなど)を使いたいときは、--headed を付けて許可します。
| 項目 | 既定(headless) | --headed を付けたとき |
| -------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| フォーカス | 奪わない | 対象のウィンドウを前面に出してよい |
| マウスカーソル | 動かさない | 動かしてよい |
| キー入力の合成 | しない | してよい |
| 物理入力の扱い | 使わない。API で操作できなければエラーで止まる(ACTION_NOT_SUPPORTED、POLICY_DENIED など) | 使ってよい。実際に使うかは OS と操作ごとに決まり、check・set-value・expand はどの OS でも API 経由のまま |
どの OS でも --headed が必要なのは、triple-click・hover・drag・mouse-move・mouse-click・mouse-wheel です。double-click も基本的には必要ですが、macOS で部品が「開く」操作を持っている場合は不要です。
同梱のスキルには、「headless で失敗したからといって、--headed に切り替えて回復しようとしないこと」とはっきり書かれています。--headed は、ユーザーが物理入力を明示的に許可したときだけ使うものです。エージェントが自分の判断でマウスを動かし始めると、人が作業中のウィンドウを横取りしかねないので、ここは守っておきたいところです。
失敗したときの判断:disposition を見る 🚦
agent-desktop のコマンドは、成功しても失敗しても JSON を1つ返します。失敗したときは ok: false になり、error の中に理由が入ります。公式ドキュメントに載っている例を、一部省略して引用します。
{
"version": "2.6",
"ok": false,
"command": "click",
"error": {
"code": "SNAPSHOT_NOT_FOUND",
"message": "Snapshot 's3tufs86hddhyl' not found",
"recovery": {
"strategy": "refresh_snapshot_then_retry_original",
"retryable": true,
"requires_fresh_snapshot": true
},
"disposition": { "delivery": "not_delivered", "retry": "safe" }
}
}
エージェントの分岐に使うのは、error.code と error.disposition です。message や suggestion の文言は変わることがあるので、そこで条件分岐してはいけないとドキュメントに書かれています。
中でも見ておきたいのが disposition で、「入力がアプリに届いたかどうか」と「やり直してよいかどうか」を表しています。
- delivery が not_delivered(何も届いていない)のときだけ、retry が safe になります。
- それ以外(retry が unsafe か unknown)は、操作が届いた可能性があります。もう一度同じ操作をすると、2回クリックや2回入力になったり、toggle なら元に戻ってしまったりします。
この判断の流れを図にしました。
!アクションが失敗したときの判断フロー。結果を受け取り、成功なら読み直して確かめる。失敗なら disposition.retry が safe かを見て、safe なら原因を直してやり直す。unsafe か unknown なら画面の状態を読み、状態を見て次の手を決める
オレンジのひし形が、一番大事な分かれ道です。unsafe や unknown のときは同じ操作を繰り返すのではなく、get・is・新しいスナップショットで今の画面を読んでから次を決めます。結果に details.post_state が入っていれば、それも手がかりになります。
エラーコードは全部で16種類あります。よく出てきそうなものを抜き出しました。
| コード | 意味 | 対応 |
| ---------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| STALE_REF | ref の部品がもう存在しない・一致しない | 新しいスナップショットを取って、その ref を使う |
| AMBIGUOUS_TARGET | 一致する部品・ウィンドウが複数あり、選べない | 別々の部品なら find・--root・--window-id で絞る。macOS 以外では、そっくりな部品を ref で選び分けることはできない |
| SNAPSHOT_NOT_FOUND | スナップショット ID が見つからない(期限切れ・別セッション) | 同じセッションでスナップショットを取り直す |
| POLICY_DENIED | headless のまま物理入力が必要な操作をしようとした | モードを切り替えて回復しようとしない |
| PERM_DENIED | OS の権限(アクセシビリティなど)が足りない | agent-desktop permissions で確認して許可する |
| TIMEOUT | 待ち時間の上限を超えた | details.kind を読み、retry が safe のときだけやり直す |
エージェントへのつなぎ方 🔌
インストールは npm から行います。Bun・Yarn・pnpm でも同じパッケージを入れられ、macOS と Linux なら brew install agent-desktop も使えます。
npm install -g agent-desktop
agent-desktop status # OS・権限・対応している画面の種類を表示
agent-desktop permissions --guide # macOS:アクセシビリティの権限を案内付きで設定
あとは、エージェントに使い方を覚えさせます。方法は次の図の4通りです。
flowchart LR
E["エージェント"] --> K["スキルを入れる<br>npx skills add"]
E --> G["AGENTS.md に<br>手順を書く"]
E --> M["MCP サーバー<br>agent-desktop mcp"]
E --> C["C ライブラリを<br>プログラムから呼ぶ"]
K --> T["skills get desktop<br>skills get platform"]
G --> T
T --> X["CLI を実行"]
バイナリには、そのバージョン用の手引きが入っています。agent-desktop skills get desktop でループ・ref・確認・やり直しのルールを、agent-desktop skills get platform で今の OS に固有の注意を読めます。スキルとして入れる場合は、次のコマンドです。
npx skills add https://github.com/vercel-labs/agent-desktop --skill agent-desktop
AGENTS.md に書く場合、README では次の内容が紹介されています。
Use `agent-desktop` to see and operate desktop apps. Before the first use, run
`agent-desktop skills get desktop` and `agent-desktop skills get platform`, and follow them.
MCP クライアントから使う場合は、設定ファイルに次のように追加します。
{ "mcpServers": { "agent-desktop": { "command": "agent-desktop", "args": ["mcp"] } } }
ツール名はコマンド名に desktop_ を付けたもので、ハイフンはアンダースコアに、サブコマンドはつなげた名前になります(desktop_snapshot、desktop_list_windows、desktop_session_start など)。引数も同じ規則で、snapshot --app Finder -i なら desktop_snapshot に { "app": "Finder", "interactive_only": true } を渡します。--headed や --session のような全体に効くオプションは、ツールの引数では指定できず、agent-desktop mcp --headed のようにサーバーの起動時にだけ付けられます。エージェントが勝手に物理入力を許可できない作りになっているわけです。
コマンドは全部で60個あり、そのうち56個が実際に動きます。残りの key-down・key-up・mouse-down・mouse-up は、押しっぱなしのキーやボタンを確実に離せる仕組みができるまで、実行を拒否するようになっています。
| グループ | 主なコマンド |
| -------------------- | -------------------------------------------------------------------------------------------------- |
| 観察 | snapshot, find, get, is, screenshot, list-surfaces |
| ref への操作 | click, type, set-value, select, toggle, check, expand, scroll など |
| キーボード・マウス | press, hover, drag, mouse-move, mouse-click など |
| アプリ・ウィンドウ | launch, close-app, list-apps, list-windows, focus-window など |
| 通知・クリップボード | list-notifications, notification-action, clipboard-get, clipboard-set など |
| 待機・セッション | wait, session, trace, cursor-overlay |
| システム | status, permissions, version, batch, skills |
使う前に気をつけたいこと ⚠️
読み取った内容には、デスクトップの中身がそのまま入ります。 スナップショット、クリップボードの読み取り、スクリーンショット、コマンドの出力、デバッグ用のファイルには、画面に出ていた私的な情報が含まれることがあります。README の冒頭でも、公開のログやアップロードに入れないよう注意されています。エージェントの会話ログも同じ扱いにしておくのが安全です。
秘密の文字列は標準入力から渡します。 type・set-value・clipboard-set には --stdin があり、パスワードなどをコマンドの引数に載せずに済みます。batch で JSON にまとめた文字列はプロセスの引数に出てしまうので、秘密を含む手順は別のコマンドに分けるよう書かれています。
MCP サーバーは、ログイン中のユーザーのシェルと同じ扱いにします。 MCP 経由でも、アクセシビリティツリーから見えるアプリはすべて操作でき、desktop_launch は PATH 上のプログラムを任意の引数で起動できます。クライアント側の確認ダイアログは有効にしておき、画面から読んだ文字列はモデルにとって信用できない入力だと考えておきます(画面に「このボタンを押して」と書いてあるだけで押してしまうと困るので)。
権限が足りないと、空のツリーに見えます。 macOS では、agent-desktop を起動するアプリ(ターミナルなど)にアクセシビリティの権限が必要です。同梱スキルのよくある失敗の一覧にも「status と permissions の確認を飛ばす」が入っているので、最初に agent-desktop status を実行しておくと安心です。
PowerShell では ref を引用符で囲みます。 @token が PowerShell の構文として解釈されてしまうため、'@s8f3k2p9:e8' のように書きます。
更新の速いプロジェクトです。 1.0.0(2026-10-27、Linux 対応)から1.2.0(2026-11-05、MCP 対応)まで、パッチ版を含めて10日ほどで5回リリースされています。1.1.0 では JSON の形式が 2.6 に上がる破壊的な変更も入りました。記事の内容は 2026年11月5日時点のものなので、実際に使うときは agent-desktop version と同梱のスキルで最新の決まりごとを確認してください。
まとめ
agent-desktop の設計をひとことで言うと、「部品の一覧を読み、ref で指して操作し、読み直して確かめる。確信が持てないときは止まる」です。古い ref は拒否し、そっくりな部品は推測で選ばず、届いたかどうか分からない操作は繰り返させません。どれも、エージェントが人のパソコンの上で間違ったボタンを押さないための決まりごとになっています。
機能の多さよりも、disposition のように「次の一手をどう判断するか」まで JSON に書いてくれる点が、エージェントから呼ぶ道具として扱いやすいところだと感じました(エラーの文言ではなくコードで分岐してね、と念を押してくれるのもありがたいです)。
試してみる場合は、agent-desktop status で権限を確認し、agent-desktop skills get desktop の手引きを読むところから始めるのがおすすめです。Web ページも操作したいなら、姉妹ツールの agent-browser と組み合わせる形になります 🛠️
参考
- vercel-labs/agent-desktop(GitHub) — README、CONCEPTS.md、FAQ、CHANGELOG、同梱スキル(2026-11-05 時点の main)
- agent-desktop 公式ドキュメント — 導入ページ
- Skeleton and drill-down — 骨組みと掘り下げの読み方
- Errors and recovery — エラーコードと disposition
- Headed mode — headless と --headed
- Using agent-desktop over MCP — MCP サーバーの使い方
- agent-desktop(npm)
- agent-browser — Web ページ用の姉妹ツール
Vercel's agent-desktop and the Computer-Use Land Grab
On October 30, 2026, Vercel Labs quietly shipped agent-desktop — a Rust CLI and C library that lets AI agents operate any desktop application through the operating system's accessibility tree. No screenshots. No pixel-guessing. No model baked in. Just structured JSON with a ref for every clickable element.
> 📖 Read the full version with charts and embedded sources on AgentConn →
Within days, the repo had rocketed past 13,000 GitHub stars and 900 forks. That kind of velocity — roughly 3,800 stars in the first 24 hours — doesn't happen for incremental developer tooling. It happens when a project lands squarely on a nerve the industry has been pressing for months: who owns the layer between AI agents and the operating system?
That question is the real story here. Not the tool itself — though it's impressively engineered — but what its explosive reception reveals about where the computer-use infrastructure war is heading.
Chris Tate, the Vercel engineer behind the project, framed it simply: "agent-browser, for your whole computer."

View original post on X →
---
What agent-desktop Actually Is
Strip away the hype and agent-desktop is a command-line tool that does three things in a loop:
1. Snapshot — read an app's UI through the OS accessibility layer, returning a JSON tree where every interactive element has a unique ref
2. Act — click, type, scroll, or otherwise interact with a specific ref
3. Verify — take another snapshot to confirm the action landed
That's it. The agent's model runs elsewhere. The tool embeds no LLM, has no GUI, and makes no decisions. It's pure infrastructure — a bridge between an agent's intent and the operating system's native controls.
# Install globally
npm install -g agent-desktop
# Snapshot an app interactively
agent-desktop snapshot --app Finder -i
# Click a specific element
agent-desktop click @s8f3k2p9:e8
The key architectural choice: accessibility tree over screenshots. Instead of sending a 3,811-token screenshot of Apple Maps to the model, agent-desktop's region snapshot returns 273 tokens of structured JSON. In a simulated 52-step task, Vercel Labs reports total token usage of 31K versus 198K for the screenshot approach — a roughly 84% reduction.
> 📊 Token savings context: The 78–96% token reduction figures are self-reported by Vercel Labs. No independent computer-use benchmark exists yet for these claims. The savings are real in principle — structured text is always cheaper than images — but the magnitude will vary dramatically depending on how well each app exposes its accessibility metadata.
Platform support spans macOS 13+ (AX API), Windows 10 1809+ (UI Automation), and Ubuntu 24.04+ (AT-SPI), on both x64 and ARM64. The tool ships under Apache-2.0, and agent-desktop mcp exposes every command as an MCP tool over stdio — meaning any agent framework that speaks MCP can drive it without a single line of integration code.
As Dev.to coverage noted, v1.0.2 marked the formal launch — adding a docs site and consolidating all agent instructions into a single AGENTS.md file, a pattern that signals Vercel expects agent frameworks to discover and configure the tool automatically.

Read the full Dev.to walkthrough →
CellCog's technical analysis breaks down the "skeleton drilling" technique in detail: the agent maps the full window once, identifies the relevant region, then works inside that region at dramatically lower token cost. Their assessment also highlights the privacy implications — snapshots, clipboard reads, and debug output can contain sensitive desktop content, so agent transcripts should be treated as confidential.

Read CellCog's full analysis →
{% youtube qPeMxQfIavo %}
---
The Accessibility Tree Bet
To understand why this matters, you need to understand what agent-desktop is replacing.
The dominant computer-use paradigm since Anthropic introduced it in October 2024 has been screenshot-based: the agent takes a screenshot, a vision-language model interprets the pixels, and the agent clicks coordinates. This works on everything — every app, every framework, every custom-drawn canvas. It's also ruinously expensive, painfully slow, and fundamentally brittle. A button that moves three pixels between frames breaks the entire chain.
Agent-desktop flips the model. Instead of asking a VLM "what's on screen?", it asks the OS "what elements exist and what can I do with them?" The accessibility tree — originally built for screen readers and assistive technology — provides exactly the structured metadata that agents need: element roles, labels, states, and actionable refs.
{% youtube wf2QPobtUqU %}
The practical advantages are significant:
- Headless by default. Ref actions don't move the physical pointer or take focus, so an agent can work while you use the same machine. Multiple agents can operate different apps simultaneously, each with its own cursor.
- Deterministic targeting. Clicking ref @s8f3k2p9:e8 always hits the same element, regardless of window position, DPI scaling, or display configuration. No coordinate math, no off-by-one pixel errors.
- Error semantics. Failed actions return structured errors like STALE_REF or AMBIGUOUS_TARGET with retry dispositions — the agent knows why something failed and whether retrying is safe.
- Token efficiency. Text-based snapshots cost a fraction of what image-based screenshots require. At scale, across thousands of agent invocations per day, this is a material cost difference.
But the accessibility tree comes with a fundamental limitation: it only works when apps actually expose their UI through accessibility APIs. And that's where the contrarian case gets interesting.
---
The Landscape: Who's Fighting for This Layer
Agent-desktop didn't emerge in a vacuum. The computer-use infrastructure space has been heating up all year, with every major player staking a claim.
The model providers are building vertically:
- Anthropic shipped Dispatch, their consumer desktop agent product, combining local computer-use with mobile delegation. Claude's Computer Use went from under 15% OSWorld accuracy in late 2024 to 72.5% in early 2026.
- OpenAI launched Operator (browser-first, January 2025), then extended desktop control into Codex with macOS support in April 2026. Sam Altman framed their latest as "a new era of computer use."
- Google has Gemini Computer Use in preview, plus Project Mariner for browser automation.

View original post on X →
The infrastructure players are building horizontally:
- Vercel Labs now has both agent-browser (web, 33K+ stars) and agent-desktop (native apps, 13K+ stars) — a full-stack computer-use toolkit that covers everything from the browser DOM to native OS controls.

View original post on X →
- Cua (formerly Computer Use Agent) ships Cua Driver, an open-source framework that returns accessibility tree and screenshots together, with the agent trying accessibility actions first and falling back to pixel clicks.
- UI-TARS Desktop from ByteDance takes the VLM-native approach, using a specialized vision model trained specifically for UI interaction.
- Deck positions itself as the enterprise infrastructure layer — authentication, governance, session management, and audit trails for computer-use agents at scale.
The market tells the story: computer-use agents are projected to grow from a $7.8B market in 2026 to over $52B by 2030, according to Deck's industry analysis.

Read Deck's full State of Computer Use report →
{% youtube wflNENRSUb4 %}
---
The Infrastructure Thesis: Why Vercel, Not Anthropic, Might Win This Layer
Here's the non-obvious take: the model providers are building computer-use the wrong way around.
Anthropic's Dispatch, OpenAI's Codex, and Google's Mariner all bundle computer-use into their model products. You get computer-use when you use their model. The capability is tightly coupled to the provider. Switch models and you lose desktop access.
Vercel is doing the opposite. Agent-desktop is model-agnostic infrastructure. It doesn't care whether you're running Claude, GPT, Gemini, Llama, or a fine-tuned open model. The tool returns JSON; the model interprets it.
This mirrors a pattern we've seen before in the agent stack:
| Layer | Model-Coupled | Infrastructure |
|-------|--------------|----------------|
| Code generation | GitHub Copilot (GPT) | Claude Code, Cursor (model-agnostic) |
| Browser automation | Operator (GPT) | Agent-browser, Playwright (model-agnostic) |
| Desktop automation | Dispatch (Claude), Codex (GPT) | agent-desktop (model-agnostic) |
The infrastructure play tends to win over time because it lets practitioners swap models as capabilities shift — and in 2026, capabilities are shifting fast.
> 🎯 The Vercel playbook: Build the infrastructure layer that every agent needs, give it away as open source, and capture value through the deployment platform (Vercel's core business). Agent-browser did this for the web; agent-desktop extends it to the entire OS. Same strategy, bigger surface area.
---
What the Community Is Saying
The Hacker News thread (99 points, 44 comments) for a similar accessibility-tree desktop tool surfaced the debates that will define this category.

View full discussion on Hacker News →
The cross-platform reality check dominated the thread. While agent-desktop claims macOS, Windows, and Linux support, commenters pushed back hard on Linux's AT-SPI implementation. One commenter noted AT-SPI support is "very hit or miss, mostly miss."
The custom UI problem is the elephant in the room. macOS apps don't have to implement accessibility APIs. Zoom's custom-drawn controls, game UIs, and Electron apps with lazy-loaded content all expose partial or broken accessibility trees.
But the momentum is real. Multiple commenters reported building nearly identical tools. When several independent developers converge on the same abstraction at the same time, that's a strong signal that the pattern is correct.
---
The Contrarian Corner: Why Screenshots Might Still Win
> ⚠️ The case against the accessibility tree: Structured data is cleaner, but coverage is the killer constraint. The best data in the world is useless if it only describes 60% of the UI your agent needs to interact with.
Here's the uncomfortable truth about the accessibility tree approach:
Most software is accessibility-incomplete. Despite decades of accessibility standards, the majority of desktop applications expose fragmented or empty accessibility trees.
VLMs are getting cheaper faster than apps are getting more accessible. The cost of processing a screenshot has dropped roughly 10x in the past 18 months.
The hybrid approach is already standard. Cua Driver returns both the accessibility tree and a screenshot for every observation. The agent tries structured actions first and falls back to pixel clicks when the tree is sparse.
The honest assessment: agent-desktop's pure accessibility-tree approach is correct for the apps it covers and insufficient for the apps it doesn't.
---
What This Means for You
If you're building agents that interact with desktop applications, here's what to evaluate now:
1. Test agent-desktop against your actual target apps. Run agent-desktop snapshot --app YourActualApp -i and check what the tree exposes.
2. Architect for hybrid from day one. The winning pattern is accessibility tree first, screenshot fallback second.
3. Pay attention to the MCP integration. Agent-desktop exposing itself as an MCP server means any MCP-compatible agent framework can drive desktop apps with zero integration code.
4. Watch the token economics, but don't over-index. The 78–96% savings sound dramatic, but the real question is cost-per-successful-task.
5. Track the benchmarks. Computer-use accuracy went from under 15% to 72.5% in 18 months — but it's still far from reliable for mission-critical workflows.
---
The Bottom Line
Vercel's agent-desktop is the sharpest articulation yet of a thesis that's been building all year: computer-use is infrastructure, not a model feature.
The 13,000-star explosion isn't just developer enthusiasm for a well-built Rust CLI. It's a vote for a future where the layer between agents and operating systems is open, model-agnostic, and composable.
Whether the accessibility tree or screenshots or some hybrid wins the implementation debate is almost secondary. The structural question — does computer-use belong to the model layer or the infrastructure layer? — is being answered in real-time by where developers are putting their stars and their production dependencies.
Right now, the infrastructure layer is winning. And Vercel just made the strongest open-source bid to own it.
---
For more on the computer-use agent landscape, see our coverage on AgentConn.
Originally published at AgentConn
1 reaction
OSのアクセシビリティツリーを経由してAIエージェントにデスクトップ操作をさせるツールっぽい
画面の要素を直接認識できるからGUIの自動化テストとかで使えそうかな
yug1224 starred vercel-labs/agent-desktop
vercel-labs/agent-desktop
3 likes
pingpad: table tennis in the browser, with your phone as the paddle
---
title: pingpad: table tennis in the browser, with your phone as the paddle
published: true
description: How pingpad turns a phone into a paddle over WebRTC: swing recognition on the phone, guiding the player between two devices, and Playwright tests for both.
tags: webrtc, gamedev, webdev, typescript
cover_image: dev-to-uploads.s3.us-east-2.amazonaws.com
Use a ratio of 100:42 for best results.
published_at: 2026-11-03 12:45 +0000
---
pingpad is a table tennis game that runs in the browser. You open pingpad.app on a laptop, a tablet or a TV, scan the QR code with your phone, and the phone becomes your paddle. There's nothing to install and no account to create. You can play the computer, play a friend while the next players wait on the bench, or play alone and chase a record. Badges and records stay on your phone.
{% embed youtube.com %}
One of the people who tried it summed it up: "The Scan'n Play side of it works really well. No install, no questions, no pesky app store. I love it."
This article is about how it's built: a phone and a screen talking peer to peer, a swing recognised on the phone rather than tracked, a lot of work spent on guiding the player between two devices, and the library it all sits on.
It started with a counter
In 2019 I wrote a WebRTC proof of concept: a counter shown on one screen and driven from a phone. You snapped a QR code and updated the counter in real time. The goal was to go a bit further than the usual WebRTC exercises.
In 2022 it became webrtc-remote-control, an open source library for what any app runs into once a phone drives another screen: reconnections, page reloads, phones going to sleep, a remote that has to find its screen again. I had demos, the counter and an accelerometer moving a 3D object, and they worked. What I lacked was a game idea.
At the end of September 2026 I started on pingpad with AI coding agents. The library already handled the most critical part, the link between the phone and the screen, so I could build the game on top of it. The React and Vue bindings each come with an llm.md guide, written so that a coding assistant knows how to use them.
Five weeks later, pingpad has had over 200 pull requests merged.
Phone and screen, peer to peer
The phone and the screen talk over a WebRTC data channel. No game server sits between them.
Two devices still need someone to introduce them. I ported the PeerJS signaling server to Cloudflare Workers, on Durable Objects. It introduces the phone and the screen, then carries nothing. I picked Workers because the alternatives fit badly. Vercel cuts a WebSocket function after 300 seconds and bills its memory as long as the socket is open, so a screen left open would have used up the monthly quota in about a week. Render's free tier goes to sleep after 15 minutes. Cloudflare doesn't bill a hibernated Durable Object socket, so a screen waiting for players costs nothing.
STUN finds a direct path when one exists, even between a phone on 5G and a laptop on home Wi-Fi. Some networks make that impossible, such as a symmetric NAT or a corporate firewall. For those, Cloudflare's TURN relays the traffic, still DTLS-encrypted, so the relay can't read it. The screen shows whether each paddle connected over the local network, across the internet through STUN, or through the relay, something WebRTC usually hides.
On the same Wi-Fi, the median latency from phone to screen is 3.5 ms.
Recognise the swing, don't track the paddle
A phone can't tell where it is in space. Its sensors give acceleration and orientation, not position, so you can't track a paddle the way a camera would. What you can do is recognise a swing.
So the phone doesn't stream its sensors. It runs the swing detector itself, at full sensor rate, 60 times a second on iOS, and sends one compact, timestamped event when it sees a swing. The screen converts that timestamp with a clock offset it measures by pings, measured again regularly and from scratch when a paddle reconnects. Then the screen decides whether the swing hit the ball, by comparing the time of the swing with the time the ball reached the paddle. A network hiccup delays the message, but it doesn't change your shot.
I don't have a ping-pong table at home, so I recorded myself hitting foam stress balls with the back of the phone. A recorder on the phone captured each take, sensors and microphone together, and I labelled it: forehands, backhands, serves. The detector's thresholds come from those recordings, never from tuning by hand. A bench replays every recording through the detector. The detector is a pure module with no DOM dependency, so the exact same function runs on the phone and in the bench.
The microphone was there to hear the contact, and it showed that the acceleration peak doesn't mark it. Depending on how you swing, the peak can come before the ball touches the phone as well as after. That's why the screen decides the hit with a window around the ball's arrival, instead of trusting the peak.
I tuned the detector on an iPhone. It's meant to work on any recent phone, and it has played fine on Android too.
Guiding the player between two devices
A good share of the pull requests went into guiding the player, because this isn't a game where you tap your screen. You hold your phone like a paddle while the game plays on another screen, and nobody has that reflex yet. At each step, the player has to be told what to do, on the device they're looking at.
Some of the situations the game handles:
- A visitor clicks Play on their phone, when the phone is meant to be the paddle. The game explains that this device would become the screen, and offers to send the link to a computer.
- The QR code is scanned from Instagram's or Messenger's built-in browser, which won't give access to the motion sensors. The paddle says so, and how to open the page in the real browser.
- iOS only grants the motion sensors after DeviceMotionEvent.requestPermission(), called from a user gesture, on HTTPS. The paddle's button is that gesture.
- Calibration shows a phone on the screen turning as the player turns theirs, so they can see what the game sees.
- Once the ball is served, the paddle tells the player to watch the screen.
- A phone locks, goes to the background or reloads mid-match. The game pauses instead of giving the point away, and the phone finds the game again when it comes back.
- A third phone joins. It goes on the bench, in the order phones came in, and the screen calls it out by number. A player can hand over their seat, and a player who leaves keeps it until someone on the bench takes it.
- A new version is deployed during a game. The protocol is versioned, so a phone and a screen on different versions notice it and say what to do.
Each of these has a message where the player is looking, phone or screen, and an end-to-end test that replays it.
Commands work the same everywhere. Pausing, choosing the match length or turning the sound off goes through one function on the screen, whether it comes from a button, a key, or a paddle. The screen sends each paddle the commands it offers, so any player can control the game from the phone in their hand. That was the point for TVs: once the game is open, nobody has to pick up the remote and steer a cursor through the TV's browser.
Testing a game that needs two devices
pingpad has 178 end-to-end tests, and 87 of them cover these player situations. Playwright opens the screen in one browser context and each paddle in another, emulating a phone, and sends the sensor events itself. A local PeerJS server starts with the tests.
Headless Chromium draws the 3D scene on the CPU. The screen and the paddles share that CPU, drawing the screen takes most of it, and the paddles fall behind. So in end-to-end runs, the screen doesn't draw, while its frame loop still advances the rally. The tests take less CPU and finish sooner.
The same fixtures film the demo videos for pull requests and the videos on the landing page. One setup drives the tests and the videos, so when the interface changes, the videos are filmed again with the same scenarios.
Those tests are what let me change the game without replaying every scenario by hand on two devices.
Working with agents
"A game in one prompt" makes for a good demo. pingpad wasn't one. What made agents useful on it was the setup around them:
- the network layer was a library that already worked, documented for agents;
- every change goes through a pull request, and every push runs format, lint, types, unit tests, build and end-to-end tests;
- every pull request gets its own preview deployment, to try it on a real phone before it merges;
- the dev server is reachable from a phone over HTTPS on the local network, thanks to portless, since iOS only gives motion sensors to a secure page;
- a test that is written must fail when the condition it checks breaks;
- an AGENTS.md file states the architecture and the rules, and the project records the decisions it lives with as ADRs;
- every message between phone and screen is a schema, and the protocol is versioned, with each version frozen in a tested file.
I kept the design decisions, the tests on a real phone, and the approval of every merge. I wrote about how I work with AI agents on LinkedIn, in French.
What the game gave back to the library
Playing for real, with phones that lock, go to the background and change networks, turned up bugs the library's demos never showed. I fixed each one in the library rather than working around it in the game:
- On iOS, a remote stayed listed after navigating away, because Safari skips beforeunload when it puts a page in the back/forward cache. The library now listens to pagehide (0.5.1).
- A first connection whose ICE negotiation stalled waited forever (0.5.2).
- Messages that arrived before the first listener was attached were lost, which affected the React bindings (0.5.3).
- A page reloaded quickly could find its id still held by the signaling server (0.6.0).
The game's code is closed for now. webrtc-remote-control is open source under the MIT licence, with an llm.md guide for React and one for Vue: topheman/webrtc-remote-control.
Seven years after that counter, the phone has its game: pingpad.app.
I wrote this article with the help of an AI assistant, from my own notes and the project's history, and edited it myself.
2 reactions · 1 comment
Setting up Vercel Agent Desktop with Claude Code on a Mac, and where background mode stops working
Agent Desktop (vercel-labs/agent-desktop, Apache 2.0) lets Claude Code use desktop apps by reading their accessibility tree instead of screenshots. Default mode runs in the background, so no mouse movement and no focus stealing.
Setup on a Mac:
npm install -g agent-desktop
agent-desktop permissions --guide
npx skills add vercel-labs/agent-desktop --skill agent-desktop
claude --allowedTools "Bash(agent-desktop:*)"
The Accessibility permission goes to whatever app launches Claude Code (Terminal, iTerm2, VS Code). Screen Recording is only needed for the screenshot command.
Gotchas from setting it up:
- that allowedTools rule doesn’t cover commands piped into grep or head, and some of those got denied
- snapshots are JSON and get big fast. A File menu task used about 550k input tokens (mostly cached). --app, -i --compact and --root keep them down
- anything on screen in that app ends up in Claude’s context, so name the app in your prompt and keep sensitive ones closed
Where background mode worked and where it didn’t (Claude Code 2.1.316, Opus 5.5, one run per task):
- reading an app and pressing buttons: worked. Calculator 128 × 46 came back as 5,888
- filling a text field: worked, it added a line in TextEdit
- saving: not reliable. cmd+s couldn’t be confirmed, and Save was greyed out in the File menu while the window was in the background
- selecting or styling text: needs --headed, which takes over your real mouse and keyboard
Claude also handled the failures well. When an action couldn’t be confirmed or a click was refused, it said so instead of claiming it worked.
Cleanup when you’re done: npm uninstall -g agent-desktop, delete the skill folder and ~/.agent-desktop, and turn off the Accessibility permission you gave your terminal.
aiparabellum.com
3 points · 1 comment
エージェントブラウザって何? ego lite・Claude・agent-browserを比べてみた
こんにちは! 私はAIスタートアップでカスタマーサクセスとして働いています。
最近、「エージェントブラウザ」という言葉をよく見かけるようになりました。会社では同僚のエンジニアの方にego liteを勧められ、提供しているサービスの検証をしたい時などに使用しています。爆速で検証が終わるのでとても便利でした。
lite.ego.app
ただ、普段Claudeのデスクトップアプリを使用しているのですが、そこでClaude in Chromeが使えたり、Claudeアプリの中のもブラウザがあったので、同僚の方が結構な勢いでego liteを進める理由がわかりませんでした。
そこで調べてみることにしました。
1. エージェントブラウザって何?
AIエージェントが操作するためのブラウザだそうです。
ego liteや、Claudeアプリの中のブラウザがここに入ります。
Claude in Chromeはエージェントブラウザそのものではなく、ふだんのChromeをAIで操作できる拡張機能です。
AIが操作するためのブラウザとは
ふつうのブラウザは、人が目で見てマウスで操作する前提ですが、エージェントブラウザには、AIが使いやすいように次のような工夫がされているそうです。
ページを文字の一覧にする:入力欄やボタンを抜き出して、AIが読める形で渡す
番号で操作できる:「e3 に入力」のように指示でき、座標やセレクタが要らない
外から命令できる:Claude Codeなどのエージェントが操作の指示を送れる
人の作業と分ける:AI用の作業場所を別に用意して、人のタブを動かさない
人が見張れる:操作中の画面を見たり、途中で止めたりできる
なお、どこに何を入力するかを判断するのは、ブラウザではなくAIエージェント側です。
2. 4つのエージェントブラウザ等を比べてみた
ツール
正体
操作するAI
動かすブラウザ
ログイン状態
人の作業との関係
ego lite
ブラウザ本体
外部のエージェント
(Claude Code、Codexなど)
ego lite内の別の作業場所(Space)
Chromeから引き継げる
自分のタブとは分かれて並行
Claude in Chrome
Chromeの拡張機能
Claude
ふだんのChrome
そのまま使える
同じChromeを使う
Claudeアプリ内のブラウザ
Claudeアプリの機能
Claude
アプリ専用のブラウザ
アプリ側で別に持つ
アプリの中で見ながら代われる
agent-browser
コマンドで動く部品
外部のエージェント
別に立ち上がるブラウザ
基本は別
裏で動く
Claude in Chrome:ふだんのChromeを、Claudeが操作する
ふだんのChromeを使うので、ログイン済みのサービスもそのまま操作できます。
Claudeアプリ内のブラウザ:アプリの中の専用ブラウザ
Claudeデスクトップアプリの地球儀アイコンから開くブラウザです。ふだんのChromeとは別のブラウザで、ログイン状態もアプリ側で別に持ちます。
Claudeが操作している画面を横で見られて、途中で自分が代わることもできます。人が頼む点ではClaude in Chromeと同じで、ふだんのブラウザと切り離して動く点ではagent-browserに近い、中間の位置づけです。
agent-browser:AIエージェントが使う部品
人が直接使うものではなく、Claude Codeなどのエージェントが作業の途中で呼び出す部品です。たとえばClaude Codeにアプリを作らせて、そのアプリが画面上で正しく動くかを確かめる、といった使い方をします。
ふだんのブラウザとは切り離して、基本は画面を出さずに裏で動きます。そのぶん、ログインが必要なサービスは、agent-browser側で改めてログインしてから操作します。
ego lite:ふだんのブラウザの中で、エージェントと並行作業
ego liteは、citrolabsという開発元が作っているブラウザです。Google Chromeと同じ仕組みを土台にしているので、見た目や使い心地はChromeに近いです。無料で使えて、中身(プログラム)も公開されています。今のところMac専用で、Windowsでは使えません。
ふだんのブラウザとして使いながら、Claude CodeやCodexなどの外部エージェントにも操作させられます。エージェントは「Space」という分かれた作業場所で動くので、自分が開いているタブには触りません。Chromeのログイン状態やCookie、拡張機能も引き継げるので、エージェントのために再ログインする必要がありません。複数のSpaceで、別々の作業を同時に進めることもできます。
つまりego liteは、「ログイン済みの環境は使いたい、でも自分のタブは邪魔されたくない」という悩みに向けたツールです。agent-browserは別ブラウザなのでログインし直しが必要で、Claude in Chromeは自分と同じChromeを使います。ego liteは、その間を埋める位置づけだとわかりました。
3. 結局、どう使い分ければいいの?
違いがわかったところで、自分の仕事に当てはめて使い分けを考えてみました。
こんなとき
向いているもの
理由
ログイン済みの管理画面で、目の前の作業を手伝ってほしい
Claude in Chrome
ふだんのChromeをそのまま使える
ふだんのChromeとは分けて、ログインが必要な作業も任せたい
Claudeアプリ内のブラウザ
一度ログインすれば状態が残り、ふだんのChromeとぶつからない
開発中の画面が動くか、エージェント自身に確かめさせたい
agent-browser
エージェントがコマンドで呼び出せる
ログインが必要な自社サービスの検証を、何パターンも並行して進めたい
ego lite
ログインを引き継いだまま、Spaceごとに並行で動かせる
Claude in Chrome:ふだんの作業の延長で頼みたいとき
たとえば、ログイン済みの管理画面からお客様の利用状況を集めてまとめてもらう、といった使い方です。自分が見ている前で1つずつ進めてもらう作業に向いています。
ただし、自分と同じChromeを使うので、Claudeが操作している間はそのChromeで別の作業をしにくくなります。
Claudeアプリ内のブラウザ:ふだんのChromeと分けて頼みたいとき
たとえば、お客様の会社のWebサイトを調べて整理してもらったり、ログインが必要な管理画面で作業してもらったりする使い方です。ふだんのChromeとは別なので、自分の作業を邪魔されません。
ログイン状態はアプリ側で持つので、最初に一度アプリのブラウザでログインしておけば、次からはそのまま作業を頼めます。
agent-browser:エンジニアが開発の中で使うとき
Claude Codeに画面を作らせて、そのままエージェント自身に動作確認までさせる、といった使い方です。人がチャットで頼む道具ではないので、CSの私が直接使う場面は少なそうです。
ego lite:ログインが必要な検証を、まとめて任せたいとき
たとえば、自社サービスのテスト環境で「新規登録の流れ」「設定変更の流れ」「エラー時の表示」を、それぞれ別のSpaceでエージェントに同時に確かめてもらう、といった使い方です。Chromeのログイン状態を引き継げるので、エージェントのために毎回ログインする必要もありません。その間、自分は自分のタブで別の作業を続けられます。
ここで、同僚がego liteを勧めてくれた理由がわかった気がしました。私の使い方は、ログインが必要なサービスの検証です。この使い方だと、ログインを引き継げることと、複数の検証を並行して進められることが、そのまま「爆速で終わる」につながっていたのだと思います。
!
ego liteやClaude in Chromeのように、ログイン済みの環境をAIに操作させる場合は、誤操作したときの影響も大きくなります。本番環境ではなくテスト環境で使う、操作を任せるサイトを絞るなど、任せる範囲には注意が必要です!!
4. agent-browserを例に、AIがブラウザを動かす流れを見てみる
ところでエージェントブラウザは、どこにどのボタンがあるというのをどのように判断しているのでしょうか。
中の動きが一番わかりやすかったのが、agent-browserです。
結論からいうと、AIは画面を人間のように目で見ているわけではないそうです。agent-browserはHTMLをもとに画面の部品の一覧表を作り、そこに番号を振って、AIとの共通の認識を揃えているみたいな感じらしいです。AIは番号で「どこを操作するか」を伝え、agent-browserはその番号の部品を操作します。画面が変わったら一覧表を作り直し、番号も振り直します。
たとえばお問い合わせフォームにメールアドレスを入れて送信するとき、AIは裏でこんな命令を順番に送っています。
agent-browser open example.com
agent-browser snapshot -i
agent-browser fill @e3 "test@example.com"
agent-browser click @e5
よくわからないのですが!!!!!やっていることは4つだけということです。
ページを開く(open)
ページの部品の一覧表をもらう(snapshot)
一覧表を読んで、メールアドレス欄に入力する(fill)
送信ボタンを押す(click)
2で受け取る一覧表は、イメージとしてはこんな形です。入力欄やボタンに、e2 e3 のような番号が振られています。
- 入力欄「会社名」 → e2
- 入力欄「メールアドレス」 → e3
- ボタン「送信」 → e5
AIはこの一覧表を読んで、「メールアドレス欄は e3 だな」「送信ボタンは e5 だな」と判断します。あとは「e3 にこれを入力して」「e5 を押して」と番号で指示するだけです。
レストランにたとえると、agent-browserは番号付きのメニューを渡してくれる店員さんで、AIはメニューを読んで「3番ください」と注文するお客さんです。何を選ぶかを決めるのはお客さん(AI)で、店員さん(agent-browser)は注文どおりに動きます。
つまり、agent-browser自体が「ここはメールアドレス欄だ」と判断しているわけではありません。
agent-browserの役割:ページを一覧表にしてAIに渡すことと、AIが選んだ操作を実行すること
AIエージェントの役割:一覧表を読んで、どこに何を入れるかを判断すること
この役割分担は、ego liteやClaude in Chromeでも変わりません。
5.終わりに
エージェントブラウザのことがわかったので、業務に活用していこうと思います!!
主に検証での使用が多いのですが、活用方法を広げていければと思います。
それとブラウザではなくパソコンをちょくで触れると最近流行りのagent-desktopも使ってみたいです!
参考
citrolabs/ego-lite
vercel-labs/agent-browser
lilting.ch
skills#278 (by someone else) quite ridiculous—just skim its first two comments, absurd amounts of unnecessary detail and a preposterous solution, all very obviously slop. All that needed to be said was “cloning repositories can take arbitrarily long, so putting a 60 second timeout is obviously wrong”. The rest is worse than posturing.
Rather like the issue, this article is written in a tedious style which sure looks sloppy, and I disagree with parts of its conclusions.
> The thing is, timeouts need to exist. Infinite waits are bad. Hanging processes are bad. I’m not arguing against timeouts.
Since the author won’t, I will.
The skills case shouldn’t have a timeout at all: it’s the wrong place and the wrong thing. You rather want to check if it’s still working, and Git has that handled. The problematic case is if it can get stalled waiting for authentication, and I’m not convinced that can happen in a way that needs to be catered for. If it’s interactive, the user will observe the authentication prompt and so the timeout cutting them off is wrong, and if it’s not interactive then it should fail immediately. I’m inclined to presume it’s slop-style cargo-culting (in which area Chesterton’s fence is an increasingly unreliable rubric).
As for the Docker Gordon case, well, for a human tool I’d just say there shouldn’t be any timeout, it’s obviously dumb, the human will observe if things aren’t working as expected and interrupt it. For AI nonsense, well, this sounds to me like the wrong way to apply a timeout. I would rather expect it to throw an LLM at it and its logs or something to apply judgement like the human would, to see if it seems like it’s not working or stuck and interrupt it. A hard timeout is obviously idiotic, but a timeout at all feels from the wrong era of computing for such a thing.
8 points
Vercel agent-desktop: computer use for coding agents through the accessibility tree
Vercel Labs released agent-desktop this week, a free, open source tool that gives AI coding agents computer use on macOS, Windows and Linux. Chris Tate, who built Vercel's agent-browser, announced it on October 31 and described it as "agent-browser, for your whole computer." The interesting part is not that an agent can click buttons. It is how it sees the screen: through the operating system's accessibility tree, with no screenshots and no pixel matching.
What actually shipped
agent-desktop is a Rust CLI plus a C library, on npm as version 1.0.2 under Apache-2.0, with native binaries for x64 and ARM64. There is no language model inside it. Any agent that can run shell commands can drive it, so Claude Code, Codex, Cursor's CLI or a plain bash script all qualify. The command set covers observation, clicks and typing, window management, notifications, the clipboard and sessions, about 56 commands in total. Development started in February, led by Lahfir. Version 1.0 with Linux support shipped on October 28, and 1.0.2 followed on October 30.
Refs, not pixels
The core loop is observe, act, observe again:
agent-desktop snapshot --app Finder -i # interactive elements, each with a ref
agent-desktop click @s8f3k2p9:e8 # act on a ref from that snapshot
agent-desktop snapshot --app Finder -i # observe again to verify
A snapshot returns JSON with a ref for every element the agent can act on. The agent acts on a ref, then takes a new snapshot to check the result. Nothing is inferred from pixels. The tool reads the AX API on macOS, UI Automation on Windows and AT-SPI on Linux, so it sees the same UI structure a screen reader sees, with roles and states the OS already maintains.
Errors an agent can actually handle
Refs belong to the snapshot that produced them. When the UI shifts before an action lands, you do not get a wrong click, you get a machine-readable error: STALE_REF or AMBIGUOUS_TARGET. If several windows match, the error lists the candidate window ids in error.details, and you pass one back with --window-id. A bare @e8 without its snapshot prefix is rejected with INVALID_ARGS.
This is the part I would underline for anyone wiring agents to GUIs. Vision-based computer use fails silently: the model clicks the wrong coordinate and you find out downstream, if you find out at all. Here every failure mode has a code and a defined recovery: take a new snapshot, use its refs. Actions are safe to retry because refs stay stable, which is exactly the property you want in an unattended loop.
Dense apps: skeleton first, then drill down
A full accessibility tree of an Electron app is big. The skeleton traversal work merged into the project measured it: a Slack skeleton snapshot is about 3.6KB versus roughly 17.3KB for the full tree, a 78-96% token saving on dense Electron apps. The pattern is to map first, then drill in:
agent-desktop snapshot --skeleton --app Slack -i --compact
agent-desktop snapshot --root @s8f3k2p9:e3 -i --compact
The skeleton gives a shallow overview with child counts on truncated containers. --root starts a traversal from a previously discovered ref, so you only pay tokens for the region you are working in. For an agent on a token budget, this is the difference between a tool you can leave running and one you babysit.
Wiring it to an existing agent
Install is npm install -g agent-desktop. The binary carries its own docs, matched to its version:
agent-desktop skills get desktop # the loop, refs, verification and retry rules
agent-desktop skills get platform # what differs on the OS you run on
You can install the bundled skill into a harness with npx skills add https://github.com/vercel-labs/agent-desktop --skill agent-desktop. Two details worth knowing before you script it. Actions run headless by default: they go through the accessibility API without moving the pointer or stealing focus, and --headed opts into real input. And on PowerShell, quote every ref, because a bare @token is the splatting operator.
Platform reality check
The platform table in the repo readme is honest about gaps. macOS needs an Accessibility grant, and agent-desktop permissions --guide walks you through it. Windows needs no grant for apps at your terminal's integrity level. Linux needs at-spi2-core in your graphical session; mouse input is X11 only or --headed, the Wayland clipboard needs wl-clipboard, and notifications go through GNOME Shell. Apps without an accessibility tree are invisible to it, and it does not automate web pages, that is what agent-browser is for.
Take the data exposure seriously
Snapshots, screenshots and clipboard reads can contain private data, and the project's own docs warn against routing them into public logs. An optional helper called JEV sends screen descriptions to a configured model provider. Sit with that for a second: this tool reads your screen the way a screen reader does, and it hands what it reads to whatever agent invoked it. An agent with agent-desktop plus shell access effectively holds your user account.
I wrote about where that boundary sits when Nvidia moved agent execution into the kernel, and about the guardrail details to check before letting Copilot click your desktop. The same logic applies here: run it in a dedicated environment where the blast radius is a test account, not your daily driver.
When I would reach for it
Not for anything with an API. If the thing you are driving exposes an MCP server, a CLI or an HTTP endpoint, use that instead, it will be cheaper and more reliable. agent-desktop earns its keep on apps with no automation surface at all: installers, vendor tools, that one dialog box your CI cannot get past. The observe-act-observe loop with structured errors is the same verification discipline I want in every agent workflow, and now it extends to GUIs. That is the real news here, not the clicking.
1 reaction
Mentions
scriptc v0.4.9 → Typed-array loops 1.83x faster → 10M console.log lines in 0.54s → No-change rebuilds in 17ms → Windows hello world: 146KB, from 1.8MB Plus node:dns, more child_process, and a lot more TypeScript compiles npm i -g scriptc github.com/vercel-labs/scriptc/releases/tag/v0.4.9
In less than a week, agent-desktop went from 1.8K to 16.4K stars It's now the 5th most popular Vercel Labs repo Congrats @mdlahfir Star it: vercel-labs/agent-desktop t.co
スクショを使わずにデスクトップアプリを操作する agent-desktop の仕組み グラレコ !agent-desktop の要点をまとめたグラレコ。部品の木を読む、ref で指す、読む→操作→読み直す、迷ったら止まる、マウスを奪わない、やり直してよいかの判断、大きいアプリは骨組みから、3つの OS と MCP の8項目と、基本の流れ 最初に、この記事の内容を1枚の絵にまとめました。①〜⑧が本文で取り上げる話題に、下の矢印が基本の使い方の流れに対応しています。 はじめに agent-desktop は、Vercel Labs が公開しているオープンソースのツールです。AI エージェントが macOS・Windows・Linux のデスクトップアプリを「見て」「操作する」ための CLI と C ライブラリで、Rust で書かれています。 特徴は、スクリーンショットやピクセルの照合を使わないところです。OS が持っているアクセシビリティツリー(画面の部品を木の形に並べた情報で、スクリーンリーダーが読み上げに使うものと同じです)を読み、JSON にして返します。操作できる部品には ref という番号が付き、エージェントはその番号を指定してクリックや入力をします。 もう1つの特徴は、agent-desktop の中に言語モデルが入っていないことです。「読む → 操作する → 読み直して確かめる」というループを回すのは、呼び出す側のエージェントやスクリプトです。agent-desktop は、そのループの中で呼ばれる道具という位置づけです。 | 項目 | 内容 | | --------------- | ------------------------------------------------------------------- | | 提供 | Vercel Labs(GitHub: vercel-labs/agent-desktop) | | 形態 | CLI(agent-desktop)と C ライブラリ(libagent_desktop_ffi) | | 対応 OS | macOS 13 以降 / Windows 10 1809 以降 / Ubuntu 24.04 以降 | | ライセンス | Apache-2.0 | | 最新版 | 1.2.0(2026-11-05)。このリリースで MCP サーバーが加わりました | | GitHub のスター | 約1.6万(2026年11月5日時点) | この記事では、README・公式ドキュメント・同梱のスキル(エージェント向けの手引き)をもとに、仕組みと使い方を整理します。筆者の手元で動かした記録ではなく、ドキュメントを読んで分かったことのまとめです 📚。AI エージェントにデスクトップアプリを触らせたい方や、computer use の実装方式に関心のある方に向けて書いています。 スクリーンショット方式との違い 📸 デスクトップを AI に操作させる方法としてよく知られているのは、画面のスクリーンショットをモデルに見せて、クリックする座標を答えさせるやり方です。agent-desktop は、そこを OS の部品情報に置き換えています。 次の図は、2つの方式で「ボタンを押す」までの流れを並べたものです。 flowchart LR A1["画面を撮影"] --> A2["モデルが画像を見る"] --> A3["ボタンの座標を推測"] --> A4["座標をクリック"] B1["部品の一覧を読む<br>snapshot"] --> B2["JSON で受け取る<br>ボタンに ref"] --> B3["ref を指定<br>click"] --> B4["部品に用意された<br>操作を呼ぶ"] 上の段がスクリーンショット方式、下の段が agent-desktop です。下の段には「座標を推測する」工程がなく、エージェントは JSON に書かれた ref をそのまま指定します。 違いを表にまとめると、次のようになります。 | 観点 | スクリーンショット方式 | agent-desktop | | ------------ | ------------------------ | ----------------------------------------- | | 何を見るか | 画面の画像 | OS のアクセシビリティツリー(JSON) | | どう指すか | 画面上の座標 | 部品ごとの ref(例: @s8f3k2p9:e8) | | 操作の手段 | マウスとキーボードの入力 | 既定では部品に用意された操作を API で呼ぶ | | 見えないもの | 画面に映っていないもの | アクセシビリティツリーを公開していない UI | 最後の行は、使う前に知っておきたい制約です。agent-desktop はピクセルを見ないので、アクセシビリティツリーを公開していないアプリは見えません(スクリーンショットを撮る screenshot コマンドはありますが、ref を使う操作とは別物です)。 また、対象はデスクトップアプリだけで、Web ページの自動操作は守備範囲の外です。Web ページには同じ Vercel Labs の agent-browser を使います。Chromium や Electron 製のアプリを agent-desktop から起動した場合は、DevTools のポートを開いて、Web の中身を agent-browser から操作できるようにする連携も用意されています。 仕組み:エージェントから OS の API まで 🧱 全体の構成を図にしました。上から下に向かって呼び出しが進みます。 !agent-desktop の構成図。呼び出し側のエージェントが CLI か C ライブラリを呼び、どちらも agent-desktop-core を通る。core は PlatformAdapter だけを通して OS に触れ、ビルド時に選ばれた macOS・Windows・Linux のいずれかの実装が、AX API・UI Automation・AT-SPI で対象アプリのアクセシビリティツリーを読む 図の読み方は次のとおりです。 - 入口は2つあります。CLI は1回の実行ごとに JSON を1つ出力して終わります。C ライブラリは、自分のプログラムの中から同じ機能を呼ぶためのものです。1.2.0 からは agent-desktop mcp で MCP サーバーとしても動きます。 - agent-desktop-core には、コマンドの処理、スナップショットの作成、ref の保存(RefStore)が入っています。 - PlatformAdapter(オレンジの枠)は、core が OS に触れるための唯一の窓口です。core は OS ごとの実装を直接読み込まず、必ずここを通ります。 - OS ごとの実装は、ビルド時にどれか1つだけが組み込まれます。点線の矢印はその意味です。そのため、配布されるバイナリは「macOS 用」「Windows 用」のように OS ごとに分かれています。 それぞれの OS で使うアクセシビリティ API と、動作の条件は次の表のとおりです。 | OS | 必要な環境 | 使う API | | ------- | ----------------------------------------------------------------------------------------------------- | ------------- | | macOS | macOS 13 以降(Intel / Apple Silicon)。agent-desktop を起動するアプリにアクセシビリティの権限が必要 | AX API | | Windows | Windows 10 1809 以降、または Windows Server 2019 以降(x64 / ARM64) | UI Automation | | Linux | Ubuntu 24.04 以降(x86_64 / aarch64、glibc 2.35 以上)、X11 か Wayland、AT-SPI が動いているセッション | AT-SPI | コマンド名は3つの OS で共通です。ただし、どの操作が画面に触れずにできるかは OS ごとに違うので、公式ドキュメントには OS 別のページがあります。 基本のループ:読む → 操作する → 読み直す 🔁 README のクイックスタートは、次の3行です(Finder を例にしています)。 agent-desktop snapshot --app Finder -i # 操作できる部品を、ref 付きで読む agent-desktop click @s8f3k2p9:e8 # そのスナップショットの ref を指定して押す agent-desktop snapshot --app Finder -i # もう一度読んで、結果を確かめる -i は、ref の付かない末端の部品を省いて、操作できる部品とその親だけを残すオプションです。1回目の snapshot は、次のような JSON を返します(README に載っている例をそのまま引用しています。README の時点で一部が省略されています)。 { "version": "2.6", "ok": true, "command": "snapshot", "data": { "app": "Finder", "snapshot_id": "s8f3k2p9", "ref_count": 59, "complete": true, "tree": { "role": "window", "name": "Downloads", "children": [ { "role": "treeitem", "name": "Documents", "ref_id": "@s8f3k2p9:e8", "available_actions": ["Click"] } ] } } } role が部品の種類、name が部品の名前、ref_id がエージェントが指定する番号です。available_actions を見れば、その部品で何ができるかも分かります。人間が画面を見て「Documents という項目がある」と判断する部分を、エージェントはこの JSON から読み取ります。 1回の操作でエージェントと agent-desktop がどうやり取りするかを、シーケンス図にしました。 sequenceDiagram participant E as エージェント participant D as agent-desktop participant P as 対象アプリ<br>(OS の API 経由) E->>D: snapshot --app Finder -i D->>P: アクセシビリティツリーを読む D-->>E: JSON(部品と ref) E->>D: click @s8f3k2p9:e8 D->>P: ref の部品を探し直して押す D-->>E: JSON(結果と disposition) E->>D: snapshot または wait D->>P: もう一度読む D-->>E: JSON(変わった後の画面) Note over E: 期待どおりなら次へ<br>違えば判断し直す 図の最後で、エージェントはもう一度画面を読んでいます。公式ドキュメントには「アクションが成功したという返事は、UI が変わったことの証明にはならない。だからループは読み直しで終わる」という趣旨の説明があります。押したつもりでも画面が変わっていないことはあるので、確認までを1セットにしています。 公式ドキュメントの導入ページには、電卓アプリで「7」を押して表示を確かめる、4つのコマンドの例も載っています。 agent-desktop snapshot --app gnome-calculator --skeleton -i --compact # 1. 全体の骨組みを読む agent-desktop snapshot --root @s2txcl95uvubmn:e1 -i --compact # 2. 一部分を詳しく読む agent-desktop click @s2txcl95uvubmn:e11 # 3. 「7」のボタンを押す agent-desktop wait --element @s2txcl95uvubmn:e6 --predicate value --value 7 # 4. 表示が 7 になるのを待つ 4行目の wait は、条件を満たすまで待つコマンドです。決め打ちの sleep で待つと、アプリの反応が遅いときに確認がずれてしまうので、同梱のスキルでも wait を使うように書かれています。 ref の決まりごと 🏷️ ref は @<スナップショットID>:e<番号> という形をしています。@s8f3k2p9:e8 なら「スナップショット s8f3k2p9 で8番目に ref が付いた部品」という意味です(ref は木を深さ優先でたどる順に振られます)。番号だけの @e8 を渡すと、INVALID_ARGS で受け付けてもらえません。 ref が付くのは、基本的には操作できる部品です。ボタン・テキスト入力欄・チェックボックス・リンク・メニュー項目・タブ・スライダーなどの種類か、主な操作を持っている部品が対象で、ただの文字や何の操作も持たない入れ物には付きません。例外は、後で出てくる「骨組み」の読み方で途中まで読んだ入れ物で、掘り下げる先として ref が付くことがあります。 ref はそれを発行したスナップショットの中でだけ使えます。画面が変わったあとに古い ref を使うと、次のように扱われます。 flowchart TD A["snapshot で ref を発行"] --> B["ref を指定して操作"] B --> C{"部品を探し直す"} C -->|1つに決まる| D["操作を実行"] C -->|見つからない| E["STALE_REF"] C -->|候補が複数| F["AMBIGUOUS_TARGET"] E --> G["新しい snapshot を取って<br>その ref で操作し直す"] F --> H["別の部品・ウィンドウを<br>指定して取り直す"] ここで効いているのが、操作の直前に部品を探し直す仕組みです。agent-desktop は、ref が指していた部品が今も同じものかを確かめてから操作します。確信が持てないときは、推測で別の部品を押したりせず、エラーを返して止まります。 確かめ方は OS で違います。macOS では、ref が部品そのものの参照を持っているので、見た目がそっくりな部品が並んでいても1つずつ区別できます。Windows と Linux では、スナップショットを撮った時点でウィンドウの中に1つしかなかった部品で、今も1つだけ一致するものに限って操作します。そっくりな部品が複数あると AMBIGUOUS_TARGET になるので、別の手段を考えることになります(同梱のスキルでは、ウィンドウの中で他と区別できる部品を操作するように書かれています)。 もう1つ、ref を使った操作には待ち合わせが組み込まれています。対象の部品が操作できる状態になるまで、既定で最大5秒(type は1文字ごとに30ミリ秒を足した時間)待ってから実行し、間に合わなければ TIMEOUT を返します。--timeout-ms 0 を付けると、待たずに1回だけ試します。 大きなアプリは骨組みから読む 🗺️ Electron 製のアプリや IDE のように部品の多いアプリだと、アクセシビリティツリーの部品が数千個になることがあります。全部を一度に読むと時間がかかり、エージェントに渡すトークンも増えます。そこで agent-desktop には、「まず骨組みだけ読んで、必要な場所だけ掘り下げる」読み方が用意されています。 flowchart TD S["snapshot --skeleton -i --compact<br>深さ3までの骨組みを読む"] --> P["children_count と ref_id の<br>両方を持つ部品を選ぶ"] P --> R["snapshot --root その ref -i --compact<br>その部分だけ読む"] R --> A["読んだ ref で操作する"] A --> V["wait / get / 同じ --root で<br>読み直して確かめる"] V -->|別の場所が必要| R V -->|レイアウトが変わった| S --skeleton を付けると、読む深さが3段までになります。そこで打ち切られた入れ物には children_count(子の数)が付くので、どこに中身があるかが分かります。次に --root でその入れ物を指定すると、その部分の部品が同じスナップショットに追加されます。 小さいアプリなら、骨組みを経由せずに snapshot -i で全体を読めば十分です。探したい部品の種類や名前が決まっているなら、find で直接探す方法もあります。 なお、--root で読む量そのものが減るのは macOS だけです。Windows と Linux では、部品を探し直すためにウィンドウ全体を読み直したうえで、その部分だけを返します。ただし、エージェントが受け取る JSON はどの OS でも指定した部分だけなので、トークンを抑える効果は同じように得られます。 画面を奪わない:既定は画面に触れないモード 🖱️ agent-desktop の ref 操作は、既定では headless(画面に触れないモード)で動きます。部品に用意された操作をアクセシビリティ API で呼ぶだけで、フォーカスを奪わず、マウスカーソルも動かさず、キー入力の合成やクリップボードも使いません。人がパソコンを使っている横で動かしても邪魔をしない、という考え方です。 物理的な入力(カーソルを動かす、キーを打つなど)を使いたいときは、--headed を付けて許可します。 | 項目 | 既定(headless) | --headed を付けたとき | | -------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | フォーカス | 奪わない | 対象のウィンドウを前面に出してよい | | マウスカーソル | 動かさない | 動かしてよい | | キー入力の合成 | しない | してよい | | 物理入力の扱い | 使わない。API で操作できなければエラーで止まる(ACTION_NOT_SUPPORTED、POLICY_DENIED など) | 使ってよい。実際に使うかは OS と操作ごとに決まり、check・set-value・expand はどの OS でも API 経由のまま | どの OS でも --headed が必要なのは、triple-click・hover・drag・mouse-move・mouse-click・mouse-wheel です。double-click も基本的には必要ですが、macOS で部品が「開く」操作を持っている場合は不要です。 同梱のスキルには、「headless で失敗したからといって、--headed に切り替えて回復しようとしないこと」とはっきり書かれています。--headed は、ユーザーが物理入力を明示的に許可したときだけ使うものです。エージェントが自分の判断でマウスを動かし始めると、人が作業中のウィンドウを横取りしかねないので、ここは守っておきたいところです。 失敗したときの判断:disposition を見る 🚦 agent-desktop のコマンドは、成功しても失敗しても JSON を1つ返します。失敗したときは ok: false になり、error の中に理由が入ります。公式ドキュメントに載っている例を、一部省略して引用します。 { "version": "2.6", "ok": false, "command": "click", "error": { "code": "SNAPSHOT_NOT_FOUND", "message": "Snapshot 's3tufs86hddhyl' not found", "recovery": { "strategy": "refresh_snapshot_then_retry_original", "retryable": true, "requires_fresh_snapshot": true }, "disposition": { "delivery": "not_delivered", "retry": "safe" } } } エージェントの分岐に使うのは、error.code と error.disposition です。message や suggestion の文言は変わることがあるので、そこで条件分岐してはいけないとドキュメントに書かれています。 中でも見ておきたいのが disposition で、「入力がアプリに届いたかどうか」と「やり直してよいかどうか」を表しています。 - delivery が not_delivered(何も届いていない)のときだけ、retry が safe になります。 - それ以外(retry が unsafe か unknown)は、操作が届いた可能性があります。もう一度同じ操作をすると、2回クリックや2回入力になったり、toggle なら元に戻ってしまったりします。 この判断の流れを図にしました。 !アクションが失敗したときの判断フロー。結果を受け取り、成功なら読み直して確かめる。失敗なら disposition.retry が safe かを見て、safe なら原因を直してやり直す。unsafe か unknown なら画面の状態を読み、状態を見て次の手を決める オレンジのひし形が、一番大事な分かれ道です。unsafe や unknown のときは同じ操作を繰り返すのではなく、get・is・新しいスナップショットで今の画面を読んでから次を決めます。結果に details.post_state が入っていれば、それも手がかりになります。 エラーコードは全部で16種類あります。よく出てきそうなものを抜き出しました。 | コード | 意味 | 対応 | | ---------------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | STALE_REF | ref の部品がもう存在しない・一致しない | 新しいスナップショットを取って、その ref を使う | | AMBIGUOUS_TARGET | 一致する部品・ウィンドウが複数あり、選べない | 別々の部品なら find・--root・--window-id で絞る。macOS 以外では、そっくりな部品を ref で選び分けることはできない | | SNAPSHOT_NOT_FOUND | スナップショット ID が見つからない(期限切れ・別セッション) | 同じセッションでスナップショットを取り直す | | POLICY_DENIED | headless のまま物理入力が必要な操作をしようとした | モードを切り替えて回復しようとしない | | PERM_DENIED | OS の権限(アクセシビリティなど)が足りない | agent-desktop permissions で確認して許可する | | TIMEOUT | 待ち時間の上限を超えた | details.kind を読み、retry が safe のときだけやり直す | エージェントへのつなぎ方 🔌 インストールは npm から行います。Bun・Yarn・pnpm でも同じパッケージを入れられ、macOS と Linux なら brew install agent-desktop も使えます。 npm install -g agent-desktop agent-desktop status # OS・権限・対応している画面の種類を表示 agent-desktop permissions --guide # macOS:アクセシビリティの権限を案内付きで設定 あとは、エージェントに使い方を覚えさせます。方法は次の図の4通りです。 flowchart LR E["エージェント"] --> K["スキルを入れる<br>npx skills add"] E --> G["AGENTS.md に<br>手順を書く"] E --> M["MCP サーバー<br>agent-desktop mcp"] E --> C["C ライブラリを<br>プログラムから呼ぶ"] K --> T["skills get desktop<br>skills get platform"] G --> T T --> X["CLI を実行"] バイナリには、そのバージョン用の手引きが入っています。agent-desktop skills get desktop でループ・ref・確認・やり直しのルールを、agent-desktop skills get platform で今の OS に固有の注意を読めます。スキルとして入れる場合は、次のコマンドです。 npx skills add https://github.com/vercel-labs/agent-desktop --skill agent-desktop AGENTS.md に書く場合、README では次の内容が紹介されています。 Use `agent-desktop` to see and operate desktop apps. Before the first use, run `agent-desktop skills get desktop` and `agent-desktop skills get platform`, and follow them. MCP クライアントから使う場合は、設定ファイルに次のように追加します。 { "mcpServers": { "agent-desktop": { "command": "agent-desktop", "args": ["mcp"] } } } ツール名はコマンド名に desktop_ を付けたもので、ハイフンはアンダースコアに、サブコマンドはつなげた名前になります(desktop_snapshot、desktop_list_windows、desktop_session_start など)。引数も同じ規則で、snapshot --app Finder -i なら desktop_snapshot に { "app": "Finder", "interactive_only": true } を渡します。--headed や --session のような全体に効くオプションは、ツールの引数では指定できず、agent-desktop mcp --headed のようにサーバーの起動時にだけ付けられます。エージェントが勝手に物理入力を許可できない作りになっているわけです。 コマンドは全部で60個あり、そのうち56個が実際に動きます。残りの key-down・key-up・mouse-down・mouse-up は、押しっぱなしのキーやボタンを確実に離せる仕組みができるまで、実行を拒否するようになっています。 | グループ | 主なコマンド | | -------------------- | -------------------------------------------------------------------------------------------------- | | 観察 | snapshot, find, get, is, screenshot, list-surfaces | | ref への操作 | click, type, set-value, select, toggle, check, expand, scroll など | | キーボード・マウス | press, hover, drag, mouse-move, mouse-click など | | アプリ・ウィンドウ | launch, close-app, list-apps, list-windows, focus-window など | | 通知・クリップボード | list-notifications, notification-action, clipboard-get, clipboard-set など | | 待機・セッション | wait, session, trace, cursor-overlay | | システム | status, permissions, version, batch, skills | 使う前に気をつけたいこと ⚠️ 読み取った内容には、デスクトップの中身がそのまま入ります。 スナップショット、クリップボードの読み取り、スクリーンショット、コマンドの出力、デバッグ用のファイルには、画面に出ていた私的な情報が含まれることがあります。README の冒頭でも、公開のログやアップロードに入れないよう注意されています。エージェントの会話ログも同じ扱いにしておくのが安全です。 秘密の文字列は標準入力から渡します。 type・set-value・clipboard-set には --stdin があり、パスワードなどをコマンドの引数に載せずに済みます。batch で JSON にまとめた文字列はプロセスの引数に出てしまうので、秘密を含む手順は別のコマンドに分けるよう書かれています。 MCP サーバーは、ログイン中のユーザーのシェルと同じ扱いにします。 MCP 経由でも、アクセシビリティツリーから見えるアプリはすべて操作でき、desktop_launch は PATH 上のプログラムを任意の引数で起動できます。クライアント側の確認ダイアログは有効にしておき、画面から読んだ文字列はモデルにとって信用できない入力だと考えておきます(画面に「このボタンを押して」と書いてあるだけで押してしまうと困るので)。 権限が足りないと、空のツリーに見えます。 macOS では、agent-desktop を起動するアプリ(ターミナルなど)にアクセシビリティの権限が必要です。同梱スキルのよくある失敗の一覧にも「status と permissions の確認を飛ばす」が入っているので、最初に agent-desktop status を実行しておくと安心です。 PowerShell では ref を引用符で囲みます。 @token が PowerShell の構文として解釈されてしまうため、'@s8f3k2p9:e8' のように書きます。 更新の速いプロジェクトです。 1.0.0(2026-10-27、Linux 対応)から1.2.0(2026-11-05、MCP 対応)まで、パッチ版を含めて10日ほどで5回リリースされています。1.1.0 では JSON の形式が 2.6 に上がる破壊的な変更も入りました。記事の内容は 2026年11月5日時点のものなので、実際に使うときは agent-desktop version と同梱のスキルで最新の決まりごとを確認してください。 まとめ agent-desktop の設計をひとことで言うと、「部品の一覧を読み、ref で指して操作し、読み直して確かめる。確信が持てないときは止まる」です。古い ref は拒否し、そっくりな部品は推測で選ばず、届いたかどうか分からない操作は繰り返させません。どれも、エージェントが人のパソコンの上で間違ったボタンを押さないための決まりごとになっています。 機能の多さよりも、disposition のように「次の一手をどう判断するか」まで JSON に書いてくれる点が、エージェントから呼ぶ道具として扱いやすいところだと感じました(エラーの文言ではなくコードで分岐してね、と念を押してくれるのもありがたいです)。 試してみる場合は、agent-desktop status で権限を確認し、agent-desktop skills get desktop の手引きを読むところから始めるのがおすすめです。Web ページも操作したいなら、姉妹ツールの agent-browser と組み合わせる形になります 🛠️ 参考 - vercel-labs/agent-desktop(GitHub) — README、CONCEPTS.md、FAQ、CHANGELOG、同梱スキル(2026-11-05 時点の main) - agent-desktop 公式ドキュメント — 導入ページ - Skeleton and drill-down — 骨組みと掘り下げの読み方 - Errors and recovery — エラーコードと disposition - Headed mode — headless と --headed - Using agent-desktop over MCP — MCP サーバーの使い方 - agent-desktop(npm) - agent-browser — Web ページ用の姉妹ツール
Vercel's agent-desktop and the Computer-Use Land Grab On October 30, 2026, Vercel Labs quietly shipped agent-desktop — a Rust CLI and C library that lets AI agents operate any desktop application through the operating system's accessibility tree. No screenshots. No pixel-guessing. No model baked in. Just structured JSON with a ref for every clickable element. > 📖 Read the full version with charts and embedded sources on AgentConn → Within days, the repo had rocketed past 13,000 GitHub stars and 900 forks. That kind of velocity — roughly 3,800 stars in the first 24 hours — doesn't happen for incremental developer tooling. It happens when a project lands squarely on a nerve the industry has been pressing for months: who owns the layer between AI agents and the operating system? That question is the real story here. Not the tool itself — though it's impressively engineered — but what its explosive reception reveals about where the computer-use infrastructure war is heading. Chris Tate, the Vercel engineer behind the project, framed it simply: "agent-browser, for your whole computer."  View original post on X → --- What agent-desktop Actually Is Strip away the hype and agent-desktop is a command-line tool that does three things in a loop: 1. Snapshot — read an app's UI through the OS accessibility layer, returning a JSON tree where every interactive element has a unique ref 2. Act — click, type, scroll, or otherwise interact with a specific ref 3. Verify — take another snapshot to confirm the action landed That's it. The agent's model runs elsewhere. The tool embeds no LLM, has no GUI, and makes no decisions. It's pure infrastructure — a bridge between an agent's intent and the operating system's native controls. # Install globally npm install -g agent-desktop # Snapshot an app interactively agent-desktop snapshot --app Finder -i # Click a specific element agent-desktop click @s8f3k2p9:e8 The key architectural choice: accessibility tree over screenshots. Instead of sending a 3,811-token screenshot of Apple Maps to the model, agent-desktop's region snapshot returns 273 tokens of structured JSON. In a simulated 52-step task, Vercel Labs reports total token usage of 31K versus 198K for the screenshot approach — a roughly 84% reduction. > 📊 Token savings context: The 78–96% token reduction figures are self-reported by Vercel Labs. No independent computer-use benchmark exists yet for these claims. The savings are real in principle — structured text is always cheaper than images — but the magnitude will vary dramatically depending on how well each app exposes its accessibility metadata. Platform support spans macOS 13+ (AX API), Windows 10 1809+ (UI Automation), and Ubuntu 24.04+ (AT-SPI), on both x64 and ARM64. The tool ships under Apache-2.0, and agent-desktop mcp exposes every command as an MCP tool over stdio — meaning any agent framework that speaks MCP can drive it without a single line of integration code. As Dev.to coverage noted, v1.0.2 marked the formal launch — adding a docs site and consolidating all agent instructions into a single AGENTS.md file, a pattern that signals Vercel expects agent frameworks to discover and configure the tool automatically.  Read the full Dev.to walkthrough → CellCog's technical analysis breaks down the "skeleton drilling" technique in detail: the agent maps the full window once, identifies the relevant region, then works inside that region at dramatically lower token cost. Their assessment also highlights the privacy implications — snapshots, clipboard reads, and debug output can contain sensitive desktop content, so agent transcripts should be treated as confidential.  Read CellCog's full analysis → {% youtube qPeMxQfIavo %} --- The Accessibility Tree Bet To understand why this matters, you need to understand what agent-desktop is replacing. The dominant computer-use paradigm since Anthropic introduced it in October 2024 has been screenshot-based: the agent takes a screenshot, a vision-language model interprets the pixels, and the agent clicks coordinates. This works on everything — every app, every framework, every custom-drawn canvas. It's also ruinously expensive, painfully slow, and fundamentally brittle. A button that moves three pixels between frames breaks the entire chain. Agent-desktop flips the model. Instead of asking a VLM "what's on screen?", it asks the OS "what elements exist and what can I do with them?" The accessibility tree — originally built for screen readers and assistive technology — provides exactly the structured metadata that agents need: element roles, labels, states, and actionable refs. {% youtube wf2QPobtUqU %} The practical advantages are significant: - Headless by default. Ref actions don't move the physical pointer or take focus, so an agent can work while you use the same machine. Multiple agents can operate different apps simultaneously, each with its own cursor. - Deterministic targeting. Clicking ref @s8f3k2p9:e8 always hits the same element, regardless of window position, DPI scaling, or display configuration. No coordinate math, no off-by-one pixel errors. - Error semantics. Failed actions return structured errors like STALE_REF or AMBIGUOUS_TARGET with retry dispositions — the agent knows why something failed and whether retrying is safe. - Token efficiency. Text-based snapshots cost a fraction of what image-based screenshots require. At scale, across thousands of agent invocations per day, this is a material cost difference. But the accessibility tree comes with a fundamental limitation: it only works when apps actually expose their UI through accessibility APIs. And that's where the contrarian case gets interesting. --- The Landscape: Who's Fighting for This Layer Agent-desktop didn't emerge in a vacuum. The computer-use infrastructure space has been heating up all year, with every major player staking a claim. The model providers are building vertically: - Anthropic shipped Dispatch, their consumer desktop agent product, combining local computer-use with mobile delegation. Claude's Computer Use went from under 15% OSWorld accuracy in late 2024 to 72.5% in early 2026. - OpenAI launched Operator (browser-first, January 2025), then extended desktop control into Codex with macOS support in April 2026. Sam Altman framed their latest as "a new era of computer use." - Google has Gemini Computer Use in preview, plus Project Mariner for browser automation.  View original post on X → The infrastructure players are building horizontally: - Vercel Labs now has both agent-browser (web, 33K+ stars) and agent-desktop (native apps, 13K+ stars) — a full-stack computer-use toolkit that covers everything from the browser DOM to native OS controls.  View original post on X → - Cua (formerly Computer Use Agent) ships Cua Driver, an open-source framework that returns accessibility tree and screenshots together, with the agent trying accessibility actions first and falling back to pixel clicks. - UI-TARS Desktop from ByteDance takes the VLM-native approach, using a specialized vision model trained specifically for UI interaction. - Deck positions itself as the enterprise infrastructure layer — authentication, governance, session management, and audit trails for computer-use agents at scale. The market tells the story: computer-use agents are projected to grow from a $7.8B market in 2026 to over $52B by 2030, according to Deck's industry analysis.  Read Deck's full State of Computer Use report → {% youtube wflNENRSUb4 %} --- The Infrastructure Thesis: Why Vercel, Not Anthropic, Might Win This Layer Here's the non-obvious take: the model providers are building computer-use the wrong way around. Anthropic's Dispatch, OpenAI's Codex, and Google's Mariner all bundle computer-use into their model products. You get computer-use when you use their model. The capability is tightly coupled to the provider. Switch models and you lose desktop access. Vercel is doing the opposite. Agent-desktop is model-agnostic infrastructure. It doesn't care whether you're running Claude, GPT, Gemini, Llama, or a fine-tuned open model. The tool returns JSON; the model interprets it. This mirrors a pattern we've seen before in the agent stack: | Layer | Model-Coupled | Infrastructure | |-------|--------------|----------------| | Code generation | GitHub Copilot (GPT) | Claude Code, Cursor (model-agnostic) | | Browser automation | Operator (GPT) | Agent-browser, Playwright (model-agnostic) | | Desktop automation | Dispatch (Claude), Codex (GPT) | agent-desktop (model-agnostic) | The infrastructure play tends to win over time because it lets practitioners swap models as capabilities shift — and in 2026, capabilities are shifting fast. > 🎯 The Vercel playbook: Build the infrastructure layer that every agent needs, give it away as open source, and capture value through the deployment platform (Vercel's core business). Agent-browser did this for the web; agent-desktop extends it to the entire OS. Same strategy, bigger surface area. --- What the Community Is Saying The Hacker News thread (99 points, 44 comments) for a similar accessibility-tree desktop tool surfaced the debates that will define this category.  View full discussion on Hacker News → The cross-platform reality check dominated the thread. While agent-desktop claims macOS, Windows, and Linux support, commenters pushed back hard on Linux's AT-SPI implementation. One commenter noted AT-SPI support is "very hit or miss, mostly miss." The custom UI problem is the elephant in the room. macOS apps don't have to implement accessibility APIs. Zoom's custom-drawn controls, game UIs, and Electron apps with lazy-loaded content all expose partial or broken accessibility trees. But the momentum is real. Multiple commenters reported building nearly identical tools. When several independent developers converge on the same abstraction at the same time, that's a strong signal that the pattern is correct. --- The Contrarian Corner: Why Screenshots Might Still Win > ⚠️ The case against the accessibility tree: Structured data is cleaner, but coverage is the killer constraint. The best data in the world is useless if it only describes 60% of the UI your agent needs to interact with. Here's the uncomfortable truth about the accessibility tree approach: Most software is accessibility-incomplete. Despite decades of accessibility standards, the majority of desktop applications expose fragmented or empty accessibility trees. VLMs are getting cheaper faster than apps are getting more accessible. The cost of processing a screenshot has dropped roughly 10x in the past 18 months. The hybrid approach is already standard. Cua Driver returns both the accessibility tree and a screenshot for every observation. The agent tries structured actions first and falls back to pixel clicks when the tree is sparse. The honest assessment: agent-desktop's pure accessibility-tree approach is correct for the apps it covers and insufficient for the apps it doesn't. --- What This Means for You If you're building agents that interact with desktop applications, here's what to evaluate now: 1. Test agent-desktop against your actual target apps. Run agent-desktop snapshot --app YourActualApp -i and check what the tree exposes. 2. Architect for hybrid from day one. The winning pattern is accessibility tree first, screenshot fallback second. 3. Pay attention to the MCP integration. Agent-desktop exposing itself as an MCP server means any MCP-compatible agent framework can drive desktop apps with zero integration code. 4. Watch the token economics, but don't over-index. The 78–96% savings sound dramatic, but the real question is cost-per-successful-task. 5. Track the benchmarks. Computer-use accuracy went from under 15% to 72.5% in 18 months — but it's still far from reliable for mission-critical workflows. --- The Bottom Line Vercel's agent-desktop is the sharpest articulation yet of a thesis that's been building all year: computer-use is infrastructure, not a model feature. The 13,000-star explosion isn't just developer enthusiasm for a well-built Rust CLI. It's a vote for a future where the layer between agents and operating systems is open, model-agnostic, and composable. Whether the accessibility tree or screenshots or some hybrid wins the implementation debate is almost secondary. The structural question — does computer-use belong to the model layer or the infrastructure layer? — is being answered in real-time by where developers are putting their stars and their production dependencies. Right now, the infrastructure layer is winning. And Vercel just made the strongest open-source bid to own it. --- For more on the computer-use agent landscape, see our coverage on AgentConn. Originally published at AgentConn
OSのアクセシビリティツリーを経由してAIエージェントにデスクトップ操作をさせるツールっぽい 画面の要素を直接認識できるからGUIの自動化テストとかで使えそうかな yug1224 starred vercel-labs/agent-desktop vercel-labs/agent-desktop
pingpad: table tennis in the browser, with your phone as the paddle --- title: pingpad: table tennis in the browser, with your phone as the paddle published: true description: How pingpad turns a phone into a paddle over WebRTC: swing recognition on the phone, guiding the player between two devices, and Playwright tests for both. tags: webrtc, gamedev, webdev, typescript cover_image: dev-to-uploads.s3.us-east-2.amazonaws.com Use a ratio of 100:42 for best results. published_at: 2026-11-03 12:45 +0000 --- pingpad is a table tennis game that runs in the browser. You open pingpad.app on a laptop, a tablet or a TV, scan the QR code with your phone, and the phone becomes your paddle. There's nothing to install and no account to create. You can play the computer, play a friend while the next players wait on the bench, or play alone and chase a record. Badges and records stay on your phone. {% embed youtube.com %} One of the people who tried it summed it up: "The Scan'n Play side of it works really well. No install, no questions, no pesky app store. I love it." This article is about how it's built: a phone and a screen talking peer to peer, a swing recognised on the phone rather than tracked, a lot of work spent on guiding the player between two devices, and the library it all sits on. It started with a counter In 2019 I wrote a WebRTC proof of concept: a counter shown on one screen and driven from a phone. You snapped a QR code and updated the counter in real time. The goal was to go a bit further than the usual WebRTC exercises. In 2022 it became webrtc-remote-control, an open source library for what any app runs into once a phone drives another screen: reconnections, page reloads, phones going to sleep, a remote that has to find its screen again. I had demos, the counter and an accelerometer moving a 3D object, and they worked. What I lacked was a game idea. At the end of September 2026 I started on pingpad with AI coding agents. The library already handled the most critical part, the link between the phone and the screen, so I could build the game on top of it. The React and Vue bindings each come with an llm.md guide, written so that a coding assistant knows how to use them. Five weeks later, pingpad has had over 200 pull requests merged. Phone and screen, peer to peer The phone and the screen talk over a WebRTC data channel. No game server sits between them. Two devices still need someone to introduce them. I ported the PeerJS signaling server to Cloudflare Workers, on Durable Objects. It introduces the phone and the screen, then carries nothing. I picked Workers because the alternatives fit badly. Vercel cuts a WebSocket function after 300 seconds and bills its memory as long as the socket is open, so a screen left open would have used up the monthly quota in about a week. Render's free tier goes to sleep after 15 minutes. Cloudflare doesn't bill a hibernated Durable Object socket, so a screen waiting for players costs nothing. STUN finds a direct path when one exists, even between a phone on 5G and a laptop on home Wi-Fi. Some networks make that impossible, such as a symmetric NAT or a corporate firewall. For those, Cloudflare's TURN relays the traffic, still DTLS-encrypted, so the relay can't read it. The screen shows whether each paddle connected over the local network, across the internet through STUN, or through the relay, something WebRTC usually hides. On the same Wi-Fi, the median latency from phone to screen is 3.5 ms. Recognise the swing, don't track the paddle A phone can't tell where it is in space. Its sensors give acceleration and orientation, not position, so you can't track a paddle the way a camera would. What you can do is recognise a swing. So the phone doesn't stream its sensors. It runs the swing detector itself, at full sensor rate, 60 times a second on iOS, and sends one compact, timestamped event when it sees a swing. The screen converts that timestamp with a clock offset it measures by pings, measured again regularly and from scratch when a paddle reconnects. Then the screen decides whether the swing hit the ball, by comparing the time of the swing with the time the ball reached the paddle. A network hiccup delays the message, but it doesn't change your shot. I don't have a ping-pong table at home, so I recorded myself hitting foam stress balls with the back of the phone. A recorder on the phone captured each take, sensors and microphone together, and I labelled it: forehands, backhands, serves. The detector's thresholds come from those recordings, never from tuning by hand. A bench replays every recording through the detector. The detector is a pure module with no DOM dependency, so the exact same function runs on the phone and in the bench. The microphone was there to hear the contact, and it showed that the acceleration peak doesn't mark it. Depending on how you swing, the peak can come before the ball touches the phone as well as after. That's why the screen decides the hit with a window around the ball's arrival, instead of trusting the peak. I tuned the detector on an iPhone. It's meant to work on any recent phone, and it has played fine on Android too. Guiding the player between two devices A good share of the pull requests went into guiding the player, because this isn't a game where you tap your screen. You hold your phone like a paddle while the game plays on another screen, and nobody has that reflex yet. At each step, the player has to be told what to do, on the device they're looking at. Some of the situations the game handles: - A visitor clicks Play on their phone, when the phone is meant to be the paddle. The game explains that this device would become the screen, and offers to send the link to a computer. - The QR code is scanned from Instagram's or Messenger's built-in browser, which won't give access to the motion sensors. The paddle says so, and how to open the page in the real browser. - iOS only grants the motion sensors after DeviceMotionEvent.requestPermission(), called from a user gesture, on HTTPS. The paddle's button is that gesture. - Calibration shows a phone on the screen turning as the player turns theirs, so they can see what the game sees. - Once the ball is served, the paddle tells the player to watch the screen. - A phone locks, goes to the background or reloads mid-match. The game pauses instead of giving the point away, and the phone finds the game again when it comes back. - A third phone joins. It goes on the bench, in the order phones came in, and the screen calls it out by number. A player can hand over their seat, and a player who leaves keeps it until someone on the bench takes it. - A new version is deployed during a game. The protocol is versioned, so a phone and a screen on different versions notice it and say what to do. Each of these has a message where the player is looking, phone or screen, and an end-to-end test that replays it. Commands work the same everywhere. Pausing, choosing the match length or turning the sound off goes through one function on the screen, whether it comes from a button, a key, or a paddle. The screen sends each paddle the commands it offers, so any player can control the game from the phone in their hand. That was the point for TVs: once the game is open, nobody has to pick up the remote and steer a cursor through the TV's browser. Testing a game that needs two devices pingpad has 178 end-to-end tests, and 87 of them cover these player situations. Playwright opens the screen in one browser context and each paddle in another, emulating a phone, and sends the sensor events itself. A local PeerJS server starts with the tests. Headless Chromium draws the 3D scene on the CPU. The screen and the paddles share that CPU, drawing the screen takes most of it, and the paddles fall behind. So in end-to-end runs, the screen doesn't draw, while its frame loop still advances the rally. The tests take less CPU and finish sooner. The same fixtures film the demo videos for pull requests and the videos on the landing page. One setup drives the tests and the videos, so when the interface changes, the videos are filmed again with the same scenarios. Those tests are what let me change the game without replaying every scenario by hand on two devices. Working with agents "A game in one prompt" makes for a good demo. pingpad wasn't one. What made agents useful on it was the setup around them: - the network layer was a library that already worked, documented for agents; - every change goes through a pull request, and every push runs format, lint, types, unit tests, build and end-to-end tests; - every pull request gets its own preview deployment, to try it on a real phone before it merges; - the dev server is reachable from a phone over HTTPS on the local network, thanks to portless, since iOS only gives motion sensors to a secure page; - a test that is written must fail when the condition it checks breaks; - an AGENTS.md file states the architecture and the rules, and the project records the decisions it lives with as ADRs; - every message between phone and screen is a schema, and the protocol is versioned, with each version frozen in a tested file. I kept the design decisions, the tests on a real phone, and the approval of every merge. I wrote about how I work with AI agents on LinkedIn, in French. What the game gave back to the library Playing for real, with phones that lock, go to the background and change networks, turned up bugs the library's demos never showed. I fixed each one in the library rather than working around it in the game: - On iOS, a remote stayed listed after navigating away, because Safari skips beforeunload when it puts a page in the back/forward cache. The library now listens to pagehide (0.5.1). - A first connection whose ICE negotiation stalled waited forever (0.5.2). - Messages that arrived before the first listener was attached were lost, which affected the React bindings (0.5.3). - A page reloaded quickly could find its id still held by the signaling server (0.6.0). The game's code is closed for now. webrtc-remote-control is open source under the MIT licence, with an llm.md guide for React and one for Vue: topheman/webrtc-remote-control. Seven years after that counter, the phone has its game: pingpad.app. I wrote this article with the help of an AI assistant, from my own notes and the project's history, and edited it myself.
Setting up Vercel Agent Desktop with Claude Code on a Mac, and where background mode stops working Agent Desktop (vercel-labs/agent-desktop, Apache 2.0) lets Claude Code use desktop apps by reading their accessibility tree instead of screenshots. Default mode runs in the background, so no mouse movement and no focus stealing. Setup on a Mac: npm install -g agent-desktop agent-desktop permissions --guide npx skills add vercel-labs/agent-desktop --skill agent-desktop claude --allowedTools "Bash(agent-desktop:*)" The Accessibility permission goes to whatever app launches Claude Code (Terminal, iTerm2, VS Code). Screen Recording is only needed for the screenshot command. Gotchas from setting it up: - that allowedTools rule doesn’t cover commands piped into grep or head, and some of those got denied - snapshots are JSON and get big fast. A File menu task used about 550k input tokens (mostly cached). --app, -i --compact and --root keep them down - anything on screen in that app ends up in Claude’s context, so name the app in your prompt and keep sensitive ones closed Where background mode worked and where it didn’t (Claude Code 2.1.316, Opus 5.5, one run per task): - reading an app and pressing buttons: worked. Calculator 128 × 46 came back as 5,888 - filling a text field: worked, it added a line in TextEdit - saving: not reliable. cmd+s couldn’t be confirmed, and Save was greyed out in the File menu while the window was in the background - selecting or styling text: needs --headed, which takes over your real mouse and keyboard Claude also handled the failures well. When an action couldn’t be confirmed or a click was refused, it said so instead of claiming it worked. Cleanup when you’re done: npm uninstall -g agent-desktop, delete the skill folder and ~/.agent-desktop, and turn off the Accessibility permission you gave your terminal. aiparabellum.com
エージェントブラウザって何? ego lite・Claude・agent-browserを比べてみた こんにちは! 私はAIスタートアップでカスタマーサクセスとして働いています。 最近、「エージェントブラウザ」という言葉をよく見かけるようになりました。会社では同僚のエンジニアの方にego liteを勧められ、提供しているサービスの検証をしたい時などに使用しています。爆速で検証が終わるのでとても便利でした。 lite.ego.app ただ、普段Claudeのデスクトップアプリを使用しているのですが、そこでClaude in Chromeが使えたり、Claudeアプリの中のもブラウザがあったので、同僚の方が結構な勢いでego liteを進める理由がわかりませんでした。 そこで調べてみることにしました。 1. エージェントブラウザって何? AIエージェントが操作するためのブラウザだそうです。 ego liteや、Claudeアプリの中のブラウザがここに入ります。 Claude in Chromeはエージェントブラウザそのものではなく、ふだんのChromeをAIで操作できる拡張機能です。 AIが操作するためのブラウザとは ふつうのブラウザは、人が目で見てマウスで操作する前提ですが、エージェントブラウザには、AIが使いやすいように次のような工夫がされているそうです。 ページを文字の一覧にする:入力欄やボタンを抜き出して、AIが読める形で渡す 番号で操作できる:「e3 に入力」のように指示でき、座標やセレクタが要らない 外から命令できる:Claude Codeなどのエージェントが操作の指示を送れる 人の作業と分ける:AI用の作業場所を別に用意して、人のタブを動かさない 人が見張れる:操作中の画面を見たり、途中で止めたりできる なお、どこに何を入力するかを判断するのは、ブラウザではなくAIエージェント側です。 2. 4つのエージェントブラウザ等を比べてみた ツール 正体 操作するAI 動かすブラウザ ログイン状態 人の作業との関係 ego lite ブラウザ本体 外部のエージェント (Claude Code、Codexなど) ego lite内の別の作業場所(Space) Chromeから引き継げる 自分のタブとは分かれて並行 Claude in Chrome Chromeの拡張機能 Claude ふだんのChrome そのまま使える 同じChromeを使う Claudeアプリ内のブラウザ Claudeアプリの機能 Claude アプリ専用のブラウザ アプリ側で別に持つ アプリの中で見ながら代われる agent-browser コマンドで動く部品 外部のエージェント 別に立ち上がるブラウザ 基本は別 裏で動く Claude in Chrome:ふだんのChromeを、Claudeが操作する ふだんのChromeを使うので、ログイン済みのサービスもそのまま操作できます。 Claudeアプリ内のブラウザ:アプリの中の専用ブラウザ Claudeデスクトップアプリの地球儀アイコンから開くブラウザです。ふだんのChromeとは別のブラウザで、ログイン状態もアプリ側で別に持ちます。 Claudeが操作している画面を横で見られて、途中で自分が代わることもできます。人が頼む点ではClaude in Chromeと同じで、ふだんのブラウザと切り離して動く点ではagent-browserに近い、中間の位置づけです。 agent-browser:AIエージェントが使う部品 人が直接使うものではなく、Claude Codeなどのエージェントが作業の途中で呼び出す部品です。たとえばClaude Codeにアプリを作らせて、そのアプリが画面上で正しく動くかを確かめる、といった使い方をします。 ふだんのブラウザとは切り離して、基本は画面を出さずに裏で動きます。そのぶん、ログインが必要なサービスは、agent-browser側で改めてログインしてから操作します。 ego lite:ふだんのブラウザの中で、エージェントと並行作業 ego liteは、citrolabsという開発元が作っているブラウザです。Google Chromeと同じ仕組みを土台にしているので、見た目や使い心地はChromeに近いです。無料で使えて、中身(プログラム)も公開されています。今のところMac専用で、Windowsでは使えません。 ふだんのブラウザとして使いながら、Claude CodeやCodexなどの外部エージェントにも操作させられます。エージェントは「Space」という分かれた作業場所で動くので、自分が開いているタブには触りません。Chromeのログイン状態やCookie、拡張機能も引き継げるので、エージェントのために再ログインする必要がありません。複数のSpaceで、別々の作業を同時に進めることもできます。 つまりego liteは、「ログイン済みの環境は使いたい、でも自分のタブは邪魔されたくない」という悩みに向けたツールです。agent-browserは別ブラウザなのでログインし直しが必要で、Claude in Chromeは自分と同じChromeを使います。ego liteは、その間を埋める位置づけだとわかりました。 3. 結局、どう使い分ければいいの? 違いがわかったところで、自分の仕事に当てはめて使い分けを考えてみました。 こんなとき 向いているもの 理由 ログイン済みの管理画面で、目の前の作業を手伝ってほしい Claude in Chrome ふだんのChromeをそのまま使える ふだんのChromeとは分けて、ログインが必要な作業も任せたい Claudeアプリ内のブラウザ 一度ログインすれば状態が残り、ふだんのChromeとぶつからない 開発中の画面が動くか、エージェント自身に確かめさせたい agent-browser エージェントがコマンドで呼び出せる ログインが必要な自社サービスの検証を、何パターンも並行して進めたい ego lite ログインを引き継いだまま、Spaceごとに並行で動かせる Claude in Chrome:ふだんの作業の延長で頼みたいとき たとえば、ログイン済みの管理画面からお客様の利用状況を集めてまとめてもらう、といった使い方です。自分が見ている前で1つずつ進めてもらう作業に向いています。 ただし、自分と同じChromeを使うので、Claudeが操作している間はそのChromeで別の作業をしにくくなります。 Claudeアプリ内のブラウザ:ふだんのChromeと分けて頼みたいとき たとえば、お客様の会社のWebサイトを調べて整理してもらったり、ログインが必要な管理画面で作業してもらったりする使い方です。ふだんのChromeとは別なので、自分の作業を邪魔されません。 ログイン状態はアプリ側で持つので、最初に一度アプリのブラウザでログインしておけば、次からはそのまま作業を頼めます。 agent-browser:エンジニアが開発の中で使うとき Claude Codeに画面を作らせて、そのままエージェント自身に動作確認までさせる、といった使い方です。人がチャットで頼む道具ではないので、CSの私が直接使う場面は少なそうです。 ego lite:ログインが必要な検証を、まとめて任せたいとき たとえば、自社サービスのテスト環境で「新規登録の流れ」「設定変更の流れ」「エラー時の表示」を、それぞれ別のSpaceでエージェントに同時に確かめてもらう、といった使い方です。Chromeのログイン状態を引き継げるので、エージェントのために毎回ログインする必要もありません。その間、自分は自分のタブで別の作業を続けられます。 ここで、同僚がego liteを勧めてくれた理由がわかった気がしました。私の使い方は、ログインが必要なサービスの検証です。この使い方だと、ログインを引き継げることと、複数の検証を並行して進められることが、そのまま「爆速で終わる」につながっていたのだと思います。 ! ego liteやClaude in Chromeのように、ログイン済みの環境をAIに操作させる場合は、誤操作したときの影響も大きくなります。本番環境ではなくテスト環境で使う、操作を任せるサイトを絞るなど、任せる範囲には注意が必要です!! 4. agent-browserを例に、AIがブラウザを動かす流れを見てみる ところでエージェントブラウザは、どこにどのボタンがあるというのをどのように判断しているのでしょうか。 中の動きが一番わかりやすかったのが、agent-browserです。 結論からいうと、AIは画面を人間のように目で見ているわけではないそうです。agent-browserはHTMLをもとに画面の部品の一覧表を作り、そこに番号を振って、AIとの共通の認識を揃えているみたいな感じらしいです。AIは番号で「どこを操作するか」を伝え、agent-browserはその番号の部品を操作します。画面が変わったら一覧表を作り直し、番号も振り直します。 たとえばお問い合わせフォームにメールアドレスを入れて送信するとき、AIは裏でこんな命令を順番に送っています。 agent-browser open example.com agent-browser snapshot -i agent-browser fill @e3 "test@example.com" agent-browser click @e5 よくわからないのですが!!!!!やっていることは4つだけということです。 ページを開く(open) ページの部品の一覧表をもらう(snapshot) 一覧表を読んで、メールアドレス欄に入力する(fill) 送信ボタンを押す(click) 2で受け取る一覧表は、イメージとしてはこんな形です。入力欄やボタンに、e2 e3 のような番号が振られています。 - 入力欄「会社名」 → e2 - 入力欄「メールアドレス」 → e3 - ボタン「送信」 → e5 AIはこの一覧表を読んで、「メールアドレス欄は e3 だな」「送信ボタンは e5 だな」と判断します。あとは「e3 にこれを入力して」「e5 を押して」と番号で指示するだけです。 レストランにたとえると、agent-browserは番号付きのメニューを渡してくれる店員さんで、AIはメニューを読んで「3番ください」と注文するお客さんです。何を選ぶかを決めるのはお客さん(AI)で、店員さん(agent-browser)は注文どおりに動きます。 つまり、agent-browser自体が「ここはメールアドレス欄だ」と判断しているわけではありません。 agent-browserの役割:ページを一覧表にしてAIに渡すことと、AIが選んだ操作を実行すること AIエージェントの役割:一覧表を読んで、どこに何を入れるかを判断すること この役割分担は、ego liteやClaude in Chromeでも変わりません。 5.終わりに エージェントブラウザのことがわかったので、業務に活用していこうと思います!! 主に検証での使用が多いのですが、活用方法を広げていければと思います。 それとブラウザではなくパソコンをちょくで触れると最近流行りのagent-desktopも使ってみたいです! 参考 citrolabs/ego-lite vercel-labs/agent-browser lilting.ch
skills#278 (by someone else) quite ridiculous—just skim its first two comments, absurd amounts of unnecessary detail and a preposterous solution, all very obviously slop. All that needed to be said was “cloning repositories can take arbitrarily long, so putting a 60 second timeout is obviously wrong”. The rest is worse than posturing. Rather like the issue, this article is written in a tedious style which sure looks sloppy, and I disagree with parts of its conclusions. > The thing is, timeouts need to exist. Infinite waits are bad. Hanging processes are bad. I’m not arguing against timeouts. Since the author won’t, I will. The skills case shouldn’t have a timeout at all: it’s the wrong place and the wrong thing. You rather want to check if it’s still working, and Git has that handled. The problematic case is if it can get stalled waiting for authentication, and I’m not convinced that can happen in a way that needs to be catered for. If it’s interactive, the user will observe the authentication prompt and so the timeout cutting them off is wrong, and if it’s not interactive then it should fail immediately. I’m inclined to presume it’s slop-style cargo-culting (in which area Chesterton’s fence is an increasingly unreliable rubric). As for the Docker Gordon case, well, for a human tool I’d just say there shouldn’t be any timeout, it’s obviously dumb, the human will observe if things aren’t working as expected and interrupt it. For AI nonsense, well, this sounds to me like the wrong way to apply a timeout. I would rather expect it to throw an LLM at it and its logs or something to apply judgement like the human would, to see if it seems like it’s not working or stuck and interrupt it. A hard timeout is obviously idiotic, but a timeout at all feels from the wrong era of computing for such a thing.
Vercel agent-desktop: computer use for coding agents through the accessibility tree Vercel Labs released agent-desktop this week, a free, open source tool that gives AI coding agents computer use on macOS, Windows and Linux. Chris Tate, who built Vercel's agent-browser, announced it on October 31 and described it as "agent-browser, for your whole computer." The interesting part is not that an agent can click buttons. It is how it sees the screen: through the operating system's accessibility tree, with no screenshots and no pixel matching. What actually shipped agent-desktop is a Rust CLI plus a C library, on npm as version 1.0.2 under Apache-2.0, with native binaries for x64 and ARM64. There is no language model inside it. Any agent that can run shell commands can drive it, so Claude Code, Codex, Cursor's CLI or a plain bash script all qualify. The command set covers observation, clicks and typing, window management, notifications, the clipboard and sessions, about 56 commands in total. Development started in February, led by Lahfir. Version 1.0 with Linux support shipped on October 28, and 1.0.2 followed on October 30. Refs, not pixels The core loop is observe, act, observe again: agent-desktop snapshot --app Finder -i # interactive elements, each with a ref agent-desktop click @s8f3k2p9:e8 # act on a ref from that snapshot agent-desktop snapshot --app Finder -i # observe again to verify A snapshot returns JSON with a ref for every element the agent can act on. The agent acts on a ref, then takes a new snapshot to check the result. Nothing is inferred from pixels. The tool reads the AX API on macOS, UI Automation on Windows and AT-SPI on Linux, so it sees the same UI structure a screen reader sees, with roles and states the OS already maintains. Errors an agent can actually handle Refs belong to the snapshot that produced them. When the UI shifts before an action lands, you do not get a wrong click, you get a machine-readable error: STALE_REF or AMBIGUOUS_TARGET. If several windows match, the error lists the candidate window ids in error.details, and you pass one back with --window-id. A bare @e8 without its snapshot prefix is rejected with INVALID_ARGS. This is the part I would underline for anyone wiring agents to GUIs. Vision-based computer use fails silently: the model clicks the wrong coordinate and you find out downstream, if you find out at all. Here every failure mode has a code and a defined recovery: take a new snapshot, use its refs. Actions are safe to retry because refs stay stable, which is exactly the property you want in an unattended loop. Dense apps: skeleton first, then drill down A full accessibility tree of an Electron app is big. The skeleton traversal work merged into the project measured it: a Slack skeleton snapshot is about 3.6KB versus roughly 17.3KB for the full tree, a 78-96% token saving on dense Electron apps. The pattern is to map first, then drill in: agent-desktop snapshot --skeleton --app Slack -i --compact agent-desktop snapshot --root @s8f3k2p9:e3 -i --compact The skeleton gives a shallow overview with child counts on truncated containers. --root starts a traversal from a previously discovered ref, so you only pay tokens for the region you are working in. For an agent on a token budget, this is the difference between a tool you can leave running and one you babysit. Wiring it to an existing agent Install is npm install -g agent-desktop. The binary carries its own docs, matched to its version: agent-desktop skills get desktop # the loop, refs, verification and retry rules agent-desktop skills get platform # what differs on the OS you run on You can install the bundled skill into a harness with npx skills add https://github.com/vercel-labs/agent-desktop --skill agent-desktop. Two details worth knowing before you script it. Actions run headless by default: they go through the accessibility API without moving the pointer or stealing focus, and --headed opts into real input. And on PowerShell, quote every ref, because a bare @token is the splatting operator. Platform reality check The platform table in the repo readme is honest about gaps. macOS needs an Accessibility grant, and agent-desktop permissions --guide walks you through it. Windows needs no grant for apps at your terminal's integrity level. Linux needs at-spi2-core in your graphical session; mouse input is X11 only or --headed, the Wayland clipboard needs wl-clipboard, and notifications go through GNOME Shell. Apps without an accessibility tree are invisible to it, and it does not automate web pages, that is what agent-browser is for. Take the data exposure seriously Snapshots, screenshots and clipboard reads can contain private data, and the project's own docs warn against routing them into public logs. An optional helper called JEV sends screen descriptions to a configured model provider. Sit with that for a second: this tool reads your screen the way a screen reader does, and it hands what it reads to whatever agent invoked it. An agent with agent-desktop plus shell access effectively holds your user account. I wrote about where that boundary sits when Nvidia moved agent execution into the kernel, and about the guardrail details to check before letting Copilot click your desktop. The same logic applies here: run it in a dedicated environment where the blast radius is a test account, not your daily driver. When I would reach for it Not for anything with an API. If the thing you are driving exposes an MCP server, a CLI or an HTTP endpoint, use that instead, it will be cheaper and more reliable. agent-desktop earns its keep on apps with no automation surface at all: installers, vendor tools, that one dialog box your CI cannot get past. The observe-act-observe loop with structured errors is the same verification discipline I want in every agent workflow, and now it extends to GUIs. That is the real news here, not the clicking.