# Your Agent Can Use Any App. For a Quarter Fewer Tokens.

computer-cli, the computer-use tool your agent calls, used 26% fewer input tokens than Cua's MCP server on 20 hard OSWorld tasks, at the same pass rate.

Muqsit Nawaz, 2026-10-20

![A brass desk lamp lights a leather notebook and a glass of water on a dark wooden desk, beside the words "Your agent can use any app." and the computer-cli install command.](/hero-computer-cli-osworld.webp)

Most apps have no API. Most have no MCP server either.

Your agent can still use them. [computer-cli](https://www.npmjs.com/package/@phnx-labs/computer-cli), the computer-use tool your agent calls, drives the screen and keyboard like a person would.

We ran it on 20 hard OSWorld tasks, three times each, against [Cua](https://github.com/trycua/cua)'s MCP server. Same model, same tasks.

computer-cli passed 88%, Cua 84%. Two passes in 58 runs is within chance, so call it a tie.

The savings are the real story: 16% lower cost, 26% fewer input tokens, 20% fewer model calls.

On these tasks, a $10M bill would have come to $8.4M.

Across the benchmark, that's 10.4 million tokens your agent didn't have to read.

<style>.ccl-figure{margin:2.5rem 0}.ccl-fig{display:block;width:100%;height:auto;font-family:Inter,system-ui,sans-serif}.ccl-fig .ccl-h{font-family:var(--font-display),Jost,sans-serif;font-weight:500;font-size:24px;letter-spacing:.02em;text-transform:uppercase}.ccl-fig .ccl-m{font-size:20px}.ccl-fig .ccl-s{font-size:18px}.ccl-fig .ccl-xs{font-size:16px}.ccl-fig .ccl-b{font-weight:600}.ccl-figure figcaption{font-size:14px;color:var(--t-caption,#665E52);margin-top:.75rem;text-align:center}</style>

<figure class="ccl-figure">
<svg class="ccl-fig" viewBox="0 0 720 470" role="img" aria-labelledby="ccl-f1t ccl-f1d"><title id="ccl-f1t">computer-cli against Cua MCP on 20 hard OSWorld-Verified tasks</title><desc id="ccl-f1d">Tasks passed 88 percent against 84. Input tokens per run 499 thousand against 679 thousand. Cost per run 0.165 dollars against 0.196. Model calls per run 14.3 against 17.8.</desc><text x="24" y="34" class="ccl-h" fill="var(--t-text,#141829)">Same tasks, same model, same checker</text><rect x="24" y="52" width="14" height="14" fill="var(--t-accent,#7A6230)"/><text x="46" y="64" class="ccl-s" fill="var(--t-text,#141829)">computer-cli 0.1.12</text><rect x="250" y="52" width="14" height="14" fill="var(--t-text,#141829)" opacity="0.32"/><text x="272" y="64" class="ccl-s" fill="var(--t-text,#141829)">Cua MCP server</text><text x="24" y="118" class="ccl-m ccl-b" fill="var(--t-text,#141829)">Tasks passed</text><text x="24" y="142" class="ccl-xs" fill="var(--t-caption,#665E52)">higher is better</text><rect x="250" y="104" width="290.4" height="20" fill="var(--t-accent,#7A6230)" opacity="1"/><text x="548.4" y="120" class="ccl-s" fill="var(--t-text,#141829)">88% (51/58)</text><rect x="250" y="132" width="277.2" height="20" fill="var(--t-text,#141829)" opacity="0.32"/><text x="535.2" y="148" class="ccl-s" fill="var(--t-caption,#665E52)">84% (49/58)</text><text x="24" y="206" class="ccl-m ccl-b" fill="var(--t-text,#141829)">Input tokens per run</text><text x="24" y="230" class="ccl-xs" fill="var(--t-caption,#665E52)">lower is better</text><rect x="250" y="192" width="242.8" height="20" fill="var(--t-accent,#7A6230)" opacity="1"/><text x="500.8" y="208" class="ccl-s" fill="var(--t-text,#141829)">499k</text><rect x="250" y="220" width="330.0" height="20" fill="var(--t-text,#141829)" opacity="0.32"/><text x="588.0" y="236" class="ccl-s" fill="var(--t-caption,#665E52)">679k</text><text x="24" y="294" class="ccl-m ccl-b" fill="var(--t-text,#141829)">Cost per run</text><text x="24" y="318" class="ccl-xs" fill="var(--t-caption,#665E52)">lower is better</text><rect x="250" y="280" width="277.8" height="20" fill="var(--t-accent,#7A6230)" opacity="1"/><text x="535.8" y="296" class="ccl-s" fill="var(--t-text,#141829)">$0.165</text><rect x="250" y="308" width="330.0" height="20" fill="var(--t-text,#141829)" opacity="0.32"/><text x="588.0" y="324" class="ccl-s" fill="var(--t-caption,#665E52)">$0.196</text><text x="24" y="382" class="ccl-m ccl-b" fill="var(--t-text,#141829)">Model calls per run</text><text x="24" y="406" class="ccl-xs" fill="var(--t-caption,#665E52)">lower is better</text><rect x="250" y="368" width="265.1" height="20" fill="var(--t-accent,#7A6230)" opacity="1"/><text x="523.1" y="384" class="ccl-s" fill="var(--t-text,#141829)">14.3</text><rect x="250" y="396" width="330.0" height="20" fill="var(--t-text,#141829)" opacity="0.32"/><text x="588.0" y="412" class="ccl-s" fill="var(--t-caption,#665E52)">17.8</text><text x="24" y="458" class="ccl-xs" fill="var(--t-caption,#665E52)">Each metric drawn from zero on its own scale. Run on 2026-10-20.</text></svg>
<figcaption>58 scored runs per tool. The 2 runs per tool that hit the 100-turn cap, all on one task, are unscored by OSWorld's checker; counting them as failures gives 51/60 against 49/60.</figcaption>
</figure>

## What OSWorld measures

[OSWorld](https://os-world.github.io/) is the benchmark most computer-use agents get measured on.

Each task boots a real Ubuntu machine with real apps: LibreOffice, Thunderbird, GIMP, Chrome, VS Code. The agent gets an instruction, like "create a pivot table in a new sheet that counts each invoice number." When it stops, a script checks the files and settings it left behind.

No partial credit.

We drew 20 tasks from the hardest domains: multi-app workflows, LibreOffice Calc, Writer and Impress, and Thunderbird. Claude Sonnet 5.5 did the work in Claude Code both times. The only thing we changed was the computer-use tool it could call: `computer mcp` from computer-cli 0.1.12, or Cua's `cua mcp`.

## Task by task

computer-cli used fewer model calls on 15 of the 20 tasks.

The gap is widest on the long multi-app tasks. Setting an emailed document's image as the wallpaper took 23 calls with computer-cli and 42 with Cua. Brightening a slide's image and saving it took 13 against 22.

<figure class="ccl-figure">
<svg class="ccl-fig" viewBox="0 0 560 1186" role="img" aria-labelledby="ccl-f2t ccl-f2d"><title id="ccl-f2t">Mean model calls per task, computer-cli against Cua MCP</title><desc id="ccl-f2d">For each of the 20 tasks, a gold dot for computer-cli and a grey dot for Cua MCP at the mean number of model calls over its scored runs, with passes out of scored runs. computer-cli used fewer calls on 15 of the 20 tasks.</desc><text x="24" y="34" class="ccl-h" fill="var(--t-text,#141829)">Model calls per task</text><circle cx="31" cy="62" r="7" fill="var(--t-accent,#7A6230)"/><text x="46" y="68" class="ccl-s" fill="var(--t-text,#141829)">computer-cli</text><circle cx="207" cy="62" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><text x="222" y="68" class="ccl-s" fill="var(--t-text,#141829)">Cua MCP</text><line x1="24.0" x2="24.0" y1="102" y2="1142" stroke="var(--t-edge,#DCD2C3)" stroke-width="1"/><text x="24.0" y="94" text-anchor="start" class="ccl-xs" fill="var(--t-caption,#665E52)">0</text><line x1="152.0" x2="152.0" y1="102" y2="1142" stroke="var(--t-edge,#DCD2C3)" stroke-width="1"/><text x="152.0" y="94" text-anchor="middle" class="ccl-xs" fill="var(--t-caption,#665E52)">25</text><line x1="280.0" x2="280.0" y1="102" y2="1142" stroke="var(--t-edge,#DCD2C3)" stroke-width="1"/><text x="280.0" y="94" text-anchor="middle" class="ccl-xs" fill="var(--t-caption,#665E52)">50</text><line x1="408.0" x2="408.0" y1="102" y2="1142" stroke="var(--t-edge,#DCD2C3)" stroke-width="1"/><text x="408.0" y="94" text-anchor="middle" class="ccl-xs" fill="var(--t-caption,#665E52)">75</text><line x1="536.0" x2="536.0" y1="102" y2="1142" stroke="var(--t-edge,#DCD2C3)" stroke-width="1"/><text x="536.0" y="94" text-anchor="end" class="ccl-xs" fill="var(--t-caption,#665E52)">100</text><text x="24" y="120" class="ccl-xs" fill="var(--t-text,#141829)">Grade students from a scale table<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="49.6" x2="53.2" y1="136" y2="136" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="53.2" cy="136" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="49.6" cy="136" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="172" class="ccl-xs" fill="var(--t-text,#141829)">Star every email in a folder<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="49.6" x2="59.8" y1="188" y2="188" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="59.8" cy="188" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="49.6" cy="188" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="224" class="ccl-xs" fill="var(--t-text,#141829)">Bookmark four authors' homepages<tspan fill="var(--t-caption,#665E52)">  ·  2/3 vs 2/3</tspan></text><line x1="153.5" x2="196.5" y1="240" y2="240" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="196.5" cy="240" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="153.5" cy="240" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="276" class="ccl-xs" fill="var(--t-text,#141829)">Set a document to Times New Roman<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="53.2" x2="66.5" y1="292" y2="292" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="66.5" cy="292" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="53.2" cy="292" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="328" class="ccl-xs" fill="var(--t-text,#141829)">GitHub project setup (1 scored run each)<tspan fill="var(--t-caption,#665E52)">  ·  0/1 vs 1/1</tspan></text><line x1="157.1" x2="515.5" y1="344" y2="344" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="515.5" cy="344" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="157.1" cy="344" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="380" class="ccl-xs" fill="var(--t-text,#141829)">Personalize an academic homepage<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="136.6" x2="222.1" y1="396" y2="396" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="136.6" cy="396" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="222.1" cy="396" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="432" class="ccl-xs" fill="var(--t-text,#141829)">Open Thunderbird's profile manager<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="107.5" x2="152.0" y1="448" y2="448" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="152.0" cy="448" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="107.5" cy="448" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="484" class="ccl-xs" fill="var(--t-text,#141829)">Add a bullet point to a slide<tspan fill="var(--t-caption,#665E52)">  ·  1/3 vs 1/3</tspan></text><line x1="56.3" x2="75.2" y1="500" y2="500" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="75.2" cy="500" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="56.3" cy="500" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="536" class="ccl-xs" fill="var(--t-text,#141829)">Set an emailed image as wallpaper<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="143.3" x2="239.0" y1="552" y2="552" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="239.0" cy="552" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="143.3" cy="552" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="588" class="ccl-xs" fill="var(--t-text,#141829)">Save slides as pre.pptx<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="70.1" x2="75.2" y1="604" y2="604" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="70.1" cy="604" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="75.2" cy="604" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="640" class="ccl-xs" fill="var(--t-text,#141829)">Align text on slides 3, 4 and 5<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 1/3</tspan></text><line x1="81.9" x2="126.4" y1="656" y2="656" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="126.4" cy="656" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="81.9" cy="656" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="692" class="ccl-xs" fill="var(--t-text,#141829)">Compute ages from birthdays<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="49.6" x2="51.1" y1="708" y2="708" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="49.6" cy="708" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="51.1" cy="708" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="744" class="ccl-xs" fill="var(--t-text,#141829)">Transpose a table to B8<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="59.8" x2="83.9" y1="760" y2="760" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="59.8" cy="760" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="83.9" cy="760" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="796" class="ccl-xs" fill="var(--t-text,#141829)">Add "Page 1" to slide 2<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 2/3</tspan></text><line x1="53.2" x2="63.4" y1="812" y2="812" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="63.4" cy="812" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="53.2" cy="812" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="848" class="ccl-xs" fill="var(--t-text,#141829)">Fill reading times from a website<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="78.8" x2="99.3" y1="864" y2="864" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="99.3" cy="864" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="78.8" cy="864" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="900" class="ccl-xs" fill="var(--t-text,#141829)">Format a column to two decimals<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="68.5" x2="75.2" y1="916" y2="916" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="75.2" cy="916" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="68.5" cy="916" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="952" class="ccl-xs" fill="var(--t-text,#141829)">Crop an image in GIMP from a shell<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="92.1" x2="124.9" y1="968" y2="968" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="124.9" cy="968" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="92.1" cy="968" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="1004" class="ccl-xs" fill="var(--t-text,#141829)">Convert Word references to LaTeX<tspan fill="var(--t-caption,#665E52)">  ·  0/3 vs 0/3</tspan></text><line x1="127.9" x2="213.4" y1="1020" y2="1020" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="127.9" cy="1020" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="213.4" cy="1020" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="1056" class="ccl-xs" fill="var(--t-text,#141829)">Brighten a slide's image<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="92.1" x2="138.2" y1="1072" y2="1072" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="138.2" cy="1072" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="92.1" cy="1072" r="7" fill="var(--t-accent,#7A6230)"/><text x="24" y="1108" class="ccl-xs" fill="var(--t-text,#141829)">Count invoices with a pivot table<tspan fill="var(--t-caption,#665E52)">  ·  3/3 vs 3/3</tspan></text><line x1="97.2" x2="136.6" y1="1124" y2="1124" stroke="var(--t-text,#141829)" stroke-opacity="0.25" stroke-width="2"/><circle cx="136.6" cy="1124" r="7" fill="var(--t-text,#141829)" opacity="0.4"/><circle cx="97.2" cy="1124" r="7" fill="var(--t-accent,#7A6230)"/></svg>
<figcaption>Each row is one task: dots at the mean model calls over its scored runs, and passes out of scored runs after the task name, computer-cli first. The GitHub task has one scored run per tool; its other four runs hit the 100-turn cap.</figcaption>
</figure>

## Where the tokens go

A computer-use agent pays for every screenshot it looks at. Then it keeps paying, because each image stays in the context the model rereads on every later call.

So fewer calls and fewer images compound. Four things in how computer-cli's MCP server works are the likely reasons. We didn't run an ablation, so we can't tell you how much each one is worth.

- **One call acts and looks.** Every action returns the screen after it (since 0.1.6), once the screen has stopped changing (since 0.1.10). The agent never spends a call just to check that a click landed.
- **Several actions, one image.** When the agent sends a burst of actions, all but the last skip the screenshot with `screenshot: false` (0.1.11). Five steps cost one image, not five.
- **A whole row in one go.** `type-text` types `\t` as Tab and `\n` as Enter (0.1.11). A spreadsheet row or a form fills in one call. Before that, those keys went out as codes the machine ignored, and the agent retyped cell by cell.
- **Click where you look.** Screenshots come back 1280 pixels wide. The agent clicks in those pixels and the server maps them to the real 1920×1080 screen (0.1.11). No math for the model to get wrong.

0.1.12, the version we tested, only made screenshots faster to capture. That changes time, not tokens.

Here's one Calc task (sum two columns into a new sheet), on our first cut and on the released build. Both passed.

<div class="learn-comparison">
  <div class="learn-comparison-row">
    <span class="learn-comparison-label">First cut</span>
    <span class="learn-comparison-value">9 model calls, $0.143: the two typed rows lost their tabs and newlines, so it cleared them and retyped every cell</span>
  </div>
  <div class="learn-comparison-row">
    <span class="learn-comparison-label">Released 0.1.11</span>
    <span class="learn-comparison-value">5 model calls, $0.054: look, add a sheet, type both rows in one call, done</span>
  </div>
</div>

## How we kept it honest

If you pick tasks after you see where you win, you're fooling yourself. So we wrote the rule down before any agent ran. Times are UTC, October 20, 2026.

- **09:46.** The [rule](/benchmarks/osworld-hard20/RULE.txt) is written: the pool (OSWorld-Verified `test_all` at commit `b138d34`, the six domains), the exclusions, seed `20261020`, the draw, the tools, three trials, and scoring by OSWorld's own checker.
- **09:47 to 09:54.** A run with no agent walks the seeded order and keeps the first 20 tasks that set up and score cleanly. All 20 did ([walk.txt](/benchmarks/osworld-hard20/walk.txt)).
- **09:54.** The [task list](/benchmarks/osworld-hard20/tasks.txt) is frozen. Its SHA-256 is `d1520f7f777797bfae64f0d5c47aea2baac996c2ba63f526847532c562894c5a`.
- **09:55.** The first agent run starts. 120 runs follow, each on a fresh machine.

We left out the 39 tasks in OSWorld's `test_small` split, because we used them while building 0.1.11 and 0.1.12. We also left out Google Drive, infeasible and container-degraded tasks.

One environment fix applied to both tools: Chrome and VS Code can't start in Cua's stock OSWorld container under Docker's default security profile, so both started with `--no-sandbox` ([Dockerfile.txt](/benchmarks/osworld-hard20/Dockerfile.txt)).

Every run is in [results.txt](/benchmarks/osworld-hard20/results.txt), with its metrics in [runs.csv](/benchmarks/osworld-hard20/runs.csv). `python3 score.py runs.csv` reproduces [score.txt](/benchmarks/osworld-hard20/score.txt) from those files alone ([score.py](/benchmarks/osworld-hard20/score.py)). [DEVIATIONS.txt](/benchmarks/osworld-hard20/DEVIATIONS.txt) lists what didn't go to plan: a first launch that failed before any agent started, two debug runs we excluded, and how we scored runs that hit the turn cap. [README.txt](/benchmarks/osworld-hard20/README.txt) explains every file.

## Where Cua does better

Speed. On the scored runs it's a tie: 52.8 seconds per run for us, 51.5 for Cua. Count the four runs that hit the turn cap and we're 14% slower, 62.0 seconds against 54.2. Our two capped runs took 329 and 330 seconds; Cua's took 139 and 130.

Our time per action includes waiting for the screen to settle and capturing it over VNC. Cua's tool calls returned faster in our runs. 0.1.12 halved our capture time; the settle wait is next.

Cua also needed far fewer calls on three tasks. Converting a Word reference list to LaTeX took it 20 calls to our 37 (neither passed). An academic homepage took 22 to our 39. Transposing a table took 7 to our 12.

And on setting up a GitHub project's Python environment, Cua passed once. We never did.

## Try it

```bash
npm i -g @phnx-labs/computer-cli

# any VNC machine, as an MCP server for Claude Code
claude mcp add computer -- computer mcp --host vnc://localhost:5901
```

The same tool drives Mac apps through Accessibility and Windows apps over SSH. It's the computer your agent uses on Rush when a job needs one: a real machine in its own sandbox, and the result back with the trajectory behind it.
