@claude-collective/cli 0.6.0 → 0.13.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 (232) hide show
  1. package/CHANGELOG.md +192 -0
  2. package/README.md +26 -9
  3. package/dist/{chunk-TOPAIL5W.js → chunk-3U3R4NCG.js} +2 -2
  4. package/dist/chunk-3U3R4NCG.js.map +1 -0
  5. package/dist/{chunk-TFV6Z7F7.js → chunk-57Y5RALO.js} +10 -10
  6. package/dist/chunk-57Y5RALO.js.map +1 -0
  7. package/dist/chunk-66UDJBF6.js +96 -0
  8. package/dist/chunk-66UDJBF6.js.map +1 -0
  9. package/dist/chunk-6DCSSORF.js +264 -0
  10. package/dist/chunk-6DCSSORF.js.map +1 -0
  11. package/dist/chunk-6Q3Y7KVB.js +31 -0
  12. package/dist/chunk-6Q3Y7KVB.js.map +1 -0
  13. package/dist/{chunk-SJYG4EJZ.js → chunk-76DWXGQE.js} +10 -8
  14. package/dist/chunk-76DWXGQE.js.map +1 -0
  15. package/dist/{chunk-AZP2AA5M.js → chunk-7Q44DMSP.js} +241 -84
  16. package/dist/chunk-7Q44DMSP.js.map +1 -0
  17. package/dist/chunk-ACNBKXXJ.js +321 -0
  18. package/dist/chunk-ACNBKXXJ.js.map +1 -0
  19. package/dist/{chunk-JMQGWQZU.js → chunk-B7CCVP6Q.js} +42 -10
  20. package/dist/chunk-B7CCVP6Q.js.map +1 -0
  21. package/dist/chunk-BDLUZVKU.js +54 -0
  22. package/dist/chunk-BDLUZVKU.js.map +1 -0
  23. package/dist/chunk-CDX4W4DM.js +120 -0
  24. package/dist/chunk-CDX4W4DM.js.map +1 -0
  25. package/dist/{chunk-MYAVQ23U.js → chunk-CJEHB4TB.js} +23 -9
  26. package/dist/chunk-CJEHB4TB.js.map +1 -0
  27. package/dist/{chunk-6WEQADPL.js → chunk-CPZOTVCI.js} +15 -14
  28. package/dist/chunk-CPZOTVCI.js.map +1 -0
  29. package/dist/chunk-D237EVNB.js +187 -0
  30. package/dist/chunk-D237EVNB.js.map +1 -0
  31. package/dist/{chunk-UFWNMW3G.js → chunk-DRXPNNPB.js} +19 -18
  32. package/dist/chunk-DRXPNNPB.js.map +1 -0
  33. package/dist/chunk-E3FJH4TF.js +80 -0
  34. package/dist/chunk-E3FJH4TF.js.map +1 -0
  35. package/dist/{chunk-D4IQAT27.js → chunk-ED4E6Q2T.js} +10 -10
  36. package/dist/chunk-ED4E6Q2T.js.map +1 -0
  37. package/dist/{chunk-SYQ7R2JO.js → chunk-EHS3TWWP.js} +3 -3
  38. package/dist/chunk-EHS3TWWP.js.map +1 -0
  39. package/dist/{chunk-AU7XVCLO.js → chunk-GDH553MV.js} +6 -6
  40. package/dist/chunk-GDH553MV.js.map +1 -0
  41. package/dist/chunk-HLJX2FTL.js +95 -0
  42. package/dist/chunk-HLJX2FTL.js.map +1 -0
  43. package/dist/chunk-I2DSLOXZ.js +75 -0
  44. package/dist/chunk-I2DSLOXZ.js.map +1 -0
  45. package/dist/{chunk-J2Y4A3LP.js → chunk-I4TPKIYX.js} +33 -18
  46. package/dist/chunk-I4TPKIYX.js.map +1 -0
  47. package/dist/{chunk-ZSKHDU5P.js → chunk-IMDW5ZUP.js} +19 -11
  48. package/dist/chunk-IMDW5ZUP.js.map +1 -0
  49. package/dist/{chunk-U4VYHKPM.js → chunk-JIPWV2FX.js} +6 -6
  50. package/dist/chunk-JIPWV2FX.js.map +1 -0
  51. package/dist/{chunk-OSQDDJXX.js → chunk-K7EVM5LY.js} +5 -10
  52. package/dist/chunk-K7EVM5LY.js.map +1 -0
  53. package/dist/{chunk-MJSFR562.js → chunk-KAAEN2PO.js} +3 -3
  54. package/dist/chunk-KAAEN2PO.js.map +1 -0
  55. package/dist/{chunk-URDV4OCP.js → chunk-LE6IY6IT.js} +22 -17
  56. package/dist/chunk-LE6IY6IT.js.map +1 -0
  57. package/dist/{chunk-FKU7VSUD.js → chunk-NDY25DTL.js} +6 -6
  58. package/dist/chunk-NDY25DTL.js.map +1 -0
  59. package/dist/{chunk-UNHCZRO4.js → chunk-P26A2K5N.js} +7 -7
  60. package/dist/chunk-P26A2K5N.js.map +1 -0
  61. package/dist/{chunk-DHFFRMF6.js → chunk-RTE64SJA.js} +2 -2
  62. package/dist/chunk-RTE64SJA.js.map +1 -0
  63. package/dist/{chunk-6ESUJMM7.js → chunk-SGJ23HIP.js} +14 -11
  64. package/dist/chunk-SGJ23HIP.js.map +1 -0
  65. package/dist/{chunk-367K3JB3.js → chunk-SVYPSDWY.js} +10 -10
  66. package/dist/chunk-SVYPSDWY.js.map +1 -0
  67. package/dist/{chunk-MMDXNZPF.js → chunk-TKFPKEV3.js} +2 -2
  68. package/dist/chunk-TKFPKEV3.js.map +1 -0
  69. package/dist/{chunk-M7YCPFIX.js → chunk-UQTEPWU7.js} +2 -2
  70. package/dist/chunk-UQTEPWU7.js.map +1 -0
  71. package/dist/{chunk-QESUUPOE.js → chunk-V46GGCCI.js} +80 -27
  72. package/dist/chunk-V46GGCCI.js.map +1 -0
  73. package/dist/chunk-X6QONICW.js +86 -0
  74. package/dist/chunk-X6QONICW.js.map +1 -0
  75. package/dist/chunk-XY3XDVMI.js +15599 -0
  76. package/dist/chunk-XY3XDVMI.js.map +1 -0
  77. package/dist/chunk-Y2LW7R3Y.js +23 -0
  78. package/dist/chunk-Y2LW7R3Y.js.map +1 -0
  79. package/dist/chunk-Z2CWURZ6.js +78 -0
  80. package/dist/chunk-Z2CWURZ6.js.map +1 -0
  81. package/dist/chunk-Z7G4B5HJ.js +377 -0
  82. package/dist/chunk-Z7G4B5HJ.js.map +1 -0
  83. package/dist/{chunk-ZDQIUHAM.js → chunk-ZENYS6KW.js} +16 -15
  84. package/dist/chunk-ZENYS6KW.js.map +1 -0
  85. package/dist/{cli-v2 → cli}/defaults/agent-mappings.yaml +5 -5
  86. package/dist/commands/build/marketplace.js +19 -60
  87. package/dist/commands/build/marketplace.js.map +1 -1
  88. package/dist/commands/build/plugins.js +21 -59
  89. package/dist/commands/build/plugins.js.map +1 -1
  90. package/dist/commands/build/stack.js +15 -15
  91. package/dist/commands/build/stack.js.map +1 -1
  92. package/dist/commands/compile.js +21 -21
  93. package/dist/commands/compile.js.map +1 -1
  94. package/dist/commands/config/get.js +9 -8
  95. package/dist/commands/config/get.js.map +1 -1
  96. package/dist/commands/config/index.js +7 -6
  97. package/dist/commands/config/index.js.map +1 -1
  98. package/dist/commands/config/path.js +8 -7
  99. package/dist/commands/config/path.js.map +1 -1
  100. package/dist/commands/config/set-project.js +9 -8
  101. package/dist/commands/config/set-project.js.map +1 -1
  102. package/dist/commands/config/set.js +9 -8
  103. package/dist/commands/config/set.js.map +1 -1
  104. package/dist/commands/config/show.js +6 -5
  105. package/dist/commands/config/unset-project.js +9 -8
  106. package/dist/commands/config/unset-project.js.map +1 -1
  107. package/dist/commands/config/unset.js +9 -8
  108. package/dist/commands/config/unset.js.map +1 -1
  109. package/dist/commands/diff.js +12 -12
  110. package/dist/commands/diff.js.map +1 -1
  111. package/dist/commands/doctor.js +10 -10
  112. package/dist/commands/doctor.js.map +1 -1
  113. package/dist/commands/edit.js +52 -48
  114. package/dist/commands/edit.js.map +1 -1
  115. package/dist/commands/eject.js +180 -97
  116. package/dist/commands/eject.js.map +1 -1
  117. package/dist/commands/import/skill.js +339 -0
  118. package/dist/commands/import/skill.js.map +1 -0
  119. package/dist/commands/info.js +9 -9
  120. package/dist/commands/info.js.map +1 -1
  121. package/dist/commands/init.js +205 -77
  122. package/dist/commands/init.js.map +1 -1
  123. package/dist/commands/list.js +9 -9
  124. package/dist/commands/list.js.map +1 -1
  125. package/dist/commands/new/agent.js +19 -21
  126. package/dist/commands/new/agent.js.map +1 -1
  127. package/dist/commands/new/skill.js +11 -12
  128. package/dist/commands/new/skill.js.map +1 -1
  129. package/dist/commands/outdated.js +12 -12
  130. package/dist/commands/outdated.js.map +1 -1
  131. package/dist/commands/search.js +205 -17
  132. package/dist/commands/search.js.map +1 -1
  133. package/dist/commands/test-imports.js +18 -18
  134. package/dist/commands/test-imports.js.map +1 -1
  135. package/dist/commands/uninstall.js +70 -83
  136. package/dist/commands/uninstall.js.map +1 -1
  137. package/dist/commands/update.js +22 -22
  138. package/dist/commands/update.js.map +1 -1
  139. package/dist/commands/validate.js +9 -9
  140. package/dist/commands/validate.js.map +1 -1
  141. package/dist/commands/version/bump.js +8 -8
  142. package/dist/commands/version/bump.js.map +1 -1
  143. package/dist/commands/version/index.js +8 -8
  144. package/dist/commands/version/index.js.map +1 -1
  145. package/dist/commands/version/set.js +7 -7
  146. package/dist/commands/version/set.js.map +1 -1
  147. package/dist/commands/version/show.js +8 -8
  148. package/dist/commands/version/show.js.map +1 -1
  149. package/dist/components/common/confirm.js +1 -1
  150. package/dist/components/common/message.js +1 -1
  151. package/dist/components/common/message.js.map +1 -1
  152. package/dist/components/common/spinner.js +1 -1
  153. package/dist/components/common/spinner.js.map +1 -1
  154. package/dist/components/skill-search/skill-search.js +10 -0
  155. package/dist/components/wizard/category-grid.js +9 -0
  156. package/dist/components/wizard/category-grid.test.js +861 -0
  157. package/dist/components/wizard/category-grid.test.js.map +1 -0
  158. package/dist/components/wizard/section-progress.js +9 -0
  159. package/dist/components/wizard/section-progress.test.js +281 -0
  160. package/dist/components/wizard/section-progress.test.js.map +1 -0
  161. package/dist/components/wizard/step-approach.js +4 -3
  162. package/dist/components/wizard/step-build.js +16 -0
  163. package/dist/components/wizard/step-build.js.map +1 -0
  164. package/dist/components/wizard/step-build.test.js +741 -0
  165. package/dist/components/wizard/step-build.test.js.map +1 -0
  166. package/dist/components/wizard/step-confirm.js +2 -4
  167. package/dist/components/wizard/step-refine.js +10 -0
  168. package/dist/components/wizard/step-refine.js.map +1 -0
  169. package/dist/components/wizard/step-refine.test.js +236 -0
  170. package/dist/components/wizard/step-refine.test.js.map +1 -0
  171. package/dist/components/wizard/step-stack-options.js +11 -0
  172. package/dist/components/wizard/step-stack-options.js.map +1 -0
  173. package/dist/components/wizard/step-stack.js +3 -3
  174. package/dist/components/wizard/wizard-footer.js +9 -0
  175. package/dist/components/wizard/wizard-footer.js.map +1 -0
  176. package/dist/components/wizard/wizard-tabs.js +11 -0
  177. package/dist/components/wizard/wizard-tabs.js.map +1 -0
  178. package/dist/components/wizard/wizard.js +14 -11
  179. package/dist/hooks/init.js +5 -4
  180. package/dist/hooks/init.js.map +1 -1
  181. package/dist/index.js +1 -1
  182. package/dist/index.js.map +1 -1
  183. package/dist/stores/wizard-store.js +2 -2
  184. package/dist/stores/wizard-store.test.js +249 -15835
  185. package/dist/stores/wizard-store.test.js.map +1 -1
  186. package/package.json +3 -2
  187. package/dist/chunk-367K3JB3.js.map +0 -1
  188. package/dist/chunk-6ESUJMM7.js.map +0 -1
  189. package/dist/chunk-6OY6ZYQF.js +0 -93
  190. package/dist/chunk-6OY6ZYQF.js.map +0 -1
  191. package/dist/chunk-6WEQADPL.js.map +0 -1
  192. package/dist/chunk-AU7XVCLO.js.map +0 -1
  193. package/dist/chunk-AZP2AA5M.js.map +0 -1
  194. package/dist/chunk-D4IQAT27.js.map +0 -1
  195. package/dist/chunk-DHFFRMF6.js.map +0 -1
  196. package/dist/chunk-FKU7VSUD.js.map +0 -1
  197. package/dist/chunk-J2Y4A3LP.js.map +0 -1
  198. package/dist/chunk-JMQGWQZU.js.map +0 -1
  199. package/dist/chunk-JY4RO76L.js +0 -73
  200. package/dist/chunk-JY4RO76L.js.map +0 -1
  201. package/dist/chunk-M7YCPFIX.js.map +0 -1
  202. package/dist/chunk-MJSFR562.js.map +0 -1
  203. package/dist/chunk-MMDXNZPF.js.map +0 -1
  204. package/dist/chunk-MYAVQ23U.js.map +0 -1
  205. package/dist/chunk-OSQDDJXX.js.map +0 -1
  206. package/dist/chunk-QESUUPOE.js.map +0 -1
  207. package/dist/chunk-SJYG4EJZ.js.map +0 -1
  208. package/dist/chunk-SYQ7R2JO.js.map +0 -1
  209. package/dist/chunk-TD643KB3.js +0 -245
  210. package/dist/chunk-TD643KB3.js.map +0 -1
  211. package/dist/chunk-TFV6Z7F7.js.map +0 -1
  212. package/dist/chunk-TGOHJCQ4.js +0 -83
  213. package/dist/chunk-TGOHJCQ4.js.map +0 -1
  214. package/dist/chunk-TOPAIL5W.js.map +0 -1
  215. package/dist/chunk-U4VYHKPM.js.map +0 -1
  216. package/dist/chunk-UFWNMW3G.js.map +0 -1
  217. package/dist/chunk-UNHCZRO4.js.map +0 -1
  218. package/dist/chunk-URDV4OCP.js.map +0 -1
  219. package/dist/chunk-YI6JVSFO.js +0 -43
  220. package/dist/chunk-YI6JVSFO.js.map +0 -1
  221. package/dist/chunk-YNSNRR5D.js +0 -184
  222. package/dist/chunk-YNSNRR5D.js.map +0 -1
  223. package/dist/chunk-Z6DLWTBY.js +0 -46
  224. package/dist/chunk-Z6DLWTBY.js.map +0 -1
  225. package/dist/chunk-ZDQIUHAM.js.map +0 -1
  226. package/dist/chunk-ZSKHDU5P.js.map +0 -1
  227. package/dist/components/wizard/selection-header.js +0 -11
  228. package/dist/components/wizard/step-category.js +0 -12
  229. package/dist/components/wizard/step-subcategory.js +0 -13
  230. /package/dist/components/{wizard/selection-header.js.map → skill-search/skill-search.js.map} +0 -0
  231. /package/dist/components/wizard/{step-category.js.map → category-grid.js.map} +0 -0
  232. /package/dist/components/wizard/{step-subcategory.js.map → section-progress.js.map} +0 -0
@@ -1,65 +1,53 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- getCollectivePluginDir,
4
- getPluginSkillsDir
5
- } from "../chunk-D4IQAT27.js";
3
+ copySkillsToLocalFlattened
4
+ } from "../chunk-K7EVM5LY.js";
5
+ import "../chunk-KAAEN2PO.js";
6
6
  import {
7
- DIRS,
8
- PROJECT_ROOT
9
- } from "../chunk-SJYG4EJZ.js";
7
+ loadSkillsMatrixFromSource
8
+ } from "../chunk-CPZOTVCI.js";
9
+ import "../chunk-B7CCVP6Q.js";
10
+ import "../chunk-IMDW5ZUP.js";
10
11
  import {
11
12
  BaseCommand,
12
13
  EXIT_CODES
13
- } from "../chunk-SYQ7R2JO.js";
14
- import "../chunk-TOPAIL5W.js";
14
+ } from "../chunk-EHS3TWWP.js";
15
+ import {
16
+ loadProjectConfig,
17
+ resolveSource
18
+ } from "../chunk-V46GGCCI.js";
19
+ import "../chunk-3U3R4NCG.js";
15
20
  import {
16
21
  copy,
17
22
  directoryExists,
18
23
  ensureDir,
19
24
  fileExists,
25
+ readFile,
20
26
  writeFile
21
- } from "../chunk-MMDXNZPF.js";
27
+ } from "../chunk-TKFPKEV3.js";
28
+ import {
29
+ CLAUDE_SRC_DIR,
30
+ DIRS,
31
+ LOCAL_SKILLS_PATH,
32
+ PROJECT_ROOT
33
+ } from "../chunk-76DWXGQE.js";
22
34
  import {
23
35
  init_esm_shims
24
36
  } from "../chunk-DHET7RCE.js";
25
37
 
26
- // src/cli-v2/commands/eject.ts
38
+ // src/cli/commands/eject.ts
27
39
  init_esm_shims();
28
40
  import { Args, Flags } from "@oclif/core";
29
41
  import path from "path";
30
42
  import os from "os";
31
- var EJECT_TYPES = ["templates", "config", "skills", "agents", "all"];
32
- var DEFAULT_CONFIG_CONTENT = `# Claude Collective Configuration
33
- # Agent-skill mappings for this project
34
-
35
- name: my-project
36
- description: Project description
37
-
38
- # Agents to compile
39
- agents:
40
- - web-developer
41
- - api-developer
42
- - web-tester
43
- - web-pm
44
-
45
- # Agent-specific skill assignments (optional)
46
- # If not specified, all available skills are given to all agents
47
- agent_skills:
48
- web-developer:
49
- - react
50
- - zustand
51
- - scss-modules
52
- api-developer:
53
- - hono
54
- - drizzle
55
- - better-auth
56
- `;
43
+ import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
44
+ var EJECT_TYPES = ["agent-partials", "skills", "all"];
57
45
  var Eject = class _Eject extends BaseCommand {
58
- static summary = "Eject bundled content for local customization";
59
- static description = "Copy templates, config, skills, or agent partials to your project for customization";
46
+ static summary = "Eject skills or agent partials for local customization";
47
+ static description = "Copy agent partials or skills to your project for customization. Agent partials are always copied from the CLI. Skills are copied from the configured source (public marketplace by default).";
60
48
  static args = {
61
49
  type: Args.string({
62
- description: "What to eject: templates, config, skills, agents, all",
50
+ description: "What to eject: agent-partials, skills, all",
63
51
  required: false,
64
52
  options: EJECT_TYPES
65
53
  })
@@ -74,6 +62,10 @@ var Eject = class _Eject extends BaseCommand {
74
62
  output: Flags.string({
75
63
  char: "o",
76
64
  description: "Output directory (default: .claude/ in current directory)"
65
+ }),
66
+ refresh: Flags.boolean({
67
+ description: "Force refresh from remote source",
68
+ default: false
77
69
  })
78
70
  };
79
71
  async run() {
@@ -81,7 +73,7 @@ var Eject = class _Eject extends BaseCommand {
81
73
  const projectDir = process.cwd();
82
74
  if (!args.type) {
83
75
  this.error(
84
- "Please specify what to eject: templates, config, skills, agents, or all",
76
+ "Please specify what to eject: agent-partials, skills, or all",
85
77
  { exit: EXIT_CODES.INVALID_ARGS }
86
78
  );
87
79
  }
@@ -100,7 +92,7 @@ var Eject = class _Eject extends BaseCommand {
100
92
  });
101
93
  }
102
94
  } else {
103
- outputBase = path.join(projectDir, ".claude");
95
+ outputBase = path.join(projectDir, CLAUDE_SRC_DIR);
104
96
  }
105
97
  this.log("");
106
98
  this.log("Claude Collective Eject");
@@ -110,96 +102,187 @@ var Eject = class _Eject extends BaseCommand {
110
102
  }
111
103
  const ejectType = args.type;
112
104
  const directOutput = !!flags.output;
105
+ let sourceResult;
106
+ if (ejectType === "skills" || ejectType === "all") {
107
+ sourceResult = await loadSkillsMatrixFromSource({
108
+ sourceFlag: flags.source,
109
+ projectDir,
110
+ forceRefresh: flags.refresh
111
+ });
112
+ }
113
113
  switch (ejectType) {
114
- case "templates":
115
- await this.ejectTemplates(outputBase, flags.force, directOutput);
116
- break;
117
- case "config":
118
- await this.ejectConfig(outputBase, flags.force, directOutput);
114
+ case "agent-partials":
115
+ await this.ejectAgentPartials(outputBase, flags.force, directOutput);
119
116
  break;
120
117
  case "skills":
121
- await this.ejectSkills(outputBase, flags.force, directOutput);
122
- break;
123
- case "agents":
124
- await this.ejectAgents(outputBase, flags.force, directOutput);
118
+ await this.ejectSkills(
119
+ projectDir,
120
+ flags.force,
121
+ directOutput,
122
+ sourceResult,
123
+ directOutput ? outputBase : void 0
124
+ );
125
125
  break;
126
126
  case "all":
127
- await this.ejectTemplates(outputBase, flags.force, directOutput);
128
- await this.ejectConfig(outputBase, flags.force, directOutput);
129
- await this.ejectSkills(outputBase, flags.force, directOutput);
130
- await this.ejectAgents(outputBase, flags.force, directOutput);
127
+ await this.ejectAgentPartials(outputBase, flags.force, directOutput);
128
+ await this.ejectSkills(
129
+ projectDir,
130
+ flags.force,
131
+ directOutput,
132
+ sourceResult,
133
+ directOutput ? outputBase : void 0
134
+ );
131
135
  break;
132
136
  }
137
+ if (flags.source) {
138
+ await this.saveSourceToProjectConfig(projectDir, flags.source);
139
+ }
140
+ await this.ensureMinimalConfig(projectDir, flags.source, sourceResult);
133
141
  this.log("");
134
142
  this.logSuccess("Eject complete!");
135
143
  this.log("");
136
144
  }
137
- async ejectTemplates(outputBase, force, directOutput = false) {
138
- const sourceDir = path.join(PROJECT_ROOT, DIRS.templates);
139
- const destDir = directOutput ? outputBase : path.join(outputBase, "templates");
140
- if (await directoryExists(destDir) && !force) {
141
- this.warn(
142
- `Templates already exist at ${destDir}. Use --force to overwrite.`
143
- );
144
- return;
145
+ /**
146
+ * Save source to project-level .claude-src/config.yaml.
147
+ * Creates the config file if it doesn't exist, or merges with existing config.
148
+ */
149
+ async saveSourceToProjectConfig(projectDir, source) {
150
+ const configPath = path.join(projectDir, CLAUDE_SRC_DIR, "config.yaml");
151
+ let config = {};
152
+ if (await fileExists(configPath)) {
153
+ const content = await readFile(configPath);
154
+ config = parseYaml(content) || {};
145
155
  }
146
- await ensureDir(destDir);
147
- await copy(sourceDir, destDir);
148
- this.logSuccess(`Templates ejected to ${destDir}`);
149
- this.log("You can now customize agent.liquid and partials locally.");
156
+ config.source = source;
157
+ await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));
158
+ await writeFile(configPath, stringifyYaml(config, { indent: 2 }));
159
+ this.log(`Source saved to .claude-src/config.yaml`);
150
160
  }
151
- async ejectConfig(outputBase, force, directOutput = false) {
152
- const destPath = path.join(outputBase, "config.yaml");
153
- if (await fileExists(destPath) && !force) {
154
- this.warn(
155
- `Config already exists at ${destPath}. Use --force to overwrite.`
156
- );
161
+ /**
162
+ * Ensure a minimal config.yaml exists so that `cc compile` can work after eject.
163
+ * Only creates if config doesn't already exist.
164
+ * Includes all resolved config values: source, marketplace, author, agents_source.
165
+ */
166
+ async ensureMinimalConfig(projectDir, sourceFlag, sourceResult) {
167
+ const configPath = path.join(projectDir, CLAUDE_SRC_DIR, "config.yaml");
168
+ if (await fileExists(configPath)) {
157
169
  return;
158
170
  }
159
- await ensureDir(path.dirname(destPath));
160
- await writeFile(destPath, DEFAULT_CONFIG_CONTENT);
161
- this.logSuccess(`Config template ejected to ${destPath}`);
162
- this.log("Customize agent-skill mappings for your project.");
171
+ const projectName = path.basename(projectDir);
172
+ const config = {
173
+ name: projectName,
174
+ installMode: "local"
175
+ };
176
+ const resolvedConfig = sourceResult?.sourceConfig ?? await resolveSource(sourceFlag, projectDir);
177
+ if (sourceFlag) {
178
+ config.source = sourceFlag;
179
+ } else if (resolvedConfig.source) {
180
+ config.source = resolvedConfig.source;
181
+ }
182
+ if (resolvedConfig.marketplace) {
183
+ config.marketplace = resolvedConfig.marketplace;
184
+ }
185
+ const existingProjectConfig = await loadProjectConfig(projectDir);
186
+ if (existingProjectConfig?.author) {
187
+ config.author = existingProjectConfig.author;
188
+ }
189
+ if (existingProjectConfig?.agents_source) {
190
+ config.agents_source = existingProjectConfig.agents_source;
191
+ }
192
+ await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));
193
+ let configContent = stringifyYaml(config, { indent: 2 });
194
+ const exampleStackComment = `
195
+ # Example stack configuration (uncomment and customize):
196
+ #
197
+ # skills:
198
+ # - web-framework-react
199
+ # - web-styling-scss-modules
200
+ # - api-framework-hono
201
+ # - api-database-drizzle
202
+ #
203
+ # agents:
204
+ # - web-developer
205
+ # - api-developer
206
+ # - web-reviewer
207
+ #
208
+ # stack:
209
+ # web-developer:
210
+ # framework: web-framework-react
211
+ # styling: web-styling-scss-modules
212
+ # api-developer:
213
+ # api: api-framework-hono
214
+ # database: api-database-drizzle
215
+ `;
216
+ configContent += exampleStackComment;
217
+ await writeFile(configPath, configContent);
218
+ this.logSuccess(`Created ${CLAUDE_SRC_DIR}/config.yaml`);
163
219
  }
164
- async ejectSkills(outputBase, force, directOutput = false) {
165
- const pluginDir = getCollectivePluginDir();
166
- const sourceDir = getPluginSkillsDir(pluginDir);
220
+ /**
221
+ * Eject agent partials (templates + agent partial files).
222
+ *
223
+ * Combines the old templates and agents eject into a single operation:
224
+ * - Copies `PROJECT_ROOT/src/agents/_templates/` to `<dest>/_templates/`
225
+ * - Copies agent partials from `PROJECT_ROOT/src/agents/` (excluding `_templates`) to `<dest>/`
226
+ *
227
+ * Always copies from CLI's PROJECT_ROOT - the `--source` flag has no effect.
228
+ */
229
+ async ejectAgentPartials(outputBase, force, directOutput = false) {
230
+ const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);
167
231
  if (!await directoryExists(sourceDir)) {
168
- this.warn("No skills found in installed plugin.");
169
- this.log("Install skills with 'cc init' first, then try again.");
232
+ this.warn("No agent partials found in CLI.");
170
233
  return;
171
234
  }
172
- const destDir = directOutput ? outputBase : path.join(outputBase, "skills");
235
+ const destDir = directOutput ? outputBase : path.join(outputBase, "agents");
173
236
  if (await directoryExists(destDir) && !force) {
174
237
  this.warn(
175
- `Skills already exist at ${destDir}. Use --force to overwrite.`
238
+ `Agent partials already exist at ${destDir}. Use --force to overwrite.`
176
239
  );
177
240
  return;
178
241
  }
179
242
  await ensureDir(destDir);
180
243
  await copy(sourceDir, destDir);
181
- this.logSuccess(`Skills ejected to ${destDir}`);
182
- this.log("You can now customize skill content locally.");
244
+ this.logSuccess(`Agent partials ejected to ${destDir}`);
245
+ this.log(
246
+ "You can now customize templates, agent intro, workflow, and examples locally."
247
+ );
183
248
  }
184
- async ejectAgents(outputBase, force, directOutput = false) {
185
- const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);
186
- if (!await directoryExists(sourceDir)) {
187
- this.warn("No agent partials found.");
188
- return;
189
- }
190
- const destDir = directOutput ? outputBase : path.join(outputBase, "agents", "_partials");
249
+ /**
250
+ * Eject skills from the configured source to local .claude/skills/ directory.
251
+ *
252
+ * Uses the source resolution system:
253
+ * - Default: Public marketplace
254
+ * - `--source /path`: Custom local source
255
+ * - `--source url`: Custom remote source
256
+ *
257
+ * Skills are copied in a flattened structure using their normalized skill IDs.
258
+ */
259
+ async ejectSkills(projectDir, force, directOutput = false, sourceResult, customOutputBase) {
260
+ const destDir = directOutput && customOutputBase ? customOutputBase : path.join(projectDir, LOCAL_SKILLS_PATH);
191
261
  if (await directoryExists(destDir) && !force) {
192
262
  this.warn(
193
- `Agent partials already exist at ${destDir}. Use --force to overwrite.`
263
+ `Skills already exist at ${destDir}. Use --force to overwrite.`
194
264
  );
195
265
  return;
196
266
  }
267
+ const skillIds = Object.keys(sourceResult.matrix.skills).filter(
268
+ (skillId) => !sourceResult.matrix.skills[skillId].local
269
+ );
270
+ if (skillIds.length === 0) {
271
+ this.warn("No skills found in source to eject.");
272
+ return;
273
+ }
197
274
  await ensureDir(destDir);
198
- await copy(sourceDir, destDir);
199
- this.logSuccess(`Agent partials ejected to ${destDir}`);
200
- this.log(
201
- "You can now customize agent intro, workflow, and examples locally."
275
+ const copiedSkills = await copySkillsToLocalFlattened(
276
+ skillIds,
277
+ destDir,
278
+ sourceResult.matrix,
279
+ sourceResult
280
+ );
281
+ const sourceLabel = sourceResult.isLocal ? sourceResult.sourcePath : sourceResult.marketplace || sourceResult.sourceConfig.source;
282
+ this.logSuccess(
283
+ `${copiedSkills.length} skills ejected to ${destDir} from ${sourceLabel}`
202
284
  );
285
+ this.log("You can now customize skill content locally.");
203
286
  }
204
287
  };
205
288
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli-v2/commands/eject.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport os from \"os\";\nimport { BaseCommand } from \"../base-command.js\";\nimport {\n copy,\n ensureDir,\n directoryExists,\n fileExists,\n writeFile,\n} from \"../utils/fs.js\";\nimport { DIRS, PROJECT_ROOT } from \"../consts.js\";\nimport {\n getCollectivePluginDir,\n getPluginSkillsDir,\n} from \"../lib/plugin-finder.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\n\nconst EJECT_TYPES = [\"templates\", \"config\", \"skills\", \"agents\", \"all\"] as const;\ntype EjectType = (typeof EJECT_TYPES)[number];\n\nconst DEFAULT_CONFIG_CONTENT = `# Claude Collective Configuration\n# Agent-skill mappings for this project\n\nname: my-project\ndescription: Project description\n\n# Agents to compile\nagents:\n - web-developer\n - api-developer\n - web-tester\n - web-pm\n\n# Agent-specific skill assignments (optional)\n# If not specified, all available skills are given to all agents\nagent_skills:\n web-developer:\n - react\n - zustand\n - scss-modules\n api-developer:\n - hono\n - drizzle\n - better-auth\n`;\n\nexport default class Eject extends BaseCommand {\n static summary = \"Eject bundled content for local customization\";\n static description =\n \"Copy templates, config, skills, or agent partials to your project for customization\";\n\n static args = {\n type: Args.string({\n description: \"What to eject: templates, config, skills, agents, all\",\n required: false,\n options: EJECT_TYPES as unknown as string[],\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing files\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory (default: .claude/ in current directory)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Eject);\n const projectDir = process.cwd();\n\n if (!args.type) {\n this.error(\n \"Please specify what to eject: templates, config, skills, agents, or all\",\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n\n if (!EJECT_TYPES.includes(args.type as EjectType)) {\n this.error(`Unknown eject type: ${args.type}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n // Resolve output base directory\n let outputBase: string;\n if (flags.output) {\n // Expand ~ to home directory if present\n const expandedPath = flags.output.startsWith(\"~\")\n ? path.join(os.homedir(), flags.output.slice(1))\n : flags.output;\n outputBase = path.resolve(projectDir, expandedPath);\n\n // Validate output path is not an existing file\n if (await fileExists(outputBase)) {\n this.error(`Output path exists as a file: ${outputBase}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n } else {\n outputBase = path.join(projectDir, \".claude\");\n }\n\n this.log(\"\");\n this.log(\"Claude Collective Eject\");\n this.log(\"\");\n\n // Show output directory when using custom path\n if (flags.output) {\n this.log(`Output directory: ${outputBase}`);\n }\n\n const ejectType = args.type as EjectType;\n const directOutput = !!flags.output;\n\n switch (ejectType) {\n case \"templates\":\n await this.ejectTemplates(outputBase, flags.force, directOutput);\n break;\n case \"config\":\n await this.ejectConfig(outputBase, flags.force, directOutput);\n break;\n case \"skills\":\n await this.ejectSkills(outputBase, flags.force, directOutput);\n break;\n case \"agents\":\n await this.ejectAgents(outputBase, flags.force, directOutput);\n break;\n case \"all\":\n await this.ejectTemplates(outputBase, flags.force, directOutput);\n await this.ejectConfig(outputBase, flags.force, directOutput);\n await this.ejectSkills(outputBase, flags.force, directOutput);\n await this.ejectAgents(outputBase, flags.force, directOutput);\n break;\n }\n\n this.log(\"\");\n this.logSuccess(\"Eject complete!\");\n this.log(\"\");\n }\n\n private async ejectTemplates(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.templates);\n // When directOutput is true (--output used), write directly to outputBase\n // When false (default), add \"templates\" subdirectory for backward compatibility\n const destDir = directOutput\n ? outputBase\n : path.join(outputBase, \"templates\");\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(\n `Templates already exist at ${destDir}. Use --force to overwrite.`,\n );\n return;\n }\n\n await ensureDir(destDir);\n await copy(sourceDir, destDir);\n\n this.logSuccess(`Templates ejected to ${destDir}`);\n this.log(\"You can now customize agent.liquid and partials locally.\");\n }\n\n private async ejectConfig(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n // Config always outputs to config.yaml in the specified location\n const destPath = path.join(outputBase, \"config.yaml\");\n\n if ((await fileExists(destPath)) && !force) {\n this.warn(\n `Config already exists at ${destPath}. Use --force to overwrite.`,\n );\n return;\n }\n\n await ensureDir(path.dirname(destPath));\n await writeFile(destPath, DEFAULT_CONFIG_CONTENT);\n\n this.logSuccess(`Config template ejected to ${destPath}`);\n this.log(\"Customize agent-skill mappings for your project.\");\n }\n\n private async ejectSkills(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n // Find skills from installed plugin\n const pluginDir = getCollectivePluginDir();\n const sourceDir = getPluginSkillsDir(pluginDir);\n\n if (!(await directoryExists(sourceDir))) {\n this.warn(\"No skills found in installed plugin.\");\n this.log(\"Install skills with 'cc init' first, then try again.\");\n return;\n }\n\n // When directOutput is true (--output used), write directly to outputBase\n // When false (default), add \"skills\" subdirectory\n const destDir = directOutput ? outputBase : path.join(outputBase, \"skills\");\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(\n `Skills already exist at ${destDir}. Use --force to overwrite.`,\n );\n return;\n }\n\n await ensureDir(destDir);\n await copy(sourceDir, destDir);\n\n this.logSuccess(`Skills ejected to ${destDir}`);\n this.log(\"You can now customize skill content locally.\");\n }\n\n private async ejectAgents(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n // Source is the agents directory from PROJECT_ROOT (excluding _templates)\n const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(sourceDir))) {\n this.warn(\"No agent partials found.\");\n return;\n }\n\n // When directOutput is true (--output used), write directly to outputBase\n // When false (default), add \"agents/_partials\" subdirectory\n const destDir = directOutput\n ? outputBase\n : path.join(outputBase, \"agents\", \"_partials\");\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(\n `Agent partials already exist at ${destDir}. Use --force to overwrite.`,\n );\n return;\n }\n\n await ensureDir(destDir);\n await copy(sourceDir, destDir);\n\n this.logSuccess(`Agent partials ejected to ${destDir}`);\n this.log(\n \"You can now customize agent intro, workflow, and examples locally.\",\n );\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/eject.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport os from \"os\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { BaseCommand } from \"../base-command.js\";\nimport {\n copy,\n ensureDir,\n directoryExists,\n fileExists,\n readFile,\n writeFile,\n} from \"../utils/fs.js\";\nimport {\n CLAUDE_SRC_DIR,\n DIRS,\n LOCAL_SKILLS_PATH,\n PROJECT_ROOT,\n} from \"../consts.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport {\n loadSkillsMatrixFromSource,\n type SourceLoadResult,\n} from \"../lib/source-loader.js\";\nimport { copySkillsToLocalFlattened } from \"../lib/skill-copier.js\";\nimport { loadProjectConfig, resolveSource } from \"../lib/config.js\";\n\nconst EJECT_TYPES = [\"agent-partials\", \"skills\", \"all\"] as const;\ntype EjectType = (typeof EJECT_TYPES)[number];\n\nexport default class Eject extends BaseCommand {\n static summary = \"Eject skills or agent partials for local customization\";\n static description =\n \"Copy agent partials or skills to your project for customization. \" +\n \"Agent partials are always copied from the CLI. \" +\n \"Skills are copied from the configured source (public marketplace by default).\";\n\n static args = {\n type: Args.string({\n description: \"What to eject: agent-partials, skills, all\",\n required: false,\n options: EJECT_TYPES as unknown as string[],\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing files\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory (default: .claude/ in current directory)\",\n }),\n refresh: Flags.boolean({\n description: \"Force refresh from remote source\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Eject);\n const projectDir = process.cwd();\n\n if (!args.type) {\n this.error(\n \"Please specify what to eject: agent-partials, skills, or all\",\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n\n if (!EJECT_TYPES.includes(args.type as EjectType)) {\n this.error(`Unknown eject type: ${args.type}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n\n // Resolve output base directory\n let outputBase: string;\n if (flags.output) {\n // Expand ~ to home directory if present\n const expandedPath = flags.output.startsWith(\"~\")\n ? path.join(os.homedir(), flags.output.slice(1))\n : flags.output;\n outputBase = path.resolve(projectDir, expandedPath);\n\n // Validate output path is not an existing file\n if (await fileExists(outputBase)) {\n this.error(`Output path exists as a file: ${outputBase}`, {\n exit: EXIT_CODES.INVALID_ARGS,\n });\n }\n } else {\n outputBase = path.join(projectDir, CLAUDE_SRC_DIR);\n }\n\n this.log(\"\");\n this.log(\"Claude Collective Eject\");\n this.log(\"\");\n\n // Show output directory when using custom path\n if (flags.output) {\n this.log(`Output directory: ${outputBase}`);\n }\n\n const ejectType = args.type as EjectType;\n const directOutput = !!flags.output;\n\n // Load source when ejecting skills or all\n let sourceResult: SourceLoadResult | undefined;\n if (ejectType === \"skills\" || ejectType === \"all\") {\n sourceResult = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n forceRefresh: flags.refresh,\n });\n }\n\n switch (ejectType) {\n case \"agent-partials\":\n await this.ejectAgentPartials(outputBase, flags.force, directOutput);\n break;\n case \"skills\":\n await this.ejectSkills(\n projectDir,\n flags.force,\n directOutput,\n sourceResult!,\n directOutput ? outputBase : undefined,\n );\n break;\n case \"all\":\n await this.ejectAgentPartials(outputBase, flags.force, directOutput);\n await this.ejectSkills(\n projectDir,\n flags.force,\n directOutput,\n sourceResult!,\n directOutput ? outputBase : undefined,\n );\n break;\n }\n\n // Save source to project config if --source was provided\n if (flags.source) {\n await this.saveSourceToProjectConfig(projectDir, flags.source);\n }\n\n // Create minimal config.yaml if it doesn't exist\n await this.ensureMinimalConfig(projectDir, flags.source, sourceResult);\n\n this.log(\"\");\n this.logSuccess(\"Eject complete!\");\n this.log(\"\");\n }\n\n /**\n * Save source to project-level .claude-src/config.yaml.\n * Creates the config file if it doesn't exist, or merges with existing config.\n */\n private async saveSourceToProjectConfig(\n projectDir: string,\n source: string,\n ): Promise<void> {\n const configPath = path.join(projectDir, CLAUDE_SRC_DIR, \"config.yaml\");\n\n let config: Record<string, unknown> = {};\n if (await fileExists(configPath)) {\n const content = await readFile(configPath);\n config = (parseYaml(content) as Record<string, unknown>) || {};\n }\n\n config.source = source;\n\n await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));\n await writeFile(configPath, stringifyYaml(config, { indent: 2 }));\n\n this.log(`Source saved to .claude-src/config.yaml`);\n }\n\n /**\n * Ensure a minimal config.yaml exists so that `cc compile` can work after eject.\n * Only creates if config doesn't already exist.\n * Includes all resolved config values: source, marketplace, author, agents_source.\n */\n private async ensureMinimalConfig(\n projectDir: string,\n sourceFlag?: string,\n sourceResult?: SourceLoadResult,\n ): Promise<void> {\n const configPath = path.join(projectDir, CLAUDE_SRC_DIR, \"config.yaml\");\n\n // Don't overwrite existing config\n if (await fileExists(configPath)) {\n return;\n }\n\n const projectName = path.basename(projectDir);\n\n // Build config with all available values\n const config: Record<string, unknown> = {\n name: projectName,\n installMode: \"local\",\n };\n\n // Get resolved source config\n const resolvedConfig =\n sourceResult?.sourceConfig ??\n (await resolveSource(sourceFlag, projectDir));\n\n // Add source (flag overrides resolved source, but always include it)\n if (sourceFlag) {\n config.source = sourceFlag;\n } else if (resolvedConfig.source) {\n config.source = resolvedConfig.source;\n }\n\n // Add marketplace if available\n if (resolvedConfig.marketplace) {\n config.marketplace = resolvedConfig.marketplace;\n }\n\n // Load project config to get author and agents_source\n const existingProjectConfig = await loadProjectConfig(projectDir);\n if (existingProjectConfig?.author) {\n config.author = existingProjectConfig.author;\n }\n if (existingProjectConfig?.agents_source) {\n config.agents_source = existingProjectConfig.agents_source;\n }\n\n await ensureDir(path.join(projectDir, CLAUDE_SRC_DIR));\n\n // Build config YAML with commented example stack blueprint\n let configContent = stringifyYaml(config, { indent: 2 });\n\n // Append commented example stack configuration as a blueprint for users\n const exampleStackComment = `\n# Example stack configuration (uncomment and customize):\n#\n# skills:\n# - web-framework-react\n# - web-styling-scss-modules\n# - api-framework-hono\n# - api-database-drizzle\n#\n# agents:\n# - web-developer\n# - api-developer\n# - web-reviewer\n#\n# stack:\n# web-developer:\n# framework: web-framework-react\n# styling: web-styling-scss-modules\n# api-developer:\n# api: api-framework-hono\n# database: api-database-drizzle\n`;\n\n configContent += exampleStackComment;\n await writeFile(configPath, configContent);\n\n this.logSuccess(`Created ${CLAUDE_SRC_DIR}/config.yaml`);\n }\n\n /**\n * Eject agent partials (templates + agent partial files).\n *\n * Combines the old templates and agents eject into a single operation:\n * - Copies `PROJECT_ROOT/src/agents/_templates/` to `<dest>/_templates/`\n * - Copies agent partials from `PROJECT_ROOT/src/agents/` (excluding `_templates`) to `<dest>/`\n *\n * Always copies from CLI's PROJECT_ROOT - the `--source` flag has no effect.\n */\n private async ejectAgentPartials(\n outputBase: string,\n force: boolean,\n directOutput: boolean = false,\n ): Promise<void> {\n const sourceDir = path.join(PROJECT_ROOT, DIRS.agents);\n\n if (!(await directoryExists(sourceDir))) {\n this.warn(\"No agent partials found in CLI.\");\n return;\n }\n\n // Destination directory structure:\n // When directOutput is true: write directly to outputBase\n // When false (default): add \"agents\" subdirectory (to .claude-src/agents/)\n const destDir = directOutput ? outputBase : path.join(outputBase, \"agents\");\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(\n `Agent partials already exist at ${destDir}. Use --force to overwrite.`,\n );\n return;\n }\n\n await ensureDir(destDir);\n\n // Copy entire agents directory (includes _templates and all agent partials)\n await copy(sourceDir, destDir);\n\n this.logSuccess(`Agent partials ejected to ${destDir}`);\n this.log(\n \"You can now customize templates, agent intro, workflow, and examples locally.\",\n );\n }\n\n /**\n * Eject skills from the configured source to local .claude/skills/ directory.\n *\n * Uses the source resolution system:\n * - Default: Public marketplace\n * - `--source /path`: Custom local source\n * - `--source url`: Custom remote source\n *\n * Skills are copied in a flattened structure using their normalized skill IDs.\n */\n private async ejectSkills(\n projectDir: string,\n force: boolean,\n directOutput: boolean = false,\n sourceResult: SourceLoadResult,\n customOutputBase?: string,\n ): Promise<void> {\n // Destination directory structure:\n // When directOutput is true (custom --output): write directly to customOutputBase\n // When false (default): use .claude/skills/ (skills are runtime files, not source files)\n const destDir =\n directOutput && customOutputBase\n ? customOutputBase\n : path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if ((await directoryExists(destDir)) && !force) {\n this.warn(\n `Skills already exist at ${destDir}. Use --force to overwrite.`,\n );\n return;\n }\n\n // Get all non-local skill IDs from the source matrix\n const skillIds = Object.keys(sourceResult.matrix.skills).filter(\n (skillId) => !sourceResult.matrix.skills[skillId].local,\n );\n\n if (skillIds.length === 0) {\n this.warn(\"No skills found in source to eject.\");\n return;\n }\n\n await ensureDir(destDir);\n\n // Copy skills using flattened structure\n const copiedSkills = await copySkillsToLocalFlattened(\n skillIds,\n destDir,\n sourceResult.matrix,\n sourceResult,\n );\n\n const sourceLabel = sourceResult.isLocal\n ? sourceResult.sourcePath\n : sourceResult.marketplace || sourceResult.sourceConfig.source;\n\n this.logSuccess(\n `${copiedSkills.length} skills ejected to ${destDir} from ${sourceLabel}`,\n );\n this.log(\"You can now customize skill content locally.\");\n }\n}\n"],"mappings":"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","names":[]}