sidehand
Let your AI agent use Windows apps while you keep working: reads and operates desktop controls without stealing your focus, from Windows or WSL. Zero dependencies.
Package details
Install sidehand from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:sidehand- Package
sidehand- Version
0.4.0- Published
- Nov 3, 2026
- Downloads
- 468/mo · 468/wk
- Author
- blue-b
- License
- MIT
- Types
- extension, skill
- Size
- 114.2 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"skills": [
"./skills/sidehand"
],
"extensions": [
"./extensions/sidehand/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
English | 한국어
Sidehand
Your AI agent works in your Windows apps. You keep the keyboard.
Sidehand lets Claude Code, Codex, pi or any agent with a shell read and operate Windows desktop apps in the background. It fills in forms, clicks, right-clicks, drags, scrolls, presses keys and shortcuts, starts apps and arranges windows without bringing anything to the front, so whatever you are doing (a game, a browser, a document) keeps your keyboard. It works from Windows or from inside WSL, and it needs nothing beyond the PowerShell that ships with Windows.

Unedited take on a real Windows 11 desktop, recorded with Recordly by demo/record.ps1. Keystrokes go into Notes for the whole run: 145 of 145 arrived, and the foreground window never changed. MP4
Why Sidehand
- It does not take your focus. On a real desktop, 20 of 20 background actions in WinForms, WPF, Edge and VS Code landed while the window you were typing in stayed in front. With the other tools we measured, a different window jumped to the front every time.
- It is cheap to read. A window comes back as one compact line per control: 5 to 12 times fewer tokens than the JSON the other tools returned for the same window.
- It is small and transparent. No daemon, no telemetry, no downloaded binary. About 1,400 lines of PowerShell, C# and JavaScript, compiled on your PC into
%LOCALAPPDATA%\sidehandon first use. Reading it takes an afternoon, removing it takes one command.
Benchmark
Same Windows 11 PC and test apps for all three tools. Focus: each action ran against a fresh background WinForms or WPF window while Notes held the keyboard (demo/record.ps1). Tokens: one read of the same window, o200k_base tokenizer; Cua Driver with include_screenshot: false. Size: npm unpacked size, or the binary for Cua Driver. Chart source: demo/benchmark_chart.py.
What works while you type
Every ✅ took effect without changing the foreground window, on a real desktop (demo/measure.ps1, demo/record.ps1) or on the hidden test desktop (test/isolated). Where the cursor was tracked, it never moved.
| Win32, WinForms | WPF | Chromium (Edge, Chrome) | Electron (VS Code) | |
|---|---|---|---|---|
| Type, click, check, select, expand | ✅ | ✅ | ✅ except <select> drop-downs |
✅ click |
| Right-click, double-click, wheel, hover | ✅ | ❌ | ✅ | not measured |
| Drag inside an app | ✅ | ❌ | not measured | not measured |
Keys and shortcuts (Enter, ctrl+a) |
✅ | with consent | with consent | with consent |
Starting an app and moving, resizing, minimizing or restoring a window use the same Windows calls for every app (tested with WinForms). WPF ignores mouse messages that do not come from the real mouse, and WPF and browser content take keys only while their window is focused, so those need the user's consent (--allow-foreground).
Compared with other tools
| Sidehand | Cua Driver | agent-desktop | Windows-MCP | Claude / OpenAI computer use | |
|---|---|---|---|---|---|
| Works while you keep typing | ✅ | ⚠️ the terminal comes forward | ❌ the app comes forward | ❌ moves your real mouse | ❌ moves your real mouse |
| Reads apps as text, not just pixels | ✅ | ✅ | ✅ | ✅ | ❌ |
| Screenshots | ✅ | ✅ | ✅ | ✅ | ✅ |
| Hides private info in screenshots (black, blur, pixelate) | ✅ | ❌ | ❌ | ❌ | ❌ |
| Right-click, double-click, drag, keys without touching your mouse | ✅ | ✅ | ❌ needs --headed |
❌ | ❌ |
| Real mouse input, which takes your mouse over | ❌ on purpose | ✅ | ✅ --headed |
✅ | ✅ |
| Web pages: navigation and DOM | ❌ buttons and inputs only | ✅ CDP | hands off to agent-browser | ✅ DOM mode | ✅ |
| Nothing left running in the background | ✅ | ❌ daemon | ✅ | ❌ MCP server | ❌ agent harness |
| macOS and Linux | ❌ | ✅ | ✅ | ❌ | ✅ |
⚠️ and ❌ in the first row were measured for Cua Driver and agent-desktop and follow from the documented design for the other two; agent-desktop documents drag, hover and mouse commands as --headed only. A ❌ for hiding private info means we found no such feature in the docs or the source (November 2026).
Real mouse input is left out on purpose: Windows has one cursor per session, so an agent that moves it takes it from you. We also tried a second, synthetic pen pointer; Windows still moved the cursor and WPF ignored it, so it did not ship. Pick Cua Driver or agent-desktop if you need macOS or Linux, real mouse input or full browser automation. Pick Sidehand if you work on Windows, want the agent to stay out of your way, and prefer a tool small enough to read.
Install
# CLI, for Claude Code, Codex or any agent that runs shell commands (Windows or WSL, Node 18.3+)
npm install -g sidehand
# pi
pi install git:github.com/Blue-B/sidehand
For a CLI agent, add this to AGENTS.md or CLAUDE.md:
Use the `sidehand` CLI to read and operate Windows desktop apps without taking the user's focus.
Read with `sidehand tree "<window title>"`, act with `sidehand act <ref> <action>`, see `sidehand --help`.
Never pass `--allow-foreground` or `--bring-to-front` unless the user agreed.
Usage
$ sidehand tree "Contoso Orders"
window: Contoso Orders (18 elements)
e4 Edit "Customer"
e6 Edit "Quantity"
e8 ComboBox "Region"
e11 CheckBox "Express shipping" [Off]
e12 Button "Submit order"
$ sidehand act e4 type "Blue-B Studio"
ok set text via window message: e4 Edit "Customer" value="Blue-B Studio"
$ sidehand act e8 select Jeju
ok select "Jeju" via window message: e8 ComboBox "Region" value="Jeju"
$ sidehand act e12 click
ok click via window message: e12 Button "Submit order"
$ sidehand wait "Contoso Orders" "Order submitted"
ok found in Contoso Orders
e13 Text "Order submitted: Blue-B Studio, 3 units to Jeju, express"
| Command | What it does |
|---|---|
sidehand windows, monitors |
list targets |
sidehand tree <title> [--filter t] |
the window's controls as text, each with a ref; long lists show 25 items |
sidehand wait <title> <text> [--gone] |
wait until a control containing the text appears or disappears |
sidehand act <ref> <action> [value] |
click, type, check, uncheck, select, expand, collapse, scroll, right-click, double-click, hover, wheel down 3, drag <ref or dx,dy>, press <keys> (Enter, ctrl+a, "Down Down Enter"), focus |
sidehand window <title> <action> |
move x,y, resize w,h, minimize, restore (comes back behind your windows), close |
sidehand launch <app> [args] |
start an app, document or URL without it taking your focus |
sidehand clipboard [text] |
read the clipboard, or replace it |
sidehand capture <mode> |
full, region, monitor, active, or window (works while the window is covered) |
sidehand crop, mask, resize, info |
edit screenshots; mask blacks out, pixelates or blurs regions before you share them |
In pi the same operations are tools named sidehand_ui_tree, sidehand_ui_act, sidehand_capture and so on.
Limits
focusand capturing a minimized window would take your foreground, so they are refused unless the agent passes--allow-foregroundor--bring-to-front.- Games and other apps that draw their own UI expose no controls. Sidehand can still capture them.
- Minimized windows:
sidehand window <title> restorebrings one back behind your windows first. - WPF apps ignore background mouse gestures (right-click, double-click, drag, wheel), and HTML
<select>drop-downs ignore background selection; Sidehand reports a failure instead of pretending. - Drag and drop between two apps (files into a folder) needs the real mouse.
- Keys go to a control with its own window handle; WPF and browser content need
--allow-foreground. - Apps running as administrator only accept messages from an agent that also runs elevated.
How it works
scripts/SidehandUia.csis a native UI Automation client, the COM interface screen readers use. Windows PowerShell compiles it once into%LOCALAPPDATA%\sidehandtogether with an interop assembly generated from Windows' ownUIAutomationCore.dll.- For each action it first looks for a classic control with its own window handle (
EDIT,BUTTON,LISTBOX,COMBOBOX) and sends itWM_SETTEXT,BM_CLICKorLB_/CB_SETCURSEL. A window message cannot activate a window. - Other controls get the UI Automation pattern call while the target's top-level window carries
WS_EX_NOACTIVATE, so the app's ownFocus()call cannot bring it forward. The idea comes from Cua Driver's no-raise guard. If an app still comes forward, the result says so. - Mouse gestures and keys are posted to the window under the element (
WM_RBUTTONDOWN,WM_MOUSEWHEEL,WM_KEYDOWNand so on). They go through the app's own message loop but never move your cursor. For shortcuts, Ctrl, Shift and Alt are marked as held in the target thread's key state only, for the moment of the keystroke. - Everything runs in physical pixels, so coordinates and screenshots are exact on scaled displays.
Reproduce the numbers
npm test # hidden desktop, nothing appears on screen, a few minutes
powershell -File demo/measure.ps1 # real desktop: focus and cursor for WinForms, Edge and VS Code, about 3 minutes idle
powershell -File demo/record.ps1 # real desktop: the demo video and the three-tool table, 5 to 10 minutes idle
npm test runs test apps and a decoy "user" window on a separate, never-shown Windows desktop inside a kill-on-close job, and fails if any Sidehand action activates its window. It also runs Cua Driver and agent-desktop when they are installed. demo/record.ps1 -Recordly re-creates the demo video and stops by itself if someone uses the PC.
License
MIT