@curdx/flow 2.3.11 → 3.1.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 (210) hide show
  1. package/CHANGELOG.md +21 -34
  2. package/LICENSE +1 -1
  3. package/README.md +28 -79
  4. package/dist/index.mjs +995 -0
  5. package/package.json +33 -42
  6. package/.claude-plugin/marketplace.json +0 -48
  7. package/.claude-plugin/plugin.json +0 -70
  8. package/agent-preamble/preamble.md +0 -314
  9. package/agents/flow-adversary.md +0 -202
  10. package/agents/flow-architect.md +0 -197
  11. package/agents/flow-brownfield-analyst.md +0 -142
  12. package/agents/flow-debugger.md +0 -321
  13. package/agents/flow-edge-hunter.md +0 -288
  14. package/agents/flow-executor.md +0 -269
  15. package/agents/flow-orchestrator.md +0 -145
  16. package/agents/flow-planner.md +0 -246
  17. package/agents/flow-product-designer.md +0 -159
  18. package/agents/flow-qa-engineer.md +0 -282
  19. package/agents/flow-researcher.md +0 -165
  20. package/agents/flow-reviewer.md +0 -303
  21. package/agents/flow-security-auditor.md +0 -401
  22. package/agents/flow-triage-analyst.md +0 -272
  23. package/agents/flow-ui-researcher.md +0 -229
  24. package/agents/flow-ux-designer.md +0 -221
  25. package/agents/flow-verifier.md +0 -349
  26. package/bin/curdx-flow +0 -5
  27. package/bin/curdx-flow.js +0 -54
  28. package/cli/README.md +0 -104
  29. package/cli/doctor-workflow.js +0 -483
  30. package/cli/doctor.js +0 -73
  31. package/cli/help.js +0 -59
  32. package/cli/install-bundled-mcps.js +0 -37
  33. package/cli/install-companions.js +0 -19
  34. package/cli/install-context7-config.js +0 -80
  35. package/cli/install-curdx-plugin.js +0 -96
  36. package/cli/install-language.js +0 -35
  37. package/cli/install-next-steps.js +0 -29
  38. package/cli/install-options.js +0 -9
  39. package/cli/install-paths.js +0 -52
  40. package/cli/install-recommended-plugins.js +0 -104
  41. package/cli/install-required-plugins.js +0 -57
  42. package/cli/install-self-update.js +0 -62
  43. package/cli/install-workflow.js +0 -209
  44. package/cli/install.js +0 -101
  45. package/cli/lib/claude-commands.js +0 -41
  46. package/cli/lib/claude-ops.js +0 -47
  47. package/cli/lib/claude.js +0 -183
  48. package/cli/lib/config.js +0 -24
  49. package/cli/lib/doctor-claude-settings.js +0 -1186
  50. package/cli/lib/doctor-report.js +0 -978
  51. package/cli/lib/doctor-runtime-environment.js +0 -196
  52. package/cli/lib/frontmatter.js +0 -44
  53. package/cli/lib/json-schema.js +0 -57
  54. package/cli/lib/logging.js +0 -25
  55. package/cli/lib/process.js +0 -60
  56. package/cli/lib/prompts.js +0 -135
  57. package/cli/lib/runtime.js +0 -107
  58. package/cli/lib/semver.js +0 -109
  59. package/cli/lib/version.js +0 -12
  60. package/cli/protocols-body.md +0 -22
  61. package/cli/protocols.js +0 -162
  62. package/cli/registry.js +0 -123
  63. package/cli/router.js +0 -49
  64. package/cli/uninstall-actions.js +0 -360
  65. package/cli/uninstall-workflow.js +0 -146
  66. package/cli/uninstall.js +0 -42
  67. package/cli/upgrade-workflow.js +0 -80
  68. package/cli/upgrade.js +0 -91
  69. package/cli/utils.js +0 -40
  70. package/gates/adversarial-review-gate.md +0 -219
  71. package/gates/coverage-audit-gate.md +0 -182
  72. package/gates/devex-gate.md +0 -254
  73. package/gates/edge-case-gate.md +0 -194
  74. package/gates/karpathy-gate.md +0 -130
  75. package/gates/security-gate.md +0 -218
  76. package/gates/tdd-gate.md +0 -182
  77. package/gates/test-quality-gate.md +0 -59
  78. package/gates/verification-gate.md +0 -179
  79. package/hooks/hooks.json +0 -58
  80. package/hooks/scripts/common.sh +0 -46
  81. package/hooks/scripts/inject-karpathy.sh +0 -53
  82. package/hooks/scripts/quick-mode-guard.sh +0 -68
  83. package/hooks/scripts/session-start.sh +0 -90
  84. package/hooks/scripts/stop-watcher.sh +0 -230
  85. package/hooks/scripts/subagent-artifact-guard.sh +0 -159
  86. package/hooks/scripts/subagent-statusline.sh +0 -105
  87. package/knowledge/artifact-output-discipline.md +0 -24
  88. package/knowledge/artifact-summary-contracts.md +0 -50
  89. package/knowledge/atomic-commits.md +0 -262
  90. package/knowledge/claude-code-runtime-contracts.md +0 -219
  91. package/knowledge/epic-decomposition.md +0 -307
  92. package/knowledge/execution-strategies.md +0 -303
  93. package/knowledge/karpathy-guidelines.md +0 -219
  94. package/knowledge/planning-reviews.md +0 -211
  95. package/knowledge/poc-first-workflow.md +0 -223
  96. package/knowledge/review-feedback-intake.md +0 -57
  97. package/knowledge/spec-driven-development.md +0 -180
  98. package/knowledge/systematic-debugging.md +0 -378
  99. package/knowledge/two-stage-review.md +0 -249
  100. package/knowledge/wave-execution.md +0 -403
  101. package/monitors/monitors.json +0 -8
  102. package/monitors/scripts/flow-state-monitor.sh +0 -99
  103. package/output-styles/curdx-evidence-first.md +0 -34
  104. package/schemas/agent-frontmatter.schema.json +0 -63
  105. package/schemas/config.schema.json +0 -134
  106. package/schemas/gate-frontmatter.schema.json +0 -30
  107. package/schemas/hooks.schema.json +0 -115
  108. package/schemas/output-style-frontmatter.schema.json +0 -22
  109. package/schemas/plugin-manifest.schema.json +0 -436
  110. package/schemas/plugin-settings.schema.json +0 -29
  111. package/schemas/skill-frontmatter.schema.json +0 -177
  112. package/schemas/spec-frontmatter.schema.json +0 -42
  113. package/schemas/spec-state.schema.json +0 -147
  114. package/settings.json +0 -7
  115. package/skills/brownfield-index/SKILL.md +0 -53
  116. package/skills/brownfield-index/references/applicability.md +0 -12
  117. package/skills/brownfield-index/references/handoff.md +0 -8
  118. package/skills/brownfield-index/references/index-contract.md +0 -10
  119. package/skills/browser-qa/SKILL.md +0 -39
  120. package/skills/browser-qa/references/handoff.md +0 -6
  121. package/skills/browser-qa/references/prerequisites.md +0 -10
  122. package/skills/browser-qa/references/qa-contract.md +0 -20
  123. package/skills/cancel/SKILL.md +0 -41
  124. package/skills/cancel/references/destructive-mode.md +0 -17
  125. package/skills/cancel/references/reporting.md +0 -18
  126. package/skills/cancel/references/state-recovery.md +0 -30
  127. package/skills/cancel/references/target-resolution.md +0 -7
  128. package/skills/debug/SKILL.md +0 -45
  129. package/skills/debug/references/context-gathering.md +0 -11
  130. package/skills/debug/references/failure-guard.md +0 -25
  131. package/skills/debug/references/intake.md +0 -12
  132. package/skills/debug/references/phase-workflow.md +0 -34
  133. package/skills/debug/references/reporting.md +0 -20
  134. package/skills/epic/SKILL.md +0 -39
  135. package/skills/epic/references/epic-artifacts.md +0 -20
  136. package/skills/epic/references/epic-intake.md +0 -9
  137. package/skills/epic/references/slice-handoff.md +0 -16
  138. package/skills/fast/SKILL.md +0 -62
  139. package/skills/fast/references/applicability.md +0 -25
  140. package/skills/fast/references/clarification.md +0 -20
  141. package/skills/fast/references/execution-contract.md +0 -56
  142. package/skills/help/SKILL.md +0 -55
  143. package/skills/help/references/dispatch.md +0 -20
  144. package/skills/help/references/overview.md +0 -39
  145. package/skills/help/references/troubleshoot.md +0 -47
  146. package/skills/help/references/workflow.md +0 -37
  147. package/skills/implement/SKILL.md +0 -96
  148. package/skills/implement/references/error-recovery.md +0 -36
  149. package/skills/implement/references/linear-execution.md +0 -32
  150. package/skills/implement/references/preflight.md +0 -43
  151. package/skills/implement/references/progress-contract.md +0 -32
  152. package/skills/implement/references/state-init.md +0 -33
  153. package/skills/implement/references/stop-hook-execution.md +0 -36
  154. package/skills/implement/references/strategy-router.md +0 -38
  155. package/skills/implement/references/subagent-execution.md +0 -43
  156. package/skills/implement/references/wave-execution.md +0 -162
  157. package/skills/init/SKILL.md +0 -49
  158. package/skills/init/references/gitignore-and-health.md +0 -26
  159. package/skills/init/references/next-steps.md +0 -22
  160. package/skills/init/references/preflight.md +0 -15
  161. package/skills/init/references/scaffold-contract.md +0 -27
  162. package/skills/review/SKILL.md +0 -82
  163. package/skills/review/references/optional-passes.md +0 -48
  164. package/skills/review/references/preflight.md +0 -38
  165. package/skills/review/references/report-contract.md +0 -49
  166. package/skills/review/references/reporting.md +0 -20
  167. package/skills/review/references/stage-execution.md +0 -32
  168. package/skills/security-audit/SKILL.md +0 -47
  169. package/skills/security-audit/references/audit-contract.md +0 -21
  170. package/skills/security-audit/references/gate-handoff.md +0 -8
  171. package/skills/security-audit/references/scope-and-depth.md +0 -9
  172. package/skills/spec/SKILL.md +0 -100
  173. package/skills/spec/references/artifact-landing.md +0 -31
  174. package/skills/spec/references/phase-execution.md +0 -50
  175. package/skills/spec/references/planning-review.md +0 -31
  176. package/skills/spec/references/preflight-and-routing.md +0 -46
  177. package/skills/spec/references/reporting.md +0 -21
  178. package/skills/start/SKILL.md +0 -84
  179. package/skills/start/references/branch-routing.md +0 -51
  180. package/skills/start/references/mode-semantics.md +0 -12
  181. package/skills/start/references/preflight.md +0 -13
  182. package/skills/start/references/reporting.md +0 -20
  183. package/skills/start/references/state-seeding.md +0 -44
  184. package/skills/start/references/workflow-handoff.md +0 -26
  185. package/skills/status/SKILL.md +0 -41
  186. package/skills/status/references/gather-contract.md +0 -27
  187. package/skills/status/references/health-rules.md +0 -27
  188. package/skills/status/references/output-contract.md +0 -24
  189. package/skills/status/references/preflight.md +0 -10
  190. package/skills/status/references/recovery-hints.md +0 -18
  191. package/skills/ui-sketch/SKILL.md +0 -39
  192. package/skills/ui-sketch/references/brief-intake.md +0 -10
  193. package/skills/ui-sketch/references/iteration-handoff.md +0 -5
  194. package/skills/ui-sketch/references/variant-contract.md +0 -15
  195. package/skills/verify/SKILL.md +0 -56
  196. package/skills/verify/references/evidence-workflow.md +0 -39
  197. package/skills/verify/references/output-contract.md +0 -23
  198. package/skills/verify/references/preflight.md +0 -11
  199. package/skills/verify/references/report-handoff.md +0 -35
  200. package/skills/verify/references/strict-mode.md +0 -12
  201. package/templates/CONTEXT.md.tmpl +0 -53
  202. package/templates/PROJECT.md.tmpl +0 -59
  203. package/templates/ROADMAP.md.tmpl +0 -50
  204. package/templates/STATE.md.tmpl +0 -49
  205. package/templates/config.json.tmpl +0 -51
  206. package/templates/design.md.tmpl +0 -83
  207. package/templates/progress.md.tmpl +0 -77
  208. package/templates/requirements.md.tmpl +0 -76
  209. package/templates/research.md.tmpl +0 -83
  210. package/templates/tasks.md.tmpl +0 -107
@@ -1,360 +0,0 @@
1
- import { existsSync, lstatSync, unlinkSync, rmSync, readlinkSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { homedir } from "node:os";
4
-
5
- import { REQUIRED_PLUGINS, RECOMMENDED_PLUGINS, BUNDLED_MCPS } from "./registry.js";
6
- import { readConfig, writeConfig } from "./lib/config.js";
7
- import {
8
- removeMcp,
9
- removePluginMarketplace,
10
- uninstallPlugin,
11
- } from "./lib/claude-ops.js";
12
- import {
13
- confirm,
14
- color,
15
- listPlugins,
16
- log,
17
- resultLastLine,
18
- resultOutput,
19
- } from "./utils.js";
20
- import { reconcileLegacyContext7InstallState } from "./install-context7-config.js";
21
- import {
22
- UNINSTALL_STEP_COUNT,
23
- getInstalledTargets,
24
- getManagedMarketplaceIds,
25
- selectRecommendedPluginsToRemove,
26
- shouldKeepBundledMcps,
27
- shouldKeepRequiredPlugins,
28
- } from "./uninstall-workflow.js";
29
-
30
- const HOME = homedir();
31
-
32
- const RECOMMENDED = RECOMMENDED_PLUGINS.map(toUninstallTarget);
33
- const REQUIRED = REQUIRED_PLUGINS.map(toUninstallTarget);
34
-
35
- // Symlinks created by install.js (only cleaned with --purge)
36
- const MANAGED_SYMLINKS = [
37
- join(HOME, ".local", "bin", "bun"),
38
- join(HOME, ".local", "bin", "uv"),
39
- ];
40
-
41
- export async function uninstallCurdxFlowPlugin(
42
- {
43
- listPluginsImpl = listPlugins,
44
- uninstallPluginImpl = uninstallPlugin,
45
- logImpl = log,
46
- resultOutputImpl = resultOutput,
47
- } = {}
48
- ) {
49
- logImpl.blank();
50
- logImpl.step(1, UNINSTALL_STEP_COUNT, "Uninstalling curdx-flow plugin...");
51
- const curdx = listPluginsImpl().find((plugin) => plugin.name === "curdx-flow");
52
- if (!curdx) {
53
- logImpl.info("curdx-flow not installed, skipping");
54
- return;
55
- }
56
-
57
- const result = await uninstallPluginImpl({
58
- scope: "user",
59
- uninstallSpec: "curdx-flow@curdx-flow-marketplace",
60
- });
61
- if (result.code === 0) {
62
- logImpl.ok("curdx-flow uninstalled");
63
- return;
64
- }
65
-
66
- logImpl.err(`Uninstall failed: ${resultOutputImpl(result)}`);
67
- }
68
-
69
- export async function maybeUninstallRecommendedPlugins(
70
- { yes, keepRecommended },
71
- {
72
- getInstalledTargetsImpl = getInstalledTargets,
73
- selectRecommendedPluginsToRemoveImpl = selectRecommendedPluginsToRemove,
74
- uninstallNamedPluginImpl = uninstallNamedPlugin,
75
- logImpl = log,
76
- } = {}
77
- ) {
78
- logImpl.blank();
79
- logImpl.step(2, UNINSTALL_STEP_COUNT, "Recommended plugins");
80
- if (keepRecommended) {
81
- logImpl.info("Keeping recommended plugins (--keep-recommended)");
82
- return;
83
- }
84
-
85
- const present = getInstalledTargetsImpl(RECOMMENDED);
86
- if (present.length === 0) {
87
- logImpl.info("No installed recommended plugins");
88
- return;
89
- }
90
-
91
- const selected = await selectRecommendedPluginsToRemoveImpl({ yes, present });
92
- for (const name of selected) {
93
- const entry = present.find((plugin) => plugin.name === name);
94
- if (!entry) continue;
95
- await uninstallNamedPluginImpl(entry);
96
- }
97
- }
98
-
99
- export async function uninstallNamedPlugin(
100
- entry,
101
- {
102
- uninstallPluginImpl = uninstallPlugin,
103
- resultLastLineImpl = resultLastLine,
104
- } = {}
105
- ) {
106
- log.blank();
107
- console.log(` ${color.cyan("▸")} Uninstalling ${color.bold(entry.name)}...`);
108
- const result = await uninstallPluginImpl(entry);
109
- if (result.code === 0) {
110
- console.log(` ${color.green("✓")} ${entry.name} uninstalled`);
111
- return;
112
- }
113
-
114
- console.log(
115
- ` ${color.red("✗")} ${entry.name} uninstall failed: ${resultLastLineImpl(result)}`
116
- );
117
- }
118
-
119
- export async function maybeRemoveBundledMcps(
120
- { yes, keepRecommended },
121
- {
122
- shouldKeepBundledMcpsImpl = shouldKeepBundledMcps,
123
- confirmImpl = confirm,
124
- removeMcpImpl = removeMcp,
125
- logImpl = log,
126
- } = {}
127
- ) {
128
- logImpl.blank();
129
- logImpl.info("Required user-level MCP servers (sequential-thinking)");
130
- if (shouldKeepBundledMcpsImpl({ yes, keepRecommended })) {
131
- logImpl.info(
132
- color.dim("--yes or --keep-recommended: keeping user-level MCPs (remove manually with `claude mcp remove <name>`)")
133
- );
134
- return;
135
- }
136
-
137
- const removeMcps = await confirmImpl(
138
- `Remove user-level MCPs registered by install (${BUNDLED_MCPS.map((mcp) => mcp.name).join(", ")})? ${color.dim("(keeps them if other tools depend on them)")}`,
139
- false
140
- );
141
- if (!removeMcps) {
142
- logImpl.info("Keeping user-level MCPs");
143
- return;
144
- }
145
-
146
- for (const mcp of BUNDLED_MCPS) {
147
- const result = await removeMcpImpl({ name: mcp.name });
148
- if (result.code === 0) {
149
- logImpl.ok(` ${mcp.name.padEnd(22)} removed`);
150
- } else {
151
- logImpl.info(` ${mcp.name.padEnd(22)} ${color.dim("not present or already removed")}`);
152
- }
153
- }
154
- }
155
-
156
- export async function maybeUninstallRequiredPlugins(
157
- { yes },
158
- {
159
- shouldKeepRequiredPluginsImpl = shouldKeepRequiredPlugins,
160
- confirmImpl = confirm,
161
- uninstallPluginImpl = uninstallPlugin,
162
- logImpl = log,
163
- } = {}
164
- ) {
165
- logImpl.blank();
166
- logImpl.info("Required companion plugins");
167
- if (shouldKeepRequiredPluginsImpl({ yes })) {
168
- logImpl.info(
169
- color.dim("--yes mode: keeping required companion plugins (use --purge to remove them)")
170
- );
171
- return;
172
- }
173
-
174
- const removeRequired = await confirmImpl(
175
- `Remove required companion plugins (${REQUIRED.map((plugin) => plugin.name).join(", ")})? ${color.dim("(keeps shared tools available if other workflows depend on them)")}`,
176
- false
177
- );
178
- if (!removeRequired) {
179
- logImpl.info("Keeping required companion plugins");
180
- return;
181
- }
182
-
183
- for (const plugin of REQUIRED) {
184
- const result = await uninstallPluginImpl(plugin);
185
- if (result.code === 0) {
186
- logImpl.ok(` ${plugin.name.padEnd(22)} uninstalled`);
187
- } else {
188
- logImpl.info(` ${plugin.name.padEnd(22)} ${color.dim("not present or already removed")}`);
189
- }
190
- }
191
- }
192
-
193
- export async function maybePurgeRuntimeArtifacts(
194
- { purge },
195
- {
196
- purgeManagedMarketplacesImpl = purgeManagedMarketplaces,
197
- removeManagedSymlinksImpl = removeManagedSymlinks,
198
- readConfigImpl = readConfig,
199
- writeConfigImpl = writeConfig,
200
- removeMcpImpl = removeMcp,
201
- readUserMcpConfigImpl,
202
- logImpl = log,
203
- } = {}
204
- ) {
205
- logImpl.blank();
206
- logImpl.step(3, UNINSTALL_STEP_COUNT, "Runtime symlinks and marketplaces");
207
- if (!purge) {
208
- logImpl.info(
209
- color.dim("Keeping ~/.local/bin/bun, ~/.local/bin/uv (use --purge to remove)")
210
- );
211
- logImpl.info(
212
- color.dim("Reason: these bun/uv binaries may be used by other tools — confirm before deleting")
213
- );
214
- return;
215
- }
216
-
217
- await purgeManagedMarketplacesImpl();
218
- removeManagedSymlinksImpl();
219
- await purgeLegacyContext7InstallState({
220
- readConfigImpl,
221
- writeConfigImpl,
222
- removeMcpImpl,
223
- readUserMcpConfigImpl,
224
- logImpl,
225
- });
226
- }
227
-
228
- export async function maybeRemoveProjectState(
229
- { yes },
230
- {
231
- cwd = process.cwd(),
232
- confirmImpl = confirm,
233
- existsSyncImpl = existsSync,
234
- rmSyncImpl = rmSync,
235
- logImpl = log,
236
- } = {}
237
- ) {
238
- logImpl.blank();
239
- logImpl.step(4, UNINSTALL_STEP_COUNT, "Project state directory");
240
- const flowDir = join(cwd, ".flow");
241
- if (!existsSyncImpl(flowDir)) {
242
- logImpl.info(".flow/ does not exist, skipping");
243
- return;
244
- }
245
-
246
- if (yes) {
247
- logImpl.info(
248
- color.dim("--yes mode: keeping .flow/ (contains specs & decisions — confirm by hand before deleting)")
249
- );
250
- return;
251
- }
252
-
253
- const ok = await confirmImpl(
254
- `${color.red("DANGER:")} delete the ${color.bold(".flow/")} directory of the current project? ${color.dim("(includes all specs / decisions, not recoverable)")}`,
255
- false
256
- );
257
- if (!ok) {
258
- logImpl.info("Keeping .flow/");
259
- return;
260
- }
261
-
262
- try {
263
- rmSyncImpl(flowDir, { recursive: true, force: true });
264
- logImpl.ok(`Removed ${flowDir}`);
265
- } catch (err) {
266
- logImpl.err(`Removal failed: ${err.message}`);
267
- }
268
- }
269
-
270
- async function purgeManagedMarketplaces(
271
- {
272
- getManagedMarketplaceIdsImpl = getManagedMarketplaceIds,
273
- removePluginMarketplaceImpl = removePluginMarketplace,
274
- logImpl = log,
275
- } = {}
276
- ) {
277
- const marketplaceIds = getManagedMarketplaceIdsImpl(RECOMMENDED.concat(REQUIRED));
278
-
279
- for (const marketplaceId of marketplaceIds) {
280
- const result = await removePluginMarketplaceImpl(marketplaceId);
281
- if (result.code === 0) {
282
- logImpl.ok(`Removed marketplace ${marketplaceId}`);
283
- } else if (!result.stderr.includes("not found")) {
284
- logImpl.warn(`Failed to remove marketplace ${marketplaceId}: ${resultLastLine(result)}`);
285
- }
286
- }
287
- }
288
-
289
- function removeManagedSymlinks(
290
- {
291
- existsSyncImpl = existsSync,
292
- isBrokenSymlinkImpl = isBrokenSymlink,
293
- lstatSyncImpl = lstatSync,
294
- readlinkSyncImpl = readlinkSync,
295
- unlinkSyncImpl = unlinkSync,
296
- logImpl = log,
297
- } = {}
298
- ) {
299
- for (const link of MANAGED_SYMLINKS) {
300
- if (!existsSyncImpl(link) && !isBrokenSymlinkImpl(link)) {
301
- continue;
302
- }
303
- try {
304
- const stat = lstatSyncImpl(link);
305
- if (!stat.isSymbolicLink()) {
306
- logImpl.warn(
307
- `${link} is not a symlink (likely a real file placed by the user), skipping`
308
- );
309
- continue;
310
- }
311
- const target = readlinkSyncImpl(link);
312
- unlinkSyncImpl(link);
313
- logImpl.ok(`Removed symlink ${link} ${color.dim(`(was → ${target})`)}`);
314
- } catch (err) {
315
- logImpl.warn(`Failed to remove ${link}: ${err.message}`);
316
- }
317
- }
318
- }
319
-
320
- async function purgeLegacyContext7InstallState(
321
- {
322
- readConfigImpl = readConfig,
323
- writeConfigImpl = writeConfig,
324
- removeMcpImpl = removeMcp,
325
- readUserMcpConfigImpl,
326
- logImpl = log,
327
- } = {}
328
- ) {
329
- const config = readConfigImpl();
330
- const language = config?.language === "zh" ? "zh" : "en";
331
- await reconcileLegacyContext7InstallState(
332
- { name: "context7-plugin" },
333
- language,
334
- config,
335
- {
336
- writeConfigImpl,
337
- removeMcpImpl,
338
- readUserMcpConfigImpl,
339
- logImpl,
340
- }
341
- );
342
- }
343
-
344
- function toUninstallTarget(entry) {
345
- return {
346
- name: entry.name,
347
- uninstallSpec: entry.uninstallSpec,
348
- uninstallArgs: entry.uninstallArgs || [],
349
- marketplaceId: entry.marketplaceId,
350
- scope: entry.scope,
351
- };
352
- }
353
-
354
- function isBrokenSymlink(pathname) {
355
- try {
356
- return lstatSync(pathname).isSymbolicLink();
357
- } catch {
358
- return false;
359
- }
360
- }
@@ -1,146 +0,0 @@
1
- import { GLOBAL_CLAUDE_MD, removeGlobalProtocols } from "./protocols.js";
2
- import {
3
- claudeVersion,
4
- color,
5
- confirm,
6
- listPlugins,
7
- log,
8
- multiSelect,
9
- } from "./utils.js";
10
-
11
- export const UNINSTALL_STEP_COUNT = 4;
12
-
13
- export function createUninstallContext(args = []) {
14
- return {
15
- yes: args.includes("--yes") || args.includes("-y"),
16
- purge: args.includes("--purge"),
17
- keepRecommended: args.includes("--keep-recommended"),
18
- };
19
- }
20
-
21
- export function ensureClaudeCliAvailableForUninstall(
22
- { claudeVersionImpl = claudeVersion, logImpl = log, exitImpl = process.exit } = {}
23
- ) {
24
- const version = claudeVersionImpl();
25
- if (!version) {
26
- logImpl.err("claude CLI not found, cannot uninstall plugin.");
27
- exitImpl(1);
28
- return null;
29
- }
30
-
31
- return version;
32
- }
33
-
34
- export async function confirmUninstallStep(
35
- { yes },
36
- { confirmImpl = confirm, logImpl = log } = {}
37
- ) {
38
- if (yes) {
39
- return true;
40
- }
41
-
42
- const confirmed = await confirmImpl(
43
- `This will uninstall the ${color.bold("curdx-flow")} plugin. Continue?`,
44
- false
45
- );
46
- if (!confirmed) {
47
- logImpl.info("Cancelled");
48
- }
49
- return confirmed;
50
- }
51
-
52
- export function getInstalledTargets(entries, { listPluginsImpl = listPlugins } = {}) {
53
- const installedNames = new Set(listPluginsImpl().map((plugin) => plugin.name));
54
- return entries.filter((entry) => installedNames.has(entry.name));
55
- }
56
-
57
- export async function selectRecommendedPluginsToRemove(
58
- { yes, present },
59
- { multiSelectImpl = multiSelect, logImpl = log } = {}
60
- ) {
61
- if (present.length === 0) {
62
- return [];
63
- }
64
-
65
- if (yes) {
66
- logImpl.info(
67
- color.dim("--yes mode: keeping recommended plugins (use --purge to remove them)")
68
- );
69
- return [];
70
- }
71
-
72
- const choices = present.map((entry) => ({
73
- label: color.bold(entry.name),
74
- value: entry.name,
75
- hint: "",
76
- }));
77
-
78
- return multiSelectImpl(
79
- "Which recommended plugins to also uninstall? (default: none)",
80
- choices,
81
- []
82
- );
83
- }
84
-
85
- export function shouldKeepBundledMcps({ yes, keepRecommended }) {
86
- if (!yes && !keepRecommended) {
87
- return false;
88
- }
89
-
90
- return true;
91
- }
92
-
93
- export function shouldKeepRequiredPlugins({ yes }) {
94
- return yes;
95
- }
96
-
97
- export function getManagedMarketplaceIds(entries) {
98
- return [
99
- ...new Set(
100
- entries
101
- .map((entry) => entry.marketplaceId)
102
- .filter((id) => id && id !== "claude-plugins-official")
103
- ),
104
- ];
105
- }
106
-
107
- export function removeProtocolsStep(
108
- { logImpl = log, removeGlobalProtocolsImpl = removeGlobalProtocols } = {}
109
- ) {
110
- logImpl.blank();
111
- console.log(color.dim("Removing global protocols from ~/.claude/CLAUDE.md..."));
112
-
113
- try {
114
- const result = removeGlobalProtocolsImpl();
115
- if (result.action === "removed") {
116
- logImpl.ok(`Global protocols removed ${color.dim(`(${GLOBAL_CLAUDE_MD})`)}`);
117
- } else if (result.action === "not-present") {
118
- logImpl.info("Global protocols not present, skipping");
119
- } else {
120
- logImpl.info("~/.claude/CLAUDE.md does not exist, skipping");
121
- }
122
- } catch (err) {
123
- logImpl.warn(`Protocol removal failed: ${err.message}`);
124
- }
125
- }
126
-
127
- export function printUninstallSummary({ purge }, { logImpl = log } = {}) {
128
- logImpl.blank();
129
- console.log(color.bold("✅ Uninstall complete"));
130
- if (purge) {
131
- return;
132
- }
133
-
134
- console.log(
135
- color.dim(
136
- `\nArtifacts kept:\n` +
137
- ` - ~/.local/bin/bun, ~/.local/bin/uv (symlinks; use --purge to remove)\n` +
138
- ` - bun/uv binaries themselves (~/.bun/bin/bun, ~/.local/bin/uv real installs)\n` +
139
- ` - claude-mem data (~/.claude-mem/)\n` +
140
- ` - claude marketplace cache`
141
- )
142
- );
143
- console.log(
144
- color.dim(`\nFully purge: ${color.cyan("curdx-flow uninstall --purge")}`)
145
- );
146
- }
package/cli/uninstall.js DELETED
@@ -1,42 +0,0 @@
1
- /**
2
- * uninstall command — remove curdx-flow plugin (and optionally recommended plugins / artifacts).
3
- */
4
-
5
- import { log } from "./utils.js";
6
- import {
7
- createUninstallContext,
8
- ensureClaudeCliAvailableForUninstall,
9
- printUninstallSummary,
10
- removeProtocolsStep,
11
- confirmUninstallStep,
12
- } from "./uninstall-workflow.js";
13
- import {
14
- maybePurgeRuntimeArtifacts,
15
- maybeRemoveBundledMcps,
16
- maybeRemoveProjectState,
17
- maybeUninstallRecommendedPlugins,
18
- maybeUninstallRequiredPlugins,
19
- uninstallCurdxFlowPlugin,
20
- } from "./uninstall-actions.js";
21
-
22
- export async function uninstall(args = []) {
23
- const context = createUninstallContext(args);
24
-
25
- log.title("🗑️ CurdX-Flow Uninstaller");
26
-
27
- ensureClaudeCliAvailableForUninstall();
28
-
29
- if (!(await confirmUninstallStep(context))) {
30
- return;
31
- }
32
-
33
- await uninstallCurdxFlowPlugin();
34
- await maybeUninstallRecommendedPlugins(context);
35
- await maybeRemoveBundledMcps(context);
36
- await maybeUninstallRequiredPlugins(context);
37
- await maybePurgeRuntimeArtifacts(context);
38
- removeProtocolsStep();
39
- await maybeRemoveProjectState(context);
40
-
41
- printUninstallSummary(context);
42
- }
@@ -1,80 +0,0 @@
1
- import { claudeVersion, color, listPlugins, log, resultLastLine } from "./utils.js";
2
-
3
- export const UPGRADE_STEP_COUNT = 3;
4
-
5
- export function ensureClaudeCliAvailableForUpgrade(
6
- { claudeVersionImpl = claudeVersion, logImpl = log, exitImpl = process.exit } = {}
7
- ) {
8
- const version = claudeVersionImpl();
9
- if (!version) {
10
- logImpl.err("claude CLI not found");
11
- exitImpl(1);
12
- return null;
13
- }
14
-
15
- return version;
16
- }
17
-
18
- export function getInstalledPluginNames({ listPluginsImpl = listPlugins } = {}) {
19
- return new Set(listPluginsImpl().map((plugin) => plugin.name));
20
- }
21
-
22
- export function getPluginNameFromSpec(spec) {
23
- return String(spec).split("@")[0];
24
- }
25
-
26
- export function classifyPluginUpdateResult(result) {
27
- if (result.code !== 0) {
28
- return {
29
- status: "failed",
30
- message: resultLastLine(result),
31
- };
32
- }
33
-
34
- if (!result.stdout.includes("updated from")) {
35
- return {
36
- status: "unchanged",
37
- message: "already up to date",
38
- };
39
- }
40
-
41
- const match = result.stdout.match(/updated from (\S+) to (\S+)/);
42
- if (!match) {
43
- return {
44
- status: "updated",
45
- message: "updated",
46
- };
47
- }
48
-
49
- return {
50
- status: "updated",
51
- from: match[1],
52
- to: match[2],
53
- message: color.dim(`${match[1]} → ${match[2]}`),
54
- };
55
- }
56
-
57
- export async function refreshMarketplaces(
58
- marketplaceIds,
59
- { updatePluginMarketplaceImpl, logImpl = log } = {}
60
- ) {
61
- logImpl.step(1, UPGRADE_STEP_COUNT, "Refreshing marketplaces...");
62
-
63
- for (const marketplaceId of marketplaceIds) {
64
- const result = await updatePluginMarketplaceImpl(marketplaceId);
65
- if (result.code === 0) {
66
- logImpl.ok(` ${marketplaceId}`);
67
- continue;
68
- }
69
-
70
- if (!result.stderr.includes("not found")) {
71
- logImpl.warn(` ${marketplaceId}: ${resultLastLine(result)}`);
72
- }
73
- }
74
- }
75
-
76
- export function printUpgradeSummary({ logImpl = log } = {}) {
77
- logImpl.blank();
78
- logImpl.ok("Upgrade complete");
79
- console.log(color.dim(" Some changes require a Claude Code restart to take effect"));
80
- }
package/cli/upgrade.js DELETED
@@ -1,91 +0,0 @@
1
- /**
2
- * upgrade command — update curdx-flow + recommended plugins to latest.
3
- */
4
-
5
- import { log, readConfig } from "./utils.js";
6
- import { reconcileLegacyContext7InstallState } from "./install-context7-config.js";
7
- import {
8
- PLUGINS_TO_UPDATE,
9
- MARKETPLACES_TO_REFRESH,
10
- } from "./registry.js";
11
- import {
12
- updatePlugin,
13
- updatePluginMarketplace,
14
- } from "./lib/claude-ops.js";
15
- import {
16
- classifyPluginUpdateResult,
17
- ensureClaudeCliAvailableForUpgrade,
18
- getInstalledPluginNames,
19
- getPluginNameFromSpec,
20
- printUpgradeSummary,
21
- refreshMarketplaces,
22
- UPGRADE_STEP_COUNT,
23
- } from "./upgrade-workflow.js";
24
-
25
- export async function upgrade(
26
- args = [],
27
- {
28
- updatePluginImpl = updatePlugin,
29
- updatePluginMarketplaceImpl = updatePluginMarketplace,
30
- ensureClaudeCliAvailableForUpgradeImpl = ensureClaudeCliAvailableForUpgrade,
31
- getInstalledPluginNamesImpl = getInstalledPluginNames,
32
- readConfigImpl = readConfig,
33
- reconcileLegacyContext7InstallStateImpl = reconcileLegacyContext7InstallState,
34
- logImpl = log,
35
- } = {}
36
- ) {
37
- logImpl.title("⬆️ CurdX-Flow upgrade");
38
-
39
- ensureClaudeCliAvailableForUpgradeImpl({ logImpl });
40
-
41
- // Refresh marketplaces first (derived from cli/registry.js)
42
- await refreshMarketplaces(MARKETPLACES_TO_REFRESH, {
43
- updatePluginMarketplaceImpl,
44
- logImpl,
45
- });
46
-
47
- // Update each plugin
48
- logImpl.blank();
49
- logImpl.step(2, UPGRADE_STEP_COUNT, "Updating installed plugins...");
50
- const installedNames = getInstalledPluginNamesImpl();
51
-
52
- for (const spec of PLUGINS_TO_UPDATE) {
53
- const pluginName = getPluginNameFromSpec(spec);
54
- if (!installedNames.has(pluginName)) {
55
- logImpl.info(` ${pluginName.padEnd(22)} not installed, skipping`);
56
- continue;
57
- }
58
-
59
- const result = await updatePluginImpl(spec);
60
- const status = classifyPluginUpdateResult(result);
61
-
62
- if (status.status === "updated") {
63
- logImpl.ok(` ${pluginName.padEnd(22)} ${status.message}`);
64
- continue;
65
- }
66
-
67
- if (status.status === "unchanged") {
68
- logImpl.info(` ${pluginName.padEnd(22)} ${status.message}`);
69
- continue;
70
- }
71
-
72
- logImpl.warn(` ${pluginName.padEnd(22)} ${status.message}`);
73
- }
74
-
75
- logImpl.blank();
76
- logImpl.step(3, UPGRADE_STEP_COUNT, "Reconciling legacy Context7 state...");
77
- if (installedNames.has("context7-plugin")) {
78
- const config = readConfigImpl();
79
- const language = config?.language === "zh" ? "zh" : "en";
80
- await reconcileLegacyContext7InstallStateImpl(
81
- { name: "context7-plugin" },
82
- language,
83
- config,
84
- { logImpl }
85
- );
86
- } else {
87
- logImpl.info(" context7-plugin not installed, skipping");
88
- }
89
-
90
- printUpgradeSummary({ logImpl });
91
- }