Most assistants tell you how to do it. Helix opens the app, runs the command, reads the page and comes back with the answer — on your own machine, with your own accounts, while you watch every step.
Windows 10/11 · no account required to install
What it is
Every computer-use agent can move a mouse. The interesting question is what it does instead — because a click is a coordinate guessed against a photograph, and it takes the machine away from the person using it.
"How much disk space is left?" is one PowerShell line and zero clicks. Helix asks the machine and reads the answer, rather than opening Settings and squinting at a screenshot of it.
Web work happens in an off-screen Chrome tab driven through the DevTools protocol — by element, not by pixel. Your browser, your session, and your mouse stays yours.
The planner writes down what it is assuming and what it can't know until it looks. If the request is genuinely ambiguous, it stops and asks instead of guessing which of your three contacts you meant.
The reasoning is a trace, not a spinner: what it restated, what it rejected, what it's watching out for — folded away, openable, live as it runs.
Typed risk classes. Reading is free; sending, buying, deleting and powering off stop for your say-so. A question ("what's running?") never interrupts you.
Send a task and watch the milestones arrive. Or take the screen itself — tap to click, hold to right-click, drag to scroll, type into whatever has focus. The Android app reaches the same 125 endpoints the desktop does, from anywhere, so anything the PC can do it can do too.
What it learned about this machine, and what it knows about you, are retrieved against wherever the run has actually reached — not against the sentence you typed twenty steps ago. All of it inside one budget, so recall cannot quietly grow to outweigh the screenshot it rides on.
Benchmarks
Everything below was measured on one Windows 11 desktop, from the agent's own timing log and from live runs against the real model. Each figure is a before-and-after on the same request — that is the only comparison that controls for the task being easy or hard.
The reasoning was never the bottleneck — think averaged about 5 seconds and never exceeded 12.5. The time was in blocking timeouts: a browser verb that was going to fail took the full 30-second ceiling to say so, and one step spent 120 seconds watching an animation that had already finished.
Three requests, run end to end against the live model before and after. "What's my public IP" was previously refused in chat — the router had no category for a question about your own machine, so it answered "I do not have access to your network information".
The Notepad task got worse before it got better: an early fix made the run try to "present" its answer in a Windows message box — which blocks waiting for a click — three times over. Both the popup habit and the criterion that caused it are fixed.
A light-DOM walk reached 14,472 characters. The composed walk returns 25,033 — the difference is every code example on the page, which MDN renders inside a web component.
Discovering where the shadow roots are was being redone on every single query — four times for one obstacle check. It is now computed once per call and dropped immediately after, which is what makes it safe.
start spotify works for
programs that happen to be on PATH and fails for almost everything people actually
install. Helix asks Windows for the Start-menu AppID and launches it the way clicking
its tile would — Store apps, MSIX packages and ordinary programs alike — then waits
for the window to confirm it really opened.
The relay understood a fixed list of hand-written actions, so anything not on that list was unreachable away from home — and most of it was unreachable at home too. It now carries the same request the app would have made over Wi-Fi. Seven endpoints are deliberately withheld: credentials and re-pairing stay things you do at the machine.
Across 615 samples — five phone sizes, five desktop shapes, a 5×5 grid on each. A screen is letterboxed inside the phone's frame, so the element's rectangle is not the picture. The error changes with the aspect ratio, which is why it reads as the pointer drifting rather than as arithmetic that is simply wrong.
Events published while the socket was down returned early and were never recorded, so nothing could resend them — the phone was not behind, it was permanently missing a section. Events are now kept and numbered first, and the phone collects the gap when it reconnects.
Four stores each rendering "a short block" with nobody owning the sum. At a hundred entries per store that reached roughly 15,000 characters on every step, and no log line anywhere would have said so. One budget now covers the lot — and trims whole lines only, because a truncated instruction reads as a different instruction.
Timings come from the agent's own per-step log (look /
think / act / settle) and from live end-to-end runs driven through the real
server and the real model. DOM figures were taken in a headless Chrome against a live
public page, with the before-and-after measured in the same session on the same
document.
There are no head-to-head scores against other models on this page. We have not run Helix on OSWorld, WebArena or any published computer-use benchmark, and putting invented numbers next to another company's name would be worthless to you and unfair to them. The comparison below is about architecture — what the systems are able to do — which is checkable rather than claimed.
Comparison
Not a score — a capability table. Cloud agents run in a clean virtual machine somewhere else; Helix runs on the computer you are sitting at. That single difference decides most of the rows.
| Helix | Cloud computer-use agent | |
|---|---|---|
| Where it runs | Your own PC, with your apps and logins | A fresh VM in a datacentre |
| Your installed software | Spotify, Office, games, launchers — whatever you have | Only what the sandbox image ships |
| Your signed-in sessions | Already signed in, because it is your browser | Needs credentials handed to it |
| Shell access | PowerShell and cmd, classified per command | Usually, inside the sandbox only |
| Web work | Off-screen tab, driven by element through DevTools | Screenshot plus coordinates, typically |
| Can you keep using the machine? | Yes for web, files and API work — it never takes the mouse | Yes — it is not your machine |
| Reads pages through shadow DOM | Composed walk: document, shadow roots, same-origin frames | Depends; querySelectorAll misses it |
| Permission model | Typed risk classes — it asks before anything that commits | Varies; often all-or-nothing |
| Reasoning you can read | Live trace: assumptions, rejected routes, what it can't know | Usually a summary after the fact |
| Repeats what worked | Verified replay — checks the screen matches before acting | Replans from scratch |
| Cost to you | Free; bring your own model key | Metered per task or per seat |
| Works offline-ish | Shell, files and app control need no cloud but the model call | Entirely remote |
Code mode
Driving a screen is the wrong tool for changing software. Code mode is a different agent with a different loop: it reads files, writes code, runs the project's own tests and shows you the diff — inside one folder you choose, and nowhere else.
Every path a tool is handed goes through a single resolver. It refuses
.., absolute paths, Windows' drive-relative
C:foo, and — the case a string comparison misses —
a symlink pointing out, by resolving links before it compares.
Before a file is touched, its bytes are copied aside. "Undo that" puts every
file in the turn back, including removing the ones it created. Copies live in
Helix's own data folder — never a .helix/ dropped into
your repository where it can be committed.
"Edit failed" makes a model try the same thing again. "old_string appeared 3 times; add surrounding lines to make it unique" makes it fix the call. Every failure says what was wrong and what would work.
A batch of edits to one file is applied in memory and written once. "3 of 5 worked" forces a re-read to discover which — so a failed batch writes nothing and says so.
Build makes changes. Plan investigates and writes a plan. Ask answers questions. Review reports what is wrong. The three read-only modes are derived from each tool's own flag, so a new tool cannot leak into them by being forgotten.
A tool that returns a 900 KB file eats the window the rest of the task needed. Silent truncation is worse — the model then edits confidently against text that was cut off. So it caps loudly and says how to narrow the request.
Bypass genuinely never asks — but it still cannot leave the project folder. That is refused by the boundary, not by the permission setting, because a boundary that depends on a setting is not a boundary.
Connect any Model Context Protocol (MCP) server — your database, your issue tracker, your own — over a local process or a hosted endpoint, and its tools become things Helix can call while it codes.
Everything a server offers is treated as capable of
changing something. We cannot see what a stranger's code does, and assuming a
tool called get_issue is read-only is exactly the
assumption that eventually deletes something.
A server that will not start disables itself with a readable reason and the session carries on. Plugins bundle servers and written standards into one thing you install once — and nothing runs until you switch it on.
Not a notification — the session. Every coding session you have, listed with its project and how far it got. Open one, read the diffs, send a correction while it is still working, change the permission mode, or answer a request it is waiting on. Over your Wi-Fi or through the cloud link, so "from anywhere" means anywhere.
Shipping
An update mechanism is only as good as the release process behind it. Helix had a correct one that reached nobody: three releases were built, staged, and never uploaded, while the site went on serving a version four months old.
A Helix install is 237 MB and almost none of it changes: OpenCV alone is 99 MB and is byte-identical between releases. Only the files whose hashes differ are shipped — in practice 5 to 7 files — and the patch is checked against the exact version it was built for before anything is touched.
An update that installs and then fails to launch is the worst thing an updater can do: the app is simply gone, and the only route back is another machine.
So the launch is counted, not observed. The version being replaced is kept on disk, a counter is armed before the installer runs, and only the interface reporting that it rendered clears it. Reaching a second launch with the counter still set means the first never made it — and Helix offers the way back.
The swap itself is a batch file: no dependencies, cannot fail to start, and outlives the process it replaces. Every step is a rename, and every failure path puts the old version back and restarts it.
Release notes come from the changelog at build time and are embedded in the same manifest the download page reads — so the app, the site and your phone cannot describe a release differently. Three versions behind? You get all three releases of changes, not just the newest.
Finding an update starts fetching it in the background, verified against its checksum before it could ever run. Installing is still a click — but a click on a file already on disk, not a two-minute wait. Then it installs silently and reopens itself, rather than walking you through a setup wizard again.
A release found to be faulty stops being offered — one line, no rebuild, no 122 MB upload. And a fix that should not be postponed can be marked required, which removes "Not now" without ever installing behind your back.
How it works
Before anything runs, a dedicated reasoning call restates the request, names what it is assuming, considers more than one route and says why it rejected the others — with the screen in front of it, so the plan is made against what is actually there.
A Google API call, an off-screen tab, the files tool, one shell command, and only then the mouse. The decision is repeated back on every step, because a screenshot argues for the mouse every time.
A step that follows a file read or an API call takes no screenshot — the screen cannot have changed. It can ask for one, and any action that aims at a coordinate without a fresh frame is refused rather than guessed.
Every few steps it compares what has happened against the success criteria it wrote at the start, and against its own plan. "Busy but not finishing" is a failure nothing else catches, because everything looks like it is working.
Engineering
A selection from recent work, newest first. Every one was reproduced and measured before it was believed — and the most instructive were found by driving the real thing end to end, or by re-checking something already claimed to be finished.
1.10.0 published a manifest full of release notes to an app that could not render them: the executable was built before the code that reads them, and the changelog it needed was never bundled at all. Grepping the shipped statics proves nothing about Python — those live compressed inside the exe. The check now opens the archive and asserts each module is really in it.
Every individual step succeeded; the last one — the upload — was a line in a document. The live site served a version four months old while three releases' worth of fixes sat on a disk. Releasing is now one command that ends by asking the site what it is actually serving, rather than by reporting what it did.
Applying an update patch to a tree that was already the target produces the target — so checking only the result succeeded for the wrong reason. Found by testing against the real published artifact rather than a fixture. Patches now carry a fingerprint of the version they were built from and are refused, before any work, when it does not match.
Once an update began fetching itself in the background, pressing Install started a second transfer to the same version-stamped path. Interleaved writes produce a file matching nobody's checksum — or worse, one whose bytes change after it was verified. Transfers are serialised; the second caller finds the finished file waiting.
Re-running the release bumped the version counter twice while the built package stayed three behind. A phone downloads that, installs it, still reports the old version — and is prompted to update again, forever. Publishing now reads the version stamped inside the package and refuses to ship a mismatch.
Code mode borrows the main agent's model client. Inside the function that builds
it, a local named agent shadowed the module-level one —
so the first coding task anyone ever sent would have failed on
None. Renamed, and asserted in the tests.
Screenshots were failing, so the new pages were checked by measuring the DOM — which passed everything. Forcing a real viewport made screenshots work and found four genuine defects at once: diff colours chosen only for the dark theme and near-invisible on the light one, mobile styles referencing variables that do not exist, a fixed sidebar starving the conversation in a narrow window, and a message box floating mid-screen on the phone.
The app's button styling is scoped to its dialogs and composer. A button on a new page fell back to the browser's default grey box — with the app's near-white text colour on it. Invisible, and only on the pages nobody had photographed yet.
Windows consoles still default to a codepage that cannot encode a box-drawing character. Redirecting the release script's output to a log killed it before it had done anything — a release tool that cannot survive being logged is not a release tool.
Chrome does not fail a screenshot of a tab it has decided not to render — it waits. On the general 20-second timeout that became the largest stall in the agent, and what came back was a picture of the desktop captioned as the tab. Now bounded at 3.5s with a forced-frame retry, and the fallback says so.
The page reader walked childNodes and never crossed a shadow
boundary — so on MDN it returned the prose and none of the code examples, and reported
it as the whole page. Now walks the flattened tree: shadow roots, slots and same-origin
frames. +73% of the document, verified in real Chrome.
click_element resolves a control by name and then moves the
physical mouse — but it was not classified as an input verb, so the guard that refuses
desktop clicks while the agent is looking at its off-screen tab skipped it entirely.
The model reads a label off a web page and the click lands on your screen.
Two plans existed: one from the routing call, made blind, and one from the deliberation, made with the screen in front of it. The code preferred the blind one on every phone-sent task. It also had no state — printed identically into every prompt under "skip the steps already done", with nothing recording which those were.
Asked for the Windows version, a run finished with "Notepad is open and displaying the Windows version information." Eleven steps, and you are told nothing. Same request now: 5 steps, 24s, and the actual version number.
Plan step N was marked done as soon as N actions had happened — so a six-step plan displayed as finished by the sixth click, and a run stuck on step two for thirty steps showed as complete. It now advances on milestones the agent actually declares.
Every shell command was classified as "runs code", so under the default policy
Get-Date interrupted you for approval. An agent that asks
permission to read the clock teaches people to approve without reading. Commands are
now judged by what they do, via an allowlist — wrong means one extra prompt, never a
missing one.
Backed by 60 test files run on every change, including a suite that drives the page toolkit in a real Chrome against a deliberately hostile fixture, and a mutation harness that breaks each guard on purpose to prove the test would notice.
Writing
The phone could reach ten things on a machine that served 125. The fix was to stop adding verbs — and then to find the app had been edited in a generated file.
Read →A phone watching a task would freeze mid-run and never recover. The agent was fine — a single early return was throwing the events away.
Read →Helix remembers in four places. Two were asked one question, once, before the task began — and never again.
Read →"It feels slow" and "where the time goes" turned out to be different stories. The reasoning was never the bottleneck — blocking timeouts were.
Read →querySelectorAll is a lie on a page built from components.
We were reading 58% of a document and reporting it as all of it.
There was a planning layer, and almost none of it was connected to the run. Seven things it decided that nothing downstream ever read.
Read →The planner could conclude "I cannot do this without knowing which Riya you mean" — and the run would set off and pick one.
Read →Free. Installs in a click, runs in your tray, and asks before it does anything it cannot undo.