@agents-inc/cli 0.76.0 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/{chunk-Q4PJSAMP.js → chunk-32HX6UYI.js} +2 -1
  3. package/dist/chunk-32HX6UYI.js.map +1 -0
  4. package/dist/{chunk-CKU7FJNV.js → chunk-7HGMFJ4Y.js} +3 -3
  5. package/dist/{chunk-UBNHVBSV.js → chunk-7JQIMEUX.js} +3 -3
  6. package/dist/{chunk-XYZ7B5BY.js → chunk-7LBYURQR.js} +2 -2
  7. package/dist/{chunk-NWW3OJH5.js → chunk-A5JSBU65.js} +2 -2
  8. package/dist/{chunk-ODVQXXEO.js → chunk-B4C2S5LP.js} +17 -43
  9. package/dist/{chunk-ODVQXXEO.js.map → chunk-B4C2S5LP.js.map} +1 -1
  10. package/dist/{chunk-IDN2OZJY.js → chunk-C22ACAL2.js} +2 -2
  11. package/dist/{chunk-I2SUTL7S.js → chunk-D4T3HHE7.js} +5 -5
  12. package/dist/chunk-D4T3HHE7.js.map +1 -0
  13. package/dist/{chunk-7XUKTYVD.js → chunk-EO6KJI5D.js} +1038 -270
  14. package/dist/chunk-EO6KJI5D.js.map +1 -0
  15. package/dist/{chunk-WZ5S4LGX.js → chunk-F4IZ3UAS.js} +16 -22
  16. package/dist/chunk-F4IZ3UAS.js.map +1 -0
  17. package/dist/{chunk-JWMYAJHD.js → chunk-FSK4TQX7.js} +1236 -354
  18. package/dist/chunk-FSK4TQX7.js.map +1 -0
  19. package/dist/{chunk-WMMU5FOO.js → chunk-FUWUCKES.js} +2 -2
  20. package/dist/{chunk-WMMU5FOO.js.map → chunk-FUWUCKES.js.map} +1 -1
  21. package/dist/{chunk-S6DKM6MJ.js → chunk-HANGA633.js} +4 -8
  22. package/dist/{chunk-S6DKM6MJ.js.map → chunk-HANGA633.js.map} +1 -1
  23. package/dist/{chunk-CBYRFAUN.js → chunk-HK53FRMU.js} +3 -1
  24. package/dist/chunk-HK53FRMU.js.map +1 -0
  25. package/dist/{chunk-I534EWJQ.js → chunk-IFCASC6R.js} +2 -2
  26. package/dist/{chunk-2I5SXGXR.js → chunk-KQDGLEBF.js} +80 -5
  27. package/dist/chunk-KQDGLEBF.js.map +1 -0
  28. package/dist/{chunk-AE2QHAFO.js → chunk-KVRR4PEJ.js} +81 -73
  29. package/dist/chunk-KVRR4PEJ.js.map +1 -0
  30. package/dist/{chunk-R7F5YQMI.js → chunk-LVBRC2CP.js} +2 -6
  31. package/dist/chunk-LVBRC2CP.js.map +1 -0
  32. package/dist/{chunk-CCSU4R65.js → chunk-MG55NDVG.js} +2 -2
  33. package/dist/{chunk-M4ZDKHJV.js → chunk-MUCQ27HV.js} +2 -2
  34. package/dist/chunk-N2XGUAJU.js +34 -0
  35. package/dist/{chunk-7PZFDI46.js.map → chunk-N2XGUAJU.js.map} +1 -1
  36. package/dist/{chunk-PRG7PKZM.js → chunk-N34D3ROY.js} +14 -13
  37. package/dist/chunk-N34D3ROY.js.map +1 -0
  38. package/dist/{chunk-7PMFIL5L.js → chunk-NKLNT7N7.js} +4 -21
  39. package/dist/chunk-NKLNT7N7.js.map +1 -0
  40. package/dist/{chunk-WS3TL2AO.js → chunk-OIHZ2YH3.js} +172 -102
  41. package/dist/chunk-OIHZ2YH3.js.map +1 -0
  42. package/dist/chunk-OOWNDQCG.js +192 -0
  43. package/dist/chunk-OOWNDQCG.js.map +1 -0
  44. package/dist/{chunk-EEZSCHS2.js → chunk-OTMIGYBB.js} +52 -10
  45. package/dist/chunk-OTMIGYBB.js.map +1 -0
  46. package/dist/chunk-PZERKWE2.js +114 -0
  47. package/dist/chunk-PZERKWE2.js.map +1 -0
  48. package/dist/{chunk-O5CPXIC4.js → chunk-Q755X6QF.js} +4 -4
  49. package/dist/{chunk-36YW5E7G.js → chunk-QD3GQ2CH.js} +5 -5
  50. package/dist/{chunk-ERHTXNIF.js → chunk-RU5XLS5Q.js} +1 -5
  51. package/dist/{chunk-ERHTXNIF.js.map → chunk-RU5XLS5Q.js.map} +1 -1
  52. package/dist/{chunk-VQV3DSHD.js → chunk-SJNUTUSJ.js} +5 -5
  53. package/dist/{chunk-KPRCP3MZ.js → chunk-U2KFFRRX.js} +2 -2
  54. package/dist/{chunk-CBJTSEI2.js → chunk-VDVLM3KB.js} +54 -6
  55. package/dist/chunk-VDVLM3KB.js.map +1 -0
  56. package/dist/{chunk-7NACNRFG.js → chunk-W46L2PXK.js} +32 -23
  57. package/dist/chunk-W46L2PXK.js.map +1 -0
  58. package/dist/{chunk-6F3CZLD6.js → chunk-XA7WF3BI.js} +3 -3
  59. package/dist/{chunk-WN2TUP4M.js → chunk-XYPAOBBV.js} +2 -2
  60. package/dist/{chunk-LO5QGAP2.js → chunk-YFHVP3VA.js} +5 -12
  61. package/dist/chunk-YFHVP3VA.js.map +1 -0
  62. package/dist/commands/build/marketplace.js +4 -4
  63. package/dist/commands/build/plugins.js +8 -8
  64. package/dist/commands/build/stack.js +8 -8
  65. package/dist/commands/compile.js +38 -22
  66. package/dist/commands/compile.js.map +1 -1
  67. package/dist/commands/config/index.js +8 -8
  68. package/dist/commands/config/path.js +7 -7
  69. package/dist/commands/config/show.js +8 -8
  70. package/dist/commands/diff.js +35 -15
  71. package/dist/commands/diff.js.map +1 -1
  72. package/dist/commands/doctor.js +24 -12
  73. package/dist/commands/doctor.js.map +1 -1
  74. package/dist/commands/edit.js +47 -37
  75. package/dist/commands/edit.js.map +1 -1
  76. package/dist/commands/eject.js +7 -7
  77. package/dist/commands/import/skill.js +7 -7
  78. package/dist/commands/info.js +7 -7
  79. package/dist/commands/init.js +28 -28
  80. package/dist/commands/list.js +7 -7
  81. package/dist/commands/new/agent.js +8 -8
  82. package/dist/commands/new/marketplace.js +9 -9
  83. package/dist/commands/new/skill.js +8 -8
  84. package/dist/commands/outdated.js +18 -10
  85. package/dist/commands/outdated.js.map +1 -1
  86. package/dist/commands/search.js +9 -9
  87. package/dist/commands/uninstall.js +15 -27
  88. package/dist/commands/uninstall.js.map +1 -1
  89. package/dist/commands/update.js +26 -16
  90. package/dist/commands/update.js.map +1 -1
  91. package/dist/commands/validate.js +7 -7
  92. package/dist/components/skill-search/skill-search.js +2 -2
  93. package/dist/components/wizard/category-grid.js +3 -3
  94. package/dist/components/wizard/category-grid.test.js +18 -19
  95. package/dist/components/wizard/category-grid.test.js.map +1 -1
  96. package/dist/components/wizard/checkbox-grid.js +1 -2
  97. package/dist/components/wizard/checkbox-grid.test.js +2 -4
  98. package/dist/components/wizard/checkbox-grid.test.js.map +1 -1
  99. package/dist/components/wizard/domain-selection.js +10 -11
  100. package/dist/components/wizard/help-modal.js +2 -2
  101. package/dist/components/wizard/search-modal.js +2 -2
  102. package/dist/components/wizard/search-modal.test.js +2 -2
  103. package/dist/components/wizard/source-grid.js +4 -4
  104. package/dist/components/wizard/source-grid.test.js +13 -13
  105. package/dist/components/wizard/stack-selection.js +10 -9
  106. package/dist/components/wizard/stats-panel.js +12 -0
  107. package/dist/components/wizard/step-agents.js +9 -10
  108. package/dist/components/wizard/step-agents.test.js +16 -15
  109. package/dist/components/wizard/step-agents.test.js.map +1 -1
  110. package/dist/components/wizard/step-build.js +11 -12
  111. package/dist/components/wizard/step-build.test.js +34 -32
  112. package/dist/components/wizard/step-build.test.js.map +1 -1
  113. package/dist/components/wizard/step-confirm.js +4 -6
  114. package/dist/components/wizard/step-confirm.test.js +24 -23
  115. package/dist/components/wizard/step-confirm.test.js.map +1 -1
  116. package/dist/components/wizard/step-refine.js +2 -3
  117. package/dist/components/wizard/step-refine.test.js +2 -3
  118. package/dist/components/wizard/step-refine.test.js.map +1 -1
  119. package/dist/components/wizard/step-settings.js +8 -9
  120. package/dist/components/wizard/step-settings.test.js +14 -15
  121. package/dist/components/wizard/step-settings.test.js.map +1 -1
  122. package/dist/components/wizard/step-sources.js +11 -12
  123. package/dist/components/wizard/step-sources.test.js +17 -19
  124. package/dist/components/wizard/step-sources.test.js.map +1 -1
  125. package/dist/components/wizard/step-stack.js +12 -14
  126. package/dist/components/wizard/step-stack.test.js +26 -25
  127. package/dist/components/wizard/step-stack.test.js.map +1 -1
  128. package/dist/components/wizard/view-title.js +21 -3
  129. package/dist/components/wizard/view-title.js.map +1 -1
  130. package/dist/components/wizard/wizard-layout.js +12 -11
  131. package/dist/components/wizard/wizard-tabs.js +1 -1
  132. package/dist/components/wizard/wizard-tabs.test.js +1 -1
  133. package/dist/components/wizard/wizard.js +26 -26
  134. package/dist/config-exports.js +1 -1
  135. package/dist/hooks/init.js +28 -28
  136. package/dist/{loader-7RQ4G4TH.js → loader-JMOO2A7C.js} +4 -4
  137. package/dist/{source-loader-CXCIDGWV.js → source-loader-D3VIG3GM.js} +7 -7
  138. package/dist/source-manager-FPYFJRR7.js +19 -0
  139. package/dist/source-manager-FPYFJRR7.js.map +1 -0
  140. package/dist/stores/wizard-store.js +7 -7
  141. package/dist/stores/wizard-store.test.js +12 -12
  142. package/dist/stores/wizard-store.test.js.map +1 -1
  143. package/package.json +1 -1
  144. package/dist/chunk-2I5SXGXR.js.map +0 -1
  145. package/dist/chunk-7NACNRFG.js.map +0 -1
  146. package/dist/chunk-7PMFIL5L.js.map +0 -1
  147. package/dist/chunk-7PZFDI46.js +0 -40
  148. package/dist/chunk-7XUKTYVD.js.map +0 -1
  149. package/dist/chunk-AE2QHAFO.js.map +0 -1
  150. package/dist/chunk-CBJTSEI2.js.map +0 -1
  151. package/dist/chunk-CBYRFAUN.js.map +0 -1
  152. package/dist/chunk-EEZSCHS2.js.map +0 -1
  153. package/dist/chunk-EWBNSS5Y.js +0 -113
  154. package/dist/chunk-EWBNSS5Y.js.map +0 -1
  155. package/dist/chunk-I2SUTL7S.js.map +0 -1
  156. package/dist/chunk-JNQKCZA3.js +0 -28
  157. package/dist/chunk-JNQKCZA3.js.map +0 -1
  158. package/dist/chunk-JWMYAJHD.js.map +0 -1
  159. package/dist/chunk-LO5QGAP2.js.map +0 -1
  160. package/dist/chunk-PRG7PKZM.js.map +0 -1
  161. package/dist/chunk-Q4PJSAMP.js.map +0 -1
  162. package/dist/chunk-R7F5YQMI.js.map +0 -1
  163. package/dist/chunk-WS3TL2AO.js.map +0 -1
  164. package/dist/chunk-WZ5S4LGX.js.map +0 -1
  165. package/dist/source-manager-TPLO2DVS.js +0 -19
  166. /package/dist/{chunk-CKU7FJNV.js.map → chunk-7HGMFJ4Y.js.map} +0 -0
  167. /package/dist/{chunk-UBNHVBSV.js.map → chunk-7JQIMEUX.js.map} +0 -0
  168. /package/dist/{chunk-XYZ7B5BY.js.map → chunk-7LBYURQR.js.map} +0 -0
  169. /package/dist/{chunk-NWW3OJH5.js.map → chunk-A5JSBU65.js.map} +0 -0
  170. /package/dist/{chunk-IDN2OZJY.js.map → chunk-C22ACAL2.js.map} +0 -0
  171. /package/dist/{chunk-I534EWJQ.js.map → chunk-IFCASC6R.js.map} +0 -0
  172. /package/dist/{chunk-CCSU4R65.js.map → chunk-MG55NDVG.js.map} +0 -0
  173. /package/dist/{chunk-M4ZDKHJV.js.map → chunk-MUCQ27HV.js.map} +0 -0
  174. /package/dist/{chunk-O5CPXIC4.js.map → chunk-Q755X6QF.js.map} +0 -0
  175. /package/dist/{chunk-36YW5E7G.js.map → chunk-QD3GQ2CH.js.map} +0 -0
  176. /package/dist/{chunk-VQV3DSHD.js.map → chunk-SJNUTUSJ.js.map} +0 -0
  177. /package/dist/{chunk-KPRCP3MZ.js.map → chunk-U2KFFRRX.js.map} +0 -0
  178. /package/dist/{chunk-6F3CZLD6.js.map → chunk-XA7WF3BI.js.map} +0 -0
  179. /package/dist/{chunk-WN2TUP4M.js.map → chunk-XYPAOBBV.js.map} +0 -0
  180. /package/dist/{loader-7RQ4G4TH.js.map → components/wizard/stats-panel.js.map} +0 -0
  181. /package/dist/{source-loader-CXCIDGWV.js.map → loader-JMOO2A7C.js.map} +0 -0
  182. /package/dist/{source-manager-TPLO2DVS.js.map → source-loader-D3VIG3GM.js.map} +0 -0
@@ -11,29 +11,29 @@ import {
11
11
  getProjectPluginsDir,
12
12
  isClaudeCLIAvailable,
13
13
  listPluginNames,
14
- loadProjectSourceConfig,
14
+ loadProjectConfigFromDir,
15
15
  readForkedFromMetadata
16
- } from "../chunk-WS3TL2AO.js";
17
- import "../chunk-I534EWJQ.js";
18
- import "../chunk-JWMYAJHD.js";
16
+ } from "../chunk-OIHZ2YH3.js";
17
+ import "../chunk-IFCASC6R.js";
18
+ import "../chunk-FSK4TQX7.js";
19
19
  import {
20
20
  BaseCommand,
21
21
  EXIT_CODES
22
- } from "../chunk-XYZ7B5BY.js";
22
+ } from "../chunk-7LBYURQR.js";
23
23
  import {
24
24
  directoryExists,
25
25
  getErrorMessage,
26
26
  listDirectories,
27
27
  remove
28
- } from "../chunk-WN2TUP4M.js";
29
- import "../chunk-Q4PJSAMP.js";
28
+ } from "../chunk-XYPAOBBV.js";
29
+ import "../chunk-32HX6UYI.js";
30
30
  import {
31
31
  CLAUDE_DIR,
32
32
  CLAUDE_SRC_DIR,
33
33
  CLI_COLORS,
34
34
  DEFAULT_BRANDING
35
35
  } from "../chunk-FMYAYX6W.js";
36
- import "../chunk-7XUKTYVD.js";
36
+ import "../chunk-EO6KJI5D.js";
37
37
  import {
38
38
  init_esm_shims
39
39
  } from "../chunk-DHET7RCE.js";
@@ -43,15 +43,7 @@ init_esm_shims();
43
43
  import { Flags } from "@oclif/core";
44
44
  import { render, Box, Text, useApp } from "ink";
45
45
  import path from "path";
46
- import os from "os";
47
46
  import { jsx, jsxs } from "react/jsx-runtime";
48
- function collectConfiguredSources(config) {
49
- if (!config) return [];
50
- return [
51
- ...config.source ? [config.source] : [],
52
- ...config.sources?.map((entry) => entry.url) ?? []
53
- ];
54
- }
55
47
  function collectConfiguredAgents(config) {
56
48
  if (!config?.agents) return [];
57
49
  return config.agents.map((a) => a.name);
@@ -72,7 +64,7 @@ async function detectUninstallTarget(projectDir) {
72
64
  directoryExists(agentsDir),
73
65
  directoryExists(claudeDir),
74
66
  directoryExists(claudeSrcDir),
75
- loadProjectSourceConfig(projectDir)
67
+ loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null)
76
68
  ]
77
69
  );
78
70
  let pluginNames = [];
@@ -80,7 +72,6 @@ async function detectUninstallTarget(projectDir) {
80
72
  pluginNames = await listPluginNames(projectDir);
81
73
  } catch {
82
74
  }
83
- const configuredSources = collectConfiguredSources(config);
84
75
  const configuredAgents = collectConfiguredAgents(config);
85
76
  const cliInstalledKeys = getCliInstalledPluginKeys(config);
86
77
  const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));
@@ -98,7 +89,6 @@ async function detectUninstallTarget(projectDir) {
98
89
  claudeDir,
99
90
  claudeSrcDir,
100
91
  config,
101
- configuredSources,
102
92
  configuredAgents
103
93
  };
104
94
  }
@@ -167,12 +157,8 @@ async function isDirectoryEmpty(dirPath) {
167
157
  return true;
168
158
  }
169
159
  }
170
- function skillMatchesConfiguredSource(forkedFromSource, configuredSources) {
171
- if (!forkedFromSource || configuredSources.length === 0) return false;
172
- return configuredSources.includes(forkedFromSource);
173
- }
174
- function shouldRemoveSkill(forkedFrom, configuredSources, hasConfig) {
175
- return forkedFrom !== null && (skillMatchesConfiguredSource(forkedFrom.source, configuredSources) || !forkedFrom.source && hasConfig);
160
+ function shouldRemoveSkill(forkedFrom) {
161
+ return forkedFrom !== null;
176
162
  }
177
163
  var Uninstall = class _Uninstall extends BaseCommand {
178
164
  static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;
@@ -261,7 +247,9 @@ var Uninstall = class _Uninstall extends BaseCommand {
261
247
  for (const pluginName of target.cliPluginNames) {
262
248
  if (cliAvailable) {
263
249
  try {
264
- const pluginScope = projectDir === os.homedir() ? "user" : "project";
250
+ const skillId = pluginName.split("@")[0];
251
+ const skillConfig = target.config?.skills?.find((s) => s.id === skillId);
252
+ const pluginScope = skillConfig?.scope === "global" ? "user" : "project";
265
253
  await claudePluginUninstall(pluginName, pluginScope, projectDir);
266
254
  } catch {
267
255
  }
@@ -311,7 +299,7 @@ var Uninstall = class _Uninstall extends BaseCommand {
311
299
  for (const skillDirName of skillDirNames) {
312
300
  const skillDir = path.join(target.skillsDir, skillDirName);
313
301
  const forkedFrom = await readForkedFromMetadata(skillDir);
314
- if (shouldRemoveSkill(forkedFrom, target.configuredSources, target.config !== null)) {
302
+ if (shouldRemoveSkill(forkedFrom)) {
315
303
  await remove(skillDir);
316
304
  removedCount++;
317
305
  this.log(` Uninstalled skill '${skillDirName}'`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/uninstall.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp } from \"ink\";\nimport path from \"path\";\nimport os from \"os\";\n\nimport { BaseCommand } from \"../base-command\";\nimport { Confirm } from \"../components/common/confirm\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { directoryExists, listDirectories, remove } from \"../utils/fs\";\nimport { claudePluginUninstall, isClaudeCLIAvailable } from \"../utils/exec\";\nimport { listPluginNames, getProjectPluginsDir } from \"../lib/plugins\";\nimport { readForkedFromMetadata } from \"../lib/skills\";\nimport { loadProjectSourceConfig } from \"../lib/configuration/config\";\nimport type { ProjectConfig } from \"../types\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR, CLI_COLORS, DEFAULT_BRANDING } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { SUCCESS_MESSAGES, INFO_MESSAGES } from \"../utils/messages\";\n\ntype UninstallTarget = {\n hasPlugins: boolean;\n pluginNames: string[];\n /** Plugin names filtered to only those installed by this CLI (matched against config skills) */\n cliPluginNames: string[];\n hasLocalSkills: boolean;\n hasLocalAgents: boolean;\n hasClaudeDir: boolean;\n hasClaudeSrcDir: boolean;\n pluginsDir: string;\n skillsDir: string;\n agentsDir: string;\n claudeDir: string;\n claudeSrcDir: string;\n /** Resolved project source config from .claude-src/config.ts */\n config: Partial<ProjectConfig> | null;\n /** All configured source URLs (primary + extras) */\n configuredSources: string[];\n /** Agent names from the generated config (e.g., [\"web-developer\"]) */\n configuredAgents: string[];\n};\n\nfunction collectConfiguredSources(config: Partial<ProjectConfig> | null): string[] {\n if (!config) return [];\n return [\n ...(config.source ? [config.source] : []),\n ...(config.sources?.map((entry) => entry.url) ?? []),\n ];\n}\n\nfunction collectConfiguredAgents(config: Partial<ProjectConfig> | null): string[] {\n if (!config?.agents) return [];\n return config.agents.map((a) => a.name);\n}\n\nfunction getCliInstalledPluginKeys(config: Partial<ProjectConfig> | null): Set<string> {\n if (!config?.skills) return new Set();\n return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));\n}\n\nasync function detectUninstallTarget(projectDir: string): Promise<UninstallTarget> {\n const pluginsDir = getProjectPluginsDir(projectDir);\n const skillsDir = path.join(projectDir, CLAUDE_DIR, \"skills\");\n const agentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n const claudeDir = path.join(projectDir, CLAUDE_DIR);\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(\n [\n directoryExists(skillsDir),\n directoryExists(agentsDir),\n directoryExists(claudeDir),\n directoryExists(claudeSrcDir),\n loadProjectSourceConfig(projectDir),\n ],\n );\n\n let pluginNames: string[] = [];\n try {\n pluginNames = await listPluginNames(projectDir);\n } catch {\n // Best-effort: plugin detection may fail\n }\n\n const configuredSources = collectConfiguredSources(config);\n const configuredAgents = collectConfiguredAgents(config);\n const cliInstalledKeys = getCliInstalledPluginKeys(config);\n const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));\n\n return {\n hasPlugins: cliPluginNames.length > 0,\n pluginNames,\n cliPluginNames,\n hasLocalSkills,\n hasLocalAgents,\n hasClaudeDir,\n hasClaudeSrcDir,\n pluginsDir,\n skillsDir,\n agentsDir,\n claudeDir,\n claudeSrcDir,\n config,\n configuredSources,\n configuredAgents,\n };\n}\n\ntype UninstallConfirmProps = {\n target: UninstallTarget;\n removeAll: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UninstallConfirm: React.FC<UninstallConfirmProps> = ({\n target,\n removeAll,\n onConfirm,\n onCancel,\n}) => {\n const { exit } = useApp();\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>The following will be removed:</Text>\n <Text> </Text>\n\n {target.hasPlugins && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Plugins:</Text>\n {target.cliPluginNames.map((name) => (\n <Text key={name} dimColor>\n {\" \"}\n {name}\n </Text>\n ))}\n </Box>\n )}\n\n {(target.hasLocalSkills || target.hasLocalAgents) && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> CLI-managed files:</Text>\n {target.hasLocalSkills && <Text dimColor> {target.skillsDir}/ (matching sources)</Text>}\n {target.hasLocalAgents && <Text dimColor> {target.agentsDir}/ (CLI-compiled)</Text>}\n </Box>\n )}\n\n {removeAll && target.hasClaudeSrcDir && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Config:</Text>\n <Text dimColor> {target.claudeSrcDir}/</Text>\n </Box>\n )}\n\n <Text> </Text>\n <Confirm\n message=\"Are you sure you want to uninstall?\"\n onConfirm={() => {\n onConfirm();\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n defaultValue={false}\n />\n </Box>\n );\n};\n\nasync function isDirectoryEmpty(dirPath: string): Promise<boolean> {\n const { readdir } = await import(\"fs/promises\");\n try {\n const allEntries = await readdir(dirPath);\n return allEntries.length === 0;\n } catch {\n return true;\n }\n}\n\nfunction skillMatchesConfiguredSource(\n forkedFromSource: string | undefined,\n configuredSources: string[],\n): boolean {\n if (!forkedFromSource || configuredSources.length === 0) return false;\n return configuredSources.includes(forkedFromSource);\n}\n\nfunction shouldRemoveSkill(\n forkedFrom: { source?: string } | null,\n configuredSources: string[],\n hasConfig: boolean,\n): boolean {\n return (\n forkedFrom !== null &&\n (skillMatchesConfiguredSource(forkedFrom.source, configuredSources) ||\n (!forkedFrom.source && hasConfig))\n );\n}\n\nexport default class Uninstall extends BaseCommand {\n static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;\n\n static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by source), compiled agents, and plugins. User-created content is preserved.`;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --all\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n all: Flags.boolean({\n description: \"Also remove .claude-src/ config directory\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Uninstall);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);\n this.log(\"\");\n\n const target = await detectUninstallTarget(projectDir);\n\n const hasAnythingToRemove =\n target.hasPlugins ||\n target.hasLocalSkills ||\n target.hasLocalAgents ||\n (flags.all && target.hasClaudeSrcDir);\n\n if (!hasAnythingToRemove) {\n this.warn(\"Nothing to uninstall.\");\n this.log(\"\");\n this.log(INFO_MESSAGES.NOT_INSTALLED);\n this.log(\"\");\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return;\n }\n\n if (!flags.yes) {\n const confirmed = await new Promise<boolean>((resolve) => {\n const { waitUntilExit } = render(\n <UninstallConfirm\n target={target}\n removeAll={flags.all}\n onConfirm={() => resolve(true)}\n onCancel={() => resolve(false)}\n />,\n );\n\n waitUntilExit().catch(() => resolve(false));\n });\n\n if (!confirmed) {\n this.log(\"\");\n this.log(\"Uninstall cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n } else {\n this.log(\"The following will be removed:\");\n this.log(\"\");\n\n if (target.hasPlugins) {\n this.log(\" Plugins:\");\n for (const pluginName of target.cliPluginNames) {\n this.log(` ${pluginName}`);\n }\n }\n\n if (target.hasLocalSkills || target.hasLocalAgents) {\n this.log(\" CLI-managed files:\");\n if (target.hasLocalSkills) {\n this.log(` ${target.skillsDir}/ (matching sources)`);\n }\n if (target.hasLocalAgents) {\n this.log(` ${target.agentsDir}/ (CLI-compiled)`);\n }\n }\n\n if (flags.all && target.hasClaudeSrcDir) {\n this.log(\" Config:\");\n this.log(` ${target.claudeSrcDir}/`);\n }\n\n this.log(\"\");\n }\n\n if (target.hasPlugins) {\n this.log(\"Uninstalling plugins...\");\n\n try {\n const cliAvailable = await isClaudeCLIAvailable();\n\n for (const pluginName of target.cliPluginNames) {\n if (cliAvailable) {\n try {\n const pluginScope = projectDir === os.homedir() ? \"user\" : \"project\";\n await claudePluginUninstall(pluginName, pluginScope, projectDir);\n } catch {\n // Best-effort: plugin may not be registered with Claude CLI\n }\n }\n\n const pluginPath = path.join(target.pluginsDir, pluginName);\n await remove(pluginPath);\n this.log(` Uninstalled plugin '${pluginName}'`);\n }\n\n this.logSuccess(\n `Uninstalled ${target.cliPluginNames.length} ${target.cliPluginNames.length === 1 ? \"plugin\" : \"plugins\"}`,\n );\n } catch (error) {\n this.log(\"Plugin uninstall failed\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n try {\n await this.removeLocalFiles(target, flags.all);\n } catch (error) {\n this.log(\"Failed to remove local files\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} has been uninstalled.`);\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.UNINSTALL_COMPLETE);\n this.log(\"\");\n }\n\n private async removeLocalFiles(target: UninstallTarget, removeAll: boolean): Promise<void> {\n await this.removeMatchingSkills(target);\n await this.removeMatchingAgents(target);\n\n if (removeAll && target.hasClaudeSrcDir) {\n await remove(target.claudeSrcDir);\n this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);\n }\n\n await this.removeEmptyClaudeDir(target);\n }\n\n private async removeMatchingSkills(target: UninstallTarget): Promise<void> {\n if (!target.hasLocalSkills) return;\n\n const skillDirNames = await listDirectories(target.skillsDir);\n let removedCount = 0;\n let skippedCount = 0;\n\n for (const skillDirName of skillDirNames) {\n const skillDir = path.join(target.skillsDir, skillDirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n if (shouldRemoveSkill(forkedFrom, target.configuredSources, target.config !== null)) {\n await remove(skillDir);\n removedCount++;\n this.log(` Uninstalled skill '${skillDirName}'`);\n } else {\n this.warn(`Skipping '${skillDirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`);\n skippedCount++;\n }\n }\n\n if (removedCount > 0) {\n this.logSuccess(\n `Removed ${removedCount} CLI-installed ${removedCount === 1 ? \"skill\" : \"skills\"}`,\n );\n }\n\n if (skippedCount > 0) return;\n if (!(await directoryExists(target.skillsDir))) return;\n if (await isDirectoryEmpty(target.skillsDir)) {\n await remove(target.skillsDir);\n }\n }\n\n private async removeMatchingAgents(target: UninstallTarget): Promise<void> {\n if (!target.hasLocalAgents) return;\n if (target.configuredAgents.length === 0) return;\n\n const agentFiles = await this.listAgentFiles(target.agentsDir);\n let removedCount = 0;\n\n for (const agentFile of agentFiles) {\n const agentName = agentFile.replace(/\\.md$/, \"\");\n if (!target.configuredAgents.includes(agentName)) continue;\n\n await remove(path.join(target.agentsDir, agentFile));\n this.log(` Uninstalled agent '${agentName}'`);\n removedCount++;\n }\n\n if (removedCount > 0) {\n this.logSuccess(\n `Removed ${removedCount} compiled ${removedCount === 1 ? \"agent\" : \"agents\"}`,\n );\n }\n\n if (!(await directoryExists(target.agentsDir))) return;\n if (await isDirectoryEmpty(target.agentsDir)) {\n await remove(target.agentsDir);\n }\n }\n\n private async listAgentFiles(agentsDir: string): Promise<string[]> {\n try {\n const { readdir } = await import(\"fs/promises\");\n return (await readdir(agentsDir)).filter((f) => f.endsWith(\".md\"));\n } catch {\n return [];\n }\n }\n\n private async removeEmptyClaudeDir(target: UninstallTarget): Promise<void> {\n if (!target.hasClaudeDir) return;\n if (!(await directoryExists(target.claudeDir))) return;\n\n if (await isDirectoryEmpty(target.claudeDir)) {\n await remove(target.claudeDir);\n this.logSuccess(`Removed ${CLAUDE_DIR}/`);\n } else {\n this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/uninstall.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags } from \"@oclif/core\";\nimport { render, Box, Text, useApp } from \"ink\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../base-command\";\nimport { Confirm } from \"../components/common/confirm\";\nimport { getErrorMessage } from \"../utils/errors\";\nimport { directoryExists, listDirectories, remove } from \"../utils/fs\";\nimport { claudePluginUninstall, isClaudeCLIAvailable } from \"../utils/exec\";\nimport { listPluginNames, getProjectPluginsDir } from \"../lib/plugins\";\nimport { readForkedFromMetadata } from \"../lib/skills\";\nimport { loadProjectConfigFromDir } from \"../lib/configuration/project-config\";\nimport type { ProjectConfig } from \"../types\";\nimport { CLAUDE_DIR, CLAUDE_SRC_DIR, CLI_COLORS, DEFAULT_BRANDING } from \"../consts\";\nimport { EXIT_CODES } from \"../lib/exit-codes\";\nimport { SUCCESS_MESSAGES, INFO_MESSAGES } from \"../utils/messages\";\n\ntype UninstallTarget = {\n hasPlugins: boolean;\n pluginNames: string[];\n /** Plugin names filtered to only those installed by this CLI (matched against config skills) */\n cliPluginNames: string[];\n hasLocalSkills: boolean;\n hasLocalAgents: boolean;\n hasClaudeDir: boolean;\n hasClaudeSrcDir: boolean;\n pluginsDir: string;\n skillsDir: string;\n agentsDir: string;\n claudeDir: string;\n claudeSrcDir: string;\n /** Resolved project source config from .claude-src/config.ts */\n config: Partial<ProjectConfig> | null;\n /** Agent names from the generated config (e.g., [\"web-developer\"]) */\n configuredAgents: string[];\n};\n\nfunction collectConfiguredAgents(config: Partial<ProjectConfig> | null): string[] {\n if (!config?.agents) return [];\n return config.agents.map((a) => a.name);\n}\n\nfunction getCliInstalledPluginKeys(config: Partial<ProjectConfig> | null): Set<string> {\n if (!config?.skills) return new Set();\n return new Set(config.skills.map((skill) => `${skill.id}@${skill.source}`));\n}\n\nasync function detectUninstallTarget(projectDir: string): Promise<UninstallTarget> {\n const pluginsDir = getProjectPluginsDir(projectDir);\n const skillsDir = path.join(projectDir, CLAUDE_DIR, \"skills\");\n const agentsDir = path.join(projectDir, CLAUDE_DIR, \"agents\");\n const claudeDir = path.join(projectDir, CLAUDE_DIR);\n const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);\n\n const [hasLocalSkills, hasLocalAgents, hasClaudeDir, hasClaudeSrcDir, config] = await Promise.all(\n [\n directoryExists(skillsDir),\n directoryExists(agentsDir),\n directoryExists(claudeDir),\n directoryExists(claudeSrcDir),\n loadProjectConfigFromDir(projectDir).then((result) => result?.config ?? null),\n ],\n );\n\n let pluginNames: string[] = [];\n try {\n pluginNames = await listPluginNames(projectDir);\n } catch {\n // Best-effort: plugin detection may fail\n }\n\n const configuredAgents = collectConfiguredAgents(config);\n const cliInstalledKeys = getCliInstalledPluginKeys(config);\n const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));\n\n return {\n hasPlugins: cliPluginNames.length > 0,\n pluginNames,\n cliPluginNames,\n hasLocalSkills,\n hasLocalAgents,\n hasClaudeDir,\n hasClaudeSrcDir,\n pluginsDir,\n skillsDir,\n agentsDir,\n claudeDir,\n claudeSrcDir,\n config,\n configuredAgents,\n };\n}\n\ntype UninstallConfirmProps = {\n target: UninstallTarget;\n removeAll: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UninstallConfirm: React.FC<UninstallConfirmProps> = ({\n target,\n removeAll,\n onConfirm,\n onCancel,\n}) => {\n const { exit } = useApp();\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>The following will be removed:</Text>\n <Text> </Text>\n\n {target.hasPlugins && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Plugins:</Text>\n {target.cliPluginNames.map((name) => (\n <Text key={name} dimColor>\n {\" \"}\n {name}\n </Text>\n ))}\n </Box>\n )}\n\n {(target.hasLocalSkills || target.hasLocalAgents) && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> CLI-managed files:</Text>\n {target.hasLocalSkills && <Text dimColor> {target.skillsDir}/ (matching sources)</Text>}\n {target.hasLocalAgents && <Text dimColor> {target.agentsDir}/ (CLI-compiled)</Text>}\n </Box>\n )}\n\n {removeAll && target.hasClaudeSrcDir && (\n <Box flexDirection=\"column\">\n <Text color={CLI_COLORS.ERROR}> Config:</Text>\n <Text dimColor> {target.claudeSrcDir}/</Text>\n </Box>\n )}\n\n <Text> </Text>\n <Confirm\n message=\"Are you sure you want to uninstall?\"\n onConfirm={() => {\n onConfirm();\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n defaultValue={false}\n />\n </Box>\n );\n};\n\nasync function isDirectoryEmpty(dirPath: string): Promise<boolean> {\n const { readdir } = await import(\"fs/promises\");\n try {\n const allEntries = await readdir(dirPath);\n return allEntries.length === 0;\n } catch {\n return true;\n }\n}\n\nfunction shouldRemoveSkill(forkedFrom: { source?: string } | null): boolean {\n return forkedFrom !== null;\n}\n\nexport default class Uninstall extends BaseCommand {\n static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;\n\n static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by source), compiled agents, and plugins. User-created content is preserved.`;\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --all\",\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n all: Flags.boolean({\n description: \"Also remove .claude-src/ config directory\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Uninstall);\n const projectDir = process.cwd();\n\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} Uninstall`);\n this.log(\"\");\n\n const target = await detectUninstallTarget(projectDir);\n\n const hasAnythingToRemove =\n target.hasPlugins ||\n target.hasLocalSkills ||\n target.hasLocalAgents ||\n (flags.all && target.hasClaudeSrcDir);\n\n if (!hasAnythingToRemove) {\n this.warn(\"Nothing to uninstall.\");\n this.log(\"\");\n this.log(INFO_MESSAGES.NOT_INSTALLED);\n this.log(\"\");\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return;\n }\n\n if (!flags.yes) {\n const confirmed = await new Promise<boolean>((resolve) => {\n const { waitUntilExit } = render(\n <UninstallConfirm\n target={target}\n removeAll={flags.all}\n onConfirm={() => resolve(true)}\n onCancel={() => resolve(false)}\n />,\n );\n\n waitUntilExit().catch(() => resolve(false));\n });\n\n if (!confirmed) {\n this.log(\"\");\n this.log(\"Uninstall cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n } else {\n this.log(\"The following will be removed:\");\n this.log(\"\");\n\n if (target.hasPlugins) {\n this.log(\" Plugins:\");\n for (const pluginName of target.cliPluginNames) {\n this.log(` ${pluginName}`);\n }\n }\n\n if (target.hasLocalSkills || target.hasLocalAgents) {\n this.log(\" CLI-managed files:\");\n if (target.hasLocalSkills) {\n this.log(` ${target.skillsDir}/ (matching sources)`);\n }\n if (target.hasLocalAgents) {\n this.log(` ${target.agentsDir}/ (CLI-compiled)`);\n }\n }\n\n if (flags.all && target.hasClaudeSrcDir) {\n this.log(\" Config:\");\n this.log(` ${target.claudeSrcDir}/`);\n }\n\n this.log(\"\");\n }\n\n if (target.hasPlugins) {\n this.log(\"Uninstalling plugins...\");\n\n try {\n const cliAvailable = await isClaudeCLIAvailable();\n\n for (const pluginName of target.cliPluginNames) {\n if (cliAvailable) {\n try {\n // Derive scope from per-skill config; fall back to project-level heuristic\n const skillId = pluginName.split(\"@\")[0];\n const skillConfig = target.config?.skills?.find((s) => s.id === skillId);\n const pluginScope = skillConfig?.scope === \"global\" ? \"user\" : \"project\";\n await claudePluginUninstall(pluginName, pluginScope, projectDir);\n } catch {\n // Best-effort: plugin may not be registered with Claude CLI\n }\n }\n\n const pluginPath = path.join(target.pluginsDir, pluginName);\n await remove(pluginPath);\n this.log(` Uninstalled plugin '${pluginName}'`);\n }\n\n this.logSuccess(\n `Uninstalled ${target.cliPluginNames.length} ${target.cliPluginNames.length === 1 ? \"plugin\" : \"plugins\"}`,\n );\n } catch (error) {\n this.log(\"Plugin uninstall failed\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n try {\n await this.removeLocalFiles(target, flags.all);\n } catch (error) {\n this.log(\"Failed to remove local files\");\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n this.log(\"\");\n this.log(`${DEFAULT_BRANDING.NAME} has been uninstalled.`);\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.UNINSTALL_COMPLETE);\n this.log(\"\");\n }\n\n private async removeLocalFiles(target: UninstallTarget, removeAll: boolean): Promise<void> {\n await this.removeMatchingSkills(target);\n await this.removeMatchingAgents(target);\n\n if (removeAll && target.hasClaudeSrcDir) {\n await remove(target.claudeSrcDir);\n this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);\n }\n\n await this.removeEmptyClaudeDir(target);\n }\n\n private async removeMatchingSkills(target: UninstallTarget): Promise<void> {\n if (!target.hasLocalSkills) return;\n\n const skillDirNames = await listDirectories(target.skillsDir);\n let removedCount = 0;\n let skippedCount = 0;\n\n for (const skillDirName of skillDirNames) {\n const skillDir = path.join(target.skillsDir, skillDirName);\n const forkedFrom = await readForkedFromMetadata(skillDir);\n\n if (shouldRemoveSkill(forkedFrom)) {\n await remove(skillDir);\n removedCount++;\n this.log(` Uninstalled skill '${skillDirName}'`);\n } else {\n this.warn(`Skipping '${skillDirName}': not created by ${DEFAULT_BRANDING.NAME} CLI`);\n skippedCount++;\n }\n }\n\n if (removedCount > 0) {\n this.logSuccess(\n `Removed ${removedCount} CLI-installed ${removedCount === 1 ? \"skill\" : \"skills\"}`,\n );\n }\n\n if (skippedCount > 0) return;\n if (!(await directoryExists(target.skillsDir))) return;\n if (await isDirectoryEmpty(target.skillsDir)) {\n await remove(target.skillsDir);\n }\n }\n\n private async removeMatchingAgents(target: UninstallTarget): Promise<void> {\n if (!target.hasLocalAgents) return;\n if (target.configuredAgents.length === 0) return;\n\n const agentFiles = await this.listAgentFiles(target.agentsDir);\n let removedCount = 0;\n\n for (const agentFile of agentFiles) {\n const agentName = agentFile.replace(/\\.md$/, \"\");\n if (!target.configuredAgents.includes(agentName)) continue;\n\n await remove(path.join(target.agentsDir, agentFile));\n this.log(` Uninstalled agent '${agentName}'`);\n removedCount++;\n }\n\n if (removedCount > 0) {\n this.logSuccess(\n `Removed ${removedCount} compiled ${removedCount === 1 ? \"agent\" : \"agents\"}`,\n );\n }\n\n if (!(await directoryExists(target.agentsDir))) return;\n if (await isDirectoryEmpty(target.agentsDir)) {\n await remove(target.agentsDir);\n }\n }\n\n private async listAgentFiles(agentsDir: string): Promise<string[]> {\n try {\n const { readdir } = await import(\"fs/promises\");\n return (await readdir(agentsDir)).filter((f) => f.endsWith(\".md\"));\n } catch {\n return [];\n }\n }\n\n private async removeEmptyClaudeDir(target: UninstallTarget): Promise<void> {\n if (!target.hasClaudeDir) return;\n if (!(await directoryExists(target.claudeDir))) return;\n\n if (await isDirectoryEmpty(target.claudeDir)) {\n await remove(target.claudeDir);\n this.logSuccess(`Removed ${CLAUDE_DIR}/`);\n } else {\n this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-N6S7ZRIL.js";
5
5
  import {
6
6
  recompileAgents
7
- } from "../chunk-VQV3DSHD.js";
7
+ } from "../chunk-SJNUTUSJ.js";
8
8
  import {
9
9
  ERROR_MESSAGES,
10
10
  INFO_MESSAGES,
@@ -15,26 +15,26 @@ import {
15
15
  compareLocalSkillsWithSource,
16
16
  injectForkedFromMetadata,
17
17
  loadSkillsMatrixFromSource
18
- } from "../chunk-WS3TL2AO.js";
19
- import "../chunk-I534EWJQ.js";
18
+ } from "../chunk-OIHZ2YH3.js";
19
+ import "../chunk-IFCASC6R.js";
20
20
  import {
21
21
  matrix
22
- } from "../chunk-JWMYAJHD.js";
22
+ } from "../chunk-FSK4TQX7.js";
23
23
  import {
24
24
  BaseCommand,
25
25
  EXIT_CODES
26
- } from "../chunk-XYZ7B5BY.js";
26
+ } from "../chunk-7LBYURQR.js";
27
27
  import {
28
28
  copy,
29
29
  fileExists,
30
30
  getErrorMessage
31
- } from "../chunk-WN2TUP4M.js";
32
- import "../chunk-Q4PJSAMP.js";
31
+ } from "../chunk-XYPAOBBV.js";
32
+ import "../chunk-32HX6UYI.js";
33
33
  import {
34
34
  CLI_BIN_NAME,
35
35
  LOCAL_SKILLS_PATH
36
36
  } from "../chunk-FMYAYX6W.js";
37
- import "../chunk-7XUKTYVD.js";
37
+ import "../chunk-EO6KJI5D.js";
38
38
  import {
39
39
  init_esm_shims
40
40
  } from "../chunk-DHET7RCE.js";
@@ -44,6 +44,7 @@ init_esm_shims();
44
44
  import { Flags, Args } from "@oclif/core";
45
45
  import { printTable } from "@oclif/table";
46
46
  import { render } from "ink";
47
+ import os from "os";
47
48
  import path from "path";
48
49
  import { jsx } from "react/jsx-runtime";
49
50
  async function updateSkill(skill, projectDir, sourceResult) {
@@ -129,8 +130,12 @@ var Update = class _Update extends BaseCommand {
129
130
  const projectDir = process.cwd();
130
131
  const shouldRecompile = !flags["no-recompile"];
131
132
  try {
132
- const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);
133
- if (!await fileExists(localSkillsPath)) {
133
+ const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);
134
+ const homeDir = os.homedir();
135
+ const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);
136
+ const hasProject = await fileExists(projectLocalPath);
137
+ const hasGlobal = projectDir !== homeDir && await fileExists(globalLocalPath);
138
+ if (!hasProject && !hasGlobal) {
134
139
  this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);
135
140
  return;
136
141
  }
@@ -149,11 +154,15 @@ var Update = class _Update extends BaseCommand {
149
154
  sourceSkills[skillId] = { path: skill.path };
150
155
  }
151
156
  }
152
- const allResults = await compareLocalSkillsWithSource(
153
- projectDir,
154
- sourceResult.sourcePath,
155
- sourceSkills
156
- );
157
+ const projectResults = hasProject ? await compareLocalSkillsWithSource(projectDir, sourceResult.sourcePath, sourceSkills) : [];
158
+ const globalResults = hasGlobal ? await compareLocalSkillsWithSource(homeDir, sourceResult.sourcePath, sourceSkills) : [];
159
+ const skillBaseDir = /* @__PURE__ */ new Map();
160
+ for (const r of projectResults) skillBaseDir.set(r.id, projectDir);
161
+ for (const r of globalResults) {
162
+ if (!skillBaseDir.has(r.id)) skillBaseDir.set(r.id, homeDir);
163
+ }
164
+ const seenIds = new Set(projectResults.map((r) => r.id));
165
+ const allResults = [...projectResults, ...globalResults.filter((r) => !seenIds.has(r.id))];
157
166
  let outdatedSkills = allResults.filter((r) => r.status === "outdated");
158
167
  if (args.skill) {
159
168
  const foundSkill = findSkillByPartialMatch(args.skill, allResults);
@@ -247,7 +256,8 @@ var Update = class _Update extends BaseCommand {
247
256
  const failed = [];
248
257
  for (const skill of outdatedSkills) {
249
258
  this.log(`Updating ${skill.id}...`);
250
- const result = await updateSkill(skill, projectDir, sourceResult);
259
+ const baseDir = skillBaseDir.get(skill.id) ?? projectDir;
260
+ const result = await updateSkill(skill, baseDir, sourceResult);
251
261
  if (result.success) {
252
262
  this.log(` Updated ${skill.id}`);
253
263
  updated.push(skill.id);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { render } from \"ink\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/loading/index.js\";\nimport { matrix } from \"../lib/matrix/matrix-provider\";\nimport { recompileAgents } from \"../lib/agents/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n compareLocalSkillsWithSource,\n injectForkedFromMetadata,\n type SkillComparisonResult,\n} from \"../lib/skills/index.js\";\nimport { fileExists, copy } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport {\n ERROR_MESSAGES,\n SUCCESS_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n} from \"../utils/messages.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\nasync function updateSkill(\n skill: SkillComparisonResult,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<{ success: boolean; newHash: string | null; error?: string }> {\n if (!skill.sourcePath || !skill.sourceHash) {\n return { success: false, newHash: null, error: \"No source path available\" };\n }\n\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n await copy(srcPath, destPath);\n await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n\n return { success: true, newHash: skill.sourceHash };\n } catch (error) {\n return {\n success: false,\n newHash: null,\n error: getErrorMessage(error),\n };\n }\n}\n\nfunction findSkillByPartialMatch(\n skillName: string,\n results: SkillComparisonResult[],\n): SkillComparisonResult | null {\n const exact = results.find((r) => r.id === skillName);\n if (exact) return exact;\n\n const partial = results.find((r) => {\n const nameWithoutAuthor = r.id.replace(/\\s*\\(@\\w+\\)$/, \"\").toLowerCase();\n return nameWithoutAuthor === skillName.toLowerCase();\n });\n if (partial) return partial;\n\n const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());\n if (byDir) return byDir;\n\n return null;\n}\n\nfunction findSimilarSkills(skillName: string, results: SkillComparisonResult[]): string[] {\n const lowered = skillName.toLowerCase();\n return results\n .filter((r) => {\n const name = r.id.toLowerCase();\n const dir = r.dirName.toLowerCase();\n return (\n name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(\" \")[0])\n );\n })\n .map((r) => r.id)\n .slice(0, 3);\n}\n\ntype UpdateConfirmProps = {\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({ onConfirm, onCancel }) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n if (!(await fileExists(localSkillsPath))) {\n this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);\n return;\n }\n\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n\n const sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(matrix.skills)) {\n if (!skill) continue;\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n const allResults = await compareLocalSkillsWithSource(\n projectDir,\n sourceResult.sourcePath,\n sourceSkills,\n );\n\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n if (args.skill) {\n const foundSkill = findSkillByPartialMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n const similar = findSimilarSkills(args.skill, allResults);\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(`Run \\`${CLI_BIN_NAME} search ${args.skill}\\` to search available skills.`);\n this.log(\"\");\n this.error(ERROR_MESSAGES.SKILL_NOT_FOUND, { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`);\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n outdatedSkills = [foundSkill];\n }\n\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.ALL_SKILLS_UP_TO_DATE);\n this.log(\"\");\n return;\n }\n\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return;\n }\n }\n\n this.log(\"\");\n\n const updated: string[] = [];\n const failed: string[] = [];\n\n for (const skill of outdatedSkills) {\n this.log(`Updating ${skill.id}...`);\n\n const result = await updateSkill(skill, projectDir, sourceResult);\n\n if (result.success) {\n this.log(` Updated ${skill.id}`);\n updated.push(skill.id);\n } else {\n this.log(` Failed to update ${skill.id}: ${result.error}`);\n failed.push(skill.id);\n }\n }\n\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updated.length > 0) {\n this.log(\"\");\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n\n try {\n const recompileResult = await recompileAgents({\n pluginDir: projectDir,\n sourcePath: sourceResult.sourcePath,\n projectDir,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(`Could not recompile agents: ${getErrorMessage(error)}`);\n }\n }\n\n this.log(\"\");\n if (failed.length === 0) {\n const agentMsg =\n recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : \"\";\n this.logSuccess(`Update complete! ${updated.length} skill(s) updated${agentMsg}.`);\n } else {\n this.warn(\n `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`,\n );\n }\n this.log(\"\");\n\n if (failed.length > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/update.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags, Args } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport { render } from \"ink\";\nimport os from \"os\";\nimport path from \"path\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { loadSkillsMatrixFromSource, type SourceLoadResult } from \"../lib/loading/index.js\";\nimport { matrix } from \"../lib/matrix/matrix-provider\";\nimport { recompileAgents } from \"../lib/agents/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n compareLocalSkillsWithSource,\n injectForkedFromMetadata,\n type SkillComparisonResult,\n} from \"../lib/skills/index.js\";\nimport { fileExists, copy } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport {\n ERROR_MESSAGES,\n SUCCESS_MESSAGES,\n STATUS_MESSAGES,\n INFO_MESSAGES,\n} from \"../utils/messages.js\";\nimport { Confirm } from \"../components/common/confirm.js\";\n\nasync function updateSkill(\n skill: SkillComparisonResult,\n projectDir: string,\n sourceResult: SourceLoadResult,\n): Promise<{ success: boolean; newHash: string | null; error?: string }> {\n if (!skill.sourcePath || !skill.sourceHash) {\n return { success: false, newHash: null, error: \"No source path available\" };\n }\n\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const destPath = path.join(localSkillsPath, skill.dirName);\n const srcPath = path.join(sourceResult.sourcePath, \"src\", skill.sourcePath);\n\n try {\n await copy(srcPath, destPath);\n await injectForkedFromMetadata(destPath, skill.id, skill.sourceHash);\n\n return { success: true, newHash: skill.sourceHash };\n } catch (error) {\n return {\n success: false,\n newHash: null,\n error: getErrorMessage(error),\n };\n }\n}\n\nfunction findSkillByPartialMatch(\n skillName: string,\n results: SkillComparisonResult[],\n): SkillComparisonResult | null {\n const exact = results.find((r) => r.id === skillName);\n if (exact) return exact;\n\n const partial = results.find((r) => {\n const nameWithoutAuthor = r.id.replace(/\\s*\\(@\\w+\\)$/, \"\").toLowerCase();\n return nameWithoutAuthor === skillName.toLowerCase();\n });\n if (partial) return partial;\n\n const byDir = results.find((r) => r.dirName.toLowerCase() === skillName.toLowerCase());\n if (byDir) return byDir;\n\n return null;\n}\n\nfunction findSimilarSkills(skillName: string, results: SkillComparisonResult[]): string[] {\n const lowered = skillName.toLowerCase();\n return results\n .filter((r) => {\n const name = r.id.toLowerCase();\n const dir = r.dirName.toLowerCase();\n return (\n name.includes(lowered) || dir.includes(lowered) || lowered.includes(name.split(\" \")[0])\n );\n })\n .map((r) => r.id)\n .slice(0, 3);\n}\n\ntype UpdateConfirmProps = {\n onConfirm: () => void;\n onCancel: () => void;\n};\n\nconst UpdateConfirm: React.FC<UpdateConfirmProps> = ({ onConfirm, onCancel }) => {\n return (\n <Confirm\n message=\"Proceed with update?\"\n onConfirm={onConfirm}\n onCancel={onCancel}\n defaultValue={false}\n />\n );\n};\n\nexport default class Update extends BaseCommand {\n static summary = \"Update local skills from source\";\n\n static description =\n \"Update local skills from the source repository. By default, checks all skills for updates. Specify a skill name to update only that skill.\";\n\n static args = {\n skill: Args.string({\n description: \"Specific skill to update (optional)\",\n required: false,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n yes: Flags.boolean({\n char: \"y\",\n description: \"Skip confirmation prompt\",\n default: false,\n }),\n \"no-recompile\": Flags.boolean({\n description: \"Skip agent recompilation after update\",\n default: false,\n }),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"<%= config.bin %> <%= command.id %> my-skill\",\n \"<%= config.bin %> <%= command.id %> --yes\",\n \"<%= config.bin %> <%= command.id %> --source /path/to/marketplace\",\n \"<%= config.bin %> <%= command.id %> --no-recompile\",\n ];\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Update);\n const projectDir = process.cwd();\n const shouldRecompile = !flags[\"no-recompile\"];\n\n try {\n const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const homeDir = os.homedir();\n const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);\n const hasProject = await fileExists(projectLocalPath);\n const hasGlobal = projectDir !== homeDir && (await fileExists(globalLocalPath));\n\n if (!hasProject && !hasGlobal) {\n this.warn(ERROR_MESSAGES.NO_LOCAL_SKILLS);\n return;\n }\n\n this.log(STATUS_MESSAGES.LOADING_SKILLS);\n\n const sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n this.log(\n `Loaded from ${sourceResult.isLocal ? \"local\" : \"remote\"}: ${sourceResult.sourcePath}`,\n );\n\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of Object.entries(matrix.skills)) {\n if (!skill) continue;\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Check both project-scoped and global-scoped local skills\n const projectResults = hasProject\n ? await compareLocalSkillsWithSource(projectDir, sourceResult.sourcePath, sourceSkills)\n : [];\n const globalResults = hasGlobal\n ? await compareLocalSkillsWithSource(homeDir, sourceResult.sourcePath, sourceSkills)\n : [];\n\n // Track which base dir each skill lives in (for updateSkill dest path)\n const skillBaseDir = new Map<string, string>();\n for (const r of projectResults) skillBaseDir.set(r.id, projectDir);\n for (const r of globalResults) {\n if (!skillBaseDir.has(r.id)) skillBaseDir.set(r.id, homeDir);\n }\n\n // Merge results, project-scoped takes precedence\n const seenIds = new Set(projectResults.map((r) => r.id));\n const allResults = [...projectResults, ...globalResults.filter((r) => !seenIds.has(r.id))];\n\n let outdatedSkills = allResults.filter((r) => r.status === \"outdated\");\n\n if (args.skill) {\n const foundSkill = findSkillByPartialMatch(args.skill, allResults);\n\n if (!foundSkill) {\n this.log(\"\");\n this.log(`Error: Skill \"${args.skill}\" not found.`);\n this.log(\"\");\n\n const similar = findSimilarSkills(args.skill, allResults);\n if (similar.length > 0) {\n this.log(\"Did you mean one of these?\");\n for (const name of similar) {\n this.log(` - ${name}`);\n }\n this.log(\"\");\n }\n\n this.log(`Run \\`${CLI_BIN_NAME} search ${args.skill}\\` to search available skills.`);\n this.log(\"\");\n this.error(ERROR_MESSAGES.SKILL_NOT_FOUND, { exit: EXIT_CODES.ERROR });\n }\n\n if (foundSkill.status === \"current\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is already up to date.`);\n this.log(\"\");\n this.log(` Local hash: ${foundSkill.localHash}`);\n this.log(` Source hash: ${foundSkill.sourceHash}`);\n this.log(\"\");\n return;\n }\n\n if (foundSkill.status === \"local-only\") {\n this.log(\"\");\n this.log(`Skill \"${foundSkill.id}\" is a local-only skill (not forked from source).`);\n this.log(\"Cannot update local-only skills.\");\n this.log(\"\");\n return;\n }\n\n outdatedSkills = [foundSkill];\n }\n\n if (outdatedSkills.length === 0) {\n this.log(\"\");\n this.logSuccess(SUCCESS_MESSAGES.ALL_SKILLS_UP_TO_DATE);\n this.log(\"\");\n return;\n }\n\n this.log(\"\");\n this.log(\"The following skills will be updated:\");\n this.log(\"\");\n\n printTable({\n data: outdatedSkills.map((skill) => ({\n skill: skill.id,\n localHash: skill.localHash ?? \"-\",\n sourceHash: skill.sourceHash ?? \"-\",\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`${outdatedSkills.length} skill(s) will be updated.`);\n this.log(\"\");\n\n if (!flags.yes) {\n let confirmed = false;\n let cancelled = false;\n\n const { waitUntilExit } = render(\n <UpdateConfirm\n onConfirm={() => {\n confirmed = true;\n }}\n onCancel={() => {\n cancelled = true;\n }}\n />,\n );\n\n await waitUntilExit();\n\n if (cancelled) {\n this.log(\"Update cancelled\");\n this.exit(EXIT_CODES.CANCELLED);\n }\n\n if (!confirmed) {\n this.log(INFO_MESSAGES.NO_CHANGES_MADE);\n return;\n }\n }\n\n this.log(\"\");\n\n const updated: string[] = [];\n const failed: string[] = [];\n\n for (const skill of outdatedSkills) {\n this.log(`Updating ${skill.id}...`);\n\n const baseDir = skillBaseDir.get(skill.id) ?? projectDir;\n const result = await updateSkill(skill, baseDir, sourceResult);\n\n if (result.success) {\n this.log(` Updated ${skill.id}`);\n updated.push(skill.id);\n } else {\n this.log(` Failed to update ${skill.id}: ${result.error}`);\n failed.push(skill.id);\n }\n }\n\n let recompiledAgents: string[] = [];\n\n if (shouldRecompile && updated.length > 0) {\n this.log(\"\");\n this.log(STATUS_MESSAGES.RECOMPILING_AGENTS);\n\n try {\n const recompileResult = await recompileAgents({\n pluginDir: projectDir,\n sourcePath: sourceResult.sourcePath,\n projectDir,\n });\n\n recompiledAgents = recompileResult.compiled;\n\n if (recompiledAgents.length > 0) {\n this.log(\"Agents recompiled\");\n for (const agent of recompiledAgents) {\n this.log(` Recompiled: ${agent}`);\n }\n } else {\n this.log(INFO_MESSAGES.NO_AGENTS_TO_RECOMPILE);\n }\n\n if (recompileResult.warnings.length > 0) {\n for (const warning of recompileResult.warnings) {\n this.warn(warning);\n }\n }\n } catch (error) {\n this.warn(\"Agent recompilation failed\");\n this.warn(`Could not recompile agents: ${getErrorMessage(error)}`);\n }\n }\n\n this.log(\"\");\n if (failed.length === 0) {\n const agentMsg =\n recompiledAgents.length > 0 ? `, ${recompiledAgents.length} agent(s) recompiled` : \"\";\n this.logSuccess(`Update complete! ${updated.length} skill(s) updated${agentMsg}.`);\n } else {\n this.warn(\n `Update finished with errors: ${updated.length} updated, ${failed.length} failed.`,\n );\n }\n this.log(\"\");\n\n if (failed.length > 0) {\n this.error(\"Some updates failed\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n this.error(`Update failed: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -11,17 +11,17 @@ import {
11
11
  validateAllPlugins,
12
12
  validateAllSchemas,
13
13
  validatePlugin
14
- } from "../chunk-WS3TL2AO.js";
14
+ } from "../chunk-OIHZ2YH3.js";
15
15
  import {
16
16
  parseFrontmatter
17
- } from "../chunk-I534EWJQ.js";
17
+ } from "../chunk-IFCASC6R.js";
18
18
  import {
19
19
  matrix
20
- } from "../chunk-JWMYAJHD.js";
20
+ } from "../chunk-FSK4TQX7.js";
21
21
  import {
22
22
  BaseCommand,
23
23
  EXIT_CODES
24
- } from "../chunk-XYZ7B5BY.js";
24
+ } from "../chunk-7LBYURQR.js";
25
25
  import {
26
26
  SKILL_ID_PATTERN,
27
27
  directoryExists,
@@ -31,14 +31,14 @@ import {
31
31
  metadataValidationSchema,
32
32
  readFile,
33
33
  setVerbose
34
- } from "../chunk-WN2TUP4M.js";
35
- import "../chunk-Q4PJSAMP.js";
34
+ } from "../chunk-XYPAOBBV.js";
35
+ import "../chunk-32HX6UYI.js";
36
36
  import {
37
37
  SKILLS_DIR_PATH,
38
38
  SKILL_CATEGORIES_PATH,
39
39
  STANDARD_FILES
40
40
  } from "../chunk-FMYAYX6W.js";
41
- import "../chunk-7XUKTYVD.js";
41
+ import "../chunk-EO6KJI5D.js";
42
42
  import {
43
43
  init_esm_shims
44
44
  } from "../chunk-DHET7RCE.js";
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SkillSearch
4
- } from "../../chunk-CCSU4R65.js";
4
+ } from "../../chunk-MG55NDVG.js";
5
5
  import "../../chunk-3REKTRAN.js";
6
6
  import "../../chunk-U3IGFMCY.js";
7
- import "../../chunk-CBYRFAUN.js";
7
+ import "../../chunk-HK53FRMU.js";
8
8
  import "../../chunk-FMYAYX6W.js";
9
9
  import "../../chunk-DHET7RCE.js";
10
10
  export {
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CategoryGrid
4
- } from "../../chunk-7NACNRFG.js";
4
+ } from "../../chunk-W46L2PXK.js";
5
5
  import "../../chunk-P2FHS5IS.js";
6
6
  import "../../chunk-FFMWFEUH.js";
7
- import "../../chunk-CBYRFAUN.js";
8
- import "../../chunk-JWMYAJHD.js";
7
+ import "../../chunk-HK53FRMU.js";
8
+ import "../../chunk-FSK4TQX7.js";
9
9
  import "../../chunk-FMYAYX6W.js";
10
10
  import "../../chunk-DHET7RCE.js";
11
11
  export {
@@ -14,9 +14,9 @@ import {
14
14
  } from "../../chunk-66UDJBF6.js";
15
15
  import {
16
16
  CATEGORY_GRID_MATRIX
17
- } from "../../chunk-6F3CZLD6.js";
18
- import "../../chunk-M4ZDKHJV.js";
19
- import "../../chunk-WMMU5FOO.js";
17
+ } from "../../chunk-XA7WF3BI.js";
18
+ import "../../chunk-MUCQ27HV.js";
19
+ import "../../chunk-FUWUCKES.js";
20
20
  import {
21
21
  afterEach,
22
22
  beforeEach,
@@ -27,21 +27,21 @@ import {
27
27
  } from "../../chunk-XY3XDVMI.js";
28
28
  import {
29
29
  CategoryGrid
30
- } from "../../chunk-7NACNRFG.js";
30
+ } from "../../chunk-W46L2PXK.js";
31
31
  import "../../chunk-P2FHS5IS.js";
32
32
  import "../../chunk-FFMWFEUH.js";
33
- import "../../chunk-PRG7PKZM.js";
34
- import "../../chunk-CBYRFAUN.js";
35
- import "../../chunk-WS3TL2AO.js";
36
- import "../../chunk-I534EWJQ.js";
33
+ import "../../chunk-N34D3ROY.js";
34
+ import "../../chunk-HK53FRMU.js";
35
+ import "../../chunk-OIHZ2YH3.js";
36
+ import "../../chunk-IFCASC6R.js";
37
37
  import {
38
38
  BUILT_IN_MATRIX,
39
39
  initializeMatrix
40
- } from "../../chunk-JWMYAJHD.js";
41
- import "../../chunk-WN2TUP4M.js";
42
- import "../../chunk-Q4PJSAMP.js";
40
+ } from "../../chunk-FSK4TQX7.js";
41
+ import "../../chunk-XYPAOBBV.js";
42
+ import "../../chunk-32HX6UYI.js";
43
43
  import "../../chunk-FMYAYX6W.js";
44
- import "../../chunk-7XUKTYVD.js";
44
+ import "../../chunk-EO6KJI5D.js";
45
45
  import {
46
46
  init_esm_shims
47
47
  } from "../../chunk-DHET7RCE.js";
@@ -513,7 +513,7 @@ describe("CategoryGrid component", () => {
513
513
  await delay(INPUT_DELAY_MS);
514
514
  globalExpect(onFocusChange).toHaveBeenCalledWith(0, 1);
515
515
  });
516
- it("should call onFocusChange when pressing up arrow (wraps to framework when locked)", async () => {
516
+ it("should call onFocusChange when pressing up arrow (wraps to last row)", async () => {
517
517
  const onFocusChange = vi.fn();
518
518
  const { stdin, unmount } = renderGrid({
519
519
  defaultFocusedRow: 0,
@@ -524,7 +524,7 @@ describe("CategoryGrid component", () => {
524
524
  await delay(RENDER_DELAY_MS);
525
525
  await stdin.write(ARROW_UP);
526
526
  await delay(INPUT_DELAY_MS);
527
- globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
527
+ globalExpect(onFocusChange).toHaveBeenCalledWith(4, 0);
528
528
  });
529
529
  it("should navigate between sections when unlocked", async () => {
530
530
  const onFocusChange = vi.fn();
@@ -703,17 +703,16 @@ describe("CategoryGrid component", () => {
703
703
  await delay(INPUT_DELAY_MS);
704
704
  globalExpect(onToggle).toHaveBeenCalled();
705
705
  });
706
- it("should bounce focus away from locked sections on mount", async () => {
706
+ it("should keep focus on initial row when no sections are locked", async () => {
707
707
  const onFocusChange = vi.fn();
708
708
  const { unmount } = renderGrid({
709
709
  defaultFocusedRow: 1,
710
- // Styling (locked)
711
710
  defaultFocusedCol: 0,
712
711
  onFocusChange
713
712
  });
714
713
  cleanup = unmount;
715
714
  await delay(RENDER_DELAY_MS);
716
- globalExpect(onFocusChange).toHaveBeenCalledWith(0, 0);
715
+ globalExpect(onFocusChange).not.toHaveBeenCalled();
717
716
  });
718
717
  });
719
718
  describe("discouraged options navigation", () => {
@@ -812,7 +811,7 @@ describe("CategoryGrid component", () => {
812
811
  await delay(INPUT_DELAY_MS);
813
812
  globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
814
813
  });
815
- it("should only jump to unlocked sections", async () => {
814
+ it("should jump to next section on Tab", async () => {
816
815
  const onFocusChange = vi.fn();
817
816
  const { stdin, unmount } = renderGrid({
818
817
  defaultFocusedRow: 0,
@@ -823,7 +822,7 @@ describe("CategoryGrid component", () => {
823
822
  await delay(RENDER_DELAY_MS);
824
823
  await stdin.write(TAB);
825
824
  await delay(INPUT_DELAY_MS);
826
- globalExpect(onFocusChange).not.toHaveBeenCalled();
825
+ globalExpect(onFocusChange).toHaveBeenCalledWith(1, 0);
827
826
  });
828
827
  });
829
828
  describe("compatibility labels toggle", () => {