pctr
Element-based Windows UI Automation CLI for AI agents.
Instead of screenshotting and guessing pixel coordinates, pctr finds controls
by their name / control type / automation id and acts on them. Window moves,
DPI changes, and layout shifts don't break your script.
Built on pywinauto (UI Automation) with pyautogui / pydirectinput for raw
mouse and keyboard input. On top of UIA it also offers OCR
(Windows.Media.Ocr) and YOLO-World open-vocabulary detection for text and
objects that aren't exposed as controls.
Install
pip install pctr
pip install "pctr[vision]" # adds ultralytics for `pctr look`
Windows only.
Commands
| Command | What it does |
|---|---|
pctr windows [--filter RE] [--process PID] |
List top-level windows (pid=… | title). |
pctr tree --title RE [--depth N] [--limit N] |
Dump the UIA control tree of a window. |
pctr find --title RE [--name RE] [--limit N] [--nth N] |
List matching elements. |
pctr click --title RE --name RE [--method auto|invoke|mouse] [--dbl] |
Click an element. |
pctr set --title RE --name RE --text S |
Set a field via the UIA ValuePattern (exact, instant). |
pctr type [--title RE --name RE] --text S [--delay 0.03] [--chunk 1] |
Send keystrokes (see notes). |
pctr keys --keys "{ENTER}" |
Send a global key combo (pywinauto syntax). |
pctr hotkey --keys ctrl+s |
Send a modifier combo (prefer this over keys "^s"). |
pctr focus --title RE |
Bring a window to the foreground. |
pctr wait --title RE --name RE [--timeout S] |
Wait until an element exists. |
pctr shot [--title RE] --out PATH |
Screenshot the screen or a window. |
pctr size |
Print primary screen size as WxH. |
pctr desktop <action> |
Virtual desktops: list / windows / where / on-current / next / prev / new / close / move-window. |
pctr move --x N --y N / down / up / hold --ms N |
Raw mouse control (--direct for games). |
pctr drag --start x,y --end x,y [--duration S] |
Drag between two points. |
pctr keydown / keyup --key a / keyhold --key w --ms 1500 |
Hold keyboard keys (--direct for games). |
pctr ocr [--title RE] |
OCR the screen/window; list words with boxes. |
pctr ocrfind --text RE |
OCR then list matches with click centers (single words). |
pctr ocrclick --text RE [--nth N] |
OCR then click a word. |
pctr look --for "a dog" [--title RE] [--conf X] |
YOLO-World detect objects by text prompt. |
pctr lookclick --for "a dog" [--nth N] |
Detect then click the top match. |
pctr skill [--install] / pctr setup |
Print/install the agent skill + an AGENTS.md section. |
Common filters: --title (regex), --name (regex), --control-type
(Button, Edit, Pane, MenuItem, …), --auto-id, --nth, --process.
click, set, wait accept any selector - --name is not required.
tree/find require a window selector (--title or --process).
The loop
pctr tree --title "Notepad" --limit 60 # see what's clickable
pctr click --title "Notepad" --name "^File$"
pctr set --title "Notepad" --name "Text Editor" --text "hello"
Virtual desktops
pctr desktop list # desktops (#index, guid, [current], window count)
pctr desktop windows --desktop 1 # windows on desktop #1
pctr desktop where --title "App" # which desktop a window is on
pctr desktop on-current --title "App" # True / False
pctr desktop next | prev | new | close # switch (moves the active desktop)
pctr desktop move-window --title RE --to N
- Switching uses the standard Win+Ctrl hotkeys and moves the active desktop
(you included). Add
--directif a game has focus. - Cross-desktop control: UIA actions (
click --method invoke,set) reach windows on another desktop without switching (accessibility layer, not screen input). Raw mouse/keys only affect the active desktop. move-windowis blocked on Windows 11 (third-partyMoveWindowToDesktopreturnsAccess denied); it works on Windows 10.
Exit codes
0success,1no match / window not found,2usage/validation error.- Errors print one
error: …line - no tracebacks.
Notes
- Prefer
set(ValuePattern) overtypefor text fields - it can't drop or reorder characters.type's element path uses pywinautotype_keys, which interprets{ } + ^ % ~ ( )as key syntax, so it is not literal. - Global
type/keysgo to the OS-focused window -pctr focusfirst. - Prefer
pctr hotkey --keys ctrl+soverkeys "^s"; the^modifier is fragile through shells. ocrfind/ocrclickmatch one word at a time (Windows OCR tokenizes words).lookreads its model from--modelor thePCTR_YOLO_MODELenv var; progress bars go to stderr so stdout stays parseable.- Qt apps expose a rich tree including embedded webviews. Electron apps expose
only the window frame (use
focus+ global keys, or drive them over CDP). - Games ignore synthetic input - pass
--directto mouse/key commands and focus the game first.
License
MIT
Metadata
Release files for pctr 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pctr-0.3.2.tar.gz | 20.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pctr-0.3.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.0 kB
Release files / pctr-0.3.2.tar.gz
| Download URL | pctr-0.3.2.tar.gz |
|---|---|
| Size | 20.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b0cc5fd93b501c38aae30cfb792f504986b3587154701e59f1168f86a03796a3
|
|
BLAKE2b-256 checksum How to use checksums |
d27cb4cad5d24af75f0bb2cd365d98aa33ed8f763e0ba83fd9cdd0a5f48cee53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|
Release files / pctr-0.3.2-py3-none-any.whl
| Download URL | pctr-0.3.2-py3-none-any.whl |
|---|---|
| Size | 20.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
da67bf07f555de155cd0b05cd0b95718c2e48f8d30d5614dad15dfd20663fb01
|
|
BLAKE2b-256 checksum How to use checksums |
93ecbe7be1413903013b56dc07ec1fe93f6d7c48807c91bf6234f6aa9908c4d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.11
|