@claude-collective/cli 0.2.0 → 0.6.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 (166) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +1 -1
  3. package/dist/chunk-367K3JB3.js +84 -0
  4. package/dist/chunk-367K3JB3.js.map +1 -0
  5. package/dist/chunk-6ESUJMM7.js +54 -0
  6. package/dist/chunk-6ESUJMM7.js.map +1 -0
  7. package/dist/chunk-6OY6ZYQF.js +93 -0
  8. package/dist/chunk-6OY6ZYQF.js.map +1 -0
  9. package/dist/chunk-6WEQADPL.js +307 -0
  10. package/dist/chunk-6WEQADPL.js.map +1 -0
  11. package/dist/chunk-AU7XVCLO.js +91 -0
  12. package/dist/chunk-AU7XVCLO.js.map +1 -0
  13. package/dist/chunk-AZP2AA5M.js +425 -0
  14. package/dist/chunk-AZP2AA5M.js.map +1 -0
  15. package/dist/chunk-D4IQAT27.js +114 -0
  16. package/dist/chunk-D4IQAT27.js.map +1 -0
  17. package/dist/chunk-DHET7RCE.js +50 -0
  18. package/dist/chunk-DHET7RCE.js.map +1 -0
  19. package/dist/chunk-DHFFRMF6.js +31 -0
  20. package/dist/chunk-DHFFRMF6.js.map +1 -0
  21. package/dist/chunk-FKU7VSUD.js +453 -0
  22. package/dist/chunk-FKU7VSUD.js.map +1 -0
  23. package/dist/chunk-J2Y4A3LP.js +478 -0
  24. package/dist/chunk-J2Y4A3LP.js.map +1 -0
  25. package/dist/chunk-JMQGWQZU.js +607 -0
  26. package/dist/chunk-JMQGWQZU.js.map +1 -0
  27. package/dist/chunk-JY4RO76L.js +73 -0
  28. package/dist/chunk-JY4RO76L.js.map +1 -0
  29. package/dist/chunk-M7YCPFIX.js +108 -0
  30. package/dist/chunk-M7YCPFIX.js.map +1 -0
  31. package/dist/chunk-MJSFR562.js +57 -0
  32. package/dist/chunk-MJSFR562.js.map +1 -0
  33. package/dist/chunk-MMDXNZPF.js +69 -0
  34. package/dist/chunk-MMDXNZPF.js.map +1 -0
  35. package/dist/chunk-MYAVQ23U.js +356 -0
  36. package/dist/chunk-MYAVQ23U.js.map +1 -0
  37. package/dist/chunk-OSQDDJXX.js +146 -0
  38. package/dist/chunk-OSQDDJXX.js.map +1 -0
  39. package/dist/chunk-QESUUPOE.js +241 -0
  40. package/dist/chunk-QESUUPOE.js.map +1 -0
  41. package/dist/chunk-SJYG4EJZ.js +57 -0
  42. package/dist/chunk-SJYG4EJZ.js.map +1 -0
  43. package/dist/chunk-SYQ7R2JO.js +95 -0
  44. package/dist/chunk-SYQ7R2JO.js.map +1 -0
  45. package/dist/chunk-TD643KB3.js +245 -0
  46. package/dist/chunk-TD643KB3.js.map +1 -0
  47. package/dist/chunk-TFV6Z7F7.js +129 -0
  48. package/dist/chunk-TFV6Z7F7.js.map +1 -0
  49. package/dist/chunk-TGOHJCQ4.js +83 -0
  50. package/dist/chunk-TGOHJCQ4.js.map +1 -0
  51. package/dist/chunk-TOPAIL5W.js +22 -0
  52. package/dist/chunk-TOPAIL5W.js.map +1 -0
  53. package/dist/chunk-U4VYHKPM.js +110 -0
  54. package/dist/chunk-U4VYHKPM.js.map +1 -0
  55. package/dist/chunk-UFWNMW3G.js +392 -0
  56. package/dist/chunk-UFWNMW3G.js.map +1 -0
  57. package/dist/chunk-UNHCZRO4.js +64 -0
  58. package/dist/chunk-UNHCZRO4.js.map +1 -0
  59. package/dist/chunk-URDV4OCP.js +308 -0
  60. package/dist/chunk-URDV4OCP.js.map +1 -0
  61. package/dist/chunk-YI6JVSFO.js +43 -0
  62. package/dist/chunk-YI6JVSFO.js.map +1 -0
  63. package/dist/chunk-YNSNRR5D.js +184 -0
  64. package/dist/chunk-YNSNRR5D.js.map +1 -0
  65. package/dist/chunk-Z6DLWTBY.js +46 -0
  66. package/dist/chunk-Z6DLWTBY.js.map +1 -0
  67. package/dist/chunk-ZDQIUHAM.js +89 -0
  68. package/dist/chunk-ZDQIUHAM.js.map +1 -0
  69. package/dist/chunk-ZSKHDU5P.js +124 -0
  70. package/dist/chunk-ZSKHDU5P.js.map +1 -0
  71. package/dist/cli-v2/defaults/agent-mappings.yaml +185 -0
  72. package/dist/commands/build/marketplace.js +295 -0
  73. package/dist/commands/build/marketplace.js.map +1 -0
  74. package/dist/commands/build/plugins.js +362 -0
  75. package/dist/commands/build/plugins.js.map +1 -0
  76. package/dist/commands/build/stack.js +169 -0
  77. package/dist/commands/build/stack.js.map +1 -0
  78. package/dist/commands/compile.js +461 -0
  79. package/dist/commands/compile.js.map +1 -0
  80. package/dist/commands/config/get.js +60 -0
  81. package/dist/commands/config/get.js.map +1 -0
  82. package/dist/commands/config/index.js +22 -0
  83. package/dist/commands/config/index.js.map +1 -0
  84. package/dist/commands/config/path.js +35 -0
  85. package/dist/commands/config/path.js.map +1 -0
  86. package/dist/commands/config/set-project.js +61 -0
  87. package/dist/commands/config/set-project.js.map +1 -0
  88. package/dist/commands/config/set.js +60 -0
  89. package/dist/commands/config/set.js.map +1 -0
  90. package/dist/commands/config/show.js +13 -0
  91. package/dist/commands/config/show.js.map +1 -0
  92. package/dist/commands/config/unset-project.js +57 -0
  93. package/dist/commands/config/unset-project.js.map +1 -0
  94. package/dist/commands/config/unset.js +56 -0
  95. package/dist/commands/config/unset.js.map +1 -0
  96. package/dist/commands/diff.js +755 -0
  97. package/dist/commands/diff.js.map +1 -0
  98. package/dist/commands/doctor.js +413 -0
  99. package/dist/commands/doctor.js.map +1 -0
  100. package/dist/commands/edit.js +253 -0
  101. package/dist/commands/edit.js.map +1 -0
  102. package/dist/commands/eject.js +208 -0
  103. package/dist/commands/eject.js.map +1 -0
  104. package/dist/commands/info.js +205 -0
  105. package/dist/commands/info.js.map +1 -0
  106. package/dist/commands/init.js +914 -0
  107. package/dist/commands/init.js.map +1 -0
  108. package/dist/commands/list.js +44 -0
  109. package/dist/commands/list.js.map +1 -0
  110. package/dist/commands/new/agent.js +230 -0
  111. package/dist/commands/new/agent.js.map +1 -0
  112. package/dist/commands/new/skill.js +204 -0
  113. package/dist/commands/new/skill.js.map +1 -0
  114. package/dist/commands/outdated.js +242 -0
  115. package/dist/commands/outdated.js.map +1 -0
  116. package/dist/commands/search.js +115 -0
  117. package/dist/commands/search.js.map +1 -0
  118. package/dist/commands/test-imports.js +92 -0
  119. package/dist/commands/test-imports.js.map +1 -0
  120. package/dist/commands/uninstall.js +302 -0
  121. package/dist/commands/uninstall.js.map +1 -0
  122. package/dist/commands/update.js +428 -0
  123. package/dist/commands/update.js.map +1 -0
  124. package/dist/commands/validate.js +375 -0
  125. package/dist/commands/validate.js.map +1 -0
  126. package/dist/commands/version/bump.js +95 -0
  127. package/dist/commands/version/bump.js.map +1 -0
  128. package/dist/commands/version/index.js +70 -0
  129. package/dist/commands/version/index.js.map +1 -0
  130. package/dist/commands/version/set.js +101 -0
  131. package/dist/commands/version/set.js.map +1 -0
  132. package/dist/commands/version/show.js +70 -0
  133. package/dist/commands/version/show.js.map +1 -0
  134. package/dist/components/common/confirm.js +9 -0
  135. package/dist/components/common/confirm.js.map +1 -0
  136. package/dist/components/common/message.js +24 -0
  137. package/dist/components/common/message.js.map +1 -0
  138. package/dist/components/common/spinner.js +14 -0
  139. package/dist/components/common/spinner.js.map +1 -0
  140. package/dist/components/wizard/selection-header.js +11 -0
  141. package/dist/components/wizard/selection-header.js.map +1 -0
  142. package/dist/components/wizard/step-approach.js +11 -0
  143. package/dist/components/wizard/step-approach.js.map +1 -0
  144. package/dist/components/wizard/step-category.js +12 -0
  145. package/dist/components/wizard/step-category.js.map +1 -0
  146. package/dist/components/wizard/step-confirm.js +12 -0
  147. package/dist/components/wizard/step-confirm.js.map +1 -0
  148. package/dist/components/wizard/step-stack.js +11 -0
  149. package/dist/components/wizard/step-stack.js.map +1 -0
  150. package/dist/components/wizard/step-subcategory.js +13 -0
  151. package/dist/components/wizard/step-subcategory.js.map +1 -0
  152. package/dist/components/wizard/wizard.js +19 -0
  153. package/dist/components/wizard/wizard.js.map +1 -0
  154. package/dist/hooks/init.js +41 -0
  155. package/dist/hooks/init.js.map +1 -0
  156. package/dist/index.js +10 -0
  157. package/dist/index.js.map +1 -0
  158. package/dist/magic-string.es-RGXYGAW3.js +1316 -0
  159. package/dist/magic-string.es-RGXYGAW3.js.map +1 -0
  160. package/dist/stores/wizard-store.js +10 -0
  161. package/dist/stores/wizard-store.js.map +1 -0
  162. package/dist/stores/wizard-store.test.js +15991 -0
  163. package/dist/stores/wizard-store.test.js.map +1 -0
  164. package/package.json +44 -25
  165. package/dist/cli/index.js +0 -6314
  166. package/dist/cli/index.js.map +0 -1
@@ -0,0 +1,307 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ extractAllSkills,
4
+ loadSkillsMatrix,
5
+ loadStacks,
6
+ mergeMatrixWithSkills,
7
+ parseFrontmatter,
8
+ resolveAgentConfigToSkills
9
+ } from "./chunk-JMQGWQZU.js";
10
+ import {
11
+ fetchFromSource
12
+ } from "./chunk-ZSKHDU5P.js";
13
+ import {
14
+ isLocalSource,
15
+ resolveSource
16
+ } from "./chunk-QESUUPOE.js";
17
+ import {
18
+ LOCAL_SKILLS_PATH,
19
+ PROJECT_ROOT,
20
+ SKILLS_DIR_PATH,
21
+ SKILLS_MATRIX_PATH
22
+ } from "./chunk-SJYG4EJZ.js";
23
+ import {
24
+ verbose
25
+ } from "./chunk-TOPAIL5W.js";
26
+ import {
27
+ directoryExists,
28
+ fileExists,
29
+ listDirectories,
30
+ readFile
31
+ } from "./chunk-MMDXNZPF.js";
32
+ import {
33
+ init_esm_shims
34
+ } from "./chunk-DHET7RCE.js";
35
+
36
+ // src/cli-v2/lib/local-skill-loader.ts
37
+ init_esm_shims();
38
+ import { parse as parseYaml } from "yaml";
39
+ import path from "path";
40
+ var LOCAL_CATEGORY = "local";
41
+ var LOCAL_AUTHOR = "@local";
42
+ async function discoverLocalSkills(projectDir) {
43
+ const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);
44
+ if (!await directoryExists(localSkillsPath)) {
45
+ verbose(`Local skills directory not found: ${localSkillsPath}`);
46
+ return null;
47
+ }
48
+ const skills = [];
49
+ const skillDirs = await listDirectories(localSkillsPath);
50
+ for (const skillDirName of skillDirs) {
51
+ const skill = await extractLocalSkill(localSkillsPath, skillDirName);
52
+ if (skill) {
53
+ skills.push(skill);
54
+ }
55
+ }
56
+ verbose(`Discovered ${skills.length} local skills from ${localSkillsPath}`);
57
+ return {
58
+ skills,
59
+ localSkillsPath
60
+ };
61
+ }
62
+ async function extractLocalSkill(localSkillsPath, skillDirName) {
63
+ const skillDir = path.join(localSkillsPath, skillDirName);
64
+ const metadataPath = path.join(skillDir, "metadata.yaml");
65
+ const skillMdPath = path.join(skillDir, "SKILL.md");
66
+ if (!await fileExists(metadataPath)) {
67
+ verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);
68
+ return null;
69
+ }
70
+ if (!await fileExists(skillMdPath)) {
71
+ verbose(`Skipping local skill '${skillDirName}': No SKILL.md found`);
72
+ return null;
73
+ }
74
+ const metadataContent = await readFile(metadataPath);
75
+ const metadata = parseYaml(metadataContent);
76
+ if (!metadata.cli_name) {
77
+ verbose(
78
+ `Skipping local skill '${skillDirName}': Missing required 'cli_name' in metadata.yaml`
79
+ );
80
+ return null;
81
+ }
82
+ const skillMdContent = await readFile(skillMdPath);
83
+ const frontmatter = parseFrontmatter(skillMdContent);
84
+ if (!frontmatter) {
85
+ verbose(
86
+ `Skipping local skill '${skillDirName}': Invalid SKILL.md frontmatter`
87
+ );
88
+ return null;
89
+ }
90
+ const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;
91
+ const skillId = frontmatter.name;
92
+ const extracted = {
93
+ id: skillId,
94
+ directoryPath: skillDirName,
95
+ name: `${metadata.cli_name} ${LOCAL_AUTHOR}`,
96
+ description: metadata.cli_description || frontmatter.description,
97
+ usageGuidance: void 0,
98
+ category: LOCAL_CATEGORY,
99
+ categoryExclusive: false,
100
+ author: LOCAL_AUTHOR,
101
+ tags: [],
102
+ compatibleWith: [],
103
+ conflictsWith: [],
104
+ requires: [],
105
+ requiresSetup: [],
106
+ providesSetupFor: [],
107
+ path: relativePath,
108
+ local: true,
109
+ localPath: relativePath
110
+ };
111
+ verbose(`Extracted local skill: ${skillId}`);
112
+ return extracted;
113
+ }
114
+
115
+ // src/cli-v2/lib/source-loader.ts
116
+ init_esm_shims();
117
+ import path2 from "path";
118
+ async function loadSkillsMatrixFromSource(options = {}) {
119
+ const {
120
+ sourceFlag,
121
+ projectDir,
122
+ forceRefresh = false,
123
+ devMode = false
124
+ } = options;
125
+ const sourceConfig = await resolveSource(sourceFlag, projectDir);
126
+ const { source } = sourceConfig;
127
+ verbose(`Loading skills from source: ${source}`);
128
+ const isLocal = isLocalSource(source) || devMode === true;
129
+ let result;
130
+ if (isLocal) {
131
+ result = await loadFromLocal(source, sourceConfig);
132
+ } else {
133
+ result = await loadFromRemote(source, sourceConfig, forceRefresh);
134
+ }
135
+ const resolvedProjectDir = projectDir || process.cwd();
136
+ const localSkillsResult = await discoverLocalSkills(resolvedProjectDir);
137
+ if (localSkillsResult && localSkillsResult.skills.length > 0) {
138
+ verbose(
139
+ `Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`
140
+ );
141
+ result.matrix = mergeLocalSkillsIntoMatrix(
142
+ result.matrix,
143
+ localSkillsResult
144
+ );
145
+ }
146
+ return result;
147
+ }
148
+ async function loadFromLocal(source, sourceConfig) {
149
+ let skillsPath;
150
+ if (isLocalSource(source)) {
151
+ skillsPath = path2.isAbsolute(source) ? source : path2.resolve(process.cwd(), source);
152
+ } else {
153
+ skillsPath = PROJECT_ROOT;
154
+ }
155
+ verbose(`Loading skills from local path: ${skillsPath}`);
156
+ const sourceMatrixPath = path2.join(skillsPath, SKILLS_MATRIX_PATH);
157
+ const cliMatrixPath = path2.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);
158
+ let matrixPath;
159
+ if (await fileExists(sourceMatrixPath)) {
160
+ matrixPath = sourceMatrixPath;
161
+ verbose(`Matrix from source: ${matrixPath}`);
162
+ } else {
163
+ matrixPath = cliMatrixPath;
164
+ verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);
165
+ }
166
+ const skillsDir = path2.join(skillsPath, SKILLS_DIR_PATH);
167
+ verbose(`Skills from source: ${skillsDir}`);
168
+ const matrix = await loadSkillsMatrix(matrixPath);
169
+ const skills = await extractAllSkills(skillsDir);
170
+ const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);
171
+ const stacks = await loadStacks(PROJECT_ROOT);
172
+ if (stacks.length > 0) {
173
+ mergedMatrix.suggestedStacks = stacks.map(
174
+ (stack) => stackToResolvedStack(stack, mergedMatrix.aliases)
175
+ );
176
+ verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);
177
+ }
178
+ return {
179
+ matrix: mergedMatrix,
180
+ sourceConfig,
181
+ sourcePath: skillsPath,
182
+ isLocal: true,
183
+ marketplace: sourceConfig.marketplace
184
+ };
185
+ }
186
+ async function loadFromRemote(source, sourceConfig, forceRefresh) {
187
+ verbose(`Fetching skills from remote source: ${source}`);
188
+ const fetchResult = await fetchFromSource(source, { forceRefresh });
189
+ verbose(`Fetched to: ${fetchResult.path}`);
190
+ const sourceMatrixPath = path2.join(fetchResult.path, SKILLS_MATRIX_PATH);
191
+ const cliMatrixPath = path2.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);
192
+ let matrixPath;
193
+ if (await fileExists(sourceMatrixPath)) {
194
+ matrixPath = sourceMatrixPath;
195
+ verbose(`Matrix from source: ${matrixPath}`);
196
+ } else {
197
+ matrixPath = cliMatrixPath;
198
+ verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);
199
+ }
200
+ const skillsDir = path2.join(fetchResult.path, SKILLS_DIR_PATH);
201
+ verbose(`Skills from source: ${skillsDir}`);
202
+ const matrix = await loadSkillsMatrix(matrixPath);
203
+ const skills = await extractAllSkills(skillsDir);
204
+ const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);
205
+ const stacks = await loadStacks(PROJECT_ROOT);
206
+ if (stacks.length > 0) {
207
+ mergedMatrix.suggestedStacks = stacks.map(
208
+ (stack) => stackToResolvedStack(stack, mergedMatrix.aliases)
209
+ );
210
+ verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);
211
+ }
212
+ return {
213
+ matrix: mergedMatrix,
214
+ sourceConfig,
215
+ sourcePath: fetchResult.path,
216
+ isLocal: false,
217
+ marketplace: sourceConfig.marketplace
218
+ };
219
+ }
220
+ function stackToResolvedStack(stack, skillAliases) {
221
+ const allSkillIds = [];
222
+ const seenSkillIds = /* @__PURE__ */ new Set();
223
+ for (const agentId of Object.keys(stack.agents)) {
224
+ const agentConfig = stack.agents[agentId];
225
+ const skillRefs = resolveAgentConfigToSkills(agentConfig, skillAliases);
226
+ for (const ref of skillRefs) {
227
+ if (!seenSkillIds.has(ref.id)) {
228
+ seenSkillIds.add(ref.id);
229
+ allSkillIds.push(ref.id);
230
+ }
231
+ }
232
+ }
233
+ const agentCount = Object.keys(stack.agents).length;
234
+ verbose(
235
+ `Stack '${stack.id}' has ${allSkillIds.length} skills from ${agentCount} agents`
236
+ );
237
+ return {
238
+ id: stack.id,
239
+ name: stack.name,
240
+ description: stack.description,
241
+ audience: [],
242
+ // Not used in new format
243
+ skills: {},
244
+ // Skills come from stack agent configs, resolved at runtime
245
+ allSkillIds,
246
+ philosophy: stack.philosophy || ""
247
+ };
248
+ }
249
+ var LOCAL_CATEGORY_TOP = {
250
+ id: "local",
251
+ name: "Local Skills",
252
+ description: "Project-specific skills from .claude/skills/",
253
+ exclusive: false,
254
+ required: false,
255
+ order: 0
256
+ };
257
+ var LOCAL_CATEGORY_CUSTOM = {
258
+ id: "local/custom",
259
+ name: "Custom",
260
+ description: "Your project-specific skills",
261
+ exclusive: false,
262
+ required: false,
263
+ order: 0,
264
+ parent: "local"
265
+ };
266
+ function mergeLocalSkillsIntoMatrix(matrix, localResult) {
267
+ if (!matrix.categories["local"]) {
268
+ matrix.categories["local"] = LOCAL_CATEGORY_TOP;
269
+ }
270
+ if (!matrix.categories["local/custom"]) {
271
+ matrix.categories["local/custom"] = LOCAL_CATEGORY_CUSTOM;
272
+ }
273
+ for (const metadata of localResult.skills) {
274
+ const resolvedSkill = {
275
+ id: metadata.id,
276
+ alias: void 0,
277
+ name: metadata.name,
278
+ description: metadata.description,
279
+ usageGuidance: metadata.usageGuidance,
280
+ category: "local/custom",
281
+ categoryExclusive: false,
282
+ tags: metadata.tags ?? [],
283
+ author: "@local",
284
+ conflictsWith: [],
285
+ recommends: [],
286
+ recommendedBy: [],
287
+ requires: [],
288
+ requiredBy: [],
289
+ alternatives: [],
290
+ discourages: [],
291
+ requiresSetup: [],
292
+ providesSetupFor: [],
293
+ path: metadata.path,
294
+ local: true,
295
+ localPath: metadata.localPath
296
+ };
297
+ matrix.skills[metadata.id] = resolvedSkill;
298
+ verbose(`Added local skill: ${metadata.id}`);
299
+ }
300
+ return matrix;
301
+ }
302
+
303
+ export {
304
+ discoverLocalSkills,
305
+ loadSkillsMatrixFromSource
306
+ };
307
+ //# sourceMappingURL=chunk-6WEQADPL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/lib/local-skill-loader.ts","../src/cli-v2/lib/source-loader.ts"],"sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport {\n directoryExists,\n listDirectories,\n fileExists,\n readFile,\n} from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { LOCAL_SKILLS_PATH } from \"../consts\";\nimport { parseFrontmatter } from \"./loader\";\nimport type { ExtractedSkillMetadata } from \"../types-matrix\";\n\nconst LOCAL_CATEGORY = \"local\";\nconst LOCAL_AUTHOR = \"@local\";\n\ninterface LocalRawMetadata {\n cli_name: string;\n cli_description?: string;\n}\n\nexport interface LocalSkillDiscoveryResult {\n skills: ExtractedSkillMetadata[];\n localSkillsPath: string;\n}\n\nexport async function discoverLocalSkills(\n projectDir: string,\n): Promise<LocalSkillDiscoveryResult | null> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (!(await directoryExists(localSkillsPath))) {\n verbose(`Local skills directory not found: ${localSkillsPath}`);\n return null;\n }\n\n const skills: ExtractedSkillMetadata[] = [];\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const skillDirName of skillDirs) {\n const skill = await extractLocalSkill(localSkillsPath, skillDirName);\n if (skill) {\n skills.push(skill);\n }\n }\n\n verbose(`Discovered ${skills.length} local skills from ${localSkillsPath}`);\n\n return {\n skills,\n localSkillsPath,\n };\n}\n\nasync function extractLocalSkill(\n localSkillsPath: string,\n skillDirName: string,\n): Promise<ExtractedSkillMetadata | null> {\n const skillDir = path.join(localSkillsPath, skillDirName);\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n const skillMdPath = path.join(skillDir, \"SKILL.md\");\n\n if (!(await fileExists(metadataPath))) {\n verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);\n return null;\n }\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping local skill '${skillDirName}': No SKILL.md found`);\n return null;\n }\n\n const metadataContent = await readFile(metadataPath);\n const metadata = parseYaml(metadataContent) as LocalRawMetadata;\n\n if (!metadata.cli_name) {\n verbose(\n `Skipping local skill '${skillDirName}': Missing required 'cli_name' in metadata.yaml`,\n );\n return null;\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent);\n\n if (!frontmatter) {\n verbose(\n `Skipping local skill '${skillDirName}': Invalid SKILL.md frontmatter`,\n );\n return null;\n }\n\n const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;\n const skillId = frontmatter.name;\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDirName,\n name: `${metadata.cli_name} ${LOCAL_AUTHOR}`,\n description: metadata.cli_description || frontmatter.description,\n usageGuidance: undefined,\n category: LOCAL_CATEGORY,\n categoryExclusive: false,\n author: LOCAL_AUTHOR,\n tags: [],\n compatibleWith: [],\n conflictsWith: [],\n requires: [],\n requiresSetup: [],\n providesSetupFor: [],\n path: relativePath,\n local: true,\n localPath: relativePath,\n };\n\n verbose(`Extracted local skill: ${skillId}`);\n return extracted;\n}\n","import path from \"path\";\nimport { PROJECT_ROOT, SKILLS_DIR_PATH, SKILLS_MATRIX_PATH } from \"../consts\";\nimport type {\n CategoryDefinition,\n MergedSkillsMatrix,\n ResolvedSkill,\n ResolvedStack,\n} from \"../types-matrix\";\nimport type { Stack } from \"../types-stacks\";\nimport { fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { isLocalSource, resolveSource, type ResolvedConfig } from \"./config\";\nimport {\n discoverLocalSkills,\n type LocalSkillDiscoveryResult,\n} from \"./local-skill-loader\";\nimport {\n extractAllSkills,\n loadSkillsMatrix,\n mergeMatrixWithSkills,\n} from \"./matrix-loader\";\nimport { fetchFromSource } from \"./source-fetcher\";\nimport { loadStacks, resolveAgentConfigToSkills } from \"./stacks-loader\";\n\nexport interface SourceLoadOptions {\n sourceFlag?: string;\n projectDir?: string;\n forceRefresh?: boolean;\n devMode?: boolean;\n}\n\nexport interface SourceLoadResult {\n matrix: MergedSkillsMatrix;\n sourceConfig: ResolvedConfig;\n sourcePath: string;\n isLocal: boolean;\n marketplace?: string;\n}\n\nexport async function loadSkillsMatrixFromSource(\n options: SourceLoadOptions = {},\n): Promise<SourceLoadResult> {\n const {\n sourceFlag,\n projectDir,\n forceRefresh = false,\n devMode = false,\n } = options;\n\n const sourceConfig = await resolveSource(sourceFlag, projectDir);\n const { source } = sourceConfig;\n\n verbose(`Loading skills from source: ${source}`);\n\n const isLocal = isLocalSource(source) || devMode === true;\n\n let result: SourceLoadResult;\n if (isLocal) {\n result = await loadFromLocal(source, sourceConfig);\n } else {\n result = await loadFromRemote(source, sourceConfig, forceRefresh);\n }\n\n const resolvedProjectDir = projectDir || process.cwd();\n const localSkillsResult = await discoverLocalSkills(resolvedProjectDir);\n\n if (localSkillsResult && localSkillsResult.skills.length > 0) {\n verbose(\n `Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`,\n );\n result.matrix = mergeLocalSkillsIntoMatrix(\n result.matrix,\n localSkillsResult,\n );\n }\n\n return result;\n}\n\nasync function loadFromLocal(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<SourceLoadResult> {\n let skillsPath: string;\n\n if (isLocalSource(source)) {\n skillsPath = path.isAbsolute(source)\n ? source\n : path.resolve(process.cwd(), source);\n } else {\n skillsPath = PROJECT_ROOT;\n }\n\n verbose(`Loading skills from local path: ${skillsPath}`);\n\n // Check if source has its own matrix, otherwise fallback to CLI matrix\n const sourceMatrixPath = path.join(skillsPath, SKILLS_MATRIX_PATH);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(skillsPath, SKILLS_DIR_PATH);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from CLI's config/stacks.yaml (Phase 6: agent-centric config)\n const stacks = await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n // Phase 7: Skills are defined in stacks (per agent, per subcategory), not in agent YAMLs\n // Use skill_aliases from the matrix to resolve technology aliases to full skill IDs\n mergedMatrix.suggestedStacks = stacks.map((stack) =>\n stackToResolvedStack(stack, mergedMatrix.aliases),\n );\n verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: skillsPath,\n isLocal: true,\n marketplace: sourceConfig.marketplace,\n };\n}\n\nasync function loadFromRemote(\n source: string,\n sourceConfig: ResolvedConfig,\n forceRefresh: boolean,\n): Promise<SourceLoadResult> {\n verbose(`Fetching skills from remote source: ${source}`);\n\n const fetchResult = await fetchFromSource(source, { forceRefresh });\n\n verbose(`Fetched to: ${fetchResult.path}`);\n\n // Check if source has its own matrix, otherwise fallback to CLI matrix\n const sourceMatrixPath = path.join(fetchResult.path, SKILLS_MATRIX_PATH);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(fetchResult.path, SKILLS_DIR_PATH);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from CLI's config/stacks.yaml (Phase 6: agent-centric config)\n const stacks = await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n // Phase 7: Skills are defined in stacks (per agent, per subcategory), not in agent YAMLs\n // Use skill_aliases from the matrix to resolve technology aliases to full skill IDs\n mergedMatrix.suggestedStacks = stacks.map((stack) =>\n stackToResolvedStack(stack, mergedMatrix.aliases),\n );\n verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: fetchResult.path,\n isLocal: false,\n marketplace: sourceConfig.marketplace,\n };\n}\n\n/**\n * Convert a Stack (from config/stacks.yaml) to ResolvedStack format\n * for compatibility with the wizard.\n *\n * Phase 7: Skills are defined in stacks per agent (subcategory -> technology alias).\n * Uses skill_aliases from the matrix to resolve aliases to full skill IDs.\n */\nfunction stackToResolvedStack(\n stack: Stack,\n skillAliases: Record<string, string>,\n): ResolvedStack {\n // Collect all unique skill IDs from agent configs in this stack\n const allSkillIds: string[] = [];\n const seenSkillIds = new Set<string>();\n\n // stack.agents is Record<string, StackAgentConfig> - iterate over agent IDs\n for (const agentId of Object.keys(stack.agents)) {\n const agentConfig = stack.agents[agentId];\n\n // Resolve this agent's technology selections to skill IDs\n const skillRefs = resolveAgentConfigToSkills(agentConfig, skillAliases);\n\n for (const ref of skillRefs) {\n if (!seenSkillIds.has(ref.id)) {\n seenSkillIds.add(ref.id);\n allSkillIds.push(ref.id);\n }\n }\n }\n\n const agentCount = Object.keys(stack.agents).length;\n verbose(\n `Stack '${stack.id}' has ${allSkillIds.length} skills from ${agentCount} agents`,\n );\n\n return {\n id: stack.id,\n name: stack.name,\n description: stack.description,\n audience: [], // Not used in new format\n skills: {}, // Skills come from stack agent configs, resolved at runtime\n allSkillIds,\n philosophy: stack.philosophy || \"\",\n };\n}\n\nconst LOCAL_CATEGORY_TOP: CategoryDefinition = {\n id: \"local\",\n name: \"Local Skills\",\n description: \"Project-specific skills from .claude/skills/\",\n exclusive: false,\n required: false,\n order: 0,\n};\n\nconst LOCAL_CATEGORY_CUSTOM: CategoryDefinition = {\n id: \"local/custom\",\n name: \"Custom\",\n description: \"Your project-specific skills\",\n exclusive: false,\n required: false,\n order: 0,\n parent: \"local\",\n};\n\nfunction mergeLocalSkillsIntoMatrix(\n matrix: MergedSkillsMatrix,\n localResult: LocalSkillDiscoveryResult,\n): MergedSkillsMatrix {\n if (!matrix.categories[\"local\"]) {\n matrix.categories[\"local\"] = LOCAL_CATEGORY_TOP;\n }\n if (!matrix.categories[\"local/custom\"]) {\n matrix.categories[\"local/custom\"] = LOCAL_CATEGORY_CUSTOM;\n }\n\n for (const metadata of localResult.skills) {\n const resolvedSkill: ResolvedSkill = {\n id: metadata.id,\n alias: undefined,\n name: metadata.name,\n description: metadata.description,\n usageGuidance: metadata.usageGuidance,\n\n category: \"local/custom\",\n categoryExclusive: false,\n tags: metadata.tags ?? [],\n\n author: \"@local\",\n\n conflictsWith: [],\n recommends: [],\n recommendedBy: [],\n requires: [],\n requiredBy: [],\n alternatives: [],\n discourages: [],\n\n requiresSetup: [],\n providesSetupFor: [],\n\n path: metadata.path,\n\n local: true,\n localPath: metadata.localPath,\n };\n\n matrix.skills[metadata.id] = resolvedSkill;\n verbose(`Added local skill: ${metadata.id}`);\n }\n\n return matrix;\n}\n"],"mappings":"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","names":["path","path"]}
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DEFAULT_VERSION
4
+ } from "./chunk-SJYG4EJZ.js";
5
+ import {
6
+ ensureDir,
7
+ writeFile
8
+ } from "./chunk-MMDXNZPF.js";
9
+ import {
10
+ init_esm_shims
11
+ } from "./chunk-DHET7RCE.js";
12
+
13
+ // src/cli-v2/lib/plugin-manifest.ts
14
+ init_esm_shims();
15
+ import path from "path";
16
+ var DEFAULT_LICENSE = "MIT";
17
+ var PLUGIN_DIR_NAME = ".claude-plugin";
18
+ var PLUGIN_MANIFEST_FILE = "plugin.json";
19
+ var SKILL_PLUGIN_PREFIX = "skill-";
20
+ function buildAuthor(name, email) {
21
+ if (!name) {
22
+ return void 0;
23
+ }
24
+ const author = { name };
25
+ if (email) {
26
+ author.email = email;
27
+ }
28
+ return author;
29
+ }
30
+ function generateSkillPluginManifest(options) {
31
+ const manifest = {
32
+ name: `${SKILL_PLUGIN_PREFIX}${options.skillName}`,
33
+ version: options.version ?? DEFAULT_VERSION,
34
+ license: DEFAULT_LICENSE,
35
+ skills: "./skills/"
36
+ };
37
+ if (options.description) {
38
+ manifest.description = options.description;
39
+ }
40
+ const author = buildAuthor(options.author, options.authorEmail);
41
+ if (author) {
42
+ manifest.author = author;
43
+ }
44
+ if (options.keywords && options.keywords.length > 0) {
45
+ manifest.keywords = options.keywords;
46
+ }
47
+ return manifest;
48
+ }
49
+ function generateStackPluginManifest(options) {
50
+ const manifest = {
51
+ name: options.stackName,
52
+ version: options.version ?? DEFAULT_VERSION,
53
+ license: DEFAULT_LICENSE
54
+ };
55
+ if (options.hasSkills) {
56
+ manifest.skills = "./skills/";
57
+ }
58
+ if (options.description) {
59
+ manifest.description = options.description;
60
+ }
61
+ const author = buildAuthor(options.author, options.authorEmail);
62
+ if (author) {
63
+ manifest.author = author;
64
+ }
65
+ if (options.keywords && options.keywords.length > 0) {
66
+ manifest.keywords = options.keywords;
67
+ }
68
+ if (options.hasHooks) {
69
+ manifest.hooks = "./hooks/hooks.json";
70
+ }
71
+ return manifest;
72
+ }
73
+ async function writePluginManifest(outputDir, manifest) {
74
+ const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);
75
+ const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);
76
+ await ensureDir(pluginDir);
77
+ const content = JSON.stringify(manifest, null, 2);
78
+ await writeFile(manifestPath, content);
79
+ return manifestPath;
80
+ }
81
+ function getPluginManifestPath(outputDir) {
82
+ return path.join(outputDir, PLUGIN_DIR_NAME, PLUGIN_MANIFEST_FILE);
83
+ }
84
+
85
+ export {
86
+ generateSkillPluginManifest,
87
+ generateStackPluginManifest,
88
+ writePluginManifest,
89
+ getPluginManifestPath
90
+ };
91
+ //# sourceMappingURL=chunk-AU7XVCLO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-v2/lib/plugin-manifest.ts"],"sourcesContent":["import path from \"path\";\nimport { ensureDir, writeFile } from \"../utils/fs\";\nimport { DEFAULT_VERSION } from \"../consts\";\nimport type { PluginManifest, PluginAuthor } from \"../../types\";\n\nconst DEFAULT_LICENSE = \"MIT\";\nconst PLUGIN_DIR_NAME = \".claude-plugin\";\nconst PLUGIN_MANIFEST_FILE = \"plugin.json\";\nconst SKILL_PLUGIN_PREFIX = \"skill-\";\n\nexport interface SkillPluginOptions {\n skillName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n}\n\nexport interface StackPluginOptions {\n stackName: string;\n description?: string;\n author?: string;\n authorEmail?: string;\n version?: string;\n keywords?: string[];\n hasSkills?: boolean;\n hasAgents?: boolean;\n hasHooks?: boolean;\n}\n\nfunction buildAuthor(name?: string, email?: string): PluginAuthor | undefined {\n if (!name) {\n return undefined;\n }\n const author: PluginAuthor = { name };\n if (email) {\n author.email = email;\n }\n return author;\n}\n\nexport function generateSkillPluginManifest(\n options: SkillPluginOptions,\n): PluginManifest {\n const manifest: PluginManifest = {\n name: `${SKILL_PLUGIN_PREFIX}${options.skillName}`,\n version: options.version ?? DEFAULT_VERSION,\n license: DEFAULT_LICENSE,\n skills: \"./skills/\",\n };\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n return manifest;\n}\n\nexport function generateStackPluginManifest(\n options: StackPluginOptions,\n): PluginManifest {\n const manifest: PluginManifest = {\n name: options.stackName,\n version: options.version ?? DEFAULT_VERSION,\n license: DEFAULT_LICENSE,\n };\n\n if (options.hasSkills) {\n manifest.skills = \"./skills/\";\n }\n\n if (options.description) {\n manifest.description = options.description;\n }\n\n const author = buildAuthor(options.author, options.authorEmail);\n if (author) {\n manifest.author = author;\n }\n\n if (options.keywords && options.keywords.length > 0) {\n manifest.keywords = options.keywords;\n }\n\n // Note: Claude Code plugins don't support agents field in manifest\n // Agents are discovered from ./agents/ directory automatically\n\n if (options.hasHooks) {\n manifest.hooks = \"./hooks/hooks.json\";\n }\n\n return manifest;\n}\n\nexport async function writePluginManifest(\n outputDir: string,\n manifest: PluginManifest,\n): Promise<string> {\n const pluginDir = path.join(outputDir, PLUGIN_DIR_NAME);\n const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_FILE);\n\n await ensureDir(pluginDir);\n\n const content = JSON.stringify(manifest, null, 2);\n await writeFile(manifestPath, content);\n\n return manifestPath;\n}\n\nexport function getPluginDir(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME);\n}\n\nexport function getPluginManifestPath(outputDir: string): string {\n return path.join(outputDir, PLUGIN_DIR_NAME, PLUGIN_MANIFEST_FILE);\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AAAA,OAAO,UAAU;AAKjB,IAAM,kBAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAuB5B,SAAS,YAAY,MAAe,OAA0C;AAC5E,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AACA,QAAM,SAAuB,EAAE,KAAK;AACpC,MAAI,OAAO;AACT,WAAO,QAAQ;AAAA,EACjB;AACA,SAAO;AACT;AAEO,SAAS,4BACd,SACgB;AAChB,QAAM,WAA2B;AAAA,IAC/B,MAAM,GAAG,mBAAmB,GAAG,QAAQ,SAAS;AAAA,IAChD,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,MAAI,QAAQ,aAAa;AACvB,aAAS,cAAc,QAAQ;AAAA,EACjC;AAEA,QAAM,SAAS,YAAY,QAAQ,QAAQ,QAAQ,WAAW;AAC9D,MAAI,QAAQ;AACV,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,aAAS,WAAW,QAAQ;AAAA,EAC9B;AAEA,SAAO;AACT;AAEO,SAAS,4BACd,SACgB;AAChB,QAAM,WAA2B;AAAA,IAC/B,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS;AAAA,EACX;AAEA,MAAI,QAAQ,WAAW;AACrB,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,aAAa;AACvB,aAAS,cAAc,QAAQ;AAAA,EACjC;AAEA,QAAM,SAAS,YAAY,QAAQ,QAAQ,QAAQ,WAAW;AAC9D,MAAI,QAAQ;AACV,aAAS,SAAS;AAAA,EACpB;AAEA,MAAI,QAAQ,YAAY,QAAQ,SAAS,SAAS,GAAG;AACnD,aAAS,WAAW,QAAQ;AAAA,EAC9B;AAKA,MAAI,QAAQ,UAAU;AACpB,aAAS,QAAQ;AAAA,EACnB;AAEA,SAAO;AACT;AAEA,eAAsB,oBACpB,WACA,UACiB;AACjB,QAAM,YAAY,KAAK,KAAK,WAAW,eAAe;AACtD,QAAM,eAAe,KAAK,KAAK,WAAW,oBAAoB;AAE9D,QAAM,UAAU,SAAS;AAEzB,QAAM,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC;AAChD,QAAM,UAAU,cAAc,OAAO;AAErC,SAAO;AACT;AAMO,SAAS,sBAAsB,WAA2B;AAC/D,SAAO,KAAK,KAAK,WAAW,iBAAiB,oBAAoB;AACnE;","names":[]}