playbooks 0.1.16 → 0.1.17

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 +833 -466
  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.16",
11
+ version: "0.1.17",
12
12
  description: "Install agent skills, MCPs and docs into your coding agents from any git repository.",
13
13
  type: "module",
14
14
  bin: {
@@ -4571,12 +4571,16 @@ async function recordParsedTracking(skills, results, installGlobally, parsed, te
4571
4571
  const hash = await fetchSkillFolderHash(normalizedSource, skillPathValue);
4572
4572
  if (hash) skillFolderHash = hash;
4573
4573
  }
4574
+ if (parsed.type === "well-known" && parsed.contentHash) {
4575
+ skillFolderHash = parsed.contentHash;
4576
+ }
4574
4577
  await addSkillToLock(
4575
4578
  displayName,
4576
4579
  {
4577
4580
  source: normalizedSource ?? parsed.url,
4578
4581
  sourceType: parsed.type,
4579
4582
  sourceUrl: parsed.url,
4583
+ ...parsed.type === "well-known" && parsed.licenseKey ? { licenseKey: parsed.licenseKey } : {},
4580
4584
  skillPath: skillPathValue,
4581
4585
  skillFolderHash,
4582
4586
  ref: parsed.ref
@@ -4646,7 +4650,10 @@ function formatResultSummary(results) {
4646
4650
  if (!firstResult) continue;
4647
4651
  if (firstResult.mode === "copy") {
4648
4652
  lines.push(`${chalk2.green("\u2713")} ${skillName} ${chalk2.dim("(copied)")}`);
4653
+ const seenPaths = /* @__PURE__ */ new Set();
4649
4654
  for (const r of skillResults) {
4655
+ if (seenPaths.has(r.path)) continue;
4656
+ seenPaths.add(r.path);
4650
4657
  const shortPath = shortenPath(r.path, cwd);
4651
4658
  lines.push(` ${chalk2.dim("\u2192")} ${shortPath}`);
4652
4659
  }
@@ -4754,15 +4761,51 @@ function AddInstallScreen() {
4754
4761
  ] });
4755
4762
  }
4756
4763
 
4757
- // src/tui/screens/AddMode.tsx
4758
- import { join as join12 } from "path";
4759
- import { Box as Box14 } from "ink";
4764
+ // src/tui/screens/AddLicenseKey.tsx
4765
+ import { Box as Box14, Text as Text14 } from "ink";
4766
+ import TextInput2 from "ink-text-input";
4760
4767
  import React11 from "react";
4761
4768
  import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
4769
+ function AddLicenseKeyScreen() {
4770
+ const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
4771
+ const [value, setValue] = React11.useState(
4772
+ addSkill.licenseKey ?? invocation.options.licenseKey ?? ""
4773
+ );
4774
+ const { wrapOnChange } = useTextInput({
4775
+ onClear: () => {
4776
+ setValue("");
4777
+ }
4778
+ });
4779
+ const onSubmit = (input) => {
4780
+ const trimmed = input.trim();
4781
+ if (!trimmed) {
4782
+ setFlash("Enter a license key.");
4783
+ return;
4784
+ }
4785
+ updateAddSkill({ licenseKey: trimmed });
4786
+ navigateTo("add-skill-select");
4787
+ };
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 })
4795
+ ] }),
4796
+ /* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: TEXT_INPUT_HINT }) })
4797
+ ] });
4798
+ }
4799
+
4800
+ // src/tui/screens/AddMode.tsx
4801
+ 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";
4762
4805
  function AddModeScreen() {
4763
4806
  const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
4764
4807
  const options = invocation.options;
4765
- React11.useEffect(() => {
4808
+ React12.useEffect(() => {
4766
4809
  if (navAction === "pop") return;
4767
4810
  if (addSkill.installMode) {
4768
4811
  navigateTo("add-confirm");
@@ -4792,9 +4835,9 @@ function AddModeScreen() {
4792
4835
  { label: "Symlink (recommended)", value: "symlink", hint: symlinkHint },
4793
4836
  { label: "Copy to each agent", value: "copy", hint: copyHint }
4794
4837
  ];
4795
- return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
4796
- /* @__PURE__ */ jsx16(AddFlowHeader, { title: "Install mode" }),
4797
- /* @__PURE__ */ jsx16(
4838
+ return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, children: [
4839
+ /* @__PURE__ */ jsx17(AddFlowHeader, { title: "Install mode" }),
4840
+ /* @__PURE__ */ jsx17(
4798
4841
  SingleSelect,
4799
4842
  {
4800
4843
  items,
@@ -4810,9 +4853,9 @@ function AddModeScreen() {
4810
4853
 
4811
4854
  // src/tui/screens/AddResult.tsx
4812
4855
  import chalk3 from "chalk";
4813
- import { Box as Box15, Text as Text14 } from "ink";
4814
- import React12 from "react";
4815
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
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";
4816
4859
  function AddResultScreen() {
4817
4860
  const { addSkill, resetAddSkill, navigateTo } = useNavigation();
4818
4861
  const results = addSkill.installResults ?? [];
@@ -4820,7 +4863,7 @@ function AddResultScreen() {
4820
4863
  const failed = results.filter((r) => !r.success);
4821
4864
  const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
4822
4865
  const summary = successful.length > 0 ? formatResultSummary(successful) : null;
4823
- const summaryLines = React12.useMemo(() => {
4866
+ const summaryLines = React13.useMemo(() => {
4824
4867
  if (!summary) return [];
4825
4868
  const counts = /* @__PURE__ */ new Map();
4826
4869
  return summary.lines.map((line) => {
@@ -4829,15 +4872,15 @@ function AddResultScreen() {
4829
4872
  return { line, key: `${line}-${count}` };
4830
4873
  });
4831
4874
  }, [summary]);
4832
- return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, children: [
4833
- /* @__PURE__ */ jsx17(AddFlowHeader, { title: "Install results" }),
4834
- summary ? /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", marginBottom: 1, children: [
4835
- /* @__PURE__ */ jsx17(Text14, { children: summary.title }),
4836
- summaryLines.map(({ line, key }) => /* @__PURE__ */ jsx17(Text14, { children: line }, key))
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))
4837
4880
  ] }) : null,
4838
- failed.length > 0 ? /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", marginBottom: 1, children: [
4839
- /* @__PURE__ */ jsx17(Text14, { color: "red", children: `Failed to install ${failed.length}` }),
4840
- failed.map((r) => /* @__PURE__ */ jsxs13(Text14, { children: [
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: [
4841
4884
  chalk3.red("\u2717"),
4842
4885
  " ",
4843
4886
  r.skill,
@@ -4847,15 +4890,15 @@ function AddResultScreen() {
4847
4890
  chalk3.dim(r.error)
4848
4891
  ] }, `${r.skill}-${r.agentId}`))
4849
4892
  ] }) : null,
4850
- successful.length > 0 ? /* @__PURE__ */ jsx17(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsxs13(Text14, { dimColor: true, children: [
4893
+ successful.length > 0 ? /* @__PURE__ */ jsx18(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
4851
4894
  "Installed to: ",
4852
4895
  formatList(successful.map((r) => r.agent))
4853
4896
  ] }) }) : null,
4854
- symlinkFailures.length > 0 ? /* @__PURE__ */ jsxs13(Box15, { marginBottom: 1, children: [
4855
- /* @__PURE__ */ jsx17(Text14, { color: "yellow", children: `Symlinks failed for: ${formatList(symlinkFailures.map((r) => r.agent))}` }),
4856
- /* @__PURE__ */ jsx17(Text14, { dimColor: true, children: "Files were copied instead." })
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." })
4857
4900
  ] }) : null,
4858
- /* @__PURE__ */ jsx17(
4901
+ /* @__PURE__ */ jsx18(
4859
4902
  SelectMenu,
4860
4903
  {
4861
4904
  items: [
@@ -4878,13 +4921,13 @@ function AddResultScreen() {
4878
4921
  }
4879
4922
 
4880
4923
  // src/tui/screens/AddScope.tsx
4881
- import { Box as Box16 } from "ink";
4882
- import React13 from "react";
4883
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
4924
+ import { Box as Box17 } from "ink";
4925
+ import React14 from "react";
4926
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
4884
4927
  function AddScopeScreen() {
4885
4928
  const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
4886
4929
  const options = invocation.options;
4887
- React13.useEffect(() => {
4930
+ React14.useEffect(() => {
4888
4931
  if (navAction === "pop") return;
4889
4932
  if (addSkill.installGlobally !== void 0) {
4890
4933
  navigateTo("add-mode");
@@ -4907,9 +4950,9 @@ function AddScopeScreen() {
4907
4950
  const globalBase = getCanonicalSkillsBase({ global: true, cwd });
4908
4951
  const projectHint = `Project base (symlink): ${shortenPath(projectBase, cwd)}`;
4909
4952
  const globalHint = `Global base (symlink): ${shortenPath(globalBase, cwd)}`;
4910
- return /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", padding: 1, children: [
4911
- /* @__PURE__ */ jsx18(AddFlowHeader, { title: "Install scope" }),
4912
- /* @__PURE__ */ jsx18(
4953
+ return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
4954
+ /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Install scope" }),
4955
+ /* @__PURE__ */ jsx19(
4913
4956
  SingleSelect,
4914
4957
  {
4915
4958
  items: [
@@ -4931,23 +4974,23 @@ function AddScopeScreen() {
4931
4974
  }
4932
4975
 
4933
4976
  // src/tui/screens/AddSecurityScan.tsx
4934
- import { Box as Box17, Text as Text15 } from "ink";
4935
- import React14 from "react";
4936
- import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
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";
4937
4980
  function AddSecurityScanScreen() {
4938
4981
  const { invocation, addSkill, updateAddSkill, navigateTo, resetTo, setFlash, setBackHandler } = useNavigation();
4939
4982
  const options = invocation.options;
4940
- const [status, setStatus] = React14.useState("scanning");
4941
- const [error, setError] = React14.useState(null);
4942
- const [manualView, setManualView] = React14.useState("menu");
4943
- const [confirmText, setConfirmText] = React14.useState("");
4944
- const [selectedRow, setSelectedRow] = React14.useState(null);
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);
4945
4988
  const spinner = useSpinnerFrame(status === "scanning");
4946
4989
  const { wrapOnChange } = useTextInput({
4947
4990
  onClear: () => setConfirmText(""),
4948
4991
  disabled: status !== "risky" || manualView !== "type-confirm"
4949
4992
  });
4950
- React14.useEffect(() => {
4993
+ React15.useEffect(() => {
4951
4994
  const selectedSkills = addSkill.selectedSkills;
4952
4995
  if (!selectedSkills || selectedSkills.length === 0) {
4953
4996
  navigateTo("add-skill-select");
@@ -4987,7 +5030,7 @@ function AddSecurityScanScreen() {
4987
5030
  cancelled = true;
4988
5031
  };
4989
5032
  }, [addSkill.selectedSkills, navigateTo, updateAddSkill]);
4990
- React14.useEffect(() => {
5033
+ React15.useEffect(() => {
4991
5034
  if (status !== "risky") {
4992
5035
  setBackHandler(null);
4993
5036
  return () => setBackHandler(null);
@@ -5011,17 +5054,17 @@ function AddSecurityScanScreen() {
5011
5054
  return () => setBackHandler(null);
5012
5055
  }, [status, manualView, setBackHandler]);
5013
5056
  if (status === "error") {
5014
- return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
5015
- /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Security scan" }),
5016
- /* @__PURE__ */ jsx19(Text15, { color: "red", children: error ?? "Scan failed" }),
5017
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
5018
5061
  ] });
5019
5062
  }
5020
5063
  if (status === "scanning") {
5021
5064
  const count = addSkill.selectedSkills?.length ?? 0;
5022
- return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
5023
- /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Security scan" }),
5024
- /* @__PURE__ */ jsxs15(Text15, { children: [
5065
+ return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5066
+ /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
5067
+ /* @__PURE__ */ jsxs16(Text16, { children: [
5025
5068
  spinner,
5026
5069
  " Scanning ",
5027
5070
  count,
@@ -5032,9 +5075,9 @@ function AddSecurityScanScreen() {
5032
5075
  ] });
5033
5076
  }
5034
5077
  if (status === "risky") {
5035
- return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
5036
- /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Security scan" }),
5037
- /* @__PURE__ */ jsx19(
5078
+ return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
5079
+ /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
5080
+ /* @__PURE__ */ jsx20(
5038
5081
  ManualSecurityGate,
5039
5082
  {
5040
5083
  scanRows: addSkill.securityScanRows ?? [],
@@ -5058,12 +5101,12 @@ function AddSecurityScanScreen() {
5058
5101
  ] });
5059
5102
  }
5060
5103
  if (options.yes) {
5061
- return /* @__PURE__ */ jsx19(Box17, { padding: 1 });
5104
+ return /* @__PURE__ */ jsx20(Box18, { padding: 1 });
5062
5105
  }
5063
- return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
5064
- /* @__PURE__ */ jsx19(AddFlowHeader, { title: "Security scan" }),
5065
- /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: "Scan complete." }),
5066
- /* @__PURE__ */ jsx19(Box17, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text15, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
5067
5110
  ] });
5068
5111
  }
5069
5112
 
@@ -5072,8 +5115,8 @@ import { existsSync as existsSync6 } from "fs";
5072
5115
  import { mkdir as mkdir6, mkdtemp as mkdtemp4, writeFile as writeFile4 } from "fs/promises";
5073
5116
  import { tmpdir as tmpdir5 } from "os";
5074
5117
  import { join as join15 } from "path";
5075
- import { Box as Box18, Text as Text16 } from "ink";
5076
- import React15 from "react";
5118
+ import { Box as Box19, Text as Text17 } from "ink";
5119
+ import React16 from "react";
5077
5120
 
5078
5121
  // src/mintlify.ts
5079
5122
  import matter3 from "gray-matter";
@@ -5346,7 +5389,18 @@ var WellKnownProvider = class {
5346
5389
  try {
5347
5390
  const parsed = new URL(baseUrl);
5348
5391
  const basePath = parsed.pathname.replace(/\/$/, "");
5392
+ const indexSuffix = `/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`;
5349
5393
  const urlsToTry = [
5394
+ // If the caller already passed the index.json URL, try it directly.
5395
+ ...basePath.endsWith(indexSuffix) ? [
5396
+ {
5397
+ indexUrl: `${parsed.protocol}//${parsed.host}${basePath}`,
5398
+ baseUrl: `${parsed.protocol}//${parsed.host}${basePath.slice(
5399
+ 0,
5400
+ Math.max(0, basePath.length - indexSuffix.length)
5401
+ )}`
5402
+ }
5403
+ ] : [],
5350
5404
  {
5351
5405
  indexUrl: `${parsed.protocol}//${parsed.host}${basePath}/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`,
5352
5406
  baseUrl: `${parsed.protocol}//${parsed.host}${basePath}`
@@ -5391,19 +5445,46 @@ var WellKnownProvider = class {
5391
5445
  const e = entry;
5392
5446
  if (typeof e.name !== "string" || !e.name) return false;
5393
5447
  if (typeof e.description !== "string" || !e.description) return false;
5394
- if (!Array.isArray(e.files) || e.files.length === 0) return false;
5395
5448
  const nameRegex = /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/;
5396
5449
  if (!nameRegex.test(e.name) && e.name.length > 1) {
5397
5450
  if (e.name.length === 1 && !/^[a-z0-9]$/.test(e.name)) {
5398
5451
  return false;
5399
5452
  }
5400
5453
  }
5401
- for (const file of e.files) {
5402
- if (typeof file !== "string") return false;
5403
- if (file.startsWith("/") || file.startsWith("\\") || file.includes("..")) return false;
5454
+ if (Array.isArray(e.files) && e.files.length > 0) {
5455
+ for (const file of e.files) {
5456
+ if (typeof file !== "string") return false;
5457
+ if (file.startsWith("/") || file.startsWith("\\") || file.includes("..")) return false;
5458
+ }
5459
+ const hasSkillMd2 = e.files.some(
5460
+ (f) => typeof f === "string" && f.toLowerCase() === "skill.md"
5461
+ );
5462
+ if (!hasSkillMd2) return false;
5463
+ return true;
5464
+ }
5465
+ if (!e.content || typeof e.content !== "object") return false;
5466
+ const c = e.content;
5467
+ if (typeof c.endpoint !== "string" || !c.endpoint) return false;
5468
+ if (typeof c.method !== "string" || !c.method) return false;
5469
+ if (e.auth != null) {
5470
+ if (typeof e.auth !== "object") return false;
5471
+ const a = e.auth;
5472
+ if (typeof a.tokenHeader !== "string" || !a.tokenHeader) return false;
5473
+ if (a.tokenPrefix != null && typeof a.tokenPrefix !== "string") return false;
5474
+ } else {
5475
+ if (typeof c.tokenHeader !== "string" || !c.tokenHeader) return false;
5476
+ if (c.tokenPrefix != null && typeof c.tokenPrefix !== "string") return false;
5477
+ }
5478
+ if (e.verify != null) {
5479
+ if (typeof e.verify !== "object") return false;
5480
+ const v = e.verify;
5481
+ if (typeof v.endpoint !== "string" || !v.endpoint) return false;
5482
+ if (typeof v.method !== "string" || !v.method) return false;
5483
+ if (e.auth == null) {
5484
+ if (typeof v.tokenHeader !== "string" || !v.tokenHeader) return false;
5485
+ if (v.tokenPrefix != null && typeof v.tokenPrefix !== "string") return false;
5486
+ }
5404
5487
  }
5405
- const hasSkillMd2 = e.files.some((f) => typeof f === "string" && f.toLowerCase() === "skill.md");
5406
- if (!hasSkillMd2) return false;
5407
5488
  return true;
5408
5489
  }
5409
5490
  async fetchSkill(url) {
@@ -5450,6 +5531,9 @@ var WellKnownProvider = class {
5450
5531
  }
5451
5532
  async fetchSkillByEntry(baseUrl, entry) {
5452
5533
  try {
5534
+ if (!("files" in entry)) {
5535
+ return null;
5536
+ }
5453
5537
  const skillBaseUrl = `${baseUrl.replace(/\/$/, "")}/${this.WELL_KNOWN_PATH}/${entry.name}`;
5454
5538
  const skillMdUrl = `${skillBaseUrl}/SKILL.md`;
5455
5539
  const response = await fetch(skillMdUrl);
@@ -5610,9 +5694,82 @@ async function resolveRemoteSkill(url) {
5610
5694
  import { mkdir as mkdir5, mkdtemp as mkdtemp3, writeFile as writeFile3 } from "fs/promises";
5611
5695
  import { tmpdir as tmpdir4 } from "os";
5612
5696
  import { dirname as dirname4, join as join13 } from "path";
5613
- async function prepareWellKnownSkills(sourceUrl) {
5614
- const discovered = await wellKnownProvider.fetchAllSkills(sourceUrl);
5615
- if (discovered.length === 0) {
5697
+ var WellKnownLicenseKeyRequiredError = class extends Error {
5698
+ code = "LICENSE_KEY_REQUIRED";
5699
+ constructor() {
5700
+ super("A license key is required to install this skill.");
5701
+ }
5702
+ };
5703
+ function isStaticEntry(entry) {
5704
+ return "files" in entry;
5705
+ }
5706
+ function isAuthedEntry(entry) {
5707
+ return "content" in entry && !("files" in entry);
5708
+ }
5709
+ function resolveAuthForEndpoint(entry, endpoint) {
5710
+ if (entry.auth?.tokenHeader) {
5711
+ return { tokenHeader: entry.auth.tokenHeader, tokenPrefix: entry.auth.tokenPrefix ?? "" };
5712
+ }
5713
+ const spec = endpoint === "content" ? entry.content : entry.verify;
5714
+ const tokenHeader = spec?.tokenHeader;
5715
+ const tokenPrefix = spec?.tokenPrefix;
5716
+ if (typeof tokenHeader !== "string" || !tokenHeader) {
5717
+ throw new Error(
5718
+ "Invalid well-known index entry: missing auth.tokenHeader (or legacy tokenHeader)."
5719
+ );
5720
+ }
5721
+ return { tokenHeader, tokenPrefix: typeof tokenPrefix === "string" ? tokenPrefix : "" };
5722
+ }
5723
+ async function fetchAuthedManifest(entry, licenseKey) {
5724
+ const contentAuth = resolveAuthForEndpoint(entry, "content");
5725
+ const tokenValue = `${contentAuth.tokenPrefix}${licenseKey}`;
5726
+ if (entry.verify) {
5727
+ const verifyAuth = resolveAuthForEndpoint(entry, "verify");
5728
+ const verifyRes = await fetch(entry.verify.endpoint, {
5729
+ method: entry.verify.method,
5730
+ headers: { [verifyAuth.tokenHeader]: tokenValue }
5731
+ });
5732
+ if (!verifyRes.ok) {
5733
+ const text = await verifyRes.text().catch(() => "");
5734
+ let msg = text;
5735
+ try {
5736
+ const parsed = JSON.parse(text);
5737
+ if (typeof parsed?.error === "string" && parsed.error) {
5738
+ msg = parsed.error;
5739
+ }
5740
+ } catch {
5741
+ }
5742
+ throw new Error(msg || `License verification failed (${verifyRes.status}).`);
5743
+ }
5744
+ }
5745
+ const res = await fetch(entry.content.endpoint, {
5746
+ method: entry.content.method,
5747
+ headers: { [contentAuth.tokenHeader]: tokenValue }
5748
+ });
5749
+ if (!res.ok) {
5750
+ const text = await res.text().catch(() => "");
5751
+ throw new Error(text || `Unable to fetch skill content (${res.status}).`);
5752
+ }
5753
+ const json = await res.json();
5754
+ if (json && typeof json === "object" && "success" in json) {
5755
+ const wrapped = json;
5756
+ if (!wrapped.success) {
5757
+ throw new Error(wrapped.error || "Unable to fetch skill content.");
5758
+ }
5759
+ return wrapped.data;
5760
+ }
5761
+ return json;
5762
+ }
5763
+ async function prepareWellKnownSkills(sourceUrl, options) {
5764
+ const result = await wellKnownProvider.fetchIndex(sourceUrl);
5765
+ if (!result) {
5766
+ throw new Error(
5767
+ "No skills found at this URL. Make sure it exposes /.well-known/skills/index.json."
5768
+ );
5769
+ }
5770
+ const { index, resolvedBaseUrl } = result;
5771
+ const entries = index.skills ?? [];
5772
+ if (!Array.isArray(entries) || entries.length === 0) {
5616
5773
  throw new Error(
5617
5774
  "No skills found at this URL. Make sure it exposes /.well-known/skills/index.json."
5618
5775
  );
@@ -5623,33 +5780,86 @@ async function prepareWellKnownSkills(sourceUrl) {
5623
5780
  const originMap = /* @__PURE__ */ new Map();
5624
5781
  const skills = [];
5625
5782
  const sourceIdentifier = wellKnownProvider.getSourceIdentifier(sourceUrl);
5626
- for (const skill of discovered) {
5627
- const skillDir = join13(tempDir, skill.installName);
5783
+ let contentHash;
5784
+ const authedEntries = entries.filter(isAuthedEntry);
5785
+ const staticEntries = entries.filter(isStaticEntry);
5786
+ if (authedEntries.length > 0) {
5787
+ const licenseKey = options?.licenseKey?.trim();
5788
+ if (!licenseKey) {
5789
+ throw new WellKnownLicenseKeyRequiredError();
5790
+ }
5791
+ const prefixPerEntry = authedEntries.length > 1;
5792
+ for (const entry of authedEntries) {
5793
+ const manifest = await fetchAuthedManifest(entry, licenseKey);
5794
+ const m = manifest;
5795
+ if (!m || typeof m !== "object" || !m.files || typeof m.files !== "object") {
5796
+ throw new Error("Invalid manifest returned from content endpoint.");
5797
+ }
5798
+ if (typeof m.contentHash === "string" && m.contentHash) {
5799
+ contentHash = m.contentHash;
5800
+ }
5801
+ const base = prefixPerEntry ? join13(tempDir, entry.name) : tempDir;
5802
+ if (prefixPerEntry) {
5803
+ await mkdir5(base, { recursive: true });
5804
+ }
5805
+ for (const [filePath, fileContent] of Object.entries(m.files)) {
5806
+ if (typeof fileContent !== "string") continue;
5807
+ const targetPath = join13(base, filePath);
5808
+ if (!isPathSafe(base, targetPath)) {
5809
+ continue;
5810
+ }
5811
+ await mkdir5(dirname4(targetPath), { recursive: true });
5812
+ await writeFile3(targetPath, fileContent, "utf-8");
5813
+ }
5814
+ const discovered = await discoverSkills(base);
5815
+ for (const skill of discovered) {
5816
+ skills.push(skill);
5817
+ const displayName = getSkillDisplayName(skill);
5818
+ const relativeSkillDir = skill.path.startsWith(`${tempDir}/`) ? skill.path.slice(tempDir.length + 1) : null;
5819
+ const relativeSkillMd = relativeSkillDir ? `${relativeSkillDir}/SKILL.md` : null;
5820
+ originMap.set(displayName, {
5821
+ sourceType: "well-known",
5822
+ sourceUrl,
5823
+ source: sourceIdentifier,
5824
+ skillPath: relativeSkillMd ?? void 0
5825
+ });
5826
+ }
5827
+ }
5828
+ }
5829
+ for (const entry of staticEntries) {
5830
+ const fetched = await wellKnownProvider.fetchSkillByEntry(resolvedBaseUrl, entry);
5831
+ if (!fetched) continue;
5832
+ const skillDir = join13(tempDir, fetched.installName);
5628
5833
  await mkdir5(skillDir, { recursive: true });
5629
- for (const [filePath, content] of skill.files.entries()) {
5834
+ for (const [filePath, fileContent] of fetched.files.entries()) {
5630
5835
  const targetPath = join13(skillDir, filePath);
5631
5836
  if (!isPathSafe(skillDir, targetPath)) {
5632
5837
  throw new Error("Invalid file path in well-known skill index.");
5633
5838
  }
5634
5839
  await mkdir5(dirname4(targetPath), { recursive: true });
5635
- await writeFile3(targetPath, content, "utf-8");
5840
+ await writeFile3(targetPath, fileContent, "utf-8");
5636
5841
  }
5637
5842
  const localSkill = {
5638
- name: skill.installName,
5639
- description: skill.description,
5843
+ name: fetched.installName,
5844
+ description: fetched.description,
5640
5845
  path: skillDir,
5641
- rawContent: skill.content,
5642
- metadata: skill.metadata
5846
+ rawContent: fetched.content,
5847
+ metadata: fetched.metadata
5643
5848
  };
5644
5849
  skills.push(localSkill);
5645
5850
  originMap.set(getSkillDisplayName(localSkill), {
5646
5851
  sourceType: "well-known",
5647
- sourceUrl: skill.sourceUrl,
5852
+ sourceUrl: fetched.sourceUrl,
5648
5853
  source: sourceIdentifier,
5649
- skillPath: skill.sourceUrl
5854
+ skillPath: fetched.sourceUrl
5650
5855
  });
5651
5856
  }
5652
- return { tempDir, skills, originBySkillName: originMap };
5857
+ if (skills.length === 0) {
5858
+ throw new Error(
5859
+ "No skills found at this URL. Make sure it exposes /.well-known/skills/index.json."
5860
+ );
5861
+ }
5862
+ return { tempDir, skills, originBySkillName: originMap, contentHash };
5653
5863
  }
5654
5864
 
5655
5865
  // src/marketplace.ts
@@ -5959,7 +6169,7 @@ function autoSelect(skills, options) {
5959
6169
  }
5960
6170
 
5961
6171
  // src/tui/screens/AddSkillSelect.tsx
5962
- import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
6172
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
5963
6173
  function AddSkillSelectScreen() {
5964
6174
  const {
5965
6175
  invocation,
@@ -5973,16 +6183,16 @@ function AddSkillSelectScreen() {
5973
6183
  resetAddSkill,
5974
6184
  setLastSource
5975
6185
  } = useNavigation();
5976
- const [status, setStatus] = React15.useState(
6186
+ const [status, setStatus] = React16.useState(
5977
6187
  addSkill.skills && addSkill.skills.length > 0 ? "ready" : "loading"
5978
6188
  );
5979
- const [error, setError] = React15.useState(null);
5980
- const [listMode, setListMode] = React15.useState(false);
5981
- const [showLoading, setShowLoading] = React15.useState(false);
6189
+ const [error, setError] = React16.useState(null);
6190
+ const [listMode, setListMode] = React16.useState(false);
6191
+ const [showLoading, setShowLoading] = React16.useState(false);
5982
6192
  const spinner = useSpinnerFrame(status === "loading");
5983
6193
  const source = addSkill.source ?? invocation.source;
5984
6194
  const options = invocation.options;
5985
- React15.useEffect(() => {
6195
+ React16.useEffect(() => {
5986
6196
  let cancelled = false;
5987
6197
  const load = async () => {
5988
6198
  if (!source) {
@@ -6046,10 +6256,27 @@ function AddSkillSelectScreen() {
6046
6256
  return;
6047
6257
  }
6048
6258
  if (parsed.type === "well-known") {
6049
- const prepared = await prepareWellKnownSkills(parsed.url);
6259
+ const licenseKey = addSkill.licenseKey ?? options.licenseKey ?? parsed.licenseKey;
6260
+ let prepared;
6261
+ try {
6262
+ prepared = await prepareWellKnownSkills(parsed.url, { licenseKey });
6263
+ } catch (err) {
6264
+ if (err instanceof WellKnownLicenseKeyRequiredError) {
6265
+ updateAddSkill({ parsed });
6266
+ navigateTo("add-license-key");
6267
+ return;
6268
+ }
6269
+ throw err;
6270
+ }
6050
6271
  tempDirForCleanup = prepared.tempDir;
6272
+ const nextParsed = {
6273
+ ...parsed,
6274
+ ...licenseKey ? { licenseKey } : {},
6275
+ ...prepared.contentHash ? { contentHash: prepared.contentHash } : {}
6276
+ };
6051
6277
  updateAddSkill({
6052
- parsed,
6278
+ parsed: nextParsed,
6279
+ ...licenseKey ? { licenseKey } : {},
6053
6280
  tempDir: prepared.tempDir,
6054
6281
  skills: prepared.skills,
6055
6282
  originBySkillName: prepared.originBySkillName
@@ -6162,8 +6389,8 @@ function AddSkillSelectScreen() {
6162
6389
  return () => {
6163
6390
  cancelled = true;
6164
6391
  };
6165
- }, [source, addSkill.skills, updateAddSkill, navigateTo, options, setFlash]);
6166
- React15.useEffect(() => {
6392
+ }, [source, addSkill.skills, addSkill.licenseKey, updateAddSkill, navigateTo, options, setFlash]);
6393
+ React16.useEffect(() => {
6167
6394
  if (invocation.source) {
6168
6395
  setBackHandler(() => {
6169
6396
  setLastSource(invocation.source ?? null);
@@ -6179,7 +6406,7 @@ function AddSkillSelectScreen() {
6179
6406
  setBackHandler(null);
6180
6407
  };
6181
6408
  }, [invocation.source, resetTo, setBackHandler, resetAddSkill, setInvocation, setLastSource]);
6182
- React15.useEffect(() => {
6409
+ React16.useEffect(() => {
6183
6410
  if (status !== "loading") {
6184
6411
  setShowLoading(false);
6185
6412
  return;
@@ -6190,18 +6417,18 @@ function AddSkillSelectScreen() {
6190
6417
  return () => clearTimeout(timer);
6191
6418
  }, [status]);
6192
6419
  if (!source) {
6193
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
6194
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Add skills" }),
6195
- /* @__PURE__ */ jsx20(Text16, { children: `Missing source. ${BACK_QUIT_HINT}` })
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}` })
6196
6423
  ] });
6197
6424
  }
6198
6425
  if (status === "loading" && !showLoading) {
6199
- return /* @__PURE__ */ jsx20(Box18, { padding: 1 });
6426
+ return /* @__PURE__ */ jsx21(Box19, { padding: 1 });
6200
6427
  }
6201
6428
  if (status === "loading") {
6202
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
6203
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Scanning skills" }),
6204
- /* @__PURE__ */ jsxs16(Text16, { children: [
6429
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6430
+ /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Scanning skills" }),
6431
+ /* @__PURE__ */ jsxs17(Text17, { children: [
6205
6432
  spinner,
6206
6433
  " Fetching skills from ",
6207
6434
  source
@@ -6209,32 +6436,32 @@ function AddSkillSelectScreen() {
6209
6436
  ] });
6210
6437
  }
6211
6438
  if (status === "error") {
6212
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
6213
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Unable to load skills" }),
6214
- /* @__PURE__ */ jsx20(Text16, { color: "red", children: error }),
6215
- /* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
6216
6443
  ] });
6217
6444
  }
6218
6445
  const skills = addSkill.skills ?? [];
6219
6446
  if (listMode || status === "list") {
6220
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
6221
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: `Available skills (${skills.length})` }),
6222
- skills.map((skill) => /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", marginBottom: 1, children: [
6223
- /* @__PURE__ */ jsx20(Text16, { children: getSkillDisplayName(skill) }),
6224
- skill.description ? /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: skill.description }) : null
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
6225
6452
  ] }, skill.name)),
6226
- /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT })
6453
+ /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT })
6227
6454
  ] });
6228
6455
  }
6229
6456
  if (skills.length === 0) {
6230
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
6231
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "No skills found" }),
6232
- /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT })
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 })
6233
6460
  ] });
6234
6461
  }
6235
- return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
6236
- /* @__PURE__ */ jsx20(AddFlowHeader, { title: "Select skills" }),
6237
- /* @__PURE__ */ jsx20(
6462
+ return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6463
+ /* @__PURE__ */ jsx21(AddFlowHeader, { title: "Select skills" }),
6464
+ /* @__PURE__ */ jsx21(
6238
6465
  MultiSelect,
6239
6466
  {
6240
6467
  items: skills.map((skill) => ({
@@ -6266,22 +6493,22 @@ function AddSkillSelectScreen() {
6266
6493
  }
6267
6494
 
6268
6495
  // src/tui/screens/AddSource.tsx
6269
- import { Box as Box19, Text as Text17 } from "ink";
6270
- import TextInput2 from "ink-text-input";
6271
- import React16 from "react";
6272
- import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
6496
+ import { Box as Box20, Text as Text18 } from "ink";
6497
+ import TextInput3 from "ink-text-input";
6498
+ import React17 from "react";
6499
+ import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
6273
6500
  function AddSourceScreen() {
6274
6501
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, lastSource, setLastSource } = useNavigation();
6275
- const [value, setValue] = React16.useState(
6502
+ const [value, setValue] = React17.useState(
6276
6503
  addSkill.source ?? invocation.source ?? lastSource ?? ""
6277
6504
  );
6278
- const didAutofillRef = React16.useRef(false);
6505
+ const didAutofillRef = React17.useRef(false);
6279
6506
  const { wrapOnChange } = useTextInput({
6280
6507
  onClear: () => {
6281
6508
  setValue("");
6282
6509
  }
6283
6510
  });
6284
- React16.useEffect(() => {
6511
+ React17.useEffect(() => {
6285
6512
  const preset = invocation.source;
6286
6513
  if (!preset || didAutofillRef.current) return;
6287
6514
  didAutofillRef.current = true;
@@ -6298,31 +6525,31 @@ function AddSourceScreen() {
6298
6525
  updateAddSkill({ source: trimmed });
6299
6526
  navigateTo("add-skill-select");
6300
6527
  };
6301
- return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
6302
- /* @__PURE__ */ jsx21(Header, { title: "Add skills" }),
6303
- /* @__PURE__ */ jsx21(Box19, { marginBottom: 1, children: /* @__PURE__ */ jsx21(Text17, { children: "Where should we fetch skills from?" }) }),
6304
- /* @__PURE__ */ jsx21(Box19, { marginBottom: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: "Examples: owner/repo, https://.../SKILL.md, ./local/path" }) }),
6305
- /* @__PURE__ */ jsxs17(Box19, { children: [
6306
- /* @__PURE__ */ jsx21(Text17, { color: "green", children: "> " }),
6307
- /* @__PURE__ */ jsx21(TextInput2, { value, onChange: wrapOnChange(setValue), onSubmit })
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 })
6308
6535
  ] }),
6309
- /* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: TEXT_INPUT_HINT }) })
6536
+ /* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: TEXT_INPUT_HINT }) })
6310
6537
  ] });
6311
6538
  }
6312
6539
 
6313
6540
  // src/tui/screens/AddTargets.tsx
6314
- import { Box as Box20, Text as Text18 } from "ink";
6315
- import React17 from "react";
6316
- import { Fragment as Fragment2, jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
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";
6317
6544
  function AddTargetsScreen() {
6318
6545
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, navAction } = useNavigation();
6319
- const [status, setStatus] = React17.useState("loading");
6320
- const [mode, setMode] = React17.useState("choice");
6321
- const [availableAgents, setAvailableAgents] = React17.useState([]);
6322
- const [lastSelected, setLastSelected] = React17.useState([]);
6323
- const [showLoading, setShowLoading] = React17.useState(false);
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);
6324
6551
  const spinner = useSpinnerFrame(status === "loading");
6325
- React17.useEffect(() => {
6552
+ React18.useEffect(() => {
6326
6553
  let cancelled = false;
6327
6554
  const run = async () => {
6328
6555
  setStatus("loading");
@@ -6371,7 +6598,7 @@ function AddTargetsScreen() {
6371
6598
  cancelled = true;
6372
6599
  };
6373
6600
  }, [invocation.options, updateAddSkill, navigateTo, addSkill.targetAgents, setFlash, navAction]);
6374
- React17.useEffect(() => {
6601
+ React18.useEffect(() => {
6375
6602
  if (status !== "loading") {
6376
6603
  setShowLoading(false);
6377
6604
  return;
@@ -6382,12 +6609,12 @@ function AddTargetsScreen() {
6382
6609
  return () => clearTimeout(timer);
6383
6610
  }, [status]);
6384
6611
  if (status === "loading" && !showLoading) {
6385
- return /* @__PURE__ */ jsx22(Box20, { padding: 1 });
6612
+ return /* @__PURE__ */ jsx23(Box21, { padding: 1 });
6386
6613
  }
6387
6614
  if (status === "loading") {
6388
- return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
6389
- /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Detecting agents" }),
6390
- /* @__PURE__ */ jsxs18(Text18, { children: [
6615
+ return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
6616
+ /* @__PURE__ */ jsx23(AddFlowHeader, { title: "Detecting agents" }),
6617
+ /* @__PURE__ */ jsxs19(Text19, { children: [
6391
6618
  spinner,
6392
6619
  " Checking installed agents..."
6393
6620
  ] })
@@ -6409,9 +6636,9 @@ function AddTargetsScreen() {
6409
6636
  label: agents[agent].displayName,
6410
6637
  hint: agents[agent].skillsDir
6411
6638
  }));
6412
- return /* @__PURE__ */ jsx22(Box20, { flexDirection: "column", padding: 1, children: mode === "choice" ? /* @__PURE__ */ jsxs18(Fragment2, { children: [
6413
- /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Install to" }),
6414
- /* @__PURE__ */ jsx22(
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(
6415
6642
  SingleSelect,
6416
6643
  {
6417
6644
  items: [
@@ -6444,9 +6671,9 @@ function AddTargetsScreen() {
6444
6671
  }
6445
6672
  }
6446
6673
  )
6447
- ] }) : /* @__PURE__ */ jsxs18(Fragment2, { children: [
6448
- /* @__PURE__ */ jsx22(AddFlowHeader, { title: "Select agents" }),
6449
- /* @__PURE__ */ jsx22(
6674
+ ] }) : /* @__PURE__ */ jsxs19(Fragment2, { children: [
6675
+ /* @__PURE__ */ jsx23(AddFlowHeader, { title: "Select agents" }),
6676
+ /* @__PURE__ */ jsx23(
6450
6677
  MultiSelect,
6451
6678
  {
6452
6679
  items: selectableItems,
@@ -6478,9 +6705,9 @@ function AddTargetsScreen() {
6478
6705
  }
6479
6706
 
6480
6707
  // src/tui/screens/FindSkillResults.tsx
6481
- import { Box as Box21, Text as Text19 } from "ink";
6482
- import React18 from "react";
6483
- import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
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";
6484
6711
  var formatStars = (value) => {
6485
6712
  if (!value || value <= 0) return "";
6486
6713
  if (value >= 1e3) {
@@ -6509,8 +6736,8 @@ var truncateLabel = (value, max = 100) => {
6509
6736
  };
6510
6737
  function FindSkillResultsScreen() {
6511
6738
  const { findSkill, updateFindSkill, resetAddSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
6512
- const [status, setStatus] = React18.useState("ready");
6513
- const [error, setError] = React18.useState(null);
6739
+ const [status, setStatus] = React19.useState("ready");
6740
+ const [error, setError] = React19.useState(null);
6514
6741
  const spinner = useSpinnerFrame(status === "loading");
6515
6742
  const results = findSkill.results ?? [];
6516
6743
  const query = findSkill.query ?? "";
@@ -6548,36 +6775,36 @@ function FindSkillResultsScreen() {
6548
6775
  setStatus("error");
6549
6776
  }
6550
6777
  };
6551
- React18.useEffect(() => {
6778
+ React19.useEffect(() => {
6552
6779
  if (results.length === 0) {
6553
6780
  setStatus("ready");
6554
6781
  }
6555
6782
  }, [results.length]);
6556
6783
  if (status === "loading") {
6557
- return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
6558
- /* @__PURE__ */ jsx23(Header, { title: "Preparing skills" }),
6559
- /* @__PURE__ */ jsxs19(Text19, { children: [
6784
+ return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
6785
+ /* @__PURE__ */ jsx24(Header, { title: "Preparing skills" }),
6786
+ /* @__PURE__ */ jsxs20(Text20, { children: [
6560
6787
  spinner,
6561
6788
  " Cloning repositories..."
6562
6789
  ] })
6563
6790
  ] });
6564
6791
  }
6565
6792
  if (results.length === 0) {
6566
- return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
6567
- /* @__PURE__ */ jsx23(Header, { title: "No results" }),
6568
- /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: "No skills found." }),
6569
- /* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
6570
6797
  ] });
6571
6798
  }
6572
- return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
6573
- /* @__PURE__ */ jsx23(Header, { title: "Select skills" }),
6574
- /* @__PURE__ */ jsxs19(Box21, { marginBottom: 1, flexDirection: "column", children: [
6575
- /* @__PURE__ */ jsx23(Text19, { children: `Query: ${query}` }),
6576
- /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: `Mode: ${modeLabel} search` }),
6577
- /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: FIND_SKILLS_HINT })
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 })
6578
6805
  ] }),
6579
- status === "error" ? /* @__PURE__ */ jsx23(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsx23(Text19, { color: "red", children: error }) }) : null,
6580
- /* @__PURE__ */ jsx23(
6806
+ status === "error" ? /* @__PURE__ */ jsx24(Box22, { marginBottom: 1, children: /* @__PURE__ */ jsx24(Text20, { color: "red", children: error }) }) : null,
6807
+ /* @__PURE__ */ jsx24(
6581
6808
  MultiSelect,
6582
6809
  {
6583
6810
  items: results.map((result) => ({
@@ -6595,21 +6822,21 @@ function FindSkillResultsScreen() {
6595
6822
  }
6596
6823
 
6597
6824
  // src/tui/screens/FindSkillSearch.tsx
6598
- import { Box as Box22, Text as Text20, useInput as useInput5 } from "ink";
6599
- import TextInput3 from "ink-text-input";
6600
- import React19 from "react";
6601
- import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
6825
+ import { Box as Box23, Text as Text21, useInput as useInput5 } from "ink";
6826
+ import TextInput4 from "ink-text-input";
6827
+ import React20 from "react";
6828
+ import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
6602
6829
  var MIN_QUERY_LENGTH = 2;
6603
6830
  function getDebounceMs(queryLength) {
6604
6831
  return Math.max(150, 350 - queryLength * 50);
6605
6832
  }
6606
6833
  function FindSkillSearchScreen() {
6607
6834
  const { findSkill, updateFindSkill, navigateTo, setFlash } = useNavigation();
6608
- const [value, setValue] = React19.useState(findSkill.query ?? "");
6609
- const [status, setStatus] = React19.useState("idle");
6610
- const [error, setError] = React19.useState(null);
6611
- const [preview, setPreview] = React19.useState([]);
6612
- const debounceRef = React19.useRef(null);
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);
6613
6840
  const spinner = useSpinnerFrame(status === "searching" || status === "loading");
6614
6841
  const { wrapOnChange } = useTextInput({
6615
6842
  disabled: status === "loading",
@@ -6620,7 +6847,7 @@ function FindSkillSearchScreen() {
6620
6847
  updateFindSkill({ query: "" });
6621
6848
  }
6622
6849
  });
6623
- const triggerLiveSearch = React19.useCallback((query) => {
6850
+ const triggerLiveSearch = React20.useCallback((query) => {
6624
6851
  if (debounceRef.current) {
6625
6852
  clearTimeout(debounceRef.current);
6626
6853
  debounceRef.current = null;
@@ -6644,14 +6871,14 @@ function FindSkillSearchScreen() {
6644
6871
  }
6645
6872
  }, debounceMs);
6646
6873
  }, []);
6647
- React19.useEffect(() => {
6874
+ React20.useEffect(() => {
6648
6875
  return () => {
6649
6876
  if (debounceRef.current) {
6650
6877
  clearTimeout(debounceRef.current);
6651
6878
  }
6652
6879
  };
6653
6880
  }, []);
6654
- const goToLexicalResults = React19.useCallback(async () => {
6881
+ const goToLexicalResults = React20.useCallback(async () => {
6655
6882
  const query = value.trim();
6656
6883
  if (!query || query.length < MIN_QUERY_LENGTH) {
6657
6884
  setFlash(`Enter at least ${MIN_QUERY_LENGTH} characters.`);
@@ -6678,7 +6905,7 @@ function FindSkillSearchScreen() {
6678
6905
  setStatus("error");
6679
6906
  }
6680
6907
  }, [value, setFlash, updateFindSkill, navigateTo]);
6681
- const runSemanticSearch = React19.useCallback(async () => {
6908
+ const runSemanticSearch = React20.useCallback(async () => {
6682
6909
  const query = value.trim();
6683
6910
  if (!query) {
6684
6911
  setFlash("Enter a search term.");
@@ -6723,13 +6950,13 @@ function FindSkillSearchScreen() {
6723
6950
  });
6724
6951
  const showPreview = preview.length > 0 && status !== "loading";
6725
6952
  const showSearching = status === "searching" && value.trim().length >= MIN_QUERY_LENGTH;
6726
- return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
6727
- /* @__PURE__ */ jsx24(Header, { title: "Find skills" }),
6728
- /* @__PURE__ */ jsx24(Box22, { marginBottom: 1, children: /* @__PURE__ */ jsx24(Text20, { children: "Find a skill to give your agent new capabilities." }) }),
6729
- /* @__PURE__ */ jsxs20(Box22, { children: [
6730
- /* @__PURE__ */ jsx24(Text20, { color: "green", children: "> " }),
6731
- /* @__PURE__ */ jsx24(
6732
- TextInput3,
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(
6959
+ TextInput4,
6733
6960
  {
6734
6961
  value,
6735
6962
  onChange: wrapOnChange((next) => {
@@ -6746,52 +6973,52 @@ function FindSkillSearchScreen() {
6746
6973
  }
6747
6974
  )
6748
6975
  ] }),
6749
- showSearching && !showPreview ? /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
6976
+ showSearching && !showPreview ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
6750
6977
  spinner,
6751
6978
  " Searching..."
6752
6979
  ] }) }) : null,
6753
- showPreview ? /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", marginTop: 1, children: [
6754
- /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
6980
+ showPreview ? /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", marginTop: 1, children: [
6981
+ /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
6755
6982
  preview.length,
6756
6983
  " result",
6757
6984
  preview.length !== 1 ? "s" : "",
6758
6985
  " found:"
6759
6986
  ] }),
6760
- preview.slice(0, 3).map((result) => /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
6987
+ preview.slice(0, 3).map((result) => /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
6761
6988
  " ",
6762
6989
  "\u2022 ",
6763
6990
  result.name,
6764
6991
  result.repoOwner ? ` (${result.repoOwner}/${result.repoName})` : ""
6765
6992
  ] }, result.id)),
6766
- preview.length > 3 ? /* @__PURE__ */ jsxs20(Text20, { dimColor: true, children: [
6993
+ preview.length > 3 ? /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
6767
6994
  " ",
6768
6995
  "... and ",
6769
6996
  preview.length - 3,
6770
6997
  " more"
6771
6998
  ] }) : null
6772
6999
  ] }) : null,
6773
- status === "loading" ? /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsxs20(Text20, { children: [
7000
+ status === "loading" ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { children: [
6774
7001
  spinner,
6775
7002
  " Running AI search..."
6776
7003
  ] }) }) : null,
6777
- status === "error" ? /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text20, { color: "red", children: error }) }) : null,
6778
- /* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: "Enter for fast results, Tab for AI search" }) }),
6779
- /* @__PURE__ */ jsx24(Box22, { children: /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: TEXT_INPUT_HINT }) })
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 }) })
6780
7007
  ] });
6781
7008
  }
6782
7009
 
6783
7010
  // src/tui/screens/GetUrl.tsx
6784
- import { Box as Box23, Text as Text21, useApp } from "ink";
6785
- import React20 from "react";
6786
- import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
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";
6787
7014
  function GetUrlScreen() {
6788
7015
  const { exit } = useApp();
6789
7016
  const { invocation } = useNavigation();
6790
7017
  const spinner = useSpinnerFrame(true);
6791
- const didRun = React20.useRef(false);
7018
+ const didRun = React21.useRef(false);
6792
7019
  const outputPath = invocation.options?.output ?? null;
6793
7020
  const outputFormat = invocation.options?.json ? "json" : "markdown";
6794
- React20.useEffect(() => {
7021
+ React21.useEffect(() => {
6795
7022
  let cancelled = false;
6796
7023
  const run = async () => {
6797
7024
  if (didRun.current) return;
@@ -6820,12 +7047,12 @@ function GetUrlScreen() {
6820
7047
  cancelled = true;
6821
7048
  };
6822
7049
  }, [exit, invocation]);
6823
- return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
6824
- /* @__PURE__ */ jsx25(Header, { title: "Fetching URL" }),
6825
- invocation.source ? /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: `URL: ${invocation.source}` }) : null,
6826
- outputPath ? /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: `Output: ${outputPath}` }) : null,
6827
- outputFormat === "json" ? /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: "Format: json" }) : null,
6828
- /* @__PURE__ */ jsxs21(Text21, { children: [
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: [
6829
7056
  spinner,
6830
7057
  " Fetching markdown..."
6831
7058
  ] })
@@ -6833,8 +7060,8 @@ function GetUrlScreen() {
6833
7060
  }
6834
7061
 
6835
7062
  // src/tui/screens/ListSkills.tsx
6836
- import { Box as Box24, Text as Text22 } from "ink";
6837
- import React21 from "react";
7063
+ import { Box as Box25, Text as Text23 } from "ink";
7064
+ import React22 from "react";
6838
7065
 
6839
7066
  // src/installed-skills.ts
6840
7067
  import { lstat as lstat2, readFile as readFile5, readdir as readdir4, stat as stat4 } from "fs/promises";
@@ -6949,12 +7176,12 @@ async function findSkillInstallations(skillName, scope, cwd = process.cwd()) {
6949
7176
  }
6950
7177
 
6951
7178
  // src/tui/screens/ListSkills.tsx
6952
- import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
7179
+ import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
6953
7180
  function ListScreen() {
6954
7181
  const { navigateTo, setBackHandler } = useNavigation();
6955
- const [summaries, setSummaries] = React21.useState([]);
6956
- const [selectedAgent, setSelectedAgent] = React21.useState(null);
6957
- React21.useEffect(() => {
7182
+ const [summaries, setSummaries] = React22.useState([]);
7183
+ const [selectedAgent, setSelectedAgent] = React22.useState(null);
7184
+ React22.useEffect(() => {
6958
7185
  let cancelled = false;
6959
7186
  const load = async () => {
6960
7187
  const installed = await detectInstalledAgents();
@@ -6977,7 +7204,7 @@ function ListScreen() {
6977
7204
  cancelled = true;
6978
7205
  };
6979
7206
  }, []);
6980
- React21.useEffect(() => {
7207
+ React22.useEffect(() => {
6981
7208
  if (!selectedAgent) {
6982
7209
  setBackHandler(null);
6983
7210
  return;
@@ -6992,17 +7219,17 @@ function ListScreen() {
6992
7219
  }, [selectedAgent, setBackHandler]);
6993
7220
  if (selectedAgent) {
6994
7221
  const total = selectedAgent.projectSkills.length + selectedAgent.globalSkills.length;
6995
- return /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", padding: 1, children: [
6996
- /* @__PURE__ */ jsx26(Header, { title: `${agents[selectedAgent.agent].displayName} (${total})` }),
6997
- selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", marginBottom: 1, children: [
6998
- /* @__PURE__ */ jsx26(Text22, { children: "Project" }),
6999
- selectedAgent.projectSkills.map((name) => /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: name }, `p-${name}`))
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}`))
7000
7227
  ] }) : null,
7001
- selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", marginBottom: 1, children: [
7002
- /* @__PURE__ */ jsx26(Text22, { children: "Global" }),
7003
- selectedAgent.globalSkills.map((name) => /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: name }, `g-${name}`))
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}`))
7004
7231
  ] }) : null,
7005
- /* @__PURE__ */ jsx26(
7232
+ /* @__PURE__ */ jsx27(
7006
7233
  SelectMenu,
7007
7234
  {
7008
7235
  items: [
@@ -7029,9 +7256,9 @@ function ListScreen() {
7029
7256
  hint: `${count} skill${count !== 1 ? "s" : ""}`
7030
7257
  };
7031
7258
  });
7032
- return /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", padding: 1, children: [
7033
- /* @__PURE__ */ jsx26(Header, { title: "Installed skills" }),
7034
- /* @__PURE__ */ jsx26(
7259
+ return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
7260
+ /* @__PURE__ */ jsx27(Header, { title: "Installed skills" }),
7261
+ /* @__PURE__ */ jsx27(
7035
7262
  SelectMenu,
7036
7263
  {
7037
7264
  items,
@@ -7048,8 +7275,8 @@ function ListScreen() {
7048
7275
  }
7049
7276
 
7050
7277
  // src/tui/screens/MainMenu.tsx
7051
- import { Box as Box25 } from "ink";
7052
- import { jsx as jsx27 } from "react/jsx-runtime";
7278
+ import { Box as Box26 } from "ink";
7279
+ import { jsx as jsx28 } from "react/jsx-runtime";
7053
7280
  function MainMenu() {
7054
7281
  const { navigateTo, resetAddSkill, resetFindSkill, setInvocation } = useNavigation();
7055
7282
  const items = [
@@ -7063,7 +7290,7 @@ function MainMenu() {
7063
7290
  { label: "Update docs", value: "update-docs" },
7064
7291
  { label: "Exit", value: "exit" }
7065
7292
  ];
7066
- return /* @__PURE__ */ jsx27(Box25, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx27(
7293
+ return /* @__PURE__ */ jsx28(Box26, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx28(
7067
7294
  SelectMenu,
7068
7295
  {
7069
7296
  items,
@@ -7118,16 +7345,16 @@ function MainMenu() {
7118
7345
  // src/tui/screens/ManageSkills.tsx
7119
7346
  import { rm as rm5 } from "fs/promises";
7120
7347
  import chalk4 from "chalk";
7121
- import { Box as Box26, Text as Text23 } from "ink";
7122
- import React22 from "react";
7123
- import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
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";
7124
7351
  function ManageScreen() {
7125
7352
  const { navigateTo, setFlash, setBackHandler } = useNavigation();
7126
- const [summaries, setSummaries] = React22.useState([]);
7127
- const [selectedAgent, setSelectedAgent] = React22.useState(null);
7128
- const [selectedSkills, setSelectedSkills] = React22.useState(null);
7129
- const [isRemoving, setIsRemoving] = React22.useState(false);
7130
- React22.useEffect(() => {
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(() => {
7131
7358
  let cancelled = false;
7132
7359
  const load = async () => {
7133
7360
  const installedAgents = await detectInstalledAgents();
@@ -7149,7 +7376,7 @@ function ManageScreen() {
7149
7376
  cancelled = true;
7150
7377
  };
7151
7378
  }, [setFlash]);
7152
- React22.useEffect(() => {
7379
+ React23.useEffect(() => {
7153
7380
  if (isRemoving) {
7154
7381
  setBackHandler(() => true);
7155
7382
  return () => setBackHandler(null);
@@ -7172,16 +7399,16 @@ function ManageScreen() {
7172
7399
  return () => setBackHandler(null);
7173
7400
  }, [isRemoving, selectedSkills, selectedAgent, setBackHandler]);
7174
7401
  if (summaries.length === 0) {
7175
- return /* @__PURE__ */ jsxs23(Box26, { flexDirection: "column", padding: 1, children: [
7176
- /* @__PURE__ */ jsx28(Header, { title: "Remove skills" }),
7177
- /* @__PURE__ */ jsx28(Text23, { dimColor: true, children: "No skills found yet." }),
7178
- /* @__PURE__ */ jsx28(Text23, { dimColor: true, children: BACK_QUIT_HINT })
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 })
7179
7406
  ] });
7180
7407
  }
7181
7408
  if (!selectedAgent) {
7182
- return /* @__PURE__ */ jsxs23(Box26, { flexDirection: "column", padding: 1, children: [
7183
- /* @__PURE__ */ jsx28(Header, { title: "Select agent" }),
7184
- /* @__PURE__ */ jsx28(
7409
+ return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7410
+ /* @__PURE__ */ jsx29(Header, { title: "Select agent" }),
7411
+ /* @__PURE__ */ jsx29(
7185
7412
  SelectMenu,
7186
7413
  {
7187
7414
  items: summaries.map((summary) => ({
@@ -7198,9 +7425,9 @@ function ManageScreen() {
7198
7425
  ] });
7199
7426
  }
7200
7427
  if (!selectedSkills) {
7201
- return /* @__PURE__ */ jsxs23(Box26, { flexDirection: "column", padding: 1, children: [
7202
- /* @__PURE__ */ jsx28(Header, { title: `Remove skills (${agents[selectedAgent.agent].displayName})` }),
7203
- /* @__PURE__ */ jsx28(
7428
+ return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7429
+ /* @__PURE__ */ jsx29(Header, { title: `Remove skills (${agents[selectedAgent.agent].displayName})` }),
7430
+ /* @__PURE__ */ jsx29(
7204
7431
  MultiSelect,
7205
7432
  {
7206
7433
  items: selectedAgent.skills.map((skill) => ({
@@ -7220,19 +7447,19 @@ function ManageScreen() {
7220
7447
  ] });
7221
7448
  }
7222
7449
  if (isRemoving) {
7223
- return /* @__PURE__ */ jsxs23(Box26, { flexDirection: "column", padding: 1, children: [
7224
- /* @__PURE__ */ jsx28(Header, { title: "Removing skills" }),
7225
- /* @__PURE__ */ jsx28(Text23, { children: "Removing selected skills..." })
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..." })
7226
7453
  ] });
7227
7454
  }
7228
- return /* @__PURE__ */ jsxs23(Box26, { flexDirection: "column", padding: 1, children: [
7229
- /* @__PURE__ */ jsx28(Header, { title: "Confirm removal" }),
7230
- selectedSkills.map((skill) => /* @__PURE__ */ jsxs23(Text23, { children: [
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: [
7231
7458
  formatSkillLabel(skill),
7232
7459
  " ",
7233
7460
  chalk4.dim(`(${skill.scope})`)
7234
7461
  ] }, `${skill.slug}-${skill.scope}`)),
7235
- /* @__PURE__ */ jsx28(
7462
+ /* @__PURE__ */ jsx29(
7236
7463
  SelectMenu,
7237
7464
  {
7238
7465
  items: [
@@ -7295,14 +7522,14 @@ function formatSkillLabel(skill) {
7295
7522
  }
7296
7523
 
7297
7524
  // src/tui/screens/MarketplacePlugins.tsx
7298
- import { Box as Box27, Text as Text24 } from "ink";
7299
- import React23 from "react";
7300
- import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
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";
7301
7528
  function MarketplacePluginScreen() {
7302
7529
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
7303
7530
  const plugins = addSkill.marketplace?.plugins ?? [];
7304
7531
  const options = invocation.options;
7305
- React23.useEffect(() => {
7532
+ React24.useEffect(() => {
7306
7533
  if (plugins.length === 0) {
7307
7534
  return;
7308
7535
  }
@@ -7317,25 +7544,25 @@ function MarketplacePluginScreen() {
7317
7544
  }
7318
7545
  }, [plugins, options.yes, updateAddSkill, navigateTo, addSkill.marketplace]);
7319
7546
  if (plugins.length === 0) {
7320
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7321
- /* @__PURE__ */ jsx29(AddFlowHeader, { title: "Marketplace plugins" }),
7322
- /* @__PURE__ */ jsx29(Text24, { dimColor: true, children: "No plugins found." }),
7323
- /* @__PURE__ */ jsx29(Text24, { dimColor: true, children: BACK_QUIT_HINT })
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 })
7324
7551
  ] });
7325
7552
  }
7326
7553
  if (options.list) {
7327
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7328
- /* @__PURE__ */ jsx29(AddFlowHeader, { title: `Marketplace plugins (${plugins.length})` }),
7329
- plugins.map((plugin) => /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", marginBottom: 1, children: [
7330
- /* @__PURE__ */ jsx29(Text24, { children: plugin.name }),
7331
- plugin.description ? /* @__PURE__ */ jsx29(Text24, { dimColor: true, children: plugin.description }) : null
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
7332
7559
  ] }, plugin.name)),
7333
- /* @__PURE__ */ jsx29(Text24, { dimColor: true, children: BACK_QUIT_HINT })
7560
+ /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
7334
7561
  ] });
7335
7562
  }
7336
- return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
7337
- /* @__PURE__ */ jsx29(AddFlowHeader, { title: "Select plugins" }),
7338
- /* @__PURE__ */ jsx29(
7563
+ return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7564
+ /* @__PURE__ */ jsx30(AddFlowHeader, { title: "Select plugins" }),
7565
+ /* @__PURE__ */ jsx30(
7339
7566
  MultiSelect,
7340
7567
  {
7341
7568
  items: plugins.map((plugin) => ({
@@ -7362,16 +7589,16 @@ function MarketplacePluginScreen() {
7362
7589
  }
7363
7590
 
7364
7591
  // src/tui/screens/MarketplaceSkills.tsx
7365
- import { Box as Box28, Text as Text25 } from "ink";
7366
- import React24 from "react";
7592
+ import { Box as Box29, Text as Text26 } from "ink";
7593
+ import React25 from "react";
7367
7594
 
7368
7595
  // src/flows/marketplace.ts
7369
- import { dirname as dirname6, join as join17, relative as relative4 } from "path";
7596
+ import { dirname as dirname7, join as join17, relative as relative4 } from "path";
7370
7597
  function normalizeCandidatePath(basePath, candidate) {
7371
7598
  if (!candidate) return basePath;
7372
7599
  const cleaned = candidate.replace(/\\/g, "/");
7373
7600
  if (cleaned.endsWith(".md")) {
7374
- return join17(basePath, dirname6(cleaned));
7601
+ return join17(basePath, dirname7(cleaned));
7375
7602
  }
7376
7603
  return join17(basePath, cleaned);
7377
7604
  }
@@ -7523,16 +7750,16 @@ function buildOriginMap(skills) {
7523
7750
  }
7524
7751
 
7525
7752
  // src/tui/screens/MarketplaceSkills.tsx
7526
- import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
7753
+ import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
7527
7754
  function MarketplaceSkillScreen() {
7528
7755
  const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
7529
7756
  const options = invocation.options;
7530
- const [status, setStatus] = React24.useState("loading");
7531
- const [error, setError] = React24.useState(null);
7757
+ const [status, setStatus] = React25.useState("loading");
7758
+ const [error, setError] = React25.useState(null);
7532
7759
  const spinner = useSpinnerFrame(status === "loading");
7533
7760
  const selectedPlugins = addSkill.marketplace?.selectedPlugins ?? [];
7534
7761
  const context = addSkill.marketplace?.context;
7535
- React24.useEffect(() => {
7762
+ React25.useEffect(() => {
7536
7763
  let cancelled = false;
7537
7764
  const load = async () => {
7538
7765
  if (!context || selectedPlugins.length === 0) {
@@ -7596,27 +7823,27 @@ function MarketplaceSkillScreen() {
7596
7823
  options.yes
7597
7824
  ]);
7598
7825
  if (status === "loading") {
7599
- return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7600
- /* @__PURE__ */ jsx30(AddFlowHeader, { title: "Scanning marketplace" }),
7601
- /* @__PURE__ */ jsxs25(Text25, { children: [
7826
+ return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7827
+ /* @__PURE__ */ jsx31(AddFlowHeader, { title: "Scanning marketplace" }),
7828
+ /* @__PURE__ */ jsxs26(Text26, { children: [
7602
7829
  spinner,
7603
7830
  " Discovering skills from plugins..."
7604
7831
  ] })
7605
7832
  ] });
7606
7833
  }
7607
7834
  if (status === "error") {
7608
- return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7609
- /* @__PURE__ */ jsx30(AddFlowHeader, { title: "Marketplace scan failed" }),
7610
- /* @__PURE__ */ jsx30(Text25, { color: "red", children: error }),
7611
- /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
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 })
7612
7839
  ] });
7613
7840
  }
7614
7841
  const skills = addSkill.marketplace?.skills ?? [];
7615
7842
  const warnings = addSkill.marketplace?.warnings ?? [];
7616
- return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
7617
- /* @__PURE__ */ jsx30(AddFlowHeader, { title: "Select skills" }),
7618
- warnings.length > 0 ? /* @__PURE__ */ jsx30(Box28, { flexDirection: "column", marginBottom: 1, children: warnings.map((warning) => /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: warning }, warning)) }) : null,
7619
- /* @__PURE__ */ jsx30(
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(
7620
7847
  MultiSelect,
7621
7848
  {
7622
7849
  items: skills.map((entry) => ({
@@ -7666,8 +7893,8 @@ function autoSelect2(skills, names, yes) {
7666
7893
  // src/tui/screens/ScanSkills.tsx
7667
7894
  import { rm as rm6 } from "fs/promises";
7668
7895
  import chalk5 from "chalk";
7669
- import { Box as Box29, Text as Text26 } from "ink";
7670
- import React25 from "react";
7896
+ import { Box as Box30, Text as Text27 } from "ink";
7897
+ import React26 from "react";
7671
7898
 
7672
7899
  // src/flows/scan-installed-skills.ts
7673
7900
  import { existsSync as existsSync7 } from "fs";
@@ -7890,17 +8117,17 @@ function removalTargetsForRow(row, cwd) {
7890
8117
  }
7891
8118
 
7892
8119
  // src/tui/screens/ScanSkills.tsx
7893
- import { Fragment as Fragment3, jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
8120
+ import { Fragment as Fragment3, jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
7894
8121
  function ScanSkillsScreen() {
7895
8122
  const { setFlash, setBackHandler } = useNavigation();
7896
- const [view, setView] = React25.useState("loading");
7897
- const [error, setError] = React25.useState(null);
7898
- const [rows, setRows] = React25.useState([]);
7899
- const [progress, setProgress] = React25.useState(null);
7900
- const [selected, setSelected] = React25.useState(null);
7901
- const [removeTargets, setRemoveTargets] = React25.useState(null);
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);
7902
8129
  const spinner = useSpinnerFrame(view === "running" || view === "removing");
7903
- React25.useEffect(() => {
8130
+ React26.useEffect(() => {
7904
8131
  let cancelled = false;
7905
8132
  const run = async () => {
7906
8133
  try {
@@ -7970,7 +8197,7 @@ function ScanSkillsScreen() {
7970
8197
  cancelled = true;
7971
8198
  };
7972
8199
  }, []);
7973
- React25.useEffect(() => {
8200
+ React26.useEffect(() => {
7974
8201
  if (view === "actions" || view === "confirm-remove" || view === "removing") {
7975
8202
  setBackHandler(() => {
7976
8203
  if (view === "confirm-remove") {
@@ -7990,26 +8217,26 @@ function ScanSkillsScreen() {
7990
8217
  setBackHandler(null);
7991
8218
  return () => setBackHandler(null);
7992
8219
  }, [view, setBackHandler]);
7993
- const riskyRows = React25.useMemo(() => rows.filter(isRisky), [rows]);
7994
- const summary = React25.useMemo(() => scanSummary(rows), [rows]);
8220
+ const riskyRows = React26.useMemo(() => rows.filter(isRisky), [rows]);
8221
+ const summary = React26.useMemo(() => scanSummary(rows), [rows]);
7995
8222
  if (view === "empty") {
7996
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
7997
- /* @__PURE__ */ jsx31(Header, { title: "Scan skills" }),
7998
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
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.` })
7999
8226
  ] });
8000
8227
  }
8001
8228
  if (view === "loading") {
8002
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8003
- /* @__PURE__ */ jsx31(Header, { title: "Scan skills" }),
8004
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: "Discovering skills..." })
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..." })
8005
8232
  ] });
8006
8233
  }
8007
8234
  if (view === "running") {
8008
8235
  const completed = progress?.completed ?? 0;
8009
8236
  const total = progress?.total ?? 0;
8010
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8011
- /* @__PURE__ */ jsx31(Header, { title: "Scan skills" }),
8012
- /* @__PURE__ */ jsxs26(Text26, { children: [
8237
+ return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8238
+ /* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
8239
+ /* @__PURE__ */ jsxs27(Text27, { children: [
8013
8240
  spinner,
8014
8241
  " Scanning ",
8015
8242
  completed,
@@ -8019,14 +8246,14 @@ function ScanSkillsScreen() {
8019
8246
  total === 1 ? "" : "s",
8020
8247
  "..."
8021
8248
  ] }),
8022
- /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT }) })
8249
+ /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
8023
8250
  ] });
8024
8251
  }
8025
8252
  if (view === "error") {
8026
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8027
- /* @__PURE__ */ jsx31(Header, { title: "Scan skills" }),
8028
- /* @__PURE__ */ jsx31(Text26, { color: "red", children: error ?? "Scan failed" }),
8029
- /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
8030
8257
  ] });
8031
8258
  }
8032
8259
  if (view === "actions" && selected) {
@@ -8037,27 +8264,27 @@ function ScanSkillsScreen() {
8037
8264
  const top = selected.topSignals?.slice(0, 10) ?? [];
8038
8265
  const locationLabels = selected.skill.locations.map((l) => l.label);
8039
8266
  const riskColor = level === "critical" || level === "high" ? "red" : level === "medium" ? "yellow" : level === "low" ? "green" : "gray";
8040
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8041
- /* @__PURE__ */ jsx31(Header, { title: "Skill risk details" }),
8042
- /* @__PURE__ */ jsxs26(Text26, { children: [
8043
- /* @__PURE__ */ jsx31(Text26, { bold: true, children: selected.skill.name }),
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 }),
8044
8271
  " ",
8045
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: `(${selected.skill.slug})` })
8272
+ /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `(${selected.skill.slug})` })
8046
8273
  ] }),
8047
- selected.error ? /* @__PURE__ */ jsx31(Text26, { color: "red", children: selected.error }) : /* @__PURE__ */ jsxs26(Fragment3, { children: [
8048
- /* @__PURE__ */ jsxs26(Text26, { children: [
8049
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: "Verdict:" }),
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:" }),
8050
8277
  " ",
8051
- /* @__PURE__ */ jsx31(Text26, { color: riskColor, children: verdict }),
8052
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: ` \u2022 level=${level} score=${score} issues=${issues}` })
8278
+ /* @__PURE__ */ jsx32(Text27, { color: riskColor, children: verdict }),
8279
+ /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: ` \u2022 level=${level} score=${score} issues=${issues}` })
8053
8280
  ] }),
8054
- top.length > 0 ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: `Top signals: ${top.join(", ")}` }) : null,
8055
- selected.ruleset ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: `Ruleset: ${selected.ruleset}` }) : null
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
8056
8283
  ] }),
8057
- selected.skill.description ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: selected.skill.description }) : null,
8058
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: `Path: ${selected.skill.path}` }),
8059
- locationLabels.length > 0 ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: `Locations: ${locationLabels.join(", ")}` }) : null,
8060
- /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(
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(
8061
8288
  SelectMenu,
8062
8289
  {
8063
8290
  items: [
@@ -8083,17 +8310,17 @@ function ScanSkillsScreen() {
8083
8310
  }
8084
8311
  if (view === "confirm-remove" && selected && removeTargets) {
8085
8312
  const title = `Remove ${selected.skill.name}`;
8086
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8087
- /* @__PURE__ */ jsx31(Header, { title }),
8088
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: "These locations will be removed:" }),
8089
- /* @__PURE__ */ jsx31(Box29, { flexDirection: "column", marginTop: 1, children: removeTargets.length === 0 ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: "None found." }) : removeTargets.map((t) => /* @__PURE__ */ jsxs26(Text26, { children: [
8090
- /* @__PURE__ */ jsx31(Text26, { children: chalk5.red("\u2022") }),
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") }),
8091
8318
  " ",
8092
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: t.label }),
8319
+ /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: t.label }),
8093
8320
  " ",
8094
8321
  t.path
8095
8322
  ] }, t.path)) }),
8096
- /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(
8323
+ /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
8097
8324
  SelectMenu,
8098
8325
  {
8099
8326
  items: [
@@ -8141,33 +8368,33 @@ function ScanSkillsScreen() {
8141
8368
  ] });
8142
8369
  }
8143
8370
  if (view === "removing") {
8144
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8145
- /* @__PURE__ */ jsx31(Header, { title: "Removing skill" }),
8146
- /* @__PURE__ */ jsxs26(Text26, { children: [
8371
+ return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8372
+ /* @__PURE__ */ jsx32(Header, { title: "Removing skill" }),
8373
+ /* @__PURE__ */ jsxs27(Text27, { children: [
8147
8374
  spinner,
8148
8375
  " Removing..."
8149
8376
  ] }),
8150
- /* @__PURE__ */ jsx31(Box29, { marginTop: 1, children: /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT }) })
8377
+ /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
8151
8378
  ] });
8152
8379
  }
8153
8380
  if (riskyRows.length === 0) {
8154
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8155
- /* @__PURE__ */ jsx31(Header, { title: "Scan skills" }),
8156
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
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.` })
8157
8384
  ] });
8158
8385
  }
8159
- return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
8160
- /* @__PURE__ */ jsx31(Header, { title: "Scan skills" }),
8161
- /* @__PURE__ */ jsxs26(Box29, { marginBottom: 1, flexDirection: "column", children: [
8162
- /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: `Scanned ${plural(summary.total, "skill")}.` }),
8163
- /* @__PURE__ */ jsxs26(Text26, { children: [
8164
- /* @__PURE__ */ jsx31(Text26, { color: "red", children: plural(summary.high, "high risk") }),
8165
- /* @__PURE__ */ jsx31(Text26, { children: ", " }),
8166
- /* @__PURE__ */ jsx31(Text26, { color: "yellow", children: plural(summary.medium, "medium risk") }),
8167
- /* @__PURE__ */ jsx31(Text26, { children: " detected." })
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." })
8168
8395
  ] })
8169
8396
  ] }),
8170
- /* @__PURE__ */ jsx31(
8397
+ /* @__PURE__ */ jsx32(
8171
8398
  SingleSelect,
8172
8399
  {
8173
8400
  items: riskyRows.map((row) => ({
@@ -8188,8 +8415,8 @@ function ScanSkillsScreen() {
8188
8415
  }
8189
8416
 
8190
8417
  // src/tui/screens/UpdateDocs.tsx
8191
- import { Box as Box30, Text as Text27 } from "ink";
8192
- import React26 from "react";
8418
+ import { Box as Box31, Text as Text28 } from "ink";
8419
+ import React27 from "react";
8193
8420
 
8194
8421
  // src/docs/update.ts
8195
8422
  import { readdir as readdir6, stat as stat6 } from "fs/promises";
@@ -8255,12 +8482,12 @@ async function updateDocs(cwd = process.cwd()) {
8255
8482
  }
8256
8483
 
8257
8484
  // src/tui/screens/UpdateDocs.tsx
8258
- import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
8485
+ import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
8259
8486
  function UpdateDocsScreen() {
8260
- const [status, setStatus] = React26.useState("running");
8261
- const [summary, setSummary] = React26.useState(null);
8487
+ const [status, setStatus] = React27.useState("running");
8488
+ const [summary, setSummary] = React27.useState(null);
8262
8489
  const spinner = useSpinnerFrame(status === "running");
8263
- React26.useEffect(() => {
8490
+ React27.useEffect(() => {
8264
8491
  let cancelled = false;
8265
8492
  const run = async () => {
8266
8493
  const output2 = await updateDocs();
@@ -8278,65 +8505,180 @@ function UpdateDocsScreen() {
8278
8505
  };
8279
8506
  }, []);
8280
8507
  if (status === "running") {
8281
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8282
- /* @__PURE__ */ jsx32(Header, { title: "Updating docs" }),
8283
- /* @__PURE__ */ jsxs27(Text27, { children: [
8508
+ return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8509
+ /* @__PURE__ */ jsx33(Header, { title: "Updating docs" }),
8510
+ /* @__PURE__ */ jsxs28(Text28, { children: [
8284
8511
  spinner,
8285
8512
  " Pulling latest docs..."
8286
8513
  ] })
8287
8514
  ] });
8288
8515
  }
8289
8516
  if (status === "empty") {
8290
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8291
- /* @__PURE__ */ jsx32(Header, { title: "Update docs" }),
8292
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "No docs installed yet." }),
8293
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
8294
8521
  ] });
8295
8522
  }
8296
8523
  if (!summary) {
8297
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8298
- /* @__PURE__ */ jsx32(Header, { title: "Update docs" }),
8299
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "Nothing to update." })
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." })
8300
8527
  ] });
8301
8528
  }
8302
8529
  const cwd = process.cwd();
8303
- return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
8304
- /* @__PURE__ */ jsx32(Header, { title: "Docs update results" }),
8305
- summary.updated.length > 0 ? /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", marginBottom: 1, children: [
8306
- /* @__PURE__ */ jsx32(Text27, { children: `Updated ${summary.updated.length} repo${summary.updated.length !== 1 ? "s" : ""}` }),
8307
- summary.updated.map((item) => /* @__PURE__ */ jsxs27(Text27, { dimColor: true, children: [
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: [
8308
8535
  item.name,
8309
8536
  " \u2192 ",
8310
8537
  shortenPath(item.path, cwd)
8311
8538
  ] }, `updated-${item.name}`))
8312
8539
  ] }) : null,
8313
- summary.skipped.length > 0 ? /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", marginBottom: 1, children: [
8314
- /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "Skipped" }),
8315
- summary.skipped.map((item) => /* @__PURE__ */ jsxs27(Text27, { dimColor: true, children: [
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: [
8316
8543
  item.name,
8317
8544
  item.message ? ` (${item.message})` : ""
8318
8545
  ] }, `skipped-${item.name}`))
8319
8546
  ] }) : null,
8320
- summary.failed.length > 0 ? /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", marginBottom: 1, children: [
8321
- /* @__PURE__ */ jsx32(Text27, { color: "red", children: "Failed" }),
8322
- summary.failed.map((item) => /* @__PURE__ */ jsxs27(Text27, { color: "red", children: [
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: [
8323
8550
  item.name,
8324
8551
  item.message ? ` (${item.message})` : ""
8325
8552
  ] }, `failed-${item.name}`))
8326
8553
  ] }) : null,
8327
- /* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
8554
+ /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
8328
8555
  ] });
8329
8556
  }
8330
8557
 
8331
8558
  // src/tui/screens/UpdateSkills.tsx
8332
8559
  import chalk6 from "chalk";
8333
- import { Box as Box31, Text as Text28, useInput as useInput6 } from "ink";
8334
- import React27 from "react";
8560
+ import { Box as Box32, Text as Text29, useInput as useInput6 } from "ink";
8561
+ import React28 from "react";
8335
8562
 
8336
8563
  // src/flows/update-skills.ts
8337
- import { mkdir as mkdir7, mkdtemp as mkdtemp5, rm as rm7, stat as stat7, writeFile as writeFile5 } from "fs/promises";
8564
+ import { randomUUID } from "crypto";
8565
+ import { cp as cp2, mkdir as mkdir8, mkdtemp as mkdtemp6, rm as rm7, stat as stat7, writeFile as writeFile6 } from "fs/promises";
8566
+ import { homedir as homedir5, tmpdir as tmpdir7 } from "os";
8567
+ import { dirname as dirname9, join as join22 } from "path";
8568
+
8569
+ // src/flows/update-well-known-authed.ts
8570
+ import { mkdir as mkdir7, mkdtemp as mkdtemp5, writeFile as writeFile5 } from "fs/promises";
8338
8571
  import { tmpdir as tmpdir6 } from "os";
8339
- import { dirname as dirname7, join as join21 } from "path";
8572
+ import { dirname as dirname8, join as join21 } from "path";
8573
+ function resolveAuthedIndexAuth(entry, endpoint) {
8574
+ if (entry.auth?.tokenHeader) {
8575
+ return { tokenHeader: entry.auth.tokenHeader, tokenPrefix: entry.auth.tokenPrefix ?? "" };
8576
+ }
8577
+ const spec = endpoint === "content" ? entry.content : entry.verify;
8578
+ const tokenHeader = spec?.tokenHeader;
8579
+ const tokenPrefix = spec?.tokenPrefix;
8580
+ if (!tokenHeader) {
8581
+ throw new Error(
8582
+ "Invalid well-known index entry: missing auth.tokenHeader (or legacy tokenHeader)."
8583
+ );
8584
+ }
8585
+ return { tokenHeader, tokenPrefix: tokenPrefix ?? "" };
8586
+ }
8587
+ async function fetchWellKnownAuthedManifest(sourceUrl, licenseKey) {
8588
+ const result = await wellKnownProvider.fetchIndex(sourceUrl);
8589
+ if (!result) return null;
8590
+ const entry = result.index.skills.find(
8591
+ (e) => e && typeof e === "object" && "content" in e && !("files" in e)
8592
+ );
8593
+ if (!entry?.content?.endpoint) return null;
8594
+ const contentAuth = resolveAuthedIndexAuth(entry, "content");
8595
+ const tokenValue = `${contentAuth.tokenPrefix}${licenseKey}`;
8596
+ if (entry.verify?.endpoint) {
8597
+ const verifyAuth = resolveAuthedIndexAuth(entry, "verify");
8598
+ const verifyRes = await fetch(entry.verify.endpoint, {
8599
+ method: entry.verify.method,
8600
+ headers: { [verifyAuth.tokenHeader]: tokenValue }
8601
+ });
8602
+ if (!verifyRes.ok) {
8603
+ const text = await verifyRes.text().catch(() => "");
8604
+ let msg = text;
8605
+ try {
8606
+ const parsed = JSON.parse(text);
8607
+ if (typeof parsed?.error === "string" && parsed.error) {
8608
+ msg = parsed.error;
8609
+ }
8610
+ } catch {
8611
+ }
8612
+ throw new Error(msg || `License verification failed (${verifyRes.status}).`);
8613
+ }
8614
+ }
8615
+ const res = await fetch(entry.content.endpoint, {
8616
+ method: entry.content.method,
8617
+ headers: { [contentAuth.tokenHeader]: tokenValue }
8618
+ });
8619
+ if (!res.ok) {
8620
+ const text = await res.text().catch(() => "");
8621
+ throw new Error(text || `Unable to fetch skill content (${res.status}).`);
8622
+ }
8623
+ const json = await res.json();
8624
+ if (json && typeof json === "object" && "success" in json) {
8625
+ const wrapped = json;
8626
+ if (!wrapped.success) {
8627
+ throw new Error(wrapped.error || "Unable to fetch skill content.");
8628
+ }
8629
+ return wrapped.data;
8630
+ }
8631
+ return json;
8632
+ }
8633
+ async function updateFromWellKnownAuthed(target, helpers) {
8634
+ if (target.entry.sourceType !== "well-known") return false;
8635
+ if (!target.entry.licenseKey) return false;
8636
+ const sourceUrl = target.entry.sourceUrl || target.entry.source;
8637
+ const manifest = await fetchWellKnownAuthedManifest(sourceUrl, target.entry.licenseKey);
8638
+ if (!manifest?.files || typeof manifest.files !== "object") {
8639
+ return false;
8640
+ }
8641
+ if (manifest.contentHash) {
8642
+ target.latestHash = manifest.contentHash;
8643
+ if (target.entry.skillFolderHash && target.entry.skillFolderHash === manifest.contentHash) {
8644
+ target.status = "up-to-date";
8645
+ return false;
8646
+ }
8647
+ }
8648
+ const tempDir = await mkdtemp5(join21(tmpdir6(), "playbooks-well-known-"));
8649
+ registerTempDir(tempDir);
8650
+ try {
8651
+ await mkdir7(tempDir, { recursive: true });
8652
+ for (const [filePath, fileContent] of Object.entries(manifest.files)) {
8653
+ const targetPath = join21(tempDir, filePath);
8654
+ if (!isPathSafe(tempDir, targetPath)) continue;
8655
+ await mkdir7(dirname8(targetPath), { recursive: true });
8656
+ await writeFile5(targetPath, fileContent, "utf-8");
8657
+ }
8658
+ let sourceDir = null;
8659
+ if (target.entry.skillPath) {
8660
+ const normalized = target.entry.skillPath.replace(/\\/g, "/").replace(/^\/+/, "");
8661
+ const folder = normalized.toLowerCase().endsWith("skill.md") ? dirname8(normalized) : normalized;
8662
+ const candidate = join21(tempDir, folder);
8663
+ if (await helpers.pathExists(join21(candidate, "SKILL.md"))) {
8664
+ sourceDir = candidate;
8665
+ }
8666
+ }
8667
+ if (!sourceDir) {
8668
+ const discovered = await discoverSkills(tempDir);
8669
+ const match = discovered.find((s) => s.name === target.name) ?? null;
8670
+ sourceDir = match ? match.path : null;
8671
+ }
8672
+ if (!sourceDir) {
8673
+ return false;
8674
+ }
8675
+ return await helpers.applyUpdateFromDir(target.name, target.scope, sourceDir);
8676
+ } finally {
8677
+ await cleanupTempDir(tempDir);
8678
+ }
8679
+ }
8680
+
8681
+ // src/flows/update-skills.ts
8340
8682
  var repoTreeCache = /* @__PURE__ */ new Map();
8341
8683
  function normalizeSkillFolderPath(skillPath) {
8342
8684
  let folderPath = skillPath;
@@ -8404,6 +8746,23 @@ async function pathExists3(path) {
8404
8746
  return false;
8405
8747
  }
8406
8748
  }
8749
+ function getBackupRoot(scope) {
8750
+ const baseDir = scope === "global" ? homedir5() : process.cwd();
8751
+ return join22(baseDir, ".playbooks", "backups");
8752
+ }
8753
+ async function backupDirIfExists(input) {
8754
+ if (process.env.PLAYBOOKS_DISABLE_BACKUPS === "1") return;
8755
+ try {
8756
+ if (!await pathExists3(input.sourcePath)) return;
8757
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
8758
+ const safeSkillName = sanitizeSkillName(input.skillName);
8759
+ const backupBase = join22(getBackupRoot(input.scope), stamp, input.scope, safeSkillName);
8760
+ const dest = join22(backupBase, `${input.label}-${randomUUID()}`);
8761
+ await mkdir8(dirname9(dest), { recursive: true });
8762
+ await cp2(input.sourcePath, dest, { recursive: true, dereference: false });
8763
+ } catch {
8764
+ }
8765
+ }
8407
8766
  async function applyUpdateFromDir(skillName, scope, sourceDir) {
8408
8767
  const canonicalPath = getCanonicalPath(skillName, { global: scope === "global" });
8409
8768
  const installs = await findSkillInstallations(skillName, scope);
@@ -8413,12 +8772,14 @@ async function applyUpdateFromDir(skillName, scope, sourceDir) {
8413
8772
  return false;
8414
8773
  }
8415
8774
  if (canonicalExists || hasSymlink) {
8775
+ await backupDirIfExists({ scope, skillName, sourcePath: canonicalPath, label: "canonical" });
8416
8776
  await rm7(canonicalPath, { recursive: true, force: true });
8417
8777
  await copySkillDirectory(sourceDir, canonicalPath);
8418
8778
  }
8419
8779
  const updateTargets = installs.filter((i) => !i.isSymlink && i.path !== canonicalPath);
8420
8780
  if (updateTargets.length > 0) {
8421
8781
  for (const install of updateTargets) {
8782
+ await backupDirIfExists({ scope, skillName, sourcePath: install.path, label: "install" });
8422
8783
  await rm7(install.path, { recursive: true, force: true });
8423
8784
  await copySkillDirectory(sourceDir, install.path);
8424
8785
  }
@@ -8431,8 +8792,8 @@ async function updateFromRepo(target) {
8431
8792
  let sourceDir = null;
8432
8793
  if (target.entry.skillPath) {
8433
8794
  const normalizedPath = target.entry.skillPath.replace(/\\/g, "/");
8434
- const skillDir = join21(tempDir, dirname7(normalizedPath));
8435
- if (await pathExists3(join21(skillDir, "SKILL.md"))) {
8795
+ const skillDir = join22(tempDir, dirname9(normalizedPath));
8796
+ if (await pathExists3(join22(skillDir, "SKILL.md"))) {
8436
8797
  sourceDir = skillDir;
8437
8798
  }
8438
8799
  }
@@ -8473,21 +8834,21 @@ async function updateFromRemote(target) {
8473
8834
  if (!content && !files) {
8474
8835
  return false;
8475
8836
  }
8476
- const tempDir = await mkdtemp5(join21(tmpdir6(), "playbooks-skill-"));
8837
+ const tempDir = await mkdtemp6(join22(tmpdir7(), "playbooks-skill-"));
8477
8838
  registerTempDir(tempDir);
8478
8839
  try {
8479
- await mkdir7(tempDir, { recursive: true });
8840
+ await mkdir8(tempDir, { recursive: true });
8480
8841
  if (files) {
8481
8842
  for (const [filePath, fileContent] of files.entries()) {
8482
- const targetPath = join21(tempDir, filePath);
8843
+ const targetPath = join22(tempDir, filePath);
8483
8844
  if (!isPathSafe(tempDir, targetPath)) {
8484
8845
  continue;
8485
8846
  }
8486
- await mkdir7(dirname7(targetPath), { recursive: true });
8487
- await writeFile5(targetPath, fileContent, "utf-8");
8847
+ await mkdir8(dirname9(targetPath), { recursive: true });
8848
+ await writeFile6(targetPath, fileContent, "utf-8");
8488
8849
  }
8489
8850
  } else if (content) {
8490
- await writeFile5(join21(tempDir, "SKILL.md"), content, "utf-8");
8851
+ await writeFile6(join22(tempDir, "SKILL.md"), content, "utf-8");
8491
8852
  }
8492
8853
  return await applyUpdateFromDir(target.name, target.scope, tempDir);
8493
8854
  } finally {
@@ -8495,6 +8856,10 @@ async function updateFromRemote(target) {
8495
8856
  }
8496
8857
  }
8497
8858
  async function updateTargetSkill(target) {
8859
+ if (target.entry.sourceType === "well-known" && target.entry.licenseKey) {
8860
+ const updated = await updateFromWellKnownAuthed(target, { applyUpdateFromDir, pathExists: pathExists3 });
8861
+ if (updated) return true;
8862
+ }
8498
8863
  if (target.entry.sourceType === "github" || target.entry.sourceType === "gitlab" || target.entry.sourceType === "git") {
8499
8864
  return await updateFromRepo(target);
8500
8865
  }
@@ -8584,15 +8949,15 @@ async function updateSkills(targets) {
8584
8949
  }
8585
8950
 
8586
8951
  // src/tui/screens/UpdateSkills.tsx
8587
- import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
8952
+ import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
8588
8953
  function UpdateScreen() {
8589
8954
  const { invocation, navigateTo, setFlash } = useNavigation();
8590
- const [status, setStatus] = React27.useState("loading");
8591
- const [targets, setTargets] = React27.useState([]);
8592
- const [selected, setSelected] = React27.useState([]);
8593
- const [summary, setSummary] = React27.useState(null);
8594
- const [showOnlyNeeds, setShowOnlyNeeds] = React27.useState(false);
8595
- const [rateLimited, setRateLimited] = React27.useState(false);
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);
8596
8961
  const spinner = useSpinnerFrame(status === "running");
8597
8962
  useInput6((input) => {
8598
8963
  if (status !== "select") return;
@@ -8600,7 +8965,7 @@ function UpdateScreen() {
8600
8965
  setShowOnlyNeeds((prev) => !prev);
8601
8966
  }
8602
8967
  });
8603
- React27.useEffect(() => {
8968
+ React28.useEffect(() => {
8604
8969
  let cancelled = false;
8605
8970
  const load = async () => {
8606
8971
  const scopes = resolveScopes(invocation.options);
@@ -8642,7 +9007,7 @@ function UpdateScreen() {
8642
9007
  cancelled = true;
8643
9008
  };
8644
9009
  }, [invocation, setFlash]);
8645
- React27.useEffect(() => {
9010
+ React28.useEffect(() => {
8646
9011
  let cancelled = false;
8647
9012
  const run = async () => {
8648
9013
  if (status !== "running" || selected.length === 0) return;
@@ -8657,16 +9022,16 @@ function UpdateScreen() {
8657
9022
  };
8658
9023
  }, [status, selected]);
8659
9024
  if (status === "empty") {
8660
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8661
- /* @__PURE__ */ jsx33(Header, { title: "Update skills" }),
8662
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "No tracked skills to update yet." }),
8663
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Re-install a skill once to enable updates." })
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." })
8664
9029
  ] });
8665
9030
  }
8666
9031
  if (status === "loading") {
8667
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8668
- /* @__PURE__ */ jsx33(Header, { title: "Update skills" }),
8669
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Loading tracked skills..." })
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..." })
8670
9035
  ] });
8671
9036
  }
8672
9037
  if (status === "select") {
@@ -8674,17 +9039,17 @@ function UpdateScreen() {
8674
9039
  const defaults = selected;
8675
9040
  const hint = showOnlyNeeds ? UPDATE_HINT_NEEDS_ONLY : UPDATE_HINT_ALL;
8676
9041
  if (showOnlyNeeds && visibleTargets.length === 0) {
8677
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8678
- /* @__PURE__ */ jsx33(Header, { title: "Select skills to update" }),
8679
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "No updates found." }),
8680
- rateLimited ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "GitHub rate limit hit. Some skills may be marked unknown." }) : null,
8681
- /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: UPDATE_EMPTY_HINT }) })
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 }) })
8682
9047
  ] });
8683
9048
  }
8684
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8685
- /* @__PURE__ */ jsx33(Header, { title: "Select skills to update" }),
8686
- rateLimited ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "GitHub rate limit hit. Some skills marked unknown." }) : null,
8687
- /* @__PURE__ */ jsx33(
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(
8688
9053
  MultiSelect,
8689
9054
  {
8690
9055
  items: visibleTargets.map((target) => ({
@@ -8707,9 +9072,9 @@ function UpdateScreen() {
8707
9072
  ] });
8708
9073
  }
8709
9074
  if (status === "running") {
8710
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8711
- /* @__PURE__ */ jsx33(Header, { title: "Updating skills" }),
8712
- /* @__PURE__ */ jsxs28(Text28, { children: [
9075
+ return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
9076
+ /* @__PURE__ */ jsx34(Header, { title: "Updating skills" }),
9077
+ /* @__PURE__ */ jsxs29(Text29, { children: [
8713
9078
  spinner,
8714
9079
  " Updating ",
8715
9080
  selected.length,
@@ -8720,17 +9085,17 @@ function UpdateScreen() {
8720
9085
  ] });
8721
9086
  }
8722
9087
  if (!summary) {
8723
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8724
- /* @__PURE__ */ jsx33(Header, { title: "Update skills" }),
8725
- /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Nothing to update." })
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." })
8726
9091
  ] });
8727
9092
  }
8728
- return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
8729
- /* @__PURE__ */ jsx33(Header, { title: "Update results" }),
8730
- summary.updated.length > 0 ? /* @__PURE__ */ jsx33(Text28, { children: `Updated ${summary.updated.length} skill${summary.updated.length !== 1 ? "s" : ""}` }) : null,
8731
- summary.skipped.length > 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Skipped: ${summary.skipped.map(formatTargetLabel).join(", ")}` }) : null,
8732
- summary.failed.length > 0 ? /* @__PURE__ */ jsx33(Text28, { color: "red", children: `Failed: ${summary.failed.map(formatTargetLabel).join(", ")}` }) : null,
8733
- /* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
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 }) })
8734
9099
  ] });
8735
9100
  }
8736
9101
  function resolveScopes(options) {
@@ -8759,61 +9124,63 @@ function sortTargets(a, b) {
8759
9124
  }
8760
9125
 
8761
9126
  // src/tui/ScreenRouter.tsx
8762
- import { Fragment as Fragment4, jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
9127
+ import { Fragment as Fragment4, jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
8763
9128
  function ScreenRouter() {
8764
9129
  const { screen } = useNavigation();
8765
9130
  const render2 = (s) => {
8766
9131
  switch (s) {
8767
9132
  case "main":
8768
- return /* @__PURE__ */ jsx34(MainMenu, {});
9133
+ return /* @__PURE__ */ jsx35(MainMenu, {});
8769
9134
  case "add-source":
8770
- return /* @__PURE__ */ jsx34(AddSourceScreen, {});
9135
+ return /* @__PURE__ */ jsx35(AddSourceScreen, {});
8771
9136
  case "add-docs":
8772
- return /* @__PURE__ */ jsx34(AddDocsScreen, {});
9137
+ return /* @__PURE__ */ jsx35(AddDocsScreen, {});
8773
9138
  case "add-marketplace-plugins":
8774
- return /* @__PURE__ */ jsx34(MarketplacePluginScreen, {});
9139
+ return /* @__PURE__ */ jsx35(MarketplacePluginScreen, {});
8775
9140
  case "add-marketplace-skills":
8776
- return /* @__PURE__ */ jsx34(MarketplaceSkillScreen, {});
9141
+ return /* @__PURE__ */ jsx35(MarketplaceSkillScreen, {});
8777
9142
  case "find-skill-search":
8778
- return /* @__PURE__ */ jsx34(FindSkillSearchScreen, {});
9143
+ return /* @__PURE__ */ jsx35(FindSkillSearchScreen, {});
8779
9144
  case "find-skill-results":
8780
- return /* @__PURE__ */ jsx34(FindSkillResultsScreen, {});
9145
+ return /* @__PURE__ */ jsx35(FindSkillResultsScreen, {});
8781
9146
  case "scan-skills":
8782
- return /* @__PURE__ */ jsx34(ScanSkillsScreen, {});
9147
+ return /* @__PURE__ */ jsx35(ScanSkillsScreen, {});
8783
9148
  case "get-url":
8784
- return /* @__PURE__ */ jsx34(GetUrlScreen, {});
9149
+ return /* @__PURE__ */ jsx35(GetUrlScreen, {});
8785
9150
  case "add-skill-select":
8786
- return /* @__PURE__ */ jsx34(AddSkillSelectScreen, {});
9151
+ return /* @__PURE__ */ jsx35(AddSkillSelectScreen, {});
9152
+ case "add-license-key":
9153
+ return /* @__PURE__ */ jsx35(AddLicenseKeyScreen, {});
8787
9154
  case "add-security-scan":
8788
- return /* @__PURE__ */ jsx34(AddSecurityScanScreen, {});
9155
+ return /* @__PURE__ */ jsx35(AddSecurityScanScreen, {});
8789
9156
  case "add-targets":
8790
- return /* @__PURE__ */ jsx34(AddTargetsScreen, {});
9157
+ return /* @__PURE__ */ jsx35(AddTargetsScreen, {});
8791
9158
  case "add-scope":
8792
- return /* @__PURE__ */ jsx34(AddScopeScreen, {});
9159
+ return /* @__PURE__ */ jsx35(AddScopeScreen, {});
8793
9160
  case "add-mode":
8794
- return /* @__PURE__ */ jsx34(AddModeScreen, {});
9161
+ return /* @__PURE__ */ jsx35(AddModeScreen, {});
8795
9162
  case "add-confirm":
8796
- return /* @__PURE__ */ jsx34(AddConfirmScreen, {});
9163
+ return /* @__PURE__ */ jsx35(AddConfirmScreen, {});
8797
9164
  case "add-install":
8798
- return /* @__PURE__ */ jsx34(AddInstallScreen, {});
9165
+ return /* @__PURE__ */ jsx35(AddInstallScreen, {});
8799
9166
  case "add-result":
8800
- return /* @__PURE__ */ jsx34(AddResultScreen, {});
9167
+ return /* @__PURE__ */ jsx35(AddResultScreen, {});
8801
9168
  case "list":
8802
- return /* @__PURE__ */ jsx34(ListScreen, {});
9169
+ return /* @__PURE__ */ jsx35(ListScreen, {});
8803
9170
  case "manage":
8804
- return /* @__PURE__ */ jsx34(ManageScreen, {});
9171
+ return /* @__PURE__ */ jsx35(ManageScreen, {});
8805
9172
  case "update":
8806
- return /* @__PURE__ */ jsx34(UpdateScreen, {});
9173
+ return /* @__PURE__ */ jsx35(UpdateScreen, {});
8807
9174
  case "update-docs":
8808
- return /* @__PURE__ */ jsx34(UpdateDocsScreen, {});
9175
+ return /* @__PURE__ */ jsx35(UpdateDocsScreen, {});
8809
9176
  default:
8810
9177
  return null;
8811
9178
  }
8812
9179
  };
8813
- return /* @__PURE__ */ jsxs29(Fragment4, { children: [
8814
- /* @__PURE__ */ jsx34(BrandHeader, {}),
9180
+ return /* @__PURE__ */ jsxs30(Fragment4, { children: [
9181
+ /* @__PURE__ */ jsx35(BrandHeader, {}),
8815
9182
  render2(screen),
8816
- /* @__PURE__ */ jsx34(FlashBar, { align: "center" })
9183
+ /* @__PURE__ */ jsx35(FlashBar, { align: "center" })
8817
9184
  ] });
8818
9185
  }
8819
9186
 
@@ -8893,14 +9260,14 @@ function useKeyboardShortcuts() {
8893
9260
  }
8894
9261
 
8895
9262
  // src/tui/App.tsx
8896
- import { jsx as jsx35 } from "react/jsx-runtime";
9263
+ import { jsx as jsx36 } from "react/jsx-runtime";
8897
9264
  function AppRoot() {
8898
9265
  useKeyboardShortcuts();
8899
- return /* @__PURE__ */ jsx35(ScreenRouter, {});
9266
+ return /* @__PURE__ */ jsx36(ScreenRouter, {});
8900
9267
  }
8901
9268
  function runApp(initialInvocation, initialScreen) {
8902
9269
  const { waitUntilExit } = render(
8903
- /* @__PURE__ */ jsx35(NavigationProvider, { initialInvocation, initialScreen, children: /* @__PURE__ */ jsx35(AppRoot, {}) })
9270
+ /* @__PURE__ */ jsx36(NavigationProvider, { initialInvocation, initialScreen, children: /* @__PURE__ */ jsx36(AppRoot, {}) })
8904
9271
  );
8905
9272
  return waitUntilExit();
8906
9273
  }
@@ -8914,7 +9281,7 @@ program.addHelpCommand();
8914
9281
  var applyAddSkillOptions = (cmd) => cmd.option("-g, --global", "Install globally (user-level) instead of project-level").option(
8915
9282
  "-a, --agent <agents...>",
8916
9283
  "Target agents to install to (claude-code, codex, cursor, opencode, and more)"
8917
- ).option("-s, --skill <skills...>", "Install specific skills by name").option("-l, --list", "List available skills in the repository without installing").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install all skills to all agents without prompts (implies -y -g)");
9284
+ ).option("-s, --skill <skills...>", "Install specific skills by name").option("-l, --list", "List available skills in the repository without installing").option("-y, --yes", "Skip confirmation prompts").option("--license-key <key>", "License key for paid/private skills").option("--all", "Install all skills to all agents without prompts (implies -y -g)");
8918
9285
  function normalizeOptions(options) {
8919
9286
  const normalized = { ...options };
8920
9287
  if (normalized.all) {