agents-inc 0.156.0 → 0.158.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 (173) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/dist/{chunk-4A4L3YIW.js → chunk-2PN4QXON.js} +6 -7
  3. package/dist/chunk-2PN4QXON.js.map +1 -0
  4. package/dist/{chunk-QWVXOCXO.js → chunk-3NBXQSW2.js} +7 -9
  5. package/dist/{chunk-QWVXOCXO.js.map → chunk-3NBXQSW2.js.map} +1 -1
  6. package/dist/{chunk-WCAUUBHO.js → chunk-3PJLLBUS.js} +14597 -14536
  7. package/dist/chunk-3PJLLBUS.js.map +1 -0
  8. package/dist/{chunk-6RLV45HN.js → chunk-3Q2N7CSY.js} +6 -6
  9. package/dist/chunk-3Q2N7CSY.js.map +1 -0
  10. package/dist/{chunk-LJCNUP6M.js → chunk-4ABNXKAR.js} +2 -2
  11. package/dist/{chunk-D2CAV7MG.js → chunk-4DMFK67G.js} +2 -2
  12. package/dist/{chunk-MO5FGLVS.js → chunk-54QLV3OH.js} +11 -12
  13. package/dist/chunk-54QLV3OH.js.map +1 -0
  14. package/dist/{chunk-5F2YR5XV.js → chunk-6DBE562W.js} +15 -5
  15. package/dist/chunk-6DBE562W.js.map +1 -0
  16. package/dist/{chunk-RWOYPOMR.js → chunk-7Z4N4JWQ.js} +19 -245
  17. package/dist/chunk-7Z4N4JWQ.js.map +1 -0
  18. package/dist/{chunk-H6UTKTLK.js → chunk-DAUY2SB3.js} +98 -34
  19. package/dist/chunk-DAUY2SB3.js.map +1 -0
  20. package/dist/{chunk-2H7UWE2G.js → chunk-DP6YQFVO.js} +13 -12
  21. package/dist/chunk-DP6YQFVO.js.map +1 -0
  22. package/dist/{chunk-ILUVL7WM.js → chunk-DZD25NHW.js} +2 -2
  23. package/dist/{chunk-PCC4LBKB.js → chunk-EEAX7E2X.js} +2 -2
  24. package/dist/{chunk-IO5YBKHV.js → chunk-G6G2FT2G.js} +10 -8
  25. package/dist/chunk-G6G2FT2G.js.map +1 -0
  26. package/dist/{chunk-5QZAK6J7.js → chunk-H25VRR2T.js} +50 -18
  27. package/dist/chunk-H25VRR2T.js.map +1 -0
  28. package/dist/chunk-H2DHTJKW.js +1352 -0
  29. package/dist/chunk-H2DHTJKW.js.map +1 -0
  30. package/dist/{chunk-MHRC3KRX.js → chunk-H4CL23HG.js} +3 -3
  31. package/dist/chunk-H4CL23HG.js.map +1 -0
  32. package/dist/{chunk-F5T6TV4Z.js → chunk-IK6YOXZH.js} +40 -14
  33. package/dist/chunk-IK6YOXZH.js.map +1 -0
  34. package/dist/{chunk-HG4JPXJT.js → chunk-JG3B47P3.js} +23 -10
  35. package/dist/chunk-JG3B47P3.js.map +1 -0
  36. package/dist/{chunk-SY4X2LND.js → chunk-KUZBMEWR.js} +3 -3
  37. package/dist/{chunk-5OKLCVM4.js → chunk-KVVXINCJ.js} +3 -3
  38. package/dist/{chunk-PNMM5HNX.js → chunk-L4FHSOL5.js} +9 -10
  39. package/dist/chunk-L4FHSOL5.js.map +1 -0
  40. package/dist/{chunk-PMUABBPG.js → chunk-LKI3ENGQ.js} +9 -13
  41. package/dist/chunk-LKI3ENGQ.js.map +1 -0
  42. package/dist/{chunk-CLFHC2DK.js → chunk-OQB2CKBT.js} +17 -18
  43. package/dist/chunk-OQB2CKBT.js.map +1 -0
  44. package/dist/{chunk-HXKOIWLU.js → chunk-P6OKOH62.js} +2 -6
  45. package/dist/chunk-P6OKOH62.js.map +1 -0
  46. package/dist/{chunk-TNGMF4UX.js → chunk-PNRLBPGS.js} +12 -12
  47. package/dist/chunk-PNRLBPGS.js.map +1 -0
  48. package/dist/{chunk-Y5Y7XHVU.js → chunk-PZNXBORZ.js} +4 -4
  49. package/dist/{chunk-HTYH7CKN.js → chunk-Q7CAE5NN.js} +3 -3
  50. package/dist/{chunk-G47TDUK3.js → chunk-QNAMXQKF.js} +2 -2
  51. package/dist/{chunk-GS2NZ3GD.js → chunk-SJ4T5YLG.js} +5 -5
  52. package/dist/chunk-SJ4T5YLG.js.map +1 -0
  53. package/dist/{chunk-UMH2YZKG.js → chunk-TPQ5M3BW.js} +4 -6
  54. package/dist/{chunk-UMH2YZKG.js.map → chunk-TPQ5M3BW.js.map} +1 -1
  55. package/dist/{chunk-4G2YHZIM.js → chunk-TUXXBEBB.js} +4 -6
  56. package/dist/{chunk-4G2YHZIM.js.map → chunk-TUXXBEBB.js.map} +1 -1
  57. package/dist/{chunk-WFRTHH3A.js → chunk-TZRXWFF5.js} +3 -3
  58. package/dist/{chunk-TBOVYLQJ.js → chunk-VTIDLRNA.js} +2 -2
  59. package/dist/{chunk-OKH64JZE.js → chunk-WCZNQECQ.js} +2 -2
  60. package/dist/{chunk-ZUAZHDKP.js → chunk-WMVOJY6V.js} +277 -40
  61. package/dist/chunk-WMVOJY6V.js.map +1 -0
  62. package/dist/{chunk-YO2LTXB4.js → chunk-X52QUV4U.js} +115 -10
  63. package/dist/chunk-X52QUV4U.js.map +1 -0
  64. package/dist/{chunk-IXRZAHZF.js → chunk-XNYHMRVJ.js} +4 -4
  65. package/dist/{chunk-VPASBA7P.js → chunk-YXI3BTQQ.js} +2 -2
  66. package/dist/commands/build/marketplace.js +9 -12
  67. package/dist/commands/build/marketplace.js.map +1 -1
  68. package/dist/commands/build/plugins.js +9 -12
  69. package/dist/commands/build/plugins.js.map +1 -1
  70. package/dist/commands/compile.js +15 -19
  71. package/dist/commands/compile.js.map +1 -1
  72. package/dist/commands/doctor.js +75 -54
  73. package/dist/commands/doctor.js.map +1 -1
  74. package/dist/commands/edit.js +154 -109
  75. package/dist/commands/edit.js.map +1 -1
  76. package/dist/commands/eject.js +68 -38
  77. package/dist/commands/eject.js.map +1 -1
  78. package/dist/commands/init.js +36 -39
  79. package/dist/commands/list.js +8 -10
  80. package/dist/commands/list.js.map +1 -1
  81. package/dist/commands/new/marketplace.js +8 -11
  82. package/dist/commands/new/marketplace.js.map +1 -1
  83. package/dist/commands/search.js +10 -13
  84. package/dist/commands/search.js.map +1 -1
  85. package/dist/commands/share.js +8 -10
  86. package/dist/commands/share.js.map +1 -1
  87. package/dist/commands/uninstall.js +39 -28
  88. package/dist/commands/uninstall.js.map +1 -1
  89. package/dist/commands/update.js +7 -10
  90. package/dist/commands/update.js.map +1 -1
  91. package/dist/components/common/removal-plan-confirm.js +2 -2
  92. package/dist/components/common/select-list.js +2 -2
  93. package/dist/components/wizard/category-grid.js +4 -5
  94. package/dist/components/wizard/checkbox-grid.js +4 -4
  95. package/dist/components/wizard/domain-selection.js +9 -11
  96. package/dist/components/wizard/run-wizard-session.js +26 -28
  97. package/dist/components/wizard/scroll-affordance.js +2 -2
  98. package/dist/components/wizard/skill-agent-summary.js +5 -7
  99. package/dist/components/wizard/source-grid.js +5 -6
  100. package/dist/components/wizard/stack-selection.js +7 -9
  101. package/dist/components/wizard/step-agents.js +8 -10
  102. package/dist/components/wizard/step-build.js +7 -9
  103. package/dist/components/wizard/step-confirm.js +9 -11
  104. package/dist/components/wizard/step-sources.js +8 -10
  105. package/dist/components/wizard/step-stack.js +8 -10
  106. package/dist/components/wizard/summary-panel.js +8 -10
  107. package/dist/components/wizard/toast.js +2 -2
  108. package/dist/components/wizard/wizard-layout.js +12 -14
  109. package/dist/components/wizard/wizard-tabs.js +2 -4
  110. package/dist/components/wizard/wizard.js +25 -27
  111. package/dist/hooks/init.js +36 -39
  112. package/dist/hooks/init.js.map +1 -1
  113. package/dist/load-agent-defs-2VYAV5GL.js +13 -0
  114. package/dist/recompile-project-agents-NG5DCPHJ.js +17 -0
  115. package/dist/{source-loader-3DL3NYUX.js → source-loader-CO2FZ3OO.js} +4 -8
  116. package/dist/src/agents/_templates/agent.liquid +2 -2
  117. package/dist/stores/wizard-store.js +6 -6
  118. package/package.json +2 -4
  119. package/src/agents/_templates/agent.liquid +2 -2
  120. package/src/schemas/custom-metadata.schema.json +1 -1
  121. package/src/schemas/marketplace.schema.json +2 -1
  122. package/dist/chunk-2H7UWE2G.js.map +0 -1
  123. package/dist/chunk-4A4L3YIW.js.map +0 -1
  124. package/dist/chunk-5F2YR5XV.js.map +0 -1
  125. package/dist/chunk-5QZAK6J7.js.map +0 -1
  126. package/dist/chunk-6RLV45HN.js.map +0 -1
  127. package/dist/chunk-CLFHC2DK.js.map +0 -1
  128. package/dist/chunk-F2AMBBIA.js +0 -64
  129. package/dist/chunk-F2AMBBIA.js.map +0 -1
  130. package/dist/chunk-F5T6TV4Z.js.map +0 -1
  131. package/dist/chunk-GS2NZ3GD.js.map +0 -1
  132. package/dist/chunk-H6UTKTLK.js.map +0 -1
  133. package/dist/chunk-HG4JPXJT.js.map +0 -1
  134. package/dist/chunk-HXKOIWLU.js.map +0 -1
  135. package/dist/chunk-IO5YBKHV.js.map +0 -1
  136. package/dist/chunk-MHRC3KRX.js.map +0 -1
  137. package/dist/chunk-MO5FGLVS.js.map +0 -1
  138. package/dist/chunk-PMUABBPG.js.map +0 -1
  139. package/dist/chunk-PNMM5HNX.js.map +0 -1
  140. package/dist/chunk-RWOYPOMR.js.map +0 -1
  141. package/dist/chunk-TNGMF4UX.js.map +0 -1
  142. package/dist/chunk-VASLW636.js +0 -23
  143. package/dist/chunk-VASLW636.js.map +0 -1
  144. package/dist/chunk-WCAUUBHO.js.map +0 -1
  145. package/dist/chunk-WUQ3MTPF.js +0 -173
  146. package/dist/chunk-WUQ3MTPF.js.map +0 -1
  147. package/dist/chunk-XAXJWXI4.js +0 -1667
  148. package/dist/chunk-XAXJWXI4.js.map +0 -1
  149. package/dist/chunk-YO2LTXB4.js.map +0 -1
  150. package/dist/chunk-ZUAZHDKP.js.map +0 -1
  151. package/dist/copy-local-skills-NSUTBVLJ.js +0 -14
  152. package/dist/load-agent-defs-X4E57I2U.js +0 -15
  153. package/dist/loader-G6BFG2VA.js +0 -24
  154. package/dist/recompile-project-agents-JE4MM72I.js +0 -20
  155. package/dist/recompile-project-agents-JE4MM72I.js.map +0 -1
  156. package/dist/source-loader-3DL3NYUX.js.map +0 -1
  157. /package/dist/{chunk-LJCNUP6M.js.map → chunk-4ABNXKAR.js.map} +0 -0
  158. /package/dist/{chunk-D2CAV7MG.js.map → chunk-4DMFK67G.js.map} +0 -0
  159. /package/dist/{chunk-ILUVL7WM.js.map → chunk-DZD25NHW.js.map} +0 -0
  160. /package/dist/{chunk-PCC4LBKB.js.map → chunk-EEAX7E2X.js.map} +0 -0
  161. /package/dist/{chunk-SY4X2LND.js.map → chunk-KUZBMEWR.js.map} +0 -0
  162. /package/dist/{chunk-5OKLCVM4.js.map → chunk-KVVXINCJ.js.map} +0 -0
  163. /package/dist/{chunk-Y5Y7XHVU.js.map → chunk-PZNXBORZ.js.map} +0 -0
  164. /package/dist/{chunk-HTYH7CKN.js.map → chunk-Q7CAE5NN.js.map} +0 -0
  165. /package/dist/{chunk-G47TDUK3.js.map → chunk-QNAMXQKF.js.map} +0 -0
  166. /package/dist/{chunk-WFRTHH3A.js.map → chunk-TZRXWFF5.js.map} +0 -0
  167. /package/dist/{chunk-TBOVYLQJ.js.map → chunk-VTIDLRNA.js.map} +0 -0
  168. /package/dist/{chunk-OKH64JZE.js.map → chunk-WCZNQECQ.js.map} +0 -0
  169. /package/dist/{chunk-IXRZAHZF.js.map → chunk-XNYHMRVJ.js.map} +0 -0
  170. /package/dist/{chunk-VPASBA7P.js.map → chunk-YXI3BTQQ.js.map} +0 -0
  171. /package/dist/{copy-local-skills-NSUTBVLJ.js.map → load-agent-defs-2VYAV5GL.js.map} +0 -0
  172. /package/dist/{load-agent-defs-X4E57I2U.js.map → recompile-project-agents-NG5DCPHJ.js.map} +0 -0
  173. /package/dist/{loader-G6BFG2VA.js.map → source-loader-CO2FZ3OO.js.map} +0 -0
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SelectList
4
- } from "./chunk-TBOVYLQJ.js";
4
+ } from "./chunk-VTIDLRNA.js";
5
5
  import {
6
6
  seedToWizardResult
7
- } from "./chunk-MO5FGLVS.js";
7
+ } from "./chunk-54QLV3OH.js";
8
8
  import {
9
9
  runWizardSession
10
- } from "./chunk-IXRZAHZF.js";
10
+ } from "./chunk-XNYHMRVJ.js";
11
11
  import {
12
12
  useTerminalDimensions
13
- } from "./chunk-HG4JPXJT.js";
13
+ } from "./chunk-JG3B47P3.js";
14
14
  import {
15
15
  Spinner
16
16
  } from "./chunk-ZBPEFQ4G.js";
@@ -18,7 +18,7 @@ import {
18
18
  fetchSeedConfig,
19
19
  registerExternalSkills,
20
20
  writeExternalSkills
21
- } from "./chunk-PMUABBPG.js";
21
+ } from "./chunk-LKI3ENGQ.js";
22
22
  import {
23
23
  promptValue
24
24
  } from "./chunk-JCPANDNR.js";
@@ -26,54 +26,53 @@ import {
26
26
  compileAgentsAllScopes,
27
27
  loadSource,
28
28
  writeProjectConfig
29
- } from "./chunk-WUQ3MTPF.js";
29
+ } from "./chunk-H2DHTJKW.js";
30
30
  import {
31
+ copyLocalSkills,
31
32
  discoverInstalledSkills
32
- } from "./chunk-5QZAK6J7.js";
33
+ } from "./chunk-H25VRR2T.js";
33
34
  import {
34
35
  loadAgentDefs
35
- } from "./chunk-MHRC3KRX.js";
36
- import {
37
- copyLocalSkills
38
- } from "./chunk-F2AMBBIA.js";
36
+ } from "./chunk-H4CL23HG.js";
39
37
  import {
40
38
  render
41
39
  } from "./chunk-JFLVEFFP.js";
42
40
  import {
43
41
  BaseCommand,
44
42
  EXIT_CODES
45
- } from "./chunk-YO2LTXB4.js";
43
+ } from "./chunk-X52QUV4U.js";
46
44
  import {
47
45
  clearTerminalScreen
48
- } from "./chunk-G47TDUK3.js";
46
+ } from "./chunk-QNAMXQKF.js";
49
47
  import {
48
+ INCOMPLETE_WORK_RECOVERY,
50
49
  INSTALL_MODE_DESCRIPTIONS,
51
50
  INSTALL_MODE_LABELS,
52
51
  STATUS_MESSAGES,
53
- SUCCESS_MESSAGES,
52
+ agentsNotCompiled,
54
53
  buildAgentScopeMap,
55
54
  carriedSkillsWritten,
56
55
  deriveInstallMode,
57
56
  detectGlobalInstallation,
58
57
  detectInstallation,
59
58
  detectProjectInstallation,
59
+ fileExists,
60
+ getErrorMessage,
60
61
  getInstallationInfo,
61
62
  globalScopedAgentsHint,
63
+ initSucceeded,
62
64
  isHomeDirectory,
63
65
  loadProjectConfig,
66
+ readFileSafe,
67
+ resolveBranding,
64
68
  resolveInstallPaths,
69
+ settingsFileSchema,
65
70
  sharedConfigExistingInstall,
66
71
  sharedConfigGlobalInstall,
67
72
  skippedUnknownAgents,
68
- skippedUnknownSkills
69
- } from "./chunk-WCAUUBHO.js";
70
- import {
71
- fileExists,
72
- getErrorMessage,
73
- readFileSafe,
74
- settingsFileSchema,
73
+ skippedUnknownSkills,
75
74
  warn
76
- } from "./chunk-XAXJWXI4.js";
75
+ } from "./chunk-3PJLLBUS.js";
77
76
  import {
78
77
  ASCII_LOGO,
79
78
  CLAUDE_DIR,
@@ -85,7 +84,7 @@ import {
85
84
  EJECT_SOURCE,
86
85
  MAX_CONFIG_FILE_SIZE,
87
86
  STANDARD_FILES
88
- } from "./chunk-IO5YBKHV.js";
87
+ } from "./chunk-G6G2FT2G.js";
89
88
 
90
89
  // src/cli/commands/init.tsx
91
90
  import "react";
@@ -163,11 +162,12 @@ var DASHBOARD_OPTIONS = [
163
162
  { label: "Doctor", value: "doctor" },
164
163
  { label: "List", value: "list" }
165
164
  ];
166
- var Dashboard = ({ onSelect, onCancel }) => {
165
+ var DashboardTitle = ({ name }) => name === DEFAULT_BRANDING.NAME ? /* @__PURE__ */ jsx2(Text2, { children: ASCII_LOGO }) : /* @__PURE__ */ jsx2(Text2, { bold: true, children: name });
166
+ var Dashboard = ({ name, onSelect, onCancel }) => {
167
167
  const { exit } = useApp();
168
168
  const { rows: terminalHeight } = useTerminalDimensions();
169
169
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", height: terminalHeight, children: [
170
- /* @__PURE__ */ jsx2(Box2, { marginBottom: 1, children: /* @__PURE__ */ jsx2(Text2, { children: ASCII_LOGO }) }),
170
+ /* @__PURE__ */ jsx2(Box2, { marginBottom: 1, children: /* @__PURE__ */ jsx2(DashboardTitle, { name }) }),
171
171
  /* @__PURE__ */ jsx2(
172
172
  SelectList,
173
173
  {
@@ -187,7 +187,7 @@ var Dashboard = ({ onSelect, onCancel }) => {
187
187
  function formatDashboardText(data) {
188
188
  const modeLabel = INSTALL_MODE_LABELS[data.mode];
189
189
  const lines = [
190
- DEFAULT_BRANDING.NAME,
190
+ data.name,
191
191
  "",
192
192
  ` Skills: ${data.skillCount} installed`,
193
193
  ` Agents: ${data.agentCount} compiled`,
@@ -208,7 +208,14 @@ async function showDashboard(projectDir, log) {
208
208
  return null;
209
209
  }
210
210
  const selectedCommand = await promptValue(
211
- (resolve) => /* @__PURE__ */ jsx2(Dashboard, { onSelect: (command) => resolve(command), onCancel: () => resolve(null) }),
211
+ (resolve) => /* @__PURE__ */ jsx2(
212
+ Dashboard,
213
+ {
214
+ name: data.name,
215
+ onSelect: (command) => resolve(command),
216
+ onCancel: () => resolve(null)
217
+ }
218
+ ),
212
219
  { onExit: null, clearOnResolve: true }
213
220
  );
214
221
  clearTerminalScreen();
@@ -234,6 +241,13 @@ function sharedConfigSourceFlags(flags, payload) {
234
241
  return { marketplace: flags.marketplace ?? payload.marketplace };
235
242
  }
236
243
  var Init = class _Init extends BaseCommand {
244
+ /**
245
+ * The name this run prints itself under, resolved once on {@link install}'s spine because the
246
+ * closing line is printed several calls below it. Same shape and same reason as `uninstall`'s
247
+ * field: a plain `string` holding the shipped default rather than an optional every reader
248
+ * would have to answer for.
249
+ */
250
+ brandingName = DEFAULT_BRANDING.NAME;
237
251
  static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;
238
252
  static description = "Interactive wizard to set up skills and agents. Supports Plugin Mode (native install) and Eject Mode (copy to .claude/).";
239
253
  static examples = [
@@ -257,15 +271,29 @@ var Init = class _Init extends BaseCommand {
257
271
  helpValue: "<id>"
258
272
  })
259
273
  };
274
+ /**
275
+ * The command in two statements: do the work, then answer for it.
276
+ *
277
+ * {@link install} owns every path through the setup and returns however it likes; the exit
278
+ * code is decided once, here, after the last of them. Deciding it inside would mean deciding
279
+ * it at each of that method's endings, and an ending added later would inherit the exit-0
280
+ * default silently — which is the defect this pair exists to close. `edit` is two statements
281
+ * for the same reason.
282
+ */
283
+ async run() {
284
+ await this.install();
285
+ this.exitIfWorkIncomplete();
286
+ }
260
287
  /**
261
288
  * One spine, two producers. The wizard and a shared id differ only in *where the selection
262
289
  * comes from* — everything after it (the empty guard, the install pipeline) is identical, so it
263
290
  * lives here once rather than being written twice and drifting.
264
291
  */
265
- async run() {
292
+ async install() {
266
293
  const { flags } = await this.parse(_Init);
267
294
  const projectDir = process.cwd();
268
295
  await this.ensureConfigReadable(projectDir);
296
+ this.brandingName = await this.resolveBrandingName(projectDir);
269
297
  if (!flags.from && await this.showDashboardIfInitialized(projectDir)) return;
270
298
  const selection = flags.from ? await this.selectionFromSharedConfig(flags.from, flags, projectDir) : await this.selectionFromWizard(flags, projectDir);
271
299
  if (!selection) this.exit(EXIT_CODES.CANCELLED);
@@ -571,13 +599,39 @@ var Init = class _Init extends BaseCommand {
571
599
  skills: allSkills,
572
600
  agentScopeMap
573
601
  });
574
- this.log(`Compiled ${compileResult.compiled.length} agents
575
- `);
602
+ this.reportCompilation(compileResult);
576
603
  this.reportPropagatedRecompile(configResult.propagation);
577
604
  return { configResult, compileResult, agentScopeMap };
578
605
  }
606
+ /**
607
+ * What the compile pass did, including the half this command used to drop.
608
+ *
609
+ * It read `compiled` and nothing else, so a pass that lost a sub-agent printed a number that
610
+ * looked perfectly right — `compiled` counts successes, so it is correct either way — and the
611
+ * failures reached no surface at all: no count, no reason, no exit code. A user's FIRST
612
+ * install could silently land a roster missing a sub-agent.
613
+ *
614
+ * The compile is the last thing `init` does, so a failure here cannot be answered by aborting:
615
+ * the skills are on disk and `config.ts` and `config-types.ts` describe them. What is owed is
616
+ * the account, which {@link BaseCommand.exitIfWorkIncomplete} prints and answers for.
617
+ */
618
+ reportCompilation(compileResult) {
619
+ const { compiled, failed, warnings } = compileResult;
620
+ const summary = `Compiled ${compiled.length} agents`;
621
+ if (failed.length === 0) {
622
+ this.log(`${summary}
623
+ `);
624
+ return;
625
+ }
626
+ this.log(`${summary} (${failed.length} failed)
627
+ `);
628
+ for (const warning of warnings) {
629
+ this.warn(warning);
630
+ }
631
+ this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);
632
+ }
579
633
  reportSuccess(configResult, compileResult, agentScopeMap, installMode, pluginModeSucceeded, copyResult) {
580
- this.log(`${SUCCESS_MESSAGES.INIT_SUCCESS}
634
+ if (!this.hasIncompleteWork) this.log(`${initSucceeded(this.brandingName)}
581
635
  `);
582
636
  const isEjectOutput = installMode === "eject" || installMode === "mixed" && !pluginModeSucceeded;
583
637
  if (isEjectOutput && copyResult && copyResult.totalCopied > 0) {
@@ -699,13 +753,23 @@ function customizationSteps(split, globalConfigPath) {
699
753
  ];
700
754
  }
701
755
  async function getDashboardData(projectDir) {
702
- const [info, loaded] = await Promise.all([getInstallationInfo(), loadProjectConfig(projectDir)]);
756
+ const [info, loaded, branding] = await Promise.all([
757
+ getInstallationInfo(),
758
+ loadProjectConfig(projectDir),
759
+ resolveBranding(projectDir)
760
+ ]);
703
761
  const activeSkills = loaded?.config.skills.filter((s) => !s.excluded);
704
762
  const skillCount = info?.skillCount ?? 0;
705
763
  const agentCount = info?.agentCount ?? 0;
706
764
  const mode = info?.mode ?? (activeSkills ? deriveInstallMode(activeSkills) : "eject");
707
765
  const source = loaded?.config.marketplace;
708
- return { skillCount, agentCount, mode, ...source !== void 0 && { source } };
766
+ return {
767
+ name: branding.name,
768
+ skillCount,
769
+ agentCount,
770
+ mode,
771
+ ...source !== void 0 && { source }
772
+ };
709
773
  }
710
774
 
711
775
  export {
@@ -715,4 +779,4 @@ export {
715
779
  Init,
716
780
  getDashboardData
717
781
  };
718
- //# sourceMappingURL=chunk-H6UTKTLK.js.map
782
+ //# sourceMappingURL=chunk-DAUY2SB3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/init.tsx","../src/cli/lib/permission-checker.tsx"],"sourcesContent":["import React from \"react\";\n\nimport { Flags, type Interfaces } from \"@oclif/core\";\nimport { Box, Text, useApp } from \"ink\";\nimport { render } from \"../components/render.js\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { type WizardResultV2 } from \"../components/wizard/wizard.js\";\nimport { runWizardSession } from \"../components/wizard/run-wizard-session.js\";\nimport { useTerminalDimensions } from \"../components/hooks/use-terminal-dimensions.js\";\nimport { type SourceLoadResult } from \"../lib/loading/index.js\";\nimport {\n loadSource,\n loadAgentDefs,\n copyLocalSkills,\n writeProjectConfig,\n compileAgentsAllScopes,\n type CompilationResult,\n type SkillCopyResult,\n discoverInstalledSkills,\n} from \"../lib/operations/index.js\";\nimport { fetchSeedConfig } from \"../lib/seed/fetch-seed.js\";\nimport {\n registerExternalSkills,\n writeExternalSkills,\n type ExternalSkillInstall,\n} from \"../lib/seed/external-skills.js\";\nimport { seedToWizardResult, type SeedMapping } from \"../lib/seed/seed-to-wizard.js\";\nimport { getInstallationInfo } from \"../lib/plugins/plugin-info.js\";\nimport { loadProjectConfig } from \"../lib/configuration/project-config.js\";\nimport { resolveBranding } from \"../lib/configuration/config.js\";\nimport {\n type InstallMode,\n detectInstallation,\n detectGlobalInstallation,\n detectProjectInstallation,\n deriveInstallMode,\n resolveInstallPaths,\n buildAgentScopeMap,\n isHomeDirectory,\n INSTALL_MODE_LABELS,\n INSTALL_MODE_DESCRIPTIONS,\n} from \"../lib/installation/index.js\";\nimport { checkPermissions } from \"../lib/permission-checker.js\";\nimport {\n ASCII_LOGO,\n CLAUDE_SRC_DIR,\n CLI_INVOKE_COMMAND,\n DEFAULT_BRANDING,\n EDIT_PROJECT_SETUP_FLAG,\n EJECT_SOURCE,\n STANDARD_FILES,\n} from \"../consts.js\";\nimport { clearTerminalScreen } from \"../utils/terminal.js\";\nimport { SelectList, type SelectListItem } from \"../components/common/select-list.js\";\nimport { promptValue } from \"../components/common/prompt-confirm.js\";\nimport { Spinner } from \"../components/common/spinner.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport type { AgentName, MergedSkillsMatrix, SkillScope } from \"../types/index.js\";\nimport { type StartupMessage } from \"../utils/logger.js\";\nimport {\n INCOMPLETE_WORK_RECOVERY,\n STATUS_MESSAGES,\n agentsNotCompiled,\n carriedSkillsWritten,\n globalScopedAgentsHint,\n initSucceeded,\n sharedConfigExistingInstall,\n sharedConfigGlobalInstall,\n skippedUnknownAgents,\n skippedUnknownSkills,\n} from \"../utils/messages.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\nconst DASHBOARD_OPTIONS = [\n { label: \"Edit\", value: \"edit\" },\n { label: \"Compile\", value: \"compile\" },\n { label: \"Doctor\", value: \"doctor\" },\n { label: \"List\", value: \"list\" },\n] as const satisfies readonly SelectListItem<string>[];\n\n/** The commands offered by the project dashboard (single source: DASHBOARD_OPTIONS). */\nexport type DashboardCommand = (typeof DASHBOARD_OPTIONS)[number][\"value\"];\n\n/**\n * The dashboard's title: {@link ASCII_LOGO} for an installation resting on the shipped branding,\n * and the configured name in its place for one that white-labels it.\n *\n * **The logo gives way rather than sitting above the name, because it spells the shipped name.**\n * `branding.name` replaces a heading everywhere else it is read — every configured leg of\n * `commands/branding-name-reaches-headings` asserts {@link DEFAULT_BRANDING.NAME} is ABSENT — so\n * painting `AGENTS INC` in block capitals above `Northwind` would leave the vendor's name at the\n * most prominent surface the product has, which is the one thing white-labelling is for.\n *\n * The default path is untouched by construction: {@link resolveBranding} answers\n * {@link DEFAULT_BRANDING.NAME} for a configuration with no `branding` key, so an unbranded\n * install takes the logo arm. A configuration naming the shipped name explicitly takes it too —\n * it asked for the shipped name and gets the shipped presentation of it.\n */\nconst DashboardTitle: React.FC<{ name: string }> = ({ name }) =>\n name === DEFAULT_BRANDING.NAME ? <Text>{ASCII_LOGO}</Text> : <Text bold>{name}</Text>;\n\ntype DashboardProps = {\n /** The resolved branding name, as {@link DashboardData.name} carries it. */\n name: string;\n onSelect: (command: DashboardCommand) => void;\n onCancel: () => void;\n};\n\nconst Dashboard: React.FC<DashboardProps> = ({ name, onSelect, onCancel }) => {\n const { exit } = useApp();\n const { rows: terminalHeight } = useTerminalDimensions();\n\n return (\n <Box flexDirection=\"column\" height={terminalHeight}>\n <Box marginBottom={1}>\n <DashboardTitle name={name} />\n </Box>\n <SelectList\n items={DASHBOARD_OPTIONS}\n onSelect={(command) => {\n onSelect(command);\n exit();\n }}\n onCancel={() => {\n onCancel();\n exit();\n }}\n />\n </Box>\n );\n};\n\n/** Formats the dashboard summary as plain text lines (for non-interactive/test output). */\nexport function formatDashboardText(data: DashboardData): string {\n const modeLabel = INSTALL_MODE_LABELS[data.mode];\n const lines = [\n data.name,\n \"\",\n ` Skills: ${data.skillCount} installed`,\n ` Agents: ${data.agentCount} compiled`,\n ` Mode: ${modeLabel}`,\n ];\n if (data.source) {\n lines.push(` Marketplace: ${data.source}`);\n }\n lines.push(\"\");\n lines.push(` [Edit] [Compile] [Doctor] [List]`);\n return lines.join(\"\\n\");\n}\n\n/**\n * Shows the project dashboard and returns the selected command (or null if cancelled).\n * In non-interactive environments (no TTY), prints the summary text and returns null.\n */\nexport async function showDashboard(\n projectDir: string,\n log?: (message: string) => void,\n): Promise<DashboardCommand | null> {\n const data = await getDashboardData(projectDir);\n\n // Non-interactive: print text summary and exit (CI, piped, tests)\n if (!process.stdin.isTTY) {\n const output = log ?? console.log;\n output(formatDashboardText(data));\n return null;\n }\n\n // First-wins resolution via promptValue; clearOnResolve repaints a clean\n // terminal before unmount (dashboard occupies the full height).\n const selectedCommand = await promptValue<DashboardCommand | null>(\n (resolve) => (\n <Dashboard\n name={data.name}\n onSelect={(command) => resolve(command)}\n onCancel={() => resolve(null)}\n />\n ),\n { onExit: null, clearOnResolve: true },\n );\n\n clearTerminalScreen();\n\n return selectedCommand;\n}\n\n/**\n * Why the dashboard is on screen.\n *\n * `\"init\"` — the user ran `cc init` in an already-installed directory. That is a request\n * to set this project up, so choosing Edit continues the setup: it must materialise the\n * project even if the wizard changes nothing.\n *\n * `\"standalone\"` — the bare `cc` dashboard. Edit is just an editor there; a pass with no\n * changes is an inspection and must leave the filesystem untouched.\n */\nexport type DashboardOrigin = \"init\" | \"standalone\";\n\n/** The extra argv a dashboard selection needs to carry its origin into the command. */\nfunction dashboardCommandArgv(command: DashboardCommand, origin: DashboardOrigin): string[] {\n if (command !== \"edit\" || origin !== \"init\") return [];\n return [`--${EDIT_PROJECT_SETUP_FLAG}`];\n}\n\n/**\n * Shared dashboard entry: when the project is already initialized, shows the\n * dashboard and runs the chosen command. Returns true when the project was\n * initialized (dashboard shown), false otherwise. Never exits the process —\n * callers decide (the init hook exits SUCCESS at its own call site).\n */\nexport async function runDashboardFlow(\n projectDir: string,\n config: Interfaces.Config,\n origin: DashboardOrigin,\n log?: (message: string) => void,\n): Promise<boolean> {\n const installation = await detectInstallation(projectDir);\n if (!installation) return false;\n\n const selectedCommand = await showDashboard(projectDir, log);\n if (selectedCommand) {\n await config.runCommand(selectedCommand, dashboardCommandArgv(selectedCommand, origin));\n }\n return true;\n}\n\n/**\n * What `init` decided to install, and the little each producer knows that the shared spine does\n * not. Keeping these on the value rather than branching on a flag downstream is what stops the\n * two paths growing separate copies of the install sequence.\n */\n/**\n * The marketplace this run was pointed at, as oclif hands it over.\n *\n * `marketplace` is a required key holding `string | undefined` rather than\n * `marketplace?: string` because that is what oclif produces: a non-required flag still gets\n * its key written on the parse result, set to `undefined` when it was not passed. Under\n * `exactOptionalPropertyTypes` the two are different types, and `?` would be describing a\n * producer that never omits the key.\n */\ntype SourceFlags = { marketplace: string | undefined };\n\ntype Selection = {\n result: WizardResultV2;\n sourceResult: SourceLoadResult;\n /**\n * The marketplace this selection was actually loaded from, which the shared spine records in\n * the written config. Carried on the value because a shared id may name one the command line\n * did not, and the install has to record where its skills really came from either way.\n */\n sourceFlags: SourceFlags;\n /** Whether a person is at the terminal, so the permission notice may wait for them. */\n interactive: boolean;\n /** What to say if the selection turns out to be empty — only the producer knows why it is. */\n emptyMessage: string;\n};\n\n/**\n * Whether a decoded selection would write anything into the user's own ~/.claude. Skills and\n * sub-agents are asked separately because either can be globally scoped on its own: a shared\n * configuration can pin every skill to the project and still send a sub-agent home, and the\n * reverse.\n */\nfunction writesGlobalContent(result: WizardResultV2): boolean {\n return (\n result.skills.some((skill) => skill.scope === \"global\") ||\n result.agentConfigs.some((agent) => agent.scope === \"global\")\n );\n}\n\n/**\n * Which marketplace a shared configuration installs from.\n *\n * A payload names the one its skills were fetched from, because a skill id carries whose skill it\n * is and never where that repository lives — so without the ref the load walks on to the default\n * public catalogue and installs a different repository's skill under the same id.\n *\n * `--marketplace` still outranks it: naming one is an instruction about THIS install, while the\n * payload's ref is a record of where the sharer's came from. A payload that names none leaves the\n * flag undefined, which puts the load back on the rungs it has always walked.\n */\nfunction sharedConfigSourceFlags(flags: SourceFlags, payload: SeedPayload): SourceFlags {\n return { marketplace: flags.marketplace ?? payload.marketplace };\n}\n\nexport default class Init extends BaseCommand {\n /**\n * The name this run prints itself under, resolved once on {@link install}'s spine because the\n * closing line is printed several calls below it. Same shape and same reason as `uninstall`'s\n * field: a plain `string` holding the shipped default rather than an optional every reader\n * would have to answer for.\n */\n private brandingName: string = DEFAULT_BRANDING.NAME;\n\n static summary = `Initialize ${DEFAULT_BRANDING.NAME} in this project`;\n static description =\n \"Interactive wizard to set up skills and agents. Supports Plugin Mode (native install) and Eject Mode (copy to .claude/).\";\n\n static examples = [\n {\n description: \"Start the setup wizard\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Initialize from a custom marketplace\",\n command: \"<%= config.bin %> <%= command.id %> --marketplace github:org/marketplace\",\n },\n ];\n\n static flags = {\n marketplace: Flags.string({\n char: \"m\",\n description: \"Skills marketplace path or URL\",\n required: false,\n }),\n from: Flags.string({\n description: \"Install a configuration shared from agentsinc.sh by its id, without the wizard\",\n helpValue: \"<id>\",\n }),\n };\n\n /**\n * The command in two statements: do the work, then answer for it.\n *\n * {@link install} owns every path through the setup and returns however it likes; the exit\n * code is decided once, here, after the last of them. Deciding it inside would mean deciding\n * it at each of that method's endings, and an ending added later would inherit the exit-0\n * default silently — which is the defect this pair exists to close. `edit` is two statements\n * for the same reason.\n */\n async run(): Promise<void> {\n await this.install();\n this.exitIfWorkIncomplete();\n }\n\n /**\n * One spine, two producers. The wizard and a shared id differ only in *where the selection\n * comes from* — everything after it (the empty guard, the install pipeline) is identical, so it\n * lives here once rather than being written twice and drifting.\n */\n private async install(): Promise<void> {\n const { flags } = await this.parse(Init);\n const projectDir = process.cwd();\n\n // Every route below reads the configs first — to show a dashboard, to refuse a shared id, or\n // to inline the global one. One that exists but cannot be read is recreated, not installed\n // over, and saying so here is what keeps the raw loader error off the screen.\n await this.ensureConfigReadable(projectDir);\n\n // Read once on the spine, because the closing line is printed several calls below it. The\n // degrade arm of `resolveBrandingName` cannot fire here: the line above has already refused\n // every config this would read.\n this.brandingName = await this.resolveBrandingName(projectDir);\n\n // Only a bare `init` is diverted to the dashboard. An id is an explicit instruction to install\n // *that* configuration, so it overrides an existing installation instead.\n if (!flags.from && (await this.showDashboardIfInitialized(projectDir))) return;\n\n const selection = flags.from\n ? await this.selectionFromSharedConfig(flags.from, flags, projectDir)\n : await this.selectionFromWizard(flags, projectDir);\n\n if (!selection) this.exit(EXIT_CODES.CANCELLED);\n\n // On the spine rather than in either producer: a broken constraint is a fact about the\n // selection, not about where it came from, and `edit` reports the same fact the same way\n // the moment the wizard hands it one. Both producers run the same validator over the same\n // matrix — the wizard over what was chosen, `--from` over what survived the decode — so\n // what is said here is this catalog's verdict either way.\n this.reportValidationErrors(selection.result.validation);\n\n // A sub-agent is installable on its own — it has front-matter, a prompt and a compiled file\n // without owning a single skill — so only a selection with neither is nothing to install.\n if (selection.result.skills.length === 0 && selection.result.selectedAgents.length === 0) {\n // The producer supplies the wording because only it knows why empty means what it means:\n // nothing chosen, versus a payload this catalog cannot install.\n this.error(selection.emptyMessage, { exit: EXIT_CODES.ERROR });\n }\n\n await this.handleInstallation(\n selection.result,\n selection.sourceResult,\n selection.sourceFlags,\n selection.interactive,\n );\n }\n\n /** The interactive producer: load the source, run the wizard, return what was chosen. */\n private async selectionFromWizard(\n flags: SourceFlags,\n projectDir: string,\n ): Promise<Selection | null> {\n // The blank global config is created by writeProjectConfig() once the\n // wizard succeeds, never before it renders: a cancelled init must leave no\n // artifact that the next run could mistake for an existing installation.\n const isGlobalRoot = isHomeDirectory(projectDir);\n\n const { sourceResult, startupMessages } = await this.loadWizardInputsUnderSpinner(flags);\n\n const result = await this.runWizard(startupMessages, isGlobalRoot);\n if (!result) return null;\n\n return {\n result,\n sourceResult,\n sourceFlags: flags,\n // A person is already at the terminal, so the permission notice can wait for them.\n interactive: true,\n emptyMessage: \"No skills selected\",\n };\n }\n\n /**\n * Everything the wizard needs, loaded behind a spinner that comes down whichever way the\n * await ends.\n *\n * The cleanup is a `finally` because a source that cannot be loaded refuses the run from\n * inside this await, and oclif would otherwise paint its error under an Ink tree still\n * repainting over it. Never a `catch`: the throw reaches oclif untouched, or both the\n * error rendering and the exit code change with it.\n */\n private async loadWizardInputsUnderSpinner(flags: SourceFlags): Promise<{\n sourceResult: SourceLoadResult;\n startupMessages: StartupMessage[];\n }> {\n const { unmount, clear: clearSpinner } = render(\n <Spinner label={STATUS_MESSAGES.LOADING_SKILLS} />,\n );\n try {\n return await this.loadSourceOrFail(flags);\n } finally {\n clearSpinner();\n unmount();\n }\n }\n\n /**\n * The `--from <id>` producer: fetch and map, no wizard. Nothing here may assume a TTY — running\n * headless is most of why the flag exists.\n *\n * It is also greenfield-only, which is what two of the three refusals are: a shared\n * configuration is installed whole, so anything it would have to install over has to be\n * uninstalled first. The third is about the LOCATION rather than what is already in it — a\n * global installation holds only global-scoped content, and this is the one producer that never\n * asked. All three fire before anything is written.\n */\n private async selectionFromSharedConfig(\n id: string,\n flags: SourceFlags,\n projectDir: string,\n ): Promise<Selection> {\n await this.refuseInstalledProject(projectDir);\n\n this.log(`Fetching configuration ${id}...`);\n const fetched = await fetchSeedConfig(id);\n if (!fetched.ok) {\n this.error(fetched.error, { exit: EXIT_CODES.ERROR });\n }\n\n const sourceFlags = sharedConfigSourceFlags(flags, fetched.payload);\n const { sourceResult } = await this.loadSourceOrFail(sourceFlags);\n // Before the decode, because a skill the payload CARRIES answers to no catalogue: unseated,\n // its id is skipped like any other unknown one and its content is never read.\n const carriedSkills = this.registerExternalSkillsOrFail(\n fetched.payload,\n sourceResult.matrix,\n projectDir,\n );\n const { result, skippedSkillIds, skippedAgentNames } = this.decodeSeedOrFail(\n fetched.payload,\n sourceResult.matrix,\n );\n\n // The location refusal is `BaseCommand`'s, because `edit --from` reaches the same\n // contradiction through the other door and an invariant enforced on one producer is enforced\n // nowhere. It runs before {@link refuseBlockingGlobalInstall} because it needs no filesystem\n // probe to answer: where the install root is, and what the payload said, is all of it.\n this.refuseProjectScopedContentAtHome(result, projectDir);\n await this.refuseBlockingGlobalInstall(result);\n\n // After the refusals and before the install: every refusal on this path fires with nothing\n // written, and the copy step that follows finds these skills already where they belong.\n await this.writeCarriedSkills(carriedSkills);\n\n // Named, not counted. \"3 skills were skipped\" cannot be acted on; the ids can, and this is the\n // one moment the user can tell whether what they shared is what they are getting. Worded once,\n // in `messages.ts`, because `edit --from` reports the same skips about the same wire.\n if (skippedSkillIds.length > 0) this.warn(skippedUnknownSkills(skippedSkillIds));\n if (skippedAgentNames.length > 0) this.warn(skippedUnknownAgents(skippedAgentNames));\n\n if (result.skills.length > 0) {\n this.log(\n `Installing ${result.skills.length} skill(s) across ${result.selectedAgents.length} sub-agent(s)\\n`,\n );\n }\n\n return {\n result,\n sourceResult,\n sourceFlags,\n interactive: false,\n emptyMessage: `Configuration '${id}' contains no skills this catalog can install.`,\n };\n }\n\n /**\n * Refuses to install a shared configuration into a directory that already has one.\n *\n * Project-scoped detection rather than `detectInstallation`, whose global fallback would refuse\n * every clean project on a machine with a global install — including for a payload that never\n * goes near it. Whether a global install is in the way is a question about the PAYLOAD, and\n * {@link refuseBlockingGlobalInstall} is where it is asked.\n *\n * This runs before the fetch: there is nothing to learn from the network about a directory that\n * is already spoken for.\n */\n private async refuseInstalledProject(projectDir: string): Promise<void> {\n const installation = await detectProjectInstallation(projectDir);\n if (!installation) return;\n\n this.error(sharedConfigExistingInstall(installation.configPath), { exit: EXIT_CODES.ERROR });\n }\n\n /**\n * The other half of the same rule. A payload carrying global-scoped skills or sub-agents writes\n * into the user's own ~/.claude, so an installation there is in its way even when this project\n * is spotless. A payload with nothing global cannot reach that far and is never refused for it.\n */\n private async refuseBlockingGlobalInstall(result: WizardResultV2): Promise<void> {\n if (!writesGlobalContent(result)) return;\n\n const globalInstallation = await detectGlobalInstallation();\n if (!globalInstallation) return;\n\n this.error(sharedConfigGlobalInstall(globalInstallation.configPath), {\n exit: EXIT_CODES.ERROR,\n });\n }\n\n /**\n * The decode refuses a payload the config model has nowhere to write (see `seedToWizardResult`).\n * That is a failure of this command, reported with this command's exit code rather than left to\n * surface as an unhandled throw.\n */\n private decodeSeedOrFail(payload: SeedPayload, matrix: MergedSkillsMatrix): SeedMapping {\n try {\n return seedToWizardResult(payload, matrix);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * Seats the catalogue entries the payload carries with it, or refuses the run.\n *\n * The refusal is `registerExternalSkills`' own — a carried skill asked for as a plugin, which\n * no marketplace serves — and is reported with this command's exit code for the same reason the\n * decode's is.\n */\n private registerExternalSkillsOrFail(\n payload: SeedPayload,\n matrix: MergedSkillsMatrix,\n projectDir: string,\n ): ExternalSkillInstall[] {\n try {\n return registerExternalSkills(payload, matrix, projectDir);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /** Writes the skills the payload brought with it, and says which they were. */\n private async writeCarriedSkills(carried: ExternalSkillInstall[]): Promise<void> {\n if (carried.length === 0) return;\n\n await writeExternalSkills(carried);\n // Named rather than counted, like the skips: these are the entries no catalogue can explain,\n // so this line is the only place the user learns what arrived with the configuration itself.\n this.log(carriedSkillsWritten(carried.map((skill) => skill.id)));\n }\n\n private async showDashboardIfInitialized(projectDir: string): Promise<boolean> {\n return runDashboardFlow(projectDir, this.config, \"init\", (msg) => this.log(msg));\n }\n\n private async loadSourceOrFail(\n flags: SourceFlags,\n ): Promise<{ sourceResult: SourceLoadResult; startupMessages: StartupMessage[] }> {\n try {\n const loaded = await loadSource({\n // The one load that may CHOOSE a marketplace rather than read the stored one.\n caller: \"init\",\n ...(flags.marketplace !== undefined && { sourceFlag: flags.marketplace }),\n projectDir: process.cwd(),\n captureStartupMessages: true,\n });\n return { sourceResult: loaded.sourceResult, startupMessages: loaded.startupMessages };\n } catch (error) {\n this.error(getErrorMessage(error), {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n /**\n * `init`'s wizard opens on an empty selection, and can open on nothing else: it is reached\n * only once {@link showDashboardIfInitialized} has found no installation, and that check\n * falls back to the home directory — so a global roster to hydrate from would have diverted\n * this run to the dashboard before the wizard was built. Hydrating a saved selection is\n * `edit`'s job, and `Edit.runEditWizard` is where it happens.\n */\n private async runWizard(\n startupMessages: StartupMessage[],\n isGlobalRoot: boolean,\n ): Promise<WizardResultV2 | null> {\n return runWizardSession({\n hydrate: { isEditingFromGlobalScope: isGlobalRoot },\n props: {\n version: this.config.version,\n logo: ASCII_LOGO,\n startupMessages,\n },\n onCancel: () => this.log(\"Setup cancelled\"),\n clearTerminal: () => this.clearTerminal(),\n });\n }\n\n private async handleInstallation(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: SourceFlags,\n /**\n * Whether the caller can hold the terminal. The permission notice is an Ink app with no exit\n * of its own, so `waitUntilExit()` only ever resolves because a person is there to end it —\n * which is fine after the wizard and a hang everywhere else. `--from` sets this false: it has\n * to complete over a pipe and in CI.\n */\n interactive = true,\n ): Promise<void> {\n const projectDir = process.cwd();\n const activeSkills = result.skills.filter((s) => !s.excluded);\n const installMode = deriveInstallMode(activeSkills);\n const ejectedSkills = activeSkills.filter((s) => s.origin === EJECT_SOURCE);\n const pluginSkills = activeSkills.filter((s) => s.origin !== EJECT_SOURCE);\n\n this.logInstallPlan(installMode, ejectedSkills, pluginSkills);\n\n // Resolve marketplace up front — BEFORE any filesystem mutation. If\n // resolution fails in mixed mode, the hard-error must fire before\n // `copyEjectSkillsStep` copies anything to `.claude/skills/`, otherwise\n // we leave an orphaned half-install with no config.ts to recognise it.\n const resolvedMarketplace =\n pluginSkills.length > 0\n ? await this.requireMarketplaceOrExit(\n sourceResult,\n \"install plugin skills\",\n (marketplace) => this.log(`Registering marketplace \"${marketplace}\"...`),\n )\n : null;\n\n const copyResult =\n installMode === \"eject\" || installMode === \"mixed\"\n ? await this.copyEjectSkillsStep(ejectedSkills, projectDir, sourceResult, installMode)\n : null;\n\n if (resolvedMarketplace !== null) {\n await this.installPluginSkillsReported(\n pluginSkills,\n resolvedMarketplace,\n projectDir,\n sourceResult.matrix,\n );\n }\n // The shared install reporter hard-errors on any failure, so reaching here with\n // a resolved marketplace means plugin mode fully succeeded.\n const pluginModeSucceeded = resolvedMarketplace !== null;\n\n try {\n const { configResult, compileResult, agentScopeMap } = await this.writeConfigAndCompile(\n result,\n sourceResult,\n flags,\n );\n this.reportSuccess(\n configResult,\n compileResult,\n agentScopeMap,\n installMode,\n pluginModeSucceeded,\n copyResult,\n );\n\n await this.showPermissionNotice(projectDir, interactive);\n } catch (error) {\n this.handleError(error);\n }\n }\n\n /**\n * The permission notice, where there is one to show. It is an Ink app with no exit of its own,\n * so `waitUntilExit()` only ever resolves because a person is there to end it — which is fine\n * after the wizard and a hang everywhere else. Without a terminal to hold, one frame is\n * rendered and let go: the notice is information, not a prompt, so there is nothing to answer\n * and nothing to wait for.\n */\n private async showPermissionNotice(projectDir: string, interactive: boolean): Promise<void> {\n const permissionWarning = await checkPermissions(projectDir);\n if (!permissionWarning) return;\n\n if (!interactive) {\n const { unmount } = render(permissionWarning);\n unmount();\n return;\n }\n\n const { waitUntilExit } = render(permissionWarning);\n await waitUntilExit();\n }\n\n private logInstallPlan(\n installMode: InstallMode,\n ejectedSkills: WizardResultV2[\"skills\"],\n pluginSkills: WizardResultV2[\"skills\"],\n ): void {\n this.log(\"\\n\");\n this.log(`Selected ${ejectedSkills.length + pluginSkills.length} skills`);\n this.log(\n `Install mode: ${\n installMode === \"mixed\"\n ? `${INSTALL_MODE_LABELS.mixed} (${ejectedSkills.length} eject, ${pluginSkills.length} plugin)`\n : INSTALL_MODE_DESCRIPTIONS[installMode]\n }`,\n );\n }\n\n private async copyEjectSkillsStep(\n localSkills: WizardResultV2[\"skills\"],\n projectDir: string,\n sourceResult: SourceLoadResult,\n installMode: InstallMode,\n ): Promise<SkillCopyResult> {\n this.log(\"Copying skills to local directory...\");\n const copyResult = await copyLocalSkills(localSkills, projectDir, sourceResult);\n\n if (installMode === \"mixed\") {\n if (copyResult.projectCopied.length > 0 && copyResult.globalCopied.length > 0) {\n this.log(\n `Copied ${copyResult.totalCopied} local skills (${copyResult.projectCopied.length} project, ${copyResult.globalCopied.length} global)`,\n );\n } else if (copyResult.globalCopied.length > 0) {\n this.log(`Copied ${copyResult.globalCopied.length} local skills to ~/.claude/skills/`);\n } else {\n this.log(`Copied ${copyResult.projectCopied.length} local skills to .claude/skills/`);\n }\n } else {\n this.log(`Copied ${copyResult.totalCopied} skills to .claude/skills/\\n`);\n }\n\n return copyResult;\n }\n\n private async writeConfigAndCompile(\n result: WizardResultV2,\n sourceResult: SourceLoadResult,\n flags: SourceFlags,\n ): Promise<{\n configResult: Awaited<ReturnType<typeof writeProjectConfig>>;\n compileResult: CompilationResult;\n agentScopeMap: Map<AgentName, SkillScope>;\n }> {\n this.log(\"Generating configuration...\");\n const configResult = await writeProjectConfig({\n wizardResult: result,\n sourceResult,\n projectDir: process.cwd(),\n ...(flags.marketplace !== undefined && { sourceFlag: flags.marketplace }),\n });\n\n if (configResult.wasMerged) {\n this.log(`Merged with existing config at ${configResult.existingConfigPath}`);\n }\n\n this.log(`Configuration saved (${configResult.config.agents.length} agents)\\n`);\n this.reportUnassignedSkills(configResult.config);\n\n this.log(STATUS_MESSAGES.COMPILING_AGENTS);\n const cwd = process.cwd();\n const agentDefs = await loadAgentDefs();\n const { allSkills } = await discoverInstalledSkills(cwd);\n const agentScopeMap = buildAgentScopeMap(configResult.config);\n const compileResult = await compileAgentsAllScopes({\n projectDir: cwd,\n sourcePath: agentDefs.sourcePath,\n skills: allSkills,\n agentScopeMap,\n });\n this.reportCompilation(compileResult);\n\n this.reportPropagatedRecompile(configResult.propagation);\n\n return { configResult, compileResult, agentScopeMap };\n }\n\n /**\n * What the compile pass did, including the half this command used to drop.\n *\n * It read `compiled` and nothing else, so a pass that lost a sub-agent printed a number that\n * looked perfectly right — `compiled` counts successes, so it is correct either way — and the\n * failures reached no surface at all: no count, no reason, no exit code. A user's FIRST\n * install could silently land a roster missing a sub-agent.\n *\n * The compile is the last thing `init` does, so a failure here cannot be answered by aborting:\n * the skills are on disk and `config.ts` and `config-types.ts` describe them. What is owed is\n * the account, which {@link BaseCommand.exitIfWorkIncomplete} prints and answers for.\n */\n private reportCompilation(compileResult: CompilationResult): void {\n const { compiled, failed, warnings } = compileResult;\n const summary = `Compiled ${compiled.length} agents`;\n\n if (failed.length === 0) {\n this.log(`${summary}\\n`);\n return;\n }\n\n this.log(`${summary} (${failed.length} failed)\\n`);\n for (const warning of warnings) {\n this.warn(warning);\n }\n // Recorded off `failed` rather than off the warnings just printed: `warnings` also carries\n // entries that are not failures — a scope with nothing to compile contributes one on every\n // project-context run — and the ending must not file those as work owed.\n this.recordIncompleteWork(agentsNotCompiled(failed), INCOMPLETE_WORK_RECOVERY.RECOMPILE);\n }\n\n private reportSuccess(\n configResult: Awaited<ReturnType<typeof writeProjectConfig>>,\n compileResult: CompilationResult,\n agentScopeMap: Map<AgentName, SkillScope>,\n installMode: InstallMode,\n pluginModeSucceeded: boolean,\n copyResult: SkillCopyResult | null,\n ): void {\n // A run with work owed ends on the failure account instead — `initialized successfully!`\n // over a roster missing a sub-agent is the claim being withdrawn, not a line beside it.\n // Where the install landed is still reported below: that is what the account is about.\n if (!this.hasIncompleteWork) this.log(`${initSucceeded(this.brandingName)}\\n`);\n\n const isEjectOutput =\n installMode === \"eject\" || (installMode === \"mixed\" && !pluginModeSucceeded);\n if (isEjectOutput && copyResult && copyResult.totalCopied > 0) {\n this.reportSkillsCopied(copyResult);\n }\n this.reportAgentsCompiled(compileResult.compiled, agentScopeMap);\n this.reportConfiguration(configResult.configPath, agentScopeMap);\n }\n\n /**\n * Names the config that actually holds this install's assignments, and where a\n * recompile of them has to be run from.\n *\n * Split by the same `agentScopeMap` the two reporters above split on, because the\n * same scope decides both. A project config's `stack` is filtered down to\n * project-scoped agents on the way out, so a wholly GLOBAL install leaves it\n * carrying no assignment at all — naming it sends the user to a file with nothing\n * in it — and `compile` in this cwd runs the PROJECT pass, which recompiles no\n * global agent. At the home root both scopes resolve to one file and one pass, so\n * there is nothing to split and the project wording stands.\n */\n private reportConfiguration(\n projectConfigPath: string,\n agentScopeMap: Map<AgentName, SkillScope>,\n ): void {\n const cwd = process.cwd();\n const paths = {\n global: resolveInstallPaths(cwd, \"global\").configPath,\n project: projectConfigPath,\n };\n const split = splitAgentScopes(cwd, agentScopeMap);\n\n this.log(\"Configuration:\");\n for (const configPath of configsHoldingAssignments(split, paths)) {\n this.log(` ${configPath}`);\n }\n this.log(\"\");\n\n this.log(\"To customize agent-skill assignments:\");\n for (const [index, step] of customizationSteps(split, paths.global).entries()) {\n this.log(` ${index + 1}. ${step}`);\n }\n this.log(\"\");\n }\n\n /**\n * Reports where the skills actually landed. `copyLocalSkills` splits by scope,\n * so a default install driven from a project directory writes every skill\n * under HOME — reporting the project path there names a directory that was\n * never written.\n *\n * This block is a filesystem listing, so the entries are the on-disk directory\n * names — skill ids, not display names. `copySkillsToLocalFlattened` names each\n * destination directory after `skill.id`, so a user can copy any line and `cd`\n * into it.\n */\n private reportSkillsCopied(copyResult: SkillCopyResult): void {\n const cwd = process.cwd();\n const groups = isHomeDirectory(cwd)\n ? [\n {\n dir: resolveInstallPaths(cwd, \"project\").skillsDir,\n copied: [...copyResult.globalCopied, ...copyResult.projectCopied],\n },\n ]\n : [\n { dir: resolveInstallPaths(cwd, \"global\").skillsDir, copied: copyResult.globalCopied },\n { dir: resolveInstallPaths(cwd, \"project\").skillsDir, copied: copyResult.projectCopied },\n ].filter((group) => group.copied.length > 0);\n\n for (const group of groups) {\n this.log(\"Skills copied to:\");\n this.log(` ${group.dir}`);\n for (const copied of group.copied) {\n this.log(` ${copied.skillId}/`);\n }\n this.log(\"\");\n }\n }\n\n /**\n * Reports where the agents actually landed, mirroring the scope split\n * `compileAgentsAllScopes` performs: one pass at the home root, otherwise a\n * global pass under HOME and a project pass under the project directory.\n */\n private reportAgentsCompiled(\n compiled: AgentName[],\n agentScopeMap: Map<AgentName, SkillScope>,\n ): void {\n const cwd = process.cwd();\n const groups = isHomeDirectory(cwd)\n ? [{ dir: resolveInstallPaths(cwd, \"project\").agentsDir, agents: compiled }]\n : [\n {\n dir: resolveInstallPaths(cwd, \"global\").agentsDir,\n agents: compiled.filter((name) => agentScopeMap.get(name) === \"global\"),\n },\n {\n dir: resolveInstallPaths(cwd, \"project\").agentsDir,\n agents: compiled.filter((name) => agentScopeMap.get(name) !== \"global\"),\n },\n ].filter((group) => group.agents.length > 0);\n\n for (const group of groups) {\n this.log(\"Agents compiled to:\");\n this.log(` ${group.dir}`);\n for (const agentName of group.agents) {\n this.log(` ${agentName}.md`);\n }\n this.log(\"\");\n }\n }\n}\n\n/** The two config files an install can write, as the closing block refers to them. */\ntype ConfigPaths = { global: string; project: string };\n\n/** How this install's sub-agents fall across the two scopes, seen from the directory it ran in. */\ntype AgentScopeSplit = { globalAgentCount: number; isGlobalOnly: boolean };\n\n/**\n * At the home root the two scopes resolve to ONE config file and ONE compile pass, so there\n * is nothing to split and the split reports none — which is what leaves the project wording\n * standing there unchanged. Same fork `reportAgentsCompiled` makes over the same question.\n */\nfunction splitAgentScopes(cwd: string, agentScopeMap: Map<AgentName, SkillScope>): AgentScopeSplit {\n if (isHomeDirectory(cwd)) return { globalAgentCount: 0, isGlobalOnly: false };\n\n const scopes = [...agentScopeMap.values()];\n const globalAgentCount = scopes.filter((scope) => scope === \"global\").length;\n return {\n globalAgentCount,\n isGlobalOnly: globalAgentCount > 0 && globalAgentCount === scopes.length,\n };\n}\n\n/**\n * The config file(s) this install's assignments actually landed in. A wholly global install\n * has none in the project file — the writer filters its `stack` down to project-scoped\n * agents — so naming it would send the user to a file with nothing in it.\n */\nfunction configsHoldingAssignments(split: AgentScopeSplit, paths: ConfigPaths): string[] {\n if (split.isGlobalOnly) return [paths.global];\n if (split.globalAgentCount > 0) return [paths.global, paths.project];\n return [paths.project];\n}\n\n/**\n * What changing an assignment takes, in the order it takes it. The compile step is the half\n * that has to be scope-aware: `compile` run in a project directory performs the PROJECT pass\n * only, so it recompiles no global agent — which `globalScopedAgentsHint` already says, in\n * the words `compile` itself says it in when it lands in the mirror image of this state.\n */\nfunction customizationSteps(split: AgentScopeSplit, globalConfigPath: string): string[] {\n if (split.isGlobalOnly) {\n return [`Edit ${globalConfigPath}`, globalScopedAgentsHint(split.globalAgentCount)];\n }\n\n return [\n `Edit ${CLAUDE_SRC_DIR}/${STANDARD_FILES.CONFIG_TS}`,\n `Run '${CLI_INVOKE_COMMAND} compile' to regenerate agents`,\n ...(split.globalAgentCount > 0 ? [globalScopedAgentsHint(split.globalAgentCount)] : []),\n ];\n}\n\nexport type DashboardData = {\n /**\n * The name the dashboard is titled with — `branding.name` where the configuration supplies one\n * and {@link DEFAULT_BRANDING.NAME} otherwise. Carried on the data rather than read by either\n * consumer so {@link formatDashboardText} stays a pure function of what it is handed, and so\n * the one place that reaches a configuration is the one that already loads it.\n *\n * **Both of {@link showDashboard}'s branches read it, and that is the invariant to keep.** This\n * field was resolved for the piped branch alone for as long as it was, while the `Dashboard`\n * component was handed only its callbacks and painted {@link ASCII_LOGO} — so the dashboard a\n * person actually sees was the one surface `branding.name` never reached, and every spec on the\n * subject drove through a pipe and could not see it.\n */\n name: string;\n skillCount: number;\n agentCount: number;\n mode: InstallMode;\n source?: string;\n};\n\n/**\n * Gathers dashboard data from the installation and project config.\n *\n * Both counts come from the same scope-aware installation so the summary cannot\n * mix a project-only figure with a global one — a default install driven from a\n * project directory puts every skill and agent under HOME.\n */\nexport async function getDashboardData(projectDir: string): Promise<DashboardData> {\n // ABORT is the posture on `resolveBranding`, and it is the one already in force: the\n // `loadProjectConfig` beside it raises for the same file, so a configuration that cannot be\n // evaluated fails this call whether branding is read or not. Nothing is degraded here that was\n // not already, and the dashboard is only reached once an installation has been detected.\n const [info, loaded, branding] = await Promise.all([\n getInstallationInfo(),\n loadProjectConfig(projectDir),\n resolveBranding(projectDir),\n ]);\n\n const activeSkills = loaded?.config.skills.filter((s) => !s.excluded);\n const skillCount = info?.skillCount ?? 0;\n const agentCount = info?.agentCount ?? 0;\n const mode = info?.mode ?? (activeSkills ? deriveInstallMode(activeSkills) : \"eject\");\n const source = loaded?.config.marketplace;\n\n return {\n name: branding.name,\n skillCount,\n agentCount,\n mode,\n ...(source !== undefined && { source }),\n };\n}\n","import React from \"react\";\nimport { z } from \"zod\";\n\nimport { Text, Box } from \"ink\";\nimport path from \"path\";\n\nimport { CLAUDE_DIR, CLI_COLORS, MAX_CONFIG_FILE_SIZE, STANDARD_FILES } from \"../consts\";\nimport { fileExists, readFileSafe } from \"../utils/fs\";\nimport { warn } from \"../utils/logger\";\nimport { settingsFileSchema } from \"./schemas\";\n\ntype SettingsFile = z.infer<typeof settingsFileSchema>;\ntype PermissionConfig = NonNullable<SettingsFile[\"permissions\"]>;\n\n/**\n * Reads one settings file's permissions block; undefined when absent, malformed, or empty.\n *\n * settings.json belongs to Claude Code, which adds keys on its own release schedule. This CLI\n * consumes `permissions` and owns nothing else in the file, so it stays silent about every other\n * field rather than warning about settings it has no standing to judge.\n */\nasync function readSettingsPermissions(filePath: string): Promise<PermissionConfig | undefined> {\n if (!(await fileExists(filePath))) return undefined;\n try {\n const content = await readFileSafe(filePath, MAX_CONFIG_FILE_SIZE);\n const raw: unknown = JSON.parse(content);\n const result = settingsFileSchema.safeParse(raw);\n const parsed: SettingsFile = result.success ? result.data : {};\n return parsed.permissions;\n } catch {\n warn(`Malformed settings file at '${filePath}' — skipping`);\n return undefined;\n }\n}\n\n/** Permissions from the first settings file that defines them — settings.local.json wins. */\nasync function loadPermissions(projectRoot: string): Promise<PermissionConfig | undefined> {\n const settingsPath = path.join(projectRoot, CLAUDE_DIR, STANDARD_FILES.SETTINGS_JSON);\n const localSettingsPath = path.join(projectRoot, CLAUDE_DIR, STANDARD_FILES.SETTINGS_LOCAL_JSON);\n\n for (const filePath of [localSettingsPath, settingsPath]) {\n const permissions = await readSettingsPermissions(filePath);\n if (permissions) return permissions;\n }\n return undefined;\n}\n\nexport async function checkPermissions(projectRoot: string): Promise<React.ReactElement | null> {\n const permissions = await loadPermissions(projectRoot);\n\n if (!permissions) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Notice\n </Text>\n <Text>No permissions configured in .claude/settings.json</Text>\n <Text>Agents will prompt for approval on each tool use.</Text>\n <Text> </Text>\n <Text>For autonomous operation, add to .claude/settings.json:</Text>\n <Text> </Text>\n <Text color={CLI_COLORS.DIM}>{\"{\"}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"permissions\": {'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"allow\": ['}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Read(*)\",'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Bash(git *)\",'}</Text>\n <Text color={CLI_COLORS.DIM}>{' \"Bash(bun *)\"'}</Text>\n <Text color={CLI_COLORS.DIM}>{\" ]\"}</Text>\n <Text color={CLI_COLORS.DIM}>{\" }\"}</Text>\n <Text color={CLI_COLORS.DIM}>{\"}\"}</Text>\n </Box>\n );\n }\n\n const hasRestrictiveBash = permissions.deny?.some(\n (rule) => rule === \"Bash(*)\" || rule === \"Bash\",\n );\n const hasNoAllows = !permissions.allow || permissions.allow.length === 0;\n\n if (hasRestrictiveBash || hasNoAllows) {\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={CLI_COLORS.WARNING} padding={1}>\n <Text bold color={CLI_COLORS.WARNING}>\n Permission Warnings\n </Text>\n {hasRestrictiveBash && (\n <Text>\n ⚠ Bash is denied in permissions. Some agents require Bash for git, testing, and build\n commands.\n </Text>\n )}\n {hasNoAllows && (\n <Text>⚠ No allow rules configured. Agents will prompt for each tool use.</Text>\n )}\n </Box>\n );\n }\n\n return null;\n}\n"],"mappings":"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","names":["Box","Text","jsx","jsxs","Text","Box"]}
@@ -3,30 +3,28 @@ import {
3
3
  SEED_API_URL,
4
4
  SEED_USER_AGENT,
5
5
  readCarriedSkills
6
- } from "./chunk-PMUABBPG.js";
6
+ } from "./chunk-LKI3ENGQ.js";
7
7
  import {
8
8
  ERROR_MESSAGES,
9
9
  MATRIX_VERSION,
10
10
  SEED_VERSION,
11
+ directoryExists,
12
+ getErrorMessage,
13
+ installableSeedPayloadSchema,
11
14
  isScopePairCompatible,
12
15
  loadProjectConfig,
13
16
  readForkedFromMetadata,
14
17
  resolveInstallPaths,
15
- seedModelSchema,
16
- seedPayloadSchema
17
- } from "./chunk-WCAUUBHO.js";
18
- import {
19
- directoryExists,
20
- getErrorMessage
21
- } from "./chunk-XAXJWXI4.js";
18
+ seedModelSchema
19
+ } from "./chunk-3PJLLBUS.js";
22
20
  import {
23
21
  typedEntries,
24
22
  typedValues
25
- } from "./chunk-VASLW636.js";
23
+ } from "./chunk-7Z4N4JWQ.js";
26
24
  import {
27
25
  DEFAULT_PUBLIC_SOURCE_NAME,
28
26
  EJECT_SOURCE
29
- } from "./chunk-IO5YBKHV.js";
27
+ } from "./chunk-G6G2FT2G.js";
30
28
 
31
29
  // src/cli/lib/seed/installation-payload.ts
32
30
  import path from "path";
@@ -130,10 +128,13 @@ function configToSeedPayload(config, carried) {
130
128
  ...carried.uncarryable
131
129
  ];
132
130
  if (unshareable.length > 0) throw new Error(unshareableConfigError(unshareable));
133
- return seedPayloadSchema.parse({
131
+ return installableSeedPayloadSchema.parse({
134
132
  v: SEED_VERSION,
135
133
  matrixVersion: MATRIX_VERSION,
136
134
  stackId: null,
135
+ // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its
136
+ // body, so a key meaning what its absence already means would remint every ordinary payload.
137
+ ...config.description !== void 0 && { description: config.description },
137
138
  ...marketplace.ref !== void 0 && { marketplace: marketplace.ref },
138
139
  skills: Object.fromEntries(
139
140
  skills.map((skill) => [skill.id, toSeedSkill(skill, assignments.get(skill.id))])
@@ -243,4 +244,4 @@ export {
243
244
  skillsAuthoredHere,
244
245
  publishSeedConfig
245
246
  };
246
- //# sourceMappingURL=chunk-2H7UWE2G.js.map
247
+ //# sourceMappingURL=chunk-DP6YQFVO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/seed/installation-payload.ts","../src/cli/lib/seed/config-to-seed.ts","../src/cli/lib/seed/publish-seed.ts"],"sourcesContent":["import path from \"path\";\n\nimport { configToSeedPayload, isInstalled } from \"./config-to-seed.js\";\nimport { readCarriedSkills } from \"./external-skills.js\";\nimport { EJECT_SOURCE } from \"../../consts.js\";\nimport { loadProjectConfig } from \"../configuration/project-config.js\";\nimport { resolveInstallPaths } from \"../installation/install-base-dir.js\";\nimport { readForkedFromMetadata } from \"../skills/skill-metadata.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { directoryExists } from \"../../utils/fs.js\";\nimport { ERROR_MESSAGES } from \"../../utils/messages.js\";\n\nimport type { ContentReading, OwnedSkillDir } from \"./external-skills.js\";\nimport type { ProjectConfig, SkillConfig, SkillId } from \"../../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/**\n * A payload ready to post, and what it will install — counted the way the sharer's own screens\n * count it, off the payload rather than off the config, so what a caller announces and what it\n * posts cannot disagree.\n */\nexport type InstallationPayload =\n { ok: true; payload: SeedPayload; skills: number; agents: number } | { ok: false; error: string };\n\n/** The config to map, or the sentence explaining why there is none to map. */\ntype InstalledConfig = { ok: true; config: ProjectConfig } | { ok: false; error: string };\n\n/** The mapped payload, or every line naming something the contract cannot carry. */\ntype MappedPayload = { ok: true; payload: SeedPayload } | { ok: false; error: string };\n\n/** The installation as the round trip sees it: what it owns, and what it has to carry with it. */\ntype RoundTrip = { config: ProjectConfig; content: ContentReading };\n\n/**\n * What the round trip makes of one installed entry: whether it travels at all, and whether its\n * bytes travel with it.\n */\ntype SkillJudgement = { skill: SkillConfig; owned: boolean; carried: OwnedSkillDir | null };\n\n/**\n * Read, map, refuse — everything that can fail locally, failing before anybody spends a write.\n *\n * Shared by the two commands that mint an id for what is installed here: `share`, which reports\n * the id, and `edit --ui`, which opens it. They are one operation with two endings, and this is\n * the half that has to be identical — two spellings of \"the installation in this directory\"\n * would mint two different ids for one project, and only one of them would be true.\n *\n * Every failure is a message rather than a throw, because nothing has been written by the time\n * it runs: the caller's only job is to explain, and both callers explain the same way.\n */\nexport async function seedPayloadForInstallation(projectDir: string): Promise<InstallationPayload> {\n const installed = await readInstalledConfig(projectDir);\n if (!installed.ok) return installed;\n\n const mapped = mapOrRefuse(await readRoundTrip(installed.config, projectDir));\n if (!mapped.ok) return mapped;\n\n const { payload } = mapped;\n const skills = Object.keys(payload.skills).length;\n const agents = Object.keys(payload.agents).length;\n\n // The same guard `init --from` applies on arrival, applied here before the write instead of\n // there after it. A sub-agent is installable on its own — it has front-matter, a prompt and a\n // compiled file without owning a single skill — so only a configuration with neither skills\n // nor sub-agents is nothing to carry.\n if (skills === 0 && agents === 0) return { ok: false, error: ERROR_MESSAGES.NO_INSTALLATION };\n\n return { ok: true, payload, skills, agents };\n}\n\n/**\n * The installation this directory has: its own configuration, or the global one it inherits.\n *\n * That is the config every other command reads here, and it carries the entries of BOTH scopes\n * with each entry's own scope on it — which is exactly what the wire keys by. So a payload minted\n * from a project describes the whole of what is installed for it rather than half of it, and the\n * receiver puts each entry back where this one had it.\n *\n * A config file that exists but cannot be loaded is a fault, not an absence, so its own message\n * is reported rather than read as \"not installed\".\n */\nasync function readInstalledConfig(projectDir: string): Promise<InstalledConfig> {\n try {\n const loaded = await loadProjectConfig(projectDir);\n if (!loaded) return { ok: false, error: ERROR_MESSAGES.NO_INSTALLATION };\n return { ok: true, config: loaded.config };\n } catch (error) {\n return { ok: false, error: getErrorMessage(error) };\n }\n}\n\n/**\n * The installation minus what the round trip does not own, plus the content it has to take along.\n *\n * `forkedFrom` decides ownership, and the round trip leaves what it does not own alone. The CLI\n * stamps that key into every skill directory it writes — an ejected catalogue skill, and a skill\n * a payload carried inline — while a skill the user wrote by hand into `.claude/skills/` carries\n * none. So absence of the key is not the whole answer and provenance is: what the CLI put there\n * says so on disk, and what a person put there says nothing because nothing forked it.\n *\n * A user-authored skill is therefore neither carried nor refused — it is simply outside the\n * round trip, and nothing about leaving it home is lossy because it was never in scope. Dropping\n * it here rather than in a command is what keeps `share` and `edit --ui`, which mint an id from\n * the same directory, from disagreeing about a single project.\n *\n * The stack rows naming a dropped skill go with it: `configToSeedPayload` keys assignments by\n * the skills it carries, so a row whose skill is gone is gone too.\n *\n * One walk answers both questions, because they are asked of the same file: whether the CLI put\n * this directory here, and — for the one kind of skill no catalogue can resolve — where its bytes\n * came from, so they can travel a second time.\n */\nasync function readRoundTrip(config: ProjectConfig, projectDir: string): Promise<RoundTrip> {\n const owned = (await judgeSkills(config, projectDir)).filter((entry) => entry.owned);\n\n return {\n config: { ...config, skills: owned.map((entry) => entry.skill) },\n content: await readCarriedSkills(owned.flatMap((entry) => entry.carried ?? [])),\n };\n}\n\n/** Every installed entry, judged. One walk of the disk, whichever half of the trip is asking. */\nfunction judgeSkills(config: ProjectConfig, projectDir: string): Promise<SkillJudgement[]> {\n return Promise.all(config.skills.map((skill) => judgeSkill(skill, projectDir)));\n}\n\n/**\n * The installed skills the round trip does NOT own — the user's own work, sitting in\n * `.claude/skills/` with no `forkedFrom` to say the CLI put it there.\n *\n * The producer already drops these on the way out, so no payload minted here ever named one.\n * This is the same judgement read by the other half: `edit --from` applies a payload\n * destructively, and a payload that made no statement about a skill cannot be read as an\n * instruction to delete it. Both halves ask {@link judgeSkill}, so \"outside the round trip\" has\n * one definition and cannot come to mean two things on one machine.\n */\nexport async function skillsAuthoredHere(\n config: ProjectConfig,\n projectDir: string,\n): Promise<Set<SkillId>> {\n const judged = await judgeSkills(config, projectDir);\n return new Set(judged.filter((entry) => !entry.owned).map((entry) => entry.skill.id));\n}\n\n/** The entry travels and no directory is read for it: a row naming an id is the whole of it. */\nfunction travelsAsAnId(skill: SkillConfig): SkillJudgement {\n return { skill, owned: true, carried: null };\n}\n\n/**\n * How one installed entry answers to the round trip — asked of the disk, offline, exactly as\n * `uninstall` asks it before removing anything.\n *\n * Only a directory that EXISTS and carries no provenance is somebody's own work, and that is the\n * one thing this excludes; each guard below says why the case above it never gets that far.\n */\nasync function judgeSkill(skill: SkillConfig, projectDir: string): Promise<SkillJudgement> {\n // A marketplace skill has no local directory to hold provenance and needs none: the marketplace\n // is what installs it again.\n if (skill.origin !== EJECT_SOURCE) return travelsAsAnId(skill);\n // A tombstone is a statement about something that is NOT installed here, so there are no bytes\n // of it to carry — and a refusal raised over them would refuse a share for a skill it is not\n // sharing.\n if (!isInstalled(skill)) return travelsAsAnId(skill);\n\n const skillsDir = resolveInstallPaths(projectDir, skill.scope).skillsDir;\n const skillDir = path.join(skillsDir, skill.id);\n // A configuration recording an install that is not there is evidence of nothing rather than\n // evidence of authorship, so it travels as the configuration records it.\n if (!(await directoryExists(skillDir))) return travelsAsAnId(skill);\n\n const provenance = await readForkedFromMetadata(skillDir);\n if (provenance === null) return { skill, owned: false, carried: null };\n\n return { skill, owned: true, carried: { id: skill.id, skillDir, provenance } };\n}\n\n/**\n * The mapping, with its refusals turned into this module's own currency.\n *\n * `configToSeedPayload` throws, and what it throws is a list: every line names something this\n * installation has that a shared configuration cannot say. That is a message for the user, not a\n * fault to propagate — the alternative is worse than a failed command, because a payload quietly\n * missing what it could not say still mints an id, and that id installs a configuration nobody\n * chose.\n */\nfunction mapOrRefuse({ config, content }: RoundTrip): MappedPayload {\n try {\n return { ok: true, payload: configToSeedPayload(config, content) };\n } catch (error) {\n return { ok: false, error: getErrorMessage(error) };\n }\n}\n","import { MATRIX_VERSION } from \"@workspace/matrix\";\nimport {\n SEED_VERSION,\n installableSeedPayloadSchema,\n seedModelSchema,\n} from \"@workspace/matrix/seed\";\n\nimport { DEFAULT_PUBLIC_SOURCE_NAME, EJECT_SOURCE } from \"../../consts.js\";\nimport { isScopePairCompatible } from \"../configuration/config-generator.js\";\nimport { typedEntries, typedValues } from \"../../utils/typed-object.js\";\n\nimport type { ContentReading } from \"./external-skills.js\";\nimport type {\n AgentScopeConfig,\n ProjectConfig,\n SkillConfig,\n SkillScope,\n} from \"../../types/config.js\";\nimport type { ModelName } from \"../../types/matrix.js\";\nimport type { SkillId } from \"../../types/skills.js\";\nimport type {\n SeedAgent,\n SeedLoadState,\n SeedModel,\n SeedPayload,\n SeedSkill,\n} from \"@workspace/matrix/seed\";\n\n/** Sub-agent name -> load state for one skill: the shape the wire keys by skill. */\ntype SeedAssignments = Record<string, SeedLoadState>;\n\n/** What one walk of `config.stack` yields: the wire's assignments, and the rows that cannot be one. */\ntype StackReading = {\n assignments: Map<SkillId, SeedAssignments>;\n /** Pairs the config model has nowhere to write, worded for the refusal. */\n unwritable: string[];\n};\n\n/**\n * An installed entry. An excluded one is a tombstone — a statement about something that is NOT\n * installed here — and presence is selection on the wire, so it has nothing to say. Nothing is\n * lost by leaving it home either: `init --from` installs into a clean setup, where there is no\n * global install for a tombstone to mask.\n *\n * Exported because the reader that gathers what an installation CARRIES has to agree with the\n * mapper about what it installs: content read for an entry this payload will not name is content\n * paid for by nobody, and a refusal raised over it would refuse a share for a skill it is not\n * sharing.\n */\nexport function isInstalled(entry: { excluded?: boolean }): boolean {\n return !entry.excluded;\n}\n\n/**\n * Whether a skill from this origin obliges the payload to name a marketplace.\n *\n * Two do not. An ejected copy travels with the project, and the default public catalogue is what\n * an absent ref already means — so neither puts a ref on the wire, and two identical selections\n * cannot mint two different ids over one.\n */\nfunction needsMarketplaceNamed(origin: string): boolean {\n return origin !== EJECT_SOURCE && origin !== DEFAULT_PUBLIC_SOURCE_NAME;\n}\n\n/**\n * Asked of the contract's own enum rather than spelled out here, so widening `MODEL_NAMES`\n * without widening the wire cannot slip past as a silently dropped pin.\n */\nfunction isSeedModel(model: ModelName): model is SeedModel {\n return seedModelSchema.safeParse(model).success;\n}\n\n/** The wire spells as an enum what a stack entry spells as a boolean, and an absent flag is lazy. */\nfunction seedLoadState(preloaded: boolean | undefined): SeedLoadState {\n return preloaded === true ? \"preloaded\" : \"lazy\";\n}\n\nfunction unnameableOriginMessage(skill: SkillConfig): string {\n return `${skill.id} comes from the marketplace '${skill.origin}', and this installation does not record where that marketplace is fetched from`;\n}\n\nfunction unnameableModelMessage(agent: AgentScopeConfig[\"name\"], model: ModelName): string {\n return `${agent} pins model '${model}', which this contract has no word for — leaving it out would say \"keep the sub-agent's own metadata\", which is a different instruction`;\n}\n\nfunction unwritablePairMessage(skillId: SkillId, agent: string): string {\n return `${skillId} -> ${agent}: a project-scoped skill never reaches a sub-agent that rests at global scope`;\n}\n\n/**\n * Names everything the contract cannot carry at once, not one thing at a time: a sharer who fixes\n * one only to be refused for the next learns nothing the first message could not have told them.\n *\n * The refusal exists because the alternative is worse than a failed command. A payload quietly\n * missing what it could not say still mints an id, and that id installs a configuration nobody\n * chose — with nothing on either side saying so.\n */\nfunction unshareableConfigError(unshareable: string[]): string {\n return [\n \"This installation cannot be shared as it stands — a shared configuration has no way to carry:\",\n ...unshareable.map((line) => ` ${line}`),\n \"Sharing it anyway would mint an id that installs something else.\",\n ].join(\"\\n\");\n}\n\n/** The ref a payload has to carry, and the skills no ref this config holds can account for. */\ntype MarketplaceReading = {\n /** Absent when nothing installed here came from a marketplace. */\n ref: string | undefined;\n unnameable: string[];\n};\n\n/**\n * Whether the marketplace this installation reads is the one `skill` came from.\n *\n * A skill's `origin` is a marketplace's NAME, `config.marketplace` is the ref it was fetched from,\n * and `marketplaceName` is what joins them — the name the install read out of that repository's\n * own manifest. Without both halves agreeing, the ref would send the receiver to a repository that\n * never served this skill, which is the same silent swap under a different spelling.\n */\nfunction isRecordedMarketplace(config: ProjectConfig, skill: SkillConfig): boolean {\n return config.marketplace !== undefined && skill.origin === config.marketplaceName;\n}\n\n/** Which marketplace the payload names, decided by the skills that oblige it to name one. */\nfunction readMarketplace(config: ProjectConfig, skills: SkillConfig[]): MarketplaceReading {\n const served = skills.filter((skill) => needsMarketplaceNamed(skill.origin));\n if (served.length === 0) return { ref: undefined, unnameable: [] };\n\n const unaccounted = served.filter((skill) => !isRecordedMarketplace(config, skill));\n if (unaccounted.length > 0) {\n return { ref: undefined, unnameable: unaccounted.map(unnameableOriginMessage) };\n }\n\n return { ref: config.marketplace, unnameable: [] };\n}\n\nfunction unnameableModels(agents: AgentScopeConfig[]): string[] {\n return agents.flatMap((agent) =>\n agent.model !== undefined && !isSeedModel(agent.model)\n ? [unnameableModelMessage(agent.name, agent.model)]\n : [],\n );\n}\n\n/**\n * Turns `config.stack` inside out: it is keyed by sub-agent and this contract is keyed by skill.\n *\n * Rows naming a sub-agent or a skill this configuration does not install are dropped rather than\n * refused, because they are already no part of what is installed — `compile` warns about exactly\n * those and leaves them out of the agents it writes, so carrying them would share more than this\n * project has.\n *\n * A row the config model cannot write is the opposite case and is collected for the refusal: the\n * decoder turns the same pair away on the way back in, so minting it would produce an id that\n * cannot be installed.\n */\nfunction readStack(\n stack: ProjectConfig[\"stack\"],\n skillScopes: Map<SkillId, SkillScope>,\n agentScopes: Map<string, SkillScope>,\n): StackReading {\n const assignments = new Map<SkillId, SeedAssignments>();\n const unwritable: string[] = [];\n\n for (const [agent, agentStack] of typedEntries(stack ?? {})) {\n const agentScope = agentScopes.get(agent);\n if (agentScope === undefined) continue;\n\n for (const categoryAssignments of typedValues(agentStack)) {\n for (const { id, preloaded } of categoryAssignments) {\n const skillScope = skillScopes.get(id);\n if (skillScope === undefined) continue;\n\n if (!isScopePairCompatible(skillScope, agentScope)) {\n unwritable.push(unwritablePairMessage(id, agent));\n continue;\n }\n\n const forSkill = assignments.get(id) ?? {};\n forSkill[agent] = seedLoadState(preloaded);\n assignments.set(id, forSkill);\n }\n }\n }\n\n return { assignments, unwritable };\n}\n\nfunction toSeedSkill(skill: SkillConfig, assignments: SeedAssignments | undefined): SeedSkill {\n return {\n // \"eject\" is the project's own copy; anything else is a plugin the marketplace serves, and\n // which marketplace that is has already had to be one the envelope's ref accounts for.\n install: skill.origin === EJECT_SOURCE ? \"eject\" : \"plugin\",\n scope: skill.scope,\n assignments: assignments ?? {},\n };\n}\n\n/**\n * A sub-agent's own row, and it always says `on`.\n *\n * The web app pins `on` only where a person did, because there an agent switched on by its rows is\n * already implied by them. An installed config is not an inference — every sub-agent it names was\n * chosen and has a compiled file on disk — so saying so outright is what carries the one that owns\n * no skill, which is the only thing the agents map can do that assignments cannot.\n */\nfunction toSeedAgent(agent: AgentScopeConfig): SeedAgent {\n return {\n on: true,\n scope: agent.scope,\n ...(agent.model !== undefined && isSeedModel(agent.model) && { model: agent.model }),\n ...(agent.effort !== undefined && { effort: agent.effort }),\n };\n}\n\n/**\n * Turns the installation this directory records into the payload the config store holds, so the\n * CLI can mint an id rather than only consume one.\n *\n * The inverse of `seedToWizardResult` in `seed-to-wizard.ts`, and held to it: a\n * payload minted here and decoded there has to describe the same install. That is why the scope\n * of every skill and sub-agent travels per entry rather than being implied, why the whole stack\n * is carried as per-`(skill, sub-agent)` assignments, and why nothing here leans on a wire default\n * the decoder would have to guess back.\n *\n * What it will not do is share a thinner configuration than the one installed. Anything the\n * contract cannot state is refused by name — see {@link unshareableConfigError} — because the\n * failure mode of the alternative is an id that silently installs something else.\n *\n * `stackId` is always null. A saved config records a stack's expansion and never the id it came\n * from, and the assignments above carry that expansion in full; naming an id this module invented\n * would make the receiver overlay a stack's own preload flags over the curation being shared.\n *\n * `description` is what a resolvable id would have supplied that the assignments do not, so it is\n * carried directly instead. That is the whole of the trade: the sentence travels, the roster the id\n * would have dragged behind it does not.\n *\n * `marketplace` is the one field carried for the payload rather than for an entry, because the\n * receiver loads one catalogue before it reads a single skill row — see {@link readMarketplace}.\n *\n * `carried` arrives as an argument because it is read off disk and this mapping touches none:\n * every id above is resolved by the receiver against a catalogue it already has, and the entries\n * in `carried` are the ones that answer to no catalogue in either direction. Stated rather than\n * defaulted, because a producer that forgot the content is exactly the defect this closed.\n */\nexport function configToSeedPayload(config: ProjectConfig, carried: ContentReading): SeedPayload {\n const skills = config.skills.filter(isInstalled);\n const agents = config.agents.filter(isInstalled);\n const skillScopes = new Map(skills.map((skill) => [skill.id, skill.scope]));\n const agentScopes = new Map<string, SkillScope>(agents.map((agent) => [agent.name, agent.scope]));\n\n const { assignments, unwritable } = readStack(config.stack, skillScopes, agentScopes);\n const marketplace = readMarketplace(config, skills);\n\n const unshareable = [\n ...marketplace.unnameable,\n ...unnameableModels(agents),\n ...unwritable,\n ...carried.uncarryable,\n ];\n if (unshareable.length > 0) throw new Error(unshareableConfigError(unshareable));\n\n // Parsed rather than merely assembled, exactly as the web app's encoder is: it makes \"the JSON\n // the store will hold\" literal, and it is the one gate that catches a field whose values have\n // drifted out of the wire's enums since this module last named them.\n //\n // The INSTALLABLE half of the contract, which is the schema the store's POST route declares —\n // the lenient one exists for READING links already out in the world, and this module only ever\n // mints. It refuses nothing the refusal above permits, and that is the point: it is the belt\n // over those braces, so the day this module's own rule and the wire's disagree, the mint fails\n // loudly here instead of minting an id that cannot be installed.\n return installableSeedPayloadSchema.parse({\n v: SEED_VERSION,\n matrixVersion: MATRIX_VERSION,\n stackId: null,\n // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its\n // body, so a key meaning what its absence already means would remint every ordinary payload.\n ...(config.description !== undefined && { description: config.description }),\n ...(marketplace.ref !== undefined && { marketplace: marketplace.ref }),\n skills: Object.fromEntries(\n skills.map((skill) => [skill.id, toSeedSkill(skill, assignments.get(skill.id))]),\n ),\n // Absent rather than empty, for the reason the marketplace ref is: an id is the hash of its\n // body, so a key meaning what its absence already means would remint every ordinary payload.\n ...(Object.keys(carried.external).length > 0 && { external: carried.external }),\n agents: Object.fromEntries(agents.map((agent) => [agent.name, toSeedAgent(agent)])),\n });\n}\n","import { z } from \"zod\";\n\nimport { SEED_API_URL, SEED_USER_AGENT } from \"./fetch-seed.js\";\n\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/**\n * The store answers a stored configuration with its content-addressed id and nothing else.\n * Revalidated rather than read off the response type, because that type describes the worker this\n * CLI was built against and what answers is whatever is deployed.\n */\nconst mintedSchema = z.object({ id: z.string().min(1) });\n\nexport type PublishSeedResult = { ok: true; id: string } | { ok: false; error: string };\n\n/**\n * Stores a configuration and returns the id it was given.\n *\n * The outbound half of the boundary `fetchSeedConfig` in `fetch-seed.ts` owns the inbound half\n * of, and it keeps the same posture: every failure is a message rather than a throw.\n * Nothing local has been written by the time this runs, so there is nothing to roll back and the\n * caller's only job is to explain.\n *\n * The id is the payload's own hash, so re-sharing an unchanged configuration returns the id it\n * had — the store spends no write, and a caller can share as often as it likes.\n */\nexport async function publishSeedConfig(payload: SeedPayload): Promise<PublishSeedResult> {\n const url = `${SEED_API_URL}/configs`;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"POST\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n // The same signal the fetch half sends: it is the only thing that tells the store a\n // configuration came from the CLI rather than from a browser.\n \"user-agent\": SEED_USER_AGENT,\n },\n body: JSON.stringify(payload),\n });\n } catch {\n return { ok: false, error: `Could not reach ${SEED_API_URL} — check your connection.` };\n }\n\n if (!response.ok) {\n return { ok: false, error: `Sharing this configuration failed (HTTP ${response.status}).` };\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n return { ok: false, error: \"The configuration store returned something that is not JSON.\" };\n }\n\n const minted = mintedSchema.safeParse(body);\n if (!minted.success) {\n // Reporting success here would print an id nobody can install and tell the user to use it.\n return { ok: false, error: \"The configuration store did not return an id for this share.\" };\n }\n\n return { ok: true, id: minted.data.id };\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CLI_COLORS
4
- } from "./chunk-IO5YBKHV.js";
4
+ } from "./chunk-G6G2FT2G.js";
5
5
 
6
6
  // src/cli/components/wizard/toast.tsx
7
7
  import { Box, Text } from "ink";
@@ -25,4 +25,4 @@ var Toast = ({ children }) => {
25
25
  export {
26
26
  Toast
27
27
  };
28
- //# sourceMappingURL=chunk-ILUVL7WM.js.map
28
+ //# sourceMappingURL=chunk-DZD25NHW.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  StackSelection
4
- } from "./chunk-PNMM5HNX.js";
4
+ } from "./chunk-L4FHSOL5.js";
5
5
 
6
6
  // src/cli/components/wizard/step-stack.tsx
7
7
  import { Box } from "ink";
@@ -14,4 +14,4 @@ var StepStack = ({ onCancel }) => {
14
14
  export {
15
15
  StepStack
16
16
  };
17
- //# sourceMappingURL=chunk-PCC4LBKB.js.map
17
+ //# sourceMappingURL=chunk-EEAX7E2X.js.map
@@ -22,8 +22,12 @@ function marketplaceManifestPath(dir) {
22
22
  return path.join(dir, PLUGIN_MANIFEST_DIR, MARKETPLACE_JSON);
23
23
  }
24
24
  var DEFAULT_PLUGIN_NAME = "agents-inc";
25
- var GLOBAL_INSTALL_ROOT = os.homedir();
26
- var CACHE_DIR = path.join(os.homedir(), ".cache", DEFAULT_PLUGIN_NAME);
25
+ function globalInstallRoot() {
26
+ return os.homedir();
27
+ }
28
+ function cacheRoot() {
29
+ return path.join(os.homedir(), ".cache", DEFAULT_PLUGIN_NAME);
30
+ }
27
31
  var CLI_INVOKE_COMMAND = "npx agents-inc";
28
32
  var EDITOR_URL = "https://agentsinc.sh";
29
33
  function editorConfigUrl(id) {
@@ -42,8 +46,7 @@ var DIRS = {
42
46
  agents: "src/agents",
43
47
  skills: SKILLS_DIR_PATH,
44
48
  stacks: "src/stacks",
45
- templates: "src/agents/_templates",
46
- commands: "src/commands"
49
+ templates: "src/agents/_templates"
47
50
  };
48
51
  var METADATA_YAML_FILE = "metadata.yaml";
49
52
  var STANDARD_FILES = {
@@ -74,7 +77,6 @@ var STANDARD_DIRS = {
74
77
  SCRIPTS: "scripts",
75
78
  SKILLS: "skills",
76
79
  AGENTS: "agents",
77
- COMMANDS: "commands",
78
80
  /** Legacy per-project template override directory (`.claude/templates`). */
79
81
  TEMPLATES: "templates"
80
82
  };
@@ -212,8 +214,8 @@ export {
212
214
  PLUGINS_DIST_PATH,
213
215
  marketplaceManifestPath,
214
216
  DEFAULT_PLUGIN_NAME,
215
- GLOBAL_INSTALL_ROOT,
216
- CACHE_DIR,
217
+ globalInstallRoot,
218
+ cacheRoot,
217
219
  CLI_INVOKE_COMMAND,
218
220
  EDITOR_URL,
219
221
  editorConfigUrl,
@@ -260,4 +262,4 @@ export {
260
262
  FALLBACK_DOMAIN,
261
263
  ASCII_LOGO
262
264
  };
263
- //# sourceMappingURL=chunk-IO5YBKHV.js.map
265
+ //# sourceMappingURL=chunk-G6G2FT2G.js.map