@polterware/polter 0.1.1 → 0.2.1

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
@@ -24,14 +24,14 @@ import {
24
24
  runSupabaseCommand,
25
25
  savePipeline,
26
26
  writeProjectConfig
27
- } from "./chunk-TWWRDI3Q.js";
27
+ } from "./chunk-3XNNC5AW.js";
28
28
 
29
29
  // src/index.tsx
30
- import React19 from "react";
30
+ import React20 from "react";
31
31
  import { render } from "ink";
32
32
 
33
33
  // src/app.tsx
34
- import { Box as Box21, Text as Text23, useApp } from "ink";
34
+ import { Box as Box22, Text as Text26, useApp } from "ink";
35
35
 
36
36
  // src/hooks/useNavigation.ts
37
37
  import { useState, useCallback } from "react";
@@ -403,7 +403,8 @@ function SelectList({
403
403
  boxedSections = false,
404
404
  width = 80,
405
405
  isInputActive = true,
406
- arrowNavigation = false
406
+ arrowNavigation = false,
407
+ panelFocused = true
407
408
  }) {
408
409
  const labelWidth = labelWidthProp ?? Math.max(16, Math.floor(width * 0.45));
409
410
  const isNarrow = width < 50;
@@ -564,7 +565,7 @@ function SelectList({
564
565
  {
565
566
  flexDirection: "column",
566
567
  borderStyle: "round",
567
- borderColor: inkColors.accent,
568
+ borderColor: panelFocused ? inkColors.accent : panel.borderDim,
568
569
  borderDimColor: !hasSelectedRow && !isPinnedSection,
569
570
  paddingX: 1,
570
571
  children: [
@@ -723,7 +724,8 @@ function buildHomeItems({
723
724
  activeFeature,
724
725
  pinnedCommands,
725
726
  pinnedRuns,
726
- showPinnedSection = true
727
+ showPinnedSection = true,
728
+ showFeatureHeader = true
727
729
  }) {
728
730
  const items = [];
729
731
  if (showPinnedSection && (pinnedRuns.length > 0 || pinnedCommands.length > 0)) {
@@ -736,15 +738,17 @@ function buildHomeItems({
736
738
  });
737
739
  items.push(...buildPinnedOnlyItems(pinnedCommands, pinnedRuns));
738
740
  }
739
- items.push({
740
- id: "section-commands",
741
- value: "__section_commands__",
742
- label: `\u{1F4C2} ${activeFeature.label} Commands`,
743
- kind: "header",
744
- selectable: false
745
- });
746
- const toolOrder = { supabase: 0, vercel: 1, gh: 2, pulumi: 3 };
747
- const toolIcons = { supabase: "\u{1F7E2}", vercel: "\u26AA", gh: "\u{1F535}", pulumi: "\u{1F7E3}" };
741
+ if (showFeatureHeader) {
742
+ items.push({
743
+ id: "section-commands",
744
+ value: "__section_commands__",
745
+ label: `\u{1F4C2} ${activeFeature.label} Commands`,
746
+ kind: "header",
747
+ selectable: false
748
+ });
749
+ }
750
+ const toolOrder = { supabase: 0, vercel: 1, gh: 2, git: 3 };
751
+ const toolIcons = { supabase: "\u{1F7E2}", vercel: "\u26AA", gh: "\u{1F535}", git: "\u{1F7E0}" };
748
752
  const grouped = /* @__PURE__ */ new Map();
749
753
  for (const cmd of activeFeature.commands) {
750
754
  const existing = grouped.get(cmd.tool) ?? [];
@@ -931,7 +935,7 @@ function Home({
931
935
 
932
936
  // src/screens/CommandArgs.tsx
933
937
  import { useEffect as useEffect4, useMemo as useMemo3, useState as useState6 } from "react";
934
- import { Box as Box7, Text as Text8 } from "ink";
938
+ import { Box as Box7, Text as Text8, useInput as useInput4 } from "ink";
935
939
 
936
940
  // src/components/TextPrompt.tsx
937
941
  import { useState as useState5 } from "react";
@@ -943,7 +947,11 @@ function TextPrompt({
943
947
  placeholder,
944
948
  onSubmit,
945
949
  onCancel,
946
- validate
950
+ validate,
951
+ arrowNavigation = false,
952
+ isInputActive = true,
953
+ boxed = false,
954
+ focused = true
947
955
  }) {
948
956
  const [value, setValue] = useState5("");
949
957
  const [error, setError] = useState5();
@@ -951,7 +959,10 @@ function TextPrompt({
951
959
  if (key.escape && onCancel) {
952
960
  onCancel();
953
961
  }
954
- });
962
+ if (arrowNavigation && key.leftArrow && value === "" && onCancel) {
963
+ onCancel();
964
+ }
965
+ }, { isActive: isInputActive });
955
966
  const handleSubmit = (val) => {
956
967
  if (validate) {
957
968
  const err = validate(val);
@@ -963,7 +974,7 @@ function TextPrompt({
963
974
  setError(void 0);
964
975
  onSubmit(val);
965
976
  };
966
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
977
+ const content = /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
967
978
  /* @__PURE__ */ jsxs6(Box6, { gap: 1, children: [
968
979
  /* @__PURE__ */ jsx6(Text6, { color: inkColors.accent, bold: true, children: "?" }),
969
980
  /* @__PURE__ */ jsx6(Text6, { children: label })
@@ -988,6 +999,10 @@ function TextPrompt({
988
999
  error
989
1000
  ] }) })
990
1001
  ] });
1002
+ if (boxed) {
1003
+ return /* @__PURE__ */ jsx6(Box6, { borderStyle: "round", borderColor: focused ? inkColors.accent : panel.borderDim, paddingX: 1, children: content });
1004
+ }
1005
+ return content;
991
1006
  }
992
1007
 
993
1008
  // src/components/ToolBadge.tsx
@@ -997,13 +1012,13 @@ var toolColors = {
997
1012
  supabase: "#3ECF8E",
998
1013
  gh: "#58A6FF",
999
1014
  vercel: "#FFFFFF",
1000
- pulumi: "#8B5CF6"
1015
+ git: "#F05032"
1001
1016
  };
1002
1017
  var toolLabels = {
1003
1018
  supabase: "supabase",
1004
1019
  gh: "github",
1005
1020
  vercel: "vercel",
1006
- pulumi: "pulumi"
1021
+ git: "git"
1007
1022
  };
1008
1023
  function ToolBadge({ tool }) {
1009
1024
  return /* @__PURE__ */ jsx7(Text7, { color: toolColors[tool], dimColor: true, children: toolLabels[tool] });
@@ -1073,11 +1088,6 @@ function buildCommandArgItems({
1073
1088
  label: "Custom args...",
1074
1089
  hint: "Type any arguments manually",
1075
1090
  kind: "action"
1076
- },
1077
- {
1078
- value: "__back__",
1079
- label: "\u2190 Back to menu",
1080
- kind: "action"
1081
1091
  }
1082
1092
  ];
1083
1093
  }
@@ -1120,25 +1130,20 @@ function CommandArgs({
1120
1130
  tool: resolvedTool
1121
1131
  });
1122
1132
  };
1133
+ useInput4((_input, key) => {
1134
+ if (!command && (key.escape || key.leftArrow)) {
1135
+ onBack();
1136
+ }
1137
+ }, { isActive: isInputActive && !command });
1123
1138
  if (!command) {
1124
1139
  return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1125
- /* @__PURE__ */ jsx8(Box7, { marginBottom: 1, children: /* @__PURE__ */ jsx8(Text8, { color: "red", children: "Command not provided." }) }),
1126
- /* @__PURE__ */ jsx8(
1127
- SelectList,
1128
- {
1129
- items: [{ value: "__back__", label: "\u2190 Back to menu" }],
1130
- onSelect: onBack,
1131
- onCancel: onBack,
1132
- width,
1133
- isInputActive,
1134
- arrowNavigation: panelMode
1135
- }
1136
- )
1140
+ /* @__PURE__ */ jsx8(Text8, { color: "red", children: "Command not provided." }),
1141
+ /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: "Press Esc or \u2190 to go back" })
1137
1142
  ] });
1138
1143
  }
1139
1144
  if (phase === "custom") {
1140
1145
  const toolLabel = resolvedTool === "supabase" ? "supabase" : resolvedTool;
1141
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1146
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1142
1147
  /* @__PURE__ */ jsxs7(Box7, { marginBottom: 1, gap: 1, children: [
1143
1148
  /* @__PURE__ */ jsx8(Text8, { color: inkColors.accent, bold: true, children: "Command" }),
1144
1149
  /* @__PURE__ */ jsx8(Text8, { children: command }),
@@ -1159,7 +1164,11 @@ function CommandArgs({
1159
1164
  return;
1160
1165
  }
1161
1166
  onBack();
1162
- }
1167
+ },
1168
+ arrowNavigation: panelMode,
1169
+ isInputActive,
1170
+ boxed: panelMode,
1171
+ focused: isInputActive
1163
1172
  }
1164
1173
  ),
1165
1174
  !panelMode && /* @__PURE__ */ jsx8(StatusBar, { hint: "Type args \xB7 Enter to continue \xB7 Esc to go back", width })
@@ -1179,7 +1188,7 @@ function CommandArgs({
1179
1188
  }),
1180
1189
  [command, legacySuggestions, pinnedRuns]
1181
1190
  );
1182
- return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
1191
+ return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1183
1192
  /* @__PURE__ */ jsxs7(Box7, { marginBottom: 1, gap: 1, children: [
1184
1193
  /* @__PURE__ */ jsx8(Text8, { color: inkColors.accent, bold: true, children: "Command" }),
1185
1194
  /* @__PURE__ */ jsx8(Text8, { children: command }),
@@ -1238,9 +1247,10 @@ function CommandArgs({
1238
1247
  },
1239
1248
  onCancel: onBack,
1240
1249
  boxedSections: true,
1241
- width,
1250
+ width: panelMode ? Math.max(20, width - 4) : width,
1242
1251
  isInputActive,
1243
- arrowNavigation: panelMode
1252
+ arrowNavigation: panelMode,
1253
+ panelFocused: isInputActive
1244
1254
  }
1245
1255
  ),
1246
1256
  !panelMode && /* @__PURE__ */ jsx8(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 p pin \xB7 Esc back", width })
@@ -1255,24 +1265,28 @@ function CustomCommand({
1255
1265
  onNavigate,
1256
1266
  onBack,
1257
1267
  width = 80,
1268
+ height = 24,
1258
1269
  panelMode = false,
1259
1270
  isInputActive = true
1260
1271
  }) {
1261
1272
  const [phase, setPhase] = useState7("tool-select");
1262
1273
  const [selectedTool, setSelectedTool] = useState7("supabase");
1263
1274
  if (phase === "tool-select") {
1264
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1265
- /* @__PURE__ */ jsx9(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u270F\uFE0F Custom Command" }) }),
1266
- /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Select tool:" }),
1275
+ const toolItems = [
1276
+ { value: "__section__", label: "\u{1F6E0} Select Tool", kind: "header", selectable: false },
1277
+ { value: "supabase", label: "Supabase CLI", hint: "supabase ...", kind: "action" },
1278
+ { value: "gh", label: "GitHub CLI", hint: "gh ...", kind: "action" },
1279
+ { value: "vercel", label: "Vercel CLI", hint: "vercel ...", kind: "action" },
1280
+ { value: "git", label: "Git", hint: "git ...", kind: "action" },
1281
+ ...!panelMode ? [{ value: "__back__", label: "\u2190 Back" }] : []
1282
+ ];
1283
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1284
+ !panelMode && /* @__PURE__ */ jsx9(Box8, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u270F\uFE0F Custom Command" }) }),
1285
+ !panelMode && /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "Select tool:" }),
1267
1286
  /* @__PURE__ */ jsx9(
1268
1287
  SelectList,
1269
1288
  {
1270
- items: [
1271
- { value: "supabase", label: "Supabase CLI", hint: "supabase ..." },
1272
- { value: "gh", label: "GitHub CLI", hint: "gh ..." },
1273
- { value: "vercel", label: "Vercel CLI", hint: "vercel ..." },
1274
- { value: "__back__", label: "\u2190 Back" }
1275
- ],
1289
+ items: toolItems,
1276
1290
  onSelect: (value) => {
1277
1291
  if (value === "__back__") {
1278
1292
  onBack();
@@ -1282,16 +1296,19 @@ function CustomCommand({
1282
1296
  setPhase("input");
1283
1297
  },
1284
1298
  onCancel: onBack,
1285
- width,
1299
+ boxedSections: panelMode,
1300
+ width: panelMode ? Math.max(20, width - 4) : width,
1301
+ maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
1286
1302
  isInputActive,
1287
- arrowNavigation: panelMode
1303
+ arrowNavigation: panelMode,
1304
+ panelFocused: isInputActive
1288
1305
  }
1289
1306
  ),
1290
1307
  !panelMode && /* @__PURE__ */ jsx9(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
1291
1308
  ] });
1292
1309
  }
1293
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1294
- /* @__PURE__ */ jsxs8(Box8, { marginBottom: 1, gap: 1, children: [
1310
+ return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1311
+ !panelMode && /* @__PURE__ */ jsxs8(Box8, { marginBottom: 1, gap: 1, children: [
1295
1312
  /* @__PURE__ */ jsx9(Text9, { bold: true, color: inkColors.accent, children: "\u270F\uFE0F Custom Command" }),
1296
1313
  /* @__PURE__ */ jsxs8(Text9, { dimColor: true, children: [
1297
1314
  "(",
@@ -1312,7 +1329,11 @@ function CustomCommand({
1312
1329
  const args = value.split(" ").filter(Boolean);
1313
1330
  onNavigate("flag-selection", { args, tool: selectedTool });
1314
1331
  },
1315
- onCancel: () => setPhase("tool-select")
1332
+ onCancel: () => setPhase("tool-select"),
1333
+ arrowNavigation: panelMode,
1334
+ isInputActive,
1335
+ boxed: panelMode,
1336
+ focused: isInputActive
1316
1337
  }
1317
1338
  ),
1318
1339
  !panelMode && /* @__PURE__ */ jsx9(StatusBar, { hint: "Type a command \xB7 Enter to continue \xB7 Esc to go back", width })
@@ -1320,20 +1341,22 @@ function CustomCommand({
1320
1341
  }
1321
1342
 
1322
1343
  // src/screens/FlagSelection.tsx
1323
- import { Box as Box10 } from "ink";
1344
+ import { Box as Box10, Text as Text11 } from "ink";
1324
1345
 
1325
1346
  // src/components/FlagToggle.tsx
1326
1347
  import { useState as useState8 } from "react";
1327
- import { Box as Box9, Text as Text10, useInput as useInput4 } from "ink";
1348
+ import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
1328
1349
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1329
1350
  function FlagToggle({
1330
1351
  flags,
1331
1352
  onSubmit,
1332
- onCancel
1353
+ onCancel,
1354
+ isInputActive = true,
1355
+ arrowNavigation = false
1333
1356
  }) {
1334
1357
  const [cursor, setCursor] = useState8(0);
1335
1358
  const [selected, setSelected] = useState8(/* @__PURE__ */ new Set());
1336
- useInput4((input2, key) => {
1359
+ useInput5((input2, key) => {
1337
1360
  if (key.upArrow || input2 === "k") {
1338
1361
  setCursor((prev) => prev > 0 ? prev - 1 : flags.length - 1);
1339
1362
  }
@@ -1352,17 +1375,24 @@ function FlagToggle({
1352
1375
  return next;
1353
1376
  });
1354
1377
  }
1355
- if (key.return) {
1378
+ if (key.return || arrowNavigation && key.rightArrow) {
1356
1379
  onSubmit(Array.from(selected));
1357
1380
  }
1358
1381
  if (key.escape && onCancel) {
1359
1382
  onCancel();
1360
1383
  }
1361
- });
1384
+ if (arrowNavigation && key.leftArrow && onCancel) {
1385
+ onCancel();
1386
+ }
1387
+ }, { isActive: isInputActive });
1362
1388
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1363
1389
  /* @__PURE__ */ jsxs9(Box9, { marginBottom: 1, children: [
1364
1390
  /* @__PURE__ */ jsx10(Text10, { bold: true, color: inkColors.accent, children: "\u2691 Global Flags" }),
1365
- /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: " (Space to toggle, Enter to confirm)" })
1391
+ /* @__PURE__ */ jsxs9(Text10, { dimColor: true, children: [
1392
+ " (Space to toggle, ",
1393
+ arrowNavigation ? "\u2192" : "Enter",
1394
+ " to confirm)"
1395
+ ] })
1366
1396
  ] }),
1367
1397
  flags.map((flag, i) => {
1368
1398
  const isActive = cursor === i;
@@ -1388,7 +1418,7 @@ function FlagToggle({
1388
1418
  flag.hint && /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: flag.hint })
1389
1419
  ] }, flag.value);
1390
1420
  }),
1391
- /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: selected.size > 0 ? `${selected.size} flag${selected.size > 1 ? "s" : ""} selected` : "No flags selected (Enter to skip)" }) })
1421
+ /* @__PURE__ */ jsx10(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: selected.size > 0 ? `${selected.size} flag${selected.size > 1 ? "s" : ""} selected` : `No flags selected (${arrowNavigation ? "\u2192" : "Enter"} to skip)` }) })
1392
1422
  ] });
1393
1423
  }
1394
1424
 
@@ -1400,6 +1430,7 @@ function FlagSelection({
1400
1430
  onNavigate,
1401
1431
  onBack,
1402
1432
  width = 80,
1433
+ height = 24,
1403
1434
  panelMode = false,
1404
1435
  isInputActive = true
1405
1436
  }) {
@@ -1408,8 +1439,36 @@ function FlagSelection({
1408
1439
  onNavigate("confirm-execute", { args, tool });
1409
1440
  return /* @__PURE__ */ jsx11(Box10, {});
1410
1441
  }
1411
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
1412
- /* @__PURE__ */ jsx11(
1442
+ const cmdDisplay = `${tool} ${args.join(" ")}`;
1443
+ return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1444
+ panelMode && /* @__PURE__ */ jsx11(Box10, { marginBottom: 1, gap: 1, children: /* @__PURE__ */ jsxs10(Text11, { color: inkColors.accent, bold: true, children: [
1445
+ "\u25B6",
1446
+ " ",
1447
+ cmdDisplay
1448
+ ] }) }),
1449
+ panelMode ? /* @__PURE__ */ jsx11(
1450
+ Box10,
1451
+ {
1452
+ flexDirection: "column",
1453
+ borderStyle: "round",
1454
+ borderColor: isInputActive ? inkColors.accent : panel.borderDim,
1455
+ borderDimColor: true,
1456
+ paddingX: 1,
1457
+ children: /* @__PURE__ */ jsx11(
1458
+ FlagToggle,
1459
+ {
1460
+ flags,
1461
+ onSubmit: (selectedFlags) => {
1462
+ const finalArgs = selectedFlags.length > 0 ? [...args, ...selectedFlags] : args;
1463
+ onNavigate("confirm-execute", { args: finalArgs, tool });
1464
+ },
1465
+ onCancel: onBack,
1466
+ isInputActive,
1467
+ arrowNavigation: panelMode
1468
+ }
1469
+ )
1470
+ }
1471
+ ) : /* @__PURE__ */ jsx11(
1413
1472
  FlagToggle,
1414
1473
  {
1415
1474
  flags,
@@ -1417,7 +1476,9 @@ function FlagSelection({
1417
1476
  const finalArgs = selectedFlags.length > 0 ? [...args, ...selectedFlags] : args;
1418
1477
  onNavigate("confirm-execute", { args: finalArgs, tool });
1419
1478
  },
1420
- onCancel: onBack
1479
+ onCancel: onBack,
1480
+ isInputActive,
1481
+ arrowNavigation: panelMode
1421
1482
  }
1422
1483
  ),
1423
1484
  !panelMode && /* @__PURE__ */ jsx11(StatusBar, { hint: "Space toggle \xB7 Enter confirm \xB7 Esc back", width })
@@ -1425,33 +1486,44 @@ function FlagSelection({
1425
1486
  }
1426
1487
 
1427
1488
  // src/screens/CommandExecution.tsx
1428
- import { useState as useState10, useEffect as useEffect5 } from "react";
1429
- import { Box as Box12, Text as Text14 } from "ink";
1489
+ import { useState as useState11, useEffect as useEffect5 } from "react";
1490
+ import { Box as Box13, Text as Text17 } from "ink";
1430
1491
 
1431
1492
  // src/components/Spinner.tsx
1432
- import { Text as Text11 } from "ink";
1493
+ import { Text as Text12 } from "ink";
1433
1494
  import InkSpinner from "ink-spinner";
1434
1495
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1435
1496
  function Spinner({
1436
1497
  label = "Running...",
1437
1498
  color = inkColors.accent
1438
1499
  }) {
1439
- return /* @__PURE__ */ jsxs11(Text11, { children: [
1440
- /* @__PURE__ */ jsx12(Text11, { color, children: /* @__PURE__ */ jsx12(InkSpinner, { type: "dots" }) }),
1500
+ return /* @__PURE__ */ jsxs11(Text12, { children: [
1501
+ /* @__PURE__ */ jsx12(Text12, { color, children: /* @__PURE__ */ jsx12(InkSpinner, { type: "dots" }) }),
1441
1502
  " ",
1442
- /* @__PURE__ */ jsx12(Text11, { children: label })
1503
+ /* @__PURE__ */ jsx12(Text12, { children: label })
1443
1504
  ] });
1444
1505
  }
1445
1506
 
1446
1507
  // src/components/ConfirmPrompt.tsx
1447
- import { Box as Box11, Text as Text12, useInput as useInput5 } from "ink";
1508
+ import { Box as Box11, Text as Text13, useInput as useInput6 } from "ink";
1448
1509
  import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
1449
1510
  function ConfirmPrompt({
1450
1511
  message,
1451
1512
  defaultValue = true,
1452
- onConfirm
1513
+ onConfirm,
1514
+ onCancel,
1515
+ isInputActive = true,
1516
+ arrowNavigation = false
1453
1517
  }) {
1454
- useInput5((input2) => {
1518
+ useInput6((input2, key) => {
1519
+ if (key.escape && onCancel) {
1520
+ onCancel();
1521
+ return;
1522
+ }
1523
+ if (arrowNavigation && key.leftArrow && onCancel) {
1524
+ onCancel();
1525
+ return;
1526
+ }
1455
1527
  if (input2 === "y" || input2 === "Y") {
1456
1528
  onConfirm(true);
1457
1529
  } else if (input2 === "n" || input2 === "N") {
@@ -1459,16 +1531,16 @@ function ConfirmPrompt({
1459
1531
  } else if (input2 === "\r") {
1460
1532
  onConfirm(defaultValue);
1461
1533
  }
1462
- });
1534
+ }, { isActive: isInputActive });
1463
1535
  return /* @__PURE__ */ jsxs12(Box11, { gap: 1, children: [
1464
- /* @__PURE__ */ jsx13(Text12, { color: inkColors.accent, bold: true, children: "?" }),
1465
- /* @__PURE__ */ jsx13(Text12, { children: message }),
1466
- /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: defaultValue ? "(Y/n)" : "(y/N)" })
1536
+ /* @__PURE__ */ jsx13(Text13, { color: inkColors.accent, bold: true, children: "?" }),
1537
+ /* @__PURE__ */ jsx13(Text13, { children: message }),
1538
+ /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: defaultValue ? "(Y/n)" : "(y/N)" })
1467
1539
  ] });
1468
1540
  }
1469
1541
 
1470
1542
  // src/components/Divider.tsx
1471
- import { Text as Text13 } from "ink";
1543
+ import { Text as Text14 } from "ink";
1472
1544
  import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
1473
1545
  function Divider({
1474
1546
  label,
@@ -1480,7 +1552,7 @@ function Divider({
1480
1552
  const sideLen = Math.max(2, Math.floor((effectiveWidth - labelLen) / 2));
1481
1553
  const left = "\u2500".repeat(sideLen);
1482
1554
  const right = "\u2500".repeat(sideLen);
1483
- return /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
1555
+ return /* @__PURE__ */ jsxs13(Text14, { dimColor: true, children: [
1484
1556
  left,
1485
1557
  " ",
1486
1558
  label,
@@ -1488,14 +1560,82 @@ function Divider({
1488
1560
  right
1489
1561
  ] });
1490
1562
  }
1491
- return /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "\u2500".repeat(effectiveWidth) });
1563
+ return /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "\u2500".repeat(effectiveWidth) });
1564
+ }
1565
+
1566
+ // src/components/CommandOutput.tsx
1567
+ import { Text as Text16 } from "ink";
1568
+
1569
+ // src/components/ScrollableBox.tsx
1570
+ import { useState as useState9 } from "react";
1571
+ import { Box as Box12, Text as Text15, useInput as useInput7 } from "ink";
1572
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1573
+ function ScrollableBox({
1574
+ height,
1575
+ isActive = true,
1576
+ children
1577
+ }) {
1578
+ const totalItems = children.length;
1579
+ const [scrollOffset, setScrollOffset] = useState9(0);
1580
+ const visibleCount = Math.max(1, height - 2);
1581
+ useInput7(
1582
+ (input2, key) => {
1583
+ if (key.upArrow || input2 === "k") {
1584
+ setScrollOffset((prev) => Math.max(0, prev - 1));
1585
+ }
1586
+ if (key.downArrow || input2 === "j") {
1587
+ setScrollOffset((prev) => Math.min(Math.max(0, totalItems - visibleCount), prev + 1));
1588
+ }
1589
+ },
1590
+ { isActive }
1591
+ );
1592
+ const showScrollUp = scrollOffset > 0;
1593
+ const showScrollDown = scrollOffset + visibleCount < totalItems;
1594
+ const visible = children.slice(scrollOffset, scrollOffset + visibleCount);
1595
+ return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", height, children: [
1596
+ showScrollUp && /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: " \u2191 more" }),
1597
+ visible,
1598
+ showScrollDown && /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: " \u2193 more" })
1599
+ ] });
1600
+ }
1601
+
1602
+ // src/lib/ansi.ts
1603
+ var ANSI_RE = (
1604
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: intentional ANSI stripping
1605
+ /[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]*)*)?\u0007)|(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g
1606
+ );
1607
+ function stripAnsi(text) {
1608
+ return text.replace(ANSI_RE, "");
1609
+ }
1610
+
1611
+ // src/components/CommandOutput.tsx
1612
+ import { jsx as jsx16 } from "react/jsx-runtime";
1613
+ function cleanLines(raw) {
1614
+ const stripped = stripAnsi(raw);
1615
+ return stripped.replace(/\r/g, "").split("\n").filter((line) => line.length > 0);
1616
+ }
1617
+ function CommandOutput({
1618
+ stdout,
1619
+ stderr,
1620
+ height,
1621
+ isActive = false
1622
+ }) {
1623
+ const outLines = stdout ? cleanLines(stdout) : [];
1624
+ const errLines = stderr ? cleanLines(stderr) : [];
1625
+ if (outLines.length === 0 && errLines.length === 0) {
1626
+ return null;
1627
+ }
1628
+ return /* @__PURE__ */ jsx16(ScrollableBox, { height: Math.max(3, height), isActive, children: [
1629
+ ...outLines.map((line, i) => /* @__PURE__ */ jsx16(Text16, { children: line }, `o-${i}`)),
1630
+ ...errLines.map((line, i) => /* @__PURE__ */ jsx16(Text16, { color: "red", children: line }, `e-${i}`))
1631
+ ] });
1492
1632
  }
1493
1633
 
1494
1634
  // src/hooks/useCommand.ts
1495
- import { useState as useState9, useCallback as useCallback2 } from "react";
1496
- function useCommand(execution = "supabase", cwd = process.cwd()) {
1497
- const [status, setStatus] = useState9("idle");
1498
- const [result, setResult] = useState9(null);
1635
+ import { useState as useState10, useCallback as useCallback2 } from "react";
1636
+ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
1637
+ const [status, setStatus] = useState10("idle");
1638
+ const [result, setResult] = useState10(null);
1499
1639
  const run = useCallback2(async (args) => {
1500
1640
  setStatus("running");
1501
1641
  setResult(null);
@@ -1511,7 +1651,8 @@ function useCommand(execution = "supabase", cwd = process.cwd()) {
1511
1651
  } else {
1512
1652
  resolvedExecution = execution;
1513
1653
  }
1514
- const res = await runCommand(resolvedExecution, args, cwd);
1654
+ const runOpts = options?.quiet ? { quiet: true } : void 0;
1655
+ const res = await runCommand(resolvedExecution, args, cwd, runOpts);
1515
1656
  setResult(res);
1516
1657
  if (res.spawnError || res.exitCode !== null && res.exitCode !== 0) {
1517
1658
  setStatus("error");
@@ -1519,7 +1660,7 @@ function useCommand(execution = "supabase", cwd = process.cwd()) {
1519
1660
  setStatus("success");
1520
1661
  }
1521
1662
  return res;
1522
- }, [cwd, execution]);
1663
+ }, [cwd, execution, options?.quiet]);
1523
1664
  const reset = useCallback2(() => {
1524
1665
  setStatus("idle");
1525
1666
  setResult(null);
@@ -1540,21 +1681,71 @@ async function copyToClipboard(text) {
1540
1681
  });
1541
1682
  }
1542
1683
 
1684
+ // src/lib/errorSuggestions.ts
1685
+ var KNOWN_TOOLS = ["supabase", "gh", "vercel", "git"];
1686
+ var BACKTICK_CMD = /(?:try\s+)?(?:run(?:ning)?|use|execute)\s+`([^`]+)`/gi;
1687
+ var HAVE_YOU_RUN = /have you (?:run|tried|used)\s+((?:supabase|gh|vercel|git)\s+[\w][\w -]*\w)\??/gi;
1688
+ var DID_YOU_MEAN = /did you mean[:\s]+[`']?([a-z][\w -]*\w)[`']?\??/gi;
1689
+ var INDENTED_TOOL_CMD = /^\s{2,}((?:supabase|gh|vercel|git)\s+[\w][\w -]*\w)$/gm;
1690
+ var ARROW_BULLET = /[→•\-*]\s*(?:run:?\s*)?((?:supabase|gh|vercel|git)\s+[\w][\w -]*\w)/gim;
1691
+ var MAX_SUGGESTIONS = 3;
1692
+ function detectTool(rawCommand, fallback) {
1693
+ const first = rawCommand.trim().split(/\s+/)[0]?.toLowerCase();
1694
+ const match = KNOWN_TOOLS.find((t) => t === first);
1695
+ return match ?? fallback;
1696
+ }
1697
+ function parseRawCommand(raw, currentTool) {
1698
+ const trimmed = raw.trim();
1699
+ const tool = detectTool(trimmed, currentTool);
1700
+ const parts = trimmed.split(/\s+/);
1701
+ const args = parts[0]?.toLowerCase() === tool ? parts.slice(1) : parts;
1702
+ const display = `${tool} ${args.join(" ")}`;
1703
+ return { tool, args, display };
1704
+ }
1705
+ function parseErrorSuggestions(stdout, stderr, currentTool) {
1706
+ const combined = stripAnsi(`${stdout}
1707
+ ${stderr}`);
1708
+ const seen = /* @__PURE__ */ new Set();
1709
+ const suggestions = [];
1710
+ const patterns = [BACKTICK_CMD, HAVE_YOU_RUN, DID_YOU_MEAN, INDENTED_TOOL_CMD, ARROW_BULLET];
1711
+ for (const pattern of patterns) {
1712
+ pattern.lastIndex = 0;
1713
+ let match;
1714
+ while ((match = pattern.exec(combined)) !== null) {
1715
+ const raw = match[1];
1716
+ const suggestion = parseRawCommand(raw, currentTool);
1717
+ const key = suggestion.display;
1718
+ if (!seen.has(key)) {
1719
+ seen.add(key);
1720
+ suggestions.push(suggestion);
1721
+ }
1722
+ if (suggestions.length >= MAX_SUGGESTIONS) break;
1723
+ }
1724
+ if (suggestions.length >= MAX_SUGGESTIONS) break;
1725
+ }
1726
+ return suggestions;
1727
+ }
1728
+
1543
1729
  // src/screens/CommandExecution.tsx
1544
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1730
+ import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1545
1731
  function CommandExecution({
1546
1732
  args: initialArgs,
1547
1733
  tool = "supabase",
1548
1734
  onBack,
1735
+ onHome,
1549
1736
  onExit,
1737
+ onRunSuggestion,
1550
1738
  width = 80,
1739
+ height = 24,
1551
1740
  panelMode = false,
1552
1741
  isInputActive = true
1553
1742
  }) {
1554
- const [phase, setPhase] = useState10("confirm");
1555
- const [currentArgs, setCurrentArgs] = useState10(initialArgs);
1556
- const [pinMessage, setPinMessage] = useState10();
1557
- const { status, result, run, reset } = useCommand(tool);
1743
+ const [phase, setPhase] = useState11("confirm");
1744
+ const [currentArgs, setCurrentArgs] = useState11(initialArgs);
1745
+ const [pinMessage, setPinMessage] = useState11();
1746
+ const { status, result, run, reset } = useCommand(tool, process.cwd(), {
1747
+ quiet: panelMode
1748
+ });
1558
1749
  const cmdDisplay = `${tool} ${currentArgs.join(" ")}`;
1559
1750
  const runCommand2 = currentArgs.join(" ");
1560
1751
  useEffect5(() => {
@@ -1575,42 +1766,67 @@ function CommandExecution({
1575
1766
  }
1576
1767
  }, [phase, runCommand2, status]);
1577
1768
  if (phase === "confirm") {
1578
- return /* @__PURE__ */ jsx15(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsx15(
1579
- ConfirmPrompt,
1580
- {
1581
- message: `Execute ${cmdDisplay}?`,
1582
- defaultValue: true,
1583
- onConfirm: (confirmed) => {
1584
- if (confirmed) {
1585
- setPhase("running");
1586
- } else {
1587
- onBack();
1588
- }
1769
+ const confirmContent = /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
1770
+ /* @__PURE__ */ jsxs15(Box13, { marginBottom: 1, gap: 1, children: [
1771
+ /* @__PURE__ */ jsxs15(Text17, { color: inkColors.accent, bold: true, children: [
1772
+ "\u25B6",
1773
+ " ",
1774
+ cmdDisplay
1775
+ ] }),
1776
+ /* @__PURE__ */ jsx17(ToolBadge, { tool })
1777
+ ] }),
1778
+ /* @__PURE__ */ jsx17(
1779
+ ConfirmPrompt,
1780
+ {
1781
+ message: `Execute ${cmdDisplay}?`,
1782
+ defaultValue: true,
1783
+ onConfirm: (confirmed) => {
1784
+ if (confirmed) {
1785
+ setPhase("running");
1786
+ } else {
1787
+ onBack();
1788
+ }
1789
+ },
1790
+ onCancel: onBack,
1791
+ isInputActive,
1792
+ arrowNavigation: panelMode
1589
1793
  }
1794
+ ),
1795
+ /* @__PURE__ */ jsx17(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Enter to execute \xB7 n to cancel" }) })
1796
+ ] });
1797
+ return /* @__PURE__ */ jsx17(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: panelMode ? /* @__PURE__ */ jsx17(
1798
+ Box13,
1799
+ {
1800
+ flexDirection: "column",
1801
+ borderStyle: "round",
1802
+ borderColor: isInputActive ? inkColors.accent : panel.borderDim,
1803
+ borderDimColor: true,
1804
+ paddingX: 1,
1805
+ children: confirmContent
1590
1806
  }
1591
- ) });
1807
+ ) : confirmContent });
1592
1808
  }
1593
1809
  if (phase === "running") {
1594
- return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", children: [
1595
- /* @__PURE__ */ jsx15(Divider, { width }),
1596
- /* @__PURE__ */ jsxs14(Box12, { marginY: 1, gap: 1, children: [
1597
- /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, bold: true, children: "\u25B6" }),
1598
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Running:" }),
1599
- /* @__PURE__ */ jsx15(Text14, { children: cmdDisplay }),
1600
- /* @__PURE__ */ jsx15(ToolBadge, { tool })
1810
+ return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1811
+ /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
1812
+ /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
1813
+ /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, bold: true, children: "\u25B6" }),
1814
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Running:" }),
1815
+ /* @__PURE__ */ jsx17(Text17, { children: cmdDisplay }),
1816
+ /* @__PURE__ */ jsx17(ToolBadge, { tool })
1601
1817
  ] }),
1602
- /* @__PURE__ */ jsx15(Divider, { width }),
1603
- /* @__PURE__ */ jsx15(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx15(Spinner, { label: `Executing ${cmdDisplay}...` }) })
1818
+ /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
1819
+ /* @__PURE__ */ jsx17(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx17(Spinner, { label: `Executing ${cmdDisplay}...` }) })
1604
1820
  ] });
1605
1821
  }
1606
1822
  if (phase === "success-pin-offer") {
1607
- return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", children: [
1608
- /* @__PURE__ */ jsx15(Divider, { width }),
1609
- /* @__PURE__ */ jsxs14(Box12, { marginY: 1, gap: 1, children: [
1610
- /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, bold: true, children: "\u2713" }),
1611
- /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, bold: true, children: "Command completed successfully!" })
1823
+ return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1824
+ /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
1825
+ /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
1826
+ /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, bold: true, children: "\u2713" }),
1827
+ /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, bold: true, children: "Command completed successfully!" })
1612
1828
  ] }),
1613
- /* @__PURE__ */ jsx15(
1829
+ /* @__PURE__ */ jsx17(
1614
1830
  ConfirmPrompt,
1615
1831
  {
1616
1832
  message: "Pin this exact command?",
@@ -1621,34 +1837,75 @@ function CommandExecution({
1621
1837
  setPinMessage("Exact command pinned to Pinned Runs.");
1622
1838
  }
1623
1839
  setPhase("success");
1624
- }
1840
+ },
1841
+ onCancel: () => setPhase("success"),
1842
+ isInputActive,
1843
+ arrowNavigation: panelMode
1625
1844
  }
1626
1845
  )
1627
1846
  ] });
1628
1847
  }
1629
1848
  if (phase === "success") {
1630
- return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", children: [
1631
- /* @__PURE__ */ jsx15(Divider, { width }),
1632
- /* @__PURE__ */ jsxs14(Box12, { marginY: 1, gap: 1, children: [
1633
- /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, bold: true, children: "\u2713" }),
1634
- /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, bold: true, children: "Command completed successfully!" })
1849
+ const successItems = [
1850
+ { value: "__back__", label: "\u2190 Back to menu" }
1851
+ ];
1852
+ const outputHeight = Math.max(3, height - 12);
1853
+ return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1854
+ /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
1855
+ /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
1856
+ /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, bold: true, children: "\u2713" }),
1857
+ /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, bold: true, children: "Command completed successfully!" })
1635
1858
  ] }),
1636
- pinMessage && /* @__PURE__ */ jsx15(Box12, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, children: pinMessage }) }),
1637
- /* @__PURE__ */ jsx15(
1859
+ pinMessage && /* @__PURE__ */ jsx17(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, children: pinMessage }) }),
1860
+ /* @__PURE__ */ jsx17(
1861
+ CommandOutput,
1862
+ {
1863
+ stdout: result?.stdout,
1864
+ stderr: result?.stderr,
1865
+ height: outputHeight,
1866
+ isActive: isInputActive
1867
+ }
1868
+ ),
1869
+ /* @__PURE__ */ jsx17(
1638
1870
  SelectList,
1639
1871
  {
1640
- items: [{ value: "__back__", label: "\u2190 Back to menu" }],
1641
- onSelect: onBack,
1642
- onCancel: onBack,
1643
- width,
1872
+ items: successItems,
1873
+ onSelect: onHome ?? onBack,
1874
+ onCancel: onHome ?? onBack,
1875
+ width: panelMode ? Math.max(20, width - 4) : width,
1876
+ maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
1644
1877
  isInputActive,
1645
- arrowNavigation: panelMode
1878
+ arrowNavigation: panelMode,
1879
+ boxedSections: panelMode,
1880
+ panelFocused: isInputActive
1646
1881
  }
1647
1882
  )
1648
1883
  ] });
1649
1884
  }
1650
1885
  const hasDebug = currentArgs.includes("--debug");
1886
+ const suggestions = result ? parseErrorSuggestions(result.stdout, result.stderr, tool) : [];
1651
1887
  const errorItems = [];
1888
+ if (suggestions.length > 0) {
1889
+ errorItems.push({
1890
+ value: "__suggestions_header__",
1891
+ label: "\u{1F4A1} Suggested fixes",
1892
+ kind: "header"
1893
+ });
1894
+ for (const s of suggestions) {
1895
+ errorItems.push({
1896
+ value: `suggest:${s.display}`,
1897
+ label: s.display,
1898
+ hint: "from error output"
1899
+ });
1900
+ }
1901
+ }
1902
+ if (suggestions.length > 0) {
1903
+ errorItems.push({
1904
+ value: "__actions_header__",
1905
+ label: "",
1906
+ kind: "header"
1907
+ });
1908
+ }
1652
1909
  if (!result?.spawnError) {
1653
1910
  errorItems.push({ value: "retry", label: "\u{1F504} Retry the same command" });
1654
1911
  if (!hasDebug) {
@@ -1659,54 +1916,82 @@ function CommandExecution({
1659
1916
  });
1660
1917
  }
1661
1918
  }
1662
- errorItems.push(
1663
- {
1664
- value: "copy",
1665
- label: "\u{1F4CB} Copy command to clipboard"
1666
- },
1667
- { value: "menu", label: "\u2190 Return to main menu" },
1668
- { value: "exit", label: "\u{1F6AA} Exit Polter" }
1669
- );
1670
- return /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", children: [
1671
- /* @__PURE__ */ jsx15(Divider, { width }),
1672
- result?.spawnError ? /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", marginY: 1, children: [
1673
- /* @__PURE__ */ jsxs14(Box12, { gap: 1, children: [
1674
- /* @__PURE__ */ jsx15(Text14, { color: "red", bold: true, children: "\u2717" }),
1675
- /* @__PURE__ */ jsx15(Text14, { color: "red", bold: true, children: "Failed to start command" })
1919
+ errorItems.push({
1920
+ value: "copy",
1921
+ label: "\u{1F4CB} Copy command to clipboard"
1922
+ });
1923
+ errorItems.push({
1924
+ value: "menu",
1925
+ label: "\u2190 Back to menu"
1926
+ });
1927
+ return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
1928
+ /* @__PURE__ */ jsx17(Divider, { width: panelMode ? width - 4 : width }),
1929
+ result?.spawnError ? /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", marginY: 1, children: [
1930
+ /* @__PURE__ */ jsxs15(Box13, { gap: 1, children: [
1931
+ /* @__PURE__ */ jsx17(Text17, { color: "red", bold: true, children: "\u2717" }),
1932
+ /* @__PURE__ */ jsx17(Text17, { color: "red", bold: true, children: "Failed to start command" })
1676
1933
  ] }),
1677
- /* @__PURE__ */ jsxs14(Box12, { marginLeft: 2, marginTop: 1, children: [
1678
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Error: " }),
1679
- /* @__PURE__ */ jsx15(Text14, { color: "red", children: result.spawnError })
1934
+ /* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, children: [
1935
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Error: " }),
1936
+ /* @__PURE__ */ jsx17(Text17, { color: "red", children: result.spawnError })
1680
1937
  ] }),
1681
- (result.spawnError.includes("ENOENT") || result.spawnError.includes("not found")) && /* @__PURE__ */ jsx15(Box12, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: /* @__PURE__ */ jsxs14(Text14, { color: inkColors.accent, bold: true, children: [
1682
- "\u{1F4A1} ",
1938
+ (result.spawnError.includes("ENOENT") || result.spawnError.includes("not found")) && /* @__PURE__ */ jsx17(Box13, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: /* @__PURE__ */ jsxs15(Text17, { color: inkColors.accent, bold: true, children: [
1939
+ "\u{1F4A1}",
1940
+ " ",
1683
1941
  tool,
1684
1942
  " CLI not found in this repository or PATH"
1685
1943
  ] }) })
1686
- ] }) : /* @__PURE__ */ jsxs14(Box12, { flexDirection: "column", marginY: 1, children: [
1687
- /* @__PURE__ */ jsxs14(Box12, { gap: 1, children: [
1688
- /* @__PURE__ */ jsx15(Text14, { color: "red", bold: true, children: "\u2717" }),
1689
- /* @__PURE__ */ jsx15(Text14, { color: "red", children: "Command failed " }),
1690
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "(exit code " }),
1691
- /* @__PURE__ */ jsx15(Text14, { color: "red", bold: true, children: String(result?.exitCode) }),
1692
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: ")" })
1944
+ ] }) : /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", marginY: 1, children: [
1945
+ /* @__PURE__ */ jsxs15(Box13, { gap: 1, children: [
1946
+ /* @__PURE__ */ jsx17(Text17, { color: "red", bold: true, children: "\u2717" }),
1947
+ /* @__PURE__ */ jsx17(Text17, { color: "red", children: "Command failed " }),
1948
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "(exit code " }),
1949
+ /* @__PURE__ */ jsx17(Text17, { color: "red", bold: true, children: String(result?.exitCode) }),
1950
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: ")" })
1693
1951
  ] }),
1694
- /* @__PURE__ */ jsxs14(Box12, { marginLeft: 2, marginTop: 1, children: [
1695
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "Command: " }),
1696
- /* @__PURE__ */ jsx15(Text14, { children: cmdDisplay })
1952
+ /* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, children: [
1953
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "Command: " }),
1954
+ /* @__PURE__ */ jsx17(Text17, { children: cmdDisplay })
1697
1955
  ] }),
1698
- !hasDebug && /* @__PURE__ */ jsxs14(Box12, { marginLeft: 2, marginTop: 1, gap: 1, children: [
1699
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "\u{1F4A1} Tip: retry with" }),
1700
- /* @__PURE__ */ jsx15(Text14, { color: inkColors.accent, children: "--debug" }),
1701
- /* @__PURE__ */ jsx15(Text14, { dimColor: true, children: "to see detailed logs" })
1956
+ !hasDebug && /* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, gap: 1, children: [
1957
+ /* @__PURE__ */ jsxs15(Text17, { dimColor: true, children: [
1958
+ "\u{1F4A1}",
1959
+ " Tip: retry with"
1960
+ ] }),
1961
+ /* @__PURE__ */ jsx17(Text17, { color: inkColors.accent, children: "--debug" }),
1962
+ /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "to see detailed logs" })
1702
1963
  ] })
1703
1964
  ] }),
1704
- /* @__PURE__ */ jsx15(Box12, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx15(Text14, { bold: true, children: "What would you like to do?" }) }),
1705
- /* @__PURE__ */ jsx15(
1965
+ /* @__PURE__ */ jsx17(
1966
+ CommandOutput,
1967
+ {
1968
+ stdout: result?.stdout,
1969
+ stderr: result?.stderr,
1970
+ height: Math.max(3, height - 16 - (suggestions.length > 0 ? suggestions.length + 4 : 0)),
1971
+ isActive: false
1972
+ }
1973
+ ),
1974
+ /* @__PURE__ */ jsx17(Box13, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx17(Text17, { bold: true, children: "What would you like to do?" }) }),
1975
+ /* @__PURE__ */ jsx17(
1706
1976
  SelectList,
1707
1977
  {
1708
1978
  items: errorItems,
1709
1979
  onSelect: async (action) => {
1980
+ if (action.startsWith("suggest:")) {
1981
+ const rawCmd = action.slice("suggest:".length);
1982
+ const parts = rawCmd.split(/\s+/);
1983
+ const sugTool = parts[0];
1984
+ const sugArgs = parts.slice(1);
1985
+ if (onRunSuggestion) {
1986
+ onRunSuggestion(sugTool, sugArgs);
1987
+ } else {
1988
+ setCurrentArgs(sugArgs);
1989
+ setPinMessage(void 0);
1990
+ reset();
1991
+ setPhase("confirm");
1992
+ }
1993
+ return;
1994
+ }
1710
1995
  switch (action) {
1711
1996
  case "retry":
1712
1997
  setPinMessage(void 0);
@@ -1725,7 +2010,7 @@ function CommandExecution({
1725
2010
  await copyToClipboard(cmdDisplay);
1726
2011
  break;
1727
2012
  case "menu":
1728
- onBack();
2013
+ (onHome ?? onBack)();
1729
2014
  break;
1730
2015
  case "exit":
1731
2016
  onExit();
@@ -1733,19 +2018,22 @@ function CommandExecution({
1733
2018
  }
1734
2019
  },
1735
2020
  onCancel: onBack,
1736
- width,
2021
+ boxedSections: panelMode,
2022
+ width: panelMode ? Math.max(20, width - 4) : width,
2023
+ maxVisible: panelMode ? Math.max(errorItems.length + (suggestions.length > 0 ? 4 : 0), height - 6) : void 0,
1737
2024
  isInputActive,
1738
- arrowNavigation: panelMode
2025
+ arrowNavigation: panelMode,
2026
+ panelFocused: isInputActive
1739
2027
  }
1740
2028
  ),
1741
- !panelMode && /* @__PURE__ */ jsx15(StatusBar, { width })
2029
+ !panelMode && /* @__PURE__ */ jsx17(StatusBar, { width })
1742
2030
  ] });
1743
2031
  }
1744
2032
 
1745
2033
  // src/screens/SelfUpdate.tsx
1746
- import { useEffect as useEffect6, useState as useState11 } from "react";
1747
- import { Box as Box13, Text as Text15 } from "ink";
1748
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
2034
+ import { useEffect as useEffect6, useState as useState12 } from "react";
2035
+ import { Box as Box14, Text as Text18 } from "ink";
2036
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1749
2037
  var packageName = "@polterware/polter";
1750
2038
  var globalUpdateArgs = ["install", "-g", `${packageName}@latest`];
1751
2039
  var repositoryUpdateArgs = ["install", "-D", `${packageName}@latest`];
@@ -1756,20 +2044,23 @@ function SelfUpdate({
1756
2044
  onBack,
1757
2045
  onExit,
1758
2046
  width = 80,
2047
+ height = 24,
1759
2048
  panelMode = false,
1760
2049
  isInputActive = true
1761
2050
  }) {
1762
2051
  const repositoryRoot = findNearestPackageRoot();
1763
- const [target, setTarget] = useState11(
2052
+ const [target, setTarget] = useState12(
1764
2053
  repositoryRoot ? "repository" : "global"
1765
2054
  );
1766
- const [phase, setPhase] = useState11(
2055
+ const [phase, setPhase] = useState12(
1767
2056
  repositoryRoot ? "target" : "confirm"
1768
2057
  );
1769
2058
  const updateArgs = getUpdateArgs(target);
1770
2059
  const updateDisplay = `npm ${updateArgs.join(" ")}`;
1771
2060
  const updateCwd = target === "repository" && repositoryRoot ? repositoryRoot : process.cwd();
1772
- const { status, result, run, reset } = useCommand("npm", updateCwd);
2061
+ const { status, result, run, reset } = useCommand("npm", updateCwd, {
2062
+ quiet: panelMode
2063
+ });
1773
2064
  useEffect6(() => {
1774
2065
  if (phase === "running" && status === "idle") {
1775
2066
  run(updateArgs);
@@ -1784,24 +2075,28 @@ function SelfUpdate({
1784
2075
  }
1785
2076
  }, [phase, status]);
1786
2077
  if (phase === "target") {
1787
- return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
1788
- /* @__PURE__ */ jsx16(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text15, { bold: true, children: "Choose where to update Polter." }) }),
1789
- /* @__PURE__ */ jsx16(
2078
+ const targetItems = [
2079
+ { value: "__section__", label: "\u{1F4E6} Update Target", kind: "header", selectable: false },
2080
+ {
2081
+ value: "repository",
2082
+ label: "Current repository",
2083
+ hint: "Pin the latest version in package.json",
2084
+ kind: "action"
2085
+ },
2086
+ {
2087
+ value: "global",
2088
+ label: "Global install",
2089
+ hint: "Update the shared version available in PATH",
2090
+ kind: "action"
2091
+ },
2092
+ ...!panelMode ? [{ value: "back", label: "\u2190 Back to menu" }] : []
2093
+ ];
2094
+ return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2095
+ /* @__PURE__ */ jsx18(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx18(Text18, { bold: true, children: "Choose where to update Polter." }) }),
2096
+ /* @__PURE__ */ jsx18(
1790
2097
  SelectList,
1791
2098
  {
1792
- items: [
1793
- {
1794
- value: "repository",
1795
- label: "Current repository",
1796
- hint: "Pin the latest version in package.json"
1797
- },
1798
- {
1799
- value: "global",
1800
- label: "Global install",
1801
- hint: "Update the shared version available in PATH"
1802
- },
1803
- { value: "back", label: "\u2190 Back to menu" }
1804
- ],
2099
+ items: targetItems,
1805
2100
  onSelect: (value) => {
1806
2101
  if (value === "back") {
1807
2102
  onBack();
@@ -1812,20 +2107,23 @@ function SelfUpdate({
1812
2107
  setPhase("confirm");
1813
2108
  },
1814
2109
  onCancel: onBack,
1815
- width,
2110
+ boxedSections: panelMode,
2111
+ width: panelMode ? Math.max(20, width - 4) : width,
2112
+ maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
1816
2113
  isInputActive,
1817
- arrowNavigation: panelMode
2114
+ arrowNavigation: panelMode,
2115
+ panelFocused: isInputActive
1818
2116
  }
1819
2117
  ),
1820
- repositoryRoot && /* @__PURE__ */ jsx16(Box13, { marginTop: 1, marginLeft: 2, children: /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2118
+ repositoryRoot && /* @__PURE__ */ jsx18(Box14, { marginTop: 1, marginLeft: 2, children: /* @__PURE__ */ jsxs16(Text18, { dimColor: true, children: [
1821
2119
  "Repository root: ",
1822
2120
  repositoryRoot
1823
2121
  ] }) })
1824
2122
  ] });
1825
2123
  }
1826
2124
  if (phase === "confirm") {
1827
- return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
1828
- /* @__PURE__ */ jsx16(
2125
+ return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2126
+ /* @__PURE__ */ jsx18(
1829
2127
  ConfirmPrompt,
1830
2128
  {
1831
2129
  message: `Run ${updateDisplay}?`,
@@ -1841,12 +2139,21 @@ function SelfUpdate({
1841
2139
  return;
1842
2140
  }
1843
2141
  onBack();
1844
- }
2142
+ },
2143
+ onCancel: () => {
2144
+ if (repositoryRoot) {
2145
+ setPhase("target");
2146
+ } else {
2147
+ onBack();
2148
+ }
2149
+ },
2150
+ isInputActive,
2151
+ arrowNavigation: panelMode
1845
2152
  }
1846
2153
  ),
1847
- /* @__PURE__ */ jsxs15(Box13, { marginTop: 1, marginLeft: 2, flexDirection: "column", children: [
1848
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: target === "repository" ? "This updates the dependency in the current repository." : "This updates the global npm install." }),
1849
- target === "repository" && repositoryRoot && /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2154
+ /* @__PURE__ */ jsxs16(Box14, { marginTop: 1, marginLeft: 2, flexDirection: "column", children: [
2155
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: target === "repository" ? "This updates the dependency in the current repository." : "This updates the global npm install." }),
2156
+ target === "repository" && repositoryRoot && /* @__PURE__ */ jsxs16(Text18, { dimColor: true, children: [
1850
2157
  "Run location: ",
1851
2158
  repositoryRoot
1852
2159
  ] })
@@ -1854,38 +2161,49 @@ function SelfUpdate({
1854
2161
  ] });
1855
2162
  }
1856
2163
  if (phase === "running") {
1857
- return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
1858
- /* @__PURE__ */ jsx16(Divider, { width }),
1859
- /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
1860
- /* @__PURE__ */ jsx16(Text15, { color: inkColors.accent, bold: true, children: "\u25B6" }),
1861
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: "Running:" }),
1862
- /* @__PURE__ */ jsx16(Text15, { children: updateDisplay })
2164
+ return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2165
+ /* @__PURE__ */ jsx18(Divider, { width: panelMode ? width - 4 : width }),
2166
+ /* @__PURE__ */ jsxs16(Box14, { marginY: 1, gap: 1, children: [
2167
+ /* @__PURE__ */ jsx18(Text18, { color: inkColors.accent, bold: true, children: "\u25B6" }),
2168
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Running:" }),
2169
+ /* @__PURE__ */ jsx18(Text18, { children: updateDisplay })
1863
2170
  ] }),
1864
- /* @__PURE__ */ jsx16(Divider, { width }),
1865
- /* @__PURE__ */ jsx16(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx16(Spinner, { label: "Updating Polter..." }) })
2171
+ /* @__PURE__ */ jsx18(Divider, { width: panelMode ? width - 4 : width }),
2172
+ /* @__PURE__ */ jsx18(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx18(Spinner, { label: "Updating Polter..." }) })
1866
2173
  ] });
1867
2174
  }
1868
2175
  if (phase === "success") {
1869
- return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
1870
- /* @__PURE__ */ jsx16(Divider, { width }),
1871
- /* @__PURE__ */ jsxs15(Box13, { marginY: 1, gap: 1, children: [
1872
- /* @__PURE__ */ jsx16(Text15, { color: inkColors.accent, bold: true, children: "\u2713" }),
1873
- /* @__PURE__ */ jsx16(Text15, { color: inkColors.accent, bold: true, children: "Update completed successfully!" })
2176
+ const successItems = [
2177
+ { value: "__section__", label: "\u2705 Update Complete", kind: "header", selectable: false },
2178
+ ...!panelMode ? [{ value: "__back__", label: "\u2190 Back to menu", kind: "action" }] : [],
2179
+ { value: "__exit__", label: "\u{1F6AA} Exit Polter", kind: "action" }
2180
+ ];
2181
+ return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2182
+ /* @__PURE__ */ jsx18(Divider, { width: panelMode ? width - 4 : width }),
2183
+ /* @__PURE__ */ jsxs16(Box14, { marginY: 1, gap: 1, children: [
2184
+ /* @__PURE__ */ jsx18(Text18, { color: inkColors.accent, bold: true, children: "\u2713" }),
2185
+ /* @__PURE__ */ jsx18(Text18, { color: inkColors.accent, bold: true, children: "Update completed successfully!" })
1874
2186
  ] }),
1875
- /* @__PURE__ */ jsxs15(Box13, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: [
1876
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: "Restart Polter to use the latest version." }),
1877
- target === "repository" && repositoryRoot && /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2187
+ /* @__PURE__ */ jsxs16(Box14, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: [
2188
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Restart Polter to use the latest version." }),
2189
+ target === "repository" && repositoryRoot && /* @__PURE__ */ jsxs16(Text18, { dimColor: true, children: [
1878
2190
  "Repository updated in: ",
1879
2191
  repositoryRoot
1880
2192
  ] })
1881
2193
  ] }),
1882
- /* @__PURE__ */ jsx16(
2194
+ /* @__PURE__ */ jsx18(
2195
+ CommandOutput,
2196
+ {
2197
+ stdout: result?.stdout,
2198
+ stderr: result?.stderr,
2199
+ height: Math.max(3, height - 12),
2200
+ isActive: isInputActive
2201
+ }
2202
+ ),
2203
+ /* @__PURE__ */ jsx18(
1883
2204
  SelectList,
1884
2205
  {
1885
- items: [
1886
- { value: "__back__", label: "\u2190 Back to menu" },
1887
- { value: "__exit__", label: "\u{1F6AA} Exit Polter" }
1888
- ],
2206
+ items: successItems,
1889
2207
  onSelect: (value) => {
1890
2208
  if (value === "__exit__") {
1891
2209
  onExit();
@@ -1894,55 +2212,69 @@ function SelfUpdate({
1894
2212
  onBack();
1895
2213
  },
1896
2214
  onCancel: onBack,
1897
- width,
2215
+ boxedSections: panelMode,
2216
+ width: panelMode ? Math.max(20, width - 4) : width,
2217
+ maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
1898
2218
  isInputActive,
1899
- arrowNavigation: panelMode
2219
+ arrowNavigation: panelMode,
2220
+ panelFocused: isInputActive
1900
2221
  }
1901
2222
  )
1902
2223
  ] });
1903
2224
  }
1904
- return /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", children: [
1905
- /* @__PURE__ */ jsx16(Divider, { width }),
1906
- result?.spawnError ? /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", marginY: 1, children: [
1907
- /* @__PURE__ */ jsxs15(Box13, { gap: 1, children: [
1908
- /* @__PURE__ */ jsx16(Text15, { color: "red", bold: true, children: "\u2717" }),
1909
- /* @__PURE__ */ jsx16(Text15, { color: "red", bold: true, children: "Failed to start update" })
2225
+ const errorItems = [
2226
+ { value: "__section__", label: "\u{1F527} Recovery Options", kind: "header", selectable: false },
2227
+ { value: "retry", label: "\u{1F504} Retry update", kind: "action" },
2228
+ ...repositoryRoot ? [{ value: "target", label: "\u2194 Choose update target", kind: "action" }] : [],
2229
+ ...!panelMode ? [{ value: "menu", label: "\u2190 Return to main menu", kind: "action" }] : [],
2230
+ { value: "exit", label: "\u{1F6AA} Exit Polter", kind: "action" }
2231
+ ];
2232
+ return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2233
+ /* @__PURE__ */ jsx18(Divider, { width: panelMode ? width - 4 : width }),
2234
+ result?.spawnError ? /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", marginY: 1, children: [
2235
+ /* @__PURE__ */ jsxs16(Box14, { gap: 1, children: [
2236
+ /* @__PURE__ */ jsx18(Text18, { color: "red", bold: true, children: "\u2717" }),
2237
+ /* @__PURE__ */ jsx18(Text18, { color: "red", bold: true, children: "Failed to start update" })
1910
2238
  ] }),
1911
- /* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, children: [
1912
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: "Error: " }),
1913
- /* @__PURE__ */ jsx16(Text15, { color: "red", children: result.spawnError })
2239
+ /* @__PURE__ */ jsxs16(Box14, { marginLeft: 2, marginTop: 1, children: [
2240
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Error: " }),
2241
+ /* @__PURE__ */ jsx18(Text18, { color: "red", children: result.spawnError })
1914
2242
  ] })
1915
- ] }) : /* @__PURE__ */ jsxs15(Box13, { flexDirection: "column", marginY: 1, children: [
1916
- /* @__PURE__ */ jsxs15(Box13, { gap: 1, children: [
1917
- /* @__PURE__ */ jsx16(Text15, { color: "red", bold: true, children: "\u2717" }),
1918
- /* @__PURE__ */ jsx16(Text15, { color: "red", children: "Update failed " }),
1919
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: "(exit code " }),
1920
- /* @__PURE__ */ jsx16(Text15, { color: "red", bold: true, children: String(result?.exitCode) }),
1921
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: ")" })
2243
+ ] }) : /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", marginY: 1, children: [
2244
+ /* @__PURE__ */ jsxs16(Box14, { gap: 1, children: [
2245
+ /* @__PURE__ */ jsx18(Text18, { color: "red", bold: true, children: "\u2717" }),
2246
+ /* @__PURE__ */ jsx18(Text18, { color: "red", children: "Update failed " }),
2247
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "(exit code " }),
2248
+ /* @__PURE__ */ jsx18(Text18, { color: "red", bold: true, children: String(result?.exitCode) }),
2249
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: ")" })
1922
2250
  ] }),
1923
- /* @__PURE__ */ jsxs15(Box13, { marginLeft: 2, marginTop: 1, children: [
1924
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: "Command: " }),
1925
- /* @__PURE__ */ jsx16(Text15, { children: updateDisplay })
2251
+ /* @__PURE__ */ jsxs16(Box14, { marginLeft: 2, marginTop: 1, children: [
2252
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Command: " }),
2253
+ /* @__PURE__ */ jsx18(Text18, { children: updateDisplay })
1926
2254
  ] })
1927
2255
  ] }),
1928
- /* @__PURE__ */ jsxs15(Box13, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: [
1929
- /* @__PURE__ */ jsx16(Text15, { dimColor: true, children: "Manual fallback:" }),
1930
- /* @__PURE__ */ jsx16(Text15, { color: inkColors.accent, children: updateDisplay }),
1931
- target === "repository" && repositoryRoot && /* @__PURE__ */ jsxs15(Text15, { dimColor: true, children: [
2256
+ /* @__PURE__ */ jsx18(
2257
+ CommandOutput,
2258
+ {
2259
+ stdout: result?.stdout,
2260
+ stderr: result?.stderr,
2261
+ height: Math.max(3, height - 16),
2262
+ isActive: false
2263
+ }
2264
+ ),
2265
+ /* @__PURE__ */ jsxs16(Box14, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: [
2266
+ /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "Manual fallback:" }),
2267
+ /* @__PURE__ */ jsx18(Text18, { color: inkColors.accent, children: updateDisplay }),
2268
+ target === "repository" && repositoryRoot && /* @__PURE__ */ jsxs16(Text18, { dimColor: true, children: [
1932
2269
  "Run location: ",
1933
2270
  repositoryRoot
1934
2271
  ] })
1935
2272
  ] }),
1936
- /* @__PURE__ */ jsx16(Box13, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx16(Text15, { bold: true, children: "What would you like to do?" }) }),
1937
- /* @__PURE__ */ jsx16(
2273
+ !panelMode && /* @__PURE__ */ jsx18(Box14, { marginTop: 1, marginBottom: 1, children: /* @__PURE__ */ jsx18(Text18, { bold: true, children: "What would you like to do?" }) }),
2274
+ /* @__PURE__ */ jsx18(
1938
2275
  SelectList,
1939
2276
  {
1940
- items: [
1941
- { value: "retry", label: "\u{1F504} Retry update" },
1942
- ...repositoryRoot ? [{ value: "target", label: "\u2194 Choose update target" }] : [],
1943
- { value: "menu", label: "\u2190 Return to main menu" },
1944
- { value: "exit", label: "\u{1F6AA} Exit Polter" }
1945
- ],
2277
+ items: errorItems,
1946
2278
  onSelect: (value) => {
1947
2279
  switch (value) {
1948
2280
  case "retry":
@@ -1962,50 +2294,78 @@ function SelfUpdate({
1962
2294
  }
1963
2295
  },
1964
2296
  onCancel: onBack,
1965
- width,
2297
+ boxedSections: panelMode,
2298
+ width: panelMode ? Math.max(20, width - 4) : width,
2299
+ maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
1966
2300
  isInputActive,
1967
- arrowNavigation: panelMode
2301
+ arrowNavigation: panelMode,
2302
+ panelFocused: isInputActive
1968
2303
  }
1969
2304
  ),
1970
- !panelMode && /* @__PURE__ */ jsx16(StatusBar, { width })
2305
+ !panelMode && /* @__PURE__ */ jsx18(StatusBar, { width })
1971
2306
  ] });
1972
2307
  }
1973
2308
 
1974
2309
  // src/screens/ToolStatus.tsx
1975
2310
  import { useMemo as useMemo4 } from "react";
1976
- import { Box as Box14, Text as Text16 } from "ink";
1977
- import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
1978
- var toolIds = ["supabase", "gh", "vercel", "pulumi"];
1979
- function ToolStatus({ onBack, width = 80, panelMode = false, isInputActive = true }) {
2311
+ import { Box as Box15, Text as Text19 } from "ink";
2312
+ import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
2313
+ var toolIds = ["supabase", "gh", "vercel", "git"];
2314
+ function ToolStatus({ onBack, width = 80, height = 24, panelMode = false, isInputActive = true }) {
1980
2315
  const tools = useMemo4(() => toolIds.map(getToolInfo), []);
1981
- return /* @__PURE__ */ jsxs16(Box14, { flexDirection: "column", children: [
1982
- /* @__PURE__ */ jsx17(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx17(Text16, { bold: true, color: inkColors.accent, children: "\u{1F527} Tool Status" }) }),
1983
- tools.map((tool) => /* @__PURE__ */ jsxs16(Box14, { gap: 1, marginLeft: 2, children: [
1984
- /* @__PURE__ */ jsx17(Text16, { color: tool.installed ? inkColors.accent : "red", children: tool.installed ? "\u2713" : "\u2717" }),
1985
- /* @__PURE__ */ jsx17(Box14, { width: 16, children: /* @__PURE__ */ jsx17(Text16, { bold: true, children: tool.label }) }),
1986
- /* @__PURE__ */ jsx17(Text16, { dimColor: true, children: tool.installed ? tool.version ?? "installed" : "not found" })
2316
+ if (panelMode) {
2317
+ const statusItems = [
2318
+ { value: "__section__", label: "Installed Tools", kind: "header", selectable: false },
2319
+ ...tools.map((tool) => ({
2320
+ value: tool.id,
2321
+ label: `${tool.installed ? "\u2713" : "\u2717"} ${tool.label}`,
2322
+ hint: tool.installed ? tool.version ?? "installed" : "not found",
2323
+ kind: "action"
2324
+ }))
2325
+ ];
2326
+ return /* @__PURE__ */ jsx19(Box15, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx19(
2327
+ SelectList,
2328
+ {
2329
+ items: statusItems,
2330
+ onSelect: () => {
2331
+ },
2332
+ onCancel: onBack,
2333
+ boxedSections: true,
2334
+ width: Math.max(20, width - 4),
2335
+ maxVisible: Math.max(6, height - 6),
2336
+ isInputActive,
2337
+ arrowNavigation: true,
2338
+ panelFocused: isInputActive
2339
+ }
2340
+ ) });
2341
+ }
2342
+ return /* @__PURE__ */ jsxs17(Box15, { flexDirection: "column", children: [
2343
+ /* @__PURE__ */ jsx19(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx19(Text19, { bold: true, color: inkColors.accent, children: "\u{1F527} Tool Status" }) }),
2344
+ tools.map((tool) => /* @__PURE__ */ jsxs17(Box15, { gap: 1, marginLeft: 2, children: [
2345
+ /* @__PURE__ */ jsx19(Text19, { color: tool.installed ? inkColors.accent : "red", children: tool.installed ? "\u2713" : "\u2717" }),
2346
+ /* @__PURE__ */ jsx19(Box15, { width: 16, children: /* @__PURE__ */ jsx19(Text19, { bold: true, children: tool.label }) }),
2347
+ /* @__PURE__ */ jsx19(Text19, { dimColor: true, children: tool.installed ? tool.version ?? "installed" : "not found" })
1987
2348
  ] }, tool.id)),
1988
- /* @__PURE__ */ jsx17(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx17(
2349
+ /* @__PURE__ */ jsx19(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx19(
1989
2350
  SelectList,
1990
2351
  {
1991
2352
  items: [{ value: "__back__", label: "\u2190 Back" }],
1992
2353
  onSelect: onBack,
1993
2354
  onCancel: onBack,
1994
2355
  width,
1995
- isInputActive,
1996
- arrowNavigation: panelMode
2356
+ isInputActive
1997
2357
  }
1998
2358
  ) }),
1999
- !panelMode && /* @__PURE__ */ jsx17(StatusBar, { hint: "Enter to go back", width })
2359
+ /* @__PURE__ */ jsx19(StatusBar, { hint: "Enter to go back", width })
2000
2360
  ] });
2001
2361
  }
2002
2362
 
2003
2363
  // src/screens/ProjectConfig.tsx
2004
- import { useMemo as useMemo5, useState as useState13 } from "react";
2005
- import { Box as Box15, Text as Text17 } from "ink";
2364
+ import { useMemo as useMemo5, useState as useState14 } from "react";
2365
+ import { Box as Box16, Text as Text20 } from "ink";
2006
2366
 
2007
2367
  // src/hooks/useEditor.ts
2008
- import { useState as useState12, useCallback as useCallback3 } from "react";
2368
+ import { useState as useState13, useCallback as useCallback3 } from "react";
2009
2369
  import { useStdin } from "ink";
2010
2370
 
2011
2371
  // src/lib/editor.ts
@@ -2056,7 +2416,7 @@ function openInEditor(filePath) {
2056
2416
  // src/hooks/useEditor.ts
2057
2417
  function useEditor() {
2058
2418
  const { setRawMode } = useStdin();
2059
- const [isEditing, setIsEditing] = useState12(false);
2419
+ const [isEditing, setIsEditing] = useState13(false);
2060
2420
  const openEditor = useCallback3(async (filePath) => {
2061
2421
  const editor = resolveEditor();
2062
2422
  const terminal = isTerminalEditor(editor.command);
@@ -2077,36 +2437,36 @@ function useEditor() {
2077
2437
  }
2078
2438
 
2079
2439
  // src/screens/ProjectConfig.tsx
2080
- import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
2440
+ import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
2081
2441
  function ProjectConfig({
2082
2442
  onBack,
2083
2443
  width = 80,
2444
+ height = 24,
2084
2445
  panelMode = false,
2085
2446
  isInputActive = true
2086
2447
  }) {
2087
2448
  const configPath = useMemo5(() => getProjectConfigPath(), []);
2088
- const [config2, setConfig] = useState13(() => getOrCreateProjectConfig());
2089
- const [phase, setPhase] = useState13("overview");
2090
- const [feedback, setFeedback] = useState13();
2449
+ const [config2, setConfig] = useState14(() => getOrCreateProjectConfig());
2450
+ const [phase, setPhase] = useState14("overview");
2451
+ const [feedback, setFeedback] = useState14();
2091
2452
  const { openEditor, isEditing } = useEditor();
2092
2453
  if (!configPath) {
2093
- return /* @__PURE__ */ jsxs17(Box15, { flexDirection: "column", children: [
2094
- /* @__PURE__ */ jsx18(Text17, { color: "red", children: "No package.json found. Run from a project directory." }),
2095
- /* @__PURE__ */ jsx18(
2454
+ return /* @__PURE__ */ jsxs18(Box16, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2455
+ /* @__PURE__ */ jsx20(Text20, { color: "red", children: "No package.json found. Run from a project directory." }),
2456
+ !panelMode && /* @__PURE__ */ jsx20(
2096
2457
  SelectList,
2097
2458
  {
2098
2459
  items: [{ value: "__back__", label: "\u2190 Back" }],
2099
2460
  onSelect: onBack,
2100
2461
  onCancel: onBack,
2101
2462
  width,
2102
- isInputActive,
2103
- arrowNavigation: panelMode
2463
+ isInputActive
2104
2464
  }
2105
2465
  )
2106
2466
  ] });
2107
2467
  }
2108
2468
  if (phase === "edit-supabase-ref") {
2109
- return /* @__PURE__ */ jsx18(Box15, { flexDirection: "column", children: /* @__PURE__ */ jsx18(
2469
+ return /* @__PURE__ */ jsx20(Box16, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: /* @__PURE__ */ jsx20(
2110
2470
  TextPrompt,
2111
2471
  {
2112
2472
  label: "Supabase project ref:",
@@ -2124,12 +2484,16 @@ function ProjectConfig({
2124
2484
  setFeedback("Supabase project ref updated");
2125
2485
  setPhase("overview");
2126
2486
  },
2127
- onCancel: () => setPhase("overview")
2487
+ onCancel: () => setPhase("overview"),
2488
+ arrowNavigation: panelMode,
2489
+ isInputActive,
2490
+ boxed: panelMode,
2491
+ focused: isInputActive
2128
2492
  }
2129
2493
  ) });
2130
2494
  }
2131
2495
  if (phase === "edit-vercel-id") {
2132
- return /* @__PURE__ */ jsx18(Box15, { flexDirection: "column", children: /* @__PURE__ */ jsx18(
2496
+ return /* @__PURE__ */ jsx20(Box16, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: /* @__PURE__ */ jsx20(
2133
2497
  TextPrompt,
2134
2498
  {
2135
2499
  label: "Vercel project ID:",
@@ -2147,12 +2511,16 @@ function ProjectConfig({
2147
2511
  setFeedback("Vercel project ID updated");
2148
2512
  setPhase("overview");
2149
2513
  },
2150
- onCancel: () => setPhase("overview")
2514
+ onCancel: () => setPhase("overview"),
2515
+ arrowNavigation: panelMode,
2516
+ isInputActive,
2517
+ boxed: panelMode,
2518
+ focused: isInputActive
2151
2519
  }
2152
2520
  ) });
2153
2521
  }
2154
2522
  if (phase === "edit-gh-repo") {
2155
- return /* @__PURE__ */ jsx18(Box15, { flexDirection: "column", children: /* @__PURE__ */ jsx18(
2523
+ return /* @__PURE__ */ jsx20(Box16, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: /* @__PURE__ */ jsx20(
2156
2524
  TextPrompt,
2157
2525
  {
2158
2526
  label: "GitHub repo (owner/name):",
@@ -2170,88 +2538,133 @@ function ProjectConfig({
2170
2538
  setFeedback("GitHub repo updated");
2171
2539
  setPhase("overview");
2172
2540
  },
2173
- onCancel: () => setPhase("overview")
2541
+ onCancel: () => setPhase("overview"),
2542
+ arrowNavigation: panelMode,
2543
+ isInputActive,
2544
+ boxed: panelMode,
2545
+ focused: isInputActive
2174
2546
  }
2175
2547
  ) });
2176
2548
  }
2177
- return /* @__PURE__ */ jsxs17(Box15, { flexDirection: "column", children: [
2178
- /* @__PURE__ */ jsx18(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx18(Text17, { bold: true, color: inkColors.accent, children: "\u2699\uFE0F Project Config" }) }),
2179
- /* @__PURE__ */ jsxs17(Box15, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: [
2180
- /* @__PURE__ */ jsxs17(Text17, { dimColor: true, children: [
2549
+ const configItems = [
2550
+ { value: "__section_current__", label: "\u{1F4CB} Current Values", kind: "header", selectable: false },
2551
+ { value: "__info_supabase__", label: `Supabase ref: ${config2.tools.supabase?.projectRef ?? "not set"}`, kind: "header", selectable: false },
2552
+ { value: "__info_vercel__", label: `Vercel ID: ${config2.tools.vercel?.projectId ?? "not set"}`, kind: "header", selectable: false },
2553
+ { value: "__info_gh__", label: `GitHub repo: ${config2.tools.gh?.repo ?? "not set"}`, kind: "header", selectable: false },
2554
+ { value: "__section_actions__", label: "\u26A1 Actions", kind: "header", selectable: false },
2555
+ { value: "supabase", label: "Set Supabase project ref", kind: "action" },
2556
+ { value: "vercel", label: "Set Vercel project ID", kind: "action" },
2557
+ { value: "gh", label: "Set GitHub repo", kind: "action" },
2558
+ { value: "editor", label: "Open config in editor", kind: "action" },
2559
+ ...!panelMode ? [{ value: "__back__", label: "\u2190 Back" }] : []
2560
+ ];
2561
+ const flatItems = [
2562
+ { value: "supabase", label: "Set Supabase project ref" },
2563
+ { value: "vercel", label: "Set Vercel project ID" },
2564
+ { value: "gh", label: "Set GitHub repo" },
2565
+ { value: "editor", label: "Open config in editor" },
2566
+ ...!panelMode ? [{ value: "__back__", label: "\u2190 Back" }] : []
2567
+ ];
2568
+ const handleSelect = (value) => {
2569
+ switch (value) {
2570
+ case "supabase":
2571
+ setPhase("edit-supabase-ref");
2572
+ break;
2573
+ case "vercel":
2574
+ setPhase("edit-vercel-id");
2575
+ break;
2576
+ case "gh":
2577
+ setPhase("edit-gh-repo");
2578
+ break;
2579
+ case "editor":
2580
+ openEditor(configPath.file).then(() => {
2581
+ try {
2582
+ const reloaded = getOrCreateProjectConfig();
2583
+ setConfig(reloaded);
2584
+ setFeedback("Config reloaded from file");
2585
+ } catch {
2586
+ setFeedback("Warning: could not parse config after editing");
2587
+ }
2588
+ });
2589
+ break;
2590
+ default:
2591
+ onBack();
2592
+ }
2593
+ };
2594
+ if (panelMode) {
2595
+ return /* @__PURE__ */ jsxs18(Box16, { flexDirection: "column", paddingX: 1, children: [
2596
+ /* @__PURE__ */ jsx20(Box16, { marginBottom: 1, marginLeft: 2, children: /* @__PURE__ */ jsxs18(Text20, { dimColor: true, children: [
2597
+ "Path: ",
2598
+ configPath.file
2599
+ ] }) }),
2600
+ feedback && /* @__PURE__ */ jsx20(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: inkColors.accent, children: [
2601
+ "\u2713 ",
2602
+ feedback
2603
+ ] }) }),
2604
+ /* @__PURE__ */ jsx20(
2605
+ SelectList,
2606
+ {
2607
+ items: configItems,
2608
+ onSelect: handleSelect,
2609
+ onCancel: onBack,
2610
+ boxedSections: true,
2611
+ width: Math.max(20, width - 4),
2612
+ maxVisible: Math.max(6, height - 6),
2613
+ isInputActive,
2614
+ arrowNavigation: true,
2615
+ panelFocused: isInputActive
2616
+ }
2617
+ )
2618
+ ] });
2619
+ }
2620
+ return /* @__PURE__ */ jsxs18(Box16, { flexDirection: "column", children: [
2621
+ /* @__PURE__ */ jsx20(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsx20(Text20, { bold: true, color: inkColors.accent, children: "\u2699\uFE0F Project Config" }) }),
2622
+ /* @__PURE__ */ jsxs18(Box16, { marginBottom: 1, marginLeft: 2, flexDirection: "column", children: [
2623
+ /* @__PURE__ */ jsxs18(Text20, { dimColor: true, children: [
2181
2624
  "Path: ",
2182
2625
  configPath.file
2183
2626
  ] }),
2184
- /* @__PURE__ */ jsxs17(Text17, { children: [
2627
+ /* @__PURE__ */ jsxs18(Text20, { children: [
2185
2628
  "Supabase ref: ",
2186
- config2.tools.supabase?.projectRef ?? /* @__PURE__ */ jsx18(Text17, { dimColor: true, children: "not set" })
2629
+ config2.tools.supabase?.projectRef ?? /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "not set" })
2187
2630
  ] }),
2188
- /* @__PURE__ */ jsxs17(Text17, { children: [
2631
+ /* @__PURE__ */ jsxs18(Text20, { children: [
2189
2632
  "Vercel ID: ",
2190
- config2.tools.vercel?.projectId ?? /* @__PURE__ */ jsx18(Text17, { dimColor: true, children: "not set" })
2633
+ config2.tools.vercel?.projectId ?? /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "not set" })
2191
2634
  ] }),
2192
- /* @__PURE__ */ jsxs17(Text17, { children: [
2635
+ /* @__PURE__ */ jsxs18(Text20, { children: [
2193
2636
  "GitHub repo: ",
2194
- config2.tools.gh?.repo ?? /* @__PURE__ */ jsx18(Text17, { dimColor: true, children: "not set" })
2637
+ config2.tools.gh?.repo ?? /* @__PURE__ */ jsx20(Text20, { dimColor: true, children: "not set" })
2195
2638
  ] })
2196
2639
  ] }),
2197
- feedback && /* @__PURE__ */ jsx18(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text17, { color: inkColors.accent, children: [
2640
+ feedback && /* @__PURE__ */ jsx20(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsxs18(Text20, { color: inkColors.accent, children: [
2198
2641
  "\u2713 ",
2199
2642
  feedback
2200
2643
  ] }) }),
2201
- /* @__PURE__ */ jsx18(
2644
+ /* @__PURE__ */ jsx20(
2202
2645
  SelectList,
2203
2646
  {
2204
- items: [
2205
- { value: "supabase", label: "Set Supabase project ref" },
2206
- { value: "vercel", label: "Set Vercel project ID" },
2207
- { value: "gh", label: "Set GitHub repo" },
2208
- { value: "editor", label: "Open config in editor" },
2209
- { value: "__back__", label: "\u2190 Back" }
2210
- ],
2211
- onSelect: (value) => {
2212
- switch (value) {
2213
- case "supabase":
2214
- setPhase("edit-supabase-ref");
2215
- break;
2216
- case "vercel":
2217
- setPhase("edit-vercel-id");
2218
- break;
2219
- case "gh":
2220
- setPhase("edit-gh-repo");
2221
- break;
2222
- case "editor":
2223
- openEditor(configPath.file).then(() => {
2224
- try {
2225
- const reloaded = getOrCreateProjectConfig();
2226
- setConfig(reloaded);
2227
- setFeedback("Config reloaded from file");
2228
- } catch {
2229
- setFeedback("Warning: could not parse config after editing");
2230
- }
2231
- });
2232
- break;
2233
- default:
2234
- onBack();
2235
- }
2236
- },
2647
+ items: flatItems,
2648
+ onSelect: handleSelect,
2237
2649
  onCancel: onBack,
2238
2650
  width,
2239
2651
  isInputActive,
2240
2652
  arrowNavigation: panelMode
2241
2653
  }
2242
2654
  ),
2243
- !panelMode && /* @__PURE__ */ jsx18(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
2655
+ /* @__PURE__ */ jsx20(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
2244
2656
  ] });
2245
2657
  }
2246
2658
 
2247
2659
  // src/screens/PipelineList.tsx
2248
2660
  import { useMemo as useMemo6 } from "react";
2249
- import { Box as Box16, Text as Text18 } from "ink";
2250
- import { jsx as jsx19, jsxs as jsxs18 } from "react/jsx-runtime";
2661
+ import { Box as Box17, Text as Text21 } from "ink";
2662
+ import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
2251
2663
  function PipelineList({
2252
2664
  onNavigate,
2253
2665
  onBack,
2254
2666
  width = 80,
2667
+ height = 24,
2255
2668
  panelMode = false,
2256
2669
  isInputActive = true
2257
2670
  }) {
@@ -2299,17 +2712,19 @@ function PipelineList({
2299
2712
  icon: "\u2795",
2300
2713
  kind: "action"
2301
2714
  });
2302
- list.push({
2303
- id: "action-back",
2304
- value: "__back__",
2305
- label: "\u2190 Back",
2306
- kind: "action"
2307
- });
2715
+ if (!panelMode) {
2716
+ list.push({
2717
+ id: "action-back",
2718
+ value: "__back__",
2719
+ label: "\u2190 Back",
2720
+ kind: "action"
2721
+ });
2722
+ }
2308
2723
  return list;
2309
- }, [pipelines]);
2310
- return /* @__PURE__ */ jsxs18(Box16, { flexDirection: "column", children: [
2311
- /* @__PURE__ */ jsx19(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsx19(Text18, { bold: true, color: inkColors.accent, children: "\u{1F517} Pipelines" }) }),
2312
- /* @__PURE__ */ jsx19(
2724
+ }, [pipelines, panelMode]);
2725
+ return /* @__PURE__ */ jsxs19(Box17, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2726
+ !panelMode && /* @__PURE__ */ jsx21(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsx21(Text21, { bold: true, color: inkColors.accent, children: "\u{1F517} Pipelines" }) }),
2727
+ /* @__PURE__ */ jsx21(
2313
2728
  SelectList,
2314
2729
  {
2315
2730
  items,
@@ -2325,19 +2740,22 @@ function PipelineList({
2325
2740
  onNavigate("pipeline-execution", { pipelineId: value });
2326
2741
  },
2327
2742
  onCancel: onBack,
2328
- width,
2743
+ boxedSections: panelMode,
2744
+ width: panelMode ? Math.max(20, width - 4) : width,
2745
+ maxVisible: panelMode ? Math.max(6, height - 6) : void 0,
2329
2746
  isInputActive,
2330
- arrowNavigation: panelMode
2747
+ arrowNavigation: panelMode,
2748
+ panelFocused: isInputActive
2331
2749
  }
2332
2750
  ),
2333
- !panelMode && /* @__PURE__ */ jsx19(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
2751
+ !panelMode && /* @__PURE__ */ jsx21(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
2334
2752
  ] });
2335
2753
  }
2336
2754
 
2337
2755
  // src/screens/PipelineBuilder.tsx
2338
- import { useState as useState14 } from "react";
2339
- import { Box as Box17, Text as Text19 } from "ink";
2340
- import { jsx as jsx20, jsxs as jsxs19 } from "react/jsx-runtime";
2756
+ import { useState as useState15 } from "react";
2757
+ import { Box as Box18, Text as Text22 } from "ink";
2758
+ import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
2341
2759
  var stepCounter = 0;
2342
2760
  function nextStepId() {
2343
2761
  stepCounter += 1;
@@ -2350,13 +2768,13 @@ function PipelineBuilder({
2350
2768
  panelMode = false,
2351
2769
  isInputActive = true
2352
2770
  }) {
2353
- const [phase, setPhase] = useState14("name");
2354
- const [name, setName] = useState14("");
2355
- const [steps, setSteps] = useState14([]);
2771
+ const [phase, setPhase] = useState15("name");
2772
+ const [name, setName] = useState15("");
2773
+ const [steps, setSteps] = useState15([]);
2356
2774
  if (phase === "name") {
2357
- return /* @__PURE__ */ jsxs19(Box17, { flexDirection: "column", children: [
2358
- /* @__PURE__ */ jsx20(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsx20(Text19, { bold: true, color: inkColors.accent, children: "\u{1F517} New Pipeline" }) }),
2359
- /* @__PURE__ */ jsx20(
2775
+ return /* @__PURE__ */ jsxs20(Box18, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2776
+ /* @__PURE__ */ jsx22(Box18, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text22, { bold: true, color: inkColors.accent, children: "\u{1F517} New Pipeline" }) }),
2777
+ /* @__PURE__ */ jsx22(
2360
2778
  TextPrompt,
2361
2779
  {
2362
2780
  label: "Pipeline name:",
@@ -2369,10 +2787,14 @@ function PipelineBuilder({
2369
2787
  setName(val.trim());
2370
2788
  setPhase("add-step");
2371
2789
  },
2372
- onCancel: onBack
2790
+ onCancel: onBack,
2791
+ arrowNavigation: panelMode,
2792
+ isInputActive,
2793
+ boxed: panelMode,
2794
+ focused: isInputActive
2373
2795
  }
2374
2796
  ),
2375
- !panelMode && /* @__PURE__ */ jsx20(StatusBar, { hint: "Type name \xB7 Enter to continue \xB7 Esc cancel", width })
2797
+ !panelMode && /* @__PURE__ */ jsx22(StatusBar, { hint: "Type name \xB7 Enter to continue \xB7 Esc cancel", width })
2376
2798
  ] });
2377
2799
  }
2378
2800
  if (phase === "add-step") {
@@ -2405,26 +2827,26 @@ function PipelineBuilder({
2405
2827
  kind: "action"
2406
2828
  }
2407
2829
  ];
2408
- return /* @__PURE__ */ jsxs19(Box17, { flexDirection: "column", children: [
2409
- /* @__PURE__ */ jsxs19(Box17, { marginBottom: 1, gap: 1, children: [
2410
- /* @__PURE__ */ jsxs19(Text19, { bold: true, color: inkColors.accent, children: [
2830
+ return /* @__PURE__ */ jsxs20(Box18, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2831
+ /* @__PURE__ */ jsxs20(Box18, { marginBottom: 1, gap: 1, children: [
2832
+ /* @__PURE__ */ jsxs20(Text22, { bold: true, color: inkColors.accent, children: [
2411
2833
  "\u{1F517} ",
2412
2834
  name
2413
2835
  ] }),
2414
- /* @__PURE__ */ jsxs19(Text19, { dimColor: true, children: [
2836
+ /* @__PURE__ */ jsxs20(Text22, { dimColor: true, children: [
2415
2837
  "(",
2416
2838
  steps.length,
2417
2839
  " steps)"
2418
2840
  ] })
2419
2841
  ] }),
2420
- steps.length > 0 && /* @__PURE__ */ jsx20(Box17, { flexDirection: "column", marginBottom: 1, children: steps.map((step, i) => /* @__PURE__ */ jsxs19(Text19, { dimColor: true, children: [
2842
+ steps.length > 0 && /* @__PURE__ */ jsx22(Box18, { flexDirection: "column", marginBottom: 1, children: steps.map((step, i) => /* @__PURE__ */ jsxs20(Text22, { dimColor: true, children: [
2421
2843
  i + 1,
2422
2844
  ". ",
2423
2845
  step.commandId,
2424
2846
  step.args.length > 0 ? ` ${step.args.join(" ")}` : ""
2425
2847
  ] }, step.id)) }),
2426
- /* @__PURE__ */ jsx20(Text19, { dimColor: true, children: "Select a command to add as step:" }),
2427
- /* @__PURE__ */ jsx20(
2848
+ /* @__PURE__ */ jsx22(Text22, { dimColor: true, children: "Select a command to add as step:" }),
2849
+ /* @__PURE__ */ jsx22(
2428
2850
  SelectList,
2429
2851
  {
2430
2852
  items: commandItems,
@@ -2456,12 +2878,14 @@ function PipelineBuilder({
2456
2878
  }
2457
2879
  },
2458
2880
  maxVisible: Math.max(8, height - 14),
2459
- width,
2881
+ boxedSections: panelMode,
2882
+ width: panelMode ? Math.max(20, width - 4) : width,
2460
2883
  isInputActive,
2461
- arrowNavigation: panelMode
2884
+ arrowNavigation: panelMode,
2885
+ panelFocused: isInputActive
2462
2886
  }
2463
2887
  ),
2464
- !panelMode && /* @__PURE__ */ jsx20(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter add step \xB7 Esc done", width })
2888
+ !panelMode && /* @__PURE__ */ jsx22(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter add step \xB7 Esc done", width })
2465
2889
  ] });
2466
2890
  }
2467
2891
  const reviewItems = [
@@ -2484,18 +2908,18 @@ function PipelineBuilder({
2484
2908
  kind: "action"
2485
2909
  }
2486
2910
  ];
2487
- return /* @__PURE__ */ jsxs19(Box17, { flexDirection: "column", children: [
2488
- /* @__PURE__ */ jsx20(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsxs19(Text19, { bold: true, color: inkColors.accent, children: [
2911
+ return /* @__PURE__ */ jsxs20(Box18, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
2912
+ /* @__PURE__ */ jsx22(Box18, { marginBottom: 1, children: /* @__PURE__ */ jsxs20(Text22, { bold: true, color: inkColors.accent, children: [
2489
2913
  "\u{1F517} Review: ",
2490
2914
  name
2491
2915
  ] }) }),
2492
- /* @__PURE__ */ jsx20(Box17, { flexDirection: "column", marginBottom: 1, children: steps.map((step, i) => /* @__PURE__ */ jsxs19(Text19, { children: [
2916
+ /* @__PURE__ */ jsx22(Box18, { flexDirection: "column", marginBottom: 1, children: steps.map((step, i) => /* @__PURE__ */ jsxs20(Text22, { children: [
2493
2917
  i + 1,
2494
2918
  ". ",
2495
2919
  step.commandId,
2496
2920
  step.args.length > 0 ? ` ${step.args.join(" ")}` : ""
2497
2921
  ] }, step.id)) }),
2498
- /* @__PURE__ */ jsx20(
2922
+ /* @__PURE__ */ jsx22(
2499
2923
  SelectList,
2500
2924
  {
2501
2925
  items: reviewItems,
@@ -2520,22 +2944,24 @@ function PipelineBuilder({
2520
2944
  onBack();
2521
2945
  },
2522
2946
  onCancel: onBack,
2523
- width,
2947
+ boxedSections: panelMode,
2948
+ width: panelMode ? Math.max(20, width - 4) : width,
2524
2949
  isInputActive,
2525
- arrowNavigation: panelMode
2950
+ arrowNavigation: panelMode,
2951
+ panelFocused: isInputActive
2526
2952
  }
2527
2953
  ),
2528
- !panelMode && /* @__PURE__ */ jsx20(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
2954
+ !panelMode && /* @__PURE__ */ jsx22(StatusBar, { hint: "\u2191\u2193 navigate \xB7 Enter select \xB7 Esc back", width })
2529
2955
  ] });
2530
2956
  }
2531
2957
 
2532
2958
  // src/screens/PipelineExecution.tsx
2533
- import { useState as useState15, useEffect as useEffect7, useMemo as useMemo7 } from "react";
2534
- import { Box as Box20, Text as Text22 } from "ink";
2959
+ import { useState as useState16, useEffect as useEffect7, useMemo as useMemo7 } from "react";
2960
+ import { Box as Box21, Text as Text25 } from "ink";
2535
2961
 
2536
2962
  // src/components/StepIndicator.tsx
2537
- import { Box as Box18, Text as Text20 } from "ink";
2538
- import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
2963
+ import { Box as Box19, Text as Text23 } from "ink";
2964
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
2539
2965
  var statusIcons = {
2540
2966
  pending: "\u25CB",
2541
2967
  running: "",
@@ -2555,21 +2981,21 @@ function StepIndicator({
2555
2981
  status,
2556
2982
  index
2557
2983
  }) {
2558
- return /* @__PURE__ */ jsxs20(Box18, { gap: 1, children: [
2559
- /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
2984
+ return /* @__PURE__ */ jsxs21(Box19, { gap: 1, children: [
2985
+ /* @__PURE__ */ jsxs21(Text23, { dimColor: true, children: [
2560
2986
  String(index + 1).padStart(2, " "),
2561
2987
  "."
2562
2988
  ] }),
2563
- status === "running" ? /* @__PURE__ */ jsx21(Spinner, { label: "" }) : /* @__PURE__ */ jsx21(
2564
- Text20,
2989
+ status === "running" ? /* @__PURE__ */ jsx23(Spinner, { label: "" }) : /* @__PURE__ */ jsx23(
2990
+ Text23,
2565
2991
  {
2566
2992
  color: statusColors[status],
2567
2993
  dimColor: status === "pending" || status === "skipped",
2568
2994
  children: statusIcons[status]
2569
2995
  }
2570
2996
  ),
2571
- /* @__PURE__ */ jsx21(
2572
- Text20,
2997
+ /* @__PURE__ */ jsx23(
2998
+ Text23,
2573
2999
  {
2574
3000
  color: statusColors[status],
2575
3001
  dimColor: status === "pending" || status === "skipped",
@@ -2581,8 +3007,8 @@ function StepIndicator({
2581
3007
  }
2582
3008
 
2583
3009
  // src/components/PipelineProgress.tsx
2584
- import { Box as Box19, Text as Text21 } from "ink";
2585
- import { jsxs as jsxs21 } from "react/jsx-runtime";
3010
+ import { Box as Box20, Text as Text24 } from "ink";
3011
+ import { jsxs as jsxs22 } from "react/jsx-runtime";
2586
3012
  function PipelineProgressBar({
2587
3013
  total,
2588
3014
  completed,
@@ -2593,14 +3019,14 @@ function PipelineProgressBar({
2593
3019
  const filledCount = total > 0 ? Math.round(completed / total * barWidth) : 0;
2594
3020
  const filled = "\u2588".repeat(filledCount);
2595
3021
  const empty = "\u2591".repeat(barWidth - filledCount);
2596
- return /* @__PURE__ */ jsxs21(Box19, { gap: 1, children: [
2597
- /* @__PURE__ */ jsxs21(Text21, { color: errors > 0 ? "red" : inkColors.accent, children: [
3022
+ return /* @__PURE__ */ jsxs22(Box20, { gap: 1, children: [
3023
+ /* @__PURE__ */ jsxs22(Text24, { color: errors > 0 ? "red" : inkColors.accent, children: [
2598
3024
  "[",
2599
3025
  filled,
2600
3026
  empty,
2601
3027
  "]"
2602
3028
  ] }),
2603
- /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
3029
+ /* @__PURE__ */ jsxs22(Text24, { dimColor: true, children: [
2604
3030
  completed,
2605
3031
  "/",
2606
3032
  total,
@@ -2610,7 +3036,7 @@ function PipelineProgressBar({
2610
3036
  }
2611
3037
 
2612
3038
  // src/screens/PipelineExecution.tsx
2613
- import { Fragment, jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
3039
+ import { Fragment, jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
2614
3040
  function PipelineExecution({
2615
3041
  pipelineId,
2616
3042
  onBack,
@@ -2623,9 +3049,9 @@ function PipelineExecution({
2623
3049
  () => getAllPipelines().find((p) => p.id === pipelineId),
2624
3050
  [pipelineId]
2625
3051
  );
2626
- const [phase, setPhase] = useState15("running");
2627
- const [progress, setProgress] = useState15(null);
2628
- const [results, setResults] = useState15([]);
3052
+ const [phase, setPhase] = useState16("running");
3053
+ const [progress, setProgress] = useState16(null);
3054
+ const [results, setResults] = useState16([]);
2629
3055
  useEffect7(() => {
2630
3056
  if (!pipeline) return;
2631
3057
  executePipeline(pipeline, (p) => {
@@ -2639,20 +3065,22 @@ function PipelineExecution({
2639
3065
  });
2640
3066
  }, [pipeline]);
2641
3067
  if (!pipeline) {
2642
- return /* @__PURE__ */ jsxs22(Box20, { flexDirection: "column", children: [
2643
- /* @__PURE__ */ jsxs22(Text22, { color: "red", children: [
3068
+ return /* @__PURE__ */ jsxs23(Box21, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
3069
+ /* @__PURE__ */ jsxs23(Text25, { color: "red", children: [
2644
3070
  "Pipeline not found: ",
2645
3071
  pipelineId
2646
3072
  ] }),
2647
- /* @__PURE__ */ jsx22(
3073
+ /* @__PURE__ */ jsx24(
2648
3074
  SelectList,
2649
3075
  {
2650
3076
  items: [{ value: "__back__", label: "\u2190 Back" }],
2651
3077
  onSelect: onBack,
2652
3078
  onCancel: onBack,
2653
- width,
3079
+ boxedSections: panelMode,
3080
+ width: panelMode ? Math.max(20, width - 4) : width,
2654
3081
  isInputActive,
2655
- arrowNavigation: panelMode
3082
+ arrowNavigation: panelMode,
3083
+ panelFocused: isInputActive
2656
3084
  }
2657
3085
  )
2658
3086
  ] });
@@ -2667,15 +3095,15 @@ function PipelineExecution({
2667
3095
  const base = cmdDef ? `${cmdDef.tool}: ${cmdDef.label}` : step.commandId;
2668
3096
  return step.args.length > 0 ? `${base} ${step.args.join(" ")}` : base;
2669
3097
  }
2670
- return /* @__PURE__ */ jsxs22(Box20, { flexDirection: "column", children: [
2671
- /* @__PURE__ */ jsxs22(Box20, { marginBottom: 1, gap: 1, children: [
2672
- /* @__PURE__ */ jsxs22(Text22, { bold: true, color: inkColors.accent, children: [
3098
+ return /* @__PURE__ */ jsxs23(Box21, { flexDirection: "column", paddingX: panelMode ? 1 : 0, children: [
3099
+ /* @__PURE__ */ jsxs23(Box21, { marginBottom: 1, gap: 1, children: [
3100
+ /* @__PURE__ */ jsxs23(Text25, { bold: true, color: inkColors.accent, children: [
2673
3101
  "\u{1F517} ",
2674
3102
  pipeline.name
2675
3103
  ] }),
2676
- /* @__PURE__ */ jsx22(Text22, { dimColor: true, children: phase === "running" ? "Running..." : "Complete" })
3104
+ /* @__PURE__ */ jsx24(Text25, { dimColor: true, children: phase === "running" ? "Running..." : "Complete" })
2677
3105
  ] }),
2678
- /* @__PURE__ */ jsx22(
3106
+ /* @__PURE__ */ jsx24(
2679
3107
  PipelineProgressBar,
2680
3108
  {
2681
3109
  total: pipeline.steps.length,
@@ -2684,8 +3112,8 @@ function PipelineExecution({
2684
3112
  width
2685
3113
  }
2686
3114
  ),
2687
- /* @__PURE__ */ jsx22(Divider, { width }),
2688
- /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", marginY: 1, children: pipeline.steps.map((step, i) => /* @__PURE__ */ jsx22(
3115
+ /* @__PURE__ */ jsx24(Divider, { width }),
3116
+ /* @__PURE__ */ jsx24(Box21, { flexDirection: "column", marginY: 1, children: pipeline.steps.map((step, i) => /* @__PURE__ */ jsx24(
2689
3117
  StepIndicator,
2690
3118
  {
2691
3119
  label: step.label ?? getStepLabel(step),
@@ -2694,17 +3122,17 @@ function PipelineExecution({
2694
3122
  },
2695
3123
  step.id
2696
3124
  )) }),
2697
- phase === "done" && /* @__PURE__ */ jsxs22(Fragment, { children: [
2698
- /* @__PURE__ */ jsx22(Divider, { width }),
2699
- /* @__PURE__ */ jsx22(Box20, { marginY: 1, children: /* @__PURE__ */ jsx22(
2700
- Text22,
3125
+ phase === "done" && /* @__PURE__ */ jsxs23(Fragment, { children: [
3126
+ /* @__PURE__ */ jsx24(Divider, { width }),
3127
+ /* @__PURE__ */ jsx24(Box21, { marginY: 1, children: /* @__PURE__ */ jsx24(
3128
+ Text25,
2701
3129
  {
2702
3130
  color: errorCount > 0 ? "red" : inkColors.accent,
2703
3131
  bold: true,
2704
3132
  children: errorCount > 0 ? `Pipeline completed with ${errorCount} error(s)` : "Pipeline completed successfully!"
2705
3133
  }
2706
3134
  ) }),
2707
- /* @__PURE__ */ jsx22(
3135
+ /* @__PURE__ */ jsx24(
2708
3136
  SelectList,
2709
3137
  {
2710
3138
  items: [
@@ -2719,13 +3147,15 @@ function PipelineExecution({
2719
3147
  onBack();
2720
3148
  },
2721
3149
  onCancel: onBack,
2722
- width,
3150
+ boxedSections: panelMode,
3151
+ width: panelMode ? Math.max(20, width - 4) : width,
2723
3152
  isInputActive,
2724
- arrowNavigation: panelMode
3153
+ arrowNavigation: panelMode,
3154
+ panelFocused: isInputActive
2725
3155
  }
2726
3156
  )
2727
3157
  ] }),
2728
- !panelMode && /* @__PURE__ */ jsx22(
3158
+ !panelMode && /* @__PURE__ */ jsx24(
2729
3159
  StatusBar,
2730
3160
  {
2731
3161
  hint: phase === "running" ? "Running pipeline..." : "Enter select \xB7 Esc back",
@@ -2736,7 +3166,7 @@ function PipelineExecution({
2736
3166
  }
2737
3167
 
2738
3168
  // src/app.tsx
2739
- import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
3169
+ import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
2740
3170
  function AppClassic() {
2741
3171
  const { screen, params, navigate, goBack, goHome } = useNavigation();
2742
3172
  const { exit } = useApp();
@@ -2751,9 +3181,9 @@ function AppClassic() {
2751
3181
  const renderScreen = () => {
2752
3182
  switch (screen) {
2753
3183
  case "home":
2754
- return /* @__PURE__ */ jsx23(Home, { onNavigate: navigate, onExit: handleExit, width, height });
3184
+ return /* @__PURE__ */ jsx25(Home, { onNavigate: navigate, onExit: handleExit, width, height });
2755
3185
  case "command-args":
2756
- return /* @__PURE__ */ jsx23(
3186
+ return /* @__PURE__ */ jsx25(
2757
3187
  CommandArgs,
2758
3188
  {
2759
3189
  command: params.command ?? "",
@@ -2764,9 +3194,9 @@ function AppClassic() {
2764
3194
  }
2765
3195
  );
2766
3196
  case "custom-command":
2767
- return /* @__PURE__ */ jsx23(CustomCommand, { onNavigate: navigate, onBack: goBack, width });
3197
+ return /* @__PURE__ */ jsx25(CustomCommand, { onNavigate: navigate, onBack: goBack, width });
2768
3198
  case "flag-selection":
2769
- return /* @__PURE__ */ jsx23(
3199
+ return /* @__PURE__ */ jsx25(
2770
3200
  FlagSelection,
2771
3201
  {
2772
3202
  args: params.args ?? [],
@@ -2778,28 +3208,32 @@ function AppClassic() {
2778
3208
  );
2779
3209
  case "confirm-execute":
2780
3210
  case "command-execution":
2781
- return /* @__PURE__ */ jsx23(
3211
+ return /* @__PURE__ */ jsx25(
2782
3212
  CommandExecution,
2783
3213
  {
2784
3214
  args: params.args ?? [],
2785
3215
  tool: params.tool,
2786
3216
  onBack: goBack,
2787
3217
  onExit: handleExit,
3218
+ onRunSuggestion: (sugTool, sugArgs) => {
3219
+ goHome();
3220
+ navigate("confirm-execute", { tool: sugTool, args: sugArgs });
3221
+ },
2788
3222
  width
2789
3223
  }
2790
3224
  );
2791
3225
  case "self-update":
2792
- return /* @__PURE__ */ jsx23(SelfUpdate, { onBack: goBack, onExit: handleExit, width });
3226
+ return /* @__PURE__ */ jsx25(SelfUpdate, { onBack: goBack, onExit: handleExit, width });
2793
3227
  case "tool-status":
2794
- return /* @__PURE__ */ jsx23(ToolStatus, { onBack: goBack, width });
3228
+ return /* @__PURE__ */ jsx25(ToolStatus, { onBack: goBack, width });
2795
3229
  case "project-config":
2796
- return /* @__PURE__ */ jsx23(ProjectConfig, { onBack: goBack, width });
3230
+ return /* @__PURE__ */ jsx25(ProjectConfig, { onBack: goBack, width });
2797
3231
  case "pipeline-list":
2798
- return /* @__PURE__ */ jsx23(PipelineList, { onNavigate: navigate, onBack: goBack, width });
3232
+ return /* @__PURE__ */ jsx25(PipelineList, { onNavigate: navigate, onBack: goBack, width });
2799
3233
  case "pipeline-builder":
2800
- return /* @__PURE__ */ jsx23(PipelineBuilder, { onBack: goBack, width, height });
3234
+ return /* @__PURE__ */ jsx25(PipelineBuilder, { onBack: goBack, width, height });
2801
3235
  case "pipeline-execution":
2802
- return /* @__PURE__ */ jsx23(
3236
+ return /* @__PURE__ */ jsx25(
2803
3237
  PipelineExecution,
2804
3238
  {
2805
3239
  pipelineId: params.pipelineId ?? "",
@@ -2809,21 +3243,21 @@ function AppClassic() {
2809
3243
  }
2810
3244
  );
2811
3245
  default:
2812
- return /* @__PURE__ */ jsx23(Box21, { children: /* @__PURE__ */ jsxs23(Text23, { color: "red", children: [
3246
+ return /* @__PURE__ */ jsx25(Box22, { children: /* @__PURE__ */ jsxs24(Text26, { color: "red", children: [
2813
3247
  "Unknown screen: ",
2814
3248
  screen
2815
3249
  ] }) });
2816
3250
  }
2817
3251
  };
2818
- return /* @__PURE__ */ jsxs23(Box21, { flexDirection: "column", children: [
2819
- /* @__PURE__ */ jsx23(GhostBanner, { width }),
3252
+ return /* @__PURE__ */ jsxs24(Box22, { flexDirection: "column", children: [
3253
+ /* @__PURE__ */ jsx25(GhostBanner, { width }),
2820
3254
  renderScreen()
2821
3255
  ] });
2822
3256
  }
2823
3257
 
2824
3258
  // src/appPanel.tsx
2825
- import React18 from "react";
2826
- import { Box as Box29, Text as Text30, useApp as useApp2, useInput as useInput7 } from "ink";
3259
+ import React19 from "react";
3260
+ import { Box as Box30, Text as Text33, useApp as useApp2, useInput as useInput9 } from "ink";
2827
3261
 
2828
3262
  // src/hooks/useFullscreen.ts
2829
3263
  import { useEffect as useEffect8 } from "react";
@@ -2841,10 +3275,10 @@ function useFullscreen() {
2841
3275
  }
2842
3276
 
2843
3277
  // src/hooks/usePanelNavigation.ts
2844
- import { useState as useState16, useCallback as useCallback4 } from "react";
3278
+ import { useState as useState17, useCallback as useCallback4 } from "react";
2845
3279
  function usePanelNavigation() {
2846
- const [state, setState] = useState16({
2847
- view: "feature",
3280
+ const [state, setState] = useState17({
3281
+ view: "pipelines",
2848
3282
  featureId: "database",
2849
3283
  innerScreen: "home",
2850
3284
  innerParams: {},
@@ -2922,19 +3356,32 @@ function usePanelNavigation() {
2922
3356
  innerStack: []
2923
3357
  }));
2924
3358
  }, []);
3359
+ const switchViewAndNavigate = useCallback4(
3360
+ (view, screen, params) => {
3361
+ setState((prev) => ({
3362
+ ...prev,
3363
+ view,
3364
+ innerScreen: screen,
3365
+ innerParams: params ?? {},
3366
+ innerStack: [{ screen: "home", params: {} }]
3367
+ }));
3368
+ },
3369
+ []
3370
+ );
2925
3371
  return {
2926
3372
  ...state,
2927
3373
  selectSidebarItem,
2928
3374
  navigateInner,
2929
3375
  goBackInner,
2930
- goHomeInner
3376
+ goHomeInner,
3377
+ switchViewAndNavigate
2931
3378
  };
2932
3379
  }
2933
3380
 
2934
3381
  // src/hooks/usePanelFocus.ts
2935
- import { useState as useState17, useCallback as useCallback5 } from "react";
3382
+ import { useState as useState18, useCallback as useCallback5 } from "react";
2936
3383
  function usePanelFocus() {
2937
- const [focused, setFocused] = useState17("sidebar");
3384
+ const [focused, setFocused] = useState18("sidebar");
2938
3385
  const toggleFocus = useCallback5(() => {
2939
3386
  setFocused((prev) => prev === "sidebar" ? "main" : "sidebar");
2940
3387
  }, []);
@@ -2952,36 +3399,35 @@ function usePanelFocus() {
2952
3399
 
2953
3400
  // src/hooks/useSidebarItems.ts
2954
3401
  import { useMemo as useMemo8 } from "react";
2955
- function useSidebarItems(hasPins = false) {
3402
+ function useSidebarItems() {
2956
3403
  return useMemo8(() => {
2957
3404
  const items = [];
2958
- if (hasPins) {
2959
- items.push({ id: "pinned", label: "Pinned", icon: "\u{1F4CC}", type: "action" });
2960
- items.push({ id: "__sep_pinned__", label: "---", icon: "", type: "separator" });
2961
- }
3405
+ items.push({ id: "__sep_workflows__", label: "---", icon: "", type: "separator", sectionTitle: "Workflows" });
3406
+ items.push({ id: "pipelines", label: "Pipelines", icon: "\u{1F517}", type: "action", section: "workflows" });
3407
+ items.push({ id: "pinned", label: "Pinned", icon: "\u{1F4CC}", type: "action", section: "workflows" });
3408
+ items.push({ id: "custom-command", label: "Custom Cmd", icon: "\u270F\uFE0F", type: "action", section: "workflows" });
3409
+ items.push({ id: "__sep_features__", label: "---", icon: "", type: "separator", sectionTitle: "Features" });
2962
3410
  for (const feature of features) {
2963
3411
  items.push({
2964
3412
  id: feature.id,
2965
3413
  label: feature.label,
2966
3414
  icon: feature.icon,
2967
- type: "feature"
3415
+ type: "feature",
3416
+ section: "features"
2968
3417
  });
2969
3418
  }
2970
- items.push({ id: "__sep__", label: "---", icon: "", type: "separator" });
2971
- items.push({ id: "custom-command", label: "Custom Cmd", icon: "\u270F\uFE0F", type: "action" });
2972
- items.push({ id: "pipelines", label: "Pipelines", icon: "\u{1F517}", type: "action" });
2973
- items.push({ id: "tool-status", label: "Tool Status", icon: "\u{1F527}", type: "action" });
2974
- items.push({ id: "config", label: "Config", icon: "\u2699\uFE0F", type: "action" });
2975
- items.push({ id: "self-update", label: "Update", icon: "\u2B06\uFE0F", type: "action" });
2976
- items.push({ id: "exit", label: "Exit", icon: "\u{1F6AA}", type: "action" });
3419
+ items.push({ id: "__sep_system__", label: "---", icon: "", type: "separator", sectionTitle: "System" });
3420
+ items.push({ id: "tool-status", label: "Tool Status", icon: "\u{1F527}", type: "action", section: "system" });
3421
+ items.push({ id: "config", label: "Config", icon: "\u2699\uFE0F", type: "action", section: "system" });
3422
+ items.push({ id: "self-update", label: "Update", icon: "\u2B06\uFE0F", type: "action", section: "system" });
2977
3423
  return items;
2978
- }, [hasPins]);
3424
+ }, []);
2979
3425
  }
2980
3426
 
2981
3427
  // src/hooks/useModal.ts
2982
- import { useState as useState18, useCallback as useCallback6 } from "react";
3428
+ import { useState as useState19, useCallback as useCallback6 } from "react";
2983
3429
  function useModal() {
2984
- const [state, setState] = useState18(null);
3430
+ const [state, setState] = useState19(null);
2985
3431
  const openModal = useCallback6((content, title) => {
2986
3432
  setState({ content, title });
2987
3433
  }, []);
@@ -2998,8 +3444,8 @@ function useModal() {
2998
3444
  }
2999
3445
 
3000
3446
  // src/components/PanelLayout.tsx
3001
- import { Box as Box22 } from "ink";
3002
- import { jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
3447
+ import { Box as Box23 } from "ink";
3448
+ import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
3003
3449
  function PanelLayout({
3004
3450
  header,
3005
3451
  footer,
@@ -3014,19 +3460,19 @@ function PanelLayout({
3014
3460
  const contentHeight = Math.max(5, height - bannerHeight - footerHeight);
3015
3461
  const sidebarWidth = singlePanel ? 0 : panel.sidebarWidth(width);
3016
3462
  const mainWidth = singlePanel ? width : width - sidebarWidth;
3017
- return /* @__PURE__ */ jsxs24(Box22, { flexDirection: "column", width, height, children: [
3463
+ return /* @__PURE__ */ jsxs25(Box23, { flexDirection: "column", width, height, children: [
3018
3464
  header,
3019
- /* @__PURE__ */ jsxs24(Box22, { flexDirection: "row", height: contentHeight, children: [
3020
- !singlePanel && /* @__PURE__ */ jsx24(Box22, { width: sidebarWidth, height: contentHeight, children: sidebar }),
3021
- /* @__PURE__ */ jsx24(Box22, { width: mainWidth, height: contentHeight, children: main2 })
3465
+ /* @__PURE__ */ jsxs25(Box23, { flexDirection: "row", height: contentHeight, children: [
3466
+ !singlePanel && /* @__PURE__ */ jsx26(Box23, { width: sidebarWidth, height: contentHeight, children: sidebar }),
3467
+ /* @__PURE__ */ jsx26(Box23, { width: mainWidth, height: contentHeight, children: main2 })
3022
3468
  ] }),
3023
- /* @__PURE__ */ jsx24(Box22, { height: footerHeight, children: footer })
3469
+ /* @__PURE__ */ jsx26(Box23, { height: footerHeight, children: footer })
3024
3470
  ] });
3025
3471
  }
3026
3472
 
3027
3473
  // src/components/Panel.tsx
3028
- import { Box as Box23, Text as Text24 } from "ink";
3029
- import { jsx as jsx25, jsxs as jsxs25 } from "react/jsx-runtime";
3474
+ import { Box as Box24, Text as Text27 } from "ink";
3475
+ import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
3030
3476
  function Panel({
3031
3477
  id,
3032
3478
  title,
@@ -3036,8 +3482,8 @@ function Panel({
3036
3482
  children
3037
3483
  }) {
3038
3484
  const borderColor = focused ? panel.borderFocused : panel.borderDim;
3039
- return /* @__PURE__ */ jsxs25(
3040
- Box23,
3485
+ return /* @__PURE__ */ jsxs26(
3486
+ Box24,
3041
3487
  {
3042
3488
  flexDirection: "column",
3043
3489
  width,
@@ -3046,21 +3492,34 @@ function Panel({
3046
3492
  borderColor,
3047
3493
  overflow: "hidden",
3048
3494
  children: [
3049
- title && /* @__PURE__ */ jsx25(Box23, { marginBottom: 0, children: /* @__PURE__ */ jsxs25(Text24, { color: focused ? inkColors.accent : void 0, bold: focused, dimColor: !focused, children: [
3495
+ title && /* @__PURE__ */ jsx27(Box24, { marginBottom: 0, children: /* @__PURE__ */ jsxs26(Text27, { color: focused ? inkColors.accent : void 0, bold: focused, dimColor: !focused, children: [
3050
3496
  " ",
3051
3497
  title,
3052
3498
  " "
3053
3499
  ] }) }),
3054
- /* @__PURE__ */ jsx25(Box23, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
3500
+ /* @__PURE__ */ jsx27(Box24, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
3055
3501
  ]
3056
3502
  }
3057
3503
  );
3058
3504
  }
3059
3505
 
3060
3506
  // src/components/Sidebar.tsx
3061
- import { useEffect as useEffect9, useMemo as useMemo9, useState as useState19 } from "react";
3062
- import { Box as Box24, Text as Text25, useInput as useInput6 } from "ink";
3063
- import { jsx as jsx26, jsxs as jsxs26 } from "react/jsx-runtime";
3507
+ import { useEffect as useEffect9, useMemo as useMemo9, useState as useState20 } from "react";
3508
+ import { Box as Box25, Text as Text28, useInput as useInput8 } from "ink";
3509
+ import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
3510
+ function groupSections(items) {
3511
+ const groups = [];
3512
+ let current = null;
3513
+ for (const item of items) {
3514
+ if (item.type === "separator" && item.sectionTitle) {
3515
+ current = { title: item.sectionTitle, items: [] };
3516
+ groups.push(current);
3517
+ } else if (current) {
3518
+ current.items.push(item);
3519
+ }
3520
+ }
3521
+ return groups;
3522
+ }
3064
3523
  function Sidebar({
3065
3524
  items,
3066
3525
  selectedId,
@@ -3074,12 +3533,13 @@ function Sidebar({
3074
3533
  [items]
3075
3534
  );
3076
3535
  const selectedIdx = selectableItems.findIndex((item) => item.id === selectedId);
3077
- const [cursorIdx, setCursorIdx] = useState19(Math.max(0, selectedIdx));
3536
+ const [cursorIdx, setCursorIdx] = useState20(Math.max(0, selectedIdx));
3537
+ const sections = useMemo9(() => groupSections(items), [items]);
3078
3538
  useEffect9(() => {
3079
3539
  const idx = selectableItems.findIndex((item) => item.id === selectedId);
3080
3540
  if (idx >= 0) setCursorIdx(idx);
3081
3541
  }, [selectedId, selectableItems]);
3082
- useInput6(
3542
+ useInput8(
3083
3543
  (input2, key) => {
3084
3544
  if (key.upArrow || input2 === "k") {
3085
3545
  setCursorIdx((prev) => {
@@ -3106,39 +3566,57 @@ function Sidebar({
3106
3566
  },
3107
3567
  { isActive: isFocused }
3108
3568
  );
3109
- let selectableIdx = 0;
3110
- return /* @__PURE__ */ jsx26(Box24, { flexDirection: "column", paddingX: 1, children: items.map((item) => {
3111
- if (item.type === "separator") {
3112
- return /* @__PURE__ */ jsx26(Box24, { children: /* @__PURE__ */ jsx26(Text25, { dimColor: true, children: symbols.horizontal.repeat(10) }) }, item.id);
3113
- }
3114
- const thisIdx = selectableIdx;
3115
- selectableIdx++;
3116
- const isCursor = isFocused && thisIdx === cursorIdx;
3117
- const isActive = item.id === selectedId;
3118
- return /* @__PURE__ */ jsx26(Box24, { gap: 0, children: /* @__PURE__ */ jsxs26(
3119
- Text25,
3569
+ let flatIdx = 0;
3570
+ return /* @__PURE__ */ jsx28(Box25, { flexDirection: "column", gap: 0, children: sections.map((section) => {
3571
+ const sectionStartIdx = flatIdx;
3572
+ const sectionEndIdx = sectionStartIdx + section.items.length - 1;
3573
+ const hasCursorInSection = isFocused && cursorIdx >= sectionStartIdx && cursorIdx <= sectionEndIdx;
3574
+ const hasActiveInSection = section.items.some((item) => item.id === selectedId);
3575
+ const borderColor = hasCursorInSection || hasActiveInSection ? inkColors.accent : "#555555";
3576
+ const rendered = /* @__PURE__ */ jsxs27(
3577
+ Box25,
3120
3578
  {
3121
- color: isCursor ? inkColors.accent : isActive ? inkColors.accent : void 0,
3122
- bold: isCursor || isActive,
3123
- dimColor: !isCursor && !isActive,
3579
+ flexDirection: "column",
3580
+ borderStyle: "round",
3581
+ borderColor,
3582
+ paddingX: 1,
3124
3583
  children: [
3125
- isCursor ? `${symbols.pointerActive} ` : " ",
3126
- item.icon,
3127
- " ",
3128
- item.label
3584
+ /* @__PURE__ */ jsx28(Text28, { dimColor: true, bold: true, children: section.title }),
3585
+ section.items.map((item) => {
3586
+ const thisIdx = flatIdx;
3587
+ flatIdx++;
3588
+ const isCursor = isFocused && thisIdx === cursorIdx;
3589
+ const isActive = item.id === selectedId;
3590
+ return /* @__PURE__ */ jsx28(Box25, { gap: 0, children: /* @__PURE__ */ jsxs27(
3591
+ Text28,
3592
+ {
3593
+ color: isCursor ? inkColors.accent : isActive ? inkColors.accent : void 0,
3594
+ bold: isCursor || isActive,
3595
+ dimColor: !isCursor && !isActive,
3596
+ children: [
3597
+ isCursor ? `${symbols.pointerActive} ` : " ",
3598
+ item.icon,
3599
+ " ",
3600
+ item.label
3601
+ ]
3602
+ }
3603
+ ) }, item.id);
3604
+ })
3129
3605
  ]
3130
- }
3131
- ) }, item.id);
3606
+ },
3607
+ section.title
3608
+ );
3609
+ return rendered;
3132
3610
  }) });
3133
3611
  }
3134
3612
 
3135
3613
  // src/components/PanelFooter.tsx
3136
- import { Box as Box25, Text as Text26 } from "ink";
3137
- import { jsx as jsx27, jsxs as jsxs27 } from "react/jsx-runtime";
3614
+ import { Box as Box26, Text as Text29 } from "ink";
3615
+ import { jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
3138
3616
  function PanelFooter({ hints, width }) {
3139
- return /* @__PURE__ */ jsx27(Box25, { width, children: /* @__PURE__ */ jsx27(Box25, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsxs27(Box25, { gap: 0, children: [
3140
- /* @__PURE__ */ jsx27(Text26, { color: inkColors.accent, bold: true, children: hint.key }),
3141
- /* @__PURE__ */ jsxs27(Text26, { dimColor: true, children: [
3617
+ return /* @__PURE__ */ jsx29(Box26, { width, children: /* @__PURE__ */ jsx29(Box26, { gap: 1, children: hints.map((hint) => /* @__PURE__ */ jsxs28(Box26, { gap: 0, children: [
3618
+ /* @__PURE__ */ jsx29(Text29, { color: inkColors.accent, bold: true, children: hint.key }),
3619
+ /* @__PURE__ */ jsxs28(Text29, { dimColor: true, children: [
3142
3620
  ":",
3143
3621
  hint.action
3144
3622
  ] })
@@ -3146,8 +3624,8 @@ function PanelFooter({ hints, width }) {
3146
3624
  }
3147
3625
 
3148
3626
  // src/components/Modal.tsx
3149
- import { Box as Box26, Text as Text27 } from "ink";
3150
- import { jsx as jsx28, jsxs as jsxs28 } from "react/jsx-runtime";
3627
+ import { Box as Box27, Text as Text30 } from "ink";
3628
+ import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
3151
3629
  function Modal({
3152
3630
  title,
3153
3631
  width,
@@ -3158,10 +3636,10 @@ function Modal({
3158
3636
  const modalHeight = Math.min(height - 4, 20);
3159
3637
  const padX = Math.max(0, Math.floor((width - modalWidth) / 2));
3160
3638
  const padY = Math.max(0, Math.floor((height - modalHeight) / 2));
3161
- return /* @__PURE__ */ jsxs28(Box26, { flexDirection: "column", width, height, children: [
3162
- padY > 0 && /* @__PURE__ */ jsx28(Box26, { height: padY }),
3163
- /* @__PURE__ */ jsx28(Box26, { marginLeft: padX, children: /* @__PURE__ */ jsxs28(
3164
- Box26,
3639
+ return /* @__PURE__ */ jsxs29(Box27, { flexDirection: "column", width, height, children: [
3640
+ padY > 0 && /* @__PURE__ */ jsx30(Box27, { height: padY }),
3641
+ /* @__PURE__ */ jsx30(Box27, { marginLeft: padX, children: /* @__PURE__ */ jsxs29(
3642
+ Box27,
3165
3643
  {
3166
3644
  flexDirection: "column",
3167
3645
  width: modalWidth,
@@ -3170,8 +3648,8 @@ function Modal({
3170
3648
  borderColor: inkColors.accent,
3171
3649
  paddingX: 1,
3172
3650
  children: [
3173
- /* @__PURE__ */ jsx28(Box26, { marginBottom: 1, children: /* @__PURE__ */ jsx28(Text27, { color: inkColors.accent, bold: true, children: title }) }),
3174
- /* @__PURE__ */ jsx28(Box26, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
3651
+ /* @__PURE__ */ jsx30(Box27, { marginBottom: 1, children: /* @__PURE__ */ jsx30(Text30, { color: inkColors.accent, bold: true, children: title }) }),
3652
+ /* @__PURE__ */ jsx30(Box27, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children })
3175
3653
  ]
3176
3654
  }
3177
3655
  ) })
@@ -3179,9 +3657,9 @@ function Modal({
3179
3657
  }
3180
3658
 
3181
3659
  // src/components/FeatureCommands.tsx
3182
- import { useEffect as useEffect10, useMemo as useMemo10, useState as useState20 } from "react";
3183
- import { Box as Box27, Text as Text28 } from "ink";
3184
- import { jsx as jsx29, jsxs as jsxs29 } from "react/jsx-runtime";
3660
+ import { useEffect as useEffect10, useMemo as useMemo10, useState as useState21 } from "react";
3661
+ import { Box as Box28, Text as Text31 } from "ink";
3662
+ import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
3185
3663
  function FeatureCommands({
3186
3664
  feature,
3187
3665
  onNavigate,
@@ -3192,9 +3670,9 @@ function FeatureCommands({
3192
3670
  height = 24,
3193
3671
  isInputActive = true
3194
3672
  }) {
3195
- const [pinnedCommands, setPinnedCommands2] = useState20(() => getPinnedCommands());
3196
- const [pinnedRuns, setPinnedRuns2] = useState20(() => getPinnedRuns());
3197
- const [pinFeedback, setPinFeedback] = useState20();
3673
+ const [pinnedCommands, setPinnedCommands2] = useState21(() => getPinnedCommands());
3674
+ const [pinnedRuns, setPinnedRuns2] = useState21(() => getPinnedRuns());
3675
+ const [pinFeedback, setPinFeedback] = useState21();
3198
3676
  useEffect10(() => {
3199
3677
  if (!pinFeedback) return;
3200
3678
  const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
@@ -3205,7 +3683,8 @@ function FeatureCommands({
3205
3683
  activeFeature: feature,
3206
3684
  pinnedCommands,
3207
3685
  pinnedRuns,
3208
- showPinnedSection: false
3686
+ showPinnedSection: false,
3687
+ showFeatureHeader: false
3209
3688
  }),
3210
3689
  [feature, pinnedCommands, pinnedRuns]
3211
3690
  );
@@ -3262,17 +3741,12 @@ function FeatureCommands({
3262
3741
  );
3263
3742
  }
3264
3743
  };
3265
- return /* @__PURE__ */ jsxs29(Box27, { flexDirection: "column", paddingX: 1, children: [
3266
- /* @__PURE__ */ jsx29(Box27, { marginBottom: 1, children: /* @__PURE__ */ jsxs29(Text28, { color: inkColors.accent, bold: true, children: [
3267
- feature.icon,
3268
- " ",
3269
- feature.label
3270
- ] }) }),
3271
- pinFeedback && /* @__PURE__ */ jsx29(Box27, { marginBottom: 1, children: /* @__PURE__ */ jsxs29(Text28, { color: inkColors.accent, children: [
3744
+ return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: 1, children: [
3745
+ pinFeedback && /* @__PURE__ */ jsx31(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsxs30(Text31, { color: inkColors.accent, children: [
3272
3746
  "\u2713 ",
3273
3747
  pinFeedback
3274
3748
  ] }) }),
3275
- /* @__PURE__ */ jsx29(
3749
+ /* @__PURE__ */ jsx31(
3276
3750
  SelectList,
3277
3751
  {
3278
3752
  items,
@@ -3283,16 +3757,17 @@ function FeatureCommands({
3283
3757
  maxVisible: Math.max(6, height - 6),
3284
3758
  onCancel: onBack,
3285
3759
  isInputActive,
3286
- arrowNavigation: true
3760
+ arrowNavigation: true,
3761
+ panelFocused: isInputActive
3287
3762
  }
3288
3763
  )
3289
3764
  ] });
3290
3765
  }
3291
3766
 
3292
3767
  // src/components/PinnedCommands.tsx
3293
- import { useEffect as useEffect11, useMemo as useMemo11, useState as useState21 } from "react";
3294
- import { Box as Box28, Text as Text29 } from "ink";
3295
- import { jsx as jsx30, jsxs as jsxs30 } from "react/jsx-runtime";
3768
+ import { useEffect as useEffect11, useMemo as useMemo11, useState as useState22 } from "react";
3769
+ import { Box as Box29, Text as Text32 } from "ink";
3770
+ import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
3296
3771
  function PinnedCommands({
3297
3772
  onNavigate,
3298
3773
  onBack,
@@ -3301,9 +3776,9 @@ function PinnedCommands({
3301
3776
  height = 24,
3302
3777
  isInputActive = true
3303
3778
  }) {
3304
- const [pinnedCommands, setPinnedCommands2] = useState21(() => getPinnedCommands());
3305
- const [pinnedRuns, setPinnedRuns2] = useState21(() => getPinnedRuns());
3306
- const [pinFeedback, setPinFeedback] = useState21();
3779
+ const [pinnedCommands, setPinnedCommands2] = useState22(() => getPinnedCommands());
3780
+ const [pinnedRuns, setPinnedRuns2] = useState22(() => getPinnedRuns());
3781
+ const [pinFeedback, setPinFeedback] = useState22();
3307
3782
  useEffect11(() => {
3308
3783
  if (!pinFeedback) return;
3309
3784
  const timeout = setTimeout(() => setPinFeedback(void 0), 1400);
@@ -3366,18 +3841,14 @@ function PinnedCommands({
3366
3841
  }
3367
3842
  };
3368
3843
  if (items.length === 0) {
3369
- return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: 1, children: [
3370
- /* @__PURE__ */ jsx30(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsx30(Text29, { color: inkColors.accent, bold: true, children: "\u{1F4CC} Pinned" }) }),
3371
- /* @__PURE__ */ jsx30(Text29, { color: "gray", children: "No pinned items. Press p on any command to pin it." })
3372
- ] });
3844
+ return /* @__PURE__ */ jsx32(Box29, { flexDirection: "column", paddingX: 1, children: /* @__PURE__ */ jsx32(Text32, { color: "gray", children: "No pinned items. Press p on any command to pin it." }) });
3373
3845
  }
3374
- return /* @__PURE__ */ jsxs30(Box28, { flexDirection: "column", paddingX: 1, children: [
3375
- /* @__PURE__ */ jsx30(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsx30(Text29, { color: inkColors.accent, bold: true, children: "\u{1F4CC} Pinned" }) }),
3376
- pinFeedback && /* @__PURE__ */ jsx30(Box28, { marginBottom: 1, children: /* @__PURE__ */ jsxs30(Text29, { color: inkColors.accent, children: [
3846
+ return /* @__PURE__ */ jsxs31(Box29, { flexDirection: "column", paddingX: 1, children: [
3847
+ pinFeedback && /* @__PURE__ */ jsx32(Box29, { marginBottom: 1, children: /* @__PURE__ */ jsxs31(Text32, { color: inkColors.accent, children: [
3377
3848
  "\u2713 ",
3378
3849
  pinFeedback
3379
3850
  ] }) }),
3380
- /* @__PURE__ */ jsx30(
3851
+ /* @__PURE__ */ jsx32(
3381
3852
  SelectList,
3382
3853
  {
3383
3854
  items,
@@ -3388,21 +3859,76 @@ function PinnedCommands({
3388
3859
  maxVisible: Math.max(6, height - 6),
3389
3860
  onCancel: onBack,
3390
3861
  isInputActive,
3391
- arrowNavigation: true
3862
+ arrowNavigation: true,
3863
+ panelFocused: isInputActive
3392
3864
  }
3393
3865
  )
3394
3866
  ] });
3395
3867
  }
3396
3868
 
3397
3869
  // src/appPanel.tsx
3398
- import { jsx as jsx31, jsxs as jsxs31 } from "react/jsx-runtime";
3870
+ import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
3871
+ var screenLabels = {
3872
+ "command-args": "Args",
3873
+ "flag-selection": "Flags",
3874
+ "confirm-execute": "Execute",
3875
+ "command-execution": "Execute",
3876
+ "custom-command": "Custom Cmd",
3877
+ "pipeline-list": "Pipelines",
3878
+ "pipeline-builder": "Builder",
3879
+ "pipeline-execution": "Run",
3880
+ "self-update": "Update",
3881
+ "tool-status": "Status",
3882
+ "project-config": "Config"
3883
+ };
3884
+ function buildBreadcrumb(nav) {
3885
+ let base;
3886
+ switch (nav.view) {
3887
+ case "feature": {
3888
+ const feat = getFeatureById(nav.featureId);
3889
+ base = feat ? `${feat.icon} ${feat.label}` : nav.featureId;
3890
+ break;
3891
+ }
3892
+ case "pinned":
3893
+ base = "\u{1F4CC} Pinned";
3894
+ break;
3895
+ case "custom-command":
3896
+ base = "\u270F\uFE0F Custom Cmd";
3897
+ break;
3898
+ case "pipelines":
3899
+ base = "\u{1F517} Pipelines";
3900
+ break;
3901
+ case "tool-status":
3902
+ base = "\u{1F527} Status";
3903
+ break;
3904
+ case "config":
3905
+ base = "\u2699\uFE0F Config";
3906
+ break;
3907
+ case "self-update":
3908
+ base = "\u2B06\uFE0F Update";
3909
+ break;
3910
+ default:
3911
+ base = nav.view;
3912
+ }
3913
+ if (nav.innerScreen === "home") {
3914
+ return base;
3915
+ }
3916
+ const parts = [base];
3917
+ for (const entry of nav.innerStack) {
3918
+ if (entry.screen !== "home") {
3919
+ parts.push(screenLabels[entry.screen] ?? entry.screen);
3920
+ }
3921
+ }
3922
+ parts.push(screenLabels[nav.innerScreen] ?? nav.innerScreen);
3923
+ return parts.join(" \u203A ");
3924
+ }
3399
3925
  var FOOTER_HINTS = [
3400
- { key: "\u2190\u2192", action: "panels" },
3926
+ { key: "Tab", action: "focus" },
3927
+ { key: "\u2190/Esc", action: "back" },
3928
+ { key: "\u2192/Enter", action: "select" },
3401
3929
  { key: "j/k", action: "nav" },
3402
- { key: "Enter", action: "select" },
3403
- { key: "Esc", action: "back" },
3404
- { key: "q", action: "quit" },
3405
3930
  { key: "p", action: "pin" },
3931
+ { key: "q", action: "quit" },
3406
3932
  { key: "?", action: "help" }
3407
3933
  ];
3408
3934
  function AppPanel() {
@@ -3411,18 +3937,10 @@ function AppPanel() {
3411
3937
  const { exit } = useApp2();
3412
3938
  const nav = usePanelNavigation();
3413
3939
  const focus = usePanelFocus();
3414
- const [hasPins, setHasPins] = React18.useState(
3415
- () => getPinnedCommands().length > 0 || getPinnedRuns().length > 0
3416
- );
3417
- const sidebarItems = useSidebarItems(hasPins);
3940
+ const sidebarItems = useSidebarItems();
3418
3941
  const modal = useModal();
3419
- const refreshPins = React18.useCallback(() => {
3420
- const newHasPins = getPinnedCommands().length > 0 || getPinnedRuns().length > 0;
3421
- setHasPins(newHasPins);
3422
- if (!newHasPins && nav.view === "pinned") {
3423
- nav.selectSidebarItem("database");
3424
- }
3425
- }, [nav.view, nav.selectSidebarItem]);
3942
+ const refreshPins = React19.useCallback(() => {
3943
+ }, []);
3426
3944
  const singlePanel = width < 60 || height < 15;
3427
3945
  const handleExit = () => {
3428
3946
  process.stdout.write(
@@ -3430,7 +3948,7 @@ function AppPanel() {
3430
3948
  );
3431
3949
  exit();
3432
3950
  };
3433
- useInput7((input2, key) => {
3951
+ useInput9((input2, key) => {
3434
3952
  if (modal.isOpen) {
3435
3953
  if (key.escape || input2 === "q") {
3436
3954
  modal.closeModal();
@@ -3455,37 +3973,37 @@ function AppPanel() {
3455
3973
  }
3456
3974
  if (input2 === "?") {
3457
3975
  modal.openModal(
3458
- /* @__PURE__ */ jsxs31(Box29, { flexDirection: "column", children: [
3459
- /* @__PURE__ */ jsxs31(Text30, { children: [
3460
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "\u2190/\u2192" }),
3976
+ /* @__PURE__ */ jsxs32(Box30, { flexDirection: "column", children: [
3977
+ /* @__PURE__ */ jsxs32(Text33, { children: [
3978
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "\u2190/\u2192" }),
3461
3979
  " Move between sidebar and main panel"
3462
3980
  ] }),
3463
- /* @__PURE__ */ jsxs31(Text30, { children: [
3464
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "Tab" }),
3981
+ /* @__PURE__ */ jsxs32(Text33, { children: [
3982
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "Tab" }),
3465
3983
  " Toggle sidebar / main panel"
3466
3984
  ] }),
3467
- /* @__PURE__ */ jsxs31(Text30, { children: [
3468
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "j/k" }),
3985
+ /* @__PURE__ */ jsxs32(Text33, { children: [
3986
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "j/k" }),
3469
3987
  " Navigate up/down"
3470
3988
  ] }),
3471
- /* @__PURE__ */ jsxs31(Text30, { children: [
3472
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "Enter" }),
3989
+ /* @__PURE__ */ jsxs32(Text33, { children: [
3990
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "Enter" }),
3473
3991
  " Select item"
3474
3992
  ] }),
3475
- /* @__PURE__ */ jsxs31(Text30, { children: [
3476
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "Esc" }),
3993
+ /* @__PURE__ */ jsxs32(Text33, { children: [
3994
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "Esc" }),
3477
3995
  " Go back (or return to sidebar)"
3478
3996
  ] }),
3479
- /* @__PURE__ */ jsxs31(Text30, { children: [
3480
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "q" }),
3997
+ /* @__PURE__ */ jsxs32(Text33, { children: [
3998
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "q" }),
3481
3999
  " Quit Polter"
3482
4000
  ] }),
3483
- /* @__PURE__ */ jsxs31(Text30, { children: [
3484
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "?" }),
4001
+ /* @__PURE__ */ jsxs32(Text33, { children: [
4002
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "?" }),
3485
4003
  " Show this help"
3486
4004
  ] }),
3487
- /* @__PURE__ */ jsxs31(Text30, { children: [
3488
- /* @__PURE__ */ jsx31(Text30, { bold: true, children: "p" }),
4005
+ /* @__PURE__ */ jsxs32(Text33, { children: [
4006
+ /* @__PURE__ */ jsx33(Text33, { bold: true, children: "p" }),
3489
4007
  " Pin/unpin command"
3490
4008
  ] })
3491
4009
  ] }),
@@ -3535,7 +4053,7 @@ function AppPanel() {
3535
4053
  }
3536
4054
  switch (nav.view) {
3537
4055
  case "pinned":
3538
- return /* @__PURE__ */ jsx31(
4056
+ return /* @__PURE__ */ jsx33(
3539
4057
  PinnedCommands,
3540
4058
  {
3541
4059
  onNavigate: nav.navigateInner,
@@ -3549,12 +4067,12 @@ function AppPanel() {
3549
4067
  case "feature": {
3550
4068
  const feature = getFeatureById(nav.featureId);
3551
4069
  if (!feature) {
3552
- return /* @__PURE__ */ jsxs31(Text30, { color: "red", children: [
4070
+ return /* @__PURE__ */ jsxs32(Text33, { color: "red", children: [
3553
4071
  "Feature not found: ",
3554
4072
  nav.featureId
3555
4073
  ] });
3556
4074
  }
3557
- return /* @__PURE__ */ jsx31(
4075
+ return /* @__PURE__ */ jsx33(
3558
4076
  FeatureCommands,
3559
4077
  {
3560
4078
  feature,
@@ -3569,60 +4087,65 @@ function AppPanel() {
3569
4087
  );
3570
4088
  }
3571
4089
  case "custom-command":
3572
- return /* @__PURE__ */ jsx31(
4090
+ return /* @__PURE__ */ jsx33(
3573
4091
  CustomCommand,
3574
4092
  {
3575
4093
  onNavigate: nav.navigateInner,
3576
4094
  onBack: focus.focusSidebar,
3577
4095
  width: mainContentWidth - 2,
4096
+ height: mainContentHeight,
3578
4097
  panelMode: true,
3579
4098
  isInputActive: focus.isMainFocused
3580
4099
  }
3581
4100
  );
3582
4101
  case "pipelines":
3583
- return /* @__PURE__ */ jsx31(
4102
+ return /* @__PURE__ */ jsx33(
3584
4103
  PipelineList,
3585
4104
  {
3586
4105
  onNavigate: nav.navigateInner,
3587
4106
  onBack: focus.focusSidebar,
3588
4107
  width: mainContentWidth - 2,
4108
+ height: mainContentHeight,
3589
4109
  panelMode: true,
3590
4110
  isInputActive: focus.isMainFocused
3591
4111
  }
3592
4112
  );
3593
4113
  case "tool-status":
3594
- return /* @__PURE__ */ jsx31(
4114
+ return /* @__PURE__ */ jsx33(
3595
4115
  ToolStatus,
3596
4116
  {
3597
4117
  onBack: focus.focusSidebar,
3598
4118
  width: mainContentWidth - 2,
4119
+ height: mainContentHeight,
3599
4120
  panelMode: true,
3600
4121
  isInputActive: focus.isMainFocused
3601
4122
  }
3602
4123
  );
3603
4124
  case "config":
3604
- return /* @__PURE__ */ jsx31(
4125
+ return /* @__PURE__ */ jsx33(
3605
4126
  ProjectConfig,
3606
4127
  {
3607
4128
  onBack: focus.focusSidebar,
3608
4129
  width: mainContentWidth - 2,
4130
+ height: mainContentHeight,
3609
4131
  panelMode: true,
3610
4132
  isInputActive: focus.isMainFocused
3611
4133
  }
3612
4134
  );
3613
4135
  case "self-update":
3614
- return /* @__PURE__ */ jsx31(
4136
+ return /* @__PURE__ */ jsx33(
3615
4137
  SelfUpdate,
3616
4138
  {
3617
4139
  onBack: focus.focusSidebar,
3618
4140
  onExit: handleExit,
3619
4141
  width: mainContentWidth - 2,
4142
+ height: mainContentHeight,
3620
4143
  panelMode: true,
3621
4144
  isInputActive: focus.isMainFocused
3622
4145
  }
3623
4146
  );
3624
4147
  default:
3625
- return /* @__PURE__ */ jsx31(Text30, { children: "Select an item from the sidebar" });
4148
+ return /* @__PURE__ */ jsx33(Text33, { children: "Select an item from the sidebar" });
3626
4149
  }
3627
4150
  };
3628
4151
  const renderInnerScreen = () => {
@@ -3630,7 +4153,7 @@ function AppPanel() {
3630
4153
  const w = mainContentWidth - 2;
3631
4154
  switch (nav.innerScreen) {
3632
4155
  case "command-args":
3633
- return /* @__PURE__ */ jsx31(
4156
+ return /* @__PURE__ */ jsx33(
3634
4157
  CommandArgs,
3635
4158
  {
3636
4159
  command: nav.innerParams.command ?? "",
@@ -3643,18 +4166,19 @@ function AppPanel() {
3643
4166
  }
3644
4167
  );
3645
4168
  case "custom-command":
3646
- return /* @__PURE__ */ jsx31(
4169
+ return /* @__PURE__ */ jsx33(
3647
4170
  CustomCommand,
3648
4171
  {
3649
4172
  onNavigate: nav.navigateInner,
3650
4173
  onBack: nav.goBackInner,
3651
4174
  width: w,
4175
+ height: mainContentHeight,
3652
4176
  panelMode: true,
3653
4177
  isInputActive: isActive
3654
4178
  }
3655
4179
  );
3656
4180
  case "flag-selection":
3657
- return /* @__PURE__ */ jsx31(
4181
+ return /* @__PURE__ */ jsx33(
3658
4182
  FlagSelection,
3659
4183
  {
3660
4184
  args: nav.innerParams.args ?? [],
@@ -3662,37 +4186,45 @@ function AppPanel() {
3662
4186
  onNavigate: nav.navigateInner,
3663
4187
  onBack: nav.goBackInner,
3664
4188
  width: w,
4189
+ height: mainContentHeight,
3665
4190
  panelMode: true,
3666
4191
  isInputActive: isActive
3667
4192
  }
3668
4193
  );
3669
4194
  case "confirm-execute":
3670
4195
  case "command-execution":
3671
- return /* @__PURE__ */ jsx31(
4196
+ return /* @__PURE__ */ jsx33(
3672
4197
  CommandExecution,
3673
4198
  {
3674
4199
  args: nav.innerParams.args ?? [],
3675
4200
  tool: nav.innerParams.tool,
3676
4201
  onBack: nav.goBackInner,
4202
+ onHome: nav.goHomeInner,
3677
4203
  onExit: handleExit,
4204
+ onRunSuggestion: (sugTool, sugArgs) => {
4205
+ nav.switchViewAndNavigate("custom-command", "confirm-execute", { tool: sugTool, args: sugArgs });
4206
+ },
3678
4207
  width: w,
4208
+ height: mainContentHeight,
3679
4209
  panelMode: true,
3680
4210
  isInputActive: isActive
3681
- }
4211
+ },
4212
+ `${nav.view}-${nav.innerParams.tool}-${(nav.innerParams.args ?? []).join("-")}`
3682
4213
  );
3683
4214
  case "pipeline-list":
3684
- return /* @__PURE__ */ jsx31(
4215
+ return /* @__PURE__ */ jsx33(
3685
4216
  PipelineList,
3686
4217
  {
3687
4218
  onNavigate: nav.navigateInner,
3688
4219
  onBack: nav.goBackInner,
3689
4220
  width: w,
4221
+ height: mainContentHeight,
3690
4222
  panelMode: true,
3691
4223
  isInputActive: isActive
3692
4224
  }
3693
4225
  );
3694
4226
  case "pipeline-builder":
3695
- return /* @__PURE__ */ jsx31(
4227
+ return /* @__PURE__ */ jsx33(
3696
4228
  PipelineBuilder,
3697
4229
  {
3698
4230
  onBack: nav.goBackInner,
@@ -3703,7 +4235,7 @@ function AppPanel() {
3703
4235
  }
3704
4236
  );
3705
4237
  case "pipeline-execution":
3706
- return /* @__PURE__ */ jsx31(
4238
+ return /* @__PURE__ */ jsx33(
3707
4239
  PipelineExecution,
3708
4240
  {
3709
4241
  pipelineId: nav.innerParams.pipelineId ?? "",
@@ -3715,48 +4247,51 @@ function AppPanel() {
3715
4247
  }
3716
4248
  );
3717
4249
  case "self-update":
3718
- return /* @__PURE__ */ jsx31(
4250
+ return /* @__PURE__ */ jsx33(
3719
4251
  SelfUpdate,
3720
4252
  {
3721
4253
  onBack: nav.goBackInner,
3722
4254
  onExit: handleExit,
3723
4255
  width: w,
4256
+ height: mainContentHeight,
3724
4257
  panelMode: true,
3725
4258
  isInputActive: isActive
3726
4259
  }
3727
4260
  );
3728
4261
  case "tool-status":
3729
- return /* @__PURE__ */ jsx31(
4262
+ return /* @__PURE__ */ jsx33(
3730
4263
  ToolStatus,
3731
4264
  {
3732
4265
  onBack: nav.goBackInner,
3733
4266
  width: w,
4267
+ height: mainContentHeight,
3734
4268
  panelMode: true,
3735
4269
  isInputActive: isActive
3736
4270
  }
3737
4271
  );
3738
4272
  case "project-config":
3739
- return /* @__PURE__ */ jsx31(
4273
+ return /* @__PURE__ */ jsx33(
3740
4274
  ProjectConfig,
3741
4275
  {
3742
4276
  onBack: nav.goBackInner,
3743
4277
  width: w,
4278
+ height: mainContentHeight,
3744
4279
  panelMode: true,
3745
4280
  isInputActive: isActive
3746
4281
  }
3747
4282
  );
3748
4283
  default:
3749
- return /* @__PURE__ */ jsxs31(Text30, { color: "red", children: [
4284
+ return /* @__PURE__ */ jsxs32(Text33, { color: "red", children: [
3750
4285
  "Unknown screen: ",
3751
4286
  nav.innerScreen
3752
4287
  ] });
3753
4288
  }
3754
4289
  };
3755
4290
  if (modal.isOpen) {
3756
- return /* @__PURE__ */ jsx31(Box29, { flexDirection: "column", width, height, children: /* @__PURE__ */ jsx31(Modal, { title: modal.modalTitle, width, height, children: modal.modalContent }) });
4291
+ return /* @__PURE__ */ jsx33(Box30, { flexDirection: "column", width, height, children: /* @__PURE__ */ jsx33(Modal, { title: modal.modalTitle, width, height, children: modal.modalContent }) });
3757
4292
  }
3758
- const header = /* @__PURE__ */ jsx31(GhostBanner, { width, compact: true });
3759
- const sidebar = /* @__PURE__ */ jsx31(
4293
+ const header = /* @__PURE__ */ jsx33(GhostBanner, { width, compact: true });
4294
+ const sidebar = /* @__PURE__ */ jsx33(
3760
4295
  Panel,
3761
4296
  {
3762
4297
  id: "sidebar",
@@ -3764,7 +4299,7 @@ function AppPanel() {
3764
4299
  width: Math.max(20, Math.min(35, Math.floor(width * 0.3))),
3765
4300
  height: Math.max(5, height - bannerHeight - 1),
3766
4301
  focused: focus.isSidebarFocused,
3767
- children: /* @__PURE__ */ jsx31(
4302
+ children: /* @__PURE__ */ jsx33(
3768
4303
  Sidebar,
3769
4304
  {
3770
4305
  items: sidebarItems,
@@ -3777,19 +4312,19 @@ function AppPanel() {
3777
4312
  )
3778
4313
  }
3779
4314
  );
3780
- const main2 = /* @__PURE__ */ jsx31(
4315
+ const main2 = /* @__PURE__ */ jsx33(
3781
4316
  Panel,
3782
4317
  {
3783
4318
  id: "main",
3784
- title: nav.view === "feature" ? getFeatureById(nav.featureId)?.label : nav.view === "pinned" ? "Pinned" : nav.view,
4319
+ title: buildBreadcrumb(nav),
3785
4320
  width: mainContentWidth,
3786
4321
  height: Math.max(5, height - bannerHeight - 1),
3787
4322
  focused: focus.isMainFocused,
3788
4323
  children: renderMainContent()
3789
4324
  }
3790
4325
  );
3791
- const footer = /* @__PURE__ */ jsx31(PanelFooter, { hints: footerHints, width });
3792
- return /* @__PURE__ */ jsx31(
4326
+ const footer = /* @__PURE__ */ jsx33(PanelFooter, { hints: footerHints, width });
4327
+ return /* @__PURE__ */ jsx33(
3793
4328
  PanelLayout,
3794
4329
  {
3795
4330
  header,
@@ -3832,11 +4367,17 @@ function parseCliArgs(argv) {
3832
4367
  if (argv_[0] === "pipeline" && argv_[1] === "run" && argv_[2]) {
3833
4368
  return { mode: "pipeline-run", options: {}, pipelineName: argv_[2] };
3834
4369
  }
3835
- if (argv_[0] === "mcp" && argv_[1] === "install") {
3836
- let mcpScope = "local";
3837
- if (argv_.includes("--project")) mcpScope = "project";
3838
- else if (argv_.includes("--global")) mcpScope = "user";
3839
- return { mode: "mcp-install", options: {}, mcpScope };
4370
+ if (argv_[0] === "mcp") {
4371
+ const sub = argv_[1];
4372
+ if (sub === "status") {
4373
+ return { mode: "mcp", options: {}, mcpAction: "status" };
4374
+ }
4375
+ if (sub === "install" || sub === "update" || sub === "remove") {
4376
+ let mcpScope = "local";
4377
+ if (argv_.includes("--project")) mcpScope = "project";
4378
+ else if (argv_.includes("--global")) mcpScope = "user";
4379
+ return { mode: "mcp", options: {}, mcpAction: sub, mcpScope };
4380
+ }
3840
4381
  }
3841
4382
  if (argv_[0] === "config") {
3842
4383
  const edit = argv_.includes("--edit");
@@ -3925,6 +4466,9 @@ function printCliHelp() {
3925
4466
  " polter mcp install Install Polter MCP server into Claude Code (local scope)",
3926
4467
  " polter mcp install --project Install for this project only (shared via repo)",
3927
4468
  " polter mcp install --global Install globally for all projects",
4469
+ " polter mcp update Update MCP server to latest version",
4470
+ " polter mcp status Show MCP registration and version info",
4471
+ " polter mcp remove Remove MCP server registration",
3928
4472
  "",
3929
4473
  " polter app setup ops [--path <dir>] [--create-project|--use-existing-project] [--yes]",
3930
4474
  " polter app link ops [--path <dir>] [--relink]",
@@ -4750,8 +5294,10 @@ import { spawnSync as spawnSync2 } from "child_process";
4750
5294
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2 } from "fs";
4751
5295
  import { join as join3 } from "path";
4752
5296
  import { homedir as homedir2 } from "os";
5297
+ import { createRequire as createRequire2 } from "module";
4753
5298
  import pc4 from "picocolors";
4754
- var MCP_ARGS = ["npx", "-y", "-p", "@polterware/polter", "polter-mcp"];
5299
+ var require3 = createRequire2(import.meta.url);
5300
+ var MCP_ARGS = ["npx", "-y", "-p", "@polterware/polter@latest", "polter-mcp"];
4755
5301
  var SCOPE_LABELS = {
4756
5302
  local: "local (this machine)",
4757
5303
  project: "project (shared via repo)",
@@ -4789,7 +5335,7 @@ function tryManualInstall(scope) {
4789
5335
  const mcpServers = settings.mcpServers ?? {};
4790
5336
  mcpServers.polter = {
4791
5337
  command: "npx",
4792
- args: ["-y", "-p", "@polterware/polter", "polter-mcp"]
5338
+ args: ["-y", "-p", "@polterware/polter@latest", "polter-mcp"]
4793
5339
  };
4794
5340
  settings.mcpServers = mcpServers;
4795
5341
  writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n");
@@ -4815,11 +5361,93 @@ async function installMcpServer(scope) {
4815
5361
  process.stdout.write(pc4.green("\n Done! Restart Claude Code to use Polter tools.\n"));
4816
5362
  } else {
4817
5363
  process.stderr.write(pc4.red("\n Failed to install. Add manually:\n\n"));
4818
- process.stderr.write(` ${pc4.dim(JSON.stringify({ mcpServers: { polter: { command: "npx", args: ["-y", "-p", "@polterware/polter", "polter-mcp"] } } }, null, 2))}
5364
+ process.stderr.write(` ${pc4.dim(JSON.stringify({ mcpServers: { polter: { command: "npx", args: ["-y", "-p", "@polterware/polter@latest", "polter-mcp"] } } }, null, 2))}
4819
5365
  `);
4820
5366
  process.exit(1);
4821
5367
  }
4822
5368
  }
5369
+ async function removeMcpServer(scope) {
5370
+ process.stdout.write(pc4.bold(`Removing Polter MCP server \u2014 ${SCOPE_LABELS[scope]}
5371
+
5372
+ `));
5373
+ if (commandExists("claude")) {
5374
+ const result = spawnSync2("claude", ["mcp", "remove", "-s", scope, "polter"], {
5375
+ stdio: "inherit",
5376
+ shell: true
5377
+ });
5378
+ if (result.status === 0) {
5379
+ process.stdout.write(pc4.green("\n Done! Polter MCP server removed.\n"));
5380
+ return;
5381
+ }
5382
+ process.stdout.write(pc4.yellow(" 'claude mcp remove' failed, falling back to manual removal...\n\n"));
5383
+ }
5384
+ const settingsPath = getSettingsPath(scope);
5385
+ if (!existsSync2(settingsPath)) {
5386
+ process.stdout.write(pc4.yellow(" No settings file found. Nothing to remove.\n"));
5387
+ return;
5388
+ }
5389
+ let settings;
5390
+ try {
5391
+ settings = JSON.parse(readFileSync2(settingsPath, "utf-8"));
5392
+ } catch {
5393
+ process.stderr.write(pc4.red(` Failed to parse ${settingsPath}
5394
+ `));
5395
+ process.exit(1);
5396
+ return;
5397
+ }
5398
+ const mcpServers = settings.mcpServers;
5399
+ if (!mcpServers?.polter) {
5400
+ process.stdout.write(pc4.yellow(" Polter MCP server not found in settings. Nothing to remove.\n"));
5401
+ return;
5402
+ }
5403
+ delete mcpServers.polter;
5404
+ settings.mcpServers = mcpServers;
5405
+ writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n");
5406
+ process.stdout.write(pc4.green(" Done! Polter MCP server removed.\n"));
5407
+ }
5408
+ async function mcpStatus() {
5409
+ process.stdout.write(pc4.bold("Polter MCP Server Status\n\n"));
5410
+ const pkg = require3("../../package.json");
5411
+ process.stdout.write(` Installed version: ${pc4.cyan(pkg.version)}
5412
+ `);
5413
+ const latestResult = spawnSync2("npm", ["view", "@polterware/polter", "version"], {
5414
+ encoding: "utf-8",
5415
+ shell: true,
5416
+ timeout: 1e4
5417
+ });
5418
+ const latest = latestResult.stdout?.trim();
5419
+ if (latest) {
5420
+ const upToDate = latest === pkg.version;
5421
+ process.stdout.write(` Latest version: ${upToDate ? pc4.green(latest) : pc4.yellow(`${latest} (update available)`)}
5422
+ `);
5423
+ }
5424
+ process.stdout.write("\n");
5425
+ const scopes = [
5426
+ { label: "Project (.mcp.json)", path: join3(process.cwd(), ".mcp.json"), key: "project" },
5427
+ { label: "User (~/.claude/settings.json)", path: join3(homedir2(), ".claude", "settings.json"), key: "user" }
5428
+ ];
5429
+ for (const scope of scopes) {
5430
+ if (!existsSync2(scope.path)) {
5431
+ process.stdout.write(` ${scope.label}: ${pc4.dim("not found")}
5432
+ `);
5433
+ continue;
5434
+ }
5435
+ try {
5436
+ const settings = JSON.parse(readFileSync2(scope.path, "utf-8"));
5437
+ const mcpServers = settings.mcpServers;
5438
+ if (mcpServers?.polter) {
5439
+ process.stdout.write(` ${scope.label}: ${pc4.green("registered")}
5440
+ `);
5441
+ } else {
5442
+ process.stdout.write(` ${scope.label}: ${pc4.dim("not registered")}
5443
+ `);
5444
+ }
5445
+ } catch {
5446
+ process.stdout.write(` ${scope.label}: ${pc4.red("error reading file")}
5447
+ `);
5448
+ }
5449
+ }
5450
+ }
4823
5451
 
4824
5452
  // src/index.tsx
4825
5453
  import pc5 from "picocolors";
@@ -4829,8 +5457,20 @@ async function main() {
4829
5457
  printCliHelp();
4830
5458
  return;
4831
5459
  }
4832
- if (parsed.mode === "mcp-install") {
4833
- await installMcpServer(parsed.mcpScope ?? "local");
5460
+ if (parsed.mode === "mcp") {
5461
+ const scope = parsed.mcpScope ?? "local";
5462
+ switch (parsed.mcpAction) {
5463
+ case "install":
5464
+ case "update":
5465
+ await installMcpServer(scope);
5466
+ break;
5467
+ case "remove":
5468
+ await removeMcpServer(scope);
5469
+ break;
5470
+ case "status":
5471
+ await mcpStatus();
5472
+ break;
5473
+ }
4834
5474
  return;
4835
5475
  }
4836
5476
  if (parsed.mode === "app") {
@@ -4867,7 +5507,7 @@ Pipeline completed with ${errors.length} error(s)
4867
5507
  return;
4868
5508
  }
4869
5509
  if (parsed.mode === "status") {
4870
- const tools = ["supabase", "gh", "vercel"];
5510
+ const tools = ["supabase", "gh", "vercel", "git"];
4871
5511
  process.stdout.write(pc5.bold("Tool Status\n\n"));
4872
5512
  for (const toolId of tools) {
4873
5513
  const info = getToolInfo(toolId);
@@ -4958,11 +5598,11 @@ Apply completed with ${errors.length} error(s).
4958
5598
  process.exit(result.exitCode ?? 0);
4959
5599
  }
4960
5600
  const AppComponent2 = parsed.classic ? AppClassic : AppPanel;
4961
- render(React19.createElement(AppComponent2));
5601
+ render(React20.createElement(AppComponent2));
4962
5602
  return;
4963
5603
  }
4964
5604
  const AppComponent = parsed.classic ? AppClassic : AppPanel;
4965
- render(React19.createElement(AppComponent));
5605
+ render(React20.createElement(AppComponent));
4966
5606
  }
4967
5607
  main().catch((error) => {
4968
5608
  const message = error instanceof Error ? error.message : String(error);