pctr 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pctr-0.4.0/src/pctr.egg-info → pctr-0.5.0}/PKG-INFO +305 -269
- {pctr-0.4.0 → pctr-0.5.0}/README.md +39 -13
- pctr-0.5.0/pyproject.toml +68 -0
- {pctr-0.4.0 → pctr-0.5.0}/setup.cfg +4 -4
- pctr-0.5.0/src/pctr/__init__.py +1 -0
- pctr-0.5.0/src/pctr/backends/__init__.py +47 -0
- pctr-0.5.0/src/pctr/backends/atspi.py +323 -0
- pctr-0.5.0/src/pctr/backends/base.py +146 -0
- pctr-0.5.0/src/pctr/backends/input.py +269 -0
- pctr-0.5.0/src/pctr/backends/ocr.py +166 -0
- pctr-0.5.0/src/pctr/backends/windows.py +439 -0
- pctr-0.5.0/src/pctr/backends/x11.py +528 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr/cli.py +219 -539
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr/data/SKILL.md +6 -5
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr/mcp_server.py +3 -2
- {pctr-0.4.0 → pctr-0.5.0/src/pctr.egg-info}/PKG-INFO +305 -269
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr.egg-info/SOURCES.txt +11 -1
- pctr-0.5.0/src/pctr.egg-info/requires.txt +38 -0
- pctr-0.5.0/tests/test_backends.py +83 -0
- pctr-0.5.0/tests/test_cli_parser.py +36 -0
- pctr-0.5.0/tests/test_dispatch.py +73 -0
- pctr-0.4.0/pyproject.toml +0 -55
- pctr-0.4.0/src/pctr/__init__.py +0 -1
- pctr-0.4.0/src/pctr.egg-info/requires.txt +0 -22
- {pctr-0.4.0 → pctr-0.5.0}/LICENSE +0 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr/__main__.py +0 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr/data/AGENTS.md +0 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr/py.typed +0 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr.egg-info/dependency_links.txt +0 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr.egg-info/entry_points.txt +0 -0
- {pctr-0.4.0 → pctr-0.5.0}/src/pctr.egg-info/top_level.txt +0 -0
|
@@ -1,269 +1,305 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: pctr
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: PCTR - Personal Computer Tactile Response. Element-based
|
|
5
|
-
Author:
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/
|
|
8
|
-
Project-URL: Repository, https://github.com/
|
|
9
|
-
Project-URL: Issues, https://github.com/
|
|
10
|
-
Keywords: automation,windows,uia,
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Environment ::
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Operating System ::
|
|
15
|
-
Classifier:
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.
|
|
20
|
-
Classifier:
|
|
21
|
-
Classifier: Topic ::
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
|
|
29
|
-
Requires-Dist:
|
|
30
|
-
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
Requires-Dist:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
Requires-Dist:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
pip install "pctr[mcp]"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
`tree
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
pctr
|
|
153
|
-
pctr
|
|
154
|
-
pctr
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
pctr
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
pctr
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
pctr
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pctr
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: PCTR - Personal Computer Tactile Response. Element-based UI Automation CLI for AI agents. Windows (UIA) and Linux X11 (AT-SPI2).
|
|
5
|
+
Author: UnixUserDev
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/UnixUserDev/pctr
|
|
8
|
+
Project-URL: Repository, https://github.com/UnixUserDev/pctr
|
|
9
|
+
Project-URL: Issues, https://github.com/UnixUserDev/pctr/issues
|
|
10
|
+
Keywords: automation,linux,windows,uia,atspi,x11,desktop,agent,computer-use,rpa
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: X11 Applications
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: mss>=9.0
|
|
27
|
+
Requires-Dist: pillow>=9.0
|
|
28
|
+
Provides-Extra: windows
|
|
29
|
+
Requires-Dist: pywinauto>=0.6.8; platform_system == "Windows" and extra == "windows"
|
|
30
|
+
Requires-Dist: uiautomation>=2.0; platform_system == "Windows" and extra == "windows"
|
|
31
|
+
Requires-Dist: pyautogui>=0.9.54; platform_system == "Windows" and extra == "windows"
|
|
32
|
+
Requires-Dist: pydirectinput>=1.0.4; platform_system == "Windows" and extra == "windows"
|
|
33
|
+
Provides-Extra: linux
|
|
34
|
+
Requires-Dist: python-xlib>=0.33; platform_system == "Linux" and extra == "linux"
|
|
35
|
+
Requires-Dist: dbus-next>=0.2.3; platform_system == "Linux" and extra == "linux"
|
|
36
|
+
Requires-Dist: rapidocr-onnxruntime>=1.3; platform_system == "Linux" and extra == "linux"
|
|
37
|
+
Provides-Extra: ocr
|
|
38
|
+
Requires-Dist: rapidocr-onnxruntime>=1.3; extra == "ocr"
|
|
39
|
+
Requires-Dist: pytesseract>=0.3.10; extra == "ocr"
|
|
40
|
+
Provides-Extra: vision
|
|
41
|
+
Requires-Dist: ultralytics>=8.2; extra == "vision"
|
|
42
|
+
Provides-Extra: mcp
|
|
43
|
+
Requires-Dist: mcp>=2; extra == "mcp"
|
|
44
|
+
Provides-Extra: pad
|
|
45
|
+
Requires-Dist: vgamepad>=0.1.0; platform_system == "Windows" and extra == "pad"
|
|
46
|
+
Provides-Extra: serial
|
|
47
|
+
Requires-Dist: pyserial>=3.5; extra == "serial"
|
|
48
|
+
Provides-Extra: all
|
|
49
|
+
Requires-Dist: pctr[linux,mcp,ocr,pad,serial,vision,windows]; extra == "all"
|
|
50
|
+
Dynamic: license-file
|
|
51
|
+
|
|
52
|
+
# pctr
|
|
53
|
+
|
|
54
|
+
**PCTR — Personal Computer Tactile Response**
|
|
55
|
+
|
|
56
|
+
Element-based UI automation CLI for AI agents. **Windows (UIA)** and **Linux X11 (AT-SPI2)**.
|
|
57
|
+
|
|
58
|
+
Instead of screenshotting and guessing pixel coordinates, `pctr` finds controls
|
|
59
|
+
by their **name / control type / automation id** and acts on them. Window moves,
|
|
60
|
+
DPI changes, and layout shifts don't break your script.
|
|
61
|
+
|
|
62
|
+
On Windows it is built on `pywinauto` (UI Automation) with `pyautogui` /
|
|
63
|
+
`pydirectinput` for raw mouse and keyboard. On Linux it uses AT-SPI2 (over the
|
|
64
|
+
accessibility D-Bus, no `pyatspi` needed), XTest (`python-xlib`) for input,
|
|
65
|
+
`mss`/compositor capture for screenshots, and `rapidocr`/tesseract for OCR.
|
|
66
|
+
On top of that it offers **OCR** and **YOLO-World** open-vocabulary detection for
|
|
67
|
+
text and objects that aren't exposed as controls.
|
|
68
|
+
|
|
69
|
+

|
|
70
|
+
|
|
71
|
+
*Driven entirely by pctr itself - list windows, map virtual desktops, dump a
|
|
72
|
+
control tree, `set` a field, read it back with OCR, screenshot it, and YOLO-World
|
|
73
|
+
detect. Recorded with OBS, which pctr also piloted.*
|
|
74
|
+
|
|
75
|
+
## Install
|
|
76
|
+
|
|
77
|
+
### Windows
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install "pctr[windows]" # UIA + input
|
|
81
|
+
pip install "pctr[vision]" # + ultralytics, for `pctr look`
|
|
82
|
+
pip install "pctr[mcp]" # + MCP SDK, for the MCP server
|
|
83
|
+
pip install "pctr[pad]" # + vgamepad, for `pctr pad` (needs ViGEmBus)
|
|
84
|
+
pip install "pctr[serial]" # + pyserial, for `pctr hid` / the serial-hid backend
|
|
85
|
+
pip install "pctr[all]" # everything
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Linux (X11 / XWayland)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install "pctr[linux]" # python-xlib + dbus-next + rapidocr
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Requires the accessibility bus to be running (`at-spi2-core`; on most desktops
|
|
95
|
+
it already is). Element targeting uses AT-SPI2, so **apps must expose
|
|
96
|
+
accessibility** (GTK/Qt/Electron do; many X11 toolkits and games do not).
|
|
97
|
+
Screenshots use `mss`; under Wayland it falls back to `spectacle` (KDE) or
|
|
98
|
+
`grim`. Global synthetic input goes through XTest, which works for X11/XWayland
|
|
99
|
+
apps — native Wayland clients are not reachable (protocol design). Use
|
|
100
|
+
`--backend auto|windows|x11|wayland` to pick explicitly.
|
|
101
|
+
|
|
102
|
+
### Both
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install "pctr[ocr]" # rapidocr + pytesseract
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## MCP server
|
|
109
|
+
|
|
110
|
+
`pctr` ships a Model Context Protocol server so MCP clients (Claude Desktop,
|
|
111
|
+
Cursor, opencode, ...) can drive the desktop directly:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install "pctr[mcp]"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Add it to your client config (stdio):
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{ "mcpServers": { "pctr": { "command": "pctr-mcp" } } }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
(or `"command": "python", "args": ["-m", "pctr.mcp_server"]`)
|
|
124
|
+
|
|
125
|
+
Tools exposed: `pctr_windows`, `pctr_tree`, `pctr_find`, `pctr_click`,
|
|
126
|
+
`pctr_set`, `pctr_type`, `pctr_keys`, `pctr_hotkey`, `pctr_focus`, `pctr_wait`,
|
|
127
|
+
`pctr_shot`, `pctr_ocr`, `pctr_ocrfind`, `pctr_ocrclick`, `pctr_look`,
|
|
128
|
+
`pctr_desktop`.
|
|
129
|
+
|
|
130
|
+
Or run/manage it from the CLI:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
pctr mcp status # SDK + server state
|
|
134
|
+
pctr mcp start --transport streamable-http --port 8765 # background HTTP server
|
|
135
|
+
pctr mcp restart | pctr mcp stop
|
|
136
|
+
pctr mcp help
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`stdio` runs in the foreground (what a client spawns); `sse` / `streamable-http`
|
|
140
|
+
run in the background, reachable at `http://127.0.0.1:8765/mcp` (or `…/sse`).
|
|
141
|
+
|
|
142
|
+
## Commands
|
|
143
|
+
|
|
144
|
+
| Command | What it does |
|
|
145
|
+
|---------|--------------|
|
|
146
|
+
| `pctr windows [--filter RE] [--process PID]` | List top-level windows (`pid=… \| title`). |
|
|
147
|
+
| `pctr tree --title RE [--depth N] [--limit N]` | Dump the UIA control tree of a window. |
|
|
148
|
+
| `pctr find --title RE [--name RE] [--limit N] [--nth N]` | List matching elements. |
|
|
149
|
+
| `pctr click --title RE --name RE [--method auto\|invoke\|mouse] [--dbl]` | Click an element. |
|
|
150
|
+
| `pctr set --title RE --name RE --text S` | Set a field via the UIA ValuePattern (exact, instant). |
|
|
151
|
+
| `pctr type [--title RE --name RE] --text S [--delay 0.03] [--chunk 1]` | Send keystrokes (see notes). |
|
|
152
|
+
| `pctr keys --keys "{ENTER}"` | Send a global key combo (pywinauto syntax). |
|
|
153
|
+
| `pctr hotkey --keys ctrl+s` | Send a modifier combo (prefer this over `keys "^s"`). |
|
|
154
|
+
| `pctr focus --title RE` | Bring a window to the foreground. |
|
|
155
|
+
| `pctr wait --title RE --name RE [--timeout S]` | Wait until an element exists. |
|
|
156
|
+
| `pctr shot [--title RE] --out PATH` | Screenshot the screen or a window. |
|
|
157
|
+
| `pctr size` | Print primary screen size as `WxH`. |
|
|
158
|
+
| `pctr desktop <action>` | Virtual desktops: `list` / `windows` / `where` / `on-current` / `next` / `prev` / `new` / `close` / `move-window`. |
|
|
159
|
+
| `pctr move --x N --y N` / `down` / `up` / `hold --ms N` | Raw mouse control (`--direct` for games). |
|
|
160
|
+
| `pctr drag --start x,y --end x,y [--duration S]` | Drag between two points. |
|
|
161
|
+
| `pctr keydown / keyup --key a` / `keyhold --key w --ms 1500` | Hold keyboard keys (`--direct` for games). |
|
|
162
|
+
| `pctr ocr [--title RE] [--lang TAG]` | OCR the screen/window; list words with boxes. |
|
|
163
|
+
| `pctr ocrfind --text RE [--lang TAG]` | OCR then list matches with click centers (single words). |
|
|
164
|
+
| `pctr ocrclick --text RE [--nth N] [--lang TAG]` | OCR then click a word. |
|
|
165
|
+
| `pctr look --for "a dog" [--title RE] [--conf X]` | YOLO-World detect objects by text prompt. |
|
|
166
|
+
| `pctr lookclick --for "a dog" [--nth N]` | Detect then click the top match. |
|
|
167
|
+
| `pctr pad <button\|stick\|trigger\|status>` | Virtual Xbox 360 gamepad via ViGEmBus. |
|
|
168
|
+
| `pctr hid <action> --port COMx` | Serial-HID bridge to a real USB-HID microcontroller. |
|
|
169
|
+
| `pctr mcp <start\|stop\|restart\|status\|help>` | Manage the MCP server (stdio or background http/sse). |
|
|
170
|
+
| `pctr skill [--install]` / `pctr setup` | Print/install the agent skill + an AGENTS.md section. |
|
|
171
|
+
|
|
172
|
+
Global flags: `--json` (machine-readable output) and `--file FILE` (run a batch
|
|
173
|
+
of commands from a file).
|
|
174
|
+
|
|
175
|
+
Common filters: `--title` (regex), `--name` (regex), `--control-type`
|
|
176
|
+
(`Button`, `Edit`, `Pane`, `MenuItem`, …), `--auto-id`, `--nth`, `--process`.
|
|
177
|
+
|
|
178
|
+
`click`, `set`, `wait` accept **any** selector - `--name` is not required.
|
|
179
|
+
`tree`/`find` require a window selector (`--title` or `--process`).
|
|
180
|
+
|
|
181
|
+
## The loop
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
pctr tree --title "Notepad" --limit 60 # see what's clickable
|
|
185
|
+
pctr click --title "Notepad" --name "^File$"
|
|
186
|
+
pctr set --title "Notepad" --name "Text Editor" --text "hello"
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## JSON output
|
|
190
|
+
|
|
191
|
+
Add `--json` (global, or per-command) for machine-readable output from
|
|
192
|
+
`windows`, `tree`, `find`, `ocr`, `ocrfind`, `look`, and `desktop`:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
pctr windows --json
|
|
196
|
+
# [{"hwnd":1234,"pid":5678,"title":"Untitled - Notepad"}, ...]
|
|
197
|
+
|
|
198
|
+
pctr desktop list --json
|
|
199
|
+
# [{"index":0,"guid":"ae37…","current":true,"windows":11}, ...]
|
|
200
|
+
|
|
201
|
+
pctr look --for "a car" --json
|
|
202
|
+
# [{"label":"a car","conf":0.86,"x":512,"y":300,"box":[400,220,620,380]}, ...]
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Progress and warnings go to stderr, so stdout stays valid JSON.
|
|
206
|
+
|
|
207
|
+
## Batch files
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
pctr --file script.txt # one command per line; # comments and blanks skipped
|
|
211
|
+
pctr --json --file script.txt # --json applies to every line
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Stops on the first failing line and reports its line number.
|
|
215
|
+
|
|
216
|
+
## Virtual desktops
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
pctr desktop list # desktops (#index, guid, [current], window count)
|
|
220
|
+
pctr desktop windows --desktop 1 # windows on desktop #1
|
|
221
|
+
pctr desktop where --title "App" # which desktop a window is on
|
|
222
|
+
pctr desktop on-current --title "App" # True / False
|
|
223
|
+
pctr desktop next | prev | new | close # switch (moves the active desktop)
|
|
224
|
+
pctr desktop move-window --title RE --to N
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- Switching uses the standard Win+Ctrl hotkeys and moves the **active** desktop
|
|
228
|
+
(you included). Add `--direct` if a game has focus.
|
|
229
|
+
- **Cross-desktop control:** UIA actions (`click --method invoke`, `set`) reach
|
|
230
|
+
windows on another desktop **without switching** (accessibility layer, not
|
|
231
|
+
screen input). Raw mouse/keys only affect the active desktop.
|
|
232
|
+
- **`move-window` is blocked on Windows 11** (third-party `MoveWindowToDesktop`
|
|
233
|
+
returns `Access denied`); it works on Windows 10.
|
|
234
|
+
|
|
235
|
+
## Raw input backends
|
|
236
|
+
|
|
237
|
+
The OS flags `SendInput` events as injected, so anything built on user32 is
|
|
238
|
+
detectable in principle. `pctr` can route raw mouse/keyboard through a different
|
|
239
|
+
backend with `--backend`:
|
|
240
|
+
|
|
241
|
+
| Backend | How | Detectable? |
|
|
242
|
+
|---|---|---|
|
|
243
|
+
| `pyautogui` (default / `sendinput`) | user32 `SendInput`, virtual keys | yes (`injected` flag) |
|
|
244
|
+
| `pydirectinput` (or `--direct`) | `SendInput` with **scancodes** — better for DirectInput games | yes |
|
|
245
|
+
| `serial-hid` | a **microcontroller presenting real USB HID** over serial | no — it *is* real hardware |
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
pctr move --backend pydirectinput --x 800 --y 400
|
|
249
|
+
pctr keyhold --key w --ms 400 --backend pydirectinput
|
|
250
|
+
pctr type --text "hi" --backend serial-hid --port COM5 # needs a board
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Applies to `move` / `down` / `up` / `hold` / `keydown` / `keyup` / `keyhold` /
|
|
254
|
+
`hotkey` / `drag` / `type` / `desktop`.
|
|
255
|
+
|
|
256
|
+
### Gamepad
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
pip install "pctr[pad]" # + the ViGEmBus driver
|
|
260
|
+
pctr pad button --name A --ms 150
|
|
261
|
+
pctr pad button --name DPAD_UP --ms 100
|
|
262
|
+
pctr pad stick --x 1.0 --y -0.5 --ms 400
|
|
263
|
+
pctr pad trigger --right 1.0 --ms 300
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Serial-HID bridge
|
|
267
|
+
|
|
268
|
+
Firmware protocol, newline-terminated ASCII:
|
|
269
|
+
`MOVE x y` · `CLICK b` · `DOWN b` · `UP b` · `KEY k DOWN|UP` · `WRITE text` · `HOTKEY a+b`
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
pip install "pctr[serial]"
|
|
273
|
+
pctr hid ports # list COM ports
|
|
274
|
+
pctr hid move --x 500 --y 300 --port COM5
|
|
275
|
+
pctr hid type --text "hello" --port COM5
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Exit codes
|
|
279
|
+
|
|
280
|
+
- `0` success, `1` no match / window not found, `2` usage/validation error.
|
|
281
|
+
- Errors print one `error: …` line - no tracebacks.
|
|
282
|
+
|
|
283
|
+
## Notes
|
|
284
|
+
|
|
285
|
+
- Prefer `set` (ValuePattern) over `type` for text fields - it can't drop or
|
|
286
|
+
reorder characters. `type`'s element path uses pywinauto `type_keys`, which
|
|
287
|
+
interprets `{ } + ^ % ~ ( )` as key syntax, so it is **not** literal.
|
|
288
|
+
- Global `type` / `keys` go to the OS-focused window - `pctr focus` first.
|
|
289
|
+
- Prefer `pctr hotkey --keys ctrl+s` over `keys "^s"`; the `^` modifier is
|
|
290
|
+
fragile through shells.
|
|
291
|
+
- `ocrfind`/`ocrclick` match one **word** at a time (Windows OCR tokenizes words).
|
|
292
|
+
- `look` reads its model from `--model` or the `PCTR_YOLO_MODEL` env var; progress
|
|
293
|
+
bars go to stderr so stdout stays parseable.
|
|
294
|
+
- Qt apps expose a rich tree including embedded webviews. Electron apps expose
|
|
295
|
+
only the window frame (use `focus` + global keys, or drive them over CDP).
|
|
296
|
+
- Games ignore synthetic input - pass `--direct` to mouse/key commands and focus
|
|
297
|
+
the game first.
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
AI-generated with [OpenCode](https://opencode.ai) — primary model: DeepSeek V4.1 Flash.
|