@polterware/polter 0.3.0 → 0.4.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/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import {
10
10
  findNearestPackageRoot,
11
11
  findPipelineByName,
12
12
  findPolterYaml,
13
+ generateProcessId,
13
14
  getAllPipelines,
14
15
  getCommandById,
15
16
  getCommandValue,
@@ -20,6 +21,7 @@ import {
20
21
  getOrCreateProjectConfig,
21
22
  getProcessOutput,
22
23
  getProjectConfigPath,
24
+ getToolDisplayName,
23
25
  getToolInfo,
24
26
  getToolLinkInfo,
25
27
  installMcpServer,
@@ -36,16 +38,18 @@ import {
36
38
  runInteractiveCommand,
37
39
  runSupabaseCommand,
38
40
  savePipeline,
41
+ startProcess,
39
42
  stopProcess,
43
+ translateCommand,
40
44
  writeProjectConfig
41
- } from "./chunk-7MIUDIAI.js";
45
+ } from "./chunk-YNOZDU75.js";
42
46
 
43
47
  // src/index.tsx
44
- import React27 from "react";
48
+ import React28 from "react";
45
49
  import { render } from "ink";
46
50
 
47
51
  // src/app.tsx
48
- import { Box as Box28, Text as Text32, useApp } from "ink";
52
+ import { Box as Box29, Text as Text33, useApp } from "ink";
49
53
 
50
54
  // src/hooks/useNavigation.ts
51
55
  import { useState, useCallback } from "react";
@@ -110,7 +114,7 @@ function useTerminalHeight() {
110
114
  }
111
115
 
112
116
  // src/components/GhostBanner.tsx
113
- import React from "react";
117
+ import React, { useState as useState3, useEffect as useEffect2 } from "react";
114
118
  import { Box, Text as Text2 } from "ink";
115
119
 
116
120
  // src/theme.ts
@@ -197,6 +201,12 @@ var toolColors = {
197
201
  git: "#F05032",
198
202
  pkg: "#CB3837"
199
203
  };
204
+ var pkgManagerColors = {
205
+ npm: "#CB3837",
206
+ pnpm: "#F69220",
207
+ yarn: "#2C8EBB",
208
+ bun: "#FBF0DF"
209
+ };
200
210
  var toolLabels = {
201
211
  supabase: "supabase",
202
212
  gh: "github",
@@ -204,8 +214,21 @@ var toolLabels = {
204
214
  git: "git",
205
215
  pkg: "pkg"
206
216
  };
217
+ function resolveToolColor(tool) {
218
+ if (tool === "pkg") {
219
+ const name = getToolDisplayName(tool);
220
+ return pkgManagerColors[name] ?? toolColors.pkg;
221
+ }
222
+ return toolColors[tool];
223
+ }
224
+ function resolveToolLabel(tool) {
225
+ if (tool === "pkg") {
226
+ return getToolDisplayName(tool);
227
+ }
228
+ return toolLabels[tool];
229
+ }
207
230
  function ToolBadge({ tool }) {
208
- return /* @__PURE__ */ jsx(Text, { color: toolColors[tool], dimColor: true, children: toolLabels[tool] });
231
+ return /* @__PURE__ */ jsx(Text, { color: resolveToolColor(tool), dimColor: true, children: resolveToolLabel(tool) });
209
232
  }
210
233
 
211
234
  // src/components/GhostBanner.tsx
@@ -219,6 +242,23 @@ var McpBadge = React.memo(function McpBadge2() {
219
242
  registered ? "ok" : "x"
220
243
  ] }) });
221
244
  });
245
+ function ProcessBadge() {
246
+ const [count, setCount] = useState3(() => {
247
+ return listProcesses().filter((p) => p.status === "running").length;
248
+ });
249
+ useEffect2(() => {
250
+ const id = setInterval(() => {
251
+ const c = listProcesses().filter((p) => p.status === "running").length;
252
+ setCount(c);
253
+ }, 2e3);
254
+ return () => clearInterval(id);
255
+ }, []);
256
+ const color = count > 0 ? "#3ECF8E" : inkColors.accent;
257
+ return /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: color, borderDimColor: count === 0, children: /* @__PURE__ */ jsxs(Text2, { color, dimColor: count === 0, children: [
258
+ "runs:",
259
+ count
260
+ ] }) });
261
+ }
222
262
  var ToolStatusBadges = React.memo(function ToolStatusBadges2() {
223
263
  const tools = ["supabase", "gh", "vercel"].map((id) => getToolLinkInfo(id));
224
264
  return /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
@@ -237,13 +277,16 @@ function GhostBanner({ width = 80, compact = false }) {
237
277
  if (compact) {
238
278
  if (width < 60) {
239
279
  return /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, flexDirection: "column", alignItems: "flex-start", children: [
240
- /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
241
- /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
242
- /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
243
- "v",
244
- VERSION
280
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
281
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
282
+ /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
283
+ /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
284
+ "v",
285
+ VERSION
286
+ ] }),
287
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
245
288
  ] }),
246
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
289
+ /* @__PURE__ */ jsx2(ProcessBadge, {})
247
290
  ] }),
248
291
  /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) })
249
292
  ] });
@@ -251,13 +294,16 @@ function GhostBanner({ width = 80, compact = false }) {
251
294
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", borderStyle: "round", borderColor: inkColors.accent, gap: 1, alignItems: "flex-start", children: [
252
295
  /* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: ghost.art.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, children: line }, i)) }),
253
296
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "flex-start", children: [
254
- /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
255
- /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
256
- /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
257
- "v",
258
- VERSION
297
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
298
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
299
+ /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
300
+ /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
301
+ "v",
302
+ VERSION
303
+ ] }),
304
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
259
305
  ] }),
260
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
306
+ /* @__PURE__ */ jsx2(ProcessBadge, {})
261
307
  ] }),
262
308
  /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) })
263
309
  ] })
@@ -265,13 +311,16 @@ function GhostBanner({ width = 80, compact = false }) {
265
311
  }
266
312
  if (width < 50) {
267
313
  return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, borderStyle: "round", borderColor: inkColors.accent, flexDirection: "column", alignItems: "flex-start", children: [
268
- /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
269
- /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
270
- /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
271
- "v",
272
- VERSION
314
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
315
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
316
+ /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
317
+ /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
318
+ "v",
319
+ VERSION
320
+ ] }),
321
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
273
322
  ] }),
274
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
323
+ /* @__PURE__ */ jsx2(ProcessBadge, {})
275
324
  ] }),
276
325
  /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) })
277
326
  ] });
@@ -286,13 +335,16 @@ function GhostBanner({ width = 80, compact = false }) {
286
335
  borderColor: inkColors.accent,
287
336
  marginBottom: 1,
288
337
  children: [
289
- /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
290
- /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
291
- /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
292
- "v",
293
- VERSION
338
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
339
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
340
+ /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
341
+ /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
342
+ "v",
343
+ VERSION
344
+ ] }),
345
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
294
346
  ] }),
295
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
347
+ /* @__PURE__ */ jsx2(ProcessBadge, {})
296
348
  ] }),
297
349
  /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) }),
298
350
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Project & infrastructure orchestrator" })
@@ -303,13 +355,16 @@ function GhostBanner({ width = 80, compact = false }) {
303
355
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "row", alignItems: "flex-start", borderStyle: "round", borderColor: inkColors.accent, gap: 1, marginBottom: 1, children: [
304
356
  /* @__PURE__ */ jsx2(Box, { flexDirection: "column", children: ghost.art.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, children: line }, i)) }),
305
357
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "flex-start", children: [
306
- /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
307
- /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
308
- /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
309
- "v",
310
- VERSION
358
+ /* @__PURE__ */ jsxs(Box, { gap: 1, children: [
359
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, gap: 2, children: [
360
+ /* @__PURE__ */ jsx2(Text2, { color: inkColors.accent, bold: true, children: "POLTER" }),
361
+ /* @__PURE__ */ jsxs(Text2, { dimColor: true, children: [
362
+ "v",
363
+ VERSION
364
+ ] }),
365
+ /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
311
366
  ] }),
312
- /* @__PURE__ */ jsx2(Text2, { color: "yellow", children: "alpha" })
367
+ /* @__PURE__ */ jsx2(ProcessBadge, {})
313
368
  ] }),
314
369
  /* @__PURE__ */ jsx2(Box, { borderStyle: "round", borderColor: inkColors.accent, paddingX: 1, children: /* @__PURE__ */ jsx2(ToolStatusBadges, {}) }),
315
370
  /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " Project & infrastructure orchestrator" })
@@ -318,7 +373,7 @@ function GhostBanner({ width = 80, compact = false }) {
318
373
  }
319
374
 
320
375
  // src/screens/Home.tsx
321
- import { useEffect as useEffect3, useMemo as useMemo2, useState as useState4 } from "react";
376
+ import { useEffect as useEffect4, useMemo as useMemo2, useState as useState5 } from "react";
322
377
  import { Box as Box5, Text as Text6, useInput as useInput2 } from "ink";
323
378
 
324
379
  // src/components/TabBar.tsx
@@ -347,7 +402,7 @@ function TabBar({ tabs, activeIndex, width = 80 }) {
347
402
  }
348
403
 
349
404
  // src/components/SelectList.tsx
350
- import { useEffect as useEffect2, useMemo, useState as useState3 } from "react";
405
+ import { useEffect as useEffect3, useMemo, useState as useState4 } from "react";
351
406
  import { Box as Box3, Text as Text4, useInput } from "ink";
352
407
 
353
408
  // src/components/selectListSections.ts
@@ -454,8 +509,8 @@ function SelectList({
454
509
  }, []),
455
510
  [items]
456
511
  );
457
- const [selectedSelectableIndex, setSelectedSelectableIndex] = useState3(0);
458
- useEffect2(() => {
512
+ const [selectedSelectableIndex, setSelectedSelectableIndex] = useState4(0);
513
+ useEffect3(() => {
459
514
  if (selectableIndexes.length === 0) {
460
515
  setSelectedSelectableIndex(0);
461
516
  return;
@@ -707,13 +762,13 @@ function buildPinnedOnlyItems(pinnedCommands, pinnedRuns) {
707
762
  if (pinnedCommands.length > 0) {
708
763
  for (const command of pinnedCommands) {
709
764
  const cmdDef = findCommandByValue(command);
710
- const toolHint = cmdDef ? cmdDef.tool : "supabase";
765
+ const toolDisplay = cmdDef ? getToolDisplayName(cmdDef.tool) : "supabase";
711
766
  const labelHint = cmdDef?.hint;
712
767
  items.push({
713
768
  id: `command:${command}`,
714
769
  value: command,
715
- label: cmdDef ? `${cmdDef.tool} ${command}` : command,
716
- hint: [toolHint, labelHint].filter(Boolean).join(" \xB7 "),
770
+ label: cmdDef ? `${toolDisplay} ${command}` : command,
771
+ hint: [toolDisplay, labelHint].filter(Boolean).join(" \xB7 "),
717
772
  icon: "\u{1F4CC}",
718
773
  kind: "command",
719
774
  rightActionable: true,
@@ -725,12 +780,12 @@ function buildPinnedOnlyItems(pinnedCommands, pinnedRuns) {
725
780
  for (const runCommand2 of pinnedRuns) {
726
781
  const baseCommand = runCommand2.split(" ").filter(Boolean)[0] ?? "";
727
782
  const cmdDef = findCommandByValue(baseCommand);
728
- const toolHint = cmdDef ? cmdDef.tool : "supabase";
783
+ const toolDisplay = cmdDef ? getToolDisplayName(cmdDef.tool) : "supabase";
729
784
  items.push({
730
785
  id: `run:${runCommand2}`,
731
786
  value: runCommand2,
732
- label: cmdDef ? `${cmdDef.tool} ${runCommand2}` : runCommand2,
733
- hint: toolHint,
787
+ label: cmdDef ? `${toolDisplay} ${runCommand2}` : runCommand2,
788
+ hint: toolDisplay,
734
789
  icon: "\u25B6",
735
790
  kind: "run",
736
791
  rightActionable: true,
@@ -767,8 +822,8 @@ function buildHomeItems({
767
822
  selectable: false
768
823
  });
769
824
  }
770
- const toolOrder = { supabase: 0, vercel: 1, gh: 2, git: 3 };
771
- const toolIcons = { supabase: "\u{1F7E2}", vercel: "\u26AA", gh: "\u{1F535}", git: "\u{1F7E0}" };
825
+ const toolOrder = { supabase: 0, vercel: 1, gh: 2, git: 3, pkg: 4 };
826
+ const toolIcons = { supabase: "\u{1F7E2}", vercel: "\u26AA", gh: "\u{1F535}", git: "\u{1F7E0}", pkg: "\u{1F4E6}" };
772
827
  const grouped = /* @__PURE__ */ new Map();
773
828
  for (const cmd of activeFeature.commands) {
774
829
  const existing = grouped.get(cmd.tool) ?? [];
@@ -784,7 +839,7 @@ function buildHomeItems({
784
839
  items.push({
785
840
  id: `tool-header-${tool}`,
786
841
  value: `__tool_header_${tool}__`,
787
- label: `${icon} ${tool}`,
842
+ label: `${icon} ${getToolDisplayName(tool)}`,
788
843
  kind: "header",
789
844
  selectable: false
790
845
  });
@@ -883,16 +938,16 @@ function Home({
883
938
  height = 24
884
939
  }) {
885
940
  const allFeatures = useMemo2(() => getFeatures(), []);
886
- const [activeTabIndex, setActiveTabIndex] = useState4(0);
887
- const [pinnedCommands, setPinnedCommands2] = useState4(
941
+ const [activeTabIndex, setActiveTabIndex] = useState5(0);
942
+ const [pinnedCommands, setPinnedCommands2] = useState5(
888
943
  () => getPinnedCommands()
889
944
  );
890
- const [pinnedRuns, setPinnedRuns2] = useState4(
945
+ const [pinnedRuns, setPinnedRuns2] = useState5(
891
946
  () => getPinnedRuns()
892
947
  );
893
- const [pinFeedback, setPinFeedback] = useState4();
948
+ const [pinFeedback, setPinFeedback] = useState5();
894
949
  const activeFeature = allFeatures[activeTabIndex];
895
- useEffect3(() => {
950
+ useEffect4(() => {
896
951
  if (!pinFeedback) return;
897
952
  const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
898
953
  return () => clearTimeout(timeout);
@@ -1031,11 +1086,11 @@ function Home({
1031
1086
  }
1032
1087
 
1033
1088
  // src/screens/CommandArgs.tsx
1034
- import { useEffect as useEffect4, useMemo as useMemo3, useState as useState6 } from "react";
1089
+ import { useEffect as useEffect5, useMemo as useMemo3, useState as useState7 } from "react";
1035
1090
  import { Box as Box7, Text as Text8, useInput as useInput4 } from "ink";
1036
1091
 
1037
1092
  // src/components/TextPrompt.tsx
1038
- import { useState as useState5 } from "react";
1093
+ import { useState as useState6 } from "react";
1039
1094
  import { Box as Box6, Text as Text7, useInput as useInput3 } from "ink";
1040
1095
  import TextInputComponent from "ink-text-input";
1041
1096
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -1050,8 +1105,8 @@ function TextPrompt({
1050
1105
  boxed = false,
1051
1106
  focused = true
1052
1107
  }) {
1053
- const [value, setValue] = useState5("");
1054
- const [error, setError] = useState5();
1108
+ const [value, setValue] = useState6("");
1109
+ const [error, setError] = useState6();
1055
1110
  useInput3((_input, key) => {
1056
1111
  if (key.escape && onCancel) {
1057
1112
  onCancel();
@@ -1190,15 +1245,15 @@ function CommandArgs({
1190
1245
  () => cmdDef?.suggestedArgs ?? [],
1191
1246
  [cmdDef]
1192
1247
  );
1193
- const [pinnedRuns, setPinnedRuns2] = useState6(() => getPinnedRuns());
1194
- const [pinFeedback, setPinFeedback] = useState6();
1195
- const [phase, setPhase] = useState6(
1248
+ const [pinnedRuns, setPinnedRuns2] = useState7(() => getPinnedRuns());
1249
+ const [pinFeedback, setPinFeedback] = useState7();
1250
+ const [phase, setPhase] = useState7(
1196
1251
  suggestions.length > 0 ? "select" : "custom"
1197
1252
  );
1198
- useEffect4(() => {
1253
+ useEffect5(() => {
1199
1254
  setPhase(suggestions.length > 0 ? "select" : "custom");
1200
1255
  }, [command, suggestions.length]);
1201
- useEffect4(() => {
1256
+ useEffect5(() => {
1202
1257
  if (!pinFeedback) return;
1203
1258
  const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
1204
1259
  return () => clearTimeout(timeout);
@@ -1340,7 +1395,7 @@ function CommandArgs({
1340
1395
  }
1341
1396
 
1342
1397
  // src/screens/CustomCommand.tsx
1343
- import { useState as useState7 } from "react";
1398
+ import { useState as useState8 } from "react";
1344
1399
  import { Box as Box8, Text as Text9 } from "ink";
1345
1400
  import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1346
1401
  function CustomCommand({
@@ -1351,8 +1406,8 @@ function CustomCommand({
1351
1406
  panelMode = false,
1352
1407
  isInputActive = true
1353
1408
  }) {
1354
- const [phase, setPhase] = useState7("tool-select");
1355
- const [selectedTool, setSelectedTool] = useState7("supabase");
1409
+ const [phase, setPhase] = useState8("tool-select");
1410
+ const [selectedTool, setSelectedTool] = useState8("supabase");
1356
1411
  if (phase === "tool-select") {
1357
1412
  const toolItems = [
1358
1413
  { value: "__section__", label: "\u{1F6E0} Select Tool", kind: "header", selectable: false },
@@ -1360,6 +1415,8 @@ function CustomCommand({
1360
1415
  { value: "gh", label: "GitHub CLI", hint: "gh ...", kind: "action" },
1361
1416
  { value: "vercel", label: "Vercel CLI", hint: "vercel ...", kind: "action" },
1362
1417
  { value: "git", label: "Git", hint: "git ...", kind: "action" },
1418
+ { value: "__free_header__", label: "", kind: "header", selectable: false },
1419
+ { value: "free", label: "\u2328 Free command", hint: "any command", kind: "action" },
1363
1420
  ...!panelMode ? [{ value: "__back__", label: "\u2190 Back" }] : []
1364
1421
  ];
1365
1422
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
@@ -1374,6 +1431,10 @@ function CustomCommand({
1374
1431
  onBack();
1375
1432
  return;
1376
1433
  }
1434
+ if (value === "free") {
1435
+ setPhase("free-input");
1436
+ return;
1437
+ }
1377
1438
  setSelectedTool(value);
1378
1439
  setPhase("input");
1379
1440
  },
@@ -1389,6 +1450,34 @@ function CustomCommand({
1389
1450
  !panelMode && /* @__PURE__ */ jsx9(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
1390
1451
  ] });
1391
1452
  }
1453
+ if (phase === "free-input") {
1454
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1455
+ !panelMode && /* @__PURE__ */ jsx9(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u2328 Free Command" }) }),
1456
+ /* @__PURE__ */ jsx9(
1457
+ TextPrompt,
1458
+ {
1459
+ label: "Enter full command:",
1460
+ placeholder: "e.g. docker ps, curl -s http://..., make build",
1461
+ validate: (val) => {
1462
+ if (!val || !val.trim()) return "Please enter a command";
1463
+ return void 0;
1464
+ },
1465
+ onSubmit: (value) => {
1466
+ const parts = value.split(" ").filter(Boolean);
1467
+ const cmd = parts[0];
1468
+ const args = parts.slice(1);
1469
+ onNavigate("command-execution", { args, rawCommand: cmd });
1470
+ },
1471
+ onCancel: () => setPhase("tool-select"),
1472
+ arrowNavigation: panelMode,
1473
+ isInputActive,
1474
+ boxed: panelMode,
1475
+ focused: isInputActive
1476
+ }
1477
+ ),
1478
+ !panelMode && /* @__PURE__ */ jsx9(StatusBar, { hint: "Type full command \xB7 Enter to execute \xB7 Esc to go back", width })
1479
+ ] });
1480
+ }
1392
1481
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1393
1482
  !panelMode && /* @__PURE__ */ jsxs8(Box8, { marginBottom: 1, gap: 1, children: [
1394
1483
  /* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u270F\uFE0F Custom Command" }),
@@ -1409,7 +1498,7 @@ function CustomCommand({
1409
1498
  },
1410
1499
  onSubmit: (value) => {
1411
1500
  const args = value.split(" ").filter(Boolean);
1412
- onNavigate("flag-selection", { args, tool: selectedTool, interactive: true });
1501
+ onNavigate("command-execution", { args, tool: selectedTool });
1413
1502
  },
1414
1503
  onCancel: () => setPhase("tool-select"),
1415
1504
  arrowNavigation: panelMode,
@@ -1426,7 +1515,7 @@ function CustomCommand({
1426
1515
  import { Box as Box10, Text as Text11 } from "ink";
1427
1516
 
1428
1517
  // src/components/FlagToggle.tsx
1429
- import { useState as useState8 } from "react";
1518
+ import { useState as useState9 } from "react";
1430
1519
  import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
1431
1520
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1432
1521
  function FlagToggle({
@@ -1436,8 +1525,8 @@ function FlagToggle({
1436
1525
  isInputActive = true,
1437
1526
  arrowNavigation = false
1438
1527
  }) {
1439
- const [cursor, setCursor] = useState8(0);
1440
- const [selected, setSelected] = useState8(/* @__PURE__ */ new Set());
1528
+ const [cursor, setCursor] = useState9(0);
1529
+ const [selected, setSelected] = useState9(/* @__PURE__ */ new Set());
1441
1530
  useInput5((input2, key) => {
1442
1531
  if (key.upArrow || input2 === "k") {
1443
1532
  setCursor((prev) => prev > 0 ? prev - 1 : flags.length - 1);
@@ -1569,7 +1658,7 @@ function FlagSelection({
1569
1658
  }
1570
1659
 
1571
1660
  // src/screens/CommandExecution.tsx
1572
- import { useState as useState11, useEffect as useEffect7 } from "react";
1661
+ import { useState as useState12, useEffect as useEffect9 } from "react";
1573
1662
  import { Box as Box13, Text as Text17, useInput as useInput8 } from "ink";
1574
1663
 
1575
1664
  // src/components/Spinner.tsx
@@ -1650,24 +1739,40 @@ function Divider({
1650
1739
  import { Text as Text16 } from "ink";
1651
1740
 
1652
1741
  // src/components/ScrollableBox.tsx
1653
- import { useState as useState9 } from "react";
1742
+ import { useState as useState10, useEffect as useEffect6, useRef } from "react";
1654
1743
  import { Box as Box12, Text as Text15, useInput as useInput7 } from "ink";
1655
1744
  import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1656
1745
  function ScrollableBox({
1657
1746
  height,
1658
1747
  isActive = true,
1748
+ autoScrollToBottom = false,
1659
1749
  children
1660
1750
  }) {
1661
1751
  const totalItems = children.length;
1662
- const [scrollOffset, setScrollOffset] = useState9(0);
1752
+ const [scrollOffset, setScrollOffset] = useState10(0);
1663
1753
  const visibleCount = Math.max(1, height - 2);
1754
+ const maxOffset = Math.max(0, totalItems - visibleCount);
1755
+ const pinnedToBottom = useRef(autoScrollToBottom);
1756
+ useEffect6(() => {
1757
+ if (autoScrollToBottom && pinnedToBottom.current) {
1758
+ setScrollOffset(maxOffset);
1759
+ }
1760
+ }, [autoScrollToBottom, maxOffset]);
1664
1761
  useInput7(
1665
1762
  (input2, key) => {
1666
1763
  if (key.upArrow || input2 === "k") {
1667
- setScrollOffset((prev) => Math.max(0, prev - 1));
1764
+ setScrollOffset((prev) => {
1765
+ const next = Math.max(0, prev - 1);
1766
+ pinnedToBottom.current = next >= maxOffset;
1767
+ return next;
1768
+ });
1668
1769
  }
1669
1770
  if (key.downArrow || input2 === "j") {
1670
- setScrollOffset((prev) => Math.min(Math.max(0, totalItems - visibleCount), prev + 1));
1771
+ setScrollOffset((prev) => {
1772
+ const next = Math.min(maxOffset, prev + 1);
1773
+ pinnedToBottom.current = next >= maxOffset;
1774
+ return next;
1775
+ });
1671
1776
  }
1672
1777
  },
1673
1778
  { isActive }
@@ -1715,12 +1820,14 @@ function CommandOutput({
1715
1820
  }
1716
1821
 
1717
1822
  // src/hooks/useCommand.ts
1718
- import { useState as useState10, useCallback as useCallback2, useRef, useEffect as useEffect5 } from "react";
1823
+ import { useState as useState11, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect7 } from "react";
1719
1824
  function useCommand(execution = "supabase", cwd = process.cwd(), options) {
1720
- const [status, setStatus] = useState10("idle");
1721
- const [result, setResult] = useState10(null);
1722
- const abortRef = useRef(null);
1723
- useEffect5(() => {
1825
+ const [status, setStatus] = useState11("idle");
1826
+ const [result, setResult] = useState11(null);
1827
+ const [partialStdout, setPartialStdout] = useState11("");
1828
+ const [partialStderr, setPartialStderr] = useState11("");
1829
+ const abortRef = useRef2(null);
1830
+ useEffect7(() => {
1724
1831
  return () => {
1725
1832
  abortRef.current?.();
1726
1833
  abortRef.current = null;
@@ -1729,9 +1836,11 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
1729
1836
  const run = useCallback2(async (args) => {
1730
1837
  setStatus("running");
1731
1838
  setResult(null);
1839
+ setPartialStdout("");
1840
+ setPartialStderr("");
1732
1841
  let resolvedExecution;
1733
1842
  if (typeof execution === "string") {
1734
- const toolIds2 = ["supabase", "gh", "vercel"];
1843
+ const toolIds2 = ["supabase", "gh", "vercel", "git", "pkg"];
1735
1844
  if (toolIds2.includes(execution)) {
1736
1845
  const resolved = resolveToolCommand(execution, cwd);
1737
1846
  resolvedExecution = { command: resolved.command, env: resolved.env };
@@ -1741,7 +1850,11 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
1741
1850
  } else {
1742
1851
  resolvedExecution = execution;
1743
1852
  }
1744
- const runOpts = options?.quiet ? { quiet: true } : void 0;
1853
+ const onData = (stdout, stderr) => {
1854
+ setPartialStdout(stdout);
1855
+ setPartialStderr(stderr);
1856
+ };
1857
+ const runOpts = { quiet: options?.quiet, onData };
1745
1858
  const handle = runCommand(resolvedExecution, args, cwd, runOpts);
1746
1859
  abortRef.current = handle.abort;
1747
1860
  const res = await handle.promise;
@@ -1761,21 +1874,23 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
1761
1874
  const reset = useCallback2(() => {
1762
1875
  setStatus("idle");
1763
1876
  setResult(null);
1877
+ setPartialStdout("");
1878
+ setPartialStderr("");
1764
1879
  }, []);
1765
- return { status, result, run, reset, abort };
1880
+ return { status, result, run, reset, abort, partialStdout, partialStderr };
1766
1881
  }
1767
1882
 
1768
1883
  // src/hooks/useInteractiveRun.ts
1769
1884
  import { useCallback as useCallback3 } from "react";
1770
1885
 
1771
1886
  // src/hooks/useFullscreen.ts
1772
- import { useEffect as useEffect6 } from "react";
1887
+ import { useEffect as useEffect8 } from "react";
1773
1888
  var ENTER_ALT_SCREEN = "\x1B[?1049h";
1774
1889
  var LEAVE_ALT_SCREEN = "\x1B[?1049l";
1775
1890
  var HIDE_CURSOR = "\x1B[?25l";
1776
1891
  var SHOW_CURSOR = "\x1B[?25h";
1777
1892
  function useFullscreen() {
1778
- useEffect6(() => {
1893
+ useEffect8(() => {
1779
1894
  process.stdout.write(ENTER_ALT_SCREEN + HIDE_CURSOR);
1780
1895
  return () => {
1781
1896
  process.stdout.write(SHOW_CURSOR + LEAVE_ALT_SCREEN);
@@ -1880,6 +1995,7 @@ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1880
1995
  function CommandExecution({
1881
1996
  args: initialArgs,
1882
1997
  tool = "supabase",
1998
+ rawCommand,
1883
1999
  interactive = false,
1884
2000
  onBack,
1885
2001
  onHome,
@@ -1890,16 +2006,17 @@ function CommandExecution({
1890
2006
  panelMode = false,
1891
2007
  isInputActive = true
1892
2008
  }) {
1893
- const [phase, setPhase] = useState11("confirm");
1894
- const [currentArgs, setCurrentArgs] = useState11(initialArgs);
1895
- const [pinMessage, setPinMessage] = useState11();
1896
- const { status, result, run, reset, abort } = useCommand(tool, process.cwd(), {
2009
+ const [phase, setPhase] = useState12("confirm");
2010
+ const [currentArgs, setCurrentArgs] = useState12(initialArgs);
2011
+ const [pinMessage, setPinMessage] = useState12();
2012
+ const execution = rawCommand ?? tool;
2013
+ const { status, result, run, reset, abort, partialStdout, partialStderr } = useCommand(execution, process.cwd(), {
1897
2014
  quiet: panelMode
1898
2015
  });
1899
2016
  const { runInteractive } = useInteractiveRun();
1900
- const [outputFocused, setOutputFocused] = useState11(false);
1901
- const [copyMessage, setCopyMessage] = useState11();
1902
- const cmdDisplay = `${tool} ${currentArgs.join(" ")}`;
2017
+ const [outputFocused, setOutputFocused] = useState12(false);
2018
+ const [copyMessage, setCopyMessage] = useState12();
2019
+ const cmdDisplay = rawCommand ? `${rawCommand} ${currentArgs.join(" ")}`.trim() : `${getToolDisplayName(tool)} ${currentArgs.join(" ")}`;
1903
2020
  const runCommand2 = currentArgs.join(" ");
1904
2021
  useInput8(
1905
2022
  (_input, key) => {
@@ -1921,7 +2038,13 @@ function CommandExecution({
1921
2038
  },
1922
2039
  { isActive: isInputActive && phase === "error-menu" }
1923
2040
  );
1924
- useEffect7(() => {
2041
+ useEffect9(() => {
2042
+ if (phase === "background-started") {
2043
+ const t = setTimeout(() => onBack(), 1500);
2044
+ return () => clearTimeout(t);
2045
+ }
2046
+ }, [phase, onBack]);
2047
+ useEffect9(() => {
1925
2048
  if (phase === "running" && status === "idle") {
1926
2049
  if (panelMode && interactive) {
1927
2050
  const interactiveResult = runInteractive(tool, currentArgs);
@@ -1935,7 +2058,7 @@ function CommandExecution({
1935
2058
  }
1936
2059
  }
1937
2060
  }, [phase, status, run, currentArgs, panelMode, interactive, tool, runInteractive]);
1938
- useEffect7(() => {
2061
+ useEffect9(() => {
1939
2062
  if (phase === "running" && status === "success") {
1940
2063
  if (isPinnedRun(runCommand2)) {
1941
2064
  setPhase("success");
@@ -1956,6 +2079,11 @@ function CommandExecution({
1956
2079
  label: pinned ? "\u{1F4CC} Unpin command" : "\u{1F4CC} Pin command",
1957
2080
  hint: "Save to quick access"
1958
2081
  },
2082
+ {
2083
+ value: "background",
2084
+ label: "\u23E9 Run in background",
2085
+ hint: "Start as background process"
2086
+ },
1959
2087
  { value: "cancel", label: "\u2190 Cancel" }
1960
2088
  ];
1961
2089
  const confirmContent = /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
@@ -1984,6 +2112,19 @@ function CommandExecution({
1984
2112
  isPinnedRun(runCommand2) ? "\u2713 Command pinned" : "\u2713 Command unpinned"
1985
2113
  );
1986
2114
  break;
2115
+ case "background": {
2116
+ const cwd = process.cwd();
2117
+ if (rawCommand) {
2118
+ const id = generateProcessId(rawCommand, currentArgs);
2119
+ startProcess(id, rawCommand, currentArgs, cwd);
2120
+ } else {
2121
+ const resolved = resolveToolCommand(tool, cwd);
2122
+ const id = generateProcessId(resolved.command, currentArgs);
2123
+ startProcess(id, resolved.command, currentArgs, cwd, resolved.env);
2124
+ }
2125
+ setPhase("background-started");
2126
+ break;
2127
+ }
1987
2128
  case "cancel":
1988
2129
  onBack();
1989
2130
  break;
@@ -2010,7 +2151,21 @@ function CommandExecution({
2010
2151
  }
2011
2152
  ) : confirmContent });
2012
2153
  }
2154
+ if (phase === "background-started") {
2155
+ return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2156
+ /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
2157
+ /* @__PURE__ */ jsx17(Text17, { color: "#3ECF8E", bold: true, children: "\u2713" }),
2158
+ /* @__PURE__ */ jsx17(Text17, { color: "#3ECF8E", bold: true, children: "Started in background" })
2159
+ ] }),
2160
+ /* @__PURE__ */ jsxs15(Box13, { children: [
2161
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Command: " }),
2162
+ /* @__PURE__ */ jsx17(Text17, { children: cmdDisplay })
2163
+ ] })
2164
+ ] });
2165
+ }
2013
2166
  if (phase === "running") {
2167
+ const hasPartialOutput = partialStdout.length > 0 || partialStderr.length > 0;
2168
+ const streamOutputHeight = Math.max(3, height - 10);
2014
2169
  return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2015
2170
  /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
2016
2171
  /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
@@ -2021,6 +2176,15 @@ function CommandExecution({
2021
2176
  ] }),
2022
2177
  /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
2023
2178
  /* @__PURE__ */ jsx17(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx17(Spinner, { label: `Executing ${cmdDisplay}...` }) }),
2179
+ hasPartialOutput && /* @__PURE__ */ jsx17(
2180
+ CommandOutput,
2181
+ {
2182
+ stdout: partialStdout,
2183
+ stderr: partialStderr,
2184
+ height: streamOutputHeight,
2185
+ isActive: false
2186
+ }
2187
+ ),
2024
2188
  /* @__PURE__ */ jsxs15(Box13, { marginTop: 1, children: [
2025
2189
  /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Press " }),
2026
2190
  /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, children: "Esc" }),
@@ -2282,7 +2446,7 @@ function CommandExecution({
2282
2446
  }
2283
2447
 
2284
2448
  // src/screens/SelfUpdate.tsx
2285
- import { useEffect as useEffect8, useState as useState12 } from "react";
2449
+ import { useEffect as useEffect10, useState as useState13 } from "react";
2286
2450
  import { Box as Box14, Text as Text18 } from "ink";
2287
2451
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2288
2452
  var packageName = "@polterware/polter";
@@ -2300,10 +2464,10 @@ function SelfUpdate({
2300
2464
  isInputActive = true
2301
2465
  }) {
2302
2466
  const repositoryRoot = findNearestPackageRoot();
2303
- const [target, setTarget] = useState12(
2467
+ const [target, setTarget] = useState13(
2304
2468
  repositoryRoot ? "repository" : "global"
2305
2469
  );
2306
- const [phase, setPhase] = useState12(
2470
+ const [phase, setPhase] = useState13(
2307
2471
  repositoryRoot ? "target" : "confirm"
2308
2472
  );
2309
2473
  const updateArgs = getUpdateArgs(target);
@@ -2312,12 +2476,12 @@ function SelfUpdate({
2312
2476
  const { status, result, run, reset } = useCommand("npm", updateCwd, {
2313
2477
  quiet: panelMode
2314
2478
  });
2315
- useEffect8(() => {
2479
+ useEffect10(() => {
2316
2480
  if (phase === "running" && status === "idle") {
2317
2481
  run(updateArgs);
2318
2482
  }
2319
2483
  }, [phase, run, status, updateArgs]);
2320
- useEffect8(() => {
2484
+ useEffect10(() => {
2321
2485
  if (phase === "running" && status === "success") {
2322
2486
  setPhase("success");
2323
2487
  }
@@ -2558,15 +2722,15 @@ function SelfUpdate({
2558
2722
  }
2559
2723
 
2560
2724
  // src/screens/ToolStatus.tsx
2561
- import { useEffect as useEffect9, useState as useState13 } from "react";
2725
+ import { useEffect as useEffect11, useState as useState14 } from "react";
2562
2726
  import { Box as Box15, Text as Text19 } from "ink";
2563
2727
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2564
2728
  var toolIds = ["supabase", "gh", "vercel", "git", "pkg"];
2565
2729
  var linkableTools = /* @__PURE__ */ new Set(["supabase", "gh", "vercel", "pkg"]);
2566
2730
  function ToolStatus({ onBack, onNavigate, width = 80, height = 24, panelMode = false, isInputActive = true }) {
2567
- const [tools, setTools] = useState13(null);
2568
- const [mcpInfo, setMcpInfo] = useState13(null);
2569
- useEffect9(() => {
2731
+ const [tools, setTools] = useState14(null);
2732
+ const [mcpInfo, setMcpInfo] = useState14(null);
2733
+ useEffect11(() => {
2570
2734
  const t = setTimeout(() => {
2571
2735
  setTools(toolIds.map((id) => getToolLinkInfo(id)));
2572
2736
  setMcpInfo(getMcpStatusInfo());
@@ -2652,11 +2816,11 @@ function ToolStatus({ onBack, onNavigate, width = 80, height = 24, panelMode = f
2652
2816
  }
2653
2817
 
2654
2818
  // src/screens/ProjectConfig.tsx
2655
- import { useMemo as useMemo4, useState as useState15 } from "react";
2819
+ import { useMemo as useMemo4, useState as useState16 } from "react";
2656
2820
  import { Box as Box16, Text as Text20 } from "ink";
2657
2821
 
2658
2822
  // src/hooks/useEditor.ts
2659
- import { useState as useState14, useCallback as useCallback4 } from "react";
2823
+ import { useState as useState15, useCallback as useCallback4 } from "react";
2660
2824
  import { useStdin } from "ink";
2661
2825
 
2662
2826
  // src/lib/editor.ts
@@ -2707,7 +2871,7 @@ function openInEditor(filePath) {
2707
2871
  // src/hooks/useEditor.ts
2708
2872
  function useEditor() {
2709
2873
  const { setRawMode } = useStdin();
2710
- const [isEditing, setIsEditing] = useState14(false);
2874
+ const [isEditing, setIsEditing] = useState15(false);
2711
2875
  const openEditor = useCallback4(async (filePath) => {
2712
2876
  const editor = resolveEditor();
2713
2877
  const terminal = isTerminalEditor(editor.command);
@@ -2737,11 +2901,11 @@ function ProjectConfig({
2737
2901
  isInputActive = true
2738
2902
  }) {
2739
2903
  const configPath = useMemo4(() => getProjectConfigPath(), []);
2740
- const [config2, setConfig] = useState15(() => getOrCreateProjectConfig());
2741
- const [phase, setPhase] = useState15("overview");
2742
- const [feedback, setFeedback] = useState15();
2743
- const [envKey, setEnvKey] = useState15("");
2744
- const [selectedEnvKey, setSelectedEnvKey] = useState15("");
2904
+ const [config2, setConfig] = useState16(() => getOrCreateProjectConfig());
2905
+ const [phase, setPhase] = useState16("overview");
2906
+ const [feedback, setFeedback] = useState16();
2907
+ const [envKey, setEnvKey] = useState16("");
2908
+ const [selectedEnvKey, setSelectedEnvKey] = useState16("");
2745
2909
  const { openEditor, isEditing } = useEditor();
2746
2910
  const detectedPkg = useMemo4(() => detectPkgManager(), []);
2747
2911
  if (!configPath) {
@@ -3223,7 +3387,7 @@ function PipelineList({
3223
3387
  }
3224
3388
 
3225
3389
  // src/screens/PipelineBuilder.tsx
3226
- import { useState as useState16 } from "react";
3390
+ import { useState as useState17 } from "react";
3227
3391
  import { Box as Box18, Text as Text22 } from "ink";
3228
3392
  import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
3229
3393
  var stepCounter = 0;
@@ -3238,9 +3402,9 @@ function PipelineBuilder({
3238
3402
  panelMode = false,
3239
3403
  isInputActive = true
3240
3404
  }) {
3241
- const [phase, setPhase] = useState16("name");
3242
- const [name, setName] = useState16("");
3243
- const [steps, setSteps] = useState16([]);
3405
+ const [phase, setPhase] = useState17("name");
3406
+ const [name, setName] = useState17("");
3407
+ const [steps, setSteps] = useState17([]);
3244
3408
  if (phase === "name") {
3245
3409
  return /* @__PURE__ */ jsxs20(Box18, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
3246
3410
  /* @__PURE__ */ jsx22(Box18, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text22, { bold: true, color: inkColors.accent, children: "\u{1F517} New Pipeline" }) }),
@@ -3426,7 +3590,7 @@ function PipelineBuilder({
3426
3590
  }
3427
3591
 
3428
3592
  // src/screens/PipelineExecution.tsx
3429
- import { useState as useState17, useEffect as useEffect10, useMemo as useMemo6 } from "react";
3593
+ import { useState as useState18, useEffect as useEffect12, useMemo as useMemo6 } from "react";
3430
3594
  import { Box as Box21, Text as Text25 } from "ink";
3431
3595
 
3432
3596
  // src/components/StepIndicator.tsx
@@ -3519,10 +3683,10 @@ function PipelineExecution({
3519
3683
  () => getAllPipelines().find((p) => p.id === pipelineId),
3520
3684
  [pipelineId]
3521
3685
  );
3522
- const [phase, setPhase] = useState17("running");
3523
- const [progress, setProgress] = useState17(null);
3524
- const [results, setResults] = useState17([]);
3525
- useEffect10(() => {
3686
+ const [phase, setPhase] = useState18("running");
3687
+ const [progress, setProgress] = useState18(null);
3688
+ const [results, setResults] = useState18([]);
3689
+ useEffect12(() => {
3526
3690
  if (!pipeline) return;
3527
3691
  executePipeline(pipeline, (p) => {
3528
3692
  setProgress({ ...p });
@@ -3636,7 +3800,7 @@ function PipelineExecution({
3636
3800
  }
3637
3801
 
3638
3802
  // src/screens/McpManage.tsx
3639
- import { useState as useState18, useCallback as useCallback5 } from "react";
3803
+ import { useState as useState19, useCallback as useCallback5 } from "react";
3640
3804
  import { Box as Box22, Text as Text26 } from "ink";
3641
3805
  import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
3642
3806
  function McpManage({
@@ -3646,10 +3810,10 @@ function McpManage({
3646
3810
  panelMode = false,
3647
3811
  isInputActive = true
3648
3812
  }) {
3649
- const [status, setStatus] = useState18(() => getMcpStatusInfo());
3650
- const [phase, setPhase] = useState18("overview");
3651
- const [action, setAction] = useState18(null);
3652
- const [result, setResult] = useState18(null);
3813
+ const [status, setStatus] = useState19(() => getMcpStatusInfo());
3814
+ const [phase, setPhase] = useState19("overview");
3815
+ const [action, setAction] = useState19(null);
3816
+ const [result, setResult] = useState19(null);
3653
3817
  const refreshStatus = useCallback5(() => {
3654
3818
  setStatus(getMcpStatusInfo());
3655
3819
  }, []);
@@ -3791,7 +3955,7 @@ function McpManage({
3791
3955
  }
3792
3956
 
3793
3957
  // src/screens/ProcessList.tsx
3794
- import { useState as useState19, useEffect as useEffect11, useCallback as useCallback6 } from "react";
3958
+ import { useState as useState20, useEffect as useEffect13, useCallback as useCallback6 } from "react";
3795
3959
  import { Box as Box23, Text as Text27, useInput as useInput9 } from "ink";
3796
3960
  import { homedir } from "os";
3797
3961
  import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
@@ -3831,22 +3995,22 @@ function ProcessList({
3831
3995
  panelMode = false,
3832
3996
  isInputActive = true
3833
3997
  }) {
3834
- const [processes, setProcesses] = useState19(() => listProcesses());
3835
- const [selectedIndex, setSelectedIndex] = useState19(0);
3836
- const [feedback, setFeedback] = useState19();
3837
- useEffect11(() => {
3998
+ const [processes, setProcesses] = useState20(() => listProcesses());
3999
+ const [selectedIndex, setSelectedIndex] = useState20(0);
4000
+ const [feedback, setFeedback] = useState20();
4001
+ useEffect13(() => {
3838
4002
  const interval = setInterval(() => {
3839
4003
  setProcesses(listProcesses());
3840
4004
  }, 2e3);
3841
4005
  return () => clearInterval(interval);
3842
4006
  }, []);
3843
- useEffect11(() => {
4007
+ useEffect13(() => {
3844
4008
  if (feedback) {
3845
4009
  const timer = setTimeout(() => setFeedback(void 0), 2e3);
3846
4010
  return () => clearTimeout(timer);
3847
4011
  }
3848
4012
  }, [feedback]);
3849
- useEffect11(() => {
4013
+ useEffect13(() => {
3850
4014
  if (selectedIndex >= processes.length && processes.length > 0) {
3851
4015
  setSelectedIndex(processes.length - 1);
3852
4016
  }
@@ -3996,7 +4160,7 @@ function ProcessList({
3996
4160
  }
3997
4161
 
3998
4162
  // src/screens/ProcessLogs.tsx
3999
- import { useState as useState20, useEffect as useEffect12, useCallback as useCallback7 } from "react";
4163
+ import { useState as useState21, useEffect as useEffect14, useCallback as useCallback7 } from "react";
4000
4164
  import { Box as Box24, Text as Text28, useInput as useInput10 } from "ink";
4001
4165
  import { spawn as spawn3 } from "child_process";
4002
4166
  import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
@@ -4015,16 +4179,16 @@ function ProcessLogs({
4015
4179
  panelMode = false,
4016
4180
  isInputActive = true
4017
4181
  }) {
4018
- const [stream, setStream] = useState20("both");
4019
- const [lines, setLines] = useState20([]);
4020
- const [proc, setProc] = useState20();
4021
- const [feedback, setFeedback] = useState20();
4182
+ const [stream, setStream] = useState21("both");
4183
+ const [lines, setLines] = useState21([]);
4184
+ const [proc, setProc] = useState21();
4185
+ const [feedback, setFeedback] = useState21();
4022
4186
  const logBoxHeight = Math.max(3, height - 6);
4023
- useEffect12(() => {
4187
+ useEffect14(() => {
4024
4188
  const refresh = () => {
4025
4189
  try {
4026
- const output2 = getProcessOutput(processId, logBoxHeight, stream);
4027
- const combined = stream === "stderr" ? output2.stderr : stream === "stdout" ? output2.stdout : [...output2.stdout, ...output2.stderr].slice(-logBoxHeight);
4190
+ const output2 = getProcessOutput(processId, 1e3, stream);
4191
+ const combined = stream === "stderr" ? output2.stderr : stream === "stdout" ? output2.stdout : [...output2.stdout, ...output2.stderr].slice(-1e3);
4028
4192
  setLines(combined);
4029
4193
  } catch {
4030
4194
  setLines([`Process "${processId}" not found`]);
@@ -4035,8 +4199,8 @@ function ProcessLogs({
4035
4199
  refresh();
4036
4200
  const interval = setInterval(refresh, 1e3);
4037
4201
  return () => clearInterval(interval);
4038
- }, [processId, logBoxHeight, stream]);
4039
- useEffect12(() => {
4202
+ }, [processId, stream]);
4203
+ useEffect14(() => {
4040
4204
  if (feedback) {
4041
4205
  const timer = setTimeout(() => setFeedback(void 0), 2e3);
4042
4206
  return () => clearTimeout(timer);
@@ -4104,10 +4268,16 @@ function ProcessLogs({
4104
4268
  borderStyle: "round",
4105
4269
  borderColor: inkColors.accent,
4106
4270
  paddingX: 1,
4107
- height: logBoxHeight + 2,
4108
4271
  width: cardWidth,
4109
- overflowY: "hidden",
4110
- children: lines.length === 0 ? /* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "No output yet..." }) : lines.map((line, i) => /* @__PURE__ */ jsx27(Text28, { wrap: "truncate", children: line }, i))
4272
+ children: /* @__PURE__ */ jsx27(
4273
+ ScrollableBox,
4274
+ {
4275
+ height: logBoxHeight,
4276
+ isActive: isInputActive,
4277
+ autoScrollToBottom: true,
4278
+ children: lines.length === 0 ? [/* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "No output yet..." }, "empty")] : lines.map((line, i) => /* @__PURE__ */ jsx27(Text28, { wrap: "truncate", children: line }, i))
4279
+ }
4280
+ )
4111
4281
  }
4112
4282
  ),
4113
4283
  feedback && /* @__PURE__ */ jsx27(Box24, { children: /* @__PURE__ */ jsx27(Text28, { color: inkColors.accent, children: feedback }) }),
@@ -4117,6 +4287,7 @@ function ProcessLogs({
4117
4287
  /* @__PURE__ */ jsx27(Text28, { bold: true, color: inkColors.accent, children: stream }),
4118
4288
  "]"
4119
4289
  ] }),
4290
+ /* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "\u2191\u2193:scroll" }),
4120
4291
  /* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "s:toggle" }),
4121
4292
  /* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "x:stop" }),
4122
4293
  /* @__PURE__ */ jsx27(Text28, { dimColor: true, children: "c:copy" }),
@@ -4126,7 +4297,7 @@ function ProcessLogs({
4126
4297
  }
4127
4298
 
4128
4299
  // src/screens/DeclarativePlan.tsx
4129
- import { useEffect as useEffect13, useState as useState21 } from "react";
4300
+ import { useEffect as useEffect15, useState as useState22 } from "react";
4130
4301
  import { Box as Box25, Text as Text29 } from "ink";
4131
4302
  import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
4132
4303
  function DeclarativePlan({
@@ -4137,10 +4308,10 @@ function DeclarativePlan({
4137
4308
  panelMode = false,
4138
4309
  isInputActive = true
4139
4310
  }) {
4140
- const [phase, setPhase] = useState21("loading");
4141
- const [actions, setActions] = useState21([]);
4142
- const [applyProgress, setApplyProgress] = useState21("");
4143
- const [applyResults, setApplyResults] = useState21([]);
4311
+ const [phase, setPhase] = useState22("loading");
4312
+ const [actions, setActions] = useState22([]);
4313
+ const [applyProgress, setApplyProgress] = useState22("");
4314
+ const [applyResults, setApplyResults] = useState22([]);
4144
4315
  const { openEditor } = useEditor();
4145
4316
  const loadPlan = () => {
4146
4317
  setPhase("loading");
@@ -4160,7 +4331,7 @@ function DeclarativePlan({
4160
4331
  setPhase("plan-view");
4161
4332
  }, 0);
4162
4333
  };
4163
- useEffect13(() => {
4334
+ useEffect15(() => {
4164
4335
  loadPlan();
4165
4336
  }, []);
4166
4337
  if (phase === "loading") {
@@ -4354,7 +4525,7 @@ function DeclarativePlan({
4354
4525
  }
4355
4526
 
4356
4527
  // src/screens/DeclarativeStatus.tsx
4357
- import { useEffect as useEffect14, useState as useState22 } from "react";
4528
+ import { useEffect as useEffect16, useState as useState23 } from "react";
4358
4529
  import { Box as Box26, Text as Text30 } from "ink";
4359
4530
  import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
4360
4531
  function DeclarativeStatus({
@@ -4364,10 +4535,10 @@ function DeclarativeStatus({
4364
4535
  panelMode = false,
4365
4536
  isInputActive = true
4366
4537
  }) {
4367
- const [phase, setPhase] = useState22("loading");
4368
- const [status, setStatus] = useState22({});
4369
- const [config2, setConfig] = useState22(null);
4370
- const [pkgInfo, setPkgInfo] = useState22(null);
4538
+ const [phase, setPhase] = useState23("loading");
4539
+ const [status, setStatus] = useState23({});
4540
+ const [config2, setConfig] = useState23(null);
4541
+ const [pkgInfo, setPkgInfo] = useState23(null);
4371
4542
  const load = () => {
4372
4543
  setPhase("loading");
4373
4544
  setTimeout(() => {
@@ -4380,7 +4551,7 @@ function DeclarativeStatus({
4380
4551
  setPhase("display");
4381
4552
  }, 0);
4382
4553
  };
4383
- useEffect14(() => {
4554
+ useEffect16(() => {
4384
4555
  load();
4385
4556
  }, []);
4386
4557
  if (phase === "loading") {
@@ -4486,7 +4657,7 @@ function DeclarativeStatus({
4486
4657
  }
4487
4658
 
4488
4659
  // src/screens/InitScaffold.tsx
4489
- import { useEffect as useEffect15, useState as useState23 } from "react";
4660
+ import { useEffect as useEffect17, useState as useState24 } from "react";
4490
4661
  import { Box as Box27, Text as Text31 } from "ink";
4491
4662
  import { writeFileSync } from "fs";
4492
4663
  import { join } from "path";
@@ -4630,9 +4801,9 @@ function InitScaffold({
4630
4801
  panelMode = false,
4631
4802
  isInputActive = true
4632
4803
  }) {
4633
- const [phase, setPhase] = useState23("detecting");
4634
- const [yamlString, setYamlString] = useState23("");
4635
- const [overwrite, setOverwrite] = useState23(false);
4804
+ const [phase, setPhase] = useState24("detecting");
4805
+ const [yamlString, setYamlString] = useState24("");
4806
+ const [overwrite, setOverwrite] = useState24(false);
4636
4807
  const { openEditor } = useEditor();
4637
4808
  const cwd = process.cwd();
4638
4809
  const yamlPath = join(cwd, "polter.yaml");
@@ -4678,7 +4849,7 @@ function InitScaffold({
4678
4849
  setPhase("preview");
4679
4850
  }, 0);
4680
4851
  };
4681
- useEffect15(() => {
4852
+ useEffect17(() => {
4682
4853
  detect();
4683
4854
  }, []);
4684
4855
  if (phase === "detecting") {
@@ -4790,8 +4961,164 @@ function InitScaffold({
4790
4961
  ] });
4791
4962
  }
4792
4963
 
4793
- // src/app.tsx
4964
+ // src/screens/ScriptPicker.tsx
4965
+ import { useState as useState25, useEffect as useEffect18, useMemo as useMemo8 } from "react";
4966
+ import { Box as Box28, Text as Text32, useInput as useInput11 } from "ink";
4967
+ import { readFileSync, existsSync } from "fs";
4968
+ import { join as join2 } from "path";
4794
4969
  import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
4970
+ function readScripts(cwd) {
4971
+ const pkgPath = join2(cwd, "package.json");
4972
+ if (!existsSync(pkgPath)) return [];
4973
+ try {
4974
+ const raw = JSON.parse(readFileSync(pkgPath, "utf-8"));
4975
+ const scripts = raw.scripts ?? {};
4976
+ return Object.entries(scripts).map(([name, command]) => ({ name, command }));
4977
+ } catch {
4978
+ return [];
4979
+ }
4980
+ }
4981
+ function ScriptPicker({
4982
+ onNavigate,
4983
+ onBack,
4984
+ width = 80,
4985
+ height = 24,
4986
+ panelMode = false,
4987
+ isInputActive = true
4988
+ }) {
4989
+ const cwd = process.cwd();
4990
+ const scripts = useMemo8(() => readScripts(cwd), [cwd]);
4991
+ const mgr = useMemo8(() => detectPkgManager(cwd), [cwd]);
4992
+ const [selectedIndex, setSelectedIndex] = useState25(0);
4993
+ const [feedback, setFeedback] = useState25();
4994
+ useEffect18(() => {
4995
+ if (feedback) {
4996
+ const timer = setTimeout(() => setFeedback(void 0), 3e3);
4997
+ return () => clearTimeout(timer);
4998
+ }
4999
+ }, [feedback]);
5000
+ useEffect18(() => {
5001
+ if (selectedIndex >= scripts.length && scripts.length > 0) {
5002
+ setSelectedIndex(scripts.length - 1);
5003
+ }
5004
+ }, [scripts.length, selectedIndex]);
5005
+ useInput11((input2, key) => {
5006
+ if (!isInputActive) return;
5007
+ if (key.escape || key.leftArrow && !key.ctrl) {
5008
+ onBack();
5009
+ return;
5010
+ }
5011
+ if (scripts.length === 0) return;
5012
+ if (key.upArrow || input2 === "k") {
5013
+ setSelectedIndex((i) => Math.max(0, i - 1));
5014
+ return;
5015
+ }
5016
+ if (key.downArrow || input2 === "j") {
5017
+ setSelectedIndex((i) => Math.min(scripts.length - 1, i + 1));
5018
+ return;
5019
+ }
5020
+ if (key.return || key.rightArrow) {
5021
+ const script = scripts[selectedIndex];
5022
+ if (script) {
5023
+ const resolved = resolveToolCommand("pkg", cwd);
5024
+ try {
5025
+ const translated = translateCommand(["run", script.name], mgr.id);
5026
+ onNavigate("command-execution", {
5027
+ tool: "pkg",
5028
+ args: translated.args
5029
+ });
5030
+ } catch {
5031
+ setFeedback(`"run" is not supported by ${mgr.id}`);
5032
+ }
5033
+ }
5034
+ return;
5035
+ }
5036
+ if (input2 === "b") {
5037
+ const script = scripts[selectedIndex];
5038
+ if (script) {
5039
+ try {
5040
+ const translated = translateCommand(["run", script.name], mgr.id);
5041
+ const id = generateProcessId(mgr.command, translated.args);
5042
+ startProcess(id, mgr.command, translated.args, cwd);
5043
+ setFeedback(`Started ${mgr.id} run ${script.name} as background process`);
5044
+ } catch (err) {
5045
+ setFeedback(err instanceof Error ? err.message : "Failed to start process");
5046
+ }
5047
+ }
5048
+ return;
5049
+ }
5050
+ });
5051
+ const contentWidth = Math.max(30, (panelMode ? width - 4 : width) - 2);
5052
+ if (scripts.length === 0) {
5053
+ return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
5054
+ !panelMode && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsxs30(Text32, { bold: true, color: inkColors.accent, children: [
5055
+ "\u{1F4DC}",
5056
+ " ",
5057
+ mgr.id,
5058
+ " scripts"
5059
+ ] }) }),
5060
+ /* @__PURE__ */ jsx31(
5061
+ Box28,
5062
+ {
5063
+ flexDirection: "column",
5064
+ borderStyle: "round",
5065
+ borderColor: panel.borderDim,
5066
+ borderDimColor: true,
5067
+ paddingX: 1,
5068
+ width: contentWidth,
5069
+ children: /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "No scripts found in package.json" })
5070
+ }
5071
+ ),
5072
+ /* @__PURE__ */ jsx31(Box28, { marginTop: 1, gap: 2, children: /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "Esc:back" }) })
5073
+ ] });
5074
+ }
5075
+ const headerHeight = panelMode ? 0 : 2;
5076
+ const footerHeight = 2;
5077
+ const feedbackHeight = feedback ? 2 : 0;
5078
+ const availableHeight = height - headerHeight - footerHeight - feedbackHeight;
5079
+ const itemHeight = 1;
5080
+ const visibleCount = Math.max(1, Math.floor(availableHeight / itemHeight));
5081
+ const windowStart = Math.max(0, Math.min(selectedIndex - Math.floor(visibleCount / 2), scripts.length - visibleCount));
5082
+ const visibleScripts = scripts.slice(windowStart, windowStart + visibleCount);
5083
+ return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
5084
+ !panelMode && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsxs30(Text32, { bold: true, color: inkColors.accent, children: [
5085
+ "\u{1F4DC}",
5086
+ " ",
5087
+ mgr.id,
5088
+ " scripts"
5089
+ ] }) }),
5090
+ feedback && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsx31(Text32, { color: inkColors.accent, children: feedback }) }),
5091
+ /* @__PURE__ */ jsx31(Box28, { flexDirection: "column", width: contentWidth, children: visibleScripts.map((script) => {
5092
+ const idx = scripts.indexOf(script);
5093
+ const isFocused = idx === selectedIndex;
5094
+ return /* @__PURE__ */ jsxs30(Box28, { gap: 1, children: [
5095
+ /* @__PURE__ */ jsxs30(Text32, { color: isFocused ? inkColors.accent : void 0, bold: isFocused, children: [
5096
+ isFocused ? "\u25B6" : " ",
5097
+ " ",
5098
+ script.name
5099
+ ] }),
5100
+ /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: script.command })
5101
+ ] }, script.name);
5102
+ }) }),
5103
+ scripts.length > visibleCount && /* @__PURE__ */ jsx31(Box28, { children: /* @__PURE__ */ jsxs30(Text32, { dimColor: true, children: [
5104
+ windowStart > 0 ? "\u25B2 " : " ",
5105
+ windowStart + visibleCount < scripts.length ? "\u25BC " : " ",
5106
+ scripts.length,
5107
+ " scripts"
5108
+ ] }) }),
5109
+ /* @__PURE__ */ jsxs30(Box28, { marginTop: 1, gap: 2, children: [
5110
+ /* @__PURE__ */ jsxs30(Text32, { dimColor: true, children: [
5111
+ "\u21B5",
5112
+ ":run"
5113
+ ] }),
5114
+ /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "b:background" }),
5115
+ /* @__PURE__ */ jsx31(Text32, { dimColor: true, children: "Esc:back" })
5116
+ ] })
5117
+ ] });
5118
+ }
5119
+
5120
+ // src/app.tsx
5121
+ import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
4795
5122
  function AppClassic() {
4796
5123
  const { screen, params, navigate, goBack, goHome } = useNavigation();
4797
5124
  const { exit } = useApp();
@@ -4806,9 +5133,9 @@ function AppClassic() {
4806
5133
  const renderScreen = () => {
4807
5134
  switch (screen) {
4808
5135
  case "home":
4809
- return /* @__PURE__ */ jsx31(Home, { onNavigate: navigate, onExit: handleExit, width, height });
5136
+ return /* @__PURE__ */ jsx32(Home, { onNavigate: navigate, onExit: handleExit, width, height });
4810
5137
  case "command-args":
4811
- return /* @__PURE__ */ jsx31(
5138
+ return /* @__PURE__ */ jsx32(
4812
5139
  CommandArgs,
4813
5140
  {
4814
5141
  command: params.command ?? "",
@@ -4819,9 +5146,9 @@ function AppClassic() {
4819
5146
  }
4820
5147
  );
4821
5148
  case "custom-command":
4822
- return /* @__PURE__ */ jsx31(CustomCommand, { onNavigate: navigate, onBack: goBack, width });
5149
+ return /* @__PURE__ */ jsx32(CustomCommand, { onNavigate: navigate, onBack: goBack, width });
4823
5150
  case "flag-selection":
4824
- return /* @__PURE__ */ jsx31(
5151
+ return /* @__PURE__ */ jsx32(
4825
5152
  FlagSelection,
4826
5153
  {
4827
5154
  args: params.args ?? [],
@@ -4833,11 +5160,12 @@ function AppClassic() {
4833
5160
  );
4834
5161
  case "confirm-execute":
4835
5162
  case "command-execution":
4836
- return /* @__PURE__ */ jsx31(
5163
+ return /* @__PURE__ */ jsx32(
4837
5164
  CommandExecution,
4838
5165
  {
4839
5166
  args: params.args ?? [],
4840
5167
  tool: params.tool,
5168
+ rawCommand: params.rawCommand,
4841
5169
  onBack: goBack,
4842
5170
  onExit: handleExit,
4843
5171
  onRunSuggestion: (sugTool, sugArgs) => {
@@ -4848,23 +5176,23 @@ function AppClassic() {
4848
5176
  }
4849
5177
  );
4850
5178
  case "self-update":
4851
- return /* @__PURE__ */ jsx31(SelfUpdate, { onBack: goBack, onExit: handleExit, width });
5179
+ return /* @__PURE__ */ jsx32(SelfUpdate, { onBack: goBack, onExit: handleExit, width });
4852
5180
  case "tool-status":
4853
- return /* @__PURE__ */ jsx31(ToolStatus, { onBack: goBack, onNavigate: navigate, width });
5181
+ return /* @__PURE__ */ jsx32(ToolStatus, { onBack: goBack, onNavigate: navigate, width });
4854
5182
  case "mcp-manage":
4855
- return /* @__PURE__ */ jsx31(McpManage, { onBack: goBack, width });
5183
+ return /* @__PURE__ */ jsx32(McpManage, { onBack: goBack, width });
4856
5184
  case "process-list":
4857
- return /* @__PURE__ */ jsx31(ProcessList, { onNavigate: navigate, onBack: goBack, width, height });
5185
+ return /* @__PURE__ */ jsx32(ProcessList, { onNavigate: navigate, onBack: goBack, width, height });
4858
5186
  case "process-logs":
4859
- return /* @__PURE__ */ jsx31(ProcessLogs, { processId: params.processId ?? "", onBack: goBack, width, height });
5187
+ return /* @__PURE__ */ jsx32(ProcessLogs, { processId: params.processId ?? "", onBack: goBack, width, height });
4860
5188
  case "project-config":
4861
- return /* @__PURE__ */ jsx31(ProjectConfig, { onBack: goBack, width });
5189
+ return /* @__PURE__ */ jsx32(ProjectConfig, { onBack: goBack, width });
4862
5190
  case "pipeline-list":
4863
- return /* @__PURE__ */ jsx31(PipelineList, { onNavigate: navigate, onBack: goBack, width });
5191
+ return /* @__PURE__ */ jsx32(PipelineList, { onNavigate: navigate, onBack: goBack, width });
4864
5192
  case "pipeline-builder":
4865
- return /* @__PURE__ */ jsx31(PipelineBuilder, { onBack: goBack, width, height });
5193
+ return /* @__PURE__ */ jsx32(PipelineBuilder, { onBack: goBack, width, height });
4866
5194
  case "pipeline-execution":
4867
- return /* @__PURE__ */ jsx31(
5195
+ return /* @__PURE__ */ jsx32(
4868
5196
  PipelineExecution,
4869
5197
  {
4870
5198
  pipelineId: params.pipelineId ?? "",
@@ -4874,32 +5202,34 @@ function AppClassic() {
4874
5202
  }
4875
5203
  );
4876
5204
  case "declarative-plan":
4877
- return /* @__PURE__ */ jsx31(DeclarativePlan, { onBack: goBack, onNavigate: navigate, width, height });
5205
+ return /* @__PURE__ */ jsx32(DeclarativePlan, { onBack: goBack, onNavigate: navigate, width, height });
4878
5206
  case "declarative-status":
4879
- return /* @__PURE__ */ jsx31(DeclarativeStatus, { onBack: goBack, width, height });
5207
+ return /* @__PURE__ */ jsx32(DeclarativeStatus, { onBack: goBack, width, height });
4880
5208
  case "init-scaffold":
4881
- return /* @__PURE__ */ jsx31(InitScaffold, { onBack: goBack, onNavigate: navigate, width, height });
5209
+ return /* @__PURE__ */ jsx32(InitScaffold, { onBack: goBack, onNavigate: navigate, width, height });
5210
+ case "script-picker":
5211
+ return /* @__PURE__ */ jsx32(ScriptPicker, { onNavigate: navigate, onBack: goBack, width, height });
4882
5212
  default:
4883
- return /* @__PURE__ */ jsx31(Box28, { children: /* @__PURE__ */ jsxs30(Text32, { color: "red", children: [
5213
+ return /* @__PURE__ */ jsx32(Box29, { children: /* @__PURE__ */ jsxs31(Text33, { color: "red", children: [
4884
5214
  "Unknown screen: ",
4885
5215
  screen
4886
5216
  ] }) });
4887
5217
  }
4888
5218
  };
4889
- return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", children: [
4890
- /* @__PURE__ */ jsx31(GhostBanner, { width }),
5219
+ return /* @__PURE__ */ jsxs31(Box29, { flexDirection: "column", children: [
5220
+ /* @__PURE__ */ jsx32(GhostBanner, { width }),
4891
5221
  renderScreen()
4892
5222
  ] });
4893
5223
  }
4894
5224
 
4895
5225
  // src/appPanel.tsx
4896
- import React26 from "react";
4897
- import { Box as Box37, Text as Text39, useApp as useApp2, useInput as useInput12 } from "ink";
5226
+ import React27 from "react";
5227
+ import { Box as Box38, Text as Text40, useApp as useApp2, useInput as useInput13 } from "ink";
4898
5228
 
4899
5229
  // src/hooks/usePanelNavigation.ts
4900
- import { useState as useState24, useCallback as useCallback8 } from "react";
5230
+ import { useState as useState26, useCallback as useCallback8 } from "react";
4901
5231
  function usePanelNavigation() {
4902
- const [state, setState] = useState24({
5232
+ const [state, setState] = useState26({
4903
5233
  view: "pipelines",
4904
5234
  featureId: "database",
4905
5235
  innerScreen: "home",
@@ -4937,6 +5267,7 @@ function usePanelNavigation() {
4937
5267
  config: "config",
4938
5268
  "self-update": "self-update",
4939
5269
  processes: "processes",
5270
+ scripts: "scripts",
4940
5271
  declarative: "declarative"
4941
5272
  };
4942
5273
  const view = viewMap[itemId];
@@ -5004,9 +5335,9 @@ function usePanelNavigation() {
5004
5335
  }
5005
5336
 
5006
5337
  // src/hooks/usePanelFocus.ts
5007
- import { useState as useState25, useCallback as useCallback9 } from "react";
5338
+ import { useState as useState27, useCallback as useCallback9 } from "react";
5008
5339
  function usePanelFocus() {
5009
- const [focused, setFocused] = useState25("sidebar");
5340
+ const [focused, setFocused] = useState27("sidebar");
5010
5341
  const toggleFocus = useCallback9(() => {
5011
5342
  setFocused((prev) => prev === "sidebar" ? "main" : "sidebar");
5012
5343
  }, []);
@@ -5023,15 +5354,16 @@ function usePanelFocus() {
5023
5354
  }
5024
5355
 
5025
5356
  // src/hooks/useSidebarItems.ts
5026
- import { useMemo as useMemo8 } from "react";
5357
+ import { useMemo as useMemo9 } from "react";
5027
5358
  function useSidebarItems() {
5028
- return useMemo8(() => {
5359
+ return useMemo9(() => {
5029
5360
  const items = [];
5030
5361
  items.push({ id: "__sep_workflows__", label: "---", icon: "", type: "separator", sectionTitle: "Workflows" });
5031
5362
  items.push({ id: "pipelines", label: "Pipelines", icon: "\u{1F517}", type: "action", section: "workflows" });
5032
5363
  items.push({ id: "pinned", label: "Pinned", icon: "\u{1F4CC}", type: "action", section: "workflows" });
5033
5364
  items.push({ id: "custom-command", label: "Custom Cmd", icon: "\u270F\uFE0F", type: "action", section: "workflows" });
5034
5365
  items.push({ id: "processes", label: "Processes", icon: "\u{1F4BB}", type: "action", section: "workflows" });
5366
+ items.push({ id: "scripts", label: "Scripts", icon: "\u{1F4DC}", type: "action", section: "workflows" });
5035
5367
  items.push({ id: "__sep_features__", label: "---", icon: "", type: "separator", sectionTitle: "Features" });
5036
5368
  for (const feature of features) {
5037
5369
  items.push({
@@ -5052,9 +5384,9 @@ function useSidebarItems() {
5052
5384
  }
5053
5385
 
5054
5386
  // src/hooks/useModal.ts
5055
- import { useState as useState26, useCallback as useCallback10 } from "react";
5387
+ import { useState as useState28, useCallback as useCallback10 } from "react";
5056
5388
  function useModal() {
5057
- const [state, setState] = useState26(null);
5389
+ const [state, setState] = useState28(null);
5058
5390
  const openModal = useCallback10((content, title) => {
5059
5391
  setState({ content, title });
5060
5392
  }, []);
@@ -5071,8 +5403,8 @@ function useModal() {
5071
5403
  }
5072
5404
 
5073
5405
  // src/components/PanelLayout.tsx
5074
- import { Box as Box29 } from "ink";
5075
- import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
5406
+ import { Box as Box30 } from "ink";
5407
+ import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
5076
5408
  function PanelLayout({
5077
5409
  header,
5078
5410
  footer,
@@ -5087,19 +5419,19 @@ function PanelLayout({
5087
5419
  const contentHeight = Math.max(5, height - bannerHeight - footerHeight);
5088
5420
  const sidebarWidth = singlePanel ? 0 : panel.sidebarWidth(width);
5089
5421
  const mainWidth = singlePanel ? width : width - sidebarWidth;
5090
- return /* @__PURE__ */ jsxs31(Box29, { flexDirection: "column", width, height, children: [
5422
+ return /* @__PURE__ */ jsxs32(Box30, { flexDirection: "column", width, height, children: [
5091
5423
  header,
5092
- /* @__PURE__ */ jsxs31(Box29, { flexDirection: "row", height: contentHeight, children: [
5093
- !singlePanel && /* @__PURE__ */ jsx32(Box29, { width: sidebarWidth, height: contentHeight, children: sidebar }),
5094
- /* @__PURE__ */ jsx32(Box29, { width: mainWidth, height: contentHeight, children: main2 })
5424
+ /* @__PURE__ */ jsxs32(Box30, { flexDirection: "row", height: contentHeight, children: [
5425
+ !singlePanel && /* @__PURE__ */ jsx33(Box30, { width: sidebarWidth, height: contentHeight, children: sidebar }),
5426
+ /* @__PURE__ */ jsx33(Box30, { width: mainWidth, height: contentHeight, children: main2 })
5095
5427
  ] }),
5096
- /* @__PURE__ */ jsx32(Box29, { height: footerHeight, children: footer })
5428
+ /* @__PURE__ */ jsx33(Box30, { height: footerHeight, children: footer })
5097
5429
  ] });
5098
5430
  }
5099
5431
 
5100
5432
  // src/components/Panel.tsx
5101
- import { Box as Box30, Text as Text33 } from "ink";
5102
- import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
5433
+ import { Box as Box31, Text as Text34 } from "ink";
5434
+ import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
5103
5435
  function Panel({
5104
5436
  id,
5105
5437
  title,
@@ -5109,8 +5441,8 @@ function Panel({
5109
5441
  children
5110
5442
  }) {
5111
5443
  const borderColor = focused ? panel.borderFocused : panel.borderDim;
5112
- return /* @__PURE__ */ jsxs32(
5113
- Box30,
5444
+ return /* @__PURE__ */ jsxs33(
5445
+ Box31,
5114
5446
  {
5115
5447
  flexDirection: "column",
5116
5448
  width,
@@ -5119,21 +5451,21 @@ function Panel({
5119
5451
  borderColor,
5120
5452
  overflow: "hidden",
5121
5453
  children: [
5122
- title && /* @__PURE__ */ jsx33(Box30, { marginBottom: 0, children: /* @__PURE__ */ jsxs32(Text33, { color: focused ? inkColors.accent : void 0, bold: focused, dimColor: !focused, children: [
5454
+ title && /* @__PURE__ */ jsx34(Box31, { marginBottom: 0, children: /* @__PURE__ */ jsxs33(Text34, { color: focused ? inkColors.accent : void 0, bold: focused, dimColor: !focused, children: [
5123
5455
  " ",
5124
5456
  title,
5125
5457
  " "
5126
5458
  ] }) }),
5127
- /* @__PURE__ */ jsx33(Box30, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
5459
+ /* @__PURE__ */ jsx34(Box31, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
5128
5460
  ]
5129
5461
  }
5130
5462
  );
5131
5463
  }
5132
5464
 
5133
5465
  // src/components/Sidebar.tsx
5134
- import { useEffect as useEffect16, useMemo as useMemo9, useState as useState27 } from "react";
5135
- import { Box as Box31, Text as Text34, useInput as useInput11 } from "ink";
5136
- import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
5466
+ import { useEffect as useEffect19, useMemo as useMemo10, useState as useState29 } from "react";
5467
+ import { Box as Box32, Text as Text35, useInput as useInput12 } from "ink";
5468
+ import { jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
5137
5469
  function groupSections(items) {
5138
5470
  const groups = [];
5139
5471
  let current = null;
@@ -5155,18 +5487,18 @@ function Sidebar({
5155
5487
  onSelect,
5156
5488
  onHighlight
5157
5489
  }) {
5158
- const selectableItems = useMemo9(
5490
+ const selectableItems = useMemo10(
5159
5491
  () => items.filter((item) => item.type !== "separator"),
5160
5492
  [items]
5161
5493
  );
5162
5494
  const selectedIdx = selectableItems.findIndex((item) => item.id === selectedId);
5163
- const [cursorIdx, setCursorIdx] = useState27(Math.max(0, selectedIdx));
5164
- const sections = useMemo9(() => groupSections(items), [items]);
5165
- useEffect16(() => {
5495
+ const [cursorIdx, setCursorIdx] = useState29(Math.max(0, selectedIdx));
5496
+ const sections = useMemo10(() => groupSections(items), [items]);
5497
+ useEffect19(() => {
5166
5498
  const idx = selectableItems.findIndex((item) => item.id === selectedId);
5167
5499
  if (idx >= 0) setCursorIdx(idx);
5168
5500
  }, [selectedId, selectableItems]);
5169
- useInput11(
5501
+ useInput12(
5170
5502
  (input2, key) => {
5171
5503
  if (key.upArrow || input2 === "k") {
5172
5504
  setCursorIdx((prev) => {
@@ -5194,28 +5526,28 @@ function Sidebar({
5194
5526
  { isActive: isFocused }
5195
5527
  );
5196
5528
  let flatIdx = 0;
5197
- return /* @__PURE__ */ jsx34(Box31, { flexDirection: "column", gap: 0, children: sections.map((section) => {
5529
+ return /* @__PURE__ */ jsx35(Box32, { flexDirection: "column", gap: 0, children: sections.map((section) => {
5198
5530
  const sectionStartIdx = flatIdx;
5199
5531
  const sectionEndIdx = sectionStartIdx + section.items.length - 1;
5200
5532
  const hasCursorInSection = isFocused && cursorIdx >= sectionStartIdx && cursorIdx <= sectionEndIdx;
5201
5533
  const hasActiveInSection = section.items.some((item) => item.id === selectedId);
5202
5534
  const borderColor = hasCursorInSection || hasActiveInSection ? inkColors.accent : "#555555";
5203
- const rendered = /* @__PURE__ */ jsxs33(
5204
- Box31,
5535
+ const rendered = /* @__PURE__ */ jsxs34(
5536
+ Box32,
5205
5537
  {
5206
5538
  flexDirection: "column",
5207
5539
  borderStyle: "round",
5208
5540
  borderColor,
5209
5541
  paddingX: 1,
5210
5542
  children: [
5211
- /* @__PURE__ */ jsx34(Text34, { dimColor: true, bold: true, children: section.title }),
5543
+ /* @__PURE__ */ jsx35(Text35, { dimColor: true, bold: true, children: section.title }),
5212
5544
  section.items.map((item) => {
5213
5545
  const thisIdx = flatIdx;
5214
5546
  flatIdx++;
5215
5547
  const isCursor = isFocused && thisIdx === cursorIdx;
5216
5548
  const isActive = item.id === selectedId;
5217
- return /* @__PURE__ */ jsx34(Box31, { gap: 0, children: /* @__PURE__ */ jsxs33(
5218
- Text34,
5549
+ return /* @__PURE__ */ jsx35(Box32, { gap: 0, children: /* @__PURE__ */ jsxs34(
5550
+ Text35,
5219
5551
  {
5220
5552
  color: isCursor ? inkColors.accent : isActive ? inkColors.accent : void 0,
5221
5553
  bold: isCursor || isActive,
@@ -5238,12 +5570,12 @@ function Sidebar({
5238
5570
  }
5239
5571
 
5240
5572
  // src/components/PanelFooter.tsx
5241
- import { Box as Box32, Text as Text35 } from "ink";
5242
- import { jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
5573
+ import { Box as Box33, Text as Text36 } from "ink";
5574
+ import { jsx as jsx36, jsxs as jsxs35 } from "react/jsx-runtime";
5243
5575
  function PanelFooter({ hints, width }) {
5244
- return /* @__PURE__ */ jsx35(Box32, { width, children: /* @__PURE__ */ jsx35(Box32, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsxs34(Box32, { gap: 0, children: [
5245
- /* @__PURE__ */ jsx35(Text35, { color: inkColors.accent, bold: true, children: hint.key }),
5246
- /* @__PURE__ */ jsxs34(Text35, { dimColor: true, children: [
5576
+ return /* @__PURE__ */ jsx36(Box33, { width, children: /* @__PURE__ */ jsx36(Box33, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsxs35(Box33, { gap: 0, children: [
5577
+ /* @__PURE__ */ jsx36(Text36, { color: inkColors.accent, bold: true, children: hint.key }),
5578
+ /* @__PURE__ */ jsxs35(Text36, { dimColor: true, children: [
5247
5579
  ":",
5248
5580
  hint.action
5249
5581
  ] })
@@ -5251,8 +5583,8 @@ function PanelFooter({ hints, width }) {
5251
5583
  }
5252
5584
 
5253
5585
  // src/components/Modal.tsx
5254
- import { Box as Box33, Text as Text36 } from "ink";
5255
- import { jsx as jsx36, jsxs as jsxs35 } from "react/jsx-runtime";
5586
+ import { Box as Box34, Text as Text37 } from "ink";
5587
+ import { jsx as jsx37, jsxs as jsxs36 } from "react/jsx-runtime";
5256
5588
  function Modal({
5257
5589
  title,
5258
5590
  width,
@@ -5263,10 +5595,10 @@ function Modal({
5263
5595
  const modalHeight = Math.min(height - 4, 20);
5264
5596
  const padX = Math.max(0, Math.floor((width - modalWidth) / 2));
5265
5597
  const padY = Math.max(0, Math.floor((height - modalHeight) / 2));
5266
- return /* @__PURE__ */ jsxs35(Box33, { flexDirection: "column", width, height, children: [
5267
- padY > 0 && /* @__PURE__ */ jsx36(Box33, { height: padY }),
5268
- /* @__PURE__ */ jsx36(Box33, { marginLeft: padX, children: /* @__PURE__ */ jsxs35(
5269
- Box33,
5598
+ return /* @__PURE__ */ jsxs36(Box34, { flexDirection: "column", width, height, children: [
5599
+ padY > 0 && /* @__PURE__ */ jsx37(Box34, { height: padY }),
5600
+ /* @__PURE__ */ jsx37(Box34, { marginLeft: padX, children: /* @__PURE__ */ jsxs36(
5601
+ Box34,
5270
5602
  {
5271
5603
  flexDirection: "column",
5272
5604
  width: modalWidth,
@@ -5275,8 +5607,8 @@ function Modal({
5275
5607
  borderColor: inkColors.accent,
5276
5608
  paddingX: 1,
5277
5609
  children: [
5278
- /* @__PURE__ */ jsx36(Box33, { marginBottom: 1, children: /* @__PURE__ */ jsx36(Text36, { color: inkColors.accent, bold: true, children: title }) }),
5279
- /* @__PURE__ */ jsx36(Box33, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
5610
+ /* @__PURE__ */ jsx37(Box34, { marginBottom: 1, children: /* @__PURE__ */ jsx37(Text37, { color: inkColors.accent, bold: true, children: title }) }),
5611
+ /* @__PURE__ */ jsx37(Box34, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
5280
5612
  ]
5281
5613
  }
5282
5614
  ) })
@@ -5284,9 +5616,9 @@ function Modal({
5284
5616
  }
5285
5617
 
5286
5618
  // src/components/FeatureCommands.tsx
5287
- import { useEffect as useEffect17, useMemo as useMemo10, useState as useState28 } from "react";
5288
- import { Box as Box34, Text as Text37 } from "ink";
5289
- import { jsx as jsx37, jsxs as jsxs36 } from "react/jsx-runtime";
5619
+ import { useEffect as useEffect20, useMemo as useMemo11, useState as useState30 } from "react";
5620
+ import { Box as Box35, Text as Text38 } from "ink";
5621
+ import { jsx as jsx38, jsxs as jsxs37 } from "react/jsx-runtime";
5290
5622
  function FeatureCommands({
5291
5623
  feature,
5292
5624
  onNavigate,
@@ -5297,15 +5629,15 @@ function FeatureCommands({
5297
5629
  height = 24,
5298
5630
  isInputActive = true
5299
5631
  }) {
5300
- const [pinnedCommands, setPinnedCommands2] = useState28(() => getPinnedCommands());
5301
- const [pinnedRuns, setPinnedRuns2] = useState28(() => getPinnedRuns());
5302
- const [pinFeedback, setPinFeedback] = useState28();
5303
- useEffect17(() => {
5632
+ const [pinnedCommands, setPinnedCommands2] = useState30(() => getPinnedCommands());
5633
+ const [pinnedRuns, setPinnedRuns2] = useState30(() => getPinnedRuns());
5634
+ const [pinFeedback, setPinFeedback] = useState30();
5635
+ useEffect20(() => {
5304
5636
  if (!pinFeedback) return;
5305
5637
  const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
5306
5638
  return () => clearTimeout(timeout);
5307
5639
  }, [pinFeedback]);
5308
- const items = useMemo10(
5640
+ const items = useMemo11(
5309
5641
  () => buildHomeItems({
5310
5642
  activeFeature: feature,
5311
5643
  pinnedCommands,
@@ -5315,8 +5647,8 @@ function FeatureCommands({
5315
5647
  }),
5316
5648
  [feature, pinnedCommands, pinnedRuns]
5317
5649
  );
5318
- const pinnedCommandSet = useMemo10(() => new Set(pinnedCommands), [pinnedCommands]);
5319
- const pinnedRunSet = useMemo10(() => new Set(pinnedRuns), [pinnedRuns]);
5650
+ const pinnedCommandSet = useMemo11(() => new Set(pinnedCommands), [pinnedCommands]);
5651
+ const pinnedRunSet = useMemo11(() => new Set(pinnedRuns), [pinnedRuns]);
5320
5652
  const refreshPins = () => {
5321
5653
  setPinnedCommands2(getPinnedCommands());
5322
5654
  setPinnedRuns2(getPinnedRuns());
@@ -5368,12 +5700,12 @@ function FeatureCommands({
5368
5700
  );
5369
5701
  }
5370
5702
  };
5371
- return /* @__PURE__ */ jsxs36(Box34, { flexDirection: "column", paddingX: 1, children: [
5372
- pinFeedback && /* @__PURE__ */ jsx37(Box34, { marginBottom: 1, children: /* @__PURE__ */ jsxs36(Text37, { color: inkColors.accent, children: [
5703
+ return /* @__PURE__ */ jsxs37(Box35, { flexDirection: "column", paddingX: 1, children: [
5704
+ pinFeedback && /* @__PURE__ */ jsx38(Box35, { marginBottom: 1, children: /* @__PURE__ */ jsxs37(Text38, { color: inkColors.accent, children: [
5373
5705
  "\u2713 ",
5374
5706
  pinFeedback
5375
5707
  ] }) }),
5376
- /* @__PURE__ */ jsx37(
5708
+ /* @__PURE__ */ jsx38(
5377
5709
  SelectList,
5378
5710
  {
5379
5711
  items,
@@ -5392,9 +5724,9 @@ function FeatureCommands({
5392
5724
  }
5393
5725
 
5394
5726
  // src/components/PinnedCommands.tsx
5395
- import { useEffect as useEffect18, useMemo as useMemo11, useState as useState29 } from "react";
5396
- import { Box as Box35, Text as Text38 } from "ink";
5397
- import { jsx as jsx38, jsxs as jsxs37 } from "react/jsx-runtime";
5727
+ import { useEffect as useEffect21, useMemo as useMemo12, useState as useState31 } from "react";
5728
+ import { Box as Box36, Text as Text39 } from "ink";
5729
+ import { jsx as jsx39, jsxs as jsxs38 } from "react/jsx-runtime";
5398
5730
  function PinnedCommands({
5399
5731
  onNavigate,
5400
5732
  onBack,
@@ -5403,20 +5735,20 @@ function PinnedCommands({
5403
5735
  height = 24,
5404
5736
  isInputActive = true
5405
5737
  }) {
5406
- const [pinnedCommands, setPinnedCommands2] = useState29(() => getPinnedCommands());
5407
- const [pinnedRuns, setPinnedRuns2] = useState29(() => getPinnedRuns());
5408
- const [pinFeedback, setPinFeedback] = useState29();
5409
- useEffect18(() => {
5738
+ const [pinnedCommands, setPinnedCommands2] = useState31(() => getPinnedCommands());
5739
+ const [pinnedRuns, setPinnedRuns2] = useState31(() => getPinnedRuns());
5740
+ const [pinFeedback, setPinFeedback] = useState31();
5741
+ useEffect21(() => {
5410
5742
  if (!pinFeedback) return;
5411
5743
  const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
5412
5744
  return () => clearTimeout(timeout);
5413
5745
  }, [pinFeedback]);
5414
- const items = useMemo11(
5746
+ const items = useMemo12(
5415
5747
  () => buildPinnedOnlyItems(pinnedCommands, pinnedRuns),
5416
5748
  [pinnedCommands, pinnedRuns]
5417
5749
  );
5418
- const pinnedCommandSet = useMemo11(() => new Set(pinnedCommands), [pinnedCommands]);
5419
- const pinnedRunSet = useMemo11(() => new Set(pinnedRuns), [pinnedRuns]);
5750
+ const pinnedCommandSet = useMemo12(() => new Set(pinnedCommands), [pinnedCommands]);
5751
+ const pinnedRunSet = useMemo12(() => new Set(pinnedRuns), [pinnedRuns]);
5420
5752
  const refreshPins = () => {
5421
5753
  setPinnedCommands2(getPinnedCommands());
5422
5754
  setPinnedRuns2(getPinnedRuns());
@@ -5468,14 +5800,14 @@ function PinnedCommands({
5468
5800
  }
5469
5801
  };
5470
5802
  if (items.length === 0) {
5471
- return /* @__PURE__ */ jsx38(Box35, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx38(Text38, { color: "gray", children: "No pinned items. Press p on any command to pin it." }) });
5803
+ return /* @__PURE__ */ jsx39(Box36, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx39(Text39, { color: "gray", children: "No pinned items. Press p on any command to pin it." }) });
5472
5804
  }
5473
- return /* @__PURE__ */ jsxs37(Box35, { flexDirection: "column", paddingX: 1, children: [
5474
- pinFeedback && /* @__PURE__ */ jsx38(Box35, { marginBottom: 1, children: /* @__PURE__ */ jsxs37(Text38, { color: inkColors.accent, children: [
5805
+ return /* @__PURE__ */ jsxs38(Box36, { flexDirection: "column", paddingX: 1, children: [
5806
+ pinFeedback && /* @__PURE__ */ jsx39(Box36, { marginBottom: 1, children: /* @__PURE__ */ jsxs38(Text39, { color: inkColors.accent, children: [
5475
5807
  "\u2713 ",
5476
5808
  pinFeedback
5477
5809
  ] }) }),
5478
- /* @__PURE__ */ jsx38(
5810
+ /* @__PURE__ */ jsx39(
5479
5811
  SelectList,
5480
5812
  {
5481
5813
  items,
@@ -5494,9 +5826,9 @@ function PinnedCommands({
5494
5826
  }
5495
5827
 
5496
5828
  // src/screens/DeclarativeHome.tsx
5497
- import { useMemo as useMemo12 } from "react";
5498
- import { Box as Box36 } from "ink";
5499
- import { jsx as jsx39 } from "react/jsx-runtime";
5829
+ import { useMemo as useMemo13 } from "react";
5830
+ import { Box as Box37 } from "ink";
5831
+ import { jsx as jsx40 } from "react/jsx-runtime";
5500
5832
  var ITEMS = [
5501
5833
  { value: "declarative-plan", label: "Plan / Apply", hint: "Diff and apply polter.yaml", kind: "action" },
5502
5834
  { value: "declarative-status", label: "Infrastructure Status", hint: "Live state from CLI tools", kind: "action" },
@@ -5509,11 +5841,11 @@ function DeclarativeHome({
5509
5841
  height = 24,
5510
5842
  isInputActive = true
5511
5843
  }) {
5512
- const handleSelect = useMemo12(
5844
+ const handleSelect = useMemo13(
5513
5845
  () => (value) => onNavigate(value),
5514
5846
  [onNavigate]
5515
5847
  );
5516
- return /* @__PURE__ */ jsx39(Box36, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx39(
5848
+ return /* @__PURE__ */ jsx40(Box37, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx40(
5517
5849
  SelectList,
5518
5850
  {
5519
5851
  items: ITEMS,
@@ -5529,7 +5861,7 @@ function DeclarativeHome({
5529
5861
  }
5530
5862
 
5531
5863
  // src/appPanel.tsx
5532
- import { jsx as jsx40, jsxs as jsxs38 } from "react/jsx-runtime";
5864
+ import { jsx as jsx41, jsxs as jsxs39 } from "react/jsx-runtime";
5533
5865
  var screenLabels = {
5534
5866
  "command-args": "Args",
5535
5867
  "flag-selection": "Flags",
@@ -5547,7 +5879,8 @@ var screenLabels = {
5547
5879
  "process-logs": "Logs",
5548
5880
  "declarative-plan": "Plan/Apply",
5549
5881
  "declarative-status": "Status",
5550
- "init-scaffold": "Init"
5882
+ "init-scaffold": "Init",
5883
+ "script-picker": "Scripts"
5551
5884
  };
5552
5885
  function buildBreadcrumb(nav) {
5553
5886
  let base;
@@ -5578,6 +5911,9 @@ function buildBreadcrumb(nav) {
5578
5911
  case "processes":
5579
5912
  base = "\u{1F4BB} Processes";
5580
5913
  break;
5914
+ case "scripts":
5915
+ base = "\u{1F4DC} Scripts";
5916
+ break;
5581
5917
  case "declarative":
5582
5918
  base = "\u{1F3D7}\uFE0F Infrastructure";
5583
5919
  break;
@@ -5613,7 +5949,7 @@ function AppPanel() {
5613
5949
  const focus = usePanelFocus();
5614
5950
  const sidebarItems = useSidebarItems();
5615
5951
  const modal = useModal();
5616
- const refreshPins = React26.useCallback(() => {
5952
+ const refreshPins = React27.useCallback(() => {
5617
5953
  }, []);
5618
5954
  const singlePanel = width < 60 || height < 15;
5619
5955
  const handleExit = () => {
@@ -5622,7 +5958,7 @@ function AppPanel() {
5622
5958
  );
5623
5959
  exit();
5624
5960
  };
5625
- useInput12((input2, key) => {
5961
+ useInput13((input2, key) => {
5626
5962
  if (modal.isOpen) {
5627
5963
  if (key.escape || input2 === "q") {
5628
5964
  modal.closeModal();
@@ -5647,37 +5983,37 @@ function AppPanel() {
5647
5983
  }
5648
5984
  if (input2 === "?") {
5649
5985
  modal.openModal(
5650
- /* @__PURE__ */ jsxs38(Box37, { flexDirection: "column", children: [
5651
- /* @__PURE__ */ jsxs38(Text39, { children: [
5652
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "\u2190/\u2192" }),
5986
+ /* @__PURE__ */ jsxs39(Box38, { flexDirection: "column", children: [
5987
+ /* @__PURE__ */ jsxs39(Text40, { children: [
5988
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "\u2190/\u2192" }),
5653
5989
  " Move between sidebar and main panel"
5654
5990
  ] }),
5655
- /* @__PURE__ */ jsxs38(Text39, { children: [
5656
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "Tab" }),
5991
+ /* @__PURE__ */ jsxs39(Text40, { children: [
5992
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "Tab" }),
5657
5993
  " Toggle sidebar / main panel"
5658
5994
  ] }),
5659
- /* @__PURE__ */ jsxs38(Text39, { children: [
5660
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "j/k" }),
5995
+ /* @__PURE__ */ jsxs39(Text40, { children: [
5996
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "j/k" }),
5661
5997
  " Navigate up/down"
5662
5998
  ] }),
5663
- /* @__PURE__ */ jsxs38(Text39, { children: [
5664
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "Enter" }),
5999
+ /* @__PURE__ */ jsxs39(Text40, { children: [
6000
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "Enter" }),
5665
6001
  " Select item"
5666
6002
  ] }),
5667
- /* @__PURE__ */ jsxs38(Text39, { children: [
5668
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "Esc" }),
6003
+ /* @__PURE__ */ jsxs39(Text40, { children: [
6004
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "Esc" }),
5669
6005
  " Go back (or return to sidebar)"
5670
6006
  ] }),
5671
- /* @__PURE__ */ jsxs38(Text39, { children: [
5672
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "q" }),
6007
+ /* @__PURE__ */ jsxs39(Text40, { children: [
6008
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "q" }),
5673
6009
  " Quit Polter"
5674
6010
  ] }),
5675
- /* @__PURE__ */ jsxs38(Text39, { children: [
5676
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "?" }),
6011
+ /* @__PURE__ */ jsxs39(Text40, { children: [
6012
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "?" }),
5677
6013
  " Show this help"
5678
6014
  ] }),
5679
- /* @__PURE__ */ jsxs38(Text39, { children: [
5680
- /* @__PURE__ */ jsx40(Text39, { bold: true, children: "p" }),
6015
+ /* @__PURE__ */ jsxs39(Text40, { children: [
6016
+ /* @__PURE__ */ jsx41(Text40, { bold: true, children: "p" }),
5681
6017
  " Pin/unpin command"
5682
6018
  ] })
5683
6019
  ] }),
@@ -5703,6 +6039,8 @@ function AppPanel() {
5703
6039
  return "self-update";
5704
6040
  case "processes":
5705
6041
  return "processes";
6042
+ case "scripts":
6043
+ return "scripts";
5706
6044
  case "declarative":
5707
6045
  return "declarative";
5708
6046
  default:
@@ -5721,7 +6059,7 @@ function AppPanel() {
5721
6059
  nav.selectSidebarItem(itemId);
5722
6060
  focus.focusMain();
5723
6061
  };
5724
- const bannerHeight = width < 60 ? 1 : 8;
6062
+ const bannerHeight = width < 60 ? 6 : 10;
5725
6063
  const footerHints = FOOTER_HINTS;
5726
6064
  const mainContentHeight = Math.max(5, height - bannerHeight - 1 - 2);
5727
6065
  const mainContentWidth = singlePanel ? width : width - Math.max(20, Math.min(35, Math.floor(width * 0.3)));
@@ -5731,7 +6069,7 @@ function AppPanel() {
5731
6069
  }
5732
6070
  switch (nav.view) {
5733
6071
  case "pinned":
5734
- return /* @__PURE__ */ jsx40(
6072
+ return /* @__PURE__ */ jsx41(
5735
6073
  PinnedCommands,
5736
6074
  {
5737
6075
  onNavigate: nav.navigateInner,
@@ -5745,12 +6083,12 @@ function AppPanel() {
5745
6083
  case "feature": {
5746
6084
  const feature = getFeatureById(nav.featureId);
5747
6085
  if (!feature) {
5748
- return /* @__PURE__ */ jsxs38(Text39, { color: "red", children: [
6086
+ return /* @__PURE__ */ jsxs39(Text40, { color: "red", children: [
5749
6087
  "Feature not found: ",
5750
6088
  nav.featureId
5751
6089
  ] });
5752
6090
  }
5753
- return /* @__PURE__ */ jsx40(
6091
+ return /* @__PURE__ */ jsx41(
5754
6092
  FeatureCommands,
5755
6093
  {
5756
6094
  feature,
@@ -5765,7 +6103,7 @@ function AppPanel() {
5765
6103
  );
5766
6104
  }
5767
6105
  case "custom-command":
5768
- return /* @__PURE__ */ jsx40(
6106
+ return /* @__PURE__ */ jsx41(
5769
6107
  CustomCommand,
5770
6108
  {
5771
6109
  onNavigate: nav.navigateInner,
@@ -5777,7 +6115,7 @@ function AppPanel() {
5777
6115
  }
5778
6116
  );
5779
6117
  case "pipelines":
5780
- return /* @__PURE__ */ jsx40(
6118
+ return /* @__PURE__ */ jsx41(
5781
6119
  PipelineList,
5782
6120
  {
5783
6121
  onNavigate: nav.navigateInner,
@@ -5789,7 +6127,7 @@ function AppPanel() {
5789
6127
  }
5790
6128
  );
5791
6129
  case "tool-status":
5792
- return /* @__PURE__ */ jsx40(
6130
+ return /* @__PURE__ */ jsx41(
5793
6131
  ToolStatus,
5794
6132
  {
5795
6133
  onBack: focus.focusSidebar,
@@ -5801,7 +6139,7 @@ function AppPanel() {
5801
6139
  }
5802
6140
  );
5803
6141
  case "processes":
5804
- return /* @__PURE__ */ jsx40(
6142
+ return /* @__PURE__ */ jsx41(
5805
6143
  ProcessList,
5806
6144
  {
5807
6145
  onNavigate: nav.navigateInner,
@@ -5812,8 +6150,20 @@ function AppPanel() {
5812
6150
  isInputActive: focus.isMainFocused
5813
6151
  }
5814
6152
  );
6153
+ case "scripts":
6154
+ return /* @__PURE__ */ jsx41(
6155
+ ScriptPicker,
6156
+ {
6157
+ onNavigate: nav.navigateInner,
6158
+ onBack: focus.focusSidebar,
6159
+ width: mainContentWidth - 2,
6160
+ height: mainContentHeight,
6161
+ panelMode: true,
6162
+ isInputActive: focus.isMainFocused
6163
+ }
6164
+ );
5815
6165
  case "declarative":
5816
- return /* @__PURE__ */ jsx40(
6166
+ return /* @__PURE__ */ jsx41(
5817
6167
  DeclarativeHome,
5818
6168
  {
5819
6169
  onNavigate: nav.navigateInner,
@@ -5824,7 +6174,7 @@ function AppPanel() {
5824
6174
  }
5825
6175
  );
5826
6176
  case "config":
5827
- return /* @__PURE__ */ jsx40(
6177
+ return /* @__PURE__ */ jsx41(
5828
6178
  ProjectConfig,
5829
6179
  {
5830
6180
  onBack: focus.focusSidebar,
@@ -5835,7 +6185,7 @@ function AppPanel() {
5835
6185
  }
5836
6186
  );
5837
6187
  case "self-update":
5838
- return /* @__PURE__ */ jsx40(
6188
+ return /* @__PURE__ */ jsx41(
5839
6189
  SelfUpdate,
5840
6190
  {
5841
6191
  onBack: focus.focusSidebar,
@@ -5847,7 +6197,7 @@ function AppPanel() {
5847
6197
  }
5848
6198
  );
5849
6199
  default:
5850
- return /* @__PURE__ */ jsx40(Text39, { children: "Select an item from the sidebar" });
6200
+ return /* @__PURE__ */ jsx41(Text40, { children: "Select an item from the sidebar" });
5851
6201
  }
5852
6202
  };
5853
6203
  const renderInnerScreen = () => {
@@ -5855,7 +6205,7 @@ function AppPanel() {
5855
6205
  const w = mainContentWidth - 2;
5856
6206
  switch (nav.innerScreen) {
5857
6207
  case "command-args":
5858
- return /* @__PURE__ */ jsx40(
6208
+ return /* @__PURE__ */ jsx41(
5859
6209
  CommandArgs,
5860
6210
  {
5861
6211
  command: nav.innerParams.command ?? "",
@@ -5868,7 +6218,7 @@ function AppPanel() {
5868
6218
  }
5869
6219
  );
5870
6220
  case "custom-command":
5871
- return /* @__PURE__ */ jsx40(
6221
+ return /* @__PURE__ */ jsx41(
5872
6222
  CustomCommand,
5873
6223
  {
5874
6224
  onNavigate: nav.navigateInner,
@@ -5880,7 +6230,7 @@ function AppPanel() {
5880
6230
  }
5881
6231
  );
5882
6232
  case "flag-selection":
5883
- return /* @__PURE__ */ jsx40(
6233
+ return /* @__PURE__ */ jsx41(
5884
6234
  FlagSelection,
5885
6235
  {
5886
6236
  args: nav.innerParams.args ?? [],
@@ -5896,11 +6246,12 @@ function AppPanel() {
5896
6246
  );
5897
6247
  case "confirm-execute":
5898
6248
  case "command-execution":
5899
- return /* @__PURE__ */ jsx40(
6249
+ return /* @__PURE__ */ jsx41(
5900
6250
  CommandExecution,
5901
6251
  {
5902
6252
  args: nav.innerParams.args ?? [],
5903
6253
  tool: nav.innerParams.tool,
6254
+ rawCommand: nav.innerParams.rawCommand,
5904
6255
  interactive: nav.innerParams.interactive,
5905
6256
  onBack: nav.goBackInner,
5906
6257
  onHome: nav.goHomeInner,
@@ -5916,7 +6267,7 @@ function AppPanel() {
5916
6267
  `${nav.view}-${nav.innerParams.tool}-${(nav.innerParams.args ?? []).join("-")}`
5917
6268
  );
5918
6269
  case "pipeline-list":
5919
- return /* @__PURE__ */ jsx40(
6270
+ return /* @__PURE__ */ jsx41(
5920
6271
  PipelineList,
5921
6272
  {
5922
6273
  onNavigate: nav.navigateInner,
@@ -5928,7 +6279,7 @@ function AppPanel() {
5928
6279
  }
5929
6280
  );
5930
6281
  case "pipeline-builder":
5931
- return /* @__PURE__ */ jsx40(
6282
+ return /* @__PURE__ */ jsx41(
5932
6283
  PipelineBuilder,
5933
6284
  {
5934
6285
  onBack: nav.goBackInner,
@@ -5939,7 +6290,7 @@ function AppPanel() {
5939
6290
  }
5940
6291
  );
5941
6292
  case "pipeline-execution":
5942
- return /* @__PURE__ */ jsx40(
6293
+ return /* @__PURE__ */ jsx41(
5943
6294
  PipelineExecution,
5944
6295
  {
5945
6296
  pipelineId: nav.innerParams.pipelineId ?? "",
@@ -5951,7 +6302,7 @@ function AppPanel() {
5951
6302
  }
5952
6303
  );
5953
6304
  case "self-update":
5954
- return /* @__PURE__ */ jsx40(
6305
+ return /* @__PURE__ */ jsx41(
5955
6306
  SelfUpdate,
5956
6307
  {
5957
6308
  onBack: nav.goBackInner,
@@ -5963,7 +6314,7 @@ function AppPanel() {
5963
6314
  }
5964
6315
  );
5965
6316
  case "tool-status":
5966
- return /* @__PURE__ */ jsx40(
6317
+ return /* @__PURE__ */ jsx41(
5967
6318
  ToolStatus,
5968
6319
  {
5969
6320
  onBack: nav.goBackInner,
@@ -5975,7 +6326,7 @@ function AppPanel() {
5975
6326
  }
5976
6327
  );
5977
6328
  case "mcp-manage":
5978
- return /* @__PURE__ */ jsx40(
6329
+ return /* @__PURE__ */ jsx41(
5979
6330
  McpManage,
5980
6331
  {
5981
6332
  onBack: nav.goBackInner,
@@ -5986,7 +6337,7 @@ function AppPanel() {
5986
6337
  }
5987
6338
  );
5988
6339
  case "process-list":
5989
- return /* @__PURE__ */ jsx40(
6340
+ return /* @__PURE__ */ jsx41(
5990
6341
  ProcessList,
5991
6342
  {
5992
6343
  onNavigate: nav.navigateInner,
@@ -5998,7 +6349,7 @@ function AppPanel() {
5998
6349
  }
5999
6350
  );
6000
6351
  case "process-logs":
6001
- return /* @__PURE__ */ jsx40(
6352
+ return /* @__PURE__ */ jsx41(
6002
6353
  ProcessLogs,
6003
6354
  {
6004
6355
  processId: nav.innerParams.processId ?? "",
@@ -6010,7 +6361,7 @@ function AppPanel() {
6010
6361
  }
6011
6362
  );
6012
6363
  case "project-config":
6013
- return /* @__PURE__ */ jsx40(
6364
+ return /* @__PURE__ */ jsx41(
6014
6365
  ProjectConfig,
6015
6366
  {
6016
6367
  onBack: nav.goBackInner,
@@ -6021,7 +6372,7 @@ function AppPanel() {
6021
6372
  }
6022
6373
  );
6023
6374
  case "declarative-plan":
6024
- return /* @__PURE__ */ jsx40(
6375
+ return /* @__PURE__ */ jsx41(
6025
6376
  DeclarativePlan,
6026
6377
  {
6027
6378
  onBack: nav.goBackInner,
@@ -6033,7 +6384,7 @@ function AppPanel() {
6033
6384
  }
6034
6385
  );
6035
6386
  case "declarative-status":
6036
- return /* @__PURE__ */ jsx40(
6387
+ return /* @__PURE__ */ jsx41(
6037
6388
  DeclarativeStatus,
6038
6389
  {
6039
6390
  onBack: nav.goBackInner,
@@ -6044,7 +6395,7 @@ function AppPanel() {
6044
6395
  }
6045
6396
  );
6046
6397
  case "init-scaffold":
6047
- return /* @__PURE__ */ jsx40(
6398
+ return /* @__PURE__ */ jsx41(
6048
6399
  InitScaffold,
6049
6400
  {
6050
6401
  onBack: nav.goBackInner,
@@ -6055,18 +6406,30 @@ function AppPanel() {
6055
6406
  isInputActive: isActive
6056
6407
  }
6057
6408
  );
6409
+ case "script-picker":
6410
+ return /* @__PURE__ */ jsx41(
6411
+ ScriptPicker,
6412
+ {
6413
+ onNavigate: nav.navigateInner,
6414
+ onBack: nav.goBackInner,
6415
+ width: w,
6416
+ height: mainContentHeight,
6417
+ panelMode: true,
6418
+ isInputActive: isActive
6419
+ }
6420
+ );
6058
6421
  default:
6059
- return /* @__PURE__ */ jsxs38(Text39, { color: "red", children: [
6422
+ return /* @__PURE__ */ jsxs39(Text40, { color: "red", children: [
6060
6423
  "Unknown screen: ",
6061
6424
  nav.innerScreen
6062
6425
  ] });
6063
6426
  }
6064
6427
  };
6065
6428
  if (modal.isOpen) {
6066
- return /* @__PURE__ */ jsx40(Box37, { flexDirection: "column", width, height, children: /* @__PURE__ */ jsx40(Modal, { title: modal.modalTitle, width, height, children: modal.modalContent }) });
6429
+ return /* @__PURE__ */ jsx41(Box38, { flexDirection: "column", width, height, children: /* @__PURE__ */ jsx41(Modal, { title: modal.modalTitle, width, height, children: modal.modalContent }) });
6067
6430
  }
6068
- const header = /* @__PURE__ */ jsx40(GhostBanner, { width, compact: true });
6069
- const sidebar = /* @__PURE__ */ jsx40(
6431
+ const header = /* @__PURE__ */ jsx41(GhostBanner, { width, compact: true });
6432
+ const sidebar = /* @__PURE__ */ jsx41(
6070
6433
  Panel,
6071
6434
  {
6072
6435
  id: "sidebar",
@@ -6074,7 +6437,7 @@ function AppPanel() {
6074
6437
  width: Math.max(20, Math.min(35, Math.floor(width * 0.3))),
6075
6438
  height: Math.max(5, height - bannerHeight - 1),
6076
6439
  focused: focus.isSidebarFocused,
6077
- children: /* @__PURE__ */ jsx40(
6440
+ children: /* @__PURE__ */ jsx41(
6078
6441
  Sidebar,
6079
6442
  {
6080
6443
  items: sidebarItems,
@@ -6087,7 +6450,7 @@ function AppPanel() {
6087
6450
  )
6088
6451
  }
6089
6452
  );
6090
- const main2 = /* @__PURE__ */ jsx40(
6453
+ const main2 = /* @__PURE__ */ jsx41(
6091
6454
  Panel,
6092
6455
  {
6093
6456
  id: "main",
@@ -6098,8 +6461,8 @@ function AppPanel() {
6098
6461
  children: renderMainContent()
6099
6462
  }
6100
6463
  );
6101
- const footer = /* @__PURE__ */ jsx40(PanelFooter, { hints: footerHints, width });
6102
- return /* @__PURE__ */ jsx40(
6464
+ const footer = /* @__PURE__ */ jsx41(PanelFooter, { hints: footerHints, width });
6465
+ return /* @__PURE__ */ jsx41(
6103
6466
  PanelLayout,
6104
6467
  {
6105
6468
  header,
@@ -6263,19 +6626,19 @@ function printCliHelp() {
6263
6626
  import pc3 from "picocolors";
6264
6627
 
6265
6628
  // src/apps/ops.ts
6266
- import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
6629
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync2 } from "fs";
6267
6630
  import { mkdtemp, readdir, stat } from "fs/promises";
6268
- import { dirname, join as join3, resolve } from "path";
6631
+ import { dirname, join as join4, resolve } from "path";
6269
6632
  import { tmpdir } from "os";
6270
6633
  import pc2 from "picocolors";
6271
6634
 
6272
6635
  // src/apps/bootstrapPaths.ts
6273
6636
  import { homedir as homedir2 } from "os";
6274
- import { join as join2 } from "path";
6637
+ import { join as join3 } from "path";
6275
6638
  function getOpsBootstrapPayloadPath() {
6276
6639
  const home = homedir2();
6277
6640
  if (process.platform === "darwin") {
6278
- return join2(
6641
+ return join3(
6279
6642
  home,
6280
6643
  "Library",
6281
6644
  "Application Support",
@@ -6285,10 +6648,10 @@ function getOpsBootstrapPayloadPath() {
6285
6648
  );
6286
6649
  }
6287
6650
  if (process.platform === "win32") {
6288
- const appData = process.env.APPDATA ?? join2(home, "AppData", "Roaming");
6289
- return join2(appData, "ops", "bootstrap", "supabase.json");
6651
+ const appData = process.env.APPDATA ?? join3(home, "AppData", "Roaming");
6652
+ return join3(appData, "ops", "bootstrap", "supabase.json");
6290
6653
  }
6291
- return join2(home, ".config", "ops", "bootstrap", "supabase.json");
6654
+ return join3(home, ".config", "ops", "bootstrap", "supabase.json");
6292
6655
  }
6293
6656
 
6294
6657
  // src/apps/opsRelease.ts
@@ -6560,9 +6923,9 @@ async function promptSelect(label, options, defaultValue) {
6560
6923
  }
6561
6924
 
6562
6925
  // src/apps/ops.ts
6563
- var LINK_REF_FILE = join3("supabase", ".temp", "project-ref");
6926
+ var LINK_REF_FILE = join4("supabase", ".temp", "project-ref");
6564
6927
  function isOpsProjectRoot(candidate) {
6565
- return existsSync(join3(candidate, "src-tauri", "tauri.conf.json")) && existsSync(join3(candidate, "supabase", "migrations")) && existsSync(join3(candidate, "package.json"));
6928
+ return existsSync2(join4(candidate, "src-tauri", "tauri.conf.json")) && existsSync2(join4(candidate, "supabase", "migrations")) && existsSync2(join4(candidate, "package.json"));
6566
6929
  }
6567
6930
  function findNearestOpsRoot(startDir) {
6568
6931
  let currentDir = resolve(startDir);
@@ -6570,7 +6933,7 @@ function findNearestOpsRoot(startDir) {
6570
6933
  if (isOpsProjectRoot(currentDir)) {
6571
6934
  return currentDir;
6572
6935
  }
6573
- const siblingCandidate = join3(currentDir, "ops");
6936
+ const siblingCandidate = join4(currentDir, "ops");
6574
6937
  if (isOpsProjectRoot(siblingCandidate)) {
6575
6938
  return siblingCandidate;
6576
6939
  }
@@ -6582,10 +6945,10 @@ function findNearestOpsRoot(startDir) {
6582
6945
  }
6583
6946
  }
6584
6947
  function readEnvFile(envPath) {
6585
- if (!existsSync(envPath)) {
6948
+ if (!existsSync2(envPath)) {
6586
6949
  return {};
6587
6950
  }
6588
- const content = readFileSync(envPath, "utf-8");
6951
+ const content = readFileSync2(envPath, "utf-8");
6589
6952
  const entries = {};
6590
6953
  for (const line of content.split("\n")) {
6591
6954
  const trimmed = line.trim();
@@ -6616,11 +6979,11 @@ function assertProjectRoot(projectRoot) {
6616
6979
  return projectRoot;
6617
6980
  }
6618
6981
  function getLinkedProjectRef(projectRoot) {
6619
- const refPath = join3(projectRoot, LINK_REF_FILE);
6620
- if (!existsSync(refPath)) {
6982
+ const refPath = join4(projectRoot, LINK_REF_FILE);
6983
+ if (!existsSync2(refPath)) {
6621
6984
  return null;
6622
6985
  }
6623
- const value = readFileSync(refPath, "utf-8").trim();
6986
+ const value = readFileSync2(refPath, "utf-8").trim();
6624
6987
  return value || null;
6625
6988
  }
6626
6989
  function getDbPasswordArgs() {
@@ -6674,7 +7037,7 @@ async function ensureSupabaseLink(projectRoot, forceRelink = false) {
6674
7037
  );
6675
7038
  }
6676
7039
  async function collectSupabaseConfig(projectRoot) {
6677
- const envPath = projectRoot ? join3(projectRoot, ".env.local") : void 0;
7040
+ const envPath = projectRoot ? join4(projectRoot, ".env.local") : void 0;
6678
7041
  const currentEnv = envPath ? readEnvFile(envPath) : {};
6679
7042
  const currentRef = projectRoot ? getLinkedProjectRef(projectRoot) : null;
6680
7043
  const url = await promptText("Supabase URL", {
@@ -6696,7 +7059,7 @@ async function collectSupabaseConfig(projectRoot) {
6696
7059
  };
6697
7060
  }
6698
7061
  function writeOpsEnv(projectRoot, config2) {
6699
- const envPath = join3(projectRoot, ".env.local");
7062
+ const envPath = join4(projectRoot, ".env.local");
6700
7063
  const currentEnv = readEnvFile(envPath);
6701
7064
  const nextEnv = {
6702
7065
  ...currentEnv,
@@ -6896,7 +7259,7 @@ async function extractArchive(archivePath, outputDir) {
6896
7259
  async function findFirstAppBundle(dir) {
6897
7260
  const entries = await readdir(dir);
6898
7261
  for (const entry of entries) {
6899
- const fullPath = join3(dir, entry);
7262
+ const fullPath = join4(dir, entry);
6900
7263
  const entryStat = await stat(fullPath);
6901
7264
  if (entryStat.isDirectory() && entry.endsWith(".app")) {
6902
7265
  return fullPath;
@@ -6912,9 +7275,9 @@ async function findFirstAppBundle(dir) {
6912
7275
  }
6913
7276
  async function deployMacosApp(context, options) {
6914
7277
  const artifact = await resolveOpsMacosArtifact(context.options);
6915
- const tempRoot = await mkdtemp(join3(tmpdir(), "polter-ops-"));
6916
- const archivePath = join3(tempRoot, artifact.fileName);
6917
- const extractDir = join3(tempRoot, "extract");
7278
+ const tempRoot = await mkdtemp(join4(tmpdir(), "polter-ops-"));
7279
+ const archivePath = join4(tempRoot, artifact.fileName);
7280
+ const extractDir = join4(tempRoot, "extract");
6918
7281
  mkdirSync(extractDir, { recursive: true });
6919
7282
  if (artifact.source === "github-release") {
6920
7283
  const releaseLabel = artifact.tagName ?? "latest";
@@ -6943,13 +7306,13 @@ async function deployMacosApp(context, options) {
6943
7306
  }
6944
7307
  const installDir = context.options.installDir ?? "/Applications";
6945
7308
  mkdirSync(installDir, { recursive: true });
6946
- const destination = join3(installDir, "ops.app");
6947
- if (options.requireExistingInstallation && !existsSync(destination)) {
7309
+ const destination = join4(installDir, "ops.app");
7310
+ if (options.requireExistingInstallation && !existsSync2(destination)) {
6948
7311
  throw new Error(
6949
7312
  `No existing Ops installation was found at ${destination}. Run \`polter app install ops\` first.`
6950
7313
  );
6951
7314
  }
6952
- if (existsSync(destination)) {
7315
+ if (existsSync2(destination)) {
6953
7316
  const confirmed = context.options.yes || await promptConfirm(`Replace existing installation at ${destination}?`, false);
6954
7317
  if (!confirmed) {
6955
7318
  process.stdout.write(`${pc2.yellow("Cancelled.")}
@@ -7213,11 +7576,14 @@ Apply completed with ${errors.length} error(s).
7213
7576
  process.exit(result.exitCode ?? 0);
7214
7577
  }
7215
7578
  const AppComponent2 = parsed.classic ? AppClassic : AppPanel;
7216
- render(React27.createElement(AppComponent2));
7217
- return;
7579
+ const inst = render(React28.createElement(AppComponent2));
7580
+ await inst.waitUntilExit();
7581
+ process.exit(0);
7218
7582
  }
7219
7583
  const AppComponent = parsed.classic ? AppClassic : AppPanel;
7220
- render(React27.createElement(AppComponent));
7584
+ const instance = render(React28.createElement(AppComponent));
7585
+ await instance.waitUntilExit();
7586
+ process.exit(0);
7221
7587
  }
7222
7588
  main().catch((error) => {
7223
7589
  const message = error instanceof Error ? error.message : String(error);