@firstpick/pi-package-webui 0.4.2 → 0.4.4

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 CHANGED
@@ -6,7 +6,7 @@ Local browser UI for [Pi coding agent](https://www.npmjs.com/package/@earendil-w
6
6
 
7
7
  Pi Web UI gives you a local browser companion for Pi: multi-tab chat, streaming output, model controls, uploads, slash-command helpers, workspace navigation, and optional extension widgets.
8
8
 
9
- > **Security:** Pi Web UI can control the spawned Pi session and run anything that session is allowed to run. It binds to `127.0.0.1` by default. Remote PIN authentication is off by default; enable it in **Controls → Network → Remote PIN auth** before exposing it on trusted networks.
9
+ > **Security:** Pi Web UI can control the spawned Pi session and run anything that session is allowed to run. It binds to `127.0.0.1` by default. Remote PIN authentication is off by default on first use; enabling it in **Controls → Network → Remote PIN auth** persists that preference for later Web UI starts.
10
10
 
11
11
  ## Requirements
12
12
 
@@ -123,6 +123,7 @@ Environment variables:
123
123
  - `PI_WEBUI_PORT`
124
124
  - `PI_WEBUI_PI_BIN`
125
125
  - `PI_WEBUI_REMOTE_AUTH=1` to start with remote PIN authentication enabled
126
+ - `PI_WEBUI_SETTINGS_FILE=/path/to/settings.json` to override where Web UI stores persisted settings such as the Remote PIN auth preference
126
127
 
127
128
  ## Main features
128
129
 
@@ -130,7 +131,7 @@ Environment variables:
130
131
  - Multi-tab Pi sessions with isolated processes, working directories, prompt drafts, activity state, and a workspace dashboard for common actions.
131
132
  - Unified command palette (`Ctrl/Cmd+K`) for commands, tabs, models, sessions, settings, and frequent Web UI actions.
132
133
  - Automatic tab naming from the first prompt, with `--name <name>` still available for an explicit initial tab name.
133
- - Streaming chat transcript with Markdown, thinking output, tool/bash cards, queue and compaction events, edit-and-retry from user prompts, and abort controls.
134
+ - Streaming chat transcript with Markdown, thinking output, tool/bash cards, queue and compaction events, edit-and-retry from user prompts, and guarded abort controls that require holding Esc or the Abort button for 3 seconds.
134
135
  - Prompt composer with uploads, drag/drop/paste, inline image support, slash-command autocomplete, and `@` file/path references with live suggestions.
135
136
  - Browser dialogs for common Pi selectors such as `/model`, `/settings`, `/theme`, `/fork`, `/clone`, `/resume`, `/tree`, `/scoped-models`, `/tools`, and `/skills`.
136
137
  - Model, thinking, session, workspace, theme, optional-feature, Codex usage, network, update/restart, event, and notification controls in the side panel.
@@ -138,7 +139,7 @@ Environment variables:
138
139
  - Side-panel theme picker backed by optional `@firstpick/pi-themes-bundle` themes when loaded.
139
140
  - Per-tab cwd changes, a clickable footer cwd picker, saved path fast picks, server-persisted fast picks, and restart-safe restoration of open tabs.
140
141
  - Detected app runner dropdown for the active tab cwd, including Cargo, Bun, npm/npx/pnpm, Python/uv, Go/Golang, Zig, C/C++, Docker Compose, root/dev/scripts shell scripts, and other common project runners with live output pinned at the top of the terminal. Projects can add browseable custom runners in `.pi-webui-runners.json` with a command (default `./`) plus a relative path to the file to run.
141
- - Browser support for Pi extension UI prompts, widgets, status updates, browser notifications when a tab needs an extension UI response and an optional side-panel toggle for agent-done notifications.
142
+ - Browser support for Pi extension UI prompts, widgets, status updates, `/btw` side-question output widgets with optional context transfer/live steering, browser notifications when a tab needs an extension UI response, and an optional side-panel toggle for agent-done notifications.
142
143
  - Localhost-only Pi/Web UI update checks with a top-right update notification and a confirmed **Update & restart** action that runs `pi update` plus all detected local/global Web UI and Pi package-manager updates, then restarts the Web UI server.
143
144
  - Feedback reactions (`👍`, `👎`, `?`) on final assistant output plus tool/bash action cards, which can ask Pi to create or update a LEARNING.
144
145
  - Mobile-friendly layout and PWA install support where the browser allows it.
@@ -155,7 +156,7 @@ Useful browser endpoints exposed by the local server include:
155
156
  For local development, run the checkout helper directly, for example:
156
157
 
157
158
  ```bash
158
- ./start-webui.sh --dev --cwd /path/to/project
159
+ ./dev/scripts/start-webui.sh --dev --cwd /path/to/project
159
160
  ```
160
161
 
161
162
  Run `../dev/scripts/sync-pi-package-symlinks.sh` first when developing companion packages from this workspace. The Web UI manifest loads companions through `node_modules/` paths, and the sync script links those paths to the top-level dev packages so only one copy is loaded.
@@ -168,13 +169,16 @@ When the standalone global `pi-webui` launcher is used, optional companion insta
168
169
 
169
170
  Optional companions:
170
171
 
172
+ - `@firstpick/pi-extension-btw` — ephemeral `/btw` side-question command with a TUI overlay, Web UI live output widget, and Transfer Context action.
171
173
  - `@firstpick/pi-prompts-git-pr` — guided Git commit/push workflow.
172
174
  - `@firstpick/pi-extension-release-npm` — NPM publish menu and release widgets.
173
175
  - `@firstpick/pi-extension-release-aur` — AUR publish menu and release widgets.
176
+ - `@firstpick/pi-extension-workflows` — `/workflow` runtime with non-blocking Web UI subprocess-output widgets.
174
177
  - `@firstpick/pi-extension-safety-guard` — interactive guardrails for dangerous bash commands and protected file edits.
175
178
  - `@firstpick/pi-extension-setup-skills` — TUI `/skills` setup command alongside WebUI-native skill toggles.
176
179
  - `@firstpick/pi-extension-todo-progress` — todo-progress rendering.
177
180
  - `@firstpick/pi-extension-tools` — TUI `/tools` active-tool manager alongside WebUI-native tool toggles.
181
+ - `@firstpick/pi-package-remote-webui` — `/remote` trusted-LAN QR helper for connecting mobile browsers to Web UI.
178
182
  - `@firstpick/pi-extension-git-footer-status` — richer extension-owned git/footer status, including the structured Web UI footer payload.
179
183
  - `@firstpick/pi-extension-stats` — stats commands and status data.
180
184
  - `@firstpick/pi-themes-bundle` — Web UI and Pi theme resources.
@@ -205,8 +209,8 @@ This requires `/git-staged-msg` and `/pr` from `@firstpick/pi-prompts-git-pr`; b
205
209
 
206
210
  - Default bind is localhost-only: `127.0.0.1:31415`.
207
211
  - The side-panel **Open to network** button rebinds the server to `0.0.0.0`, shows LAN URLs when available, and toggles to "Close for network".
208
- - The side-panel **Remote PIN auth** toggle is off by default. When enabled, the server generates a random 4-digit PIN, shows it in Controls and `/webui-status`, and requires it from non-local browser clients.
209
- - Localhost clients stay frictionless and can toggle Remote PIN auth; changing the toggle disconnects existing event streams so remote clients must re-authenticate after enablement.
212
+ - The side-panel **Remote PIN auth** toggle is off by default on first use. When enabled, the server saves that preference, generates a fresh random 4-digit PIN for each server start, shows it in Controls and `/webui-status`, and requires it from non-local browser clients.
213
+ - Localhost clients stay frictionless and can toggle Remote PIN auth; changing the toggle persists the preference and disconnects existing event streams so remote clients must re-authenticate after enablement.
210
214
  - `--host 0.0.0.0` also exposes the Web UI to the local network; pass `--remote-auth` to start with PIN auth already enabled.
211
215
  - Any connected browser client with access (and the PIN, if enabled) can control Pi and run Web UI bash actions as the Web UI process user.
212
216
  - Remote PIN auth is a simple trusted-LAN HTTP gate, not hardened multi-user authentication; do not expose it to untrusted networks.
package/bin/pi-webui.mjs CHANGED
@@ -43,6 +43,7 @@ const publicDir = path.join(packageRoot, "public");
43
43
  const webuiHelperExtensionPath = path.join(packageRoot, "webui-rpc-helper.mjs");
44
44
  const agentDir = process.env.PI_CODING_AGENT_DIR || path.join(homedir(), ".pi", "agent");
45
45
  const OPTIONAL_FEATURE_INSTALL_ROOT_ENV = "PI_WEBUI_OPTIONAL_FEATURE_INSTALL_ROOT";
46
+ const WEBUI_SETTINGS_FILE_ENV = "PI_WEBUI_SETTINGS_FILE";
46
47
  const packageJson = JSON.parse(await readFile(path.join(packageRoot, "package.json"), "utf8"));
47
48
  let piPackageJson = {};
48
49
  try {
@@ -51,7 +52,7 @@ try {
51
52
  } catch {
52
53
  piPackageJson = {};
53
54
  }
54
- const nativeParityMatrix = JSON.parse(await readFile(path.join(packageRoot, "WEBUI_TUI_NATIVE_PARITY.json"), "utf8"));
55
+ const nativeParityMatrix = JSON.parse(await readFile(path.join(packageRoot, "dev", "docs", "WEBUI_TUI_NATIVE_PARITY.json"), "utf8"));
55
56
  const webuiDevServer = isTruthyEnv(process.env.PI_WEBUI_DEV) || isSourceCheckout(packageRoot);
56
57
 
57
58
  const DEFAULT_HOST = "127.0.0.1";
@@ -220,13 +221,16 @@ function parseSlashCommand(message) {
220
221
  return parseNativeSlashCommand(message, NATIVE_SLASH_COMMAND_NAMES);
221
222
  }
222
223
  const OPTIONAL_FEATURE_PACKAGES = new Map([
224
+ ["btwCommand", "@firstpick/pi-extension-btw"],
223
225
  ["gitWorkflow", "@firstpick/pi-prompts-git-pr"],
224
226
  ["releaseNpm", "@firstpick/pi-extension-release-npm"],
225
227
  ["releaseAur", "@firstpick/pi-extension-release-aur"],
228
+ ["workflows", "@firstpick/pi-extension-workflows"],
226
229
  ["safetyGuard", "@firstpick/pi-extension-safety-guard"],
227
230
  ["tuiSkillsCommand", "@firstpick/pi-extension-setup-skills"],
228
231
  ["todoProgressWidget", "@firstpick/pi-extension-todo-progress"],
229
232
  ["tuiToolsCommand", "@firstpick/pi-extension-tools"],
233
+ ["remoteWebui", "@firstpick/pi-package-remote-webui"],
230
234
  ["gitFooterStatus", "@firstpick/pi-extension-git-footer-status"],
231
235
  ["statsCommand", "@firstpick/pi-extension-stats"],
232
236
  ["themeBundle", "@firstpick/pi-themes-bundle"],
@@ -265,8 +269,8 @@ Examples:
265
269
 
266
270
  Security:
267
271
  The web UI controls Pi tools. It binds to localhost by default. Remote PIN
268
- authentication is off by default; enable it in Controls or with --remote-auth
269
- before exposing the server on trusted networks.
272
+ authentication is off by default on first use; enabling it in Controls saves
273
+ that preference for later starts.
270
274
  `);
271
275
  }
272
276
 
@@ -289,6 +293,7 @@ function parseArgs(argv) {
289
293
  noSession: false,
290
294
  name: undefined,
291
295
  remoteAuth: isTruthyEnv(process.env.PI_WEBUI_REMOTE_AUTH),
296
+ remoteAuthExplicit: process.env.PI_WEBUI_REMOTE_AUTH !== undefined,
292
297
  piArgs: [],
293
298
  help: false,
294
299
  version: false,
@@ -345,10 +350,12 @@ function parseArgs(argv) {
345
350
  }
346
351
  if (arg === "--remote-auth") {
347
352
  options.remoteAuth = true;
353
+ options.remoteAuthExplicit = true;
348
354
  continue;
349
355
  }
350
356
  if (arg === "--no-remote-auth") {
351
357
  options.remoteAuth = false;
358
+ options.remoteAuthExplicit = true;
352
359
  continue;
353
360
  }
354
361
  throw new Error(`Unknown option: ${arg}. Pass Pi CLI args after --.`);
@@ -739,7 +746,7 @@ function sendRemoteAuthPage(res, returnPath = "/") {
739
746
  <body>
740
747
  <main>
741
748
  <h1>Remote PIN required</h1>
742
- <p>Enter the 4-digit PIN shown in the local Pi terminal or local Web UI to continue.</p>
749
+ <p>Scan a trusted /remote QR code to unlock automatically, or enter the 4-digit PIN shown in the local Pi terminal or local Web UI.</p>
743
750
  <form id="pinForm" autocomplete="off">
744
751
  <label for="pin">PIN</label>
745
752
  <input id="pin" name="pin" inputmode="numeric" pattern="[0-9]{4}" maxlength="4" autofocus required>
@@ -753,16 +760,19 @@ function sendRemoteAuthPage(res, returnPath = "/") {
753
760
  const input = document.getElementById("pin");
754
761
  const button = document.getElementById("submit");
755
762
  const error = document.getElementById("error");
756
- input.addEventListener("input", () => { input.value = input.value.replace(/\\D/g, "").slice(0, 4); error.textContent = ""; });
757
- form.addEventListener("submit", async (event) => {
758
- event.preventDefault();
763
+ function pinFromHash() {
764
+ const params = new URLSearchParams(String(window.location.hash || "").replace(/^#/, ""));
765
+ const pin = String(params.get("pin") || "").trim();
766
+ return /^\\d{4}$/.test(pin) ? pin : "";
767
+ }
768
+ async function submitPin(pin) {
759
769
  button.disabled = true;
760
770
  error.textContent = "";
761
771
  try {
762
772
  const response = await fetch("/api/remote-auth", {
763
773
  method: "POST",
764
774
  headers: { "content-type": "application/json" },
765
- body: JSON.stringify({ pin: input.value }),
775
+ body: JSON.stringify({ pin }),
766
776
  });
767
777
  const data = await response.json().catch(() => ({}));
768
778
  if (!response.ok || data.ok !== true) throw new Error(data.error || "Incorrect PIN");
@@ -773,7 +783,18 @@ function sendRemoteAuthPage(res, returnPath = "/") {
773
783
  } finally {
774
784
  button.disabled = false;
775
785
  }
786
+ }
787
+ input.addEventListener("input", () => { input.value = input.value.replace(/\\D/g, "").slice(0, 4); error.textContent = ""; });
788
+ form.addEventListener("submit", async (event) => {
789
+ event.preventDefault();
790
+ await submitPin(input.value);
776
791
  });
792
+ const autoPin = pinFromHash();
793
+ if (autoPin) {
794
+ input.value = autoPin;
795
+ window.history.replaceState(null, "", window.location.pathname + (window.location.search || ""));
796
+ submitPin(autoPin);
797
+ }
777
798
  </script>
778
799
  </body>
779
800
  </html>`;
@@ -1332,6 +1353,50 @@ async function writePathFastPicks(picks) {
1332
1353
  return normalized;
1333
1354
  }
1334
1355
 
1356
+ function webuiSettingsFile() {
1357
+ if (process.env[WEBUI_SETTINGS_FILE_ENV]) return path.resolve(expandUserPath(process.env[WEBUI_SETTINGS_FILE_ENV]));
1358
+ const configRoot = process.env.XDG_CONFIG_HOME || path.join(homedir(), ".config");
1359
+ return path.join(configRoot, "pi-webui", "settings.json");
1360
+ }
1361
+
1362
+ function normalizeWebuiSettings(value) {
1363
+ return {
1364
+ version: 1,
1365
+ remoteAuthEnabled: value?.remoteAuthEnabled === true,
1366
+ };
1367
+ }
1368
+
1369
+ let webuiSettingsCache = null;
1370
+
1371
+ async function readWebuiSettings() {
1372
+ if (webuiSettingsCache) return webuiSettingsCache;
1373
+ webuiSettingsCache = normalizeWebuiSettings(await readJsonFileIfExists(webuiSettingsFile()));
1374
+ return webuiSettingsCache;
1375
+ }
1376
+
1377
+ async function writeWebuiSettings(patch) {
1378
+ const current = await readWebuiSettings();
1379
+ const next = normalizeWebuiSettings({ ...current, ...(patch || {}) });
1380
+ const storageFile = webuiSettingsFile();
1381
+ await mkdir(path.dirname(storageFile), { recursive: true });
1382
+ const tmpFile = `${storageFile}.${process.pid}.${Date.now()}.tmp`;
1383
+ await writeFile(tmpFile, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600 });
1384
+ await rename(tmpFile, storageFile);
1385
+ webuiSettingsCache = next;
1386
+ return next;
1387
+ }
1388
+
1389
+ async function readPersistedRemoteAuthEnabled() {
1390
+ return (await readWebuiSettings()).remoteAuthEnabled === true;
1391
+ }
1392
+
1393
+ async function saveRemoteAuthPreference(enabled) {
1394
+ const nextEnabled = enabled === true;
1395
+ await writeWebuiSettings({ remoteAuthEnabled: nextEnabled });
1396
+ persistedRemoteAuthEnabled = nextEnabled;
1397
+ return persistedRemoteAuthEnabled;
1398
+ }
1399
+
1335
1400
  function parseCliScopedModelPatterns() {
1336
1401
  for (let index = 0; index < options.piArgs.length; index++) {
1337
1402
  const arg = options.piArgs[index];
@@ -5317,8 +5382,10 @@ function renameTab(tab, title, { source = "explicit", maxLength, unique = source
5317
5382
  }
5318
5383
 
5319
5384
  function maybeNameTabForConversation(tab, command) {
5320
- if (!tab || !commandStartsConversation(command) || tab.conversationStarted || tab.titleSource === "explicit") return false;
5385
+ if (!tab || !commandStartsConversation(command)) return false;
5386
+ const shouldRename = !tab.conversationStarted && tab.titleSource !== "explicit";
5321
5387
  tab.conversationStarted = true;
5388
+ if (!shouldRename) return false;
5322
5389
  const title = generatedTabTitleFromPrompt(command.message) || `Conversation ${tab.index}`;
5323
5390
  return renameTab(tab, title, { source: "auto", maxLength: AUTO_TAB_TITLE_MAX_LENGTH });
5324
5391
  }
@@ -6606,6 +6673,7 @@ async function createInitialTabs() {
6606
6673
  }
6607
6674
 
6608
6675
  const serverStartedAt = new Date().toISOString();
6676
+ let persistedRemoteAuthEnabled = await readPersistedRemoteAuthEnabled();
6609
6677
  const initialTabs = await createInitialTabs();
6610
6678
  const initialTab = initialTabs[0];
6611
6679
  let currentHost = options.host;
@@ -6650,6 +6718,19 @@ function resetRemoteAuth() {
6650
6718
  remoteAuth.tokenExpiresAt = 0;
6651
6719
  }
6652
6720
 
6721
+ function remoteAuthPreferenceEnabled() {
6722
+ return persistedRemoteAuthEnabled === true;
6723
+ }
6724
+
6725
+ function remoteAuthStartupEnabled() {
6726
+ return options.remoteAuthExplicit ? options.remoteAuth === true : remoteAuthPreferenceEnabled();
6727
+ }
6728
+
6729
+ function remoteAuthStartupReason() {
6730
+ if (options.remoteAuthExplicit) return "startup option";
6731
+ return "saved setting";
6732
+ }
6733
+
6653
6734
  function remoteAuthStatus({ includePin = false } = {}) {
6654
6735
  const enabled = !!remoteAuth.pin;
6655
6736
  const status = {
@@ -6798,9 +6879,9 @@ async function closeNetworkAccess() {
6798
6879
  await closeServerListener();
6799
6880
  await listenOn(nextHost);
6800
6881
  currentHost = nextHost;
6801
- resetRemoteAuth();
6882
+ if (!remoteAuthPreferenceEnabled()) resetRemoteAuth();
6802
6883
  console.warn("Web UI network access closed; listening on localhost only.");
6803
- return networkStatus();
6884
+ return networkStatus({ includeAuthPin: true });
6804
6885
  } catch (error) {
6805
6886
  console.error("Failed to close Web UI network access:", sanitizeError(error));
6806
6887
  if (!server.listening) {
@@ -6817,7 +6898,7 @@ async function closeNetworkAccess() {
6817
6898
  }
6818
6899
  }
6819
6900
 
6820
- if (!isLocalHost(currentHost) && options.remoteAuth !== false) enableRemoteAuth("startup network listener");
6901
+ if (remoteAuthStartupEnabled()) enableRemoteAuth(remoteAuthStartupReason());
6821
6902
 
6822
6903
  async function safeRpcData(tab, command, timeoutMs = STATUS_RPC_TIMEOUT_MS) {
6823
6904
  try {
@@ -6961,9 +7042,13 @@ const server = createServer(async (req, res) => {
6961
7042
  if (url.pathname === "/api/remote-auth/settings" && req.method === "POST") {
6962
7043
  requireLocalhostRoute(req, url.pathname);
6963
7044
  const body = await readJsonBody(req);
6964
- if (body.enabled === true) enableRemoteAuth("side panel toggle");
6965
- else if (body.enabled === false) resetRemoteAuth();
6966
- else throw makeHttpError(400, "enabled must be true or false");
7045
+ if (body.enabled === true) {
7046
+ enableRemoteAuth("side panel toggle");
7047
+ await saveRemoteAuthPreference(true);
7048
+ } else if (body.enabled === false) {
7049
+ resetRemoteAuth();
7050
+ await saveRemoteAuthPreference(false);
7051
+ } else throw makeHttpError(400, "enabled must be true or false");
6967
7052
  closeSseClientsForRemoteAuthChange();
6968
7053
  const headers = body.enabled === false ? { "set-cookie": clearRemoteAuthCookie() } : {};
6969
7054
  sendJson(res, 200, { ok: true, data: { auth: remoteAuthStatus({ includePin: true }), network: networkStatus({ includeAuthPin: true }) } }, headers);
@@ -445,8 +445,8 @@
445
445
  "priority": "P1",
446
446
  "sensitive": false,
447
447
  "guards": ["confirmation"],
448
- "currentBehavior": "Escape aborts active user bash first, then active agent runs, and closes UI surfaces with tab scoping.",
449
- "targetBehavior": "Abort active bash first where applicable; keep agent/tab scoping and clear UI cancellation rules."
448
+ "currentBehavior": "Holding Escape for 3 seconds aborts active user bash first, then active agent runs, and closes UI surfaces with tab scoping before arming abort.",
449
+ "targetBehavior": "Abort active bash first where applicable; keep agent/tab scoping and clear UI cancellation rules with a guarded hold-to-abort affordance."
450
450
  },
451
451
  {
452
452
  "id": "shortcut.editor.clear",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firstpick/pi-package-webui",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Pi Web UI companion package with a local browser UI CLI plus /webui-start and /webui-status commands.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/Firstp1ck/npm-packages/tree/main/pi-package-webui#readme",
@@ -23,14 +23,17 @@
23
23
  "image": "https://unpkg.com/@firstpick/pi-package-webui/images/WebUI_v0.3.7.png",
24
24
  "extensions": [
25
25
  "./index.ts",
26
+ "node_modules/@firstpick/pi-extension-btw/index.ts",
26
27
  "node_modules/@firstpick/pi-extension-git-footer-status/index.ts",
27
28
  "node_modules/@firstpick/pi-extension-release-aur/index.ts",
28
29
  "node_modules/@firstpick/pi-extension-release-npm/index.ts",
30
+ "node_modules/@firstpick/pi-extension-workflows/index.ts",
29
31
  "node_modules/@firstpick/pi-extension-safety-guard/index.ts",
30
32
  "node_modules/@firstpick/pi-extension-setup-skills/index.ts",
31
33
  "node_modules/@firstpick/pi-extension-stats/index.ts",
32
34
  "node_modules/@firstpick/pi-extension-todo-progress/index.ts",
33
- "node_modules/@firstpick/pi-extension-tools/index.ts"
35
+ "node_modules/@firstpick/pi-extension-tools/index.ts",
36
+ "node_modules/@firstpick/pi-package-remote-webui/index.ts"
34
37
  ],
35
38
  "skills": [
36
39
  "node_modules/@firstpick/pi-extension-release-aur/skills"
@@ -50,17 +53,20 @@
50
53
  "test": "node tests/run-all.mjs"
51
54
  },
52
55
  "dependencies": {
53
- "@earendil-works/pi-coding-agent": "^0.79.1"
56
+ "@earendil-works/pi-coding-agent": "^0.79.3"
54
57
  },
55
58
  "optionalDependencies": {
59
+ "@firstpick/pi-extension-btw": "^0.1.0",
56
60
  "@firstpick/pi-extension-git-footer-status": "^0.3.3",
57
61
  "@firstpick/pi-extension-release-aur": "^0.1.6",
58
62
  "@firstpick/pi-extension-release-npm": "^0.4.0",
63
+ "@firstpick/pi-extension-workflows": "^0.1.0",
59
64
  "@firstpick/pi-extension-safety-guard": "^0.2.3",
60
65
  "@firstpick/pi-extension-setup-skills": "^0.1.8",
61
66
  "@firstpick/pi-extension-stats": "^0.2.6",
62
67
  "@firstpick/pi-extension-todo-progress": "^0.2.4",
63
68
  "@firstpick/pi-extension-tools": "^0.1.6",
69
+ "@firstpick/pi-package-remote-webui": "^0.1.0",
64
70
  "@firstpick/pi-prompts-git-pr": "^0.1.2",
65
71
  "@firstpick/pi-themes-bundle": "^0.1.4"
66
72
  },
@@ -72,9 +78,7 @@
72
78
  "public",
73
79
  "images",
74
80
  "tests",
75
- "start-webui.sh",
76
- "start-webui.ps1",
77
- "WEBUI_TUI_NATIVE_PARITY.json",
81
+ "dev/docs/WEBUI_TUI_NATIVE_PARITY.json",
78
82
  "README.md",
79
83
  "LICENSE"
80
84
  ],