Deep Dive · Computer use

agent-desktop v1.1: Refs, Headless by Default, and What a Computer-Use CLI Actually Costs

Vercel Labs' computer-use CLI reads the accessibility tree instead of guessing pixels, and v1.1 fixed the one thing that made refs fragile. This is a practitioner's update: what changed release by release, why skeleton mode is a token-economy decision, the four commands that refuse to run, and the two interfaces — MCP and a C library — the video never mentions.

Vercel's new open source library might have solved computer use — video thumbnail
Video: AISeeKing 8:43 6 November 2026
agent-desktop Accessibility tree Headless Apache-2.0

🚫 Why screenshots break 0:00

The standard computer-use loop takes a picture of your screen, guesses where the button is, moves the mouse to a pixel, clicks, and takes another picture. It is slow, it burns tokens on images, and if a window moves a little the whole thing breaks.

agent-desktop from Vercel Labs takes the other route: it reads the operating system's accessibility tree — the same structured data screen readers use — where every button, field, checkbox and menu item already exists as data with a role, a name, and the actions it supports. Written in Rust, Apache-2.0, macOS / Windows / Linux.

This is a follow-up, not a first look. The launch of agent-desktop (v1.0, Prism Labs' coverage) is already covered in this earlier deep dive, which covers the snapshot format, the safety-by-refusal design and the eight-month path to 1.0. This article sticks to what is new and what is operationally useful now: the v1.1 delta, the token economics of skeleton mode, and the interfaces the video does not cover.

🔄 The loop, and where it lives 1:18

Three commands, repeated: snapshot --app Notes returns JSON where every actionable element carries a ref; the agent acts on a ref; a new snapshot verifies the result. Observe, act, observe.

"There is no pixel matching anywhere in that loop, and the loop stays in your agent. agent-desktop is just the tool, not the agent."
That design decision is the reason the tool is composable. It has no model inside and no opinion about who is driving. Any agent that can run a shell command — or, as below, call MCP or link a C library — can use it, and the retry policy stays where you can see it, in your own code.

🔖 Refs: identity, and refusal 1:42

A ref is scoped to the snapshot it came from — it looks like @s8f3k2p9:e8, a snapshot id, a colon, and an element number. That scoping is what makes the tool safe:

SituationWhat agent-desktop doesWhat the agent must do
The UI changed and the ref now points elsewhereReturns STALE_REF — refuses to clickTake a new snapshot
Several windows could matchReturns AMBIGUOUS_TARGET, with candidate window ids in error.detailsRe-issue with an explicit window
A bare element number is used without a snapshot idRejects with INVALID_ARGSAlways use the full ref
The ref is validPerforms the actionSnapshot again to verify
"A wrong click is way worse than no click."

That ordering — refuse, then let the agent recover — is what separates a demo from something you would point at a real account. An agent that guesses is worse than an agent that stops.

👻 Headless, and skeleton mode 2:08

Two defaults do most of the practical work, and neither is about intelligence.

DefaultWhat it meansWhy it matters
Headless by defaultRef-based actions go through the accessibility API — no pointer movement, no focus stealing. A global --headed flag enables physical input.You keep working in another window while the agent drives a background app
Skeleton modesnapshot --skeleton --app Slack -i --compact gives a shallow map; snapshot --root @s8f3k2p9:e3 -i --compact drills into one regionKeeps snapshots small: fewer tokens, less confused model
Skeleton mode is a context-management technique, not a convenience flag. A dense app's full tree is thousands of lines of JSON. Mapping shallow first and drilling into one subtree turns an unbounded context problem into a bounded one — and it is the same pattern as progressive disclosure in a UI, applied to the agent's view of a UI.

⌨️ 60 commands, four that refuse 2:43

The surface is bigger than "click and type", and the breakdown is worth seeing because it tells you what the designers thought a real workflow needs.

CategoryCommands
Observesnapshot, find, get, screenshot
Act on a refclick, double-click, triple-click, right-click, type, set-value, clear, focus, select, toggle, check, uncheck, expand, collapse, scroll, scroll-to
Keyboard and mouseKey presses, text entry with --interval-ms, physical input under --headed
Apps and windowsApp listing, window management, notifications, clipboard
Orchestrationawait, batch (many actions in one call)
Sessionssession, trace, cursor-overlay
A detail the video omits: of the 60 command names, 56 are operational. The other four — key-down, key-up, mouse-down, mouse-up — refuse to run until a daemon can release a held key or button. Shipping the names as explicit failures rather than leaving them out means an agent gets a clear error instead of inventing a fallback like "hold shift by typing shift repeatedly".

🧾 The error envelope 3:05

Every command prints one JSON envelope: ok, plus either data or an error. The errors carry a code, usually a suggestion, and a retry field — and the agent should only retry when that field says it is safe.

That one field prevents the worst class of computer-use bug: double submission. A retry after an ambiguous click on a payment button, a form submit or a "delete" confirmation is far worse than a failure. Encoding retryability in the protocol, per error, is the single design choice most computer-use tools get wrong — and it is cheap to copy in your own tool schemas.

🆕 What actually changed in 1.1 3:21

The video lists the 1.1 highlights. Checked against the release notes, most hold — but one item is bigger than it is made to sound, and the version is already one ahead.

ChangeVerifiedWhy it matters
Dock, menu-bar status items and system panels reachable on macOSYes — v1.1.0Apps that live only in the menu bar become drivable
type --interval-ms to type at a steady paceYes — v1.1.0Fixes apps that drop characters on instant paste
Cursor overlay: label pill, click ripple, insertion caretYes — v1.1.0Human-readable supervision of a headless run
Every CLI call runs in its own process; the old macOS command host is goneYes — v1.1.0No shared long-lived host to go stale or crash
Refs re-identified through the element's own accessibility address; Linux and Windows refs resolved through a capture ruleYes — v1.1.0The real headline: refs survive UI churn better, so fewer restart-the-loop rounds
Sessions and tracing, optionally with before/after screenshots per actionYes — session, traceYou can see exactly which step broke a run
A C library so you can call it without starting the CLI each timeYes — libagent_desktop_ffi ships per releaseRemoves per-call process overhead entirely
"Just hit version 1.1"Correct but stalev1.2.0 followed on 5 November: list-row selection, and the cursor overlay drawing above menus
"More than 10,000 stars"Understated~17,900 stars at the time of writing; first commit 19 February 2026

📦 A binary that carries its own docs 4:11

Installation is one npm package; the interesting part is how the tool teaches the agent to use it.

StepCommand / requirement
Installnpm install -g agent-desktop, then agent-desktop version (Homebrew also available on macOS and Linux)
Permissionsagent-desktop permissions --guide walks through the macOS accessibility grant; Windows usually needs none; Linux uses AT-SPI in your graphical session
Teach the agentagent-desktop skills get desktop prints the loop, the ref rules and the retry rules matched to the installed version; skills get platform prints what differs on your OS
Wire it inInstall the skill (npx skills add) or add two lines to AGENTS.md telling the agent to read those skills first
skills get desktop is the pattern worth stealing. The binary ships the documentation for agents, version-matched to the build, printed on demand. That removes the classic failure where the model reads an outdated README and calls flags that no longer exist — and it costs one subcommand.

🕳 What the video leaves out 4:55

Two interfaces and three platform facts are missing from the walkthrough, and they change who can use this.

OmittedDetailWhy you care
MCP serveragent-desktop mcp serves every command as an MCP tool over stdio — desktop_snapshot, desktop_click, desktop_session_start — with global flags like --session, --headed, --trace applying to every callAny MCP client gets computer use without a shell or a skill file; no per-agent integration work
C librarylibagent_desktop_ffi ships with each release; call it in process via ctypes/FFITurns per-action process startup into a function call — the difference for high-frequency loops
Platform mappingmacOS AX API, Windows UI Automation, Linux AT-SPI — one core, one platform crate per buildExplains why capabilities differ per OS instead of being bugs
Window-pinned refsAfter an action, the wait observes the ref's original process; refs from a sheet, alert, popover or Linux menu stay pinned to their windowAvoids verifying against the wrong window's state
PowerShell quotingOn Windows, quote every ref ('@s8f3k2p9:e8') because a bare @ token is the splatting operatorA five-minute debugging session avoided

💰 The cost shape of computer use 5:25

The second half of the video is sponsored, promoting a subscription and two desktop products, with pricing and links that are excluded here. The technical argument underneath is worth keeping, because it is not about the sponsor at all:

Loop stylePayload per stepModel requirement
Screenshot loopA full imageA vision-capable model, at image-token prices, every step
Accessibility-tree loopA JSON fragment with refsA text model — a cheap, fast open model is enough
"Computer use is a lot of small steps: snapshot, click, snapshot, type, snapshot. Each step is cheap, but there are a lot of them."
The economic consequence, stated without the sales pitch: moving from pixels to structured text removes the vision requirement and shrinks each step, which turns computer use from "expensive frontier model" into "many cheap calls". That is a genuine capability shift — it means the binding constraint becomes rate limits and loop length rather than image-token cost. Whether a flat-rate subscription or per-token billing is cheaper depends entirely on your step count; do the arithmetic on your own workflow, not on a demo.

🖱 Many cursors, one lease 6:50

Multi-agent mode gives each agent its own cursor and an agent id: --cursor plus --multi-agent. Their cursors move at the same time, but their actual actions take turns, so two agents never type into each other.

Look at what that sentence actually specifies: a lease. Concurrent intent, serialised actuation. It is the same rule a database uses for writes, and it is the minimum viable concurrency model for a shared desktop — the alternative (two agents interleaving keystrokes in one field) is not a feature, it is data corruption.

The video pairs this with an orchestrator that splits a desktop task across workers and reviews the results. Architecturally that is fine; check licences before adopting, since the orchestration tool promoted here declares no OSI licence.

🚧 Limitations 7:33

LimitationConsequence
It is only as good as the app's accessibility treeGames, canvas-based apps and apps with bad labels are hard or impossible
macOS requires the accessibility grantThat is effectively full control of your apps — scope what you let it run
Hover, drag and double-click may need headed modeThen the agent takes your real mouse and focus
Linux has gaps, e.g. mouse input only on X11Wayland workflows are partly out of reach
Snapshots and traces contain whatever is on screenTreat them as sensitive; keep them out of public logs and CI artefacts
An optional helper sends screen descriptions to an external model providerRead what it transmits before enabling it
The privacy point deserves more weight than a passing mention. A snapshot is a structured dump of your desktop: window titles, document names, menu items, message-preview text. Turning an agent loose on your machine and keeping the traces is functionally a keylogger with good intentions. Anything that records before/after screenshots per action should live on encrypted storage with a retention limit you chose.

⚖️ Verdict 8:09

His summary: reads the tree instead of guessing pixels, gives every element a ref, headless by default, tells the agent when retrying is safe, works on all three platforms, free and open source, and fits any agent that can run a command.

Agreed, with one qualification. The strengths are protocol decisions — ref scoping, refusal over guessing, retryability per error, shallow-then-deep snapshots — and those are copyable by anyone building a similar tool. The weakness is structural and not fixable in software: apps that expose nothing to the accessibility tree are invisible to it, and on macOS the permission it needs is the key to everything else.

"It only works as well as the app's accessibility tree."
The right reason to adopt it: not because it is faster in a demo, but because a refusal is auditable. A tool that returns STALE_REF and stops gives you a log you can reason about; a tool that clicks the wrong pixel gives you a mystery. For anything touching real accounts, that difference is the whole product.

✅ Claims checked

ClaimVerdictEvidence
agent-desktop is from Vercel Labs, written in Rust, Apache-2.0, macOS/Windows/LinuxCorrectRepo vercel-labs/agent-desktop: Rust, Apache-2.0, created 19 Feb 2026
It reads the accessibility tree instead of pixels, and ships no modelCorrectREADME: AX API on macOS, UI Automation on Windows, AT-SPI on Linux; "the loop lives in your agent"
Refs are scoped to a snapshot; STALE_REF / AMBIGUOUS_TARGET instead of random clicksCorrectREADME documents both codes, plus INVALID_ARGS for a bare ref and candidate window ids in error.details
Headless by default; --headed for physical inputCorrectREADME, global flags
60 command names, 56 operationalCorrectREADME: "60 command names, 56 operational commands"; the four that refuse are key-down, key-up, mouse-down, mouse-up
Skeleton mode: shallow map, then drill with --rootCorrectREADME example with Slack
Errors carry a code, a suggestion and a retry fieldCorrectJSON envelope: ok plus data or error
v1.1 added dock/menu-bar reach, --interval-ms, better cursor overlay, per-call processes, sessions/tracing, C libraryCorrect, mostly v1.1.0Release notes v1.1.0 (3 Nov 2026): type --interval-ms, insertion caret, label pill, "remove the macOS command host", dock/menu-bar/system panels, ref re-identification via the element's accessibility address; session/trace/C library documented in README
"Just hit version 1.1"Stale by a dayv1.2.0 released 5 Nov 2026 (list-row selection; cursor overlay above menus and system panels)
"More than 10,000 stars"Understated~17,965 stars at the time of writing
Multi-agent mode: per-agent cursors, actions take turnsCorrect--cursor / --multi-agent; an interaction lease serialises actuation
Linux mouse input only on X11; hover/drag may need headedVideo's claim, plausibleConsistent with the platform pages; not individually re-tested here
Sponsor pricing, bundled models and rate limitsCommercial claimsSponsored segment — excluded, not repeated as fact
The orchestration tool promoted at the end is open sourceNot as declaredIt carries a NOASSERTION licence on GitHub — source-available, not OSI open source

Basis note. Built from the full 8:43 transcript, then verified against the repository README, the GitHub releases API (v1.0.0 through v1.2.0) and the live repo metadata. Two figures in the video are out of date by a day or two and are corrected above; the four non-operational commands, the MCP server, the C library and the window-pinning behaviour are additions from the source repository that the video does not cover. Sponsor material is excluded.

🔑 Key takeaways

  • Refuse rather than guess. STALE_REF and AMBIGUOUS_TARGET turn a silent wrong click into a recoverable error — the single most important design choice in the tool.
  • Scope refs to their snapshot. A bare element number is rejected; validity is explicit, so the agent must re-observe before acting.
  • Encode retryability per error. A retry field that says whether retrying is safe prevents double-submitted forms — the worst bug class in computer use.
  • Headless by default changes the workflow, not just the plumbing. The agent drives a background app while you keep your mouse and focus.
  • Skeleton mode is context management. Shallow map, then drill into one subtree — bounded context instead of a thousands-line tree.
  • Ship the docs inside the binary. skills get desktop prints version-matched instructions for the agent, so the model never reads a stale README.
  • v1.1's real headline is ref identity: re-identifying refs through each element's own accessibility address means fewer restarts after the UI shifts.
  • Two interfaces the video misses: agent-desktop mcp exposes all 60 commands as MCP tools over stdio, and libagent_desktop_ffi lets you call it in process from Python or C.
  • Text instead of pixels changes the cost shape: many cheap steps on a fast text model, instead of many expensive image steps on a frontier vision model.
  • Concurrency on a shared desktop needs a lease: cursors may move together, but actuation must take turns — otherwise two agents type into the same field.
  • Treat snapshots and traces as credentials. A structured dump of your desktop is sensitive; encrypt it and set a retention limit.
  • Check versions and licences before quoting a demo. The video is one release behind (v1.2.0 shipped two days later) and both promoted companion tools deserve a licence check.

🔗 Resources

Basis note. Version facts come from the GitHub releases API, not the narration; the video's "just hit 1.1" and "more than 10,000 stars" are corrected above. The MCP server, the C library's per-release artefacts, the four refusing commands and the window-pinning rule are from the repository and are presented as additions, not as the video's claims. Sponsor content — pricing, discounts, product links — is excluded.

⏱ Timestamp index

0:00Why screenshot-based computer use breaks
0:32agent-desktop by Vercel Labs: Rust, Apache-2.0, three platforms
0:52The accessibility tree, not pixels
1:18The loop: snapshot, ref, click
1:42Refs, STALE_REF and AMBIGUOUS_TARGET
2:08Headless by default, and skeleton mode
2:4360 commands, and agent-friendly errors
3:05One JSON envelope, and the retry field
3:21What is new in version 1.1
4:11Setup, permissions, and the built-in skill
4:55Using it from an agent
5:25Cost per step (sponsored segment)
6:24Parallel sessions and scheduled runs
6:50Multi-agent cursors, and orchestration
7:33Limitations: trees, permissions, privacy
8:09Verdict
☰ View all