computer-helper-win
August 25, 2026 · View on GitHub
Windows backend for agents computer — C#/.NET 10 daemon, sibling of the Swift
native/computer-mac. Same JSON-RPC wire protocol, same result
shapes; one TS client (cli/src/lib/computer/computer-rpc.ts) drives both.
This file is a map. Read the code (and README.md) for current detail.
Layout
Program.cs Entry point (top-level statements) — TCP listener, auth, RPC loop
Rpc.cs Method dispatch table (19 methods)
Automation.cs UI Automation tree walk + SendInput (click/type/key/scroll/drag) + window focus
Screenshot.cs Graphics.CopyFromScreen over the virtual screen
Apps.cs Process/window enumeration; launch_app via PATH + App Paths registry
LaunchTarget.cs Pure path safety for launch_app (UNC/protocol rejection; RUSH-1763)
ElementCache.cs @eN element handle cache
smoke/smoke.mjs Smoke test (Unicode-typing regression loops for #554/#581)
computer-helper-win.csproj net10.0-windows, WPF + WinForms enabled
tests/LaunchTarget.Tests.csproj net10.0 xunit tests for LaunchTarget (cross-platform)
Build
bash ../../cli/scripts/build-win.sh # dotnet publish -r win-x64 --self-contained -p:PublishSingleFile
Output: dist/computer-helper-win.exe (gitignored; staged into the npm tarball at
release). Needs the .NET 10 SDK; cross-publishes from macOS/Linux
(EnableWindowsTargeting).
How the CLI reaches it
cli/src/lib/computer/ssh-tunnel.ts — resolveWinHelperExe() looks for
native/computer-win/dist/computer-helper-win.exe (dev checkout, 5 hops up from
cli/dist/lib/computer) or the bundled npm copy. setupRemoteHelper() scp's the exe
to %LOCALAPPDATA%\agents\, registers a Task Scheduler task
(AgentsComputerHelper, -AtLogOn, interactive), and starts it. The CLI connects
over an ssh -L tunnel to the daemon's loopback TCP port (8765).
Key differences from computer-mac (don't assume mac semantics)
- Transport is loopback TCP + SSH tunnel, not a Unix socket. The tunnel is the
sole ingress; an optional
--token-fileshared secret is defense-in-depth. - No TCC / no permission model. Windows UIA needs no per-process grant —
trust_statusalways returnstrusted=true. There is no allow-list,computer-policy.json, or peer-auth file. Access control = the SSH tunnel. - Lifecycle is Task Scheduler, not launchd — it must run in the interactive desktop session (not Session 0) for UIA + screen capture to work.
- Single-file needs native-lib self-extraction (
IncludeNativeLibrariesForSelfExtract) or UIA throws on the first tree walk (#519). bundle_id= process image name (notepad), not reverse-DNS.notifyis pass-through only — no Windows Toast; Rush intercepts the return.