ai-remote 0.4.5 → 0.4.6

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.
Files changed (3) hide show
  1. package/SKILL.md +245 -0
  2. package/dist/cli.mjs +271 -52
  3. package/package.json +3 -2
package/SKILL.md ADDED
@@ -0,0 +1,245 @@
1
+ ---
2
+ name: ai-remote
3
+ description: Drive a remote Windows, Linux or macOS desktop from the command line with `npx ai-remote` (also installed as `remotectl`) — open one session, then screenshot it, click, type, press keys, run shell commands over SSH, and watch it in a window. Use this skill whenever the user wants to control, inspect, automate or screenshot a machine over RDP/VNC/SSH — including when they never name the tool and just say "click the button on that Windows box", "what's on the screen of 192.168.x.x", "log into the VM and run this", or "take a screenshot of the remote desktop".
4
+ ---
5
+
6
+ # Driving a remote desktop with ai-remote
7
+
8
+ ## The one thing to get right
9
+
10
+ `open` is the only command that names a machine. It starts a session that
11
+ outlives the command, and **every command after it takes no host, no account
12
+ and no password** — they attach to the session that is already running.
13
+
14
+ ```bash
15
+ export AI_REMOTE_PASSWORD=... # never a flag; argv is world-readable
16
+ npx ai-remote open 192.168.1.20 -u owner
17
+
18
+ npx ai-remote shot -o screen.png # not `shot 192.168.1.20`
19
+ npx ai-remote click 640,400
20
+ npx ai-remote close
21
+ ```
22
+
23
+ Writing `ai-remote shot 192.168.1.20` is the single most common mistake, because
24
+ that *was* the grammar in older versions and it is all over the internet. The
25
+ CLI now refuses it with a message explaining the change rather than doing
26
+ something surprising, so if you see that error, drop the host and try again.
27
+
28
+ State carries between commands, and that is the entire point: a tool that
29
+ reconnects between acting and looking can never see the result of its own
30
+ action. Reuse also makes each command effectively instant — a keystroke is
31
+ ~0.15s against ~5s for a fresh RDP handshake.
32
+
33
+ ## Working loop
34
+
35
+ Act, then look. The session holds the framebuffer, so a screenshot taken after a
36
+ click shows what the click did.
37
+
38
+ ```bash
39
+ npx ai-remote key MetaLeft # open the Start menu
40
+ npx ai-remote shot -o after.png # see what happened
41
+ ```
42
+
43
+ `shot` waits for the screen to stop changing before it captures, so there is
44
+ normally no need to sleep first. When an action starts something slow (an app
45
+ launching, a page loading), put an explicit wait in a `do` script instead of
46
+ guessing from outside.
47
+
48
+ Prefer `do` when the next few steps are already known — one round trip instead
49
+ of four, and the timing between steps stays inside the session rather than
50
+ depending on how fast the shell gets round to the next command:
51
+
52
+ ```bash
53
+ npx ai-remote do "key MetaLeft; wait 800; type notepad; wait 1200; key Enter; wait 1500; shot s.png"
54
+ ```
55
+
56
+ Steps, separated by `;`:
57
+
58
+ | Step | Meaning |
59
+ |---|---|
60
+ | `move X,Y` | move the pointer |
61
+ | `click X,Y[,right\|middle]` | click, optionally another button |
62
+ | `dblclick X,Y` | double click |
63
+ | `scroll X,Y,DX,DY` | scroll by notches at a position |
64
+ | `type TEXT` | type into whatever has focus |
65
+ | `key Code[+Code...]` | press keys; `+` is a chord |
66
+ | `cad` | Ctrl+Alt+Del |
67
+ | `wait MS` | pause |
68
+ | `shot FILE` | write a screenshot mid-script |
69
+
70
+ ## Screenshots and coordinates
71
+
72
+ **Coordinates are always in the desktop's own pixels, never the screenshot's.**
73
+ This matters the moment you shrink a screenshot to save tokens:
74
+
75
+ ```bash
76
+ npx ai-remote shot --max-edge 800 --json -o s.png
77
+ # {"ok":true,...,"width":800,"height":500,"file":"/abs/path/s.png"}
78
+ ```
79
+
80
+ That image is 800x500 but the desktop is still 1280x800. A button you see at
81
+ (400, 250) in the image is at (640, 400) on the desktop. Scale back before
82
+ clicking:
83
+
84
+ ```
85
+ desktop_x = image_x * desktop_width / image_width
86
+ ```
87
+
88
+ `ai-remote status --json` reports the true desktop size (`width`, `height`), and
89
+ so does `shot` when you do not pass `--max-edge`. When in doubt, take the
90
+ screenshot full size and click the coordinates you read off it.
91
+
92
+ `--max-edge` is worth using anyway: a 1280x800 PNG is several hundred KB of
93
+ image tokens and a 800px one is a fraction of that, usually with no loss of
94
+ anything you needed to see.
95
+
96
+ ## Keys
97
+
98
+ Key codes are DOM-style physical codes: `MetaLeft`, `Enter`, `Escape`, `Tab`,
99
+ `F5`, `KeyA`, `Digit1`, `ArrowDown`, `ControlLeft`, `AltLeft`, `ShiftLeft`.
100
+
101
+ ```bash
102
+ npx ai-remote key ControlLeft+KeyA # a chord: Ctrl+A
103
+ npx ai-remote key MetaLeft KeyR # in sequence: Meta, then R
104
+ ```
105
+
106
+ `+` holds the modifiers down for the last key. Separate arguments are pressed
107
+ one after another. An unknown code is ignored rather than guessed at, so if
108
+ nothing happens, check the spelling against the list above.
109
+
110
+ ## Running commands instead of clicking
111
+
112
+ When the machine has SSH, a command is faster and far more reliable than driving
113
+ the GUI — no coordinates, no waiting, and real output to read:
114
+
115
+ ```bash
116
+ npx ai-remote exec "hostname"
117
+ npx ai-remote exec "dir C:\\Users"
118
+ ```
119
+
120
+ `exec` reuses the session's own account and password, so it needs no flags. Its
121
+ stdout is the command's output, and it exits 0 when the command did and 1 when
122
+ it did not — the command's own status is in `exitStatus` under `--json` if you
123
+ need the number. `ai-remote shell` opens an interactive terminal (Ctrl-] to
124
+ leave) — that one is for a human, not for an agent, because it never returns.
125
+
126
+ Reach for the GUI when the task is genuinely graphical. Reach for `exec` for
127
+ anything a shell can do.
128
+
129
+ ## Sessions
130
+
131
+ The session opened last is the one commands drive. With several open, name them:
132
+
133
+ ```bash
134
+ npx ai-remote open 192.168.1.20 -u owner --session desk
135
+ npx ai-remote open 192.168.1.30 -u owner --session build
136
+
137
+ npx ai-remote list # * marks the one commands will use
138
+ npx ai-remote shot --session desk # a name, a host, or host:port
139
+ npx ai-remote close --all # or `close` for the current one
140
+ ```
141
+
142
+ Nothing times out and nothing closes itself — a session that an agent left
143
+ mid-task is a feature, not a leak — so **close what you open** when the task is
144
+ done, or tell the user it is still running.
145
+
146
+ ## Watching
147
+
148
+ By default `open` also shows the desktop in a real window, and whoever opens it
149
+ can drive it straight away. Control is not exclusive — you and the person at the
150
+ window can both work the same desktop at once, because your input goes over the
151
+ session's own socket and never through the viewer. Expect a human to move the
152
+ pointer out from under you: if a step depends on what was on screen, take a
153
+ fresh `shot` rather than trusting one from before you paused.
154
+
155
+ - Leave the window on when a human is present. Watching it happen is the reason
156
+ it exists.
157
+ - `--watch-only` starts the window as an observer instead, for a session someone
158
+ should supervise rather than share. Taking control is then one click in the
159
+ toolbar, and the gate is enforced in the session rather than in the page.
160
+ - `--headless` (or `--no-view`) on a server or in CI. The framebuffer is the
161
+ authority either way, so a session nobody watches is not a lesser session.
162
+ - `ai-remote view` adds a window to a headless session later (`view --watch-only`
163
+ for an observer one); `view --close` takes it away without ending the session.
164
+
165
+ ## Reading results
166
+
167
+ Add `--json` to any command for one object on stdout; diagnostics go to stderr,
168
+ so the two never interleave.
169
+
170
+ ```bash
171
+ npx ai-remote status --json
172
+ # {"ok":true,"host":"...","name":"desk","width":1280,"height":800,
173
+ # "connected":true,"viewer":"http://127.0.0.1:7373/?t=...","viewers":1,
174
+ # "shell":"closed","pid":54594}
175
+ ```
176
+
177
+ Exit codes carry meaning, which is usually faster than parsing the message:
178
+
179
+ | Code | Meaning |
180
+ |---|---|
181
+ | 0 | fine |
182
+ | 10 | unreachable |
183
+ | 11 | credentials rejected |
184
+ | 12 | bad usage, or no session open |
185
+ | 13 | timed out |
186
+
187
+ ## When it does not work
188
+
189
+ **"No session is open."** — Nothing is running. `open` first. Commands never
190
+ start a session implicitly, because they have no host to start one with.
191
+
192
+ **Credentials rejected (11), or a session that stops before it is ready.** —
193
+ Almost always `AI_REMOTE_PASSWORD` missing from *this* shell. It is deliberately
194
+ not a flag, and it does not carry across terminals; export it again. `open` says
195
+ so explicitly when it sees the host ask for NLA and finds no password.
196
+
197
+ **Unreachable (10).** — `ai-remote probe <host>` is the one command besides
198
+ `open` that still takes an address: it answers whether anything is listening
199
+ before you spend a handshake finding out.
200
+
201
+ **A session that stopped by itself.** — The host closed the connection, or the
202
+ machine went away. `ai-remote list` shows what is really running; stale entries
203
+ clean themselves up when it does.
204
+
205
+ ## Getting the desktop's own size right
206
+
207
+ RDP lets the client choose the desktop size, and the host may or may not honour
208
+ it. Ask for what suits the task at `open` time (`-W 1920 -H 1080`), then trust
209
+ what `status` reports rather than what you asked for.
210
+
211
+ ## Cheat sheet
212
+
213
+ ```bash
214
+ export AI_REMOTE_PASSWORD=...
215
+ npx ai-remote open HOST[:PORT] -u USER [-d DOMAIN] [--session NAME] [--headless] [--watch-only]
216
+ npx ai-remote shot [-o FILE] [--max-edge N] [--json]
217
+ npx ai-remote click X,Y [--button right|middle] [--double]
218
+ npx ai-remote type "text"
219
+ npx ai-remote key ControlLeft+KeyA
220
+ npx ai-remote do "key MetaLeft; wait 800; type notepad; shot s.png"
221
+ npx ai-remote exec "command"
222
+ npx ai-remote view [--watch-only] [--close]
223
+ npx ai-remote status | list | close [--all]
224
+ npx ai-remote probe [HOST[:PORT]]
225
+ ```
226
+
227
+ Every command takes `--session NAME` to pick between open sessions, and `--json`
228
+ for machine-readable output. `ai-remote --help` is the authority; this file is
229
+ the map.
230
+
231
+ ## Working inside this repository
232
+
233
+ This repo *is* ai-remote. When testing a change, drive the local build rather
234
+ than the published package, or you will be exercising the last release instead
235
+ of your edit:
236
+
237
+ ```bash
238
+ node packages/core/scripts/build.mjs # after editing packages/core/src/cli/*
239
+ node packages/core/dist/cli.mjs open HOST -u USER --headless
240
+ ```
241
+
242
+ The CLI's own source is [`packages/core/src/cli/`](src/cli/):
243
+ `cli.ts` is the grammar, `sessions.ts` decides which session a command drives,
244
+ `daemon.ts` is the process that holds the connection, and `viewer.ts` plus
245
+ `window.ts` are the window. `pnpm test` covers them.