agent-desktop is a command-line tool that lets AI agents inspect and control desktop applications through operating-system accessibility data instead of screenshots or pixel matching. It is used to automate applications such as Finder, Safari, Xcode, and Slack with structured JSON commands and results.
Getting it into your agent
It runs from inside its repository, so the clone comes first — what it calls does not travel with the file alone.
git clone --depth 1 https://github.com/lahfir/agent-desktopnpx agentmods add skills/lahfir/agent-desktop/jev-desktopWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/lahfir/agent-desktop/jev-desktop)<a href="https://agentmods.dev/skills/lahfir/agent-desktop/jev-desktop"><img src="https://agentmods.dev/badge/skills/lahfir/agent-desktop/jev-desktop/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/lahfir/agent-desktop/jev-desktop"><img src="https://agentmods.dev/badge/skills/lahfir/agent-desktop/jev-desktop.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00109 | $0.03168 |
| Opus 5.5 | $0.00044 | $0.01267 |
| Sonnet 5.5 | $0.00022 | $0.00634 |
| Haiku 4.5 | $0.00011 | $0.00317 |
Grade A, and why
jev-desktop scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 11d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 234 lines — stays where its author put it; the contents beside it link to each section on GitHub.
jev-desktop
Two entry points over the same screen reading. run.mjs takes a goal and drives
until it is met. act.mjs takes one step and hands the plan back to you. Neither
puts the tree in your context.
The loop
node scripts/jev/run.mjs --app Finder "open the Applications folder"
node scripts/jev/run.mjs --app TextEdit --cursor --text "A line to write." "write the supplied sentence into the document"
Each turn reads the screen, asks for one operation and a target for that operation in the same request, carries it out, and reads again. It prints one JSON line per turn and one when it stops.
{"turn":{"step":1,"operation":"CLICK","target":"treeitem \"Applications\"",
"confidence":1,"ok":true,"delivery":"delivered_verified","changed":true}}
{"stop":"done","confidence":0.96}
The operations are CLICK, TYPE_TEXT, CHECK, UNCHECK, EXPAND,
COLLAPSE, SCROLL, DRILL, WIDEN, WAIT, DONE and BLOCKED. Only the
ones something on screen can receive are offered.
The target is asked once per operation. click_target is chosen from the
elements that advertise Click, type_text_target from those that advertise
SetValue, and so on. Only the head matching the chosen operation is read, so a
target can never be incompatible with the verb that acts on it. That is the
whole reason the loop does not need to correct itself afterwards.
Looking is an operation. A window is read with --skeleton first, so a
document holding four thousand elements costs the same first look as a panel
holding thirty. A region that was cut off reports how much it holds, and DRILL
pins it as the root for later turns. WIDEN gives the whole window back.
CHECK and UNCHECK instead of a toggle. Both are idempotent, so a box
already in the wanted state stays there and the policy never reasons about the
current one.
You supply the text. Nothing here writes a value, so a run never puts a
string on screen that you did not choose. Pass --text once per value and they
are consumed in order, or pass a function as the text option and it is asked
for each field with that field's description. When there is no value left to
give, TYPE_TEXT is not offered at all, so the run stops rather than inventing
one.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 11d ago Changed · +8 lines 3f3b83c24461
- 22d ago Changed · +22 lines 92ee97aebc33
- 28d ago First seen · 204 lines · 109 tokens per session scan A f1b9a40d348f
jev-desktop is a skill published in the GitHub repository lahfir/agent-desktop (1,797 stars, last pushed 2d ago), licensed Apache-2.0. It adds 109 tokens to every session and 3,168 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-18.
Other skills, from other repositories
kwin-desktop-automation
Use when the user asks to launch, click, type, screenshot, or otherwise drive a Linux KDE Plasma / Wayland desktop app through the kwin-mcp MCP server. Trigger when kwin-mcp tools are available and the task involves desktop GUI automation, end-to-end GUI testing, kiosk / embedded device control, or live KDE Plasma…
hatch3r-browser-verify
Opt-in browser verification skill — spec-run-first Playwright verification (assertions execute in the runner, agent reads only failures), axe-core a11y audits, toHaveScreenshot() regression diffs, E2E test scaffolds, and snapshot-mode exploratory driving. Default ON for UI-affecting agent invocations; disable globally…
tauri-pilot
Inspect, interact with, and test a running Tauri v2 app via CLI. Communicates over Unix socket using JSON-RPC 2.0. Use when testing UI, automating interactions, or debugging a Tauri app.
computer-use
A set of rules for controlling Windows desktop applications through screen observation and simulated mouse and keyboard actions. It also describes how to find and launch installed applications and verify the results.
web-navigator
A browser-automation routing guide for web tasks. It directs navigation, page inspection, and actions such as clicking or filling forms to the appropriate browser tool.
pagouse
Observe and (with a grant) drive Chromium tabs via the pagouse CLI: snapshot the accessibility tree, click/fill by ref, navigate. Not a seat adapter. Trigger keywords: pagouse, browser tab, fill form, click the button on the page, snapshot page, AX tree.