playbooks 0.1.17 → 0.1.19

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.
Files changed (2) hide show
  1. package/dist/index.js +1295 -995
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { program } from "commander";
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "playbooks",
11
- version: "0.1.17",
11
+ version: "0.1.19",
12
12
  description: "Install agent skills, MCPs and docs into your coding agents from any git repository.",
13
13
  type: "module",
14
14
  bin: {
@@ -656,6 +656,31 @@ async function pollUrlMarkdown(jobId, timeoutMs = 6e4, pollIntervalMs = 1e3) {
656
656
  }
657
657
  throw new Error("Timed out waiting for markdown");
658
658
  }
659
+ async function fetchBundle(slug) {
660
+ const url = new URL(`${API_BASE}/bundles/${encodeURIComponent(slug)}`);
661
+ const response = await fetch(url.toString(), {
662
+ headers: {
663
+ "User-Agent": USER_AGENT
664
+ }
665
+ });
666
+ let payload = null;
667
+ try {
668
+ payload = await response.json();
669
+ } catch {
670
+ payload = null;
671
+ }
672
+ if (response.status === 404) {
673
+ throw new Error(`Bundle "${slug}" not found.`);
674
+ }
675
+ if (!response.ok || !payload?.success) {
676
+ const message = payload?.error || `Failed to fetch bundle (${response.status})`;
677
+ throw new Error(message);
678
+ }
679
+ if (!payload.bundle || !payload.skills) {
680
+ throw new Error("Invalid bundle response.");
681
+ }
682
+ return { bundle: payload.bundle, skills: payload.skills };
683
+ }
659
684
  async function fetchUrlMarkdown(url) {
660
685
  const response = await requestUrlMarkdown(url);
661
686
  if (response.success && response.data) {
@@ -1310,93 +1335,656 @@ function BrandHeader() {
1310
1335
  setTitle(TARGET_TEXT);
1311
1336
  return false;
1312
1337
  }
1313
- return true;
1338
+ return true;
1339
+ };
1340
+ tick();
1341
+ const timer = setInterval(() => {
1342
+ if (!tick()) {
1343
+ clearInterval(timer);
1344
+ }
1345
+ }, interval);
1346
+ return () => {
1347
+ clearInterval(timer);
1348
+ };
1349
+ }, []);
1350
+ return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [
1351
+ /* @__PURE__ */ jsx2(Text, { bold: true, children: title }),
1352
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: TAGLINE })
1353
+ ] });
1354
+ }
1355
+
1356
+ // src/tui/ui/FlashBar.tsx
1357
+ import { Box as Box2, Text as Text2 } from "ink";
1358
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1359
+ function classify(msg) {
1360
+ const m = msg.toLowerCase();
1361
+ if (/(error|failed|unable|denied|invalid|cannot|not found)/i.test(msg)) return "error";
1362
+ if (/(deleted|linked|unlinked|updated|created|saved|enabled|disabled|added|removed|✓)/i.test(msg))
1363
+ return "success";
1364
+ if (/(warn|deprecated|missing|retry|timeout)/i.test(msg)) return "warning";
1365
+ return "info";
1366
+ }
1367
+ function FlashBar({ align = "left" }) {
1368
+ const { flashes } = useNavigation();
1369
+ if (flashes.length === 0) return /* @__PURE__ */ jsx3(Box2, { height: 1 });
1370
+ return /* @__PURE__ */ jsx3(
1371
+ Box2,
1372
+ {
1373
+ flexDirection: "column",
1374
+ paddingX: 1,
1375
+ paddingY: 0,
1376
+ gap: 0,
1377
+ justifyContent: align === "center" ? "center" : "flex-start",
1378
+ children: flashes.map((flash) => {
1379
+ const kind = classify(flash.text);
1380
+ const color = kind === "success" ? "green" : kind === "error" ? "red" : kind === "warning" ? "yellow" : "cyan";
1381
+ const label = kind === "success" ? "\u2713" : kind === "error" ? "x" : kind === "warning" ? "!" : "i";
1382
+ return /* @__PURE__ */ jsxs2(Text2, { color, children: [
1383
+ "[",
1384
+ label,
1385
+ "] ",
1386
+ flash.text
1387
+ ] }, flash.id);
1388
+ })
1389
+ }
1390
+ );
1391
+ }
1392
+
1393
+ // src/tui/screens/AddBundleSelect.tsx
1394
+ import { basename as basename4 } from "path";
1395
+ import { Box as Box6, Text as Text6 } from "ink";
1396
+ import React5 from "react";
1397
+
1398
+ // src/tui/controls/MultiSelect.tsx
1399
+ import { Box as Box3, Text as Text3, useInput } from "ink";
1400
+ import React3 from "react";
1401
+
1402
+ // src/tui/ui/hints.ts
1403
+ var TEXT_INPUT_HINT = "Ctrl+D to clear, Esc to go back";
1404
+ var MENU_HINT = "Use \u2191\u2193 to navigate, Enter to select, m for main, q/esc to quit";
1405
+ var SINGLE_SELECT_HINT = "Use \u2191\u2193 to navigate, Enter to continue, m for main, q/esc to quit";
1406
+ var MULTI_SELECT_HINT = "Space to toggle, s to select all, Enter to continue, m for main, q/esc to quit";
1407
+ var BACK_QUIT_HINT = "Press \u2190 to go back, q/esc to quit";
1408
+ var FIND_SKILLS_HINT = "Space to select one or more skills, then Enter to install.";
1409
+ var FIND_RESULTS_HINT = "Space to toggle, s to select all, i for info, Enter to install, q/esc to quit";
1410
+ var UPDATE_HINT_NEEDS_ONLY = "Showing needs update only. u to show all, s to select all, m for main, q/esc to quit";
1411
+ var UPDATE_HINT_ALL = "u to show needs update only, s to select all, m for main, q/esc to quit";
1412
+ var UPDATE_EMPTY_HINT = "Press u to show all, m for main, q/esc to quit";
1413
+ var SCAN_SKILLS_HINT = "Use \u2191\u2193 to navigate, i for info, Enter for actions, m for main, q/esc to quit";
1414
+
1415
+ // src/tui/controls/MultiSelect.tsx
1416
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1417
+ var FILTER_THRESHOLD = 10;
1418
+ function MultiSelect({
1419
+ items,
1420
+ initialSelected = [],
1421
+ onSubmit,
1422
+ limit = 10,
1423
+ hint = MULTI_SELECT_HINT,
1424
+ enableFilter,
1425
+ lockedSection,
1426
+ hintMode = "all",
1427
+ onSelectionChange
1428
+ }) {
1429
+ const [cursor, setCursor] = React3.useState(0);
1430
+ const [infoIndex, setInfoIndex] = React3.useState(null);
1431
+ const [filter, setFilter] = React3.useState("");
1432
+ const [selected, setSelected] = React3.useState(
1433
+ new Set(
1434
+ initialSelected.length > 0 ? items.map((item, index) => ({ item, index })).filter(({ item }) => initialSelected.includes(item.value)).map(({ index }) => index) : []
1435
+ )
1436
+ );
1437
+ const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD;
1438
+ const { setTextInputActive, setTextInputEscMode } = useNavigation();
1439
+ const resetFocus = React3.useCallback(() => {
1440
+ setCursor(0);
1441
+ setInfoIndex(null);
1442
+ }, []);
1443
+ React3.useEffect(() => {
1444
+ if (!showFilter) return;
1445
+ setTextInputActive(true);
1446
+ setTextInputEscMode("back");
1447
+ return () => {
1448
+ setTextInputActive(false);
1449
+ setTextInputEscMode("back");
1450
+ };
1451
+ }, [showFilter, setTextInputActive, setTextInputEscMode]);
1452
+ const filteredItems = React3.useMemo(() => {
1453
+ if (!filter) return items.map((item, index) => ({ item, originalIndex: index }));
1454
+ const lowerFilter = filter.toLowerCase();
1455
+ return items.map((item, index) => ({ item, originalIndex: index })).filter(
1456
+ ({ item }) => item.label.toLowerCase().includes(lowerFilter) || String(item.value).toLowerCase().includes(lowerFilter)
1457
+ );
1458
+ }, [items, filter]);
1459
+ const total = filteredItems.length;
1460
+ const maxItems = Math.max(5, Math.min(limit, total));
1461
+ const windowStart = Math.min(
1462
+ Math.max(0, cursor - Math.floor(maxItems / 2)),
1463
+ Math.max(0, total - maxItems)
1464
+ );
1465
+ const visible = filteredItems.slice(windowStart, windowStart + maxItems);
1466
+ const truncate = (value, max = 100) => {
1467
+ if (value.length <= max) return value;
1468
+ return `${value.slice(0, max - 3)}...`;
1469
+ };
1470
+ const getSelectedValues = React3.useCallback(
1471
+ (nextSelected) => {
1472
+ const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
1473
+ const selectedValues = Array.from(nextSelected).map((index) => items[index]?.value).filter((value) => value !== void 0);
1474
+ return [...lockedValues, ...selectedValues];
1475
+ },
1476
+ [items, lockedSection]
1477
+ );
1478
+ useInput((input, key) => {
1479
+ if (showFilter) {
1480
+ if (key.backspace || key.delete) {
1481
+ setFilter((prev) => prev.slice(0, -1));
1482
+ resetFocus();
1483
+ return;
1484
+ }
1485
+ if (input && input.length === 1 && !key.ctrl && !key.meta && !key.return && !key.tab && input !== " " && input !== "s" && input !== "S" && input !== "i" && input !== "I") {
1486
+ setFilter((prev) => prev + input);
1487
+ resetFocus();
1488
+ return;
1489
+ }
1490
+ }
1491
+ if (key.downArrow) {
1492
+ setCursor((prev) => {
1493
+ if (total === 0) return 0;
1494
+ const next = (prev + 1) % total;
1495
+ if (infoIndex !== null) {
1496
+ setInfoIndex(null);
1497
+ }
1498
+ return next;
1499
+ });
1500
+ } else if (key.upArrow) {
1501
+ setCursor((prev) => {
1502
+ if (total === 0) return 0;
1503
+ const next = (prev - 1 + total) % total;
1504
+ if (infoIndex !== null) {
1505
+ setInfoIndex(null);
1506
+ }
1507
+ return next;
1508
+ });
1509
+ } else if (input === " ") {
1510
+ if (total === 0) return;
1511
+ const currentFiltered = filteredItems[cursor];
1512
+ if (!currentFiltered) return;
1513
+ if (currentFiltered.item.disabled) return;
1514
+ const originalIndex = currentFiltered.originalIndex;
1515
+ setSelected((prev) => {
1516
+ const next = new Set(prev);
1517
+ if (next.has(originalIndex)) next.delete(originalIndex);
1518
+ else next.add(originalIndex);
1519
+ if (onSelectionChange) {
1520
+ onSelectionChange(getSelectedValues(next));
1521
+ }
1522
+ return next;
1523
+ });
1524
+ } else if (input === "s" || input === "S") {
1525
+ const selectableIndices = filteredItems.filter(({ item }) => !item.disabled).map(({ originalIndex }) => originalIndex);
1526
+ setSelected((prev) => {
1527
+ const allSelected = selectableIndices.length > 0 && selectableIndices.every((index) => prev.has(index));
1528
+ if (allSelected) {
1529
+ const next2 = new Set(prev);
1530
+ for (const index of selectableIndices) {
1531
+ next2.delete(index);
1532
+ }
1533
+ if (onSelectionChange) {
1534
+ onSelectionChange(getSelectedValues(next2));
1535
+ }
1536
+ return next2;
1537
+ }
1538
+ const next = new Set(prev);
1539
+ for (const index of selectableIndices) {
1540
+ next.add(index);
1541
+ }
1542
+ if (onSelectionChange) {
1543
+ onSelectionChange(getSelectedValues(next));
1544
+ }
1545
+ return next;
1546
+ });
1547
+ } else if (input === "i" || input === "I") {
1548
+ setInfoIndex((prev) => prev === cursor ? null : cursor);
1549
+ } else if (key.return) {
1550
+ const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
1551
+ const selectedValues = Array.from(selected).map((index) => items[index]?.value).filter((value) => value !== void 0);
1552
+ onSubmit([...lockedValues, ...selectedValues]);
1553
+ }
1554
+ });
1555
+ const filterHint = showFilter ? "Type to filter, " : "";
1556
+ const displayHint = filterHint + hint;
1557
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
1558
+ lockedSection && lockedSection.items.length > 0 && /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginBottom: 1, children: [
1559
+ /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1560
+ "\u2500\u2500 ",
1561
+ lockedSection.title,
1562
+ " \u2500\u2500"
1563
+ ] }),
1564
+ lockedSection.items.map((item) => /* @__PURE__ */ jsxs3(Text3, { color: "green", children: [
1565
+ " ",
1566
+ "\u2713 ",
1567
+ item.label
1568
+ ] }, String(item.value)))
1569
+ ] }),
1570
+ lockedSection && items.length > 0 && /* @__PURE__ */ jsx4(Box3, { marginBottom: 0, children: /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "\u2500\u2500 Other agents \u2500\u2500" }) }),
1571
+ showFilter && /* @__PURE__ */ jsxs3(Box3, { marginBottom: 1, marginTop: lockedSection ? 1 : 0, children: [
1572
+ /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "Filter: " }),
1573
+ /* @__PURE__ */ jsx4(Text3, { children: filter || " " }),
1574
+ /* @__PURE__ */ jsx4(Text3, { dimColor: true, inverse: true, children: " " }),
1575
+ filter && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1576
+ " ",
1577
+ "(",
1578
+ filteredItems.length,
1579
+ "/",
1580
+ items.length,
1581
+ ")"
1582
+ ] })
1583
+ ] }),
1584
+ total === 0 ? /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
1585
+ const visibleIndex = windowStart + index;
1586
+ const isActive = visibleIndex === cursor;
1587
+ const isSelected = selected.has(originalIndex);
1588
+ const marker = isSelected ? "\u25FC" : "\u25FB";
1589
+ const pointer = isActive ? "\u276F" : " ";
1590
+ const color = item.disabled ? "gray" : isActive ? "cyan" : void 0;
1591
+ const showHint = hintMode === "all" || hintMode === "active" && isActive;
1592
+ return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
1593
+ /* @__PURE__ */ jsxs3(Text3, { color, children: [
1594
+ pointer,
1595
+ " ",
1596
+ marker,
1597
+ " ",
1598
+ item.label
1599
+ ] }),
1600
+ infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1601
+ " ",
1602
+ " ",
1603
+ truncate(item.info)
1604
+ ] }) : item.hint && showHint ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1605
+ " ",
1606
+ " ",
1607
+ item.hint
1608
+ ] }) : null
1609
+ ] }, `${item.label}-${originalIndex}`);
1610
+ }),
1611
+ /* @__PURE__ */ jsx4(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: displayHint }) })
1612
+ ] });
1613
+ }
1614
+
1615
+ // src/tui/ui/AddFlowHeader.tsx
1616
+ import { Box as Box5, Text as Text5 } from "ink";
1617
+
1618
+ // src/cli-utils.ts
1619
+ import { homedir as homedir2 } from "os";
1620
+ function shortenPath(fullPath, cwd) {
1621
+ const home2 = homedir2();
1622
+ if (fullPath.startsWith(home2)) {
1623
+ return fullPath.replace(home2, "~");
1624
+ }
1625
+ if (fullPath.startsWith(cwd)) {
1626
+ return `.${fullPath.slice(cwd.length)}`;
1627
+ }
1628
+ return fullPath;
1629
+ }
1630
+ function formatList(items, maxShow = 5) {
1631
+ if (items.length <= maxShow) {
1632
+ return items.join(", ");
1633
+ }
1634
+ const shown = items.slice(0, maxShow);
1635
+ const remaining = items.length - maxShow;
1636
+ return `${shown.join(", ")} +${remaining} more`;
1637
+ }
1638
+
1639
+ // src/tui/ui/Header.tsx
1640
+ import { Box as Box4, Text as Text4 } from "ink";
1641
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1642
+ function Header({ title }) {
1643
+ return /* @__PURE__ */ jsx5(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: title }) });
1644
+ }
1645
+
1646
+ // src/tui/ui/AddFlowHeader.tsx
1647
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1648
+ function AddFlowHeader({ title }) {
1649
+ const { invocation, addSkill } = useNavigation();
1650
+ const source = addSkill.source ?? invocation.source;
1651
+ const cwd = process.cwd();
1652
+ let sourceLabel = source ?? "";
1653
+ if (addSkill.parsed?.type === "local" && addSkill.parsed.localPath) {
1654
+ sourceLabel = shortenPath(addSkill.parsed.localPath, cwd);
1655
+ }
1656
+ const selected = addSkill.selectedSkills;
1657
+ const available = addSkill.skills;
1658
+ let skillsLabel = null;
1659
+ if (selected && selected.length > 0) {
1660
+ skillsLabel = formatList(selected.map(getSkillDisplayName), 3);
1661
+ } else if (available && available.length > 0) {
1662
+ skillsLabel = `${available.length} available`;
1663
+ }
1664
+ return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
1665
+ /* @__PURE__ */ jsx6(Header, { title }),
1666
+ source ? /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: `Source: ${sourceLabel}` }) : null,
1667
+ skillsLabel ? /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: `Skills: ${skillsLabel}` }) : null
1668
+ ] });
1669
+ }
1670
+
1671
+ // src/tui/ui/spinner.ts
1672
+ import React4 from "react";
1673
+ var spinnerFrames = ["|", "/", "-", "\\"];
1674
+ function useSpinnerFrame(active = true, interval = 100) {
1675
+ const [index, setIndex] = React4.useState(0);
1676
+ React4.useEffect(() => {
1677
+ if (!active) return void 0;
1678
+ const timer = setInterval(() => {
1679
+ setIndex((prev) => (prev + 1) % spinnerFrames.length);
1680
+ }, interval);
1681
+ return () => clearInterval(timer);
1682
+ }, [active, interval]);
1683
+ return spinnerFrames[index] ?? "|";
1684
+ }
1685
+
1686
+ // src/tui/utils/skill-selection.ts
1687
+ import { basename as basename3 } from "path";
1688
+ function matchesSkillName(skill, input) {
1689
+ const normalized = input.toLowerCase();
1690
+ const byName = skill.name.toLowerCase() === normalized;
1691
+ const byPath = basename3(skill.path).toLowerCase() === normalized;
1692
+ return byName || byPath;
1693
+ }
1694
+ function autoSelect(skills, options) {
1695
+ if (options.skill && options.skill.length > 0) {
1696
+ const selected = skills.filter((s) => options.skill?.some((name) => matchesSkillName(s, name)));
1697
+ if (selected.length === 0) {
1698
+ return {
1699
+ status: "prompt",
1700
+ message: `No matching skills found for: ${options.skill.join(", ")}`
1701
+ };
1702
+ }
1703
+ return { status: "selected", skills: selected };
1704
+ }
1705
+ if (skills.length === 1) {
1706
+ return { status: "selected", skills };
1707
+ }
1708
+ if (options.yes) {
1709
+ return { status: "selected", skills };
1710
+ }
1711
+ return { status: "prompt" };
1712
+ }
1713
+
1714
+ // src/tui/screens/AddBundleSelect.tsx
1715
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1716
+ function groupByRepo(skills) {
1717
+ const map = /* @__PURE__ */ new Map();
1718
+ for (const skill of skills) {
1719
+ if (!skill.repoOwner || !skill.repoName) continue;
1720
+ const key = `${skill.repoOwner}/${skill.repoName}`;
1721
+ const list = map.get(key) ?? [];
1722
+ list.push(skill);
1723
+ map.set(key, list);
1724
+ }
1725
+ return map;
1726
+ }
1727
+ function findMatchingSkill(discovered, entry) {
1728
+ const targets = [entry.name, entry.skillSlug].filter((t) => Boolean(t)).map((t) => t.toLowerCase());
1729
+ for (const skill of discovered) {
1730
+ const candidates = [skill.name.toLowerCase(), basename4(skill.path).toLowerCase()];
1731
+ if (candidates.some((c) => targets.includes(c))) {
1732
+ return skill;
1733
+ }
1734
+ }
1735
+ return void 0;
1736
+ }
1737
+ function AddBundleSelectScreen() {
1738
+ const {
1739
+ invocation,
1740
+ addSkill,
1741
+ updateAddSkill,
1742
+ navigateTo,
1743
+ setFlash,
1744
+ setBackHandler,
1745
+ resetTo,
1746
+ setInvocation,
1747
+ resetAddSkill,
1748
+ setLastSource
1749
+ } = useNavigation();
1750
+ const [status, setStatus] = React5.useState(
1751
+ addSkill.skills && addSkill.skills.length > 0 ? "ready" : "loading"
1752
+ );
1753
+ const [error, setError] = React5.useState(null);
1754
+ const [bundleName, setBundleName] = React5.useState(null);
1755
+ const [listMode, setListMode] = React5.useState(false);
1756
+ const [showLoading, setShowLoading] = React5.useState(false);
1757
+ const spinner = useSpinnerFrame(status === "loading");
1758
+ const slug = invocation.source;
1759
+ const options = invocation.options;
1760
+ React5.useEffect(() => {
1761
+ let cancelled = false;
1762
+ const load = async () => {
1763
+ if (!slug) {
1764
+ setError("Missing bundle slug.");
1765
+ setStatus("error");
1766
+ return;
1767
+ }
1768
+ if (addSkill.skills && addSkill.skills.length > 0) {
1769
+ setStatus("ready");
1770
+ return;
1771
+ }
1772
+ setStatus("loading");
1773
+ const tempDirs2 = [];
1774
+ try {
1775
+ const bundle = await fetchBundle(slug);
1776
+ if (cancelled) return;
1777
+ setBundleName(bundle.bundle.name);
1778
+ const cloneable = bundle.skills.filter((s) => s.repoOwner && s.repoName);
1779
+ const skippedCount = bundle.skills.length - cloneable.length;
1780
+ if (cloneable.length === 0) {
1781
+ throw new Error("No installable skills found in this bundle.");
1782
+ }
1783
+ const grouped = groupByRepo(cloneable);
1784
+ const allSkills = [];
1785
+ const warnings = [];
1786
+ for (const [repo, entries] of grouped) {
1787
+ if (cancelled) break;
1788
+ const repoUrl = `https://github.com/${repo}.git`;
1789
+ let tempDir;
1790
+ try {
1791
+ tempDir = await cloneRepo(repoUrl);
1792
+ } catch {
1793
+ warnings.push(`Failed to clone ${repo}`);
1794
+ continue;
1795
+ }
1796
+ tempDirs2.push(tempDir);
1797
+ let discovered;
1798
+ try {
1799
+ discovered = await discoverSkills(tempDir);
1800
+ } catch {
1801
+ warnings.push(`Failed to discover skills in ${repo}`);
1802
+ continue;
1803
+ }
1804
+ for (const entry of entries) {
1805
+ if (cancelled) break;
1806
+ const match = findMatchingSkill(discovered, entry);
1807
+ if (match) {
1808
+ allSkills.push(match);
1809
+ } else {
1810
+ warnings.push(`Could not find skill "${entry.name}" in ${repo}`);
1811
+ }
1812
+ }
1813
+ }
1814
+ if (cancelled) {
1815
+ for (const dir of tempDirs2) {
1816
+ try {
1817
+ await cleanupTempDir(dir);
1818
+ } catch {
1819
+ }
1820
+ }
1821
+ return;
1822
+ }
1823
+ if (allSkills.length === 0) {
1824
+ for (const dir of tempDirs2) {
1825
+ try {
1826
+ await cleanupTempDir(dir);
1827
+ } catch {
1828
+ }
1829
+ }
1830
+ const detail = warnings.length > 0 ? `
1831
+ ${warnings.join("\n")}` : "";
1832
+ throw new Error(`No skills could be resolved from this bundle.${detail}`);
1833
+ }
1834
+ if (skippedCount > 0) {
1835
+ warnings.push(`${skippedCount} skill(s) skipped (missing repo info)`);
1836
+ }
1837
+ if (warnings.length > 0) {
1838
+ setFlash(warnings.join(". "));
1839
+ }
1840
+ updateAddSkill({
1841
+ tempDir: tempDirs2[0] ?? null,
1842
+ skills: allSkills
1843
+ });
1844
+ if (options.list) {
1845
+ setListMode(true);
1846
+ setStatus("list");
1847
+ return;
1848
+ }
1849
+ const autoSelection = autoSelect(allSkills, options);
1850
+ if (autoSelection.status === "selected") {
1851
+ updateAddSkill({
1852
+ selectedSkills: autoSelection.skills,
1853
+ securityBySkillName: void 0,
1854
+ securityScanRows: void 0,
1855
+ securityAccepted: void 0
1856
+ });
1857
+ navigateTo("add-security-scan");
1858
+ return;
1859
+ }
1860
+ if (autoSelection.status === "error") {
1861
+ throw new Error(autoSelection.message);
1862
+ }
1863
+ if (autoSelection.status === "prompt" && autoSelection.message) {
1864
+ setFlash(autoSelection.message);
1865
+ }
1866
+ setStatus("ready");
1867
+ } catch (err) {
1868
+ if (cancelled) return;
1869
+ for (const dir of tempDirs2) {
1870
+ try {
1871
+ await cleanupTempDir(dir);
1872
+ } catch {
1873
+ }
1874
+ }
1875
+ updateAddSkill({ tempDir: null, skills: void 0, selectedSkills: void 0 });
1876
+ setError(err instanceof Error ? err.message : "Failed to load bundle");
1877
+ setStatus("error");
1878
+ }
1314
1879
  };
1315
- tick();
1316
- const timer = setInterval(() => {
1317
- if (!tick()) {
1318
- clearInterval(timer);
1319
- }
1320
- }, interval);
1880
+ load();
1321
1881
  return () => {
1322
- clearInterval(timer);
1882
+ cancelled = true;
1323
1883
  };
1324
- }, []);
1325
- return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [
1326
- /* @__PURE__ */ jsx2(Text, { bold: true, children: title }),
1327
- /* @__PURE__ */ jsx2(Text, { dimColor: true, children: TAGLINE })
1328
- ] });
1329
- }
1330
-
1331
- // src/tui/ui/FlashBar.tsx
1332
- import { Box as Box2, Text as Text2 } from "ink";
1333
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1334
- function classify(msg) {
1335
- const m = msg.toLowerCase();
1336
- if (/(error|failed|unable|denied|invalid|cannot|not found)/i.test(msg)) return "error";
1337
- if (/(deleted|linked|unlinked|updated|created|saved|enabled|disabled|added|removed|✓)/i.test(msg))
1338
- return "success";
1339
- if (/(warn|deprecated|missing|retry|timeout)/i.test(msg)) return "warning";
1340
- return "info";
1341
- }
1342
- function FlashBar({ align = "left" }) {
1343
- const { flashes } = useNavigation();
1344
- if (flashes.length === 0) return /* @__PURE__ */ jsx3(Box2, { height: 1 });
1345
- return /* @__PURE__ */ jsx3(
1346
- Box2,
1347
- {
1348
- flexDirection: "column",
1349
- paddingX: 1,
1350
- paddingY: 0,
1351
- gap: 0,
1352
- justifyContent: align === "center" ? "center" : "flex-start",
1353
- children: flashes.map((flash) => {
1354
- const kind = classify(flash.text);
1355
- const color = kind === "success" ? "green" : kind === "error" ? "red" : kind === "warning" ? "yellow" : "cyan";
1356
- const label = kind === "success" ? "\u2713" : kind === "error" ? "x" : kind === "warning" ? "!" : "i";
1357
- return /* @__PURE__ */ jsxs2(Text2, { color, children: [
1358
- "[",
1359
- label,
1360
- "] ",
1361
- flash.text
1362
- ] }, flash.id);
1363
- })
1884
+ }, [slug, addSkill.skills, updateAddSkill, navigateTo, options, setFlash]);
1885
+ React5.useEffect(() => {
1886
+ setBackHandler(() => {
1887
+ setLastSource(null);
1888
+ resetAddSkill();
1889
+ setInvocation({ intent: "none", options: {} });
1890
+ resetTo("main");
1891
+ return true;
1892
+ });
1893
+ return () => {
1894
+ setBackHandler(null);
1895
+ };
1896
+ }, [resetTo, setBackHandler, resetAddSkill, setInvocation, setLastSource]);
1897
+ React5.useEffect(() => {
1898
+ if (status !== "loading") {
1899
+ setShowLoading(false);
1900
+ return;
1364
1901
  }
1365
- );
1366
- }
1367
-
1368
- // src/tui/screens/AddConfirm.tsx
1369
- import { join as join9 } from "path";
1370
- import { Box as Box10, Text as Text10 } from "ink";
1371
- import React7 from "react";
1372
-
1373
- // src/cli-utils.ts
1374
- import { homedir as homedir2 } from "os";
1375
- function shortenPath(fullPath, cwd) {
1376
- const home2 = homedir2();
1377
- if (fullPath.startsWith(home2)) {
1378
- return fullPath.replace(home2, "~");
1902
+ const timer = setTimeout(() => {
1903
+ setShowLoading(true);
1904
+ }, 150);
1905
+ return () => clearTimeout(timer);
1906
+ }, [status]);
1907
+ if (status === "loading" && !showLoading) {
1908
+ return /* @__PURE__ */ jsx7(Box6, { padding: 1 });
1379
1909
  }
1380
- if (fullPath.startsWith(cwd)) {
1381
- return `.${fullPath.slice(cwd.length)}`;
1910
+ if (status === "loading") {
1911
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
1912
+ /* @__PURE__ */ jsx7(AddFlowHeader, { title: bundleName ? `Bundle: ${bundleName}` : "Loading bundle" }),
1913
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1914
+ spinner,
1915
+ " ",
1916
+ bundleName ? "Cloning skills..." : `Fetching bundle "${slug}"...`
1917
+ ] })
1918
+ ] });
1382
1919
  }
1383
- return fullPath;
1384
- }
1385
- function formatList(items, maxShow = 5) {
1386
- if (items.length <= maxShow) {
1387
- return items.join(", ");
1920
+ if (status === "error") {
1921
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
1922
+ /* @__PURE__ */ jsx7(AddFlowHeader, { title: "Unable to load bundle" }),
1923
+ /* @__PURE__ */ jsx7(Text6, { color: "red", children: error }),
1924
+ /* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: BACK_QUIT_HINT }) })
1925
+ ] });
1388
1926
  }
1389
- const shown = items.slice(0, maxShow);
1390
- const remaining = items.length - maxShow;
1391
- return `${shown.join(", ")} +${remaining} more`;
1927
+ const skills = addSkill.skills ?? [];
1928
+ if (listMode || status === "list") {
1929
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
1930
+ /* @__PURE__ */ jsx7(AddFlowHeader, { title: `${bundleName ?? "Bundle"} (${skills.length} skills)` }),
1931
+ skills.map((skill) => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
1932
+ /* @__PURE__ */ jsx7(Text6, { children: getSkillDisplayName(skill) }),
1933
+ skill.description ? /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: skill.description }) : null
1934
+ ] }, skill.name)),
1935
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: BACK_QUIT_HINT })
1936
+ ] });
1937
+ }
1938
+ if (skills.length === 0) {
1939
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
1940
+ /* @__PURE__ */ jsx7(AddFlowHeader, { title: "No skills found" }),
1941
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: BACK_QUIT_HINT })
1942
+ ] });
1943
+ }
1944
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
1945
+ /* @__PURE__ */ jsx7(AddFlowHeader, { title: `${bundleName ?? "Bundle"} - Select skills` }),
1946
+ /* @__PURE__ */ jsx7(
1947
+ MultiSelect,
1948
+ {
1949
+ items: skills.map((skill) => ({
1950
+ value: skill,
1951
+ label: getSkillDisplayName(skill),
1952
+ hint: skill.description && skill.description.length > 60 ? `${skill.description.slice(0, 57)}...` : skill.description
1953
+ })),
1954
+ initialSelected: addSkill.selectedSkills ?? skills,
1955
+ onSubmit: (values) => {
1956
+ if (values.length === 0) {
1957
+ setFlash("Select at least one skill.");
1958
+ return;
1959
+ }
1960
+ updateAddSkill({
1961
+ selectedSkills: values,
1962
+ targetAgents: void 0,
1963
+ installGlobally: void 0,
1964
+ installMode: void 0,
1965
+ planLines: void 0,
1966
+ securityBySkillName: void 0,
1967
+ securityScanRows: void 0,
1968
+ securityAccepted: void 0
1969
+ });
1970
+ navigateTo("add-security-scan");
1971
+ }
1972
+ }
1973
+ )
1974
+ ] });
1392
1975
  }
1393
1976
 
1977
+ // src/tui/screens/AddConfirm.tsx
1978
+ import { join as join9 } from "path";
1979
+ import { Box as Box12, Text as Text12 } from "ink";
1980
+ import React9 from "react";
1981
+
1394
1982
  // src/flows/plan-summary.ts
1395
1983
  import chalk from "chalk";
1396
1984
 
1397
1985
  // src/installer/install.ts
1398
1986
  import { access, mkdir as mkdir2, rm as rm4, writeFile } from "fs/promises";
1399
- import { basename as basename3, join as join7 } from "path";
1987
+ import { basename as basename5, join as join7 } from "path";
1400
1988
 
1401
1989
  // src/installer/files.ts
1402
1990
  import { cp, lstat, mkdir, readdir as readdir2, readlink, rm as rm3, symlink } from "fs/promises";
@@ -1542,7 +2130,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
1542
2130
  error: `Agent ${agent.displayName} does not support global installation`
1543
2131
  };
1544
2132
  }
1545
- const rawSkillName = skill.name || basename3(skill.path);
2133
+ const rawSkillName = skill.name || basename5(skill.path);
1546
2134
  const { canonicalBase, canonicalDir, agentBase, agentDir } = getInstallTargets(
1547
2135
  rawSkillName,
1548
2136
  agentType,
@@ -2721,41 +3309,26 @@ async function scanSkillsForSecurity(skills, options = {}) {
2721
3309
  }
2722
3310
 
2723
3311
  // src/tui/controls/SelectMenu.tsx
2724
- import { Box as Box5 } from "ink";
3312
+ import { Box as Box9 } from "ink";
2725
3313
  import SelectInput from "ink-select-input";
2726
3314
 
2727
3315
  // src/tui/ui/Divider.tsx
2728
- import { Box as Box3, Text as Text3 } from "ink";
2729
- import { jsx as jsx4 } from "react/jsx-runtime";
3316
+ import { Box as Box7, Text as Text7 } from "ink";
3317
+ import { jsx as jsx8 } from "react/jsx-runtime";
2730
3318
  function Divider() {
2731
- return /* @__PURE__ */ jsx4(Box3, { children: /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) });
3319
+ return /* @__PURE__ */ jsx8(Box7, { children: /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) });
2732
3320
  }
2733
3321
 
2734
3322
  // src/tui/ui/HelpBar.tsx
2735
- import { Box as Box4, Text as Text4 } from "ink";
2736
-
2737
- // src/tui/ui/hints.ts
2738
- var TEXT_INPUT_HINT = "Ctrl+D to clear, Esc to go back";
2739
- var MENU_HINT = "Use \u2191\u2193 to navigate, Enter to select, m for main, q/esc to quit";
2740
- var SINGLE_SELECT_HINT = "Use \u2191\u2193 to navigate, Enter to continue, m for main, q/esc to quit";
2741
- var MULTI_SELECT_HINT = "Space to toggle, s to select all, Enter to continue, m for main, q/esc to quit";
2742
- var BACK_QUIT_HINT = "Press \u2190 to go back, q/esc to quit";
2743
- var FIND_SKILLS_HINT = "Space to select one or more skills, then Enter to install.";
2744
- var FIND_RESULTS_HINT = "Space to toggle, s to select all, i for info, Enter to install, q/esc to quit";
2745
- var UPDATE_HINT_NEEDS_ONLY = "Showing needs update only. u to show all, s to select all, m for main, q/esc to quit";
2746
- var UPDATE_HINT_ALL = "u to show needs update only, s to select all, m for main, q/esc to quit";
2747
- var UPDATE_EMPTY_HINT = "Press u to show all, m for main, q/esc to quit";
2748
- var SCAN_SKILLS_HINT = "Use \u2191\u2193 to navigate, i for info, Enter for actions, m for main, q/esc to quit";
2749
-
2750
- // src/tui/ui/HelpBar.tsx
2751
- import { jsx as jsx5 } from "react/jsx-runtime";
3323
+ import { Box as Box8, Text as Text8 } from "ink";
3324
+ import { jsx as jsx9 } from "react/jsx-runtime";
2752
3325
  function HelpBar({ text = MENU_HINT }) {
2753
- return /* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: text }) });
3326
+ return /* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: text }) });
2754
3327
  }
2755
3328
 
2756
3329
  // src/tui/ui/SelectItem.tsx
2757
- import { Text as Text5 } from "ink";
2758
- import { jsx as jsx6 } from "react/jsx-runtime";
3330
+ import { Text as Text9 } from "ink";
3331
+ import { jsx as jsx10 } from "react/jsx-runtime";
2759
3332
  function SelectItem({ label }) {
2760
3333
  const l = label.toLowerCase();
2761
3334
  let color;
@@ -2764,11 +3337,11 @@ function SelectItem({ label }) {
2764
3337
  else if (l.includes("failed \u2717") || l.includes("inactive \u2717")) color = "red";
2765
3338
  else if (l.includes("sent \u2713") || l.includes("success \u2713") || l.includes("active \u2713"))
2766
3339
  color = "green";
2767
- return /* @__PURE__ */ jsx6(Text5, { color, children: label });
3340
+ return /* @__PURE__ */ jsx10(Text9, { color, children: label });
2768
3341
  }
2769
3342
 
2770
3343
  // src/tui/controls/SelectMenu.tsx
2771
- import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
3344
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2772
3345
  var SelectInputTyped = SelectInput;
2773
3346
  function SelectMenu({
2774
3347
  items,
@@ -2778,9 +3351,9 @@ function SelectMenu({
2778
3351
  itemComponent = SelectItem,
2779
3352
  limit
2780
3353
  }) {
2781
- return /* @__PURE__ */ jsxs3(Box5, { flexDirection: "column", children: [
2782
- showDivider && /* @__PURE__ */ jsx7(Divider, {}),
2783
- /* @__PURE__ */ jsx7(
3354
+ return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
3355
+ showDivider && /* @__PURE__ */ jsx11(Divider, {}),
3356
+ /* @__PURE__ */ jsx11(
2784
3357
  SelectInputTyped,
2785
3358
  {
2786
3359
  items,
@@ -2789,17 +3362,17 @@ function SelectMenu({
2789
3362
  limit
2790
3363
  }
2791
3364
  ),
2792
- /* @__PURE__ */ jsx7(HelpBar, { text: hint })
3365
+ /* @__PURE__ */ jsx11(HelpBar, { text: hint })
2793
3366
  ] });
2794
3367
  }
2795
3368
 
2796
3369
  // src/tui/hooks/useTextInput.tsx
2797
- import { useInput } from "ink";
2798
- import React3 from "react";
3370
+ import { useInput as useInput2 } from "ink";
3371
+ import React6 from "react";
2799
3372
  function useTextInput({ onClear, disabled = false }) {
2800
3373
  const { setTextInputActive, setTextInputEscMode } = useNavigation();
2801
- const skipNextChangeRef = React3.useRef(false);
2802
- React3.useEffect(() => {
3374
+ const skipNextChangeRef = React6.useRef(false);
3375
+ React6.useEffect(() => {
2803
3376
  if (disabled) {
2804
3377
  setTextInputActive(false);
2805
3378
  setTextInputEscMode("back");
@@ -2812,17 +3385,17 @@ function useTextInput({ onClear, disabled = false }) {
2812
3385
  setTextInputEscMode("back");
2813
3386
  };
2814
3387
  }, [disabled, setTextInputActive, setTextInputEscMode]);
2815
- const clearValue = React3.useCallback(() => {
3388
+ const clearValue = React6.useCallback(() => {
2816
3389
  skipNextChangeRef.current = true;
2817
3390
  onClear();
2818
3391
  }, [onClear]);
2819
- useInput((input, key) => {
3392
+ useInput2((input, key) => {
2820
3393
  if (disabled) return;
2821
3394
  if (key.ctrl && input === "d" || input === "") {
2822
3395
  clearValue();
2823
3396
  }
2824
3397
  });
2825
- const wrapOnChange = React3.useCallback(
3398
+ const wrapOnChange = React6.useCallback(
2826
3399
  (handler) => (next) => {
2827
3400
  if (skipNextChangeRef.current) {
2828
3401
  skipNextChangeRef.current = false;
@@ -2836,66 +3409,16 @@ function useTextInput({ onClear, disabled = false }) {
2836
3409
  return { wrapOnChange };
2837
3410
  }
2838
3411
 
2839
- // src/tui/ui/AddFlowHeader.tsx
2840
- import { Box as Box7, Text as Text7 } from "ink";
2841
-
2842
- // src/tui/ui/Header.tsx
2843
- import { Box as Box6, Text as Text6 } from "ink";
2844
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
2845
- function Header({ title }) {
2846
- return /* @__PURE__ */ jsx8(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx8(Text6, { bold: true, color: "cyan", children: title }) });
2847
- }
2848
-
2849
- // src/tui/ui/AddFlowHeader.tsx
2850
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
2851
- function AddFlowHeader({ title }) {
2852
- const { invocation, addSkill } = useNavigation();
2853
- const source = addSkill.source ?? invocation.source;
2854
- const cwd = process.cwd();
2855
- let sourceLabel = source ?? "";
2856
- if (addSkill.parsed?.type === "local" && addSkill.parsed.localPath) {
2857
- sourceLabel = shortenPath(addSkill.parsed.localPath, cwd);
2858
- }
2859
- const selected = addSkill.selectedSkills;
2860
- const available = addSkill.skills;
2861
- let skillsLabel = null;
2862
- if (selected && selected.length > 0) {
2863
- skillsLabel = formatList(selected.map(getSkillDisplayName), 3);
2864
- } else if (available && available.length > 0) {
2865
- skillsLabel = `${available.length} available`;
2866
- }
2867
- return /* @__PURE__ */ jsxs5(Box7, { flexDirection: "column", marginBottom: 1, children: [
2868
- /* @__PURE__ */ jsx9(Header, { title }),
2869
- source ? /* @__PURE__ */ jsx9(Text7, { dimColor: true, children: `Source: ${sourceLabel}` }) : null,
2870
- skillsLabel ? /* @__PURE__ */ jsx9(Text7, { dimColor: true, children: `Skills: ${skillsLabel}` }) : null
2871
- ] });
2872
- }
2873
-
2874
- // src/tui/ui/spinner.ts
2875
- import React4 from "react";
2876
- var spinnerFrames = ["|", "/", "-", "\\"];
2877
- function useSpinnerFrame(active = true, interval = 100) {
2878
- const [index, setIndex] = React4.useState(0);
2879
- React4.useEffect(() => {
2880
- if (!active) return void 0;
2881
- const timer = setInterval(() => {
2882
- setIndex((prev) => (prev + 1) % spinnerFrames.length);
2883
- }, interval);
2884
- return () => clearInterval(timer);
2885
- }, [active, interval]);
2886
- return spinnerFrames[index] ?? "|";
2887
- }
2888
-
2889
3412
  // src/tui/screens/add-confirm-security.tsx
2890
- import { Box as Box9, Text as Text9 } from "ink";
3413
+ import { Box as Box11, Text as Text11 } from "ink";
2891
3414
  import TextInput from "ink-text-input";
2892
- import React6 from "react";
3415
+ import React8 from "react";
2893
3416
 
2894
3417
  // src/tui/controls/SingleSelect.tsx
2895
- import { Box as Box8, Text as Text8, useInput as useInput2 } from "ink";
2896
- import React5 from "react";
2897
- import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
2898
- var FILTER_THRESHOLD = 10;
3418
+ import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
3419
+ import React7 from "react";
3420
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
3421
+ var FILTER_THRESHOLD2 = 10;
2899
3422
  function SingleSelect({
2900
3423
  items,
2901
3424
  onSubmit,
@@ -2905,20 +3428,20 @@ function SingleSelect({
2905
3428
  hintMode = "active",
2906
3429
  initialValue
2907
3430
  }) {
2908
- const [cursor, setCursor] = React5.useState(() => {
3431
+ const [cursor, setCursor] = React7.useState(() => {
2909
3432
  if (initialValue === void 0) return 0;
2910
3433
  const index = items.findIndex((item) => item.value === initialValue);
2911
3434
  return index >= 0 ? index : 0;
2912
3435
  });
2913
- const [infoIndex, setInfoIndex] = React5.useState(null);
2914
- const [filter, setFilter] = React5.useState("");
2915
- const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD;
3436
+ const [infoIndex, setInfoIndex] = React7.useState(null);
3437
+ const [filter, setFilter] = React7.useState("");
3438
+ const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD2;
2916
3439
  const { setTextInputActive, setTextInputEscMode } = useNavigation();
2917
- const resetFocus = React5.useCallback(() => {
3440
+ const resetFocus = React7.useCallback(() => {
2918
3441
  setCursor(0);
2919
3442
  setInfoIndex(null);
2920
3443
  }, []);
2921
- React5.useEffect(() => {
3444
+ React7.useEffect(() => {
2922
3445
  if (!showFilter) return;
2923
3446
  setTextInputActive(true);
2924
3447
  setTextInputEscMode("back");
@@ -2927,7 +3450,7 @@ function SingleSelect({
2927
3450
  setTextInputEscMode("back");
2928
3451
  };
2929
3452
  }, [showFilter, setTextInputActive, setTextInputEscMode]);
2930
- const filteredItems = React5.useMemo(() => {
3453
+ const filteredItems = React7.useMemo(() => {
2931
3454
  if (!filter) return items.map((item, index) => ({ item, originalIndex: index }));
2932
3455
  const lowerFilter = filter.toLowerCase();
2933
3456
  return items.map((item, index) => ({ item, originalIndex: index })).filter(
@@ -2945,7 +3468,7 @@ function SingleSelect({
2945
3468
  if (value.length <= max) return value;
2946
3469
  return `${value.slice(0, max - 3)}...`;
2947
3470
  };
2948
- React5.useEffect(() => {
3471
+ React7.useEffect(() => {
2949
3472
  if (total === 0) {
2950
3473
  setCursor(0);
2951
3474
  return;
@@ -2954,7 +3477,7 @@ function SingleSelect({
2954
3477
  setCursor(total - 1);
2955
3478
  }
2956
3479
  }, [total, cursor]);
2957
- useInput2((input, key) => {
3480
+ useInput3((input, key) => {
2958
3481
  if (showFilter) {
2959
3482
  if (key.backspace || key.delete) {
2960
3483
  setFilter((prev) => prev.slice(0, -1));
@@ -2996,12 +3519,12 @@ function SingleSelect({
2996
3519
  });
2997
3520
  const filterHint = showFilter ? "Type to filter, " : "";
2998
3521
  const displayHint = filterHint + hint;
2999
- return /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", children: [
3000
- showFilter && /* @__PURE__ */ jsxs6(Box8, { marginBottom: 1, children: [
3001
- /* @__PURE__ */ jsx10(Text8, { dimColor: true, children: "Filter: " }),
3002
- /* @__PURE__ */ jsx10(Text8, { children: filter || " " }),
3003
- /* @__PURE__ */ jsx10(Text8, { dimColor: true, inverse: true, children: " " }),
3004
- filter && /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
3522
+ return /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", children: [
3523
+ showFilter && /* @__PURE__ */ jsxs8(Box10, { marginBottom: 1, children: [
3524
+ /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: "Filter: " }),
3525
+ /* @__PURE__ */ jsx12(Text10, { children: filter || " " }),
3526
+ /* @__PURE__ */ jsx12(Text10, { dimColor: true, inverse: true, children: " " }),
3527
+ filter && /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
3005
3528
  " ",
3006
3529
  "(",
3007
3530
  filteredItems.length,
@@ -3010,35 +3533,35 @@ function SingleSelect({
3010
3533
  ")"
3011
3534
  ] })
3012
3535
  ] }),
3013
- total === 0 ? /* @__PURE__ */ jsx10(Text8, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
3536
+ total === 0 ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
3014
3537
  const visibleIndex = windowStart + index;
3015
3538
  const isActive = visibleIndex === cursor;
3016
3539
  const pointer = isActive ? "\u276F" : " ";
3017
3540
  const color = item.disabled ? "gray" : isActive ? "cyan" : void 0;
3018
3541
  const showHint = hintMode === "all" || hintMode === "active" && isActive;
3019
- return /* @__PURE__ */ jsxs6(Box8, { flexDirection: "column", children: [
3020
- /* @__PURE__ */ jsxs6(Text8, { color, children: [
3542
+ return /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", children: [
3543
+ /* @__PURE__ */ jsxs8(Text10, { color, children: [
3021
3544
  pointer,
3022
3545
  " ",
3023
3546
  item.label
3024
3547
  ] }),
3025
- infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
3548
+ infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
3026
3549
  " ",
3027
3550
  " ",
3028
3551
  truncate(item.info)
3029
- ] }) : item.hint && showHint ? /* @__PURE__ */ jsxs6(Text8, { dimColor: true, children: [
3552
+ ] }) : item.hint && showHint ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
3030
3553
  " ",
3031
3554
  " ",
3032
3555
  item.hint
3033
3556
  ] }) : null
3034
3557
  ] }, `${item.label}-${originalIndex}`);
3035
3558
  }),
3036
- /* @__PURE__ */ jsx10(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text8, { dimColor: true, children: displayHint }) })
3559
+ /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: displayHint }) })
3037
3560
  ] });
3038
3561
  }
3039
3562
 
3040
3563
  // src/tui/screens/add-confirm-security.tsx
3041
- import { Fragment, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
3564
+ import { Fragment, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
3042
3565
  function formatSignalsBrief(signals) {
3043
3566
  if (signals.length === 0) return "None";
3044
3567
  const uniq = Array.from(new Set(signals.map((s) => s.id)));
@@ -3068,11 +3591,11 @@ function ManualSecurityGate({
3068
3591
  onInstall,
3069
3592
  onCancel
3070
3593
  }) {
3071
- const riskyScanRows = React6.useMemo(() => getRiskyScanRows(scanRows), [scanRows]);
3594
+ const riskyScanRows = React8.useMemo(() => getRiskyScanRows(scanRows), [scanRows]);
3072
3595
  if (manualView === "details") {
3073
- return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
3074
- /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: "Skills with scan findings:" }),
3075
- /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: riskyScanRows.length === 0 ? /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: "None." }) : /* @__PURE__ */ jsx11(
3596
+ return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
3597
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Skills with scan findings:" }),
3598
+ /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: riskyScanRows.length === 0 ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "None." }) : /* @__PURE__ */ jsx13(
3076
3599
  SingleSelect,
3077
3600
  {
3078
3601
  items: riskyScanRows.map((row) => ({
@@ -3093,49 +3616,49 @@ function ManualSecurityGate({
3093
3616
  }
3094
3617
  if (manualView === "detail-skill" && selectedRow) {
3095
3618
  const riskColor = selectedRow.level === "critical" || selectedRow.level === "high" ? "red" : selectedRow.level === "medium" ? "yellow" : selectedRow.level === "low" ? "green" : "gray";
3096
- return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
3097
- /* @__PURE__ */ jsx11(Text9, { children: /* @__PURE__ */ jsx11(Text9, { bold: true, children: selectedRow.name }) }),
3098
- selectedRow.error ? /* @__PURE__ */ jsx11(Text9, { color: "red", children: selectedRow.error }) : /* @__PURE__ */ jsxs7(Fragment, { children: [
3099
- /* @__PURE__ */ jsxs7(Text9, { children: [
3100
- /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: "Verdict:" }),
3619
+ return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
3620
+ /* @__PURE__ */ jsx13(Text11, { children: /* @__PURE__ */ jsx13(Text11, { bold: true, children: selectedRow.name }) }),
3621
+ selectedRow.error ? /* @__PURE__ */ jsx13(Text11, { color: "red", children: selectedRow.error }) : /* @__PURE__ */ jsxs9(Fragment, { children: [
3622
+ /* @__PURE__ */ jsxs9(Text11, { children: [
3623
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Verdict:" }),
3101
3624
  " ",
3102
- /* @__PURE__ */ jsx11(Text9, { color: riskColor, children: selectedRow.verdict }),
3103
- /* @__PURE__ */ jsx11(
3104
- Text9,
3625
+ /* @__PURE__ */ jsx13(Text11, { color: riskColor, children: selectedRow.verdict }),
3626
+ /* @__PURE__ */ jsx13(
3627
+ Text11,
3105
3628
  {
3106
3629
  dimColor: true,
3107
3630
  children: ` \u2022 level=${selectedRow.level} score=${selectedRow.score} issues=${selectedRow.signals.length}`
3108
3631
  }
3109
3632
  )
3110
3633
  ] }),
3111
- /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: `Top signals: ${formatSignalsBrief(selectedRow.signals)}` }),
3112
- /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: `Ruleset: ${selectedRow.ruleset}` }),
3113
- selectedRow.truncated ? /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: "Note: scan was truncated due to file/byte/signal limits." }) : null
3634
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Top signals: ${formatSignalsBrief(selectedRow.signals)}` }),
3635
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Ruleset: ${selectedRow.ruleset}` }),
3636
+ selectedRow.truncated ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Note: scan was truncated due to file/byte/signal limits." }) : null
3114
3637
  ] }),
3115
- /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: `Path: ${selectedRow.path}` }),
3116
- !selectedRow.error && selectedRow.signals.length > 0 ? /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", marginTop: 1, children: [
3117
- /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: `Findings (${selectedRow.signals.length}):` }),
3118
- selectedRow.signals.slice(0, 12).map((sig, idx) => /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
3638
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Path: ${selectedRow.path}` }),
3639
+ !selectedRow.error && selectedRow.signals.length > 0 ? /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", marginTop: 1, children: [
3640
+ /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Findings (${selectedRow.signals.length}):` }),
3641
+ selectedRow.signals.slice(0, 12).map((sig, idx) => /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3119
3642
  "\u2022 ",
3120
3643
  " ",
3121
3644
  formatFindingLine(sig)
3122
3645
  ] }, `${sig.id}-${idx}`)),
3123
- selectedRow.signals.length > 12 ? /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: `\u2026 ${selectedRow.signals.length - 12} more` }) : null
3646
+ selectedRow.signals.length > 12 ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `\u2026 ${selectedRow.signals.length - 12} more` }) : null
3124
3647
  ] }) : null,
3125
- /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: BACK_QUIT_HINT }) })
3648
+ /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: BACK_QUIT_HINT }) })
3126
3649
  ] });
3127
3650
  }
3128
3651
  if (manualView === "type-confirm") {
3129
- return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
3130
- /* @__PURE__ */ jsx11(Text9, { color: "red", children: "High risk patterns detected." }),
3131
- /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
3652
+ return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
3653
+ /* @__PURE__ */ jsx13(Text11, { color: "red", children: "High risk patterns detected." }),
3654
+ /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3132
3655
  "If you still want to proceed, type ",
3133
- /* @__PURE__ */ jsx11(Text9, { bold: true, children: "install" }),
3656
+ /* @__PURE__ */ jsx13(Text11, { bold: true, children: "install" }),
3134
3657
  " and press Enter."
3135
3658
  ] }),
3136
- /* @__PURE__ */ jsxs7(Box9, { marginTop: 1, children: [
3137
- /* @__PURE__ */ jsx11(Text9, { color: "green", children: "> " }),
3138
- /* @__PURE__ */ jsx11(
3659
+ /* @__PURE__ */ jsxs9(Box11, { marginTop: 1, children: [
3660
+ /* @__PURE__ */ jsx13(Text11, { color: "green", children: "> " }),
3661
+ /* @__PURE__ */ jsx13(
3139
3662
  TextInput,
3140
3663
  {
3141
3664
  value: confirmText,
@@ -3152,22 +3675,22 @@ function ManualSecurityGate({
3152
3675
  }
3153
3676
  )
3154
3677
  ] }),
3155
- /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text9, { dimColor: true, children: TEXT_INPUT_HINT }) })
3678
+ /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: TEXT_INPUT_HINT }) })
3156
3679
  ] });
3157
3680
  }
3158
- return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
3159
- /* @__PURE__ */ jsx11(Text9, { color: "red", children: "High risk patterns detected." }),
3160
- /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
3681
+ return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
3682
+ /* @__PURE__ */ jsx13(Text11, { color: "red", children: "High risk patterns detected." }),
3683
+ /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3161
3684
  "Review the scan summary below (or open scan details). If you proceed, you will need to type",
3162
3685
  " ",
3163
- /* @__PURE__ */ jsx11(Text9, { bold: true, children: "install" }),
3686
+ /* @__PURE__ */ jsx13(Text11, { bold: true, children: "install" }),
3164
3687
  "."
3165
3688
  ] }),
3166
- /* @__PURE__ */ jsx11(Box9, { flexDirection: "column", marginTop: 1, children: riskyScanRows.slice(0, 6).map((row) => {
3689
+ /* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginTop: 1, children: riskyScanRows.slice(0, 6).map((row) => {
3167
3690
  const level = row.level ?? "none";
3168
3691
  const top = row.error ? "" : ` top=${formatSignalsBrief(row.signals)}`;
3169
3692
  const suffix = row.error ? ` scan failed: ${row.error}` : ` score=${row.score} issues=${row.signals.length}${top}`;
3170
- return /* @__PURE__ */ jsxs7(Text9, { dimColor: true, children: [
3693
+ return /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3171
3694
  "\u2022",
3172
3695
  " ",
3173
3696
  row.name,
@@ -3176,7 +3699,7 @@ function ManualSecurityGate({
3176
3699
  suffix
3177
3700
  ] }, row.path);
3178
3701
  }) }),
3179
- /* @__PURE__ */ jsx11(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx11(
3702
+ /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
3180
3703
  SelectMenu,
3181
3704
  {
3182
3705
  items: [
@@ -3203,7 +3726,7 @@ function ManualSecurityGate({
3203
3726
  }
3204
3727
 
3205
3728
  // src/tui/screens/AddConfirm.tsx
3206
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
3729
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
3207
3730
  function AddConfirmScreen() {
3208
3731
  const {
3209
3732
  invocation,
@@ -3216,13 +3739,13 @@ function AddConfirmScreen() {
3216
3739
  setBackHandler
3217
3740
  } = useNavigation();
3218
3741
  const options = invocation.options;
3219
- const [lines, setLines] = React7.useState([]);
3220
- const [scanStatus, setScanStatus] = React7.useState("idle");
3221
- const [requiresManual, setRequiresManual] = React7.useState(false);
3222
- const [confirmText, setConfirmText] = React7.useState("");
3223
- const [scanRows, setScanRows] = React7.useState([]);
3224
- const [manualView, setManualView] = React7.useState("menu");
3225
- const [selectedRow, setSelectedRow] = React7.useState(null);
3742
+ const [lines, setLines] = React9.useState([]);
3743
+ const [scanStatus, setScanStatus] = React9.useState("idle");
3744
+ const [requiresManual, setRequiresManual] = React9.useState(false);
3745
+ const [confirmText, setConfirmText] = React9.useState("");
3746
+ const [scanRows, setScanRows] = React9.useState([]);
3747
+ const [manualView, setManualView] = React9.useState("menu");
3748
+ const [selectedRow, setSelectedRow] = React9.useState(null);
3226
3749
  const spinner = useSpinnerFrame(scanStatus === "scanning");
3227
3750
  const { wrapOnChange } = useTextInput({
3228
3751
  onClear: () => {
@@ -3230,7 +3753,7 @@ function AddConfirmScreen() {
3230
3753
  },
3231
3754
  disabled: !requiresManual || manualView !== "type-confirm"
3232
3755
  });
3233
- React7.useEffect(() => {
3756
+ React9.useEffect(() => {
3234
3757
  const selectedSkills = addSkill.selectedSkills;
3235
3758
  const targetAgents2 = addSkill.targetAgents;
3236
3759
  const installGlobally = addSkill.installGlobally;
@@ -3301,7 +3824,7 @@ function AddConfirmScreen() {
3301
3824
  navigateTo,
3302
3825
  setFlash
3303
3826
  ]);
3304
- React7.useEffect(() => {
3827
+ React9.useEffect(() => {
3305
3828
  if (!requiresManual) {
3306
3829
  setBackHandler(null);
3307
3830
  return () => setBackHandler(null);
@@ -3332,7 +3855,7 @@ function AddConfirmScreen() {
3332
3855
  const canonicalBase = getCanonicalSkillsBase({ global: addSkill.installGlobally, cwd });
3333
3856
  const canonicalLabel = shortenPath(canonicalBase, cwd);
3334
3857
  const targetAgents = addSkill.targetAgents ?? [];
3335
- const keyedLines = React7.useMemo(() => {
3858
+ const keyedLines = React9.useMemo(() => {
3336
3859
  const counts = /* @__PURE__ */ new Map();
3337
3860
  return lines.map((line) => {
3338
3861
  const count = (counts.get(line) ?? 0) + 1;
@@ -3349,21 +3872,21 @@ function AddConfirmScreen() {
3349
3872
  }).filter((p) => p !== null)
3350
3873
  )
3351
3874
  ) : [];
3352
- return /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", padding: 1, children: [
3353
- /* @__PURE__ */ jsx12(AddFlowHeader, { title: "Review plan" }),
3354
- /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", marginBottom: 1, children: [
3355
- /* @__PURE__ */ jsx12(Text10, { children: `Skills: ${skillsCount} \u2022 Agents: ${agentsCount}` }),
3356
- addSkill.targetAgents ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: `Targets: ${formatList(addSkill.targetAgents.map((agent) => agents[agent].displayName))}` }) : null,
3357
- addSkill.installGlobally !== void 0 ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: `Scope: ${scopeLabel}` }) : null,
3358
- addSkill.installMode ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: `Mode: ${installModeLabel}` }) : null,
3359
- addSkill.installMode === "symlink" ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: `Canonical base: ${canonicalLabel}` }) : null,
3360
- addSkill.installMode === "copy" && agentPaths.length > 0 ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: `Agent dirs: ${formatList(agentPaths, 3)}` }) : null
3875
+ return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
3876
+ /* @__PURE__ */ jsx14(AddFlowHeader, { title: "Review plan" }),
3877
+ /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginBottom: 1, children: [
3878
+ /* @__PURE__ */ jsx14(Text12, { children: `Skills: ${skillsCount} \u2022 Agents: ${agentsCount}` }),
3879
+ addSkill.targetAgents ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Targets: ${formatList(addSkill.targetAgents.map((agent) => agents[agent].displayName))}` }) : null,
3880
+ addSkill.installGlobally !== void 0 ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Scope: ${scopeLabel}` }) : null,
3881
+ addSkill.installMode ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Mode: ${installModeLabel}` }) : null,
3882
+ addSkill.installMode === "symlink" ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Canonical base: ${canonicalLabel}` }) : null,
3883
+ addSkill.installMode === "copy" && agentPaths.length > 0 ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Agent dirs: ${formatList(agentPaths, 3)}` }) : null
3361
3884
  ] }),
3362
- keyedLines.map(({ line, key }) => /* @__PURE__ */ jsx12(Text10, { children: line }, key)),
3363
- /* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: scanStatus === "scanning" ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
3885
+ keyedLines.map(({ line, key }) => /* @__PURE__ */ jsx14(Text12, { children: line }, key)),
3886
+ /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: scanStatus === "scanning" ? /* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
3364
3887
  spinner,
3365
3888
  " Scanning skills for suspicious patterns..."
3366
- ] }) : requiresManual ? /* @__PURE__ */ jsx12(
3889
+ ] }) : requiresManual ? /* @__PURE__ */ jsx14(
3367
3890
  ManualSecurityGate,
3368
3891
  {
3369
3892
  scanRows,
@@ -3378,7 +3901,7 @@ function AddConfirmScreen() {
3378
3901
  onInstall: () => navigateTo("add-install"),
3379
3902
  onCancel: () => resetTo("main")
3380
3903
  }
3381
- ) : /* @__PURE__ */ jsx12(
3904
+ ) : /* @__PURE__ */ jsx14(
3382
3905
  SelectMenu,
3383
3906
  {
3384
3907
  items: [
@@ -3399,12 +3922,12 @@ function AddConfirmScreen() {
3399
3922
  }
3400
3923
 
3401
3924
  // src/tui/screens/AddDocs.tsx
3402
- import { Box as Box12, Text as Text12, useInput as useInput4 } from "ink";
3403
- import React9 from "react";
3925
+ import { Box as Box13, Text as Text13, useInput as useInput4 } from "ink";
3926
+ import React10 from "react";
3404
3927
 
3405
3928
  // src/docs/install.ts
3406
3929
  import { mkdir as mkdir3, stat as stat3 } from "fs/promises";
3407
- import { basename as basename4 } from "path";
3930
+ import { basename as basename6 } from "path";
3408
3931
 
3409
3932
  // src/docs/paths.ts
3410
3933
  import { join as join10 } from "path";
@@ -3449,7 +3972,7 @@ async function installDocs(sources, cwd = process.cwd()) {
3449
3972
  const docsBase = getDocsBase(cwd);
3450
3973
  await mkdir3(docsBase, { recursive: true });
3451
3974
  for (const source of sources) {
3452
- const slug = sanitizeDocName(source.name || basename4(source.url));
3975
+ const slug = sanitizeDocName(source.name || basename6(source.url));
3453
3976
  const targetPath = getDocPath(slug, cwd);
3454
3977
  if (!isPathSafe(docsBase, targetPath)) {
3455
3978
  results.push({
@@ -3704,226 +4227,24 @@ function normalizeStringArray(value) {
3704
4227
  return filtered.length > 0 ? filtered : void 0;
3705
4228
  }
3706
4229
 
3707
- // src/tui/controls/MultiSelect.tsx
3708
- import { Box as Box11, Text as Text11, useInput as useInput3 } from "ink";
3709
- import React8 from "react";
3710
- import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
3711
- var FILTER_THRESHOLD2 = 10;
3712
- function MultiSelect({
3713
- items,
3714
- initialSelected = [],
3715
- onSubmit,
3716
- limit = 10,
3717
- hint = MULTI_SELECT_HINT,
3718
- enableFilter,
3719
- lockedSection,
3720
- hintMode = "all",
3721
- onSelectionChange
3722
- }) {
3723
- const [cursor, setCursor] = React8.useState(0);
3724
- const [infoIndex, setInfoIndex] = React8.useState(null);
3725
- const [filter, setFilter] = React8.useState("");
3726
- const [selected, setSelected] = React8.useState(
3727
- new Set(
3728
- initialSelected.length > 0 ? items.map((item, index) => ({ item, index })).filter(({ item }) => initialSelected.includes(item.value)).map(({ index }) => index) : []
3729
- )
3730
- );
3731
- const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD2;
3732
- const { setTextInputActive, setTextInputEscMode } = useNavigation();
3733
- const resetFocus = React8.useCallback(() => {
3734
- setCursor(0);
3735
- setInfoIndex(null);
3736
- }, []);
3737
- React8.useEffect(() => {
3738
- if (!showFilter) return;
3739
- setTextInputActive(true);
3740
- setTextInputEscMode("back");
3741
- return () => {
3742
- setTextInputActive(false);
3743
- setTextInputEscMode("back");
3744
- };
3745
- }, [showFilter, setTextInputActive, setTextInputEscMode]);
3746
- const filteredItems = React8.useMemo(() => {
3747
- if (!filter) return items.map((item, index) => ({ item, originalIndex: index }));
3748
- const lowerFilter = filter.toLowerCase();
3749
- return items.map((item, index) => ({ item, originalIndex: index })).filter(
3750
- ({ item }) => item.label.toLowerCase().includes(lowerFilter) || String(item.value).toLowerCase().includes(lowerFilter)
3751
- );
3752
- }, [items, filter]);
3753
- const total = filteredItems.length;
3754
- const maxItems = Math.max(5, Math.min(limit, total));
3755
- const windowStart = Math.min(
3756
- Math.max(0, cursor - Math.floor(maxItems / 2)),
3757
- Math.max(0, total - maxItems)
3758
- );
3759
- const visible = filteredItems.slice(windowStart, windowStart + maxItems);
3760
- const truncate = (value, max = 100) => {
3761
- if (value.length <= max) return value;
3762
- return `${value.slice(0, max - 3)}...`;
3763
- };
3764
- const getSelectedValues = React8.useCallback(
3765
- (nextSelected) => {
3766
- const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
3767
- const selectedValues = Array.from(nextSelected).map((index) => items[index]?.value).filter((value) => value !== void 0);
3768
- return [...lockedValues, ...selectedValues];
3769
- },
3770
- [items, lockedSection]
3771
- );
3772
- useInput3((input, key) => {
3773
- if (showFilter) {
3774
- if (key.backspace || key.delete) {
3775
- setFilter((prev) => prev.slice(0, -1));
3776
- resetFocus();
3777
- return;
3778
- }
3779
- if (input && input.length === 1 && !key.ctrl && !key.meta && !key.return && !key.tab && input !== " " && input !== "s" && input !== "S" && input !== "i" && input !== "I") {
3780
- setFilter((prev) => prev + input);
3781
- resetFocus();
3782
- return;
3783
- }
3784
- }
3785
- if (key.downArrow) {
3786
- setCursor((prev) => {
3787
- if (total === 0) return 0;
3788
- const next = (prev + 1) % total;
3789
- if (infoIndex !== null) {
3790
- setInfoIndex(null);
3791
- }
3792
- return next;
3793
- });
3794
- } else if (key.upArrow) {
3795
- setCursor((prev) => {
3796
- if (total === 0) return 0;
3797
- const next = (prev - 1 + total) % total;
3798
- if (infoIndex !== null) {
3799
- setInfoIndex(null);
3800
- }
3801
- return next;
3802
- });
3803
- } else if (input === " ") {
3804
- if (total === 0) return;
3805
- const currentFiltered = filteredItems[cursor];
3806
- if (!currentFiltered) return;
3807
- if (currentFiltered.item.disabled) return;
3808
- const originalIndex = currentFiltered.originalIndex;
3809
- setSelected((prev) => {
3810
- const next = new Set(prev);
3811
- if (next.has(originalIndex)) next.delete(originalIndex);
3812
- else next.add(originalIndex);
3813
- if (onSelectionChange) {
3814
- onSelectionChange(getSelectedValues(next));
3815
- }
3816
- return next;
3817
- });
3818
- } else if (input === "s" || input === "S") {
3819
- const selectableIndices = filteredItems.filter(({ item }) => !item.disabled).map(({ originalIndex }) => originalIndex);
3820
- setSelected((prev) => {
3821
- const allSelected = selectableIndices.length > 0 && selectableIndices.every((index) => prev.has(index));
3822
- if (allSelected) {
3823
- const next2 = new Set(prev);
3824
- for (const index of selectableIndices) {
3825
- next2.delete(index);
3826
- }
3827
- if (onSelectionChange) {
3828
- onSelectionChange(getSelectedValues(next2));
3829
- }
3830
- return next2;
3831
- }
3832
- const next = new Set(prev);
3833
- for (const index of selectableIndices) {
3834
- next.add(index);
3835
- }
3836
- if (onSelectionChange) {
3837
- onSelectionChange(getSelectedValues(next));
3838
- }
3839
- return next;
3840
- });
3841
- } else if (input === "i" || input === "I") {
3842
- setInfoIndex((prev) => prev === cursor ? null : cursor);
3843
- } else if (key.return) {
3844
- const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
3845
- const selectedValues = Array.from(selected).map((index) => items[index]?.value).filter((value) => value !== void 0);
3846
- onSubmit([...lockedValues, ...selectedValues]);
3847
- }
3848
- });
3849
- const filterHint = showFilter ? "Type to filter, " : "";
3850
- const displayHint = filterHint + hint;
3851
- return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
3852
- lockedSection && lockedSection.items.length > 0 && /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", marginBottom: 1, children: [
3853
- /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3854
- "\u2500\u2500 ",
3855
- lockedSection.title,
3856
- " \u2500\u2500"
3857
- ] }),
3858
- lockedSection.items.map((item) => /* @__PURE__ */ jsxs9(Text11, { color: "green", children: [
3859
- " ",
3860
- "\u2713 ",
3861
- item.label
3862
- ] }, String(item.value)))
3863
- ] }),
3864
- lockedSection && items.length > 0 && /* @__PURE__ */ jsx13(Box11, { marginBottom: 0, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "\u2500\u2500 Other agents \u2500\u2500" }) }),
3865
- showFilter && /* @__PURE__ */ jsxs9(Box11, { marginBottom: 1, marginTop: lockedSection ? 1 : 0, children: [
3866
- /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Filter: " }),
3867
- /* @__PURE__ */ jsx13(Text11, { children: filter || " " }),
3868
- /* @__PURE__ */ jsx13(Text11, { dimColor: true, inverse: true, children: " " }),
3869
- filter && /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3870
- " ",
3871
- "(",
3872
- filteredItems.length,
3873
- "/",
3874
- items.length,
3875
- ")"
3876
- ] })
3877
- ] }),
3878
- total === 0 ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
3879
- const visibleIndex = windowStart + index;
3880
- const isActive = visibleIndex === cursor;
3881
- const isSelected = selected.has(originalIndex);
3882
- const marker = isSelected ? "\u25FC" : "\u25FB";
3883
- const pointer = isActive ? "\u276F" : " ";
3884
- const color = item.disabled ? "gray" : isActive ? "cyan" : void 0;
3885
- const showHint = hintMode === "all" || hintMode === "active" && isActive;
3886
- return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
3887
- /* @__PURE__ */ jsxs9(Text11, { color, children: [
3888
- pointer,
3889
- " ",
3890
- marker,
3891
- " ",
3892
- item.label
3893
- ] }),
3894
- infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3895
- " ",
3896
- " ",
3897
- truncate(item.info)
3898
- ] }) : item.hint && showHint ? /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
3899
- " ",
3900
- " ",
3901
- item.hint
3902
- ] }) : null
3903
- ] }, `${item.label}-${originalIndex}`);
3904
- }),
3905
- /* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: displayHint }) })
3906
- ] });
3907
- }
3908
-
3909
4230
  // src/tui/screens/AddDocs.tsx
3910
- import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
4231
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
3911
4232
  var DOCS_HINT = "Space to toggle, Enter to install, m for main, q/esc to quit";
3912
4233
  var REF_HINT = "Enter to select, Ctrl+P to toggle prerelease, m for main, q/esc to quit";
3913
4234
  function AddDocsScreen() {
3914
4235
  const { navigateTo, setFlash, setBackHandler } = useNavigation();
3915
- const sources = React9.useMemo(() => getDocSources(), []);
3916
- const [status, setStatus] = React9.useState(sources.length === 0 ? "empty" : "select");
3917
- const [selected, setSelected] = React9.useState([]);
3918
- const [results, setResults] = React9.useState(null);
3919
- const [notice, setNotice] = React9.useState(null);
3920
- const [pendingSources, setPendingSources] = React9.useState([]);
3921
- const [currentIndex, setCurrentIndex] = React9.useState(0);
3922
- const [repoRefs, setRepoRefs] = React9.useState(null);
3923
- const [refStatus, setRefStatus] = React9.useState("idle");
3924
- const [refError, setRefError] = React9.useState(null);
3925
- const [refSelections, setRefSelections] = React9.useState(/* @__PURE__ */ new Map());
3926
- const [includePrerelease, setIncludePrerelease] = React9.useState(false);
4236
+ const sources = React10.useMemo(() => getDocSources(), []);
4237
+ const [status, setStatus] = React10.useState(sources.length === 0 ? "empty" : "select");
4238
+ const [selected, setSelected] = React10.useState([]);
4239
+ const [results, setResults] = React10.useState(null);
4240
+ const [notice, setNotice] = React10.useState(null);
4241
+ const [pendingSources, setPendingSources] = React10.useState([]);
4242
+ const [currentIndex, setCurrentIndex] = React10.useState(0);
4243
+ const [repoRefs, setRepoRefs] = React10.useState(null);
4244
+ const [refStatus, setRefStatus] = React10.useState("idle");
4245
+ const [refError, setRefError] = React10.useState(null);
4246
+ const [refSelections, setRefSelections] = React10.useState(/* @__PURE__ */ new Map());
4247
+ const [includePrerelease, setIncludePrerelease] = React10.useState(false);
3927
4248
  const spinner = useSpinnerFrame(status === "installing" || refStatus === "loading");
3928
4249
  useInput4((input, key) => {
3929
4250
  if (status !== "choose-ref") return;
@@ -3931,7 +4252,7 @@ function AddDocsScreen() {
3931
4252
  setIncludePrerelease((prev) => !prev);
3932
4253
  }
3933
4254
  });
3934
- React9.useEffect(() => {
4255
+ React10.useEffect(() => {
3935
4256
  let cancelled = false;
3936
4257
  const run = async () => {
3937
4258
  if (status !== "installing" || selected.length === 0) return;
@@ -3952,7 +4273,7 @@ function AddDocsScreen() {
3952
4273
  cancelled = true;
3953
4274
  };
3954
4275
  }, [status, selected, setFlash]);
3955
- React9.useEffect(() => {
4276
+ React10.useEffect(() => {
3956
4277
  if (status !== "choose-ref") {
3957
4278
  setBackHandler(null);
3958
4279
  return;
@@ -3969,7 +4290,7 @@ function AddDocsScreen() {
3969
4290
  setBackHandler(null);
3970
4291
  };
3971
4292
  }, [status, setBackHandler]);
3972
- React9.useEffect(() => {
4293
+ React10.useEffect(() => {
3973
4294
  let cancelled = false;
3974
4295
  const loadRefs = async () => {
3975
4296
  if (status !== "choose-ref") return;
@@ -4003,35 +4324,35 @@ function AddDocsScreen() {
4003
4324
  };
4004
4325
  }, [status, pendingSources, currentIndex]);
4005
4326
  if (status === "empty") {
4006
- return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
4007
- /* @__PURE__ */ jsx14(Header, { title: "Add docs" }),
4008
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "No curated docs configured yet." }),
4009
- /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: BACK_QUIT_HINT }) })
4327
+ return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4328
+ /* @__PURE__ */ jsx15(Header, { title: "Add docs" }),
4329
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "No curated docs configured yet." }),
4330
+ /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: BACK_QUIT_HINT }) })
4010
4331
  ] });
4011
4332
  }
4012
4333
  if (status === "choose-ref") {
4013
4334
  const source = pendingSources[currentIndex];
4014
4335
  if (!source) {
4015
- return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
4016
- /* @__PURE__ */ jsx14(Header, { title: "Select branch or tag" }),
4017
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "No docs selected." })
4336
+ return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4337
+ /* @__PURE__ */ jsx15(Header, { title: "Select branch or tag" }),
4338
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "No docs selected." })
4018
4339
  ] });
4019
4340
  }
4020
4341
  const built = repoRefs ? buildRefOptions(repoRefs, includePrerelease) : { options: [], note: "" };
4021
4342
  const prereleaseNote = includePrerelease ? "Showing prerelease refs." : "Stable only (Ctrl+P for prerelease).";
4022
- return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
4023
- /* @__PURE__ */ jsx14(Header, { title: "Select branch or tag" }),
4024
- /* @__PURE__ */ jsxs10(Box12, { marginBottom: 1, flexDirection: "column", children: [
4025
- /* @__PURE__ */ jsx14(Text12, { children: source.name }),
4026
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: source.docs ? `docs: ${source.docs}` : "full repo" }),
4027
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "Tags are pinned; update docs will skip them." }),
4028
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Repo ${currentIndex + 1}/${pendingSources.length}` })
4343
+ return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4344
+ /* @__PURE__ */ jsx15(Header, { title: "Select branch or tag" }),
4345
+ /* @__PURE__ */ jsxs11(Box13, { marginBottom: 1, flexDirection: "column", children: [
4346
+ /* @__PURE__ */ jsx15(Text13, { children: source.name }),
4347
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: source.docs ? `docs: ${source.docs}` : "full repo" }),
4348
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Tags are pinned; update docs will skip them." }),
4349
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: `Repo ${currentIndex + 1}/${pendingSources.length}` })
4029
4350
  ] }),
4030
- refError ? /* @__PURE__ */ jsx14(Box12, { marginBottom: 1, children: /* @__PURE__ */ jsx14(Text12, { color: "red", children: refError }) }) : null,
4031
- refStatus === "loading" ? /* @__PURE__ */ jsxs10(Text12, { children: [
4351
+ refError ? /* @__PURE__ */ jsx15(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text13, { color: "red", children: refError }) }) : null,
4352
+ refStatus === "loading" ? /* @__PURE__ */ jsxs11(Text13, { children: [
4032
4353
  spinner,
4033
4354
  " Loading refs..."
4034
- ] }) : /* @__PURE__ */ jsx14(
4355
+ ] }) : /* @__PURE__ */ jsx15(
4035
4356
  SingleSelect,
4036
4357
  {
4037
4358
  items: built.options.map((option) => ({
@@ -4061,17 +4382,17 @@ function AddDocsScreen() {
4061
4382
  hintMode: "active"
4062
4383
  }
4063
4384
  ),
4064
- /* @__PURE__ */ jsxs10(Box12, { marginTop: 1, children: [
4065
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: prereleaseNote }),
4066
- built.note ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: built.note }) : null
4385
+ /* @__PURE__ */ jsxs11(Box13, { marginTop: 1, children: [
4386
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: prereleaseNote }),
4387
+ built.note ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: built.note }) : null
4067
4388
  ] })
4068
4389
  ] });
4069
4390
  }
4070
4391
  if (status === "installing") {
4071
4392
  const docsBase = shortenPath(getDocsBase(), process.cwd());
4072
- return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
4073
- /* @__PURE__ */ jsx14(Header, { title: "Installing docs" }),
4074
- /* @__PURE__ */ jsxs10(Text12, { children: [
4393
+ return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4394
+ /* @__PURE__ */ jsx15(Header, { title: "Installing docs" }),
4395
+ /* @__PURE__ */ jsxs11(Text13, { children: [
4075
4396
  spinner,
4076
4397
  " Cloning ",
4077
4398
  selected.length,
@@ -4087,31 +4408,31 @@ function AddDocsScreen() {
4087
4408
  const skipped = results.filter((r) => r.status === "skipped");
4088
4409
  const failed = results.filter((r) => r.status === "failed");
4089
4410
  const cwd = process.cwd();
4090
- return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
4091
- /* @__PURE__ */ jsx14(Header, { title: "Docs installed" }),
4092
- installed.length > 0 ? /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginBottom: 1, children: [
4093
- /* @__PURE__ */ jsx14(Text12, { children: `Installed ${installed.length} repo${installed.length !== 1 ? "s" : ""}` }),
4094
- installed.map((item) => /* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
4411
+ return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4412
+ /* @__PURE__ */ jsx15(Header, { title: "Docs installed" }),
4413
+ installed.length > 0 ? /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginBottom: 1, children: [
4414
+ /* @__PURE__ */ jsx15(Text13, { children: `Installed ${installed.length} repo${installed.length !== 1 ? "s" : ""}` }),
4415
+ installed.map((item) => /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
4095
4416
  item.source.name,
4096
4417
  " -> ",
4097
4418
  shortenPath(item.path, cwd)
4098
4419
  ] }, `installed-${item.slug}`))
4099
4420
  ] }) : null,
4100
- skipped.length > 0 ? /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginBottom: 1, children: [
4101
- /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: "Skipped" }),
4102
- skipped.map((item) => /* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
4421
+ skipped.length > 0 ? /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginBottom: 1, children: [
4422
+ /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Skipped" }),
4423
+ skipped.map((item) => /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
4103
4424
  item.source.name,
4104
4425
  item.message ? ` (${item.message})` : ""
4105
4426
  ] }, `skipped-${item.slug}`))
4106
4427
  ] }) : null,
4107
- failed.length > 0 ? /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginBottom: 1, children: [
4108
- /* @__PURE__ */ jsx14(Text12, { color: "red", children: "Failed" }),
4109
- failed.map((item) => /* @__PURE__ */ jsxs10(Text12, { color: "red", children: [
4428
+ failed.length > 0 ? /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginBottom: 1, children: [
4429
+ /* @__PURE__ */ jsx15(Text13, { color: "red", children: "Failed" }),
4430
+ failed.map((item) => /* @__PURE__ */ jsxs11(Text13, { color: "red", children: [
4110
4431
  item.source.name,
4111
4432
  item.message ? ` (${item.message})` : ""
4112
4433
  ] }, `failed-${item.slug}`))
4113
4434
  ] }) : null,
4114
- /* @__PURE__ */ jsx14(
4435
+ /* @__PURE__ */ jsx15(
4115
4436
  SelectMenu,
4116
4437
  {
4117
4438
  items: [
@@ -4146,9 +4467,9 @@ function AddDocsScreen() {
4146
4467
  disabled: false
4147
4468
  };
4148
4469
  });
4149
- return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
4150
- /* @__PURE__ */ jsx14(Header, { title: "Select docs" }),
4151
- /* @__PURE__ */ jsx14(
4470
+ return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4471
+ /* @__PURE__ */ jsx15(Header, { title: "Select docs" }),
4472
+ /* @__PURE__ */ jsx15(
4152
4473
  MultiSelect,
4153
4474
  {
4154
4475
  items,
@@ -4177,7 +4498,7 @@ function AddDocsScreen() {
4177
4498
  }
4178
4499
  }
4179
4500
  ),
4180
- notice ? /* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text12, { color: "cyan", children: [
4501
+ notice ? /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs11(Text13, { color: "cyan", children: [
4181
4502
  "[i] ",
4182
4503
  notice
4183
4504
  ] }) }) : null
@@ -4185,8 +4506,8 @@ function AddDocsScreen() {
4185
4506
  }
4186
4507
 
4187
4508
  // src/tui/screens/AddInstall.tsx
4188
- import { Box as Box13, Text as Text13 } from "ink";
4189
- import React10 from "react";
4509
+ import { Box as Box14, Text as Text14 } from "ink";
4510
+ import React11 from "react";
4190
4511
 
4191
4512
  // src/skill-lock.ts
4192
4513
  import { createHash } from "crypto";
@@ -4685,14 +5006,14 @@ function formatResultSummary(results) {
4685
5006
  }
4686
5007
 
4687
5008
  // src/tui/screens/AddInstall.tsx
4688
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
5009
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4689
5010
  function AddInstallScreen() {
4690
5011
  const { addSkill, updateAddSkill, navigateTo } = useNavigation();
4691
5012
  const spinner = useSpinnerFrame(true);
4692
- const [status, setStatus] = React10.useState("running");
4693
- const [error, setError] = React10.useState(null);
4694
- const didRun = React10.useRef(false);
4695
- React10.useEffect(() => {
5013
+ const [status, setStatus] = React11.useState("running");
5014
+ const [error, setError] = React11.useState(null);
5015
+ const didRun = React11.useRef(false);
5016
+ React11.useEffect(() => {
4696
5017
  let cancelled = false;
4697
5018
  const run = async () => {
4698
5019
  if (didRun.current) return;
@@ -4746,15 +5067,15 @@ function AddInstallScreen() {
4746
5067
  };
4747
5068
  }, [addSkill, updateAddSkill, navigateTo]);
4748
5069
  if (status === "error") {
4749
- return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4750
- /* @__PURE__ */ jsx15(AddFlowHeader, { title: "Install failed" }),
4751
- /* @__PURE__ */ jsx15(Text13, { color: "red", children: error }),
4752
- /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: BACK_QUIT_HINT })
5070
+ return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
5071
+ /* @__PURE__ */ jsx16(AddFlowHeader, { title: "Install failed" }),
5072
+ /* @__PURE__ */ jsx16(Text14, { color: "red", children: error }),
5073
+ /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: BACK_QUIT_HINT })
4753
5074
  ] });
4754
5075
  }
4755
- return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
4756
- /* @__PURE__ */ jsx15(AddFlowHeader, { title: "Installing skills" }),
4757
- /* @__PURE__ */ jsxs11(Text13, { children: [
5076
+ return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
5077
+ /* @__PURE__ */ jsx16(AddFlowHeader, { title: "Installing skills" }),
5078
+ /* @__PURE__ */ jsxs12(Text14, { children: [
4758
5079
  spinner,
4759
5080
  " Installing..."
4760
5081
  ] })
@@ -4762,13 +5083,13 @@ function AddInstallScreen() {
4762
5083
  }
4763
5084
 
4764
5085
  // src/tui/screens/AddLicenseKey.tsx
4765
- import { Box as Box14, Text as Text14 } from "ink";
5086
+ import { Box as Box15, Text as Text15 } from "ink";
4766
5087
  import TextInput2 from "ink-text-input";
4767
- import React11 from "react";
4768
- import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
5088
+ import React12 from "react";
5089
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
4769
5090
  function AddLicenseKeyScreen() {
4770
5091
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
4771
- const [value, setValue] = React11.useState(
5092
+ const [value, setValue] = React12.useState(
4772
5093
  addSkill.licenseKey ?? invocation.options.licenseKey ?? ""
4773
5094
  );
4774
5095
  const { wrapOnChange } = useTextInput({
@@ -4785,27 +5106,27 @@ function AddLicenseKeyScreen() {
4785
5106
  updateAddSkill({ licenseKey: trimmed });
4786
5107
  navigateTo("add-skill-select");
4787
5108
  };
4788
- return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
4789
- /* @__PURE__ */ jsx16(Header, { title: "License key" }),
4790
- /* @__PURE__ */ jsx16(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text14, { children: "Enter the license key for this paid/private skill." }) }),
4791
- /* @__PURE__ */ jsx16(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: "Tip: you can also pass it via --license-key." }) }),
4792
- /* @__PURE__ */ jsxs12(Box14, { children: [
4793
- /* @__PURE__ */ jsx16(Text14, { color: "green", children: "> " }),
4794
- /* @__PURE__ */ jsx16(TextInput2, { value, onChange: wrapOnChange(setValue), onSubmit })
5109
+ return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, children: [
5110
+ /* @__PURE__ */ jsx17(Header, { title: "License key" }),
5111
+ /* @__PURE__ */ jsx17(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx17(Text15, { children: "Enter the license key for this paid/private skill." }) }),
5112
+ /* @__PURE__ */ jsx17(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx17(Text15, { dimColor: true, children: "Tip: you can also pass it via --license-key." }) }),
5113
+ /* @__PURE__ */ jsxs13(Box15, { children: [
5114
+ /* @__PURE__ */ jsx17(Text15, { color: "green", children: "> " }),
5115
+ /* @__PURE__ */ jsx17(TextInput2, { value, onChange: wrapOnChange(setValue), onSubmit })
4795
5116
  ] }),
4796
- /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: TEXT_INPUT_HINT }) })
5117
+ /* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text15, { dimColor: true, children: TEXT_INPUT_HINT }) })
4797
5118
  ] });
4798
5119
  }
4799
5120
 
4800
5121
  // src/tui/screens/AddMode.tsx
4801
5122
  import { join as join12 } from "path";
4802
- import { Box as Box15 } from "ink";
4803
- import React12 from "react";
4804
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
5123
+ import { Box as Box16 } from "ink";
5124
+ import React13 from "react";
5125
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4805
5126
  function AddModeScreen() {
4806
5127
  const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
4807
5128
  const options = invocation.options;
4808
- React12.useEffect(() => {
5129
+ React13.useEffect(() => {
4809
5130
  if (navAction === "pop") return;
4810
5131
  if (addSkill.installMode) {
4811
5132
  navigateTo("add-confirm");
@@ -4835,9 +5156,9 @@ function AddModeScreen() {
4835
5156
  { label: "Symlink (recommended)", value: "symlink", hint: symlinkHint },
4836
5157
  { label: "Copy to each agent", value: "copy", hint: copyHint }
4837
5158
  ];
4838
- return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, children: [
4839
- /* @__PURE__ */ jsx17(AddFlowHeader, { title: "Install mode" }),
4840
- /* @__PURE__ */ jsx17(
5159
+ return /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", padding: 1, children: [
5160
+ /* @__PURE__ */ jsx18(AddFlowHeader, { title: "Install mode" }),
5161
+ /* @__PURE__ */ jsx18(
4841
5162
  SingleSelect,
4842
5163
  {
4843
5164
  items,
@@ -4853,9 +5174,9 @@ function AddModeScreen() {
4853
5174
 
4854
5175
  // src/tui/screens/AddResult.tsx
4855
5176
  import chalk3 from "chalk";
4856
- import { Box as Box16, Text as Text15 } from "ink";
4857
- import React13 from "react";
4858
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
5177
+ import { Box as Box17, Text as Text16 } from "ink";
5178
+ import React14 from "react";
5179
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
4859
5180
  function AddResultScreen() {
4860
5181
  const { addSkill, resetAddSkill, navigateTo } = useNavigation();
4861
5182
  const results = addSkill.installResults ?? [];
@@ -4863,7 +5184,7 @@ function AddResultScreen() {
4863
5184
  const failed = results.filter((r) => !r.success);
4864
5185
  const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
4865
5186
  const summary = successful.length > 0 ? formatResultSummary(successful) : null;
4866
- const summaryLines = React13.useMemo(() => {
5187
+ const summaryLines = React14.useMemo(() => {
4867
5188
  if (!summary) return [];
4868
5189
  const counts = /* @__PURE__ */ new Map();
4869
5190
  return summary.lines.map((line) => {
@@ -4872,15 +5193,15 @@ function AddResultScreen() {
4872
5193
  return { line, key: `${line}-${count}` };
4873
5194
  });
4874
5195
  }, [summary]);
4875
- return /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", padding: 1, children: [
4876
- /* @__PURE__ */ jsx18(AddFlowHeader, { title: "Install results" }),
4877
- summary ? /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", marginBottom: 1, children: [
4878
- /* @__PURE__ */ jsx18(Text15, { children: summary.title }),
4879
- summaryLines.map(({ line, key }) => /* @__PURE__ */ jsx18(Text15, { children: line }, key))
5196
+ return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
5197
+ /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Install results" }),
5198
+ summary ? /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", marginBottom: 1, children: [
5199
+ /* @__PURE__ */ jsx19(Text16, { children: summary.title }),
5200
+ summaryLines.map(({ line, key }) => /* @__PURE__ */ jsx19(Text16, { children: line }, key))
4880
5201
  ] }) : null,
4881
- failed.length > 0 ? /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", marginBottom: 1, children: [
4882
- /* @__PURE__ */ jsx18(Text15, { color: "red", children: `Failed to install ${failed.length}` }),
4883
- failed.map((r) => /* @__PURE__ */ jsxs14(Text15, { children: [
5202
+ failed.length > 0 ? /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", marginBottom: 1, children: [
5203
+ /* @__PURE__ */ jsx19(Text16, { color: "red", children: `Failed to install ${failed.length}` }),
5204
+ failed.map((r) => /* @__PURE__ */ jsxs15(Text16, { children: [
4884
5205
  chalk3.red("\u2717"),
4885
5206
  " ",
4886
5207
  r.skill,
@@ -4890,15 +5211,15 @@ function AddResultScreen() {
4890
5211
  chalk3.dim(r.error)
4891
5212
  ] }, `${r.skill}-${r.agentId}`))
4892
5213
  ] }) : null,
4893
- successful.length > 0 ? /* @__PURE__ */ jsx18(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
5214
+ successful.length > 0 ? /* @__PURE__ */ jsx19(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsxs15(Text16, { dimColor: true, children: [
4894
5215
  "Installed to: ",
4895
5216
  formatList(successful.map((r) => r.agent))
4896
5217
  ] }) }) : null,
4897
- symlinkFailures.length > 0 ? /* @__PURE__ */ jsxs14(Box16, { marginBottom: 1, children: [
4898
- /* @__PURE__ */ jsx18(Text15, { color: "yellow", children: `Symlinks failed for: ${formatList(symlinkFailures.map((r) => r.agent))}` }),
4899
- /* @__PURE__ */ jsx18(Text15, { dimColor: true, children: "Files were copied instead." })
5218
+ symlinkFailures.length > 0 ? /* @__PURE__ */ jsxs15(Box17, { marginBottom: 1, children: [
5219
+ /* @__PURE__ */ jsx19(Text16, { color: "yellow", children: `Symlinks failed for: ${formatList(symlinkFailures.map((r) => r.agent))}` }),
5220
+ /* @__PURE__ */ jsx19(Text16, { dimColor: true, children: "Files were copied instead." })
4900
5221
  ] }) : null,
4901
- /* @__PURE__ */ jsx18(
5222
+ /* @__PURE__ */ jsx19(
4902
5223
  SelectMenu,
4903
5224
  {
4904
5225
  items: [
@@ -4921,13 +5242,13 @@ function AddResultScreen() {
4921
5242
  }
4922
5243
 
4923
5244
  // src/tui/screens/AddScope.tsx
4924
- import { Box as Box17 } from "ink";
4925
- import React14 from "react";
4926
- import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
5245
+ import { Box as Box18 } from "ink";
5246
+ import React15 from "react";
5247
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
4927
5248
  function AddScopeScreen() {
4928
5249
  const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
4929
5250
  const options = invocation.options;
4930
- React14.useEffect(() => {
5251
+ React15.useEffect(() => {
4931
5252
  if (navAction === "pop") return;
4932
5253
  if (addSkill.installGlobally !== void 0) {
4933
5254
  navigateTo("add-mode");
@@ -4950,9 +5271,9 @@ function AddScopeScreen() {
4950
5271
  const globalBase = getCanonicalSkillsBase({ global: true, cwd });
4951
5272
  const projectHint = `Project base (symlink): ${shortenPath(projectBase, cwd)}`;
4952
5273
  const globalHint = `Global base (symlink): ${shortenPath(globalBase, cwd)}`;
4953
- return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
4954
- /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Install scope" }),
4955
- /* @__PURE__ */ jsx19(
5274
+ return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5275
+ /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Install scope" }),
5276
+ /* @__PURE__ */ jsx20(
4956
5277
  SingleSelect,
4957
5278
  {
4958
5279
  items: [
@@ -4973,24 +5294,24 @@ function AddScopeScreen() {
4973
5294
  ] });
4974
5295
  }
4975
5296
 
4976
- // src/tui/screens/AddSecurityScan.tsx
4977
- import { Box as Box18, Text as Text16 } from "ink";
4978
- import React15 from "react";
4979
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
5297
+ // src/tui/screens/AddSecurityScan.tsx
5298
+ import { Box as Box19, Text as Text17 } from "ink";
5299
+ import React16 from "react";
5300
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
4980
5301
  function AddSecurityScanScreen() {
4981
5302
  const { invocation, addSkill, updateAddSkill, navigateTo, resetTo, setFlash, setBackHandler } = useNavigation();
4982
5303
  const options = invocation.options;
4983
- const [status, setStatus] = React15.useState("scanning");
4984
- const [error, setError] = React15.useState(null);
4985
- const [manualView, setManualView] = React15.useState("menu");
4986
- const [confirmText, setConfirmText] = React15.useState("");
4987
- const [selectedRow, setSelectedRow] = React15.useState(null);
5304
+ const [status, setStatus] = React16.useState("scanning");
5305
+ const [error, setError] = React16.useState(null);
5306
+ const [manualView, setManualView] = React16.useState("menu");
5307
+ const [confirmText, setConfirmText] = React16.useState("");
5308
+ const [selectedRow, setSelectedRow] = React16.useState(null);
4988
5309
  const spinner = useSpinnerFrame(status === "scanning");
4989
5310
  const { wrapOnChange } = useTextInput({
4990
5311
  onClear: () => setConfirmText(""),
4991
5312
  disabled: status !== "risky" || manualView !== "type-confirm"
4992
5313
  });
4993
- React15.useEffect(() => {
5314
+ React16.useEffect(() => {
4994
5315
  const selectedSkills = addSkill.selectedSkills;
4995
5316
  if (!selectedSkills || selectedSkills.length === 0) {
4996
5317
  navigateTo("add-skill-select");
@@ -5030,7 +5351,7 @@ function AddSecurityScanScreen() {
5030
5351
  cancelled = true;
5031
5352
  };
5032
5353
  }, [addSkill.selectedSkills, navigateTo, updateAddSkill]);
5033
- React15.useEffect(() => {
5354
+ React16.useEffect(() => {
5034
5355
  if (status !== "risky") {
5035
5356
  setBackHandler(null);
5036
5357
  return () => setBackHandler(null);
@@ -5054,17 +5375,17 @@ function AddSecurityScanScreen() {
5054
5375
  return () => setBackHandler(null);
5055
5376
  }, [status, manualView, setBackHandler]);
5056
5377
  if (status === "error") {
5057
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5058
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
5059
- /* @__PURE__ */ jsx20(Text16, { color: "red", children: error ?? "Scan failed" }),
5060
- /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT }) })
5378
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
5379
+ /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
5380
+ /* @__PURE__ */ jsx21(Text17, { color: "red", children: error ?? "Scan failed" }),
5381
+ /* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT }) })
5061
5382
  ] });
5062
5383
  }
5063
5384
  if (status === "scanning") {
5064
5385
  const count = addSkill.selectedSkills?.length ?? 0;
5065
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5066
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
5067
- /* @__PURE__ */ jsxs16(Text16, { children: [
5386
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
5387
+ /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
5388
+ /* @__PURE__ */ jsxs17(Text17, { children: [
5068
5389
  spinner,
5069
5390
  " Scanning ",
5070
5391
  count,
@@ -5075,9 +5396,9 @@ function AddSecurityScanScreen() {
5075
5396
  ] });
5076
5397
  }
5077
5398
  if (status === "risky") {
5078
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5079
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
5080
- /* @__PURE__ */ jsx20(
5399
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
5400
+ /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
5401
+ /* @__PURE__ */ jsx21(
5081
5402
  ManualSecurityGate,
5082
5403
  {
5083
5404
  scanRows: addSkill.securityScanRows ?? [],
@@ -5101,12 +5422,12 @@ function AddSecurityScanScreen() {
5101
5422
  ] });
5102
5423
  }
5103
5424
  if (options.yes) {
5104
- return /* @__PURE__ */ jsx20(Box18, { padding: 1 });
5425
+ return /* @__PURE__ */ jsx21(Box19, { padding: 1 });
5105
5426
  }
5106
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5107
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
5108
- /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: "Scan complete." }),
5109
- /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT }) })
5427
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
5428
+ /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
5429
+ /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: "Scan complete." }),
5430
+ /* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT }) })
5110
5431
  ] });
5111
5432
  }
5112
5433
 
@@ -5115,8 +5436,8 @@ import { existsSync as existsSync6 } from "fs";
5115
5436
  import { mkdir as mkdir6, mkdtemp as mkdtemp4, writeFile as writeFile4 } from "fs/promises";
5116
5437
  import { tmpdir as tmpdir5 } from "os";
5117
5438
  import { join as join15 } from "path";
5118
- import { Box as Box19, Text as Text17 } from "ink";
5119
- import React16 from "react";
5439
+ import { Box as Box20, Text as Text18 } from "ink";
5440
+ import React17 from "react";
5120
5441
 
5121
5442
  // src/mintlify.ts
5122
5443
  import matter3 from "gray-matter";
@@ -6140,36 +6461,8 @@ function resolvePluginSource(plugin, context) {
6140
6461
  return { kind: "unsupported", reason: "Unknown source type", overrides };
6141
6462
  }
6142
6463
 
6143
- // src/tui/utils/skill-selection.ts
6144
- import { basename as basename5 } from "path";
6145
- function matchesSkillName(skill, input) {
6146
- const normalized = input.toLowerCase();
6147
- const byName = skill.name.toLowerCase() === normalized;
6148
- const byPath = basename5(skill.path).toLowerCase() === normalized;
6149
- return byName || byPath;
6150
- }
6151
- function autoSelect(skills, options) {
6152
- if (options.skill && options.skill.length > 0) {
6153
- const selected = skills.filter((s) => options.skill?.some((name) => matchesSkillName(s, name)));
6154
- if (selected.length === 0) {
6155
- return {
6156
- status: "prompt",
6157
- message: `No matching skills found for: ${options.skill.join(", ")}`
6158
- };
6159
- }
6160
- return { status: "selected", skills: selected };
6161
- }
6162
- if (skills.length === 1) {
6163
- return { status: "selected", skills };
6164
- }
6165
- if (options.yes) {
6166
- return { status: "selected", skills };
6167
- }
6168
- return { status: "prompt" };
6169
- }
6170
-
6171
6464
  // src/tui/screens/AddSkillSelect.tsx
6172
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
6465
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
6173
6466
  function AddSkillSelectScreen() {
6174
6467
  const {
6175
6468
  invocation,
@@ -6183,16 +6476,16 @@ function AddSkillSelectScreen() {
6183
6476
  resetAddSkill,
6184
6477
  setLastSource
6185
6478
  } = useNavigation();
6186
- const [status, setStatus] = React16.useState(
6479
+ const [status, setStatus] = React17.useState(
6187
6480
  addSkill.skills && addSkill.skills.length > 0 ? "ready" : "loading"
6188
6481
  );
6189
- const [error, setError] = React16.useState(null);
6190
- const [listMode, setListMode] = React16.useState(false);
6191
- const [showLoading, setShowLoading] = React16.useState(false);
6482
+ const [error, setError] = React17.useState(null);
6483
+ const [listMode, setListMode] = React17.useState(false);
6484
+ const [showLoading, setShowLoading] = React17.useState(false);
6192
6485
  const spinner = useSpinnerFrame(status === "loading");
6193
6486
  const source = addSkill.source ?? invocation.source;
6194
6487
  const options = invocation.options;
6195
- React16.useEffect(() => {
6488
+ React17.useEffect(() => {
6196
6489
  let cancelled = false;
6197
6490
  const load = async () => {
6198
6491
  if (!source) {
@@ -6390,7 +6683,7 @@ function AddSkillSelectScreen() {
6390
6683
  cancelled = true;
6391
6684
  };
6392
6685
  }, [source, addSkill.skills, addSkill.licenseKey, updateAddSkill, navigateTo, options, setFlash]);
6393
- React16.useEffect(() => {
6686
+ React17.useEffect(() => {
6394
6687
  if (invocation.source) {
6395
6688
  setBackHandler(() => {
6396
6689
  setLastSource(invocation.source ?? null);
@@ -6406,7 +6699,7 @@ function AddSkillSelectScreen() {
6406
6699
  setBackHandler(null);
6407
6700
  };
6408
6701
  }, [invocation.source, resetTo, setBackHandler, resetAddSkill, setInvocation, setLastSource]);
6409
- React16.useEffect(() => {
6702
+ React17.useEffect(() => {
6410
6703
  if (status !== "loading") {
6411
6704
  setShowLoading(false);
6412
6705
  return;
@@ -6417,18 +6710,18 @@ function AddSkillSelectScreen() {
6417
6710
  return () => clearTimeout(timer);
6418
6711
  }, [status]);
6419
6712
  if (!source) {
6420
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6421
- /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Add skills" }),
6422
- /* @__PURE__ */ jsx21(Text17, { children: `Missing source. ${BACK_QUIT_HINT}` })
6713
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6714
+ /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Add skills" }),
6715
+ /* @__PURE__ */ jsx22(Text18, { children: `Missing source. ${BACK_QUIT_HINT}` })
6423
6716
  ] });
6424
6717
  }
6425
6718
  if (status === "loading" && !showLoading) {
6426
- return /* @__PURE__ */ jsx21(Box19, { padding: 1 });
6719
+ return /* @__PURE__ */ jsx22(Box20, { padding: 1 });
6427
6720
  }
6428
6721
  if (status === "loading") {
6429
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6430
- /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Scanning skills" }),
6431
- /* @__PURE__ */ jsxs17(Text17, { children: [
6722
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6723
+ /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Scanning skills" }),
6724
+ /* @__PURE__ */ jsxs18(Text18, { children: [
6432
6725
  spinner,
6433
6726
  " Fetching skills from ",
6434
6727
  source
@@ -6436,32 +6729,32 @@ function AddSkillSelectScreen() {
6436
6729
  ] });
6437
6730
  }
6438
6731
  if (status === "error") {
6439
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6440
- /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Unable to load skills" }),
6441
- /* @__PURE__ */ jsx21(Text17, { color: "red", children: error }),
6442
- /* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT }) })
6732
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6733
+ /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Unable to load skills" }),
6734
+ /* @__PURE__ */ jsx22(Text18, { color: "red", children: error }),
6735
+ /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: BACK_QUIT_HINT }) })
6443
6736
  ] });
6444
6737
  }
6445
6738
  const skills = addSkill.skills ?? [];
6446
6739
  if (listMode || status === "list") {
6447
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6448
- /* @__PURE__ */ jsx21(AddFlowHeader, { title: `Available skills (${skills.length})` }),
6449
- skills.map((skill) => /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, children: [
6450
- /* @__PURE__ */ jsx21(Text17, { children: getSkillDisplayName(skill) }),
6451
- skill.description ? /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: skill.description }) : null
6740
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6741
+ /* @__PURE__ */ jsx22(AddFlowHeader, { title: `Available skills (${skills.length})` }),
6742
+ skills.map((skill) => /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", marginBottom: 1, children: [
6743
+ /* @__PURE__ */ jsx22(Text18, { children: getSkillDisplayName(skill) }),
6744
+ skill.description ? /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: skill.description }) : null
6452
6745
  ] }, skill.name)),
6453
- /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT })
6746
+ /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: BACK_QUIT_HINT })
6454
6747
  ] });
6455
6748
  }
6456
6749
  if (skills.length === 0) {
6457
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6458
- /* @__PURE__ */ jsx21(AddFlowHeader, { title: "No skills found" }),
6459
- /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT })
6750
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6751
+ /* @__PURE__ */ jsx22(AddFlowHeader, { title: "No skills found" }),
6752
+ /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: BACK_QUIT_HINT })
6460
6753
  ] });
6461
6754
  }
6462
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6463
- /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Select skills" }),
6464
- /* @__PURE__ */ jsx21(
6755
+ return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6756
+ /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Select skills" }),
6757
+ /* @__PURE__ */ jsx22(
6465
6758
  MultiSelect,
6466
6759
  {
6467
6760
  items: skills.map((skill) => ({
@@ -6493,22 +6786,22 @@ function AddSkillSelectScreen() {
6493
6786
  }
6494
6787
 
6495
6788
  // src/tui/screens/AddSource.tsx
6496
- import { Box as Box20, Text as Text18 } from "ink";
6789
+ import { Box as Box21, Text as Text19 } from "ink";
6497
6790
  import TextInput3 from "ink-text-input";
6498
- import React17 from "react";
6499
- import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
6791
+ import React18 from "react";
6792
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
6500
6793
  function AddSourceScreen() {
6501
6794
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, lastSource, setLastSource } = useNavigation();
6502
- const [value, setValue] = React17.useState(
6795
+ const [value, setValue] = React18.useState(
6503
6796
  addSkill.source ?? invocation.source ?? lastSource ?? ""
6504
6797
  );
6505
- const didAutofillRef = React17.useRef(false);
6798
+ const didAutofillRef = React18.useRef(false);
6506
6799
  const { wrapOnChange } = useTextInput({
6507
6800
  onClear: () => {
6508
6801
  setValue("");
6509
6802
  }
6510
6803
  });
6511
- React17.useEffect(() => {
6804
+ React18.useEffect(() => {
6512
6805
  const preset = invocation.source;
6513
6806
  if (!preset || didAutofillRef.current) return;
6514
6807
  didAutofillRef.current = true;
@@ -6525,31 +6818,31 @@ function AddSourceScreen() {
6525
6818
  updateAddSkill({ source: trimmed });
6526
6819
  navigateTo("add-skill-select");
6527
6820
  };
6528
- return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6529
- /* @__PURE__ */ jsx22(Header, { title: "Add skills" }),
6530
- /* @__PURE__ */ jsx22(Box20, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text18, { children: "Where should we fetch skills from?" }) }),
6531
- /* @__PURE__ */ jsx22(Box20, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: "Examples: owner/repo, https://.../SKILL.md, ./local/path" }) }),
6532
- /* @__PURE__ */ jsxs18(Box20, { children: [
6533
- /* @__PURE__ */ jsx22(Text18, { color: "green", children: "> " }),
6534
- /* @__PURE__ */ jsx22(TextInput3, { value, onChange: wrapOnChange(setValue), onSubmit })
6821
+ return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
6822
+ /* @__PURE__ */ jsx23(Header, { title: "Add skills" }),
6823
+ /* @__PURE__ */ jsx23(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsx23(Text19, { children: "Where should we fetch skills from?" }) }),
6824
+ /* @__PURE__ */ jsx23(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: "Examples: owner/repo, https://.../SKILL.md, ./local/path" }) }),
6825
+ /* @__PURE__ */ jsxs19(Box21, { children: [
6826
+ /* @__PURE__ */ jsx23(Text19, { color: "green", children: "> " }),
6827
+ /* @__PURE__ */ jsx23(TextInput3, { value, onChange: wrapOnChange(setValue), onSubmit })
6535
6828
  ] }),
6536
- /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: TEXT_INPUT_HINT }) })
6829
+ /* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: TEXT_INPUT_HINT }) })
6537
6830
  ] });
6538
6831
  }
6539
6832
 
6540
6833
  // src/tui/screens/AddTargets.tsx
6541
- import { Box as Box21, Text as Text19 } from "ink";
6542
- import React18 from "react";
6543
- import { Fragment as Fragment2, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
6834
+ import { Box as Box22, Text as Text20 } from "ink";
6835
+ import React19 from "react";
6836
+ import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
6544
6837
  function AddTargetsScreen() {
6545
6838
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, navAction } = useNavigation();
6546
- const [status, setStatus] = React18.useState("loading");
6547
- const [mode, setMode] = React18.useState("choice");
6548
- const [availableAgents, setAvailableAgents] = React18.useState([]);
6549
- const [lastSelected, setLastSelected] = React18.useState([]);
6550
- const [showLoading, setShowLoading] = React18.useState(false);
6839
+ const [status, setStatus] = React19.useState("loading");
6840
+ const [mode, setMode] = React19.useState("choice");
6841
+ const [availableAgents, setAvailableAgents] = React19.useState([]);
6842
+ const [lastSelected, setLastSelected] = React19.useState([]);
6843
+ const [showLoading, setShowLoading] = React19.useState(false);
6551
6844
  const spinner = useSpinnerFrame(status === "loading");
6552
- React18.useEffect(() => {
6845
+ React19.useEffect(() => {
6553
6846
  let cancelled = false;
6554
6847
  const run = async () => {
6555
6848
  setStatus("loading");
@@ -6598,7 +6891,7 @@ function AddTargetsScreen() {
6598
6891
  cancelled = true;
6599
6892
  };
6600
6893
  }, [invocation.options, updateAddSkill, navigateTo, addSkill.targetAgents, setFlash, navAction]);
6601
- React18.useEffect(() => {
6894
+ React19.useEffect(() => {
6602
6895
  if (status !== "loading") {
6603
6896
  setShowLoading(false);
6604
6897
  return;
@@ -6609,12 +6902,12 @@ function AddTargetsScreen() {
6609
6902
  return () => clearTimeout(timer);
6610
6903
  }, [status]);
6611
6904
  if (status === "loading" && !showLoading) {
6612
- return /* @__PURE__ */ jsx23(Box21, { padding: 1 });
6905
+ return /* @__PURE__ */ jsx24(Box22, { padding: 1 });
6613
6906
  }
6614
6907
  if (status === "loading") {
6615
- return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
6616
- /* @__PURE__ */ jsx23(AddFlowHeader, { title: "Detecting agents" }),
6617
- /* @__PURE__ */ jsxs19(Text19, { children: [
6908
+ return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
6909
+ /* @__PURE__ */ jsx24(AddFlowHeader, { title: "Detecting agents" }),
6910
+ /* @__PURE__ */ jsxs20(Text20, { children: [
6618
6911
  spinner,
6619
6912
  " Checking installed agents..."
6620
6913
  ] })
@@ -6636,9 +6929,9 @@ function AddTargetsScreen() {
6636
6929
  label: agents[agent].displayName,
6637
6930
  hint: agents[agent].skillsDir
6638
6931
  }));
6639
- return /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", padding: 1, children: mode === "choice" ? /* @__PURE__ */ jsxs19(Fragment2, { children: [
6640
- /* @__PURE__ */ jsx23(AddFlowHeader, { title: "Install to" }),
6641
- /* @__PURE__ */ jsx23(
6932
+ return /* @__PURE__ */ jsx24(Box22, { flexDirection: "column", padding: 1, children: mode === "choice" ? /* @__PURE__ */ jsxs20(Fragment2, { children: [
6933
+ /* @__PURE__ */ jsx24(AddFlowHeader, { title: "Install to" }),
6934
+ /* @__PURE__ */ jsx24(
6642
6935
  SingleSelect,
6643
6936
  {
6644
6937
  items: [
@@ -6671,9 +6964,9 @@ function AddTargetsScreen() {
6671
6964
  }
6672
6965
  }
6673
6966
  )
6674
- ] }) : /* @__PURE__ */ jsxs19(Fragment2, { children: [
6675
- /* @__PURE__ */ jsx23(AddFlowHeader, { title: "Select agents" }),
6676
- /* @__PURE__ */ jsx23(
6967
+ ] }) : /* @__PURE__ */ jsxs20(Fragment2, { children: [
6968
+ /* @__PURE__ */ jsx24(AddFlowHeader, { title: "Select agents" }),
6969
+ /* @__PURE__ */ jsx24(
6677
6970
  MultiSelect,
6678
6971
  {
6679
6972
  items: selectableItems,
@@ -6705,9 +6998,9 @@ function AddTargetsScreen() {
6705
6998
  }
6706
6999
 
6707
7000
  // src/tui/screens/FindSkillResults.tsx
6708
- import { Box as Box22, Text as Text20 } from "ink";
6709
- import React19 from "react";
6710
- import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
7001
+ import { Box as Box23, Text as Text21 } from "ink";
7002
+ import React20 from "react";
7003
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
6711
7004
  var formatStars = (value) => {
6712
7005
  if (!value || value <= 0) return "";
6713
7006
  if (value >= 1e3) {
@@ -6736,8 +7029,8 @@ var truncateLabel = (value, max = 100) => {
6736
7029
  };
6737
7030
  function FindSkillResultsScreen() {
6738
7031
  const { findSkill, updateFindSkill, resetAddSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
6739
- const [status, setStatus] = React19.useState("ready");
6740
- const [error, setError] = React19.useState(null);
7032
+ const [status, setStatus] = React20.useState("ready");
7033
+ const [error, setError] = React20.useState(null);
6741
7034
  const spinner = useSpinnerFrame(status === "loading");
6742
7035
  const results = findSkill.results ?? [];
6743
7036
  const query = findSkill.query ?? "";
@@ -6775,36 +7068,36 @@ function FindSkillResultsScreen() {
6775
7068
  setStatus("error");
6776
7069
  }
6777
7070
  };
6778
- React19.useEffect(() => {
7071
+ React20.useEffect(() => {
6779
7072
  if (results.length === 0) {
6780
7073
  setStatus("ready");
6781
7074
  }
6782
7075
  }, [results.length]);
6783
7076
  if (status === "loading") {
6784
- return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
6785
- /* @__PURE__ */ jsx24(Header, { title: "Preparing skills" }),
6786
- /* @__PURE__ */ jsxs20(Text20, { children: [
7077
+ return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
7078
+ /* @__PURE__ */ jsx25(Header, { title: "Preparing skills" }),
7079
+ /* @__PURE__ */ jsxs21(Text21, { children: [
6787
7080
  spinner,
6788
7081
  " Cloning repositories..."
6789
7082
  ] })
6790
7083
  ] });
6791
7084
  }
6792
7085
  if (results.length === 0) {
6793
- return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
6794
- /* @__PURE__ */ jsx24(Header, { title: "No results" }),
6795
- /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: "No skills found." }),
6796
- /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: BACK_QUIT_HINT }) })
7086
+ return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
7087
+ /* @__PURE__ */ jsx25(Header, { title: "No results" }),
7088
+ /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: "No skills found." }),
7089
+ /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: BACK_QUIT_HINT }) })
6797
7090
  ] });
6798
7091
  }
6799
- return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
6800
- /* @__PURE__ */ jsx24(Header, { title: "Select skills" }),
6801
- /* @__PURE__ */ jsxs20(Box22, { marginBottom: 1, flexDirection: "column", children: [
6802
- /* @__PURE__ */ jsx24(Text20, { children: `Query: ${query}` }),
6803
- /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: `Mode: ${modeLabel} search` }),
6804
- /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: FIND_SKILLS_HINT })
7092
+ return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
7093
+ /* @__PURE__ */ jsx25(Header, { title: "Select skills" }),
7094
+ /* @__PURE__ */ jsxs21(Box23, { marginBottom: 1, flexDirection: "column", children: [
7095
+ /* @__PURE__ */ jsx25(Text21, { children: `Query: ${query}` }),
7096
+ /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: `Mode: ${modeLabel} search` }),
7097
+ /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: FIND_SKILLS_HINT })
6805
7098
  ] }),
6806
- status === "error" ? /* @__PURE__ */ jsx24(Box22, { marginBottom: 1, children: /* @__PURE__ */ jsx24(Text20, { color: "red", children: error }) }) : null,
6807
- /* @__PURE__ */ jsx24(
7099
+ status === "error" ? /* @__PURE__ */ jsx25(Box23, { marginBottom: 1, children: /* @__PURE__ */ jsx25(Text21, { color: "red", children: error }) }) : null,
7100
+ /* @__PURE__ */ jsx25(
6808
7101
  MultiSelect,
6809
7102
  {
6810
7103
  items: results.map((result) => ({
@@ -6822,21 +7115,21 @@ function FindSkillResultsScreen() {
6822
7115
  }
6823
7116
 
6824
7117
  // src/tui/screens/FindSkillSearch.tsx
6825
- import { Box as Box23, Text as Text21, useInput as useInput5 } from "ink";
7118
+ import { Box as Box24, Text as Text22, useInput as useInput5 } from "ink";
6826
7119
  import TextInput4 from "ink-text-input";
6827
- import React20 from "react";
6828
- import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
7120
+ import React21 from "react";
7121
+ import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
6829
7122
  var MIN_QUERY_LENGTH = 2;
6830
7123
  function getDebounceMs(queryLength) {
6831
7124
  return Math.max(150, 350 - queryLength * 50);
6832
7125
  }
6833
7126
  function FindSkillSearchScreen() {
6834
7127
  const { findSkill, updateFindSkill, navigateTo, setFlash } = useNavigation();
6835
- const [value, setValue] = React20.useState(findSkill.query ?? "");
6836
- const [status, setStatus] = React20.useState("idle");
6837
- const [error, setError] = React20.useState(null);
6838
- const [preview, setPreview] = React20.useState([]);
6839
- const debounceRef = React20.useRef(null);
7128
+ const [value, setValue] = React21.useState(findSkill.query ?? "");
7129
+ const [status, setStatus] = React21.useState("idle");
7130
+ const [error, setError] = React21.useState(null);
7131
+ const [preview, setPreview] = React21.useState([]);
7132
+ const debounceRef = React21.useRef(null);
6840
7133
  const spinner = useSpinnerFrame(status === "searching" || status === "loading");
6841
7134
  const { wrapOnChange } = useTextInput({
6842
7135
  disabled: status === "loading",
@@ -6847,7 +7140,7 @@ function FindSkillSearchScreen() {
6847
7140
  updateFindSkill({ query: "" });
6848
7141
  }
6849
7142
  });
6850
- const triggerLiveSearch = React20.useCallback((query) => {
7143
+ const triggerLiveSearch = React21.useCallback((query) => {
6851
7144
  if (debounceRef.current) {
6852
7145
  clearTimeout(debounceRef.current);
6853
7146
  debounceRef.current = null;
@@ -6871,14 +7164,14 @@ function FindSkillSearchScreen() {
6871
7164
  }
6872
7165
  }, debounceMs);
6873
7166
  }, []);
6874
- React20.useEffect(() => {
7167
+ React21.useEffect(() => {
6875
7168
  return () => {
6876
7169
  if (debounceRef.current) {
6877
7170
  clearTimeout(debounceRef.current);
6878
7171
  }
6879
7172
  };
6880
7173
  }, []);
6881
- const goToLexicalResults = React20.useCallback(async () => {
7174
+ const goToLexicalResults = React21.useCallback(async () => {
6882
7175
  const query = value.trim();
6883
7176
  if (!query || query.length < MIN_QUERY_LENGTH) {
6884
7177
  setFlash(`Enter at least ${MIN_QUERY_LENGTH} characters.`);
@@ -6905,7 +7198,7 @@ function FindSkillSearchScreen() {
6905
7198
  setStatus("error");
6906
7199
  }
6907
7200
  }, [value, setFlash, updateFindSkill, navigateTo]);
6908
- const runSemanticSearch = React20.useCallback(async () => {
7201
+ const runSemanticSearch = React21.useCallback(async () => {
6909
7202
  const query = value.trim();
6910
7203
  if (!query) {
6911
7204
  setFlash("Enter a search term.");
@@ -6950,12 +7243,12 @@ function FindSkillSearchScreen() {
6950
7243
  });
6951
7244
  const showPreview = preview.length > 0 && status !== "loading";
6952
7245
  const showSearching = status === "searching" && value.trim().length >= MIN_QUERY_LENGTH;
6953
- return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
6954
- /* @__PURE__ */ jsx25(Header, { title: "Find skills" }),
6955
- /* @__PURE__ */ jsx25(Box23, { marginBottom: 1, children: /* @__PURE__ */ jsx25(Text21, { children: "Find a skill to give your agent new capabilities." }) }),
6956
- /* @__PURE__ */ jsxs21(Box23, { children: [
6957
- /* @__PURE__ */ jsx25(Text21, { color: "green", children: "> " }),
6958
- /* @__PURE__ */ jsx25(
7246
+ return /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", padding: 1, children: [
7247
+ /* @__PURE__ */ jsx26(Header, { title: "Find skills" }),
7248
+ /* @__PURE__ */ jsx26(Box24, { marginBottom: 1, children: /* @__PURE__ */ jsx26(Text22, { children: "Find a skill to give your agent new capabilities." }) }),
7249
+ /* @__PURE__ */ jsxs22(Box24, { children: [
7250
+ /* @__PURE__ */ jsx26(Text22, { color: "green", children: "> " }),
7251
+ /* @__PURE__ */ jsx26(
6959
7252
  TextInput4,
6960
7253
  {
6961
7254
  value,
@@ -6973,52 +7266,52 @@ function FindSkillSearchScreen() {
6973
7266
  }
6974
7267
  )
6975
7268
  ] }),
6976
- showSearching && !showPreview ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
7269
+ showSearching && !showPreview ? /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
6977
7270
  spinner,
6978
7271
  " Searching..."
6979
7272
  ] }) }) : null,
6980
- showPreview ? /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", marginTop: 1, children: [
6981
- /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
7273
+ showPreview ? /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", marginTop: 1, children: [
7274
+ /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
6982
7275
  preview.length,
6983
7276
  " result",
6984
7277
  preview.length !== 1 ? "s" : "",
6985
7278
  " found:"
6986
7279
  ] }),
6987
- preview.slice(0, 3).map((result) => /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
7280
+ preview.slice(0, 3).map((result) => /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
6988
7281
  " ",
6989
7282
  "\u2022 ",
6990
7283
  result.name,
6991
7284
  result.repoOwner ? ` (${result.repoOwner}/${result.repoName})` : ""
6992
7285
  ] }, result.id)),
6993
- preview.length > 3 ? /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
7286
+ preview.length > 3 ? /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
6994
7287
  " ",
6995
7288
  "... and ",
6996
7289
  preview.length - 3,
6997
7290
  " more"
6998
7291
  ] }) : null
6999
7292
  ] }) : null,
7000
- status === "loading" ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { children: [
7293
+ status === "loading" ? /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text22, { children: [
7001
7294
  spinner,
7002
7295
  " Running AI search..."
7003
7296
  ] }) }) : null,
7004
- status === "error" ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(Text21, { color: "red", children: error }) }) : null,
7005
- /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: "Enter for fast results, Tab for AI search" }) }),
7006
- /* @__PURE__ */ jsx25(Box23, { children: /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: TEXT_INPUT_HINT }) })
7297
+ status === "error" ? /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx26(Text22, { color: "red", children: error }) }) : null,
7298
+ /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: "Enter for fast results, Tab for AI search" }) }),
7299
+ /* @__PURE__ */ jsx26(Box24, { children: /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: TEXT_INPUT_HINT }) })
7007
7300
  ] });
7008
7301
  }
7009
7302
 
7010
7303
  // src/tui/screens/GetUrl.tsx
7011
- import { Box as Box24, Text as Text22, useApp } from "ink";
7012
- import React21 from "react";
7013
- import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
7304
+ import { Box as Box25, Text as Text23, useApp } from "ink";
7305
+ import React22 from "react";
7306
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
7014
7307
  function GetUrlScreen() {
7015
7308
  const { exit } = useApp();
7016
7309
  const { invocation } = useNavigation();
7017
7310
  const spinner = useSpinnerFrame(true);
7018
- const didRun = React21.useRef(false);
7311
+ const didRun = React22.useRef(false);
7019
7312
  const outputPath = invocation.options?.output ?? null;
7020
7313
  const outputFormat = invocation.options?.json ? "json" : "markdown";
7021
- React21.useEffect(() => {
7314
+ React22.useEffect(() => {
7022
7315
  let cancelled = false;
7023
7316
  const run = async () => {
7024
7317
  if (didRun.current) return;
@@ -7047,12 +7340,12 @@ function GetUrlScreen() {
7047
7340
  cancelled = true;
7048
7341
  };
7049
7342
  }, [exit, invocation]);
7050
- return /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", padding: 1, children: [
7051
- /* @__PURE__ */ jsx26(Header, { title: "Fetching URL" }),
7052
- invocation.source ? /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: `URL: ${invocation.source}` }) : null,
7053
- outputPath ? /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: `Output: ${outputPath}` }) : null,
7054
- outputFormat === "json" ? /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: "Format: json" }) : null,
7055
- /* @__PURE__ */ jsxs22(Text22, { children: [
7343
+ return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
7344
+ /* @__PURE__ */ jsx27(Header, { title: "Fetching URL" }),
7345
+ invocation.source ? /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: `URL: ${invocation.source}` }) : null,
7346
+ outputPath ? /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: `Output: ${outputPath}` }) : null,
7347
+ outputFormat === "json" ? /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: "Format: json" }) : null,
7348
+ /* @__PURE__ */ jsxs23(Text23, { children: [
7056
7349
  spinner,
7057
7350
  " Fetching markdown..."
7058
7351
  ] })
@@ -7060,12 +7353,12 @@ function GetUrlScreen() {
7060
7353
  }
7061
7354
 
7062
7355
  // src/tui/screens/ListSkills.tsx
7063
- import { Box as Box25, Text as Text23 } from "ink";
7064
- import React22 from "react";
7356
+ import { Box as Box26, Text as Text24 } from "ink";
7357
+ import React23 from "react";
7065
7358
 
7066
7359
  // src/installed-skills.ts
7067
7360
  import { lstat as lstat2, readFile as readFile5, readdir as readdir4, stat as stat4 } from "fs/promises";
7068
- import { basename as basename6, join as join16 } from "path";
7361
+ import { basename as basename7, join as join16 } from "path";
7069
7362
  import matter8 from "gray-matter";
7070
7363
  function getAgentSkillsDir(agent, scope, cwd) {
7071
7364
  const config = agents[agent];
@@ -7153,7 +7446,7 @@ async function listSkillsForAgents(agentsList, scopes, cwd = process.cwd()) {
7153
7446
  }
7154
7447
  async function findSkillInstallations(skillName, scope, cwd = process.cwd()) {
7155
7448
  const installs = [];
7156
- const sanitized = basename6(getCanonicalPath(skillName, { global: scope === "global", cwd }));
7449
+ const sanitized = basename7(getCanonicalPath(skillName, { global: scope === "global", cwd }));
7157
7450
  if (!sanitized) {
7158
7451
  return installs;
7159
7452
  }
@@ -7176,12 +7469,12 @@ async function findSkillInstallations(skillName, scope, cwd = process.cwd()) {
7176
7469
  }
7177
7470
 
7178
7471
  // src/tui/screens/ListSkills.tsx
7179
- import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
7472
+ import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
7180
7473
  function ListScreen() {
7181
7474
  const { navigateTo, setBackHandler } = useNavigation();
7182
- const [summaries, setSummaries] = React22.useState([]);
7183
- const [selectedAgent, setSelectedAgent] = React22.useState(null);
7184
- React22.useEffect(() => {
7475
+ const [summaries, setSummaries] = React23.useState([]);
7476
+ const [selectedAgent, setSelectedAgent] = React23.useState(null);
7477
+ React23.useEffect(() => {
7185
7478
  let cancelled = false;
7186
7479
  const load = async () => {
7187
7480
  const installed = await detectInstalledAgents();
@@ -7204,7 +7497,7 @@ function ListScreen() {
7204
7497
  cancelled = true;
7205
7498
  };
7206
7499
  }, []);
7207
- React22.useEffect(() => {
7500
+ React23.useEffect(() => {
7208
7501
  if (!selectedAgent) {
7209
7502
  setBackHandler(null);
7210
7503
  return;
@@ -7219,17 +7512,17 @@ function ListScreen() {
7219
7512
  }, [selectedAgent, setBackHandler]);
7220
7513
  if (selectedAgent) {
7221
7514
  const total = selectedAgent.projectSkills.length + selectedAgent.globalSkills.length;
7222
- return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
7223
- /* @__PURE__ */ jsx27(Header, { title: `${agents[selectedAgent.agent].displayName} (${total})` }),
7224
- selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", marginBottom: 1, children: [
7225
- /* @__PURE__ */ jsx27(Text23, { children: "Project" }),
7226
- selectedAgent.projectSkills.map((name) => /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: name }, `p-${name}`))
7515
+ return /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", padding: 1, children: [
7516
+ /* @__PURE__ */ jsx28(Header, { title: `${agents[selectedAgent.agent].displayName} (${total})` }),
7517
+ selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", marginBottom: 1, children: [
7518
+ /* @__PURE__ */ jsx28(Text24, { children: "Project" }),
7519
+ selectedAgent.projectSkills.map((name) => /* @__PURE__ */ jsx28(Text24, { dimColor: true, children: name }, `p-${name}`))
7227
7520
  ] }) : null,
7228
- selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", marginBottom: 1, children: [
7229
- /* @__PURE__ */ jsx27(Text23, { children: "Global" }),
7230
- selectedAgent.globalSkills.map((name) => /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: name }, `g-${name}`))
7521
+ selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", marginBottom: 1, children: [
7522
+ /* @__PURE__ */ jsx28(Text24, { children: "Global" }),
7523
+ selectedAgent.globalSkills.map((name) => /* @__PURE__ */ jsx28(Text24, { dimColor: true, children: name }, `g-${name}`))
7231
7524
  ] }) : null,
7232
- /* @__PURE__ */ jsx27(
7525
+ /* @__PURE__ */ jsx28(
7233
7526
  SelectMenu,
7234
7527
  {
7235
7528
  items: [
@@ -7256,9 +7549,9 @@ function ListScreen() {
7256
7549
  hint: `${count} skill${count !== 1 ? "s" : ""}`
7257
7550
  };
7258
7551
  });
7259
- return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
7260
- /* @__PURE__ */ jsx27(Header, { title: "Installed skills" }),
7261
- /* @__PURE__ */ jsx27(
7552
+ return /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", padding: 1, children: [
7553
+ /* @__PURE__ */ jsx28(Header, { title: "Installed skills" }),
7554
+ /* @__PURE__ */ jsx28(
7262
7555
  SelectMenu,
7263
7556
  {
7264
7557
  items,
@@ -7275,8 +7568,8 @@ function ListScreen() {
7275
7568
  }
7276
7569
 
7277
7570
  // src/tui/screens/MainMenu.tsx
7278
- import { Box as Box26 } from "ink";
7279
- import { jsx as jsx28 } from "react/jsx-runtime";
7571
+ import { Box as Box27 } from "ink";
7572
+ import { jsx as jsx29 } from "react/jsx-runtime";
7280
7573
  function MainMenu() {
7281
7574
  const { navigateTo, resetAddSkill, resetFindSkill, setInvocation } = useNavigation();
7282
7575
  const items = [
@@ -7290,7 +7583,7 @@ function MainMenu() {
7290
7583
  { label: "Update docs", value: "update-docs" },
7291
7584
  { label: "Exit", value: "exit" }
7292
7585
  ];
7293
- return /* @__PURE__ */ jsx28(Box26, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx28(
7586
+ return /* @__PURE__ */ jsx29(Box27, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx29(
7294
7587
  SelectMenu,
7295
7588
  {
7296
7589
  items,
@@ -7345,16 +7638,16 @@ function MainMenu() {
7345
7638
  // src/tui/screens/ManageSkills.tsx
7346
7639
  import { rm as rm5 } from "fs/promises";
7347
7640
  import chalk4 from "chalk";
7348
- import { Box as Box27, Text as Text24 } from "ink";
7349
- import React23 from "react";
7350
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
7641
+ import { Box as Box28, Text as Text25 } from "ink";
7642
+ import React24 from "react";
7643
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
7351
7644
  function ManageScreen() {
7352
7645
  const { navigateTo, setFlash, setBackHandler } = useNavigation();
7353
- const [summaries, setSummaries] = React23.useState([]);
7354
- const [selectedAgent, setSelectedAgent] = React23.useState(null);
7355
- const [selectedSkills, setSelectedSkills] = React23.useState(null);
7356
- const [isRemoving, setIsRemoving] = React23.useState(false);
7357
- React23.useEffect(() => {
7646
+ const [summaries, setSummaries] = React24.useState([]);
7647
+ const [selectedAgent, setSelectedAgent] = React24.useState(null);
7648
+ const [selectedSkills, setSelectedSkills] = React24.useState(null);
7649
+ const [isRemoving, setIsRemoving] = React24.useState(false);
7650
+ React24.useEffect(() => {
7358
7651
  let cancelled = false;
7359
7652
  const load = async () => {
7360
7653
  const installedAgents = await detectInstalledAgents();
@@ -7376,7 +7669,7 @@ function ManageScreen() {
7376
7669
  cancelled = true;
7377
7670
  };
7378
7671
  }, [setFlash]);
7379
- React23.useEffect(() => {
7672
+ React24.useEffect(() => {
7380
7673
  if (isRemoving) {
7381
7674
  setBackHandler(() => true);
7382
7675
  return () => setBackHandler(null);
@@ -7399,16 +7692,16 @@ function ManageScreen() {
7399
7692
  return () => setBackHandler(null);
7400
7693
  }, [isRemoving, selectedSkills, selectedAgent, setBackHandler]);
7401
7694
  if (summaries.length === 0) {
7402
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7403
- /* @__PURE__ */ jsx29(Header, { title: "Remove skills" }),
7404
- /* @__PURE__ */ jsx29(Text24, { dimColor: true, children: "No skills found yet." }),
7405
- /* @__PURE__ */ jsx29(Text24, { dimColor: true, children: BACK_QUIT_HINT })
7695
+ return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7696
+ /* @__PURE__ */ jsx30(Header, { title: "Remove skills" }),
7697
+ /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: "No skills found yet." }),
7698
+ /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
7406
7699
  ] });
7407
7700
  }
7408
7701
  if (!selectedAgent) {
7409
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7410
- /* @__PURE__ */ jsx29(Header, { title: "Select agent" }),
7411
- /* @__PURE__ */ jsx29(
7702
+ return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7703
+ /* @__PURE__ */ jsx30(Header, { title: "Select agent" }),
7704
+ /* @__PURE__ */ jsx30(
7412
7705
  SelectMenu,
7413
7706
  {
7414
7707
  items: summaries.map((summary) => ({
@@ -7425,9 +7718,9 @@ function ManageScreen() {
7425
7718
  ] });
7426
7719
  }
7427
7720
  if (!selectedSkills) {
7428
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7429
- /* @__PURE__ */ jsx29(Header, { title: `Remove skills (${agents[selectedAgent.agent].displayName})` }),
7430
- /* @__PURE__ */ jsx29(
7721
+ return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7722
+ /* @__PURE__ */ jsx30(Header, { title: `Remove skills (${agents[selectedAgent.agent].displayName})` }),
7723
+ /* @__PURE__ */ jsx30(
7431
7724
  MultiSelect,
7432
7725
  {
7433
7726
  items: selectedAgent.skills.map((skill) => ({
@@ -7447,19 +7740,19 @@ function ManageScreen() {
7447
7740
  ] });
7448
7741
  }
7449
7742
  if (isRemoving) {
7450
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7451
- /* @__PURE__ */ jsx29(Header, { title: "Removing skills" }),
7452
- /* @__PURE__ */ jsx29(Text24, { children: "Removing selected skills..." })
7743
+ return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7744
+ /* @__PURE__ */ jsx30(Header, { title: "Removing skills" }),
7745
+ /* @__PURE__ */ jsx30(Text25, { children: "Removing selected skills..." })
7453
7746
  ] });
7454
7747
  }
7455
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7456
- /* @__PURE__ */ jsx29(Header, { title: "Confirm removal" }),
7457
- selectedSkills.map((skill) => /* @__PURE__ */ jsxs24(Text24, { children: [
7748
+ return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7749
+ /* @__PURE__ */ jsx30(Header, { title: "Confirm removal" }),
7750
+ selectedSkills.map((skill) => /* @__PURE__ */ jsxs25(Text25, { children: [
7458
7751
  formatSkillLabel(skill),
7459
7752
  " ",
7460
7753
  chalk4.dim(`(${skill.scope})`)
7461
7754
  ] }, `${skill.slug}-${skill.scope}`)),
7462
- /* @__PURE__ */ jsx29(
7755
+ /* @__PURE__ */ jsx30(
7463
7756
  SelectMenu,
7464
7757
  {
7465
7758
  items: [
@@ -7522,14 +7815,14 @@ function formatSkillLabel(skill) {
7522
7815
  }
7523
7816
 
7524
7817
  // src/tui/screens/MarketplacePlugins.tsx
7525
- import { Box as Box28, Text as Text25 } from "ink";
7526
- import React24 from "react";
7527
- import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
7818
+ import { Box as Box29, Text as Text26 } from "ink";
7819
+ import React25 from "react";
7820
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
7528
7821
  function MarketplacePluginScreen() {
7529
7822
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
7530
7823
  const plugins = addSkill.marketplace?.plugins ?? [];
7531
7824
  const options = invocation.options;
7532
- React24.useEffect(() => {
7825
+ React25.useEffect(() => {
7533
7826
  if (plugins.length === 0) {
7534
7827
  return;
7535
7828
  }
@@ -7544,25 +7837,25 @@ function MarketplacePluginScreen() {
7544
7837
  }
7545
7838
  }, [plugins, options.yes, updateAddSkill, navigateTo, addSkill.marketplace]);
7546
7839
  if (plugins.length === 0) {
7547
- return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7548
- /* @__PURE__ */ jsx30(AddFlowHeader, { title: "Marketplace plugins" }),
7549
- /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: "No plugins found." }),
7550
- /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
7840
+ return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7841
+ /* @__PURE__ */ jsx31(AddFlowHeader, { title: "Marketplace plugins" }),
7842
+ /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: "No plugins found." }),
7843
+ /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT })
7551
7844
  ] });
7552
7845
  }
7553
7846
  if (options.list) {
7554
- return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7555
- /* @__PURE__ */ jsx30(AddFlowHeader, { title: `Marketplace plugins (${plugins.length})` }),
7556
- plugins.map((plugin) => /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", marginBottom: 1, children: [
7557
- /* @__PURE__ */ jsx30(Text25, { children: plugin.name }),
7558
- plugin.description ? /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: plugin.description }) : null
7847
+ return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7848
+ /* @__PURE__ */ jsx31(AddFlowHeader, { title: `Marketplace plugins (${plugins.length})` }),
7849
+ plugins.map((plugin) => /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", marginBottom: 1, children: [
7850
+ /* @__PURE__ */ jsx31(Text26, { children: plugin.name }),
7851
+ plugin.description ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: plugin.description }) : null
7559
7852
  ] }, plugin.name)),
7560
- /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
7853
+ /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT })
7561
7854
  ] });
7562
7855
  }
7563
- return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7564
- /* @__PURE__ */ jsx30(AddFlowHeader, { title: "Select plugins" }),
7565
- /* @__PURE__ */ jsx30(
7856
+ return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7857
+ /* @__PURE__ */ jsx31(AddFlowHeader, { title: "Select plugins" }),
7858
+ /* @__PURE__ */ jsx31(
7566
7859
  MultiSelect,
7567
7860
  {
7568
7861
  items: plugins.map((plugin) => ({
@@ -7589,8 +7882,8 @@ function MarketplacePluginScreen() {
7589
7882
  }
7590
7883
 
7591
7884
  // src/tui/screens/MarketplaceSkills.tsx
7592
- import { Box as Box29, Text as Text26 } from "ink";
7593
- import React25 from "react";
7885
+ import { Box as Box30, Text as Text27 } from "ink";
7886
+ import React26 from "react";
7594
7887
 
7595
7888
  // src/flows/marketplace.ts
7596
7889
  import { dirname as dirname7, join as join17, relative as relative4 } from "path";
@@ -7750,16 +8043,16 @@ function buildOriginMap(skills) {
7750
8043
  }
7751
8044
 
7752
8045
  // src/tui/screens/MarketplaceSkills.tsx
7753
- import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
8046
+ import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7754
8047
  function MarketplaceSkillScreen() {
7755
8048
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
7756
8049
  const options = invocation.options;
7757
- const [status, setStatus] = React25.useState("loading");
7758
- const [error, setError] = React25.useState(null);
8050
+ const [status, setStatus] = React26.useState("loading");
8051
+ const [error, setError] = React26.useState(null);
7759
8052
  const spinner = useSpinnerFrame(status === "loading");
7760
8053
  const selectedPlugins = addSkill.marketplace?.selectedPlugins ?? [];
7761
8054
  const context = addSkill.marketplace?.context;
7762
- React25.useEffect(() => {
8055
+ React26.useEffect(() => {
7763
8056
  let cancelled = false;
7764
8057
  const load = async () => {
7765
8058
  if (!context || selectedPlugins.length === 0) {
@@ -7823,27 +8116,27 @@ function MarketplaceSkillScreen() {
7823
8116
  options.yes
7824
8117
  ]);
7825
8118
  if (status === "loading") {
7826
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7827
- /* @__PURE__ */ jsx31(AddFlowHeader, { title: "Scanning marketplace" }),
7828
- /* @__PURE__ */ jsxs26(Text26, { children: [
8119
+ return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8120
+ /* @__PURE__ */ jsx32(AddFlowHeader, { title: "Scanning marketplace" }),
8121
+ /* @__PURE__ */ jsxs27(Text27, { children: [
7829
8122
  spinner,
7830
8123
  " Discovering skills from plugins..."
7831
8124
  ] })
7832
8125
  ] });
7833
8126
  }
7834
8127
  if (status === "error") {
7835
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7836
- /* @__PURE__ */ jsx31(AddFlowHeader, { title: "Marketplace scan failed" }),
7837
- /* @__PURE__ */ jsx31(Text26, { color: "red", children: error }),
7838
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT })
8128
+ return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8129
+ /* @__PURE__ */ jsx32(AddFlowHeader, { title: "Marketplace scan failed" }),
8130
+ /* @__PURE__ */ jsx32(Text27, { color: "red", children: error }),
8131
+ /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT })
7839
8132
  ] });
7840
8133
  }
7841
8134
  const skills = addSkill.marketplace?.skills ?? [];
7842
8135
  const warnings = addSkill.marketplace?.warnings ?? [];
7843
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7844
- /* @__PURE__ */ jsx31(AddFlowHeader, { title: "Select skills" }),
7845
- warnings.length > 0 ? /* @__PURE__ */ jsx31(Box29, { flexDirection: "column", marginBottom: 1, children: warnings.map((warning) => /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: warning }, warning)) }) : null,
7846
- /* @__PURE__ */ jsx31(
8136
+ return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8137
+ /* @__PURE__ */ jsx32(AddFlowHeader, { title: "Select skills" }),
8138
+ warnings.length > 0 ? /* @__PURE__ */ jsx32(Box30, { flexDirection: "column", marginBottom: 1, children: warnings.map((warning) => /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: warning }, warning)) }) : null,
8139
+ /* @__PURE__ */ jsx32(
7847
8140
  MultiSelect,
7848
8141
  {
7849
8142
  items: skills.map((entry) => ({
@@ -7893,8 +8186,8 @@ function autoSelect2(skills, names, yes) {
7893
8186
  // src/tui/screens/ScanSkills.tsx
7894
8187
  import { rm as rm6 } from "fs/promises";
7895
8188
  import chalk5 from "chalk";
7896
- import { Box as Box30, Text as Text27 } from "ink";
7897
- import React26 from "react";
8189
+ import { Box as Box31, Text as Text28 } from "ink";
8190
+ import React27 from "react";
7898
8191
 
7899
8192
  // src/flows/scan-installed-skills.ts
7900
8193
  import { existsSync as existsSync7 } from "fs";
@@ -8117,17 +8410,17 @@ function removalTargetsForRow(row, cwd) {
8117
8410
  }
8118
8411
 
8119
8412
  // src/tui/screens/ScanSkills.tsx
8120
- import { Fragment as Fragment3, jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
8413
+ import { Fragment as Fragment3, jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
8121
8414
  function ScanSkillsScreen() {
8122
8415
  const { setFlash, setBackHandler } = useNavigation();
8123
- const [view, setView] = React26.useState("loading");
8124
- const [error, setError] = React26.useState(null);
8125
- const [rows, setRows] = React26.useState([]);
8126
- const [progress, setProgress] = React26.useState(null);
8127
- const [selected, setSelected] = React26.useState(null);
8128
- const [removeTargets, setRemoveTargets] = React26.useState(null);
8416
+ const [view, setView] = React27.useState("loading");
8417
+ const [error, setError] = React27.useState(null);
8418
+ const [rows, setRows] = React27.useState([]);
8419
+ const [progress, setProgress] = React27.useState(null);
8420
+ const [selected, setSelected] = React27.useState(null);
8421
+ const [removeTargets, setRemoveTargets] = React27.useState(null);
8129
8422
  const spinner = useSpinnerFrame(view === "running" || view === "removing");
8130
- React26.useEffect(() => {
8423
+ React27.useEffect(() => {
8131
8424
  let cancelled = false;
8132
8425
  const run = async () => {
8133
8426
  try {
@@ -8197,7 +8490,7 @@ function ScanSkillsScreen() {
8197
8490
  cancelled = true;
8198
8491
  };
8199
8492
  }, []);
8200
- React26.useEffect(() => {
8493
+ React27.useEffect(() => {
8201
8494
  if (view === "actions" || view === "confirm-remove" || view === "removing") {
8202
8495
  setBackHandler(() => {
8203
8496
  if (view === "confirm-remove") {
@@ -8217,26 +8510,26 @@ function ScanSkillsScreen() {
8217
8510
  setBackHandler(null);
8218
8511
  return () => setBackHandler(null);
8219
8512
  }, [view, setBackHandler]);
8220
- const riskyRows = React26.useMemo(() => rows.filter(isRisky), [rows]);
8221
- const summary = React26.useMemo(() => scanSummary(rows), [rows]);
8513
+ const riskyRows = React27.useMemo(() => rows.filter(isRisky), [rows]);
8514
+ const summary = React27.useMemo(() => scanSummary(rows), [rows]);
8222
8515
  if (view === "empty") {
8223
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8224
- /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8225
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
8516
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8517
+ /* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
8518
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
8226
8519
  ] });
8227
8520
  }
8228
8521
  if (view === "loading") {
8229
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8230
- /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8231
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "Discovering skills..." })
8522
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8523
+ /* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
8524
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Discovering skills..." })
8232
8525
  ] });
8233
8526
  }
8234
8527
  if (view === "running") {
8235
8528
  const completed = progress?.completed ?? 0;
8236
8529
  const total = progress?.total ?? 0;
8237
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8238
- /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8239
- /* @__PURE__ */ jsxs27(Text27, { children: [
8530
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8531
+ /* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
8532
+ /* @__PURE__ */ jsxs28(Text28, { children: [
8240
8533
  spinner,
8241
8534
  " Scanning ",
8242
8535
  completed,
@@ -8246,14 +8539,14 @@ function ScanSkillsScreen() {
8246
8539
  total === 1 ? "" : "s",
8247
8540
  "..."
8248
8541
  ] }),
8249
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
8542
+ /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
8250
8543
  ] });
8251
8544
  }
8252
8545
  if (view === "error") {
8253
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8254
- /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8255
- /* @__PURE__ */ jsx32(Text27, { color: "red", children: error ?? "Scan failed" }),
8256
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
8546
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8547
+ /* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
8548
+ /* @__PURE__ */ jsx33(Text28, { color: "red", children: error ?? "Scan failed" }),
8549
+ /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
8257
8550
  ] });
8258
8551
  }
8259
8552
  if (view === "actions" && selected) {
@@ -8264,27 +8557,27 @@ function ScanSkillsScreen() {
8264
8557
  const top = selected.topSignals?.slice(0, 10) ?? [];
8265
8558
  const locationLabels = selected.skill.locations.map((l) => l.label);
8266
8559
  const riskColor = level === "critical" || level === "high" ? "red" : level === "medium" ? "yellow" : level === "low" ? "green" : "gray";
8267
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8268
- /* @__PURE__ */ jsx32(Header, { title: "Skill risk details" }),
8269
- /* @__PURE__ */ jsxs27(Text27, { children: [
8270
- /* @__PURE__ */ jsx32(Text27, { bold: true, children: selected.skill.name }),
8560
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8561
+ /* @__PURE__ */ jsx33(Header, { title: "Skill risk details" }),
8562
+ /* @__PURE__ */ jsxs28(Text28, { children: [
8563
+ /* @__PURE__ */ jsx33(Text28, { bold: true, children: selected.skill.name }),
8271
8564
  " ",
8272
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `(${selected.skill.slug})` })
8565
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `(${selected.skill.slug})` })
8273
8566
  ] }),
8274
- selected.error ? /* @__PURE__ */ jsx32(Text27, { color: "red", children: selected.error }) : /* @__PURE__ */ jsxs27(Fragment3, { children: [
8275
- /* @__PURE__ */ jsxs27(Text27, { children: [
8276
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "Verdict:" }),
8567
+ selected.error ? /* @__PURE__ */ jsx33(Text28, { color: "red", children: selected.error }) : /* @__PURE__ */ jsxs28(Fragment3, { children: [
8568
+ /* @__PURE__ */ jsxs28(Text28, { children: [
8569
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Verdict:" }),
8277
8570
  " ",
8278
- /* @__PURE__ */ jsx32(Text27, { color: riskColor, children: verdict }),
8279
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: ` \u2022 level=${level} score=${score} issues=${issues}` })
8571
+ /* @__PURE__ */ jsx33(Text28, { color: riskColor, children: verdict }),
8572
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: ` \u2022 level=${level} score=${score} issues=${issues}` })
8280
8573
  ] }),
8281
- top.length > 0 ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Top signals: ${top.join(", ")}` }) : null,
8282
- selected.ruleset ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Ruleset: ${selected.ruleset}` }) : null
8574
+ top.length > 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Top signals: ${top.join(", ")}` }) : null,
8575
+ selected.ruleset ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Ruleset: ${selected.ruleset}` }) : null
8283
8576
  ] }),
8284
- selected.skill.description ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: selected.skill.description }) : null,
8285
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Path: ${selected.skill.path}` }),
8286
- locationLabels.length > 0 ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Locations: ${locationLabels.join(", ")}` }) : null,
8287
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
8577
+ selected.skill.description ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: selected.skill.description }) : null,
8578
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Path: ${selected.skill.path}` }),
8579
+ locationLabels.length > 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Locations: ${locationLabels.join(", ")}` }) : null,
8580
+ /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(
8288
8581
  SelectMenu,
8289
8582
  {
8290
8583
  items: [
@@ -8310,17 +8603,17 @@ function ScanSkillsScreen() {
8310
8603
  }
8311
8604
  if (view === "confirm-remove" && selected && removeTargets) {
8312
8605
  const title = `Remove ${selected.skill.name}`;
8313
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8314
- /* @__PURE__ */ jsx32(Header, { title }),
8315
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "These locations will be removed:" }),
8316
- /* @__PURE__ */ jsx32(Box30, { flexDirection: "column", marginTop: 1, children: removeTargets.length === 0 ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "None found." }) : removeTargets.map((t) => /* @__PURE__ */ jsxs27(Text27, { children: [
8317
- /* @__PURE__ */ jsx32(Text27, { children: chalk5.red("\u2022") }),
8606
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8607
+ /* @__PURE__ */ jsx33(Header, { title }),
8608
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "These locations will be removed:" }),
8609
+ /* @__PURE__ */ jsx33(Box31, { flexDirection: "column", marginTop: 1, children: removeTargets.length === 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "None found." }) : removeTargets.map((t) => /* @__PURE__ */ jsxs28(Text28, { children: [
8610
+ /* @__PURE__ */ jsx33(Text28, { children: chalk5.red("\u2022") }),
8318
8611
  " ",
8319
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: t.label }),
8612
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: t.label }),
8320
8613
  " ",
8321
8614
  t.path
8322
8615
  ] }, t.path)) }),
8323
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
8616
+ /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(
8324
8617
  SelectMenu,
8325
8618
  {
8326
8619
  items: [
@@ -8368,33 +8661,33 @@ function ScanSkillsScreen() {
8368
8661
  ] });
8369
8662
  }
8370
8663
  if (view === "removing") {
8371
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8372
- /* @__PURE__ */ jsx32(Header, { title: "Removing skill" }),
8373
- /* @__PURE__ */ jsxs27(Text27, { children: [
8664
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8665
+ /* @__PURE__ */ jsx33(Header, { title: "Removing skill" }),
8666
+ /* @__PURE__ */ jsxs28(Text28, { children: [
8374
8667
  spinner,
8375
8668
  " Removing..."
8376
8669
  ] }),
8377
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
8670
+ /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
8378
8671
  ] });
8379
8672
  }
8380
8673
  if (riskyRows.length === 0) {
8381
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8382
- /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8383
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
8674
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8675
+ /* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
8676
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
8384
8677
  ] });
8385
8678
  }
8386
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8387
- /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8388
- /* @__PURE__ */ jsxs27(Box30, { marginBottom: 1, flexDirection: "column", children: [
8389
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Scanned ${plural(summary.total, "skill")}.` }),
8390
- /* @__PURE__ */ jsxs27(Text27, { children: [
8391
- /* @__PURE__ */ jsx32(Text27, { color: "red", children: plural(summary.high, "high risk") }),
8392
- /* @__PURE__ */ jsx32(Text27, { children: ", " }),
8393
- /* @__PURE__ */ jsx32(Text27, { color: "yellow", children: plural(summary.medium, "medium risk") }),
8394
- /* @__PURE__ */ jsx32(Text27, { children: " detected." })
8679
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8680
+ /* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
8681
+ /* @__PURE__ */ jsxs28(Box31, { marginBottom: 1, flexDirection: "column", children: [
8682
+ /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Scanned ${plural(summary.total, "skill")}.` }),
8683
+ /* @__PURE__ */ jsxs28(Text28, { children: [
8684
+ /* @__PURE__ */ jsx33(Text28, { color: "red", children: plural(summary.high, "high risk") }),
8685
+ /* @__PURE__ */ jsx33(Text28, { children: ", " }),
8686
+ /* @__PURE__ */ jsx33(Text28, { color: "yellow", children: plural(summary.medium, "medium risk") }),
8687
+ /* @__PURE__ */ jsx33(Text28, { children: " detected." })
8395
8688
  ] })
8396
8689
  ] }),
8397
- /* @__PURE__ */ jsx32(
8690
+ /* @__PURE__ */ jsx33(
8398
8691
  SingleSelect,
8399
8692
  {
8400
8693
  items: riskyRows.map((row) => ({
@@ -8415,8 +8708,8 @@ function ScanSkillsScreen() {
8415
8708
  }
8416
8709
 
8417
8710
  // src/tui/screens/UpdateDocs.tsx
8418
- import { Box as Box31, Text as Text28 } from "ink";
8419
- import React27 from "react";
8711
+ import { Box as Box32, Text as Text29 } from "ink";
8712
+ import React28 from "react";
8420
8713
 
8421
8714
  // src/docs/update.ts
8422
8715
  import { readdir as readdir6, stat as stat6 } from "fs/promises";
@@ -8482,12 +8775,12 @@ async function updateDocs(cwd = process.cwd()) {
8482
8775
  }
8483
8776
 
8484
8777
  // src/tui/screens/UpdateDocs.tsx
8485
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
8778
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
8486
8779
  function UpdateDocsScreen() {
8487
- const [status, setStatus] = React27.useState("running");
8488
- const [summary, setSummary] = React27.useState(null);
8780
+ const [status, setStatus] = React28.useState("running");
8781
+ const [summary, setSummary] = React28.useState(null);
8489
8782
  const spinner = useSpinnerFrame(status === "running");
8490
- React27.useEffect(() => {
8783
+ React28.useEffect(() => {
8491
8784
  let cancelled = false;
8492
8785
  const run = async () => {
8493
8786
  const output2 = await updateDocs();
@@ -8505,60 +8798,60 @@ function UpdateDocsScreen() {
8505
8798
  };
8506
8799
  }, []);
8507
8800
  if (status === "running") {
8508
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8509
- /* @__PURE__ */ jsx33(Header, { title: "Updating docs" }),
8510
- /* @__PURE__ */ jsxs28(Text28, { children: [
8801
+ return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
8802
+ /* @__PURE__ */ jsx34(Header, { title: "Updating docs" }),
8803
+ /* @__PURE__ */ jsxs29(Text29, { children: [
8511
8804
  spinner,
8512
8805
  " Pulling latest docs..."
8513
8806
  ] })
8514
8807
  ] });
8515
8808
  }
8516
8809
  if (status === "empty") {
8517
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8518
- /* @__PURE__ */ jsx33(Header, { title: "Update docs" }),
8519
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "No docs installed yet." }),
8520
- /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
8810
+ return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
8811
+ /* @__PURE__ */ jsx34(Header, { title: "Update docs" }),
8812
+ /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "No docs installed yet." }),
8813
+ /* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: BACK_QUIT_HINT }) })
8521
8814
  ] });
8522
8815
  }
8523
8816
  if (!summary) {
8524
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8525
- /* @__PURE__ */ jsx33(Header, { title: "Update docs" }),
8526
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Nothing to update." })
8817
+ return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
8818
+ /* @__PURE__ */ jsx34(Header, { title: "Update docs" }),
8819
+ /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Nothing to update." })
8527
8820
  ] });
8528
8821
  }
8529
8822
  const cwd = process.cwd();
8530
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8531
- /* @__PURE__ */ jsx33(Header, { title: "Docs update results" }),
8532
- summary.updated.length > 0 ? /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", marginBottom: 1, children: [
8533
- /* @__PURE__ */ jsx33(Text28, { children: `Updated ${summary.updated.length} repo${summary.updated.length !== 1 ? "s" : ""}` }),
8534
- summary.updated.map((item) => /* @__PURE__ */ jsxs28(Text28, { dimColor: true, children: [
8823
+ return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
8824
+ /* @__PURE__ */ jsx34(Header, { title: "Docs update results" }),
8825
+ summary.updated.length > 0 ? /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", marginBottom: 1, children: [
8826
+ /* @__PURE__ */ jsx34(Text29, { children: `Updated ${summary.updated.length} repo${summary.updated.length !== 1 ? "s" : ""}` }),
8827
+ summary.updated.map((item) => /* @__PURE__ */ jsxs29(Text29, { dimColor: true, children: [
8535
8828
  item.name,
8536
8829
  " \u2192 ",
8537
8830
  shortenPath(item.path, cwd)
8538
8831
  ] }, `updated-${item.name}`))
8539
8832
  ] }) : null,
8540
- summary.skipped.length > 0 ? /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", marginBottom: 1, children: [
8541
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Skipped" }),
8542
- summary.skipped.map((item) => /* @__PURE__ */ jsxs28(Text28, { dimColor: true, children: [
8833
+ summary.skipped.length > 0 ? /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", marginBottom: 1, children: [
8834
+ /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Skipped" }),
8835
+ summary.skipped.map((item) => /* @__PURE__ */ jsxs29(Text29, { dimColor: true, children: [
8543
8836
  item.name,
8544
8837
  item.message ? ` (${item.message})` : ""
8545
8838
  ] }, `skipped-${item.name}`))
8546
8839
  ] }) : null,
8547
- summary.failed.length > 0 ? /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", marginBottom: 1, children: [
8548
- /* @__PURE__ */ jsx33(Text28, { color: "red", children: "Failed" }),
8549
- summary.failed.map((item) => /* @__PURE__ */ jsxs28(Text28, { color: "red", children: [
8840
+ summary.failed.length > 0 ? /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", marginBottom: 1, children: [
8841
+ /* @__PURE__ */ jsx34(Text29, { color: "red", children: "Failed" }),
8842
+ summary.failed.map((item) => /* @__PURE__ */ jsxs29(Text29, { color: "red", children: [
8550
8843
  item.name,
8551
8844
  item.message ? ` (${item.message})` : ""
8552
8845
  ] }, `failed-${item.name}`))
8553
8846
  ] }) : null,
8554
- /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
8847
+ /* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: BACK_QUIT_HINT }) })
8555
8848
  ] });
8556
8849
  }
8557
8850
 
8558
8851
  // src/tui/screens/UpdateSkills.tsx
8559
8852
  import chalk6 from "chalk";
8560
- import { Box as Box32, Text as Text29, useInput as useInput6 } from "ink";
8561
- import React28 from "react";
8853
+ import { Box as Box33, Text as Text30, useInput as useInput6 } from "ink";
8854
+ import React29 from "react";
8562
8855
 
8563
8856
  // src/flows/update-skills.ts
8564
8857
  import { randomUUID } from "crypto";
@@ -8949,15 +9242,15 @@ async function updateSkills(targets) {
8949
9242
  }
8950
9243
 
8951
9244
  // src/tui/screens/UpdateSkills.tsx
8952
- import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
9245
+ import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
8953
9246
  function UpdateScreen() {
8954
9247
  const { invocation, navigateTo, setFlash } = useNavigation();
8955
- const [status, setStatus] = React28.useState("loading");
8956
- const [targets, setTargets] = React28.useState([]);
8957
- const [selected, setSelected] = React28.useState([]);
8958
- const [summary, setSummary] = React28.useState(null);
8959
- const [showOnlyNeeds, setShowOnlyNeeds] = React28.useState(false);
8960
- const [rateLimited, setRateLimited] = React28.useState(false);
9248
+ const [status, setStatus] = React29.useState("loading");
9249
+ const [targets, setTargets] = React29.useState([]);
9250
+ const [selected, setSelected] = React29.useState([]);
9251
+ const [summary, setSummary] = React29.useState(null);
9252
+ const [showOnlyNeeds, setShowOnlyNeeds] = React29.useState(false);
9253
+ const [rateLimited, setRateLimited] = React29.useState(false);
8961
9254
  const spinner = useSpinnerFrame(status === "running");
8962
9255
  useInput6((input) => {
8963
9256
  if (status !== "select") return;
@@ -8965,7 +9258,7 @@ function UpdateScreen() {
8965
9258
  setShowOnlyNeeds((prev) => !prev);
8966
9259
  }
8967
9260
  });
8968
- React28.useEffect(() => {
9261
+ React29.useEffect(() => {
8969
9262
  let cancelled = false;
8970
9263
  const load = async () => {
8971
9264
  const scopes = resolveScopes(invocation.options);
@@ -9007,7 +9300,7 @@ function UpdateScreen() {
9007
9300
  cancelled = true;
9008
9301
  };
9009
9302
  }, [invocation, setFlash]);
9010
- React28.useEffect(() => {
9303
+ React29.useEffect(() => {
9011
9304
  let cancelled = false;
9012
9305
  const run = async () => {
9013
9306
  if (status !== "running" || selected.length === 0) return;
@@ -9022,16 +9315,16 @@ function UpdateScreen() {
9022
9315
  };
9023
9316
  }, [status, selected]);
9024
9317
  if (status === "empty") {
9025
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9026
- /* @__PURE__ */ jsx34(Header, { title: "Update skills" }),
9027
- /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "No tracked skills to update yet." }),
9028
- /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Re-install a skill once to enable updates." })
9318
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9319
+ /* @__PURE__ */ jsx35(Header, { title: "Update skills" }),
9320
+ /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "No tracked skills to update yet." }),
9321
+ /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "Re-install a skill once to enable updates." })
9029
9322
  ] });
9030
9323
  }
9031
9324
  if (status === "loading") {
9032
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9033
- /* @__PURE__ */ jsx34(Header, { title: "Update skills" }),
9034
- /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Loading tracked skills..." })
9325
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9326
+ /* @__PURE__ */ jsx35(Header, { title: "Update skills" }),
9327
+ /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "Loading tracked skills..." })
9035
9328
  ] });
9036
9329
  }
9037
9330
  if (status === "select") {
@@ -9039,17 +9332,17 @@ function UpdateScreen() {
9039
9332
  const defaults = selected;
9040
9333
  const hint = showOnlyNeeds ? UPDATE_HINT_NEEDS_ONLY : UPDATE_HINT_ALL;
9041
9334
  if (showOnlyNeeds && visibleTargets.length === 0) {
9042
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9043
- /* @__PURE__ */ jsx34(Header, { title: "Select skills to update" }),
9044
- /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "No updates found." }),
9045
- rateLimited ? /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "GitHub rate limit hit. Some skills may be marked unknown." }) : null,
9046
- /* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: UPDATE_EMPTY_HINT }) })
9335
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9336
+ /* @__PURE__ */ jsx35(Header, { title: "Select skills to update" }),
9337
+ /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "No updates found." }),
9338
+ rateLimited ? /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "GitHub rate limit hit. Some skills may be marked unknown." }) : null,
9339
+ /* @__PURE__ */ jsx35(Box33, { marginTop: 1, children: /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: UPDATE_EMPTY_HINT }) })
9047
9340
  ] });
9048
9341
  }
9049
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9050
- /* @__PURE__ */ jsx34(Header, { title: "Select skills to update" }),
9051
- rateLimited ? /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "GitHub rate limit hit. Some skills marked unknown." }) : null,
9052
- /* @__PURE__ */ jsx34(
9342
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9343
+ /* @__PURE__ */ jsx35(Header, { title: "Select skills to update" }),
9344
+ rateLimited ? /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "GitHub rate limit hit. Some skills marked unknown." }) : null,
9345
+ /* @__PURE__ */ jsx35(
9053
9346
  MultiSelect,
9054
9347
  {
9055
9348
  items: visibleTargets.map((target) => ({
@@ -9072,9 +9365,9 @@ function UpdateScreen() {
9072
9365
  ] });
9073
9366
  }
9074
9367
  if (status === "running") {
9075
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9076
- /* @__PURE__ */ jsx34(Header, { title: "Updating skills" }),
9077
- /* @__PURE__ */ jsxs29(Text29, { children: [
9368
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9369
+ /* @__PURE__ */ jsx35(Header, { title: "Updating skills" }),
9370
+ /* @__PURE__ */ jsxs30(Text30, { children: [
9078
9371
  spinner,
9079
9372
  " Updating ",
9080
9373
  selected.length,
@@ -9085,17 +9378,17 @@ function UpdateScreen() {
9085
9378
  ] });
9086
9379
  }
9087
9380
  if (!summary) {
9088
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9089
- /* @__PURE__ */ jsx34(Header, { title: "Update skills" }),
9090
- /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Nothing to update." })
9381
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9382
+ /* @__PURE__ */ jsx35(Header, { title: "Update skills" }),
9383
+ /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "Nothing to update." })
9091
9384
  ] });
9092
9385
  }
9093
- return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9094
- /* @__PURE__ */ jsx34(Header, { title: "Update results" }),
9095
- summary.updated.length > 0 ? /* @__PURE__ */ jsx34(Text29, { children: `Updated ${summary.updated.length} skill${summary.updated.length !== 1 ? "s" : ""}` }) : null,
9096
- summary.skipped.length > 0 ? /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: `Skipped: ${summary.skipped.map(formatTargetLabel).join(", ")}` }) : null,
9097
- summary.failed.length > 0 ? /* @__PURE__ */ jsx34(Text29, { color: "red", children: `Failed: ${summary.failed.map(formatTargetLabel).join(", ")}` }) : null,
9098
- /* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: BACK_QUIT_HINT }) })
9386
+ return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
9387
+ /* @__PURE__ */ jsx35(Header, { title: "Update results" }),
9388
+ summary.updated.length > 0 ? /* @__PURE__ */ jsx35(Text30, { children: `Updated ${summary.updated.length} skill${summary.updated.length !== 1 ? "s" : ""}` }) : null,
9389
+ summary.skipped.length > 0 ? /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: `Skipped: ${summary.skipped.map(formatTargetLabel).join(", ")}` }) : null,
9390
+ summary.failed.length > 0 ? /* @__PURE__ */ jsx35(Text30, { color: "red", children: `Failed: ${summary.failed.map(formatTargetLabel).join(", ")}` }) : null,
9391
+ /* @__PURE__ */ jsx35(Box33, { marginTop: 1, children: /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: BACK_QUIT_HINT }) })
9099
9392
  ] });
9100
9393
  }
9101
9394
  function resolveScopes(options) {
@@ -9124,63 +9417,65 @@ function sortTargets(a, b) {
9124
9417
  }
9125
9418
 
9126
9419
  // src/tui/ScreenRouter.tsx
9127
- import { Fragment as Fragment4, jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
9420
+ import { Fragment as Fragment4, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
9128
9421
  function ScreenRouter() {
9129
9422
  const { screen } = useNavigation();
9130
9423
  const render2 = (s) => {
9131
9424
  switch (s) {
9132
9425
  case "main":
9133
- return /* @__PURE__ */ jsx35(MainMenu, {});
9426
+ return /* @__PURE__ */ jsx36(MainMenu, {});
9134
9427
  case "add-source":
9135
- return /* @__PURE__ */ jsx35(AddSourceScreen, {});
9428
+ return /* @__PURE__ */ jsx36(AddSourceScreen, {});
9136
9429
  case "add-docs":
9137
- return /* @__PURE__ */ jsx35(AddDocsScreen, {});
9430
+ return /* @__PURE__ */ jsx36(AddDocsScreen, {});
9138
9431
  case "add-marketplace-plugins":
9139
- return /* @__PURE__ */ jsx35(MarketplacePluginScreen, {});
9432
+ return /* @__PURE__ */ jsx36(MarketplacePluginScreen, {});
9140
9433
  case "add-marketplace-skills":
9141
- return /* @__PURE__ */ jsx35(MarketplaceSkillScreen, {});
9434
+ return /* @__PURE__ */ jsx36(MarketplaceSkillScreen, {});
9142
9435
  case "find-skill-search":
9143
- return /* @__PURE__ */ jsx35(FindSkillSearchScreen, {});
9436
+ return /* @__PURE__ */ jsx36(FindSkillSearchScreen, {});
9144
9437
  case "find-skill-results":
9145
- return /* @__PURE__ */ jsx35(FindSkillResultsScreen, {});
9438
+ return /* @__PURE__ */ jsx36(FindSkillResultsScreen, {});
9146
9439
  case "scan-skills":
9147
- return /* @__PURE__ */ jsx35(ScanSkillsScreen, {});
9440
+ return /* @__PURE__ */ jsx36(ScanSkillsScreen, {});
9148
9441
  case "get-url":
9149
- return /* @__PURE__ */ jsx35(GetUrlScreen, {});
9442
+ return /* @__PURE__ */ jsx36(GetUrlScreen, {});
9150
9443
  case "add-skill-select":
9151
- return /* @__PURE__ */ jsx35(AddSkillSelectScreen, {});
9444
+ return /* @__PURE__ */ jsx36(AddSkillSelectScreen, {});
9445
+ case "add-bundle-select":
9446
+ return /* @__PURE__ */ jsx36(AddBundleSelectScreen, {});
9152
9447
  case "add-license-key":
9153
- return /* @__PURE__ */ jsx35(AddLicenseKeyScreen, {});
9448
+ return /* @__PURE__ */ jsx36(AddLicenseKeyScreen, {});
9154
9449
  case "add-security-scan":
9155
- return /* @__PURE__ */ jsx35(AddSecurityScanScreen, {});
9450
+ return /* @__PURE__ */ jsx36(AddSecurityScanScreen, {});
9156
9451
  case "add-targets":
9157
- return /* @__PURE__ */ jsx35(AddTargetsScreen, {});
9452
+ return /* @__PURE__ */ jsx36(AddTargetsScreen, {});
9158
9453
  case "add-scope":
9159
- return /* @__PURE__ */ jsx35(AddScopeScreen, {});
9454
+ return /* @__PURE__ */ jsx36(AddScopeScreen, {});
9160
9455
  case "add-mode":
9161
- return /* @__PURE__ */ jsx35(AddModeScreen, {});
9456
+ return /* @__PURE__ */ jsx36(AddModeScreen, {});
9162
9457
  case "add-confirm":
9163
- return /* @__PURE__ */ jsx35(AddConfirmScreen, {});
9458
+ return /* @__PURE__ */ jsx36(AddConfirmScreen, {});
9164
9459
  case "add-install":
9165
- return /* @__PURE__ */ jsx35(AddInstallScreen, {});
9460
+ return /* @__PURE__ */ jsx36(AddInstallScreen, {});
9166
9461
  case "add-result":
9167
- return /* @__PURE__ */ jsx35(AddResultScreen, {});
9462
+ return /* @__PURE__ */ jsx36(AddResultScreen, {});
9168
9463
  case "list":
9169
- return /* @__PURE__ */ jsx35(ListScreen, {});
9464
+ return /* @__PURE__ */ jsx36(ListScreen, {});
9170
9465
  case "manage":
9171
- return /* @__PURE__ */ jsx35(ManageScreen, {});
9466
+ return /* @__PURE__ */ jsx36(ManageScreen, {});
9172
9467
  case "update":
9173
- return /* @__PURE__ */ jsx35(UpdateScreen, {});
9468
+ return /* @__PURE__ */ jsx36(UpdateScreen, {});
9174
9469
  case "update-docs":
9175
- return /* @__PURE__ */ jsx35(UpdateDocsScreen, {});
9470
+ return /* @__PURE__ */ jsx36(UpdateDocsScreen, {});
9176
9471
  default:
9177
9472
  return null;
9178
9473
  }
9179
9474
  };
9180
- return /* @__PURE__ */ jsxs30(Fragment4, { children: [
9181
- /* @__PURE__ */ jsx35(BrandHeader, {}),
9475
+ return /* @__PURE__ */ jsxs31(Fragment4, { children: [
9476
+ /* @__PURE__ */ jsx36(BrandHeader, {}),
9182
9477
  render2(screen),
9183
- /* @__PURE__ */ jsx35(FlashBar, { align: "center" })
9478
+ /* @__PURE__ */ jsx36(FlashBar, { align: "center" })
9184
9479
  ] });
9185
9480
  }
9186
9481
 
@@ -9260,14 +9555,14 @@ function useKeyboardShortcuts() {
9260
9555
  }
9261
9556
 
9262
9557
  // src/tui/App.tsx
9263
- import { jsx as jsx36 } from "react/jsx-runtime";
9558
+ import { jsx as jsx37 } from "react/jsx-runtime";
9264
9559
  function AppRoot() {
9265
9560
  useKeyboardShortcuts();
9266
- return /* @__PURE__ */ jsx36(ScreenRouter, {});
9561
+ return /* @__PURE__ */ jsx37(ScreenRouter, {});
9267
9562
  }
9268
9563
  function runApp(initialInvocation, initialScreen) {
9269
9564
  const { waitUntilExit } = render(
9270
- /* @__PURE__ */ jsx36(NavigationProvider, { initialInvocation, initialScreen, children: /* @__PURE__ */ jsx36(AppRoot, {}) })
9565
+ /* @__PURE__ */ jsx37(NavigationProvider, { initialInvocation, initialScreen, children: /* @__PURE__ */ jsx37(AppRoot, {}) })
9271
9566
  );
9272
9567
  return waitUntilExit();
9273
9568
  }
@@ -9350,6 +9645,11 @@ applyAddSkillOptions(
9350
9645
  await launch({ intent: "add-skill", source, options }, initialAddSkillScreen(source));
9351
9646
  })
9352
9647
  );
9648
+ applyAddSkillOptions(
9649
+ addCmd.command("bundle <slug>").description("Add all skills from a bundle").action(async (slug, options) => {
9650
+ await launch({ intent: "add-bundle", source: slug, options }, "add-bundle-select");
9651
+ })
9652
+ );
9353
9653
  addCmd.command("docs").description("Add docs").action(async (options) => {
9354
9654
  await launch({ intent: "add-docs", options }, "add-docs");
9355
9655
  });