ai-remote 0.4.15 → 0.4.16
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.
- package/README.md +77 -0
- package/SKILL.md +47 -1
- package/dist/{cli-chunk-RBCU3NX4.mjs → cli-chunk-Q33YGIDO.mjs} +1 -1
- package/dist/{cli-chunk-EYQCDSPT.mjs → cli-chunk-S2TWL5LF.mjs} +13 -0
- package/dist/{cli-copy-NRXMTHID.mjs → cli-copy-BOF44DWQ.mjs} +1 -1
- package/dist/{cli-daemon-LU4LHDCH.mjs → cli-daemon-4VU67MLE.mjs} +316 -7
- package/dist/{cli-shell-TE6DLBIB.mjs → cli-shell-45XRTE7O.mjs} +2 -2
- package/dist/cli.mjs +63 -6
- package/dist/protocols.js +12 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,8 @@ why `npx` is still what the examples here use.
|
|
|
111
111
|
ai-remote key <Code> press keys, e.g. MetaLeft, ControlLeft+KeyA
|
|
112
112
|
ai-remote exec "cmd" run a command in the terminal (SSH)
|
|
113
113
|
ai-remote shell an interactive terminal
|
|
114
|
+
ai-remote reconnect a new terminal: fresh login, fresh PATH
|
|
115
|
+
ai-remote clipboard [on|off] share this machine's clipboard both ways
|
|
114
116
|
ai-remote cp <src> <dst> copy files; a remote path starts with ':'
|
|
115
117
|
ai-remote do "steps" several actions in one go
|
|
116
118
|
ai-remote view open the window on the session
|
|
@@ -214,6 +216,79 @@ npx ai-remote exec "uname -a"
|
|
|
214
216
|
npx ai-remote shell # Ctrl-] to leave
|
|
215
217
|
```
|
|
216
218
|
|
|
219
|
+
### The clipboard
|
|
220
|
+
|
|
221
|
+
Off by default, and turned on either from the **clipboard button in the window's
|
|
222
|
+
toolbar** or from a command line:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
npx ai-remote clipboard on # both directions, until turned off
|
|
226
|
+
npx ai-remote clipboard # what it is doing now
|
|
227
|
+
npx ai-remote open 192.168.1.50 -u owner --clipboard
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
While it is on, text copied on this machine reaches the remote clipboard and text
|
|
231
|
+
copied there reaches this one. Only a desktop carries a clipboard -- RDP
|
|
232
|
+
negotiates a `cliprdr` channel and VNC has cut-text in the protocol -- so a
|
|
233
|
+
terminal-only session has none and the toolbar button does not appear.
|
|
234
|
+
|
|
235
|
+
**The bridge is the session's, not the page's.** The obvious place to put it
|
|
236
|
+
would be the viewer, using the browser's `navigator.clipboard` -- but a browser
|
|
237
|
+
only grants a page the clipboard while that page is focused, and the moment
|
|
238
|
+
somebody wants the remote clipboard is exactly the moment they have clicked away
|
|
239
|
+
into a local application to paste it. So the session does the copying, on this
|
|
240
|
+
machine, whether or not a window is open; the toolbar button turns it on rather
|
|
241
|
+
than doing it. Two windows on one session are two views of one switch.
|
|
242
|
+
|
|
243
|
+
Two consequences worth knowing:
|
|
244
|
+
|
|
245
|
+
- **It polls.** No platform gives Node a clipboard-change event, so the local
|
|
246
|
+
side is read twice a second while sharing is on. That is why it is a toggle
|
|
247
|
+
and not always on, and why off is a real off: the timer is not running and the
|
|
248
|
+
host's clipboard messages are dropped.
|
|
249
|
+
- **Nothing goes round in circles.** Text that arrived from the host is not then
|
|
250
|
+
noticed by the poller and pushed back to it, and what was already on the
|
|
251
|
+
clipboard when sharing started is not treated as a change -- so turning
|
|
252
|
+
sharing on does not send something copied an hour ago.
|
|
253
|
+
|
|
254
|
+
It uses whatever the platform has: `pbcopy`/`pbpaste` on macOS,
|
|
255
|
+
`Set-Clipboard`/`Get-Clipboard` on Windows, and `wl-clipboard`, `xclip` or
|
|
256
|
+
`xsel` on Linux. A machine with none reports the clipboard as unavailable and
|
|
257
|
+
the button stays hidden rather than offering a switch that cannot work.
|
|
258
|
+
|
|
259
|
+
Sharing sits behind the same control gate as keyboard and pointer input: a
|
|
260
|
+
watch-only viewer can read the screen and cannot reach either clipboard.
|
|
261
|
+
|
|
262
|
+
### A new terminal, after installing something
|
|
263
|
+
|
|
264
|
+
A shell inherits its environment when it signs in, and nothing can change a
|
|
265
|
+
running process's inherited environment from outside it. So a program installed
|
|
266
|
+
a moment ago is simply not on the PATH of the shell that installed it, and
|
|
267
|
+
running the command again will not find it however many times it is tried.
|
|
268
|
+
|
|
269
|
+
`reconnect` is the fix, and it is the same one a person reaches for -- close the
|
|
270
|
+
terminal, open another:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npx ai-remote exec "winget install OpenJS.NodeJS"
|
|
274
|
+
npx ai-remote reconnect
|
|
275
|
+
npx ai-remote exec "node --version"
|
|
276
|
+
|
|
277
|
+
npx ai-remote exec --reconnect "node --version" # or both in one call
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
The session, the desktop and the window stay exactly where they are; only the
|
|
281
|
+
terminal is new. That also means the working directory and any exported
|
|
282
|
+
variables are gone, which is the point -- it is a new login, not a refresh.
|
|
283
|
+
|
|
284
|
+
On Windows a fresh login can still inherit a stale environment, because sshd
|
|
285
|
+
built its own environment block when the service started. Reading the PATH
|
|
286
|
+
straight out of the registry works regardless:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
npx ai-remote exec '$env:Path = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User")'
|
|
290
|
+
```
|
|
291
|
+
|
|
217
292
|
### Copying files
|
|
218
293
|
|
|
219
294
|
`cp` is `scp` with the session standing in for the host: a remote path starts
|
|
@@ -280,6 +355,7 @@ where a decrypted key belongs, and it is offered from there.
|
|
|
280
355
|
- `-s, --security MODE`: `auto` | `nla` | `tls` | `rdp` (default: `auto`).
|
|
281
356
|
- `-W, --width N` / `-H, --height N`: Desktop resolution (default: 1280x800).
|
|
282
357
|
- `--idle MINUTES`: Close an unused session (default: 0, never).
|
|
358
|
+
- `--clipboard`: Share this machine's clipboard with the desktop, both ways.
|
|
283
359
|
- `--headless` / `--no-view`: Run headless without opening the viewer window.
|
|
284
360
|
- `--no-reuse`: A second session beside one that is already open.
|
|
285
361
|
- `--save`: Keep the password for next time, once it has worked.
|
|
@@ -289,6 +365,7 @@ where a decrypted key belongs, and it is offered from there.
|
|
|
289
365
|
- `--session NAME`: Which session to drive (default: the one opened last).
|
|
290
366
|
- `-o, --out FILE`: Screenshot output file path (default: `screen.png`).
|
|
291
367
|
- `-r, --recursive`: For `cp`, copy a directory.
|
|
368
|
+
- `--reconnect`: For `exec`, open a new terminal first, then run the command.
|
|
292
369
|
- `--max-edge N`: Shrink a screenshot to fit N.
|
|
293
370
|
- `--json`: Output machine-readable JSON results on stdout.
|
|
294
371
|
|
package/SKILL.md
CHANGED
|
@@ -149,6 +149,50 @@ leave) — that one is for a human, not for an agent, because it never returns.
|
|
|
149
149
|
Reach for the GUI when the task is genuinely graphical. Reach for `exec` for
|
|
150
150
|
anything a shell can do.
|
|
151
151
|
|
|
152
|
+
**After installing anything, reconnect.** A shell's environment is fixed when it
|
|
153
|
+
signs in, so a `node` installed a moment ago is not on the PATH of the shell that
|
|
154
|
+
installed it, and asking again will never find it:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx ai-remote exec "winget install OpenJS.NodeJS"
|
|
158
|
+
npx ai-remote reconnect # a new login, so a new PATH
|
|
159
|
+
npx ai-remote exec "node --version"
|
|
160
|
+
|
|
161
|
+
npx ai-remote exec --reconnect "node --version" # or both in one call
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The session, the desktop and the window all stay put — only the terminal is new,
|
|
165
|
+
which also means the working directory and any exported variables are gone. On
|
|
166
|
+
Windows, if a fresh login still cannot see it, sshd handed down its own stale
|
|
167
|
+
environment; read the PATH straight out of the registry instead:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
npx ai-remote exec '$env:Path = [Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [Environment]::GetEnvironmentVariable("Path","User")'
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Note `&&` is not valid in PowerShell 5.1 — use `;` to chain, or `if ($?) { ... }`
|
|
174
|
+
when the second command should only run if the first worked.
|
|
175
|
+
|
|
176
|
+
## The clipboard
|
|
177
|
+
|
|
178
|
+
Off by default. The **clipboard button in the window's toolbar** turns it on, or
|
|
179
|
+
from a command line:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
npx ai-remote clipboard on # both directions, until turned off
|
|
183
|
+
npx ai-remote clipboard # what it is doing now
|
|
184
|
+
npx ai-remote open HOST -u USER --clipboard # on from the start
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
While it is on, text copied on this machine reaches the remote clipboard and
|
|
188
|
+
text copied there reaches this one — so a password, a path or a stack trace
|
|
189
|
+
moves without being typed. Only a desktop has a clipboard: RDP negotiates one
|
|
190
|
+
and VNC has it in the protocol, while an `--ssh` session has none and the button
|
|
191
|
+
does not appear.
|
|
192
|
+
|
|
193
|
+
Turn it off before copying anything on this machine that the remote end should
|
|
194
|
+
not see. Off is a real off — nothing is read and nothing is written.
|
|
195
|
+
|
|
152
196
|
## Copying files
|
|
153
197
|
|
|
154
198
|
`cp` is scp with the session standing in for the host. A remote path starts with
|
|
@@ -370,7 +414,9 @@ npx ai-remote click X,Y [--button right|middle] [--double]
|
|
|
370
414
|
npx ai-remote type "text"
|
|
371
415
|
npx ai-remote key ControlLeft+KeyA
|
|
372
416
|
npx ai-remote do "key MetaLeft; wait 800; type notepad; shot s.png"
|
|
373
|
-
npx ai-remote exec "command"
|
|
417
|
+
npx ai-remote exec "command" [--reconnect]
|
|
418
|
+
npx ai-remote reconnect # a new login: fresh PATH
|
|
419
|
+
npx ai-remote clipboard [on|off] # share text both ways
|
|
374
420
|
npx ai-remote cp [-r] SRC DST # ':path' is on the session
|
|
375
421
|
npx ai-remote view [--watch-only] [--close]
|
|
376
422
|
npx ai-remote status | list | close [--all]
|
|
@@ -935,6 +935,18 @@ function filterDisplay(session, bytes) {
|
|
|
935
935
|
}
|
|
936
936
|
return shown ? encodeUtf8(shown) : NO_BYTES;
|
|
937
937
|
}
|
|
938
|
+
function announceCommand(session, command) {
|
|
939
|
+
const shown = command.replace(/\r?\n/g, " \u23CE ").trimEnd();
|
|
940
|
+
if (!shown) return;
|
|
941
|
+
session.dispatchEvent(new CustomEvent("data", {
|
|
942
|
+
detail: {
|
|
943
|
+
bytes: NO_BYTES,
|
|
944
|
+
display: encodeUtf8(`\x1B[1m${shown}\x1B[0m\r
|
|
945
|
+
`),
|
|
946
|
+
isStderr: false
|
|
947
|
+
}
|
|
948
|
+
}));
|
|
949
|
+
}
|
|
938
950
|
function releaseDisplayFilter(session) {
|
|
939
951
|
const filter = session.displayFilter;
|
|
940
952
|
session.displayFilter = null;
|
|
@@ -1092,6 +1104,7 @@ var SshSession = class extends EventTarget {
|
|
|
1092
1104
|
this.commandInFlight = true;
|
|
1093
1105
|
const startedAt = Date.now();
|
|
1094
1106
|
this.displayFilter = { begin, end, stage: "before", pending: "" };
|
|
1107
|
+
announceCommand(this, text);
|
|
1095
1108
|
this.dispatchEvent(new CustomEvent("command", {
|
|
1096
1109
|
detail: { phase: "start", id, command: text }
|
|
1097
1110
|
}));
|