agents-inc 0.164.0 → 0.165.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 (191) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +8 -9
  3. package/dist/{chunk-B6FSLXYN.js → chunk-42TNV2TK.js} +3 -3
  4. package/dist/chunk-4AAOOAIN.js +49 -0
  5. package/dist/chunk-4AAOOAIN.js.map +1 -0
  6. package/dist/{chunk-NQXO4LR3.js → chunk-4C7GL4F7.js} +16 -11
  7. package/dist/chunk-4C7GL4F7.js.map +1 -0
  8. package/dist/{chunk-Q4IRRVXK.js → chunk-57KU6SPH.js} +3 -3
  9. package/dist/{chunk-S63LXWMC.js → chunk-5M3PQNXI.js} +2 -2
  10. package/dist/{chunk-3WVH2CTK.js → chunk-5P26XBZO.js} +15 -8
  11. package/dist/chunk-5P26XBZO.js.map +1 -0
  12. package/dist/{chunk-G2JJ5BO5.js → chunk-6AIZPSEI.js} +337 -140
  13. package/dist/chunk-6AIZPSEI.js.map +1 -0
  14. package/dist/{chunk-NKGYKOB7.js → chunk-6CY6PW5X.js} +7 -8
  15. package/dist/chunk-6CY6PW5X.js.map +1 -0
  16. package/dist/{chunk-XHPWTL4I.js → chunk-6SW6SB7H.js} +3 -3
  17. package/dist/chunk-AAWZED5M.js +980 -0
  18. package/dist/chunk-AAWZED5M.js.map +1 -0
  19. package/dist/{chunk-UITEKY2R.js → chunk-AQXKAPCD.js} +30 -4
  20. package/dist/chunk-AQXKAPCD.js.map +1 -0
  21. package/dist/{chunk-X4SSJZLY.js → chunk-B5UUHBAM.js} +12 -261
  22. package/dist/chunk-B5UUHBAM.js.map +1 -0
  23. package/dist/{chunk-ARYNOWKF.js → chunk-BGU25XAY.js} +8 -8
  24. package/dist/{chunk-QGUP3QJF.js → chunk-CBMAO6OP.js} +22 -18
  25. package/dist/{chunk-QGUP3QJF.js.map → chunk-CBMAO6OP.js.map} +1 -1
  26. package/dist/{chunk-YRS3QZP2.js → chunk-CEBDGZID.js} +3 -3
  27. package/dist/{chunk-ABAZMMG4.js → chunk-CK5RM3DJ.js} +2 -2
  28. package/dist/{chunk-PHCPUQVR.js → chunk-CTUJO23Z.js} +2 -2
  29. package/dist/{chunk-QZX7SYKU.js → chunk-E6CHHXGY.js} +2 -2
  30. package/dist/{chunk-ZVXGW2IC.js → chunk-F2ZWFWTP.js} +4 -6
  31. package/dist/chunk-F2ZWFWTP.js.map +1 -0
  32. package/dist/{chunk-AVK2HEKB.js → chunk-GKPW33FP.js} +2 -6
  33. package/dist/{chunk-AVK2HEKB.js.map → chunk-GKPW33FP.js.map} +1 -1
  34. package/dist/{chunk-ECURHW3T.js → chunk-HR4YDSJK.js} +13 -12
  35. package/dist/chunk-HR4YDSJK.js.map +1 -0
  36. package/dist/{chunk-XPDVAJDH.js → chunk-IM45LLQX.js} +3599 -1558
  37. package/dist/chunk-IM45LLQX.js.map +1 -0
  38. package/dist/chunk-IVNKU4DM.js +39 -0
  39. package/dist/chunk-IVNKU4DM.js.map +1 -0
  40. package/dist/{chunk-XVAQG2CV.js → chunk-JOEA52NR.js} +10 -8
  41. package/dist/chunk-JOEA52NR.js.map +1 -0
  42. package/dist/{chunk-RGYDFBCT.js → chunk-JV4TKXEN.js} +5 -5
  43. package/dist/{chunk-4VL3CEOS.js → chunk-LXXGZAD3.js} +3 -3
  44. package/dist/chunk-MBUGQI2M.js +73 -0
  45. package/dist/chunk-MBUGQI2M.js.map +1 -0
  46. package/dist/{chunk-URXIQE7I.js → chunk-MWDY76MT.js} +2 -2
  47. package/dist/{chunk-V5GLL2JB.js → chunk-P3KJCYSR.js} +7 -7
  48. package/dist/{chunk-6MV4JOCL.js → chunk-PSX7CT6V.js} +2 -2
  49. package/dist/{chunk-B3Y3QMWI.js → chunk-TRTVOVHR.js} +4 -4
  50. package/dist/{chunk-AOTCIUGX.js → chunk-TV5Y53R2.js} +2 -2
  51. package/dist/{chunk-K5ITEA3I.js → chunk-UBSSIIWD.js} +34 -17
  52. package/dist/chunk-UBSSIIWD.js.map +1 -0
  53. package/dist/chunk-UCORXS4D.js +250 -0
  54. package/dist/chunk-UCORXS4D.js.map +1 -0
  55. package/dist/chunk-UR3RRTPO.js +159 -0
  56. package/dist/chunk-UR3RRTPO.js.map +1 -0
  57. package/dist/chunk-V5CWACR5.js +375 -0
  58. package/dist/chunk-V5CWACR5.js.map +1 -0
  59. package/dist/{chunk-LT5GXEB2.js → chunk-VPJUCVU7.js} +8 -7
  60. package/dist/chunk-VPJUCVU7.js.map +1 -0
  61. package/dist/chunk-VRXX4D6K.js +31 -0
  62. package/dist/chunk-VRXX4D6K.js.map +1 -0
  63. package/dist/{chunk-2CQNPLVF.js → chunk-WIFIAQZU.js} +63 -42
  64. package/dist/chunk-WIFIAQZU.js.map +1 -0
  65. package/dist/chunk-WSGX4IWC.js +356 -0
  66. package/dist/chunk-WSGX4IWC.js.map +1 -0
  67. package/dist/{chunk-X37UYIE3.js → chunk-WTANOSXK.js} +436 -739
  68. package/dist/chunk-WTANOSXK.js.map +1 -0
  69. package/dist/{chunk-XATLUKXK.js → chunk-X2KUI7V3.js} +6 -6
  70. package/dist/{chunk-NTF4UXGK.js → chunk-XATIKM3P.js} +73 -30
  71. package/dist/chunk-XATIKM3P.js.map +1 -0
  72. package/dist/{chunk-J27W6TXS.js → chunk-XQHZPINL.js} +8 -4
  73. package/dist/chunk-XQHZPINL.js.map +1 -0
  74. package/dist/{chunk-DSL66I4N.js → chunk-Y5SNGMB7.js} +6 -6
  75. package/dist/{chunk-7REKOTKG.js → chunk-YNOOZFIB.js} +3 -3
  76. package/dist/commands/build/marketplace.js +17 -17
  77. package/dist/commands/build/marketplace.js.map +1 -1
  78. package/dist/commands/build/plugins.js +11 -9
  79. package/dist/commands/build/plugins.js.map +1 -1
  80. package/dist/commands/compile.js +106 -27
  81. package/dist/commands/compile.js.map +1 -1
  82. package/dist/commands/doctor.js +427 -192
  83. package/dist/commands/doctor.js.map +1 -1
  84. package/dist/commands/edit.js +504 -314
  85. package/dist/commands/edit.js.map +1 -1
  86. package/dist/commands/eject.js +41 -23
  87. package/dist/commands/eject.js.map +1 -1
  88. package/dist/commands/init.js +44 -40
  89. package/dist/commands/list.js +44 -10
  90. package/dist/commands/list.js.map +1 -1
  91. package/dist/commands/new/marketplace.js +13 -10
  92. package/dist/commands/new/marketplace.js.map +1 -1
  93. package/dist/commands/search.js +12 -10
  94. package/dist/commands/search.js.map +1 -1
  95. package/dist/commands/share.js +103 -15
  96. package/dist/commands/share.js.map +1 -1
  97. package/dist/commands/uninstall.js +264 -106
  98. package/dist/commands/uninstall.js.map +1 -1
  99. package/dist/commands/update.js +50 -20
  100. package/dist/commands/update.js.map +1 -1
  101. package/dist/components/common/prompt-confirm.js +1 -1
  102. package/dist/components/common/removal-plan-confirm.js +2 -2
  103. package/dist/components/common/select-list.js +3 -3
  104. package/dist/components/common/spinner.js +6 -3
  105. package/dist/components/wizard/category-grid.js +5 -5
  106. package/dist/components/wizard/checkbox-grid.js +4 -4
  107. package/dist/components/wizard/domain-selection.js +9 -9
  108. package/dist/components/wizard/run-wizard-session.js +29 -29
  109. package/dist/components/wizard/scroll-affordance.js +2 -2
  110. package/dist/components/wizard/skill-agent-summary.js +5 -5
  111. package/dist/components/wizard/source-grid.js +6 -6
  112. package/dist/components/wizard/stack-selection.js +8 -8
  113. package/dist/components/wizard/step-agents.js +8 -8
  114. package/dist/components/wizard/step-build.js +8 -8
  115. package/dist/components/wizard/step-confirm.js +9 -9
  116. package/dist/components/wizard/step-sources.js +9 -9
  117. package/dist/components/wizard/step-stack.js +9 -9
  118. package/dist/components/wizard/summary-panel.js +8 -8
  119. package/dist/components/wizard/toast.js +2 -2
  120. package/dist/components/wizard/wizard-layout.js +12 -12
  121. package/dist/components/wizard/wizard-tabs.js +2 -2
  122. package/dist/components/wizard/wizard.js +27 -27
  123. package/dist/hooks/init.js +59 -43
  124. package/dist/hooks/init.js.map +1 -1
  125. package/dist/load-agent-defs-JHLE6MAE.js +14 -0
  126. package/dist/recompile-project-agents-ZPP5NOLZ.js +18 -0
  127. package/dist/{source-loader-GRBVNRAW.js → source-loader-RWZAYJ7E.js} +6 -4
  128. package/dist/src/agents/_templates/agent-body.liquid +55 -0
  129. package/dist/src/agents/_templates/agent.liquid +1 -55
  130. package/dist/src/agents/meta/agent-summoner/output.md +1 -1
  131. package/dist/src/agents/meta/agent-summoner/playbook.md +15 -7
  132. package/dist/stores/wizard-store.js +4 -4
  133. package/package.json +10 -9
  134. package/src/agents/_templates/agent-body.liquid +55 -0
  135. package/src/agents/_templates/agent.liquid +1 -55
  136. package/src/agents/meta/agent-summoner/output.md +1 -1
  137. package/src/agents/meta/agent-summoner/playbook.md +15 -7
  138. package/src/schemas/project-config.schema.json +1 -1
  139. package/src/schemas/project-source-config.schema.json +1 -1
  140. package/dist/chunk-2CQNPLVF.js.map +0 -1
  141. package/dist/chunk-3WVH2CTK.js.map +0 -1
  142. package/dist/chunk-7ANJQLPJ.js +0 -35
  143. package/dist/chunk-7ANJQLPJ.js.map +0 -1
  144. package/dist/chunk-ECURHW3T.js.map +0 -1
  145. package/dist/chunk-FLW25ORT.js +0 -130
  146. package/dist/chunk-FLW25ORT.js.map +0 -1
  147. package/dist/chunk-G2JJ5BO5.js.map +0 -1
  148. package/dist/chunk-J27W6TXS.js.map +0 -1
  149. package/dist/chunk-JCPANDNR.js +0 -35
  150. package/dist/chunk-JCPANDNR.js.map +0 -1
  151. package/dist/chunk-JIERYE6B.js +0 -480
  152. package/dist/chunk-JIERYE6B.js.map +0 -1
  153. package/dist/chunk-JU4ZGJ7A.js +0 -668
  154. package/dist/chunk-JU4ZGJ7A.js.map +0 -1
  155. package/dist/chunk-K5ITEA3I.js.map +0 -1
  156. package/dist/chunk-LT5GXEB2.js.map +0 -1
  157. package/dist/chunk-NKGYKOB7.js.map +0 -1
  158. package/dist/chunk-NQXO4LR3.js.map +0 -1
  159. package/dist/chunk-NTF4UXGK.js.map +0 -1
  160. package/dist/chunk-UITEKY2R.js.map +0 -1
  161. package/dist/chunk-X37UYIE3.js.map +0 -1
  162. package/dist/chunk-X4SSJZLY.js.map +0 -1
  163. package/dist/chunk-XPDVAJDH.js.map +0 -1
  164. package/dist/chunk-XVAQG2CV.js.map +0 -1
  165. package/dist/chunk-ZBPEFQ4G.js +0 -12
  166. package/dist/chunk-ZBPEFQ4G.js.map +0 -1
  167. package/dist/chunk-ZVXGW2IC.js.map +0 -1
  168. package/dist/load-agent-defs-7IM3GBEQ.js +0 -13
  169. package/dist/recompile-project-agents-VR4NLGOU.js +0 -17
  170. /package/dist/{chunk-B6FSLXYN.js.map → chunk-42TNV2TK.js.map} +0 -0
  171. /package/dist/{chunk-Q4IRRVXK.js.map → chunk-57KU6SPH.js.map} +0 -0
  172. /package/dist/{chunk-S63LXWMC.js.map → chunk-5M3PQNXI.js.map} +0 -0
  173. /package/dist/{chunk-XHPWTL4I.js.map → chunk-6SW6SB7H.js.map} +0 -0
  174. /package/dist/{chunk-ARYNOWKF.js.map → chunk-BGU25XAY.js.map} +0 -0
  175. /package/dist/{chunk-YRS3QZP2.js.map → chunk-CEBDGZID.js.map} +0 -0
  176. /package/dist/{chunk-ABAZMMG4.js.map → chunk-CK5RM3DJ.js.map} +0 -0
  177. /package/dist/{chunk-PHCPUQVR.js.map → chunk-CTUJO23Z.js.map} +0 -0
  178. /package/dist/{chunk-QZX7SYKU.js.map → chunk-E6CHHXGY.js.map} +0 -0
  179. /package/dist/{chunk-RGYDFBCT.js.map → chunk-JV4TKXEN.js.map} +0 -0
  180. /package/dist/{chunk-4VL3CEOS.js.map → chunk-LXXGZAD3.js.map} +0 -0
  181. /package/dist/{chunk-URXIQE7I.js.map → chunk-MWDY76MT.js.map} +0 -0
  182. /package/dist/{chunk-V5GLL2JB.js.map → chunk-P3KJCYSR.js.map} +0 -0
  183. /package/dist/{chunk-6MV4JOCL.js.map → chunk-PSX7CT6V.js.map} +0 -0
  184. /package/dist/{chunk-B3Y3QMWI.js.map → chunk-TRTVOVHR.js.map} +0 -0
  185. /package/dist/{chunk-AOTCIUGX.js.map → chunk-TV5Y53R2.js.map} +0 -0
  186. /package/dist/{chunk-XATLUKXK.js.map → chunk-X2KUI7V3.js.map} +0 -0
  187. /package/dist/{chunk-DSL66I4N.js.map → chunk-Y5SNGMB7.js.map} +0 -0
  188. /package/dist/{chunk-7REKOTKG.js.map → chunk-YNOOZFIB.js.map} +0 -0
  189. /package/dist/{load-agent-defs-7IM3GBEQ.js.map → load-agent-defs-JHLE6MAE.js.map} +0 -0
  190. /package/dist/{recompile-project-agents-VR4NLGOU.js.map → recompile-project-agents-ZPP5NOLZ.js.map} +0 -0
  191. /package/dist/{source-loader-GRBVNRAW.js.map → source-loader-RWZAYJ7E.js.map} +0 -0
@@ -1,52 +1,60 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  RemovalPlanConfirm
4
- } from "../chunk-ZVXGW2IC.js";
5
- import "../chunk-OZXAJNLA.js";
4
+ } from "../chunk-F2ZWFWTP.js";
6
5
  import {
7
6
  promptConfirm
8
- } from "../chunk-JCPANDNR.js";
7
+ } from "../chunk-4AAOOAIN.js";
8
+ import "../chunk-OZXAJNLA.js";
9
9
  import {
10
10
  lazyGateDeps,
11
11
  mutateGlobal,
12
12
  propagateGlobalRemoval
13
- } from "../chunk-X37UYIE3.js";
14
- import "../chunk-2CQNPLVF.js";
13
+ } from "../chunk-WTANOSXK.js";
14
+ import "../chunk-WIFIAQZU.js";
15
15
  import {
16
16
  loadAgentDefs
17
- } from "../chunk-B6FSLXYN.js";
17
+ } from "../chunk-42TNV2TK.js";
18
+ import "../chunk-UR3RRTPO.js";
18
19
  import {
19
- listAgentMdFiles,
20
+ listAgentFilesOf,
20
21
  splitAgentsByProvenance
21
- } from "../chunk-JU4ZGJ7A.js";
22
+ } from "../chunk-V5CWACR5.js";
22
23
  import "../chunk-JFLVEFFP.js";
24
+ import {
25
+ providerFlag,
26
+ providerNamedBy,
27
+ refuseAnAmbiguousInstallation
28
+ } from "../chunk-MBUGQI2M.js";
23
29
  import {
24
30
  BaseCommand,
25
31
  EXIT_CODES
26
- } from "../chunk-JIERYE6B.js";
27
- import "../chunk-NKGYKOB7.js";
28
- import "../chunk-PHCPUQVR.js";
32
+ } from "../chunk-AAWZED5M.js";
33
+ import "../chunk-6CY6PW5X.js";
34
+ import "../chunk-CTUJO23Z.js";
29
35
  import {
30
36
  ConfigLoadError,
31
37
  INFO_MESSAGES,
32
38
  SUCCESS_MESSAGES,
33
39
  UNINSTALL_PLAN,
40
+ agentCodec,
34
41
  buildMarketplacePluginRef,
35
- claudePluginUninstallBestEffort,
36
42
  compiledAgentsRemoval,
37
43
  directoryExists,
38
44
  fileExists,
39
45
  getErrorMessage,
40
46
  getProjectPluginsDir,
41
- isClaudeCLIAvailable,
47
+ hostAt,
42
48
  isHomeDirectory,
43
49
  listDirectories,
44
50
  listPluginNames,
45
- loadProjectConfigFromDir,
51
+ loadProjectConfigAt,
46
52
  loadSkillsMatrixFromSource,
47
53
  localSkillsRemoval,
48
54
  notInstalledHere,
49
55
  parseMarketplacePluginRef,
56
+ plannedSourceFolderMove,
57
+ providerInUse,
50
58
  readForkedFromMetadata,
51
59
  registeredProjectUpdateSkipped,
52
60
  registeredProjectsUpdateFailed,
@@ -54,22 +62,24 @@ import {
54
62
  remove,
55
63
  removeDirIfEmpty,
56
64
  resolveInstallPaths,
57
- toClaudePluginScope,
65
+ sourceFolderInUse,
66
+ sourceRootOf,
67
+ uninstallConfigUnreadable,
68
+ uninstallNeedsTerminal,
58
69
  unmarkedAgentsKept
59
- } from "../chunk-XPDVAJDH.js";
60
- import "../chunk-AVK2HEKB.js";
70
+ } from "../chunk-IM45LLQX.js";
71
+ import "../chunk-GKPW33FP.js";
61
72
  import {
62
73
  CLAUDE_DIR,
63
- CLAUDE_SRC_DIR,
64
74
  DEFAULT_BRANDING,
65
75
  EJECT_SOURCE,
66
76
  STANDARD_FILES
67
- } from "../chunk-UITEKY2R.js";
77
+ } from "../chunk-AQXKAPCD.js";
68
78
  import "../chunk-OI2H6M5I.js";
69
79
 
70
80
  // src/cli/commands/uninstall.tsx
71
81
  import "react";
72
- import { partition } from "remeda";
82
+ import { partition, unique } from "remeda";
73
83
  import path from "path";
74
84
  import { Flags } from "@oclif/core";
75
85
  import { jsx } from "react/jsx-runtime";
@@ -80,7 +90,7 @@ function buildRemovalPlan(target) {
80
90
  ...pluginsEntry(target),
81
91
  ...localSkillsEntry(target),
82
92
  ...agents,
83
- ...configManifestEntry(target)
93
+ ...configManifestEntries(target)
84
94
  ],
85
95
  kept: keptStatements(target, agents)
86
96
  };
@@ -100,19 +110,14 @@ function compiledAgentsEntry(target) {
100
110
  if (!target.hasLocalAgents) return [];
101
111
  const agentNames = identifiableAgents(target);
102
112
  if (agentNames.length === 0) return [];
103
- return [{ kind: "agents", agentsDir: target.agentsDir, agentNames }];
113
+ return [{ kind: "agents", agentsDir: target.agentsDir, agentNames, codec: target.agentCodec }];
104
114
  }
105
115
  function identifiableAgents(target) {
106
116
  if (target.configuredAgents.length > 0) return target.configuredAgents;
107
117
  return target.markedAgents;
108
118
  }
109
- function configManifestEntry(target) {
110
- const fileNames = [
111
- ...target.hasClaudeSrcConfig ? [STANDARD_FILES.CONFIG_TS] : [],
112
- ...target.hasClaudeSrcConfigTypes ? [STANDARD_FILES.CONFIG_TYPES_TS] : []
113
- ];
114
- if (fileNames.length === 0) return [];
115
- return [{ kind: "config", claudeSrcDir: target.claudeSrcDir, fileNames }];
119
+ function configManifestEntries(target) {
120
+ return target.sourceFolders.filter((folder) => folder.manifestFiles.length > 0).map((folder) => ({ kind: "config", sourceDir: folder.dir, fileNames: folder.manifestFiles }));
116
121
  }
117
122
  function keptStatements(target, agentRemovals) {
118
123
  const removing = new Set(agentRemovals.flatMap((entry) => entry.agentNames));
@@ -120,6 +125,11 @@ function keptStatements(target, agentRemovals) {
120
125
  if (kept.length === 0) return [];
121
126
  return [unmarkedAgentsKept(target.agentsDir, kept.length)];
122
127
  }
128
+ function planEntries(plan, kind) {
129
+ return plan.entries.filter(
130
+ (entry) => entry.kind === kind
131
+ );
132
+ }
123
133
  function planEntry(plan, kind) {
124
134
  return plan.entries.find(
125
135
  (entry) => entry.kind === kind
@@ -142,7 +152,7 @@ function describeEntry(entry) {
142
152
  case "config":
143
153
  return {
144
154
  label: UNINSTALL_PLAN.CONFIG_HEADING,
145
- items: entry.fileNames.map((fileName) => `${entry.claudeSrcDir}/${fileName}`)
155
+ items: entry.fileNames.map((fileName) => `${entry.sourceDir}/${fileName}`)
146
156
  };
147
157
  default: {
148
158
  const _exhaustive = entry;
@@ -183,7 +193,7 @@ var Uninstall = class _Uninstall extends BaseCommand {
183
193
  */
184
194
  brandingName = DEFAULT_BRANDING.NAME;
185
195
  static summary = `Remove ${DEFAULT_BRANDING.NAME} from this project`;
186
- static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by marketplace), compiled agents, plugins, and the .claude-src/ config manifest (config.ts + config-types.ts). User-created content is preserved.`;
196
+ static description = `Uninstall ${DEFAULT_BRANDING.NAME} from this project. Removes CLI-managed skills (matched by marketplace), compiled agents, plugins, and the config manifest (config.ts + config-types.ts) this project keeps. User-created content is preserved.`;
187
197
  static examples = [
188
198
  "<%= config.bin %> <%= command.id %>",
189
199
  "<%= config.bin %> <%= command.id %> --yes"
@@ -193,18 +203,30 @@ var Uninstall = class _Uninstall extends BaseCommand {
193
203
  char: "y",
194
204
  description: "Skip confirmation prompt",
195
205
  default: false
196
- })
206
+ }),
207
+ provider: providerFlag()
197
208
  };
209
+ /**
210
+ * Starts at any terminal size. The size gate exists for the wizard's layout, and this command
211
+ * draws none — a plan and a one-line confirm fit any terminal — while it is the way out of every
212
+ * state, so a window too small to hold a wizard must not hold up an uninstall.
213
+ */
214
+ async ensureTerminalSize() {
215
+ }
198
216
  async run() {
199
217
  const { flags } = await this.parse(_Uninstall);
200
218
  const projectDir = process.cwd();
219
+ await refuseAnAmbiguousInstallation(
220
+ projectDir,
221
+ "uninstall",
222
+ providerNamedBy(flags.provider),
223
+ (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS })
224
+ );
201
225
  this.brandingName = await this.resolveBrandingName(projectDir);
202
226
  this.printHeader();
203
227
  const target = await detectUninstallTarget(
204
228
  projectDir,
205
- (reason) => this.warn(
206
- `Could not read the project config \u2014 plugins and compiled agents it lists may be left behind: ${reason}`
207
- )
229
+ (failure) => this.warn(uninstallConfigUnreadable(failure))
208
230
  );
209
231
  const plan = buildRemovalPlan(target);
210
232
  if (!hasAnythingToRemove(plan)) {
@@ -249,6 +271,9 @@ var Uninstall = class _Uninstall extends BaseCommand {
249
271
  return true;
250
272
  }
251
273
  async confirmRemoval(plan) {
274
+ if (!process.stdin.isTTY) {
275
+ this.error(uninstallNeedsTerminal(), { exit: EXIT_CODES.ERROR });
276
+ }
252
277
  const outcome = await promptConfirm(({ onConfirm, onCancel }) => /* @__PURE__ */ jsx(
253
278
  RemovalPlanConfirm,
254
279
  {
@@ -289,7 +314,7 @@ var Uninstall = class _Uninstall extends BaseCommand {
289
314
  /**
290
315
  * Loads what updating registered projects needs (global config with its
291
316
  * projects[] registry, skills matrix, agent definitions) BEFORE the global
292
- * .claude-src manifest is deleted — source resolution reads that config.
317
+ * the config manifest is deleted — source resolution reads that config.
293
318
  * Returns null when nothing is registered or loading fails; a load failure
294
319
  * warns and never aborts the uninstall.
295
320
  *
@@ -302,20 +327,30 @@ var Uninstall = class _Uninstall extends BaseCommand {
302
327
  * local-installer.test.ts). Skipping avoids fetching every registered extra
303
328
  * source (network on a cold cache, plus unreachable-remote warnings) during
304
329
  * an uninstall that must never hang or noise-fail on remote state.
330
+ *
331
+ * `purpose: "upkeep"` because the prune only rewrites projects that are already installed: a
332
+ * marketplace that has since lost its manifest must not leave every registered project naming
333
+ * the global content this uninstall deletes.
305
334
  */
306
335
  async prepareGlobalPropagation(target, projectDir) {
307
- const globalConfig = target.config;
308
- if (!globalConfig?.projects?.length) return null;
336
+ if (target.config === null || target.registeredProjects.length === 0) return null;
337
+ const globalConfig = { ...target.config, projects: target.registeredProjects };
309
338
  try {
310
339
  const [sourceResult, agentDefs] = await Promise.all([
311
340
  loadSkillsMatrixFromSource({
312
341
  projectDir,
342
+ purpose: "upkeep",
313
343
  skipExtraSources: true,
314
344
  matrixOnly: true
315
345
  }),
316
346
  loadAgentDefs()
317
347
  ]);
318
- return { globalConfig, matrix: sourceResult.matrix, agents: agentDefs.agents };
348
+ return {
349
+ globalConfig,
350
+ matrix: sourceResult.matrix,
351
+ agents: agentDefs.agents,
352
+ provider: providerInUse(projectDir)
353
+ };
319
354
  } catch (error) {
320
355
  this.warn(registeredProjectsUpdateFailed(getErrorMessage(error)));
321
356
  return null;
@@ -331,15 +366,18 @@ var Uninstall = class _Uninstall extends BaseCommand {
331
366
  */
332
367
  async updateRegisteredProjects(propagation) {
333
368
  try {
334
- const report = await propagateGlobalRemoval(propagation.globalConfig, {
335
- matrix: propagation.matrix,
336
- agents: propagation.agents
337
- });
338
- for (const skippedPath of report.propagated.skipped) {
369
+ const report = await propagateGlobalRemoval(
370
+ propagation.globalConfig,
371
+ { matrix: propagation.matrix, agents: propagation.agents },
372
+ propagation.provider
373
+ );
374
+ const { updated, unreadable, failed } = report.propagated;
375
+ this.reportProjectsOutOfReach(report.propagated);
376
+ for (const skippedPath of [...unreadable, ...failed]) {
339
377
  this.warn(registeredProjectUpdateSkipped(skippedPath));
340
378
  }
341
- if (report.propagated.updated.length === 0) return;
342
- this.logSuccess(registeredProjectsUpdated(report.propagated.updated.length));
379
+ if (updated.length === 0) return;
380
+ this.logSuccess(registeredProjectsUpdated(updated.length));
343
381
  this.reportPropagatedRecompile(report);
344
382
  } catch (error) {
345
383
  this.warn(registeredProjectsUpdateFailed(getErrorMessage(error)));
@@ -362,18 +400,43 @@ var Uninstall = class _Uninstall extends BaseCommand {
362
400
  for (const statement of plan.kept) {
363
401
  this.log(statement);
364
402
  }
365
- const cleanup = await cleanupEmptyDirs(target, planEntry(plan, "config"));
366
- if (cleanup.claudeSrcDirRemoved) {
367
- this.logSuccess(`Removed ${CLAUDE_SRC_DIR}/`);
368
- } else if (cleanup.claudeSrcManifestRemoved) {
369
- this.logSuccess(`Removed CLI config from ${CLAUDE_SRC_DIR}/`);
403
+ const cleanup = await cleanupEmptyDirs(target, planEntries(plan, "config"));
404
+ for (const folder of cleanup.sourceFolders) {
405
+ this.reportSourceFolderCleanup(folder);
370
406
  }
407
+ this.reportSourceRootCleanup(target.sourceRoot, cleanup);
371
408
  if (cleanup.claudeDirRemoved) {
372
409
  this.logSuccess(`Removed ${CLAUDE_DIR}/`);
373
410
  } else if (cleanup.claudeDirKept) {
374
411
  this.log(`Kept ${CLAUDE_DIR}/ (contains user content)`);
375
412
  }
376
413
  }
414
+ /** What became of one source folder: gone, emptied of the CLI's files, or kept for the user's. */
415
+ reportSourceFolderCleanup(folder) {
416
+ if (folder.dirRemoved) {
417
+ this.logSuccess(`Removed ${folder.relName}/`);
418
+ } else if (folder.manifestRemoved) {
419
+ this.logSuccess(`Removed CLI config from ${folder.relName}/`);
420
+ } else if (folder.kept) {
421
+ this.log(`Kept ${folder.relName}/ (contains user content)`);
422
+ }
423
+ }
424
+ /**
425
+ * What became of the `.agents-inc/` parent, said out loud in both directions.
426
+ *
427
+ * A scope still on the legacy name has no such parent and gets no line — the folder it kept or
428
+ * lost was reported one statement above this one.
429
+ */
430
+ reportSourceRootCleanup(sourceRoot, cleanup) {
431
+ if (sourceRoot === null) return;
432
+ if (cleanup.sourceRootRemoved) {
433
+ this.logSuccess(`Removed ${sourceRoot.relName}/`);
434
+ return;
435
+ }
436
+ if (cleanup.sourceRootKept) {
437
+ this.log(`Kept ${sourceRoot.relName}/ (contains user content)`);
438
+ }
439
+ }
377
440
  async removePlannedPlugins(entry, config, projectDir) {
378
441
  if (!entry) return;
379
442
  this.log("Uninstalling plugins...");
@@ -384,9 +447,11 @@ var Uninstall = class _Uninstall extends BaseCommand {
384
447
  projectDir,
385
448
  (name) => this.log(` Uninstalled plugin '${name}'`)
386
449
  );
387
- this.logSuccess(
388
- `Uninstalled ${pluginResult.totalUninstalled} ${pluginResult.totalUninstalled === 1 ? "plugin" : "plugins"}`
389
- );
450
+ if (pluginResult.totalUninstalled > 0) {
451
+ this.logSuccess(
452
+ `Uninstalled ${pluginResult.totalUninstalled} ${pluginResult.totalUninstalled === 1 ? "plugin" : "plugins"}`
453
+ );
454
+ }
390
455
  } catch (error) {
391
456
  this.log("Plugin uninstall failed");
392
457
  this.error(getErrorMessage(error), {
@@ -435,53 +500,86 @@ function getCliInstalledPluginKeys(config) {
435
500
  ])
436
501
  );
437
502
  }
438
- async function loadUninstallConfig(projectDir, onLoadFailed) {
503
+ async function loadUninstallConfig(configPath, projectDir, provider, onLoadFailed) {
439
504
  try {
440
- const result = await loadProjectConfigFromDir(projectDir);
505
+ const result = await loadProjectConfigAt(configPath, projectDir, provider);
441
506
  return result?.config ?? null;
442
507
  } catch (error) {
443
508
  if (!(error instanceof ConfigLoadError)) throw error;
444
- onLoadFailed(getErrorMessage(error));
509
+ onLoadFailed(error);
445
510
  return null;
446
511
  }
447
512
  }
513
+ function sourceFoldersOf(projectDir, provider) {
514
+ const read = sourceFolderInUse(projectDir, provider);
515
+ const move = plannedSourceFolderMove(projectDir, provider);
516
+ if (!read.both || move === null) return [read];
517
+ const rival = read.legacy ? move.to : move.from;
518
+ return [read, { dir: rival.dir, relName: rival.relName, legacy: !read.legacy }];
519
+ }
520
+ async function readSourceFolder(folder, projectDir, provider, onConfigLoadFailed) {
521
+ const [manifestFiles, config] = await Promise.all([
522
+ manifestFilesIn(folder.dir),
523
+ loadUninstallConfig(
524
+ path.join(folder.dir, STANDARD_FILES.CONFIG_TS),
525
+ projectDir,
526
+ provider,
527
+ onConfigLoadFailed
528
+ )
529
+ ]);
530
+ return { ...folder, manifestFiles, config };
531
+ }
532
+ async function manifestFilesIn(dir) {
533
+ const manifest = [STANDARD_FILES.CONFIG_TS, STANDARD_FILES.CONFIG_TYPES_TS];
534
+ const present = await Promise.all(
535
+ manifest.map((fileName) => fileExists(path.join(dir, fileName)))
536
+ );
537
+ return manifest.filter((_, index) => present[index]);
538
+ }
539
+ function sourceRootFor(projectDir, provider, folders) {
540
+ const ofTheFolderBeingRead = sourceRootOf(projectDir, provider);
541
+ if (ofTheFolderBeingRead !== null) return ofTheFolderBeingRead;
542
+ const move = plannedSourceFolderMove(projectDir, provider);
543
+ const rivalOnTheNewName = folders.some((folder) => !folder.legacy);
544
+ return rivalOnTheNewName && move !== null ? move.parent : null;
545
+ }
546
+ function cliInstalledPluginKeysOf(config) {
547
+ return [...getCliInstalledPluginKeys(config)];
548
+ }
549
+ function activeConfigOf(config) {
550
+ return {
551
+ ...config,
552
+ skills: config.skills.filter((s) => !s.excluded),
553
+ agents: config.agents.filter((a) => !a.excluded)
554
+ };
555
+ }
448
556
  async function detectUninstallTarget(projectDir, onConfigLoadFailed) {
449
557
  const pluginsDir = getProjectPluginsDir(projectDir);
450
558
  const { skillsDir, agentsDir } = resolveInstallPaths(projectDir);
451
559
  const claudeDir = path.join(projectDir, CLAUDE_DIR);
452
- const claudeSrcDir = path.join(projectDir, CLAUDE_SRC_DIR);
453
- const claudeSrcConfigPath = path.join(claudeSrcDir, STANDARD_FILES.CONFIG_TS);
454
- const claudeSrcConfigTypesPath = path.join(claudeSrcDir, STANDARD_FILES.CONFIG_TYPES_TS);
455
- const [
456
- hasLocalSkills,
457
- hasLocalAgents,
458
- hasClaudeDir,
459
- hasClaudeSrcConfig,
460
- hasClaudeSrcConfigTypes,
461
- config,
462
- agentProvenance
463
- ] = await Promise.all([
560
+ const provider = providerInUse(projectDir);
561
+ const folders = sourceFoldersOf(projectDir, provider);
562
+ const sourceRoot = sourceRootFor(projectDir, provider, folders);
563
+ const [hasLocalSkills, hasLocalAgents, hasClaudeDir, sourceFolders, agentProvenance] = await Promise.all([
464
564
  directoryExists(skillsDir),
465
565
  directoryExists(agentsDir),
466
566
  directoryExists(claudeDir),
467
- fileExists(claudeSrcConfigPath),
468
- fileExists(claudeSrcConfigTypesPath),
469
- loadUninstallConfig(projectDir, onConfigLoadFailed),
470
- splitAgentsByProvenance(agentsDir)
567
+ Promise.all(
568
+ folders.map((folder) => readSourceFolder(folder, projectDir, provider, onConfigLoadFailed))
569
+ ),
570
+ splitAgentsByProvenance(agentsDir, agentCodec(provider))
471
571
  ]);
572
+ const readable = sourceFolders.flatMap((folder) => folder.config ? [folder.config] : []);
573
+ const config = readable[0] ?? null;
472
574
  let pluginNames = [];
473
575
  try {
474
576
  pluginNames = await listPluginNames(projectDir);
475
577
  } catch {
476
578
  }
477
- const activeConfig = config ? {
478
- ...config,
479
- skills: config.skills.filter((s) => !s.excluded),
480
- agents: config.agents.filter((a) => !a.excluded)
481
- } : null;
482
- const configuredAgents = collectConfiguredAgents(activeConfig);
483
- const cliInstalledKeys = getCliInstalledPluginKeys(activeConfig);
484
- const cliPluginNames = pluginNames.filter((name) => cliInstalledKeys.has(name));
579
+ const activeConfigs = readable.map(activeConfigOf);
580
+ const configuredAgents = unique(activeConfigs.flatMap(collectConfiguredAgents));
581
+ const cliInstalledKeys = new Set(activeConfigs.flatMap(cliInstalledPluginKeysOf));
582
+ const cliPluginNames = thisRunOwnsAnyPlugin(projectDir) ? pluginNames.filter((name) => cliInstalledKeys.has(name)) : [];
485
583
  return {
486
584
  hasPlugins: cliPluginNames.length > 0,
487
585
  pluginNames,
@@ -489,19 +587,24 @@ async function detectUninstallTarget(projectDir, onConfigLoadFailed) {
489
587
  hasLocalSkills,
490
588
  hasLocalAgents,
491
589
  hasClaudeDir,
492
- hasClaudeSrcConfig,
493
- hasClaudeSrcConfigTypes,
494
590
  pluginsDir,
495
591
  skillsDir,
496
592
  agentsDir,
497
593
  claudeDir,
498
- claudeSrcDir,
594
+ sourceFolders,
595
+ sourceRoot,
499
596
  config,
597
+ registeredProjects: unique(readable.flatMap((each) => each.projects ?? [])),
500
598
  configuredAgents,
599
+ agentCodec: agentCodec(provider),
501
600
  markedAgents: agentProvenance.marked,
502
601
  unmarkedAgents: agentProvenance.unmarked
503
602
  };
504
603
  }
604
+ function thisRunOwnsAnyPlugin(projectDir) {
605
+ if (isHomeDirectory(projectDir)) return true;
606
+ return hostAt(projectDir).installsProjectScopedPlugins;
607
+ }
505
608
  function shouldRemoveSkill(forkedFrom) {
506
609
  return forkedFrom !== null;
507
610
  }
@@ -545,10 +648,10 @@ async function cleanupSkillsDir(dir, allRemoved) {
545
648
  return removeDirIfEmpty(dir);
546
649
  }
547
650
  async function removeMatchingAgents(entry, onRemoved) {
548
- const agentFiles = await listAgentFiles(entry.agentsDir);
549
- const removedNames = agentFiles.map((agentFile) => agentFile.replace(/\.md$/, "")).filter((agentName) => entry.agentNames.includes(agentName));
651
+ const agentFiles = await listAgentFiles(entry.agentsDir, entry.codec);
652
+ const removedNames = agentFiles.map((agentFile) => path.basename(agentFile, entry.codec.extension)).filter((agentName) => entry.agentNames.includes(agentName));
550
653
  for (const agentName of removedNames) {
551
- await remove(path.join(entry.agentsDir, `${agentName}.md`));
654
+ await remove(path.join(entry.agentsDir, `${agentName}${entry.codec.extension}`));
552
655
  onRemoved?.(agentName);
553
656
  }
554
657
  const dirCleaned = await removeDirIfEmpty(entry.agentsDir);
@@ -558,45 +661,100 @@ async function removeMatchingAgents(entry, onRemoved) {
558
661
  dirCleaned
559
662
  };
560
663
  }
664
+ var SCOPE_OF_AN_UNRECORDED_SKILL = "project";
665
+ function pluginScopesToSweep(host, primary) {
666
+ const offered = host.offeredPlacements.filter((placement) => placement.mode === "plugin").map((placement) => placement.scope);
667
+ if (!offered.includes(primary)) return offered;
668
+ return [primary, ...offered.filter((scope) => scope !== primary)];
669
+ }
670
+ async function removePluginWhereverItIsFiled(host, pluginRef, primaryScope, projectDir) {
671
+ let outcome = "absent";
672
+ for (const scope of pluginScopesToSweep(host, primaryScope)) {
673
+ try {
674
+ const swept = await host.uninstallPlugin(pluginRef, scope, projectDir);
675
+ if (swept === "removed") outcome = "removed";
676
+ } catch {
677
+ }
678
+ }
679
+ return outcome;
680
+ }
561
681
  async function uninstallPlugins(entry, config, projectDir, onUninstalled) {
562
- const cliAvailable = await isClaudeCLIAvailable();
682
+ const host = hostAt(projectDir);
683
+ const hostAvailable = await host.isAvailable();
684
+ const observed = [];
563
685
  for (const pluginName of entry.names) {
564
- if (cliAvailable) {
565
- const skillId = parseMarketplacePluginRef(pluginName);
566
- const skillConfig = config?.skills.find((s) => s.id === skillId);
567
- const primaryScope = toClaudePluginScope(skillConfig?.scope);
568
- await claudePluginUninstallBestEffort(pluginName, primaryScope, projectDir);
686
+ const removal = hostAvailable ? await removePluginWhereverItIsFiled(
687
+ host,
688
+ pluginName,
689
+ scopeThePluginIsFiledUnder(config, pluginName),
690
+ projectDir
691
+ ) : nothingWasObserved();
692
+ await remove(path.join(entry.pluginsDir, pluginName));
693
+ if (removal === "removed") {
694
+ observed.push(pluginName);
695
+ onUninstalled?.(pluginName);
569
696
  }
570
- const pluginPath = path.join(entry.pluginsDir, pluginName);
571
- await remove(pluginPath);
572
- onUninstalled?.(pluginName);
573
697
  }
574
698
  return {
575
- uninstalledNames: entry.names,
576
- totalUninstalled: entry.names.length
699
+ uninstalledNames: observed,
700
+ totalUninstalled: observed.length
577
701
  };
578
702
  }
703
+ function scopeThePluginIsFiledUnder(config, pluginName) {
704
+ const skillId = parseMarketplacePluginRef(pluginName);
705
+ return config?.skills.find((skill) => skill.id === skillId)?.scope ?? SCOPE_OF_AN_UNRECORDED_SKILL;
706
+ }
707
+ function nothingWasObserved() {
708
+ return "absent";
709
+ }
579
710
  async function removeConfigManifest(entry) {
580
711
  if (!entry) return { manifestRemoved: false, dirRemoved: false };
581
712
  await Promise.all(
582
- entry.fileNames.map((fileName) => remove(path.join(entry.claudeSrcDir, fileName)))
713
+ entry.fileNames.map((fileName) => remove(path.join(entry.sourceDir, fileName)))
583
714
  );
584
- return { manifestRemoved: true, dirRemoved: await removeDirIfEmpty(entry.claudeSrcDir) };
715
+ return { manifestRemoved: true, dirRemoved: await removeDirIfEmpty(entry.sourceDir) };
585
716
  }
586
- async function cleanupEmptyDirs(target, manifestEntry) {
587
- const manifest = await removeConfigManifest(manifestEntry);
717
+ async function cleanupEmptyDirs(target, manifestEntries) {
718
+ const sourceFolders = await Promise.all(
719
+ target.sourceFolders.map(
720
+ (folder) => cleanupSourceFolder(
721
+ folder,
722
+ manifestEntries.find((entry) => entry.sourceDir === folder.dir)
723
+ )
724
+ )
725
+ );
726
+ const providerDirRemoved = sourceFolders.some((folder) => !folder.legacy && folder.dirRemoved);
727
+ const sourceRoot = await cleanupSourceRoot(target.sourceRoot, providerDirRemoved);
588
728
  const claudeDirRemoved = target.hasClaudeDir && await removeDirIfEmpty(target.claudeDir);
589
729
  const claudeDirKept = !claudeDirRemoved && target.hasClaudeDir && await directoryExists(target.claudeDir);
590
730
  return {
591
731
  claudeDirRemoved,
592
- claudeSrcManifestRemoved: manifest.manifestRemoved,
593
- claudeSrcDirRemoved: manifest.dirRemoved,
732
+ sourceFolders,
733
+ sourceRootRemoved: sourceRoot.removed,
734
+ sourceRootKept: sourceRoot.kept,
594
735
  claudeDirKept
595
736
  };
596
737
  }
597
- async function listAgentFiles(agentsDir) {
738
+ async function cleanupSourceFolder(folder, entry) {
739
+ const manifest = await removeConfigManifest(entry);
740
+ const dirRemoved = manifest.dirRemoved || await removeDirIfEmpty(folder.dir);
741
+ const kept = !dirRemoved && await directoryExists(folder.dir);
742
+ return {
743
+ relName: folder.relName,
744
+ legacy: folder.legacy,
745
+ manifestRemoved: manifest.manifestRemoved,
746
+ dirRemoved,
747
+ kept
748
+ };
749
+ }
750
+ async function cleanupSourceRoot(sourceRoot, providerDirRemoved) {
751
+ if (sourceRoot === null || !providerDirRemoved) return { removed: false, kept: false };
752
+ const removed = await removeDirIfEmpty(sourceRoot.dir);
753
+ return { removed, kept: !removed && await directoryExists(sourceRoot.dir) };
754
+ }
755
+ async function listAgentFiles(agentsDir, codec) {
598
756
  try {
599
- return await listAgentMdFiles(agentsDir);
757
+ return await listAgentFilesOf(agentsDir, codec);
600
758
  } catch {
601
759
  return [];
602
760
  }