@firstpick/pi-package-remote-webui 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Firstpick
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @firstpick/pi-package-remote-webui
2
+
3
+ Mobile connection helper for [Pi coding agent](https://www.npmjs.com/package/@earendil-works/pi-coding-agent).
4
+
5
+ This package adds a `/remote` slash command that reuses the existing `@firstpick/pi-package-webui` server/UI, opens it to a trusted local network, and shows a QR code in Pi so a phone can connect quickly.
6
+
7
+ > **Security:** Pi Web UI can control the Web UI/Pi session. Remote PIN authentication is off by default; enable it in Web UI **Controls → Network → Remote PIN auth** if you want a 4-digit PIN for non-local clients. Use `/remote` only on trusted local networks and close LAN access when done.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pi install npm:@firstpick/pi-package-remote-webui
13
+ ```
14
+
15
+ Restart Pi after installation so the `/remote` command is loaded. The QR renderer (`qrcode-terminal`) is a runtime dependency of this Pi package and is installed with the package. For local checkout development, run `npm install` in this package directory instead of installing `qrcode-terminal` globally.
16
+
17
+ ## Usage
18
+
19
+ ```text
20
+ /remote
21
+ ```
22
+
23
+ Default behavior:
24
+
25
+ 1. Reuse a running Pi Web UI on `127.0.0.1:31415`, or start one for the current working directory.
26
+ 2. Open the Web UI listener to the local network through the existing Web UI `/api/network/open` endpoint.
27
+ 3. Show a terminal QR code, the LAN URL, and the current Remote PIN auth state.
28
+ 4. Scan the QR code from your phone and use the normal Pi Web UI. If Remote PIN auth is enabled, enter the displayed 4-digit PIN on the phone.
29
+
30
+ ## Commands
31
+
32
+ ```text
33
+ /remote
34
+ /remote status
35
+ /remote refresh
36
+ /remote close
37
+ /remote --port 31500
38
+ /remote --name mobile
39
+ /remote --yes
40
+ ```
41
+
42
+ | Command | Behavior |
43
+ |---|---|
44
+ | `/remote` | Start/reuse Web UI, confirm, open LAN access, and show QR plus Remote PIN auth state. |
45
+ | `/remote status` | Show Web UI online/network state, LAN URLs, and auth state. |
46
+ | `/remote refresh` | Re-read current LAN URL/auth state and redraw the QR widget. |
47
+ | `/remote close` | Close Web UI LAN exposure and clear the QR widget. |
48
+ | `/remote --port 31500` | Use another Web UI port. |
49
+ | `/remote --name mobile` | Name the initial Web UI tab when this package starts the server. |
50
+ | `/remote --yes` | Skip the LAN exposure confirmation. |
51
+
52
+ ## Remote PIN auth
53
+
54
+ `/remote` does not enable Remote PIN auth by itself. Auth is intentionally controlled by the Web UI server:
55
+
56
+ - In the local Web UI, open **Controls → Network → Remote PIN auth**.
57
+ - Enabling it generates a random 4-digit PIN.
58
+ - Non-local browser clients must enter that PIN before reaching Web UI.
59
+ - Localhost clients can always use the UI and toggle the setting.
60
+
61
+ The `/remote` QR widget shows `Remote PIN auth: off` or `Remote PIN auth: on · PIN 1234` when the Web UI server reports it. You can also start Web UI with auth already enabled by using `pi-webui --remote-auth` or `/webui-start --remote-auth` from `@firstpick/pi-package-webui`.
62
+
63
+ ## Caveat
64
+
65
+ This package does not mirror the exact live TUI conversation into the phone. It connects mobile to the existing Pi Web UI package, which starts/uses Pi RPC tabs with the same Pi installation, working directory, settings, packages, and session storage.
66
+
67
+ ## Development
68
+
69
+ ```bash
70
+ cd pi-package-remote-webui
71
+ npm test
72
+ npm run check
73
+ ```
74
+
75
+ ## Network safety
76
+
77
+ `/remote` intentionally uses `pi-package-webui`'s direct LAN mode instead of a reverse proxy, preserving Web UI's current localhost-vs-remote trust boundaries. Remote PIN auth remains an explicit Web UI Controls toggle and is a trusted-LAN convenience gate, not hardened multi-user authentication. Use `/remote close` when you are done.
package/docs/PLAN.md ADDED
@@ -0,0 +1,367 @@
1
+ ## Plan: `pi-package-remote-webui`
2
+
3
+ ## Implementation Progress
4
+
5
+ - [x] Plan captured in this file.
6
+ - [x] Implement package manifest, extension command, and reusable core helpers.
7
+ - [x] Add tests for argument parsing, status formatting, QR/widget output, and mocked WebUI control.
8
+ - [x] Run package checks and record results.
9
+
10
+ ### Verification Log
11
+
12
+ - `cd pi-package-remote-webui && npm test` — passed 14/14 tests.
13
+ - `cd pi-package-remote-webui && npm run check` — passed syntax check for `lib/remote-core.mjs` and 14/14 tests.
14
+ - `cd pi-package-remote-webui && npm pack --dry-run` — package dry-run succeeded and includes 9 files.
15
+
16
+ ### Recommendation
17
+
18
+ Create `pi-package-remote-webui` as a **thin Pi extension package** that reuses the existing `@firstpick/pi-package-webui` server/UI instead of building a second mobile UI.
19
+
20
+ The package should add one main command:
21
+
22
+ ```text
23
+ /remote
24
+ ```
25
+
26
+ That command should:
27
+
28
+ 1. Start or reuse the Pi Web UI server.
29
+ 2. Open it to the local network using the existing WebUI network endpoint.
30
+ 3. Pick a LAN URL.
31
+ 4. Render a QR code in Pi.
32
+ 5. Let the user scan the QR code on mobile and use the existing Pi Web UI.
33
+
34
+ This should be a UX wrapper around the current WebUI package, not a fork of it.
35
+
36
+ ---
37
+
38
+ ## Important caveat
39
+
40
+ Current `pi-package-webui` does **not** mirror the live terminal/TUI session. It starts Pi in RPC mode for WebUI tabs.
41
+
42
+ So the first version of `/remote` should mean:
43
+
44
+ > “Open a mobile WebUI connected to this Pi installation, current working directory, settings, packages, and session storage.”
45
+
46
+ It should **not** promise:
47
+
48
+ > “The phone controls the exact same live terminal conversation.”
49
+
50
+ That would require deeper Pi/WebUI core changes or a dedicated bridge.
51
+
52
+ ---
53
+
54
+ ## Package structure
55
+
56
+ ```text
57
+ pi-package-remote-webui/
58
+ package.json
59
+ index.ts
60
+ README.md
61
+ LICENSE
62
+ tests/
63
+ remote-args.test.mjs
64
+ remote-webui-control.test.mjs
65
+ ```
66
+
67
+ Suggested package name:
68
+
69
+ ```json
70
+ {
71
+ "name": "@firstpick/pi-package-remote-webui",
72
+ "keywords": ["pi-package", "pi", "webui", "remote", "mobile", "qr"],
73
+ "pi": {
74
+ "extensions": ["./index.ts"]
75
+ },
76
+ "dependencies": {
77
+ "@firstpick/pi-package-webui": "^0.3.8",
78
+ "qrcode-terminal": "^0.12.0"
79
+ },
80
+ "peerDependencies": {
81
+ "@earendil-works/pi-coding-agent": "*"
82
+ }
83
+ }
84
+ ```
85
+
86
+ ---
87
+
88
+ ## `/remote` command design
89
+
90
+ ### Default
91
+
92
+ ```text
93
+ /remote
94
+ ```
95
+
96
+ Behavior:
97
+
98
+ 1. Probe `http://127.0.0.1:31415/api/health`.
99
+ 2. If no WebUI server is running, start `pi-webui` from `@firstpick/pi-package-webui`.
100
+ 3. Ensure it is open to LAN via:
101
+
102
+ ```http
103
+ POST /api/network/open
104
+ ```
105
+
106
+ 4. Poll:
107
+
108
+ ```http
109
+ GET /api/network
110
+ ```
111
+
112
+ 5. Use the first available LAN URL, e.g.
113
+
114
+ ```text
115
+ http://192.168.1.42:31415/
116
+ ```
117
+
118
+ 6. Render QR code plus text:
119
+
120
+ ```text
121
+ Pi Remote WebUI
122
+
123
+ Scan with your phone:
124
+
125
+ <QR CODE>
126
+
127
+ http://192.168.1.42:31415/
128
+
129
+ Remote PIN auth: off
130
+
131
+ Trusted LAN only. Remote PIN auth is off; anyone with this URL can control Pi/WebUI.
132
+ Close with: /remote close
133
+ ```
134
+
135
+ Use `ctx.ui.setWidget()` so the QR remains visible after the command finishes.
136
+
137
+ ---
138
+
139
+ ## Command options
140
+
141
+ ```text
142
+ /remote
143
+ /remote status
144
+ /remote close
145
+ /remote refresh
146
+ /remote --port 31500
147
+ /remote --name mobile
148
+ /remote --yes
149
+ ```
150
+
151
+ ### Recommended meanings
152
+
153
+ | Command | Behavior |
154
+ |---|---|
155
+ | `/remote` | Start/reuse WebUI, open to LAN, show QR |
156
+ | `/remote status` | Show WebUI status, LAN URLs, whether network is open |
157
+ | `/remote close` | Call `/api/network/close`, clear QR widget/status |
158
+ | `/remote refresh` | Re-read LAN URLs and redraw QR |
159
+ | `/remote --port 31500` | Use another WebUI port |
160
+ | `/remote --name mobile` | Name the initial WebUI tab |
161
+ | `/remote --yes` | Skip confirmation warning |
162
+
163
+ ---
164
+
165
+ ## Security model
166
+
167
+ Use the existing WebUI direct LAN mode for v1.
168
+
169
+ Do **not** put a reverse proxy in front of WebUI for v1, because WebUI currently uses the real client address to distinguish localhost clients from remote LAN clients. A proxy would make mobile requests look like localhost unless carefully redesigned, weakening WebUI’s current trust boundaries.
170
+
171
+ ### Required v1 behavior
172
+
173
+ Before opening the WebUI to LAN, show a confirmation that remote browsers can control the Web UI/Pi session and that Remote PIN auth is off by default unless enabled in Web UI Controls.
174
+
175
+ Default should be “No” unless `/remote --yes` is provided.
176
+
177
+ ### Remote PIN auth
178
+
179
+ Remote PIN auth is implemented in `pi-package-webui`, not in `/remote`, so the localhost-vs-remote trust semantics remain server-owned:
180
+
181
+ - The Web UI side-panel **Controls → Network → Remote PIN auth** toggle is off by default.
182
+ - Enabling it generates a random 4-digit PIN.
183
+ - Non-local clients are challenged before accessing Web UI routes and APIs.
184
+ - Localhost clients can toggle the setting and see the PIN.
185
+ - `/remote` reads the reported auth state from `/api/network` and includes it in the QR widget.
186
+
187
+ Startup auth is also available through:
188
+
189
+ ```text
190
+ pi-webui --remote-auth
191
+ /webui-start --remote-auth
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Implementation flow
197
+
198
+ ### 1. Resolve WebUI binary
199
+
200
+ In `index.ts`, locate the bundled WebUI CLI:
201
+
202
+ ```ts
203
+ @firstpick/pi-package-webui/bin/pi-webui.mjs
204
+ ```
205
+
206
+ Use `createRequire(import.meta.url).resolve(...)` or a safe package-root fallback.
207
+
208
+ ---
209
+
210
+ ### 2. Probe existing server
211
+
212
+ Check:
213
+
214
+ ```http
215
+ GET http://127.0.0.1:<port>/api/health
216
+ ```
217
+
218
+ Accept only responses with:
219
+
220
+ ```json
221
+ {
222
+ "ok": true,
223
+ "webuiVersion": "..."
224
+ }
225
+ ```
226
+
227
+ ---
228
+
229
+ ### 3. Start WebUI if needed
230
+
231
+ Spawn:
232
+
233
+ ```bash
234
+ node path/to/pi-webui.mjs --host 127.0.0.1 --port <port> --cwd <ctx.cwd>
235
+ ```
236
+
237
+ Do not open the desktop browser.
238
+
239
+ Wait until `/api/health` succeeds.
240
+
241
+ ---
242
+
243
+ ### 4. Open LAN access
244
+
245
+ Call from localhost:
246
+
247
+ ```http
248
+ POST http://127.0.0.1:<port>/api/network/open
249
+ ```
250
+
251
+ Then poll:
252
+
253
+ ```http
254
+ GET http://127.0.0.1:<port>/api/network
255
+ ```
256
+
257
+ until:
258
+
259
+ ```json
260
+ {
261
+ "open": true,
262
+ "networkUrls": ["http://192.168.x.x:31415/"]
263
+ }
264
+ ```
265
+
266
+ If no LAN address is found, show a helpful error.
267
+
268
+ ---
269
+
270
+ ### 5. Render QR
271
+
272
+ Use `qrcode-terminal` or a tiny local QR helper.
273
+
274
+ Display with:
275
+
276
+ ```ts
277
+ ctx.ui.setWidget("pi-remote-webui", lines, { placement: "aboveEditor" });
278
+ ctx.ui.setStatus("pi-remote-webui", "remote webui open");
279
+ ctx.ui.notify("Pi Remote WebUI ready", "info");
280
+ ```
281
+
282
+ ---
283
+
284
+ ### 6. Close remote mode
285
+
286
+ `/remote close` should:
287
+
288
+ 1. Call:
289
+
290
+ ```http
291
+ POST http://127.0.0.1:<port>/api/network/close
292
+ ```
293
+
294
+ 2. Clear:
295
+
296
+ ```ts
297
+ ctx.ui.setWidget("pi-remote-webui", undefined);
298
+ ctx.ui.setStatus("pi-remote-webui", undefined);
299
+ ```
300
+
301
+ Do not kill the WebUI server unless an explicit future option like `/remote stop` is added.
302
+
303
+ ---
304
+
305
+ ## Testing plan
306
+
307
+ ### Unit tests
308
+
309
+ Test:
310
+
311
+ - Argument parsing.
312
+ - Port validation.
313
+ - URL selection from multiple LAN URLs.
314
+ - QR text generation.
315
+ - Status formatting.
316
+ - Confirmation-required behavior.
317
+
318
+ ### Mock WebUI tests
319
+
320
+ Use a local mock HTTP server for:
321
+
322
+ - `/api/health`
323
+ - `/api/network`
324
+ - `/api/network/open`
325
+ - `/api/network/close`
326
+
327
+ Verify `/remote` calls endpoints in the correct order.
328
+
329
+ ### Manual acceptance test
330
+
331
+ 1. Install package locally:
332
+
333
+ ```bash
334
+ pi install ./pi-package-remote-webui
335
+ ```
336
+
337
+ 2. Restart Pi.
338
+ 3. Run:
339
+
340
+ ```text
341
+ /remote
342
+ ```
343
+
344
+ 4. Confirm warning.
345
+ 5. Scan QR on phone.
346
+ 6. Verify Pi WebUI loads.
347
+ 7. Send a prompt from mobile.
348
+ 8. Run:
349
+
350
+ ```text
351
+ /remote close
352
+ ```
353
+
354
+ 9. Verify mobile disconnects or can no longer reach the WebUI.
355
+
356
+ ---
357
+
358
+ ## Acceptance criteria
359
+
360
+ - `/remote` starts from a normal Pi TUI session.
361
+ - QR code is visible and scannable from terminal.
362
+ - Mobile browser opens existing Pi WebUI.
363
+ - No separate mobile UI is built.
364
+ - `/remote close` closes LAN exposure.
365
+ - User is warned that Remote PIN auth is off by default unless enabled in Web UI Controls.
366
+ - QR/widget output shows Remote PIN auth state and PIN when enabled.
367
+ - Existing WebUI remote trust boundaries remain intact.