@agents-inc/cli 0.88.0 → 0.91.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 (237) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/{chunk-RWVF6DQE.js → chunk-2RFE7LTV.js} +3 -3
  3. package/dist/{chunk-ZFQTKY2S.js → chunk-2RXDM5HN.js} +5 -5
  4. package/dist/chunk-2RXDM5HN.js.map +1 -0
  5. package/dist/{chunk-CKZ65VFJ.js → chunk-35WALWDD.js} +5 -5
  6. package/dist/chunk-35WALWDD.js.map +1 -0
  7. package/dist/{chunk-BEZ6ZPDS.js → chunk-3O57Z6Q3.js} +3 -3
  8. package/dist/{chunk-2DRPZXXK.js → chunk-3STOCHK4.js} +4 -4
  9. package/dist/{chunk-ANXHMG32.js → chunk-47HMJ4BY.js} +28 -1
  10. package/dist/chunk-47HMJ4BY.js.map +1 -0
  11. package/dist/{chunk-LHUK5L6P.js → chunk-4DZNTUK7.js} +23 -10
  12. package/dist/chunk-4DZNTUK7.js.map +1 -0
  13. package/dist/{chunk-REZZSDXG.js → chunk-5IR4QU7G.js} +37 -24
  14. package/dist/chunk-5IR4QU7G.js.map +1 -0
  15. package/dist/{chunk-TAPEVEET.js → chunk-7K7SA4TZ.js} +2 -2
  16. package/dist/chunk-7QWCPF6F.js +135 -0
  17. package/dist/chunk-7QWCPF6F.js.map +1 -0
  18. package/dist/{chunk-WTPPVXJP.js → chunk-AWB6DO24.js} +17 -10
  19. package/dist/chunk-AWB6DO24.js.map +1 -0
  20. package/dist/{chunk-SB2R5KHJ.js → chunk-BGICSUQK.js} +2 -2
  21. package/dist/{chunk-HK53FRMU.js → chunk-DVBA6PGR.js} +3 -7
  22. package/dist/{chunk-HK53FRMU.js.map → chunk-DVBA6PGR.js.map} +1 -1
  23. package/dist/{chunk-YM3V4Q3W.js → chunk-DZ2IQERZ.js} +5 -5
  24. package/dist/{chunk-I5AZKNNL.js → chunk-FEKVKYCN.js} +2 -2
  25. package/dist/{chunk-EADZIYQW.js → chunk-FVBSRBU3.js} +30 -21
  26. package/dist/chunk-FVBSRBU3.js.map +1 -0
  27. package/dist/{chunk-6YR2NEW3.js → chunk-G3VPBEBC.js} +2 -2
  28. package/dist/{chunk-JNUFQBXX.js → chunk-HCSIS35Y.js} +2 -2
  29. package/dist/{chunk-NPMMU4GY.js → chunk-IR7ADPAZ.js} +56 -1
  30. package/dist/chunk-IR7ADPAZ.js.map +1 -0
  31. package/dist/{chunk-AP4DLJDP.js → chunk-JBS4CCJG.js} +2 -2
  32. package/dist/chunk-M6J5YQ3P.js +100 -0
  33. package/dist/chunk-M6J5YQ3P.js.map +1 -0
  34. package/dist/{chunk-23M3SPXX.js → chunk-MBEXASMU.js} +8 -8
  35. package/dist/{chunk-TEA5KBIA.js → chunk-NESVWSI7.js} +2 -2
  36. package/dist/{chunk-ZTRQO5CX.js → chunk-OOHPUT5M.js} +2 -2
  37. package/dist/{chunk-V36FRPAU.js → chunk-ORTNQZLF.js} +4 -2
  38. package/dist/{chunk-V36FRPAU.js.map → chunk-ORTNQZLF.js.map} +1 -1
  39. package/dist/{chunk-ANZV33N5.js → chunk-OVY7IV3C.js} +2 -2
  40. package/dist/{chunk-ITBSJNIC.js → chunk-Q3NIGPRZ.js} +3 -3
  41. package/dist/{chunk-5IYZGJDW.js → chunk-RDQBXB3Y.js} +6 -6
  42. package/dist/{chunk-MY4TVLRB.js → chunk-TJHCK4OS.js} +4 -4
  43. package/dist/{chunk-PZBLGD7O.js → chunk-UCORQ7YO.js} +2 -2
  44. package/dist/{chunk-NL5EB57E.js → chunk-UHARXISZ.js} +4 -4
  45. package/dist/chunk-UHARXISZ.js.map +1 -0
  46. package/dist/{chunk-57KI55GJ.js → chunk-UK572773.js} +3 -3
  47. package/dist/{chunk-DDCW4SKN.js → chunk-V75HVZTB.js} +7 -6
  48. package/dist/chunk-V75HVZTB.js.map +1 -0
  49. package/dist/{chunk-6XWHJHNZ.js → chunk-WEYWZ7UE.js} +4 -1
  50. package/dist/chunk-WEYWZ7UE.js.map +1 -0
  51. package/dist/{chunk-STMRDPGZ.js → chunk-XM2Y5AFQ.js} +2 -2
  52. package/dist/commands/build/marketplace.js +62 -44
  53. package/dist/commands/build/marketplace.js.map +1 -1
  54. package/dist/commands/build/plugins.js +46 -37
  55. package/dist/commands/build/plugins.js.map +1 -1
  56. package/dist/commands/build/stack.js +43 -35
  57. package/dist/commands/build/stack.js.map +1 -1
  58. package/dist/commands/compile.js +44 -41
  59. package/dist/commands/compile.js.map +1 -1
  60. package/dist/commands/config/index.js +8 -8
  61. package/dist/commands/config/path.js +7 -7
  62. package/dist/commands/config/show.js +8 -8
  63. package/dist/commands/diff.js +13 -12
  64. package/dist/commands/diff.js.map +1 -1
  65. package/dist/commands/doctor.js +17 -40
  66. package/dist/commands/doctor.js.map +1 -1
  67. package/dist/commands/edit.js +63 -70
  68. package/dist/commands/edit.js.map +1 -1
  69. package/dist/commands/eject.js +9 -9
  70. package/dist/commands/import/skill.js +60 -50
  71. package/dist/commands/import/skill.js.map +1 -1
  72. package/dist/commands/info.js +9 -9
  73. package/dist/commands/init.js +28 -29
  74. package/dist/commands/list.js +7 -7
  75. package/dist/commands/new/agent.js +8 -8
  76. package/dist/commands/new/marketplace.js +98 -83
  77. package/dist/commands/new/marketplace.js.map +1 -1
  78. package/dist/commands/new/skill.js +7 -7
  79. package/dist/commands/outdated.js +91 -100
  80. package/dist/commands/outdated.js.map +1 -1
  81. package/dist/commands/search.js +11 -11
  82. package/dist/commands/uninstall.js +40 -31
  83. package/dist/commands/uninstall.js.map +1 -1
  84. package/dist/commands/update.js +9 -9
  85. package/dist/commands/validate.js +7 -7
  86. package/dist/components/skill-search/skill-search.js +2 -2
  87. package/dist/components/wizard/category-grid.js +3 -3
  88. package/dist/components/wizard/category-grid.test.js +12 -12
  89. package/dist/components/wizard/domain-selection.js +9 -9
  90. package/dist/components/wizard/info-panel.js +18 -0
  91. package/dist/components/wizard/search-modal.js +2 -2
  92. package/dist/components/wizard/search-modal.test.js +2 -2
  93. package/dist/components/wizard/source-grid.js +4 -4
  94. package/dist/components/wizard/source-grid.test.js +13 -13
  95. package/dist/components/wizard/stack-selection.js +8 -8
  96. package/dist/components/wizard/stats-panel.js +106 -5
  97. package/dist/components/wizard/stats-panel.js.map +1 -1
  98. package/dist/components/wizard/step-agents.js +9 -9
  99. package/dist/components/wizard/step-agents.test.js +12 -12
  100. package/dist/components/wizard/step-build.js +10 -11
  101. package/dist/components/wizard/step-build.test.js +13 -14
  102. package/dist/components/wizard/step-build.test.js.map +1 -1
  103. package/dist/components/wizard/step-confirm.js +4 -4
  104. package/dist/components/wizard/step-confirm.test.js +10 -10
  105. package/dist/components/wizard/step-refine.js +2 -2
  106. package/dist/components/wizard/step-refine.test.js +2 -2
  107. package/dist/components/wizard/step-settings.js +8 -8
  108. package/dist/components/wizard/step-settings.test.js +11 -11
  109. package/dist/components/wizard/step-sources.js +12 -12
  110. package/dist/components/wizard/step-sources.test.js +15 -15
  111. package/dist/components/wizard/step-stack.js +9 -9
  112. package/dist/components/wizard/step-stack.test.js +10 -10
  113. package/dist/components/wizard/wizard-layout.js +12 -12
  114. package/dist/components/wizard/wizard.js +24 -25
  115. package/dist/config-exports.js +1 -1
  116. package/dist/hooks/init.js +28 -29
  117. package/dist/hooks/init.js.map +1 -1
  118. package/dist/{loader-SQOK2BF7.js → loader-D5VE56SI.js} +4 -4
  119. package/dist/{source-loader-CCECAU5L.js → source-loader-INCCYL5P.js} +7 -7
  120. package/dist/source-manager-TEOUO734.js +19 -0
  121. package/dist/src/agents/developer/ai-developer/critical-reminders.md +31 -0
  122. package/dist/src/agents/developer/ai-developer/critical-requirements.md +17 -0
  123. package/dist/src/agents/developer/ai-developer/examples.md +137 -0
  124. package/dist/src/agents/developer/ai-developer/intro.md +23 -0
  125. package/dist/src/agents/developer/ai-developer/metadata.yaml +12 -0
  126. package/dist/src/agents/developer/ai-developer/output-format.md +228 -0
  127. package/dist/src/agents/developer/ai-developer/workflow.md +464 -0
  128. package/dist/src/agents/planning/api-pm/critical-reminders.md +32 -0
  129. package/dist/src/agents/planning/api-pm/critical-requirements.md +21 -0
  130. package/dist/src/agents/planning/api-pm/examples.md +157 -0
  131. package/dist/src/agents/planning/api-pm/intro.md +14 -0
  132. package/dist/src/agents/planning/api-pm/metadata.yaml +12 -0
  133. package/dist/src/agents/planning/api-pm/output-format.md +317 -0
  134. package/dist/src/agents/planning/api-pm/workflow.md +214 -0
  135. package/dist/src/agents/reviewer/ai-reviewer/critical-reminders.md +23 -0
  136. package/dist/src/agents/reviewer/ai-reviewer/critical-requirements.md +19 -0
  137. package/dist/src/agents/reviewer/ai-reviewer/examples.md +131 -0
  138. package/dist/src/agents/reviewer/ai-reviewer/intro.md +23 -0
  139. package/dist/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
  140. package/dist/src/agents/reviewer/ai-reviewer/output-format.md +263 -0
  141. package/dist/src/agents/reviewer/ai-reviewer/workflow.md +177 -0
  142. package/dist/src/agents/reviewer/infra-reviewer/critical-reminders.md +21 -0
  143. package/dist/src/agents/reviewer/infra-reviewer/critical-requirements.md +19 -0
  144. package/dist/src/agents/reviewer/infra-reviewer/examples.md +123 -0
  145. package/dist/src/agents/reviewer/infra-reviewer/intro.md +25 -0
  146. package/dist/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
  147. package/dist/src/agents/reviewer/infra-reviewer/output-format.md +240 -0
  148. package/dist/src/agents/reviewer/infra-reviewer/workflow.md +250 -0
  149. package/dist/src/agents/tester/api-tester/critical-reminders.md +23 -0
  150. package/dist/src/agents/tester/api-tester/critical-requirements.md +19 -0
  151. package/dist/src/agents/tester/api-tester/examples.md +74 -0
  152. package/dist/src/agents/tester/api-tester/intro.md +21 -0
  153. package/dist/src/agents/tester/api-tester/metadata.yaml +12 -0
  154. package/dist/src/agents/tester/api-tester/output-format.md +209 -0
  155. package/dist/src/agents/tester/api-tester/workflow.md +364 -0
  156. package/dist/stores/wizard-store.js +7 -7
  157. package/dist/stores/wizard-store.test.js +26 -26
  158. package/dist/stores/wizard-store.test.js.map +1 -1
  159. package/package.json +1 -1
  160. package/src/agents/developer/ai-developer/critical-reminders.md +31 -0
  161. package/src/agents/developer/ai-developer/critical-requirements.md +17 -0
  162. package/src/agents/developer/ai-developer/examples.md +137 -0
  163. package/src/agents/developer/ai-developer/intro.md +23 -0
  164. package/src/agents/developer/ai-developer/metadata.yaml +12 -0
  165. package/src/agents/developer/ai-developer/output-format.md +228 -0
  166. package/src/agents/developer/ai-developer/workflow.md +464 -0
  167. package/src/agents/planning/api-pm/critical-reminders.md +32 -0
  168. package/src/agents/planning/api-pm/critical-requirements.md +21 -0
  169. package/src/agents/planning/api-pm/examples.md +157 -0
  170. package/src/agents/planning/api-pm/intro.md +14 -0
  171. package/src/agents/planning/api-pm/metadata.yaml +12 -0
  172. package/src/agents/planning/api-pm/output-format.md +317 -0
  173. package/src/agents/planning/api-pm/workflow.md +214 -0
  174. package/src/agents/reviewer/ai-reviewer/critical-reminders.md +23 -0
  175. package/src/agents/reviewer/ai-reviewer/critical-requirements.md +19 -0
  176. package/src/agents/reviewer/ai-reviewer/examples.md +131 -0
  177. package/src/agents/reviewer/ai-reviewer/intro.md +23 -0
  178. package/src/agents/reviewer/ai-reviewer/metadata.yaml +10 -0
  179. package/src/agents/reviewer/ai-reviewer/output-format.md +263 -0
  180. package/src/agents/reviewer/ai-reviewer/workflow.md +177 -0
  181. package/src/agents/reviewer/infra-reviewer/critical-reminders.md +21 -0
  182. package/src/agents/reviewer/infra-reviewer/critical-requirements.md +19 -0
  183. package/src/agents/reviewer/infra-reviewer/examples.md +123 -0
  184. package/src/agents/reviewer/infra-reviewer/intro.md +25 -0
  185. package/src/agents/reviewer/infra-reviewer/metadata.yaml +10 -0
  186. package/src/agents/reviewer/infra-reviewer/output-format.md +240 -0
  187. package/src/agents/reviewer/infra-reviewer/workflow.md +250 -0
  188. package/src/agents/tester/api-tester/critical-reminders.md +23 -0
  189. package/src/agents/tester/api-tester/critical-requirements.md +19 -0
  190. package/src/agents/tester/api-tester/examples.md +74 -0
  191. package/src/agents/tester/api-tester/intro.md +21 -0
  192. package/src/agents/tester/api-tester/metadata.yaml +12 -0
  193. package/src/agents/tester/api-tester/output-format.md +209 -0
  194. package/src/agents/tester/api-tester/workflow.md +364 -0
  195. package/dist/chunk-6XWHJHNZ.js.map +0 -1
  196. package/dist/chunk-ANXHMG32.js.map +0 -1
  197. package/dist/chunk-ATPHV3MD.js +0 -143
  198. package/dist/chunk-ATPHV3MD.js.map +0 -1
  199. package/dist/chunk-CKZ65VFJ.js.map +0 -1
  200. package/dist/chunk-DDCW4SKN.js.map +0 -1
  201. package/dist/chunk-EADZIYQW.js.map +0 -1
  202. package/dist/chunk-FQTYF3OU.js +0 -114
  203. package/dist/chunk-FQTYF3OU.js.map +0 -1
  204. package/dist/chunk-LHUK5L6P.js.map +0 -1
  205. package/dist/chunk-NL5EB57E.js.map +0 -1
  206. package/dist/chunk-NPMMU4GY.js.map +0 -1
  207. package/dist/chunk-REZZSDXG.js.map +0 -1
  208. package/dist/chunk-VWTZOBBQ.js +0 -111
  209. package/dist/chunk-VWTZOBBQ.js.map +0 -1
  210. package/dist/chunk-WTPPVXJP.js.map +0 -1
  211. package/dist/chunk-ZFQTKY2S.js.map +0 -1
  212. package/dist/components/wizard/help-modal.js +0 -18
  213. package/dist/source-manager-4P7MTZRR.js +0 -19
  214. /package/dist/{chunk-RWVF6DQE.js.map → chunk-2RFE7LTV.js.map} +0 -0
  215. /package/dist/{chunk-BEZ6ZPDS.js.map → chunk-3O57Z6Q3.js.map} +0 -0
  216. /package/dist/{chunk-2DRPZXXK.js.map → chunk-3STOCHK4.js.map} +0 -0
  217. /package/dist/{chunk-TAPEVEET.js.map → chunk-7K7SA4TZ.js.map} +0 -0
  218. /package/dist/{chunk-SB2R5KHJ.js.map → chunk-BGICSUQK.js.map} +0 -0
  219. /package/dist/{chunk-YM3V4Q3W.js.map → chunk-DZ2IQERZ.js.map} +0 -0
  220. /package/dist/{chunk-I5AZKNNL.js.map → chunk-FEKVKYCN.js.map} +0 -0
  221. /package/dist/{chunk-6YR2NEW3.js.map → chunk-G3VPBEBC.js.map} +0 -0
  222. /package/dist/{chunk-JNUFQBXX.js.map → chunk-HCSIS35Y.js.map} +0 -0
  223. /package/dist/{chunk-AP4DLJDP.js.map → chunk-JBS4CCJG.js.map} +0 -0
  224. /package/dist/{chunk-23M3SPXX.js.map → chunk-MBEXASMU.js.map} +0 -0
  225. /package/dist/{chunk-TEA5KBIA.js.map → chunk-NESVWSI7.js.map} +0 -0
  226. /package/dist/{chunk-ZTRQO5CX.js.map → chunk-OOHPUT5M.js.map} +0 -0
  227. /package/dist/{chunk-ANZV33N5.js.map → chunk-OVY7IV3C.js.map} +0 -0
  228. /package/dist/{chunk-ITBSJNIC.js.map → chunk-Q3NIGPRZ.js.map} +0 -0
  229. /package/dist/{chunk-5IYZGJDW.js.map → chunk-RDQBXB3Y.js.map} +0 -0
  230. /package/dist/{chunk-MY4TVLRB.js.map → chunk-TJHCK4OS.js.map} +0 -0
  231. /package/dist/{chunk-PZBLGD7O.js.map → chunk-UCORQ7YO.js.map} +0 -0
  232. /package/dist/{chunk-57KI55GJ.js.map → chunk-UK572773.js.map} +0 -0
  233. /package/dist/{chunk-STMRDPGZ.js.map → chunk-XM2Y5AFQ.js.map} +0 -0
  234. /package/dist/components/wizard/{help-modal.js.map → info-panel.js.map} +0 -0
  235. /package/dist/{loader-SQOK2BF7.js.map → loader-D5VE56SI.js.map} +0 -0
  236. /package/dist/{source-loader-CCECAU5L.js.map → source-loader-INCCYL5P.js.map} +0 -0
  237. /package/dist/{source-manager-4P7MTZRR.js.map → source-manager-TEOUO734.js.map} +0 -0
@@ -6,27 +6,27 @@ import {
6
6
  import {
7
7
  generateMarketplace,
8
8
  writeMarketplace
9
- } from "../../chunk-PZBLGD7O.js";
9
+ } from "../../chunk-UCORQ7YO.js";
10
10
  import {
11
11
  LOCAL_DEFAULTS,
12
12
  compileAllSkillPlugins,
13
13
  generateConfigSource,
14
14
  loadConfigTypesDataInBackground,
15
15
  regenerateConfigTypes
16
- } from "../../chunk-EADZIYQW.js";
17
- import "../../chunk-STMRDPGZ.js";
18
- import "../../chunk-ANXHMG32.js";
16
+ } from "../../chunk-FVBSRBU3.js";
17
+ import "../../chunk-XM2Y5AFQ.js";
18
+ import "../../chunk-47HMJ4BY.js";
19
19
  import {
20
20
  BaseCommand,
21
21
  EXIT_CODES
22
- } from "../../chunk-TAPEVEET.js";
22
+ } from "../../chunk-7K7SA4TZ.js";
23
23
  import {
24
24
  directoryExists,
25
25
  ensureDir,
26
26
  getErrorMessage,
27
27
  writeFile
28
- } from "../../chunk-ZTRQO5CX.js";
29
- import "../../chunk-6XWHJHNZ.js";
28
+ } from "../../chunk-OOHPUT5M.js";
29
+ import "../../chunk-WEYWZ7UE.js";
30
30
  import {
31
31
  CLAUDE_SRC_DIR,
32
32
  CLI_BIN_NAME,
@@ -38,7 +38,7 @@ import {
38
38
  STACKS_FILE_PATH,
39
39
  STANDARD_FILES
40
40
  } from "../../chunk-6PGL2XMY.js";
41
- import "../../chunk-NPMMU4GY.js";
41
+ import "../../chunk-IR7ADPAZ.js";
42
42
  import {
43
43
  init_esm_shims
44
44
  } from "../../chunk-DHET7RCE.js";
@@ -160,103 +160,118 @@ var NewMarketplace = class _NewMarketplace extends BaseCommand {
160
160
  };
161
161
  async run() {
162
162
  const { args, flags } = await this.parse(_NewMarketplace);
163
- this.log("");
164
- this.log("Create New Marketplace");
165
- this.log("");
166
163
  const parentDir = flags.output ? path.resolve(flags.output) : process.cwd();
167
164
  const useCurrentDir = args.name === ".";
168
165
  const marketplaceName = useCurrentDir ? path.basename(parentDir) : args.name;
169
166
  const marketplaceDir = useCurrentDir ? parentDir : path.join(parentDir, args.name);
170
- const validationError = validateMarketplaceName(marketplaceName);
167
+ this.printHeader();
168
+ this.validateName(marketplaceName, useCurrentDir);
169
+ await this.checkExistingDir(marketplaceDir, useCurrentDir, flags.force);
170
+ this.log(`Marketplace: ${marketplaceName}`);
171
+ this.log(`Directory: ${marketplaceDir}`);
172
+ this.log("");
173
+ try {
174
+ await this.createMarketplaceFiles(marketplaceName, marketplaceDir, flags.force);
175
+ await this.buildMarketplace(marketplaceDir, marketplaceName);
176
+ this.printNextSteps(marketplaceName, useCurrentDir);
177
+ } catch (error) {
178
+ this.handleError(error);
179
+ }
180
+ }
181
+ printHeader() {
182
+ this.log("");
183
+ this.log("Create New Marketplace");
184
+ this.log("");
185
+ }
186
+ validateName(name, useCurrentDir) {
187
+ const validationError = validateMarketplaceName(name);
171
188
  if (validationError) {
172
189
  if (useCurrentDir) {
173
190
  this.error(
174
- `Current directory name '${marketplaceName}' is not valid kebab-case. Rename it or pass an explicit name.`,
191
+ `Current directory name '${name}' is not valid kebab-case. Rename it or pass an explicit name.`,
175
192
  { exit: EXIT_CODES.INVALID_ARGS }
176
193
  );
177
194
  }
178
195
  this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });
179
196
  }
180
- if (!useCurrentDir && await directoryExists(marketplaceDir)) {
181
- if (!flags.force) {
182
- this.error(`Directory already exists: ${marketplaceDir}
197
+ }
198
+ async checkExistingDir(dir, useCurrentDir, force) {
199
+ if (!useCurrentDir && await directoryExists(dir)) {
200
+ if (!force) {
201
+ this.error(`Directory already exists: ${dir}
183
202
  Use --force to overwrite.`, {
184
203
  exit: EXIT_CODES.ERROR
185
204
  });
186
205
  }
187
- this.warn(`Overwriting existing directory at ${marketplaceDir}`);
206
+ this.warn(`Overwriting existing directory at ${dir}`);
188
207
  }
189
- this.log(`Marketplace: ${marketplaceName}`);
190
- this.log(`Directory: ${marketplaceDir}`);
191
- this.log("");
208
+ }
209
+ async createMarketplaceFiles(marketplaceName, marketplaceDir, force) {
192
210
  const skillName = "dummy-skill";
193
211
  this.log("Creating marketplace structure...");
194
- try {
195
- const stacksContent = generateStacksTs(marketplaceName);
196
- const stacksPath = path.join(marketplaceDir, STACKS_FILE_PATH);
197
- await ensureDir(path.dirname(stacksPath));
198
- await writeFile(stacksPath, stacksContent);
199
- const categoriesContent = generateSkillCategoriesTs(
200
- LOCAL_DEFAULTS.CATEGORY,
201
- LOCAL_DEFAULTS.DOMAIN
202
- );
203
- const categoriesPath = path.join(marketplaceDir, SKILL_CATEGORIES_PATH);
204
- await writeFile(categoriesPath, categoriesContent);
205
- const rulesContent = generateSkillRulesTs();
206
- const rulesPath = path.join(marketplaceDir, SKILL_RULES_PATH);
207
- await writeFile(rulesPath, rulesContent);
208
- const skillsDir = path.join(marketplaceDir, SKILLS_DIR_PATH);
209
- const skillArgs = [skillName, "--output", skillsDir, "--domain", LOCAL_DEFAULTS.DOMAIN];
210
- if (flags.force) skillArgs.push("--force");
211
- await this.config.runCommand("new:skill", skillArgs);
212
- const readmeContent = generateReadme(marketplaceName);
213
- const readmePath = path.join(marketplaceDir, "README.md");
214
- await writeFile(readmePath, readmeContent);
215
- const configDir = path.join(marketplaceDir, CLAUDE_SRC_DIR);
216
- await ensureDir(configDir);
217
- const configContent = generateConfigSource({
218
- name: marketplaceName,
219
- skills: [{ id: skillName, scope: "project", source: "local" }],
220
- agents: [],
221
- source: ".",
222
- marketplace: marketplaceName,
223
- stack: {
224
- "web-developer": {
225
- // Boundary cast: dummy-category is not in the generated Category union
226
- [LOCAL_DEFAULTS.CATEGORY]: [{ id: skillName }]
227
- }
212
+ const stacksContent = generateStacksTs(marketplaceName);
213
+ const stacksPath = path.join(marketplaceDir, STACKS_FILE_PATH);
214
+ await ensureDir(path.dirname(stacksPath));
215
+ await writeFile(stacksPath, stacksContent);
216
+ const categoriesContent = generateSkillCategoriesTs(
217
+ LOCAL_DEFAULTS.CATEGORY,
218
+ LOCAL_DEFAULTS.DOMAIN
219
+ );
220
+ const categoriesPath = path.join(marketplaceDir, SKILL_CATEGORIES_PATH);
221
+ await writeFile(categoriesPath, categoriesContent);
222
+ const rulesContent = generateSkillRulesTs();
223
+ const rulesPath = path.join(marketplaceDir, SKILL_RULES_PATH);
224
+ await writeFile(rulesPath, rulesContent);
225
+ const skillsDir = path.join(marketplaceDir, SKILLS_DIR_PATH);
226
+ const skillArgs = [skillName, "--output", skillsDir, "--domain", LOCAL_DEFAULTS.DOMAIN];
227
+ if (force) skillArgs.push("--force");
228
+ await this.config.runCommand("new:skill", skillArgs);
229
+ const readmeContent = generateReadme(marketplaceName);
230
+ const readmePath = path.join(marketplaceDir, "README.md");
231
+ await writeFile(readmePath, readmeContent);
232
+ const configDir = path.join(marketplaceDir, CLAUDE_SRC_DIR);
233
+ await ensureDir(configDir);
234
+ const configContent = generateConfigSource({
235
+ name: marketplaceName,
236
+ skills: [{ id: skillName, scope: "project", source: "local" }],
237
+ agents: [],
238
+ source: ".",
239
+ marketplace: marketplaceName,
240
+ stack: {
241
+ "web-developer": {
242
+ // Boundary cast: dummy-category is not in the generated Category union
243
+ [LOCAL_DEFAULTS.CATEGORY]: [{ id: skillName }]
228
244
  }
229
- });
230
- const marketplaceComment = "// Marketplaces house skills only \u2014 agents are defined by consumer projects.\n\n";
231
- await writeFile(
232
- path.join(configDir, STANDARD_FILES.CONFIG_TS),
233
- marketplaceComment + configContent
234
- );
235
- this.log("");
236
- this.logSuccess(`Created ${STACKS_FILE_PATH}`);
237
- this.logSuccess(`Created ${SKILL_CATEGORIES_PATH}`);
238
- this.logSuccess(`Created ${SKILL_RULES_PATH}`);
239
- this.logSuccess("Created README.md");
240
- this.logSuccess("Created .claude-src/config.ts");
241
- this.log("");
242
- await this.buildMarketplace(marketplaceDir, marketplaceName);
243
- this.log("Marketplace created successfully!");
244
- this.log("");
245
- this.log("Next steps:");
246
- if (!useCurrentDir) {
247
- this.log(` 1. cd ${marketplaceName}`);
248
245
  }
249
- this.log(
250
- ` ${useCurrentDir ? "1" : "2"}. ${CLI_BIN_NAME} new skill <name> --category <category-name>`
251
- );
252
- this.log(` ${useCurrentDir ? "2" : "3"}. Push to a git repository`);
253
- this.log(
254
- ` ${useCurrentDir ? "3" : "4"}. ${CLI_BIN_NAME} init --source github:your-org/${marketplaceName}`
255
- );
256
- this.log("");
257
- } catch (error) {
258
- this.handleError(error);
246
+ });
247
+ const marketplaceComment = "// Marketplaces house skills only \u2014 agents are defined by consumer projects.\n\n";
248
+ await writeFile(
249
+ path.join(configDir, STANDARD_FILES.CONFIG_TS),
250
+ marketplaceComment + configContent
251
+ );
252
+ this.log("");
253
+ this.logSuccess(`Created ${STACKS_FILE_PATH}`);
254
+ this.logSuccess(`Created ${SKILL_CATEGORIES_PATH}`);
255
+ this.logSuccess(`Created ${SKILL_RULES_PATH}`);
256
+ this.logSuccess("Created README.md");
257
+ this.logSuccess("Created .claude-src/config.ts");
258
+ this.log("");
259
+ }
260
+ printNextSteps(marketplaceName, useCurrentDir) {
261
+ this.log("Marketplace created successfully!");
262
+ this.log("");
263
+ this.log("Next steps:");
264
+ if (!useCurrentDir) {
265
+ this.log(` 1. cd ${marketplaceName}`);
259
266
  }
267
+ this.log(
268
+ ` ${useCurrentDir ? "1" : "2"}. ${CLI_BIN_NAME} new skill <name> --category <category-name>`
269
+ );
270
+ this.log(` ${useCurrentDir ? "2" : "3"}. Push to a git repository`);
271
+ this.log(
272
+ ` ${useCurrentDir ? "3" : "4"}. ${CLI_BIN_NAME} init --source github:your-org/${marketplaceName}`
273
+ );
274
+ this.log("");
260
275
  }
261
276
  async buildMarketplace(marketplaceDir, marketplaceName) {
262
277
  const skillsDir = path.resolve(marketplaceDir, SKILLS_DIR_PATH);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/new/marketplace.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { writeFile, directoryExists, ensureDir } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport {\n CLAUDE_SRC_DIR,\n CLI_BIN_NAME,\n KEBAB_CASE_PATTERN,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { compileAllSkillPlugins } from \"../../lib/skills/skill-plugin-compiler.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { generateConfigSource } from \"../../lib/configuration/config-writer.js\";\nimport { generateMarketplace, writeMarketplace } from \"../../lib/marketplace-generator.js\";\nimport { generateSkillCategoriesTs, generateSkillRulesTs } from \"../../lib/skills/generators.js\";\nimport type { Category, SkillId } from \"../../types/index.js\";\n\nexport function validateMarketplaceName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Marketplace name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Marketplace name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\nexport function generateStacksTs(name: string): string {\n const data = {\n stacks: [\n {\n id: \"dummy-stack\",\n name: \"Dummy Stack\",\n description: `Default stack for ${name}`,\n agents: {\n \"web-developer\": {\n \"dummy-category\": \"dummy-skill\",\n },\n },\n philosophy: \"Ship fast, iterate faster\",\n },\n ],\n };\n const body = JSON.stringify(data, null, 2);\n return `// Stack definitions for ${name}\\nexport default ${body};\\n`;\n}\n\nexport function generateReadme(name: string): string {\n return `# ${name}\n\nPrivate marketplace for custom skills and stacks.\n\n## Directory Structure\n\n\\`\\`\\`\n${STACKS_FILE_PATH} # Stack definitions (agent groupings with skill mappings)\n${SKILLS_DIR_PATH}/ # Custom skill definitions\n\\`\\`\\`\n\n## Creating Skills\n\n\\`\\`\\`bash\n${CLI_BIN_NAME} new skill <name> --category <category-name>\n\\`\\`\\`\n\nEach skill lives in \\`${SKILLS_DIR_PATH}/<skill-name>/\\` with:\n- \\`${STANDARD_FILES.SKILL_MD}\\` -- Skill content (what the skill teaches)\n- \\`${STANDARD_FILES.METADATA_YAML}\\` -- Skill metadata (category, author, description, custom: true)\n\n## Using This Marketplace\n\nPoint the CLI at this marketplace as a source:\n\n\\`\\`\\`bash\n# Local development\n${CLI_BIN_NAME} init --source /path/to/${name}\n\n# From a git repository\n${CLI_BIN_NAME} init --source github:your-org/${name}\n\\`\\`\\`\n\n## How It Works\n\nThe CLI auto-discovers skills from the \\`${SKILLS_DIR_PATH}/\\` directory\nand stacks from \\`${STACKS_FILE_PATH}\\`.\nCustom categories are discovered from skill \\`${STANDARD_FILES.METADATA_YAML}\\` files with \\`custom: true\\`.\nCustom skills appear alongside built-in ones in the wizard. No manual registration needed.\n`;\n}\n\nexport default class NewMarketplace extends BaseCommand {\n static summary = \"Scaffold a new private marketplace project\";\n static description =\n \"Create a new private marketplace directory with the required structure \" +\n \"for custom skills and stacks.\";\n\n static examples = [\n {\n description: \"Create a new marketplace\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills\",\n },\n {\n description: \"Initialize the current directory as a marketplace\",\n command: \"<%= config.bin %> <%= command.id %> .\",\n },\n {\n description: \"Create in a specific location\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --output ~/projects\",\n },\n {\n description: \"Overwrite an existing directory\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --force\",\n },\n ];\n\n static args = {\n name: Args.string({\n description:\n 'Name of the marketplace directory (kebab-case), or \".\" to use the current directory',\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Parent directory to create the marketplace in (default: current directory)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewMarketplace);\n\n this.log(\"\");\n this.log(\"Create New Marketplace\");\n this.log(\"\");\n\n const parentDir = flags.output ? path.resolve(flags.output) : process.cwd();\n const useCurrentDir = args.name === \".\";\n\n const marketplaceName = useCurrentDir ? path.basename(parentDir) : args.name;\n const marketplaceDir = useCurrentDir ? parentDir : path.join(parentDir, args.name);\n\n const validationError = validateMarketplaceName(marketplaceName);\n if (validationError) {\n if (useCurrentDir) {\n this.error(\n `Current directory name '${marketplaceName}' is not valid kebab-case. Rename it or pass an explicit name.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Skip existing directory check when using \".\" (the directory obviously exists)\n if (!useCurrentDir && (await directoryExists(marketplaceDir))) {\n if (!flags.force) {\n this.error(`Directory already exists: ${marketplaceDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing directory at ${marketplaceDir}`);\n }\n\n this.log(`Marketplace: ${marketplaceName}`);\n this.log(`Directory: ${marketplaceDir}`);\n this.log(\"\");\n\n const skillName = \"dummy-skill\";\n\n this.log(\"Creating marketplace structure...\");\n\n try {\n // Create config/stacks.ts\n const stacksContent = generateStacksTs(marketplaceName);\n const stacksPath = path.join(marketplaceDir, STACKS_FILE_PATH);\n await ensureDir(path.dirname(stacksPath));\n await writeFile(stacksPath, stacksContent);\n\n // Create config/skill-categories.ts\n const categoriesContent = generateSkillCategoriesTs(\n LOCAL_DEFAULTS.CATEGORY,\n LOCAL_DEFAULTS.DOMAIN,\n );\n const categoriesPath = path.join(marketplaceDir, SKILL_CATEGORIES_PATH);\n await writeFile(categoriesPath, categoriesContent);\n\n // Create config/skill-rules.ts\n const rulesContent = generateSkillRulesTs();\n const rulesPath = path.join(marketplaceDir, SKILL_RULES_PATH);\n await writeFile(rulesPath, rulesContent);\n\n // Delegate skill creation to the new:skill command\n const skillsDir = path.join(marketplaceDir, SKILLS_DIR_PATH);\n\n const skillArgs = [skillName, \"--output\", skillsDir, \"--domain\", LOCAL_DEFAULTS.DOMAIN];\n if (flags.force) skillArgs.push(\"--force\");\n await this.config.runCommand(\"new:skill\", skillArgs);\n\n // Create README.md\n const readmeContent = generateReadme(marketplaceName);\n const readmePath = path.join(marketplaceDir, \"README.md\");\n await writeFile(readmePath, readmeContent);\n\n // Create .claude-src/config.ts so the marketplace is a valid installation\n const configDir = path.join(marketplaceDir, CLAUDE_SRC_DIR);\n await ensureDir(configDir);\n // Boundary cast: custom marketplace dummy skill/category not in standard unions\n const configContent = generateConfigSource({\n name: marketplaceName,\n skills: [{ id: skillName as SkillId, scope: \"project\", source: \"local\" }],\n agents: [],\n source: \".\",\n marketplace: marketplaceName,\n stack: {\n \"web-developer\": {\n // Boundary cast: dummy-category is not in the generated Category union\n [LOCAL_DEFAULTS.CATEGORY as Category]: [{ id: skillName as SkillId }],\n },\n },\n });\n const marketplaceComment =\n \"// Marketplaces house skills only — agents are defined by consumer projects.\\n\\n\";\n await writeFile(\n path.join(configDir, STANDARD_FILES.CONFIG_TS),\n marketplaceComment + configContent,\n );\n\n this.log(\"\");\n this.logSuccess(`Created ${STACKS_FILE_PATH}`);\n this.logSuccess(`Created ${SKILL_CATEGORIES_PATH}`);\n this.logSuccess(`Created ${SKILL_RULES_PATH}`);\n this.logSuccess(\"Created README.md\");\n this.logSuccess(\"Created .claude-src/config.ts\");\n this.log(\"\");\n\n // Build plugins and marketplace.json so the marketplace is immediately valid\n await this.buildMarketplace(marketplaceDir, marketplaceName);\n\n this.log(\"Marketplace created successfully!\");\n this.log(\"\");\n this.log(\"Next steps:\");\n if (!useCurrentDir) {\n this.log(` 1. cd ${marketplaceName}`);\n }\n this.log(\n ` ${useCurrentDir ? \"1\" : \"2\"}. ${CLI_BIN_NAME} new skill <name> --category <category-name>`,\n );\n this.log(` ${useCurrentDir ? \"2\" : \"3\"}. Push to a git repository`);\n this.log(\n ` ${useCurrentDir ? \"3\" : \"4\"}. ${CLI_BIN_NAME} init --source github:your-org/${marketplaceName}`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async buildMarketplace(marketplaceDir: string, marketplaceName: string): Promise<void> {\n const skillsDir = path.resolve(marketplaceDir, SKILLS_DIR_PATH);\n const pluginsOutputDir = path.resolve(marketplaceDir, \"dist/plugins\");\n const marketplaceOutputPath = path.resolve(\n marketplaceDir,\n PLUGIN_MANIFEST_DIR,\n \"marketplace.json\",\n );\n\n try {\n this.log(\"Building plugins...\");\n const results = await compileAllSkillPlugins(skillsDir, pluginsOutputDir);\n this.logSuccess(`Built ${results.length} skill plugins.`);\n\n this.log(\"Generating marketplace.json...\");\n const marketplace = await generateMarketplace(pluginsOutputDir, {\n name: marketplaceName,\n ownerName: marketplaceName,\n pluginRoot: \"./dist/plugins\",\n });\n await writeMarketplace(marketplaceOutputPath, marketplace);\n this.logSuccess(\n `Generated ${PLUGIN_MANIFEST_DIR}/marketplace.json with ${marketplace.plugins.length} plugins.`,\n );\n\n this.log(\"Generating config-types.ts...\");\n const configTypesData = loadConfigTypesDataInBackground(marketplaceDir, marketplaceDir);\n await regenerateConfigTypes(marketplaceDir, configTypesData);\n this.logSuccess(\"Generated .claude-src/config-types.ts\");\n } catch (error) {\n this.warn(`Build step failed: ${getErrorMessage(error)}`);\n this.warn(\n \"The scaffold is still valid. Run 'build plugins' and 'build marketplace' manually.\",\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/cli/commands/new/marketplace.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { writeFile, directoryExists, ensureDir } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport {\n CLAUDE_SRC_DIR,\n CLI_BIN_NAME,\n KEBAB_CASE_PATTERN,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { compileAllSkillPlugins } from \"../../lib/skills/skill-plugin-compiler.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { generateConfigSource } from \"../../lib/configuration/config-writer.js\";\nimport { generateMarketplace, writeMarketplace } from \"../../lib/marketplace-generator.js\";\nimport { generateSkillCategoriesTs, generateSkillRulesTs } from \"../../lib/skills/generators.js\";\nimport type { Category, SkillId } from \"../../types/index.js\";\n\nexport function validateMarketplaceName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Marketplace name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Marketplace name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\nexport function generateStacksTs(name: string): string {\n const data = {\n stacks: [\n {\n id: \"dummy-stack\",\n name: \"Dummy Stack\",\n description: `Default stack for ${name}`,\n agents: {\n \"web-developer\": {\n \"dummy-category\": \"dummy-skill\",\n },\n },\n philosophy: \"Ship fast, iterate faster\",\n },\n ],\n };\n const body = JSON.stringify(data, null, 2);\n return `// Stack definitions for ${name}\\nexport default ${body};\\n`;\n}\n\nexport function generateReadme(name: string): string {\n return `# ${name}\n\nPrivate marketplace for custom skills and stacks.\n\n## Directory Structure\n\n\\`\\`\\`\n${STACKS_FILE_PATH} # Stack definitions (agent groupings with skill mappings)\n${SKILLS_DIR_PATH}/ # Custom skill definitions\n\\`\\`\\`\n\n## Creating Skills\n\n\\`\\`\\`bash\n${CLI_BIN_NAME} new skill <name> --category <category-name>\n\\`\\`\\`\n\nEach skill lives in \\`${SKILLS_DIR_PATH}/<skill-name>/\\` with:\n- \\`${STANDARD_FILES.SKILL_MD}\\` -- Skill content (what the skill teaches)\n- \\`${STANDARD_FILES.METADATA_YAML}\\` -- Skill metadata (category, author, description, custom: true)\n\n## Using This Marketplace\n\nPoint the CLI at this marketplace as a source:\n\n\\`\\`\\`bash\n# Local development\n${CLI_BIN_NAME} init --source /path/to/${name}\n\n# From a git repository\n${CLI_BIN_NAME} init --source github:your-org/${name}\n\\`\\`\\`\n\n## How It Works\n\nThe CLI auto-discovers skills from the \\`${SKILLS_DIR_PATH}/\\` directory\nand stacks from \\`${STACKS_FILE_PATH}\\`.\nCustom categories are discovered from skill \\`${STANDARD_FILES.METADATA_YAML}\\` files with \\`custom: true\\`.\nCustom skills appear alongside built-in ones in the wizard. No manual registration needed.\n`;\n}\n\nexport default class NewMarketplace extends BaseCommand {\n static summary = \"Scaffold a new private marketplace project\";\n static description =\n \"Create a new private marketplace directory with the required structure \" +\n \"for custom skills and stacks.\";\n\n static examples = [\n {\n description: \"Create a new marketplace\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills\",\n },\n {\n description: \"Initialize the current directory as a marketplace\",\n command: \"<%= config.bin %> <%= command.id %> .\",\n },\n {\n description: \"Create in a specific location\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --output ~/projects\",\n },\n {\n description: \"Overwrite an existing directory\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --force\",\n },\n ];\n\n static args = {\n name: Args.string({\n description:\n 'Name of the marketplace directory (kebab-case), or \".\" to use the current directory',\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Parent directory to create the marketplace in (default: current directory)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewMarketplace);\n const parentDir = flags.output ? path.resolve(flags.output) : process.cwd();\n const useCurrentDir = args.name === \".\";\n\n const marketplaceName = useCurrentDir ? path.basename(parentDir) : args.name;\n const marketplaceDir = useCurrentDir ? parentDir : path.join(parentDir, args.name);\n\n this.printHeader();\n this.validateName(marketplaceName, useCurrentDir);\n await this.checkExistingDir(marketplaceDir, useCurrentDir, flags.force);\n\n this.log(`Marketplace: ${marketplaceName}`);\n this.log(`Directory: ${marketplaceDir}`);\n this.log(\"\");\n\n try {\n await this.createMarketplaceFiles(marketplaceName, marketplaceDir, flags.force);\n await this.buildMarketplace(marketplaceDir, marketplaceName);\n this.printNextSteps(marketplaceName, useCurrentDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private printHeader(): void {\n this.log(\"\");\n this.log(\"Create New Marketplace\");\n this.log(\"\");\n }\n\n private validateName(name: string, useCurrentDir: boolean): void {\n const validationError = validateMarketplaceName(name);\n if (validationError) {\n if (useCurrentDir) {\n this.error(\n `Current directory name '${name}' is not valid kebab-case. Rename it or pass an explicit name.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n }\n\n private async checkExistingDir(\n dir: string,\n useCurrentDir: boolean,\n force: boolean,\n ): Promise<void> {\n if (!useCurrentDir && (await directoryExists(dir))) {\n if (!force) {\n this.error(`Directory already exists: ${dir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing directory at ${dir}`);\n }\n }\n\n private async createMarketplaceFiles(\n marketplaceName: string,\n marketplaceDir: string,\n force: boolean,\n ): Promise<void> {\n const skillName = \"dummy-skill\";\n\n this.log(\"Creating marketplace structure...\");\n\n const stacksContent = generateStacksTs(marketplaceName);\n const stacksPath = path.join(marketplaceDir, STACKS_FILE_PATH);\n await ensureDir(path.dirname(stacksPath));\n await writeFile(stacksPath, stacksContent);\n\n const categoriesContent = generateSkillCategoriesTs(\n LOCAL_DEFAULTS.CATEGORY,\n LOCAL_DEFAULTS.DOMAIN,\n );\n const categoriesPath = path.join(marketplaceDir, SKILL_CATEGORIES_PATH);\n await writeFile(categoriesPath, categoriesContent);\n\n const rulesContent = generateSkillRulesTs();\n const rulesPath = path.join(marketplaceDir, SKILL_RULES_PATH);\n await writeFile(rulesPath, rulesContent);\n\n const skillsDir = path.join(marketplaceDir, SKILLS_DIR_PATH);\n const skillArgs = [skillName, \"--output\", skillsDir, \"--domain\", LOCAL_DEFAULTS.DOMAIN];\n if (force) skillArgs.push(\"--force\");\n await this.config.runCommand(\"new:skill\", skillArgs);\n\n const readmeContent = generateReadme(marketplaceName);\n const readmePath = path.join(marketplaceDir, \"README.md\");\n await writeFile(readmePath, readmeContent);\n\n const configDir = path.join(marketplaceDir, CLAUDE_SRC_DIR);\n await ensureDir(configDir);\n // Boundary cast: custom marketplace dummy skill/category not in standard unions\n const configContent = generateConfigSource({\n name: marketplaceName,\n skills: [{ id: skillName as SkillId, scope: \"project\", source: \"local\" }],\n agents: [],\n source: \".\",\n marketplace: marketplaceName,\n stack: {\n \"web-developer\": {\n // Boundary cast: dummy-category is not in the generated Category union\n [LOCAL_DEFAULTS.CATEGORY as Category]: [{ id: skillName as SkillId }],\n },\n },\n });\n const marketplaceComment =\n \"// Marketplaces house skills only — agents are defined by consumer projects.\\n\\n\";\n await writeFile(\n path.join(configDir, STANDARD_FILES.CONFIG_TS),\n marketplaceComment + configContent,\n );\n\n this.log(\"\");\n this.logSuccess(`Created ${STACKS_FILE_PATH}`);\n this.logSuccess(`Created ${SKILL_CATEGORIES_PATH}`);\n this.logSuccess(`Created ${SKILL_RULES_PATH}`);\n this.logSuccess(\"Created README.md\");\n this.logSuccess(\"Created .claude-src/config.ts\");\n this.log(\"\");\n }\n\n private printNextSteps(marketplaceName: string, useCurrentDir: boolean): void {\n this.log(\"Marketplace created successfully!\");\n this.log(\"\");\n this.log(\"Next steps:\");\n if (!useCurrentDir) {\n this.log(` 1. cd ${marketplaceName}`);\n }\n this.log(\n ` ${useCurrentDir ? \"1\" : \"2\"}. ${CLI_BIN_NAME} new skill <name> --category <category-name>`,\n );\n this.log(` ${useCurrentDir ? \"2\" : \"3\"}. Push to a git repository`);\n this.log(\n ` ${useCurrentDir ? \"3\" : \"4\"}. ${CLI_BIN_NAME} init --source github:your-org/${marketplaceName}`,\n );\n this.log(\"\");\n }\n\n private async buildMarketplace(marketplaceDir: string, marketplaceName: string): Promise<void> {\n const skillsDir = path.resolve(marketplaceDir, SKILLS_DIR_PATH);\n const pluginsOutputDir = path.resolve(marketplaceDir, \"dist/plugins\");\n const marketplaceOutputPath = path.resolve(\n marketplaceDir,\n PLUGIN_MANIFEST_DIR,\n \"marketplace.json\",\n );\n\n try {\n this.log(\"Building plugins...\");\n const results = await compileAllSkillPlugins(skillsDir, pluginsOutputDir);\n this.logSuccess(`Built ${results.length} skill plugins.`);\n\n this.log(\"Generating marketplace.json...\");\n const marketplace = await generateMarketplace(pluginsOutputDir, {\n name: marketplaceName,\n ownerName: marketplaceName,\n pluginRoot: \"./dist/plugins\",\n });\n await writeMarketplace(marketplaceOutputPath, marketplace);\n this.logSuccess(\n `Generated ${PLUGIN_MANIFEST_DIR}/marketplace.json with ${marketplace.plugins.length} plugins.`,\n );\n\n this.log(\"Generating config-types.ts...\");\n const configTypesData = loadConfigTypesDataInBackground(marketplaceDir, marketplaceDir);\n await regenerateConfigTypes(marketplaceDir, configTypesData);\n this.logSuccess(\"Generated .claude-src/config-types.ts\");\n } catch (error) {\n this.warn(`Build step failed: ${getErrorMessage(error)}`);\n this.warn(\n \"The scaffold is still valid. Run 'build plugins' and 'build marketplace' manually.\",\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -14,13 +14,13 @@ import {
14
14
  loadConfigTypesDataInBackground,
15
15
  regenerateConfigTypes,
16
16
  resolveAuthor
17
- } from "../../chunk-EADZIYQW.js";
18
- import "../../chunk-STMRDPGZ.js";
19
- import "../../chunk-ANXHMG32.js";
17
+ } from "../../chunk-FVBSRBU3.js";
18
+ import "../../chunk-XM2Y5AFQ.js";
19
+ import "../../chunk-47HMJ4BY.js";
20
20
  import {
21
21
  BaseCommand,
22
22
  EXIT_CODES
23
- } from "../../chunk-TAPEVEET.js";
23
+ } from "../../chunk-7K7SA4TZ.js";
24
24
  import {
25
25
  directoryExists,
26
26
  ensureDir,
@@ -28,8 +28,8 @@ import {
28
28
  getErrorMessage,
29
29
  verbose,
30
30
  writeFile
31
- } from "../../chunk-ZTRQO5CX.js";
32
- import "../../chunk-6XWHJHNZ.js";
31
+ } from "../../chunk-OOHPUT5M.js";
32
+ import "../../chunk-WEYWZ7UE.js";
33
33
  import {
34
34
  CLI_BIN_NAME,
35
35
  KEBAB_CASE_PATTERN,
@@ -40,7 +40,7 @@ import {
40
40
  SKILL_RULES_PATH,
41
41
  STANDARD_FILES
42
42
  } from "../../chunk-6PGL2XMY.js";
43
- import "../../chunk-NPMMU4GY.js";
43
+ import "../../chunk-IR7ADPAZ.js";
44
44
  import {
45
45
  init_esm_shims
46
46
  } from "../../chunk-DHET7RCE.js";
@@ -3,26 +3,26 @@ import {
3
3
  compareSkillsWithSource,
4
4
  detectProject,
5
5
  loadSource
6
- } from "../chunk-LHUK5L6P.js";
6
+ } from "../chunk-4DZNTUK7.js";
7
7
  import "../chunk-N6A7A4RA.js";
8
- import "../chunk-YM3V4Q3W.js";
9
- import "../chunk-EADZIYQW.js";
10
- import "../chunk-STMRDPGZ.js";
11
- import "../chunk-ANXHMG32.js";
8
+ import "../chunk-DZ2IQERZ.js";
9
+ import "../chunk-FVBSRBU3.js";
10
+ import "../chunk-XM2Y5AFQ.js";
11
+ import "../chunk-47HMJ4BY.js";
12
12
  import {
13
13
  BaseCommand,
14
14
  EXIT_CODES
15
- } from "../chunk-TAPEVEET.js";
15
+ } from "../chunk-7K7SA4TZ.js";
16
16
  import {
17
17
  fileExists,
18
18
  getErrorMessage
19
- } from "../chunk-ZTRQO5CX.js";
20
- import "../chunk-6XWHJHNZ.js";
19
+ } from "../chunk-OOHPUT5M.js";
20
+ import "../chunk-WEYWZ7UE.js";
21
21
  import {
22
22
  CLI_BIN_NAME,
23
23
  LOCAL_SKILLS_PATH
24
24
  } from "../chunk-6PGL2XMY.js";
25
- import "../chunk-NPMMU4GY.js";
25
+ import "../chunk-IR7ADPAZ.js";
26
26
  import {
27
27
  init_esm_shims
28
28
  } from "../chunk-DHET7RCE.js";
@@ -76,110 +76,101 @@ var Outdated = class _Outdated extends BaseCommand {
76
76
  const { flags } = await this.parse(_Outdated);
77
77
  const detected = await detectProject();
78
78
  const projectDir = detected?.installation.projectDir ?? process.cwd();
79
+ const hasSkills = await this.checkLocalSkillsExist(projectDir, flags.json);
80
+ if (!hasSkills) return;
79
81
  try {
80
- const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);
81
- const homeDir = os.homedir();
82
- const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);
83
- const hasProject = await fileExists(projectLocalPath);
84
- const hasGlobal = projectDir !== homeDir && await fileExists(globalLocalPath);
85
- if (!hasProject && !hasGlobal) {
86
- if (flags.json) {
87
- this.log(
88
- JSON.stringify({
89
- skills: [],
90
- summary: { outdated: 0, current: 0, localOnly: 0 }
91
- })
92
- );
93
- } else {
94
- this.warn(
95
- `No local skills found. Run \`${CLI_BIN_NAME} init\` or \`${CLI_BIN_NAME} edit\` first.`
96
- );
97
- }
98
- return;
99
- }
100
- if (!flags.json) {
101
- this.log("Loading skills...");
102
- }
103
- const { sourceResult } = await loadSource({
104
- sourceFlag: flags.source,
105
- projectDir
106
- });
107
- const { matrix, sourcePath, isLocal } = sourceResult;
108
- if (!flags.json) {
109
- this.log(`Loaded from ${isLocal ? "local" : "remote"}: ${sourcePath}`);
110
- }
111
- const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);
112
- const summary = calculateSummary(results);
113
- if (flags.json) {
114
- this.log(
115
- JSON.stringify(
116
- {
117
- skills: results.map((r) => ({
118
- id: r.id,
119
- localHash: r.localHash,
120
- sourceHash: r.sourceHash,
121
- status: r.status
122
- })),
123
- summary: {
124
- outdated: summary.outdated,
125
- current: summary.current,
126
- localOnly: summary.localOnly
127
- }
128
- },
129
- null,
130
- 2
131
- )
132
- );
133
- } else {
134
- this.log("");
135
- if (results.length === 0) {
136
- this.logInfo("No local skills found to compare.");
137
- } else {
138
- printTable({
139
- data: results.map((result) => ({
140
- skill: result.id,
141
- localHash: formatHash(result.localHash, true),
142
- sourceHash: formatHash(result.sourceHash, false),
143
- status: result.status
144
- })),
145
- columns: [
146
- { key: "skill", name: "Skill" },
147
- { key: "localHash", name: "Local Hash" },
148
- { key: "sourceHash", name: "Source Hash" },
149
- { key: "status", name: "Status" }
150
- ],
151
- headerOptions: { bold: true }
152
- });
153
- this.log("");
154
- const parts = [];
155
- if (summary.outdated > 0) {
156
- parts.push(`${summary.outdated} outdated`);
157
- }
158
- if (summary.current > 0) {
159
- parts.push(`${summary.current} current`);
160
- }
161
- if (summary.localOnly > 0) {
162
- parts.push(`${summary.localOnly} local-only`);
163
- }
164
- this.log(`Summary: ${parts.join(", ")}`);
165
- }
166
- this.log("");
167
- }
82
+ const { results, summary, sourceResult } = await this.loadAndCompare(flags, projectDir);
83
+ this.reportResults(results, summary, sourceResult, flags.json);
168
84
  if (summary.outdated > 0) {
169
85
  this.error("Some skills are outdated", { exit: EXIT_CODES.ERROR });
170
86
  }
171
87
  } catch (error) {
172
88
  const message = getErrorMessage(error);
173
89
  if (flags.json) {
174
- this.error(JSON.stringify({ error: message }), {
175
- exit: EXIT_CODES.ERROR
176
- });
90
+ this.error(JSON.stringify({ error: message }), { exit: EXIT_CODES.ERROR });
177
91
  } else {
178
92
  this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });
179
93
  }
180
94
  }
181
95
  }
96
+ async checkLocalSkillsExist(projectDir, json) {
97
+ const homeDir = os.homedir();
98
+ const hasProject = await fileExists(path.join(projectDir, LOCAL_SKILLS_PATH));
99
+ const hasGlobal = projectDir !== homeDir && await fileExists(path.join(homeDir, LOCAL_SKILLS_PATH));
100
+ if (hasProject || hasGlobal) return true;
101
+ if (json) {
102
+ this.log(JSON.stringify({ skills: [], summary: { outdated: 0, current: 0, localOnly: 0 } }));
103
+ } else {
104
+ this.warn(
105
+ `No local skills found. Run \`${CLI_BIN_NAME} init\` or \`${CLI_BIN_NAME} edit\` first.`
106
+ );
107
+ }
108
+ return false;
109
+ }
110
+ async loadAndCompare(flags, projectDir) {
111
+ if (!flags.json) this.log("Loading skills...");
112
+ const { sourceResult } = await loadSource({ sourceFlag: flags.source, projectDir });
113
+ const { matrix, sourcePath, isLocal } = sourceResult;
114
+ if (!flags.json) this.log(`Loaded from ${isLocal ? "local" : "remote"}: ${sourcePath}`);
115
+ const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);
116
+ const summary = calculateSummary(results);
117
+ return { results, summary, sourceResult: { isLocal, sourcePath } };
118
+ }
119
+ reportResults(results, summary, _sourceResult, json) {
120
+ if (json) {
121
+ this.log(
122
+ JSON.stringify(
123
+ {
124
+ skills: results.map((r) => ({
125
+ id: r.id,
126
+ localHash: r.localHash,
127
+ sourceHash: r.sourceHash,
128
+ status: r.status
129
+ })),
130
+ summary: {
131
+ outdated: summary.outdated,
132
+ current: summary.current,
133
+ localOnly: summary.localOnly
134
+ }
135
+ },
136
+ null,
137
+ 2
138
+ )
139
+ );
140
+ return;
141
+ }
142
+ this.log("");
143
+ if (results.length === 0) {
144
+ this.logInfo("No local skills found to compare.");
145
+ } else {
146
+ printTable({
147
+ data: results.map((result) => ({
148
+ skill: result.id,
149
+ localHash: formatHash(result.localHash, true),
150
+ sourceHash: formatHash(result.sourceHash, false),
151
+ status: result.status
152
+ })),
153
+ columns: [
154
+ { key: "skill", name: "Skill" },
155
+ { key: "localHash", name: "Local Hash" },
156
+ { key: "sourceHash", name: "Source Hash" },
157
+ { key: "status", name: "Status" }
158
+ ],
159
+ headerOptions: { bold: true }
160
+ });
161
+ this.log("");
162
+ this.log(`Summary: ${formatSummaryParts(summary)}`);
163
+ }
164
+ this.log("");
165
+ }
182
166
  };
167
+ function formatSummaryParts(summary) {
168
+ const parts = [];
169
+ if (summary.outdated > 0) parts.push(`${summary.outdated} outdated`);
170
+ if (summary.current > 0) parts.push(`${summary.current} current`);
171
+ if (summary.localOnly > 0) parts.push(`${summary.localOnly} local-only`);
172
+ return parts.join(", ");
173
+ }
183
174
  export {
184
175
  Outdated as default
185
176
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport os from \"os\";\nimport path from \"path\";\nimport { countBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSource, compareSkillsWithSource, detectProject } from \"../lib/operations/index.js\";\nimport { type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport { fileExists } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\n\ntype ComparisonSummary = {\n outdated: number;\n current: number;\n localOnly: number;\n};\n\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n const counts = countBy(results, (r) => r.status);\n return {\n outdated: counts[\"outdated\"] ?? 0,\n current: counts[\"current\"] ?? 0,\n localOnly: counts[\"local-only\"] ?? 0,\n };\n}\n\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary = \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static examples = [\n {\n description: \"Check for outdated skills\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Output results as JSON\",\n command: \"<%= config.bin %> <%= command.id %> --json\",\n },\n {\n description: \"Check against a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const detected = await detectProject();\n const projectDir = detected?.installation.projectDir ?? process.cwd();\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 if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\n `No local skills found. Run \\`${CLI_BIN_NAME} init\\` or \\`${CLI_BIN_NAME} edit\\` first.`,\n );\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { sourceResult } = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n });\n const { matrix, sourcePath, isLocal } = sourceResult;\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);\n const summary = calculateSummary(results);\n\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport os from \"os\";\nimport path from \"path\";\nimport { countBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSource, compareSkillsWithSource, detectProject } from \"../lib/operations/index.js\";\nimport { type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport { fileExists } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\n\ntype ComparisonSummary = {\n outdated: number;\n current: number;\n localOnly: number;\n};\n\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n const counts = countBy(results, (r) => r.status);\n return {\n outdated: counts[\"outdated\"] ?? 0,\n current: counts[\"current\"] ?? 0,\n localOnly: counts[\"local-only\"] ?? 0,\n };\n}\n\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary = \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static examples = [\n {\n description: \"Check for outdated skills\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Output results as JSON\",\n command: \"<%= config.bin %> <%= command.id %> --json\",\n },\n {\n description: \"Check against a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const detected = await detectProject();\n const projectDir = detected?.installation.projectDir ?? process.cwd();\n\n const hasSkills = await this.checkLocalSkillsExist(projectDir, flags.json);\n if (!hasSkills) return;\n\n try {\n const { results, summary, sourceResult } = await this.loadAndCompare(flags, projectDir);\n this.reportResults(results, summary, sourceResult, flags.json);\n\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), { exit: EXIT_CODES.ERROR });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n\n private async checkLocalSkillsExist(projectDir: string, json: boolean): Promise<boolean> {\n const homeDir = os.homedir();\n const hasProject = await fileExists(path.join(projectDir, LOCAL_SKILLS_PATH));\n const hasGlobal =\n projectDir !== homeDir && (await fileExists(path.join(homeDir, LOCAL_SKILLS_PATH)));\n\n if (hasProject || hasGlobal) return true;\n\n if (json) {\n this.log(JSON.stringify({ skills: [], summary: { outdated: 0, current: 0, localOnly: 0 } }));\n } else {\n this.warn(\n `No local skills found. Run \\`${CLI_BIN_NAME} init\\` or \\`${CLI_BIN_NAME} edit\\` first.`,\n );\n }\n return false;\n }\n\n private async loadAndCompare(\n flags: { source?: string; json: boolean },\n projectDir: string,\n ): Promise<{\n results: SkillComparisonResult[];\n summary: ComparisonSummary;\n sourceResult: { isLocal: boolean; sourcePath: string };\n }> {\n if (!flags.json) this.log(\"Loading skills...\");\n\n const { sourceResult } = await loadSource({ sourceFlag: flags.source, projectDir });\n const { matrix, sourcePath, isLocal } = sourceResult;\n\n if (!flags.json) this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n\n const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);\n const summary = calculateSummary(results);\n\n return { results, summary, sourceResult: { isLocal, sourcePath } };\n }\n\n private reportResults(\n results: SkillComparisonResult[],\n summary: ComparisonSummary,\n _sourceResult: { isLocal: boolean; sourcePath: string },\n json: boolean,\n ): void {\n if (json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n return;\n }\n\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n this.log(`Summary: ${formatSummaryParts(summary)}`);\n }\n this.log(\"\");\n }\n}\n\nfunction formatSummaryParts(summary: ComparisonSummary): string {\n const parts: string[] = [];\n if (summary.outdated > 0) parts.push(`${summary.outdated} outdated`);\n if (summary.current > 0) parts.push(`${summary.current} current`);\n if (summary.localOnly > 0) parts.push(`${summary.localOnly} local-only`);\n return parts.join(\", \");\n}\n"],"mappings":"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","names":[]}