@curdx/flow 3.0.0 → 3.2.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 (219) hide show
  1. package/CHANGELOG.md +33 -82
  2. package/LICENSE +1 -1
  3. package/README.md +28 -129
  4. package/dist/index.mjs +1165 -0
  5. package/package.json +33 -44
  6. package/.claude-plugin/marketplace.json +0 -48
  7. package/.claude-plugin/plugin.json +0 -52
  8. package/agent-preamble/preamble.md +0 -314
  9. package/agents/flow-adversary.md +0 -203
  10. package/agents/flow-architect.md +0 -198
  11. package/agents/flow-brownfield-analyst.md +0 -143
  12. package/agents/flow-debugger.md +0 -321
  13. package/agents/flow-edge-hunter.md +0 -289
  14. package/agents/flow-executor.md +0 -269
  15. package/agents/flow-orchestrator.md +0 -145
  16. package/agents/flow-planner.md +0 -247
  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 -166
  20. package/agents/flow-reviewer.md +0 -304
  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 -230
  24. package/agents/flow-ux-designer.md +0 -221
  25. package/agents/flow-verifier.md +0 -350
  26. package/bin/curdx-flow +0 -5
  27. package/bin/curdx-flow-state +0 -104
  28. package/bin/curdx-flow.js +0 -54
  29. package/cli/README.md +0 -104
  30. package/cli/doctor-workflow.js +0 -483
  31. package/cli/doctor.js +0 -73
  32. package/cli/help.js +0 -59
  33. package/cli/install-bundled-mcps.js +0 -37
  34. package/cli/install-companions.js +0 -19
  35. package/cli/install-context7-config.js +0 -80
  36. package/cli/install-curdx-plugin.js +0 -96
  37. package/cli/install-language.js +0 -35
  38. package/cli/install-next-steps.js +0 -29
  39. package/cli/install-options.js +0 -9
  40. package/cli/install-paths.js +0 -52
  41. package/cli/install-recommended-plugins.js +0 -104
  42. package/cli/install-required-plugins.js +0 -57
  43. package/cli/install-self-update.js +0 -62
  44. package/cli/install-workflow.js +0 -209
  45. package/cli/install.js +0 -101
  46. package/cli/lib/claude-commands.js +0 -41
  47. package/cli/lib/claude-ops.js +0 -47
  48. package/cli/lib/claude.js +0 -183
  49. package/cli/lib/config.js +0 -24
  50. package/cli/lib/doctor-claude-settings.js +0 -1186
  51. package/cli/lib/doctor-report.js +0 -978
  52. package/cli/lib/doctor-runtime-environment.js +0 -196
  53. package/cli/lib/frontmatter.js +0 -44
  54. package/cli/lib/json-schema.js +0 -57
  55. package/cli/lib/logging.js +0 -25
  56. package/cli/lib/process.js +0 -60
  57. package/cli/lib/prompts.js +0 -135
  58. package/cli/lib/runtime.js +0 -107
  59. package/cli/lib/semver.js +0 -109
  60. package/cli/lib/version.js +0 -12
  61. package/cli/protocols-body.md +0 -22
  62. package/cli/protocols.js +0 -162
  63. package/cli/registry.js +0 -123
  64. package/cli/router.js +0 -49
  65. package/cli/uninstall-actions.js +0 -360
  66. package/cli/uninstall-workflow.js +0 -146
  67. package/cli/uninstall.js +0 -42
  68. package/cli/upgrade-workflow.js +0 -80
  69. package/cli/upgrade.js +0 -91
  70. package/cli/utils.js +0 -40
  71. package/gates/adversarial-review-gate.md +0 -219
  72. package/gates/coverage-audit-gate.md +0 -182
  73. package/gates/devex-gate.md +0 -254
  74. package/gates/edge-case-gate.md +0 -194
  75. package/gates/karpathy-gate.md +0 -130
  76. package/gates/security-gate.md +0 -218
  77. package/gates/tdd-gate.md +0 -182
  78. package/gates/test-quality-gate.md +0 -59
  79. package/gates/verification-gate.md +0 -179
  80. package/hooks/hooks.json +0 -130
  81. package/hooks/scripts/common.sh +0 -237
  82. package/hooks/scripts/config-change-guard.sh +0 -94
  83. package/hooks/scripts/flow-context-watch.sh +0 -94
  84. package/hooks/scripts/inject-karpathy.sh +0 -53
  85. package/hooks/scripts/quick-mode-guard.sh +0 -69
  86. package/hooks/scripts/session-start.sh +0 -94
  87. package/hooks/scripts/session-title.sh +0 -87
  88. package/hooks/scripts/stop-watcher.sh +0 -231
  89. package/hooks/scripts/subagent-artifact-guard.sh +0 -92
  90. package/hooks/scripts/subagent-statusline.sh +0 -111
  91. package/hooks/scripts/task-lifecycle-guard.sh +0 -106
  92. package/hooks/scripts/teammate-idle-guard.sh +0 -83
  93. package/knowledge/artifact-output-discipline.md +0 -24
  94. package/knowledge/artifact-summary-contracts.md +0 -50
  95. package/knowledge/atomic-commits.md +0 -262
  96. package/knowledge/claude-code-runtime-contracts.md +0 -240
  97. package/knowledge/epic-decomposition.md +0 -307
  98. package/knowledge/execution-strategies.md +0 -303
  99. package/knowledge/karpathy-guidelines.md +0 -219
  100. package/knowledge/planning-reviews.md +0 -211
  101. package/knowledge/poc-first-workflow.md +0 -223
  102. package/knowledge/review-feedback-intake.md +0 -57
  103. package/knowledge/spec-driven-development.md +0 -180
  104. package/knowledge/systematic-debugging.md +0 -378
  105. package/knowledge/two-stage-review.md +0 -249
  106. package/knowledge/wave-execution.md +0 -403
  107. package/monitors/monitors.json +0 -8
  108. package/monitors/scripts/flow-state-monitor.sh +0 -102
  109. package/output-styles/curdx-evidence-first.md +0 -34
  110. package/output-styles/curdx-fast-mode.md +0 -42
  111. package/output-styles/curdx-spec-mode.md +0 -46
  112. package/schemas/agent-frontmatter.schema.json +0 -66
  113. package/schemas/config.schema.json +0 -134
  114. package/schemas/gate-frontmatter.schema.json +0 -30
  115. package/schemas/hooks.schema.json +0 -115
  116. package/schemas/output-style-frontmatter.schema.json +0 -22
  117. package/schemas/plugin-manifest.schema.json +0 -436
  118. package/schemas/plugin-settings.schema.json +0 -29
  119. package/schemas/skill-frontmatter.schema.json +0 -177
  120. package/schemas/spec-frontmatter.schema.json +0 -42
  121. package/schemas/spec-state.schema.json +0 -165
  122. package/settings.json +0 -8
  123. package/skills/brownfield-index/SKILL.md +0 -53
  124. package/skills/brownfield-index/references/applicability.md +0 -12
  125. package/skills/brownfield-index/references/handoff.md +0 -8
  126. package/skills/brownfield-index/references/index-contract.md +0 -10
  127. package/skills/browser-qa/SKILL.md +0 -39
  128. package/skills/browser-qa/references/handoff.md +0 -6
  129. package/skills/browser-qa/references/prerequisites.md +0 -10
  130. package/skills/browser-qa/references/qa-contract.md +0 -20
  131. package/skills/cancel/SKILL.md +0 -41
  132. package/skills/cancel/references/destructive-mode.md +0 -17
  133. package/skills/cancel/references/reporting.md +0 -18
  134. package/skills/cancel/references/state-recovery.md +0 -30
  135. package/skills/cancel/references/target-resolution.md +0 -7
  136. package/skills/debug/SKILL.md +0 -45
  137. package/skills/debug/references/context-gathering.md +0 -11
  138. package/skills/debug/references/failure-guard.md +0 -25
  139. package/skills/debug/references/intake.md +0 -12
  140. package/skills/debug/references/phase-workflow.md +0 -34
  141. package/skills/debug/references/reporting.md +0 -20
  142. package/skills/epic/SKILL.md +0 -39
  143. package/skills/epic/references/epic-artifacts.md +0 -20
  144. package/skills/epic/references/epic-intake.md +0 -9
  145. package/skills/epic/references/slice-handoff.md +0 -16
  146. package/skills/fast/SKILL.md +0 -62
  147. package/skills/fast/references/applicability.md +0 -25
  148. package/skills/fast/references/clarification.md +0 -20
  149. package/skills/fast/references/execution-contract.md +0 -56
  150. package/skills/help/SKILL.md +0 -55
  151. package/skills/help/references/dispatch.md +0 -20
  152. package/skills/help/references/overview.md +0 -39
  153. package/skills/help/references/troubleshoot.md +0 -47
  154. package/skills/help/references/workflow.md +0 -37
  155. package/skills/implement/SKILL.md +0 -104
  156. package/skills/implement/references/error-recovery.md +0 -36
  157. package/skills/implement/references/linear-execution.md +0 -43
  158. package/skills/implement/references/native-task-sync.md +0 -107
  159. package/skills/implement/references/preflight.md +0 -43
  160. package/skills/implement/references/progress-contract.md +0 -36
  161. package/skills/implement/references/state-init.md +0 -36
  162. package/skills/implement/references/stop-hook-execution.md +0 -50
  163. package/skills/implement/references/strategy-router.md +0 -38
  164. package/skills/implement/references/subagent-execution.md +0 -57
  165. package/skills/implement/references/wave-execution.md +0 -180
  166. package/skills/init/SKILL.md +0 -49
  167. package/skills/init/references/gitignore-and-health.md +0 -26
  168. package/skills/init/references/next-steps.md +0 -22
  169. package/skills/init/references/preflight.md +0 -15
  170. package/skills/init/references/scaffold-contract.md +0 -27
  171. package/skills/review/SKILL.md +0 -82
  172. package/skills/review/references/optional-passes.md +0 -48
  173. package/skills/review/references/preflight.md +0 -38
  174. package/skills/review/references/report-contract.md +0 -49
  175. package/skills/review/references/reporting.md +0 -20
  176. package/skills/review/references/stage-execution.md +0 -32
  177. package/skills/security-audit/SKILL.md +0 -47
  178. package/skills/security-audit/references/audit-contract.md +0 -21
  179. package/skills/security-audit/references/gate-handoff.md +0 -8
  180. package/skills/security-audit/references/scope-and-depth.md +0 -9
  181. package/skills/spec/SKILL.md +0 -100
  182. package/skills/spec/references/artifact-landing.md +0 -31
  183. package/skills/spec/references/phase-execution.md +0 -50
  184. package/skills/spec/references/planning-review.md +0 -31
  185. package/skills/spec/references/preflight-and-routing.md +0 -46
  186. package/skills/spec/references/reporting.md +0 -21
  187. package/skills/start/SKILL.md +0 -84
  188. package/skills/start/references/branch-routing.md +0 -51
  189. package/skills/start/references/mode-semantics.md +0 -12
  190. package/skills/start/references/preflight.md +0 -13
  191. package/skills/start/references/reporting.md +0 -20
  192. package/skills/start/references/state-seeding.md +0 -44
  193. package/skills/start/references/workflow-handoff.md +0 -26
  194. package/skills/status/SKILL.md +0 -41
  195. package/skills/status/references/gather-contract.md +0 -30
  196. package/skills/status/references/health-rules.md +0 -27
  197. package/skills/status/references/output-contract.md +0 -25
  198. package/skills/status/references/preflight.md +0 -10
  199. package/skills/status/references/recovery-hints.md +0 -18
  200. package/skills/ui-sketch/SKILL.md +0 -39
  201. package/skills/ui-sketch/references/brief-intake.md +0 -10
  202. package/skills/ui-sketch/references/iteration-handoff.md +0 -5
  203. package/skills/ui-sketch/references/variant-contract.md +0 -15
  204. package/skills/verify/SKILL.md +0 -56
  205. package/skills/verify/references/evidence-workflow.md +0 -39
  206. package/skills/verify/references/output-contract.md +0 -23
  207. package/skills/verify/references/preflight.md +0 -11
  208. package/skills/verify/references/report-handoff.md +0 -35
  209. package/skills/verify/references/strict-mode.md +0 -12
  210. package/templates/CONTEXT.md.tmpl +0 -53
  211. package/templates/PROJECT.md.tmpl +0 -59
  212. package/templates/ROADMAP.md.tmpl +0 -50
  213. package/templates/STATE.md.tmpl +0 -49
  214. package/templates/config.json.tmpl +0 -51
  215. package/templates/design.md.tmpl +0 -83
  216. package/templates/progress.md.tmpl +0 -77
  217. package/templates/requirements.md.tmpl +0 -76
  218. package/templates/research.md.tmpl +0 -83
  219. package/templates/tasks.md.tmpl +0 -107
@@ -1,62 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { join } from "node:path";
3
-
4
- import { log, run, runSync, VERSION } from "./utils.js";
5
- import { compareVersions, isVersionNewer } from "./lib/semver.js";
6
-
7
- export { compareVersions, isVersionNewer };
8
-
9
- /**
10
- * Check for CLI updates and auto-update if available.
11
- * @returns {Promise<{updated: boolean, version?: string}>}
12
- */
13
- export async function checkAndUpdateSelf() {
14
- try {
15
- const globalPath = runSync("npm", ["root", "-g"]).stdout.trim();
16
- const installedPath = join(globalPath, "@curdx/flow");
17
-
18
- if (!existsSync(installedPath)) {
19
- return { updated: false };
20
- }
21
-
22
- log.info("Checking for CLI updates...");
23
- const res = runSync("npm", ["view", "@curdx/flow", "version"]);
24
-
25
- if (res.code !== 0) {
26
- return { updated: false };
27
- }
28
-
29
- const latestVersion = res.stdout.trim();
30
- const currentVersion = VERSION;
31
-
32
- if (latestVersion === currentVersion) {
33
- log.ok(`CLI is up to date (v${currentVersion})`);
34
- return { updated: false };
35
- }
36
-
37
- if (isVersionNewer(latestVersion, currentVersion)) {
38
- log.info(`New version available: v${currentVersion} → v${latestVersion}`);
39
- log.info("Updating CLI...");
40
-
41
- const updateRes = await run("npm", ["install", "-g", "@curdx/flow@latest"], {
42
- silent: false,
43
- });
44
-
45
- if (updateRes.code === 0) {
46
- log.ok(`CLI updated to v${latestVersion}`);
47
- return {
48
- updated: true,
49
- version: latestVersion,
50
- entryPath: join(installedPath, "bin", "curdx-flow.js"),
51
- };
52
- }
53
-
54
- log.warn("CLI update failed, continuing with current version");
55
- return { updated: false };
56
- }
57
-
58
- return { updated: false };
59
- } catch {
60
- return { updated: false };
61
- }
62
- }
@@ -1,209 +0,0 @@
1
- import { spawn } from "node:child_process";
2
-
3
- import { installRecommendedPlugins } from "./install-companions.js";
4
- import { printNextSteps } from "./install-next-steps.js";
5
- import { parseInstallOptions } from "./install-options.js";
6
- import {
7
- getMarketplaceLabel,
8
- getMarketplaceSource,
9
- shouldUseOfflineInstall,
10
- } from "./install-paths.js";
11
- import { injectGlobalProtocols, GLOBAL_CLAUDE_MD } from "./protocols.js";
12
- import { checkAndUpdateSelf } from "./install-self-update.js";
13
- import {
14
- claudeVersion,
15
- color,
16
- intro,
17
- listPlugins,
18
- log,
19
- select,
20
- } from "./utils.js";
21
-
22
- export const INSTALL_STEP_COUNT = 5;
23
-
24
- export function createInstallContext(args = []) {
25
- const options = parseInstallOptions(args);
26
- const useOffline = shouldUseOfflineInstall({ forceOnline: options.forceOnline });
27
-
28
- return {
29
- ...options,
30
- args,
31
- useOffline,
32
- marketplaceSource: getMarketplaceSource(useOffline),
33
- marketplaceLabel: getMarketplaceLabel(useOffline),
34
- };
35
- }
36
-
37
- export async function maybeRestartWithUpdatedCli(
38
- context,
39
- {
40
- checkAndUpdateSelfImpl = checkAndUpdateSelf,
41
- spawnImpl = spawn,
42
- logImpl = log,
43
- exitImpl = process.exit,
44
- } = {}
45
- ) {
46
- if (context.skipSelfUpdate) {
47
- return false;
48
- }
49
-
50
- const updateResult = await checkAndUpdateSelfImpl();
51
- if (!updateResult.updated) {
52
- return false;
53
- }
54
-
55
- logImpl.info("Restarting with updated version...");
56
- const child = spawnImpl(
57
- process.execPath,
58
- [updateResult.entryPath, "install", ...context.args, "--skip-self-update"],
59
- {
60
- stdio: "inherit",
61
- shell: false,
62
- }
63
- );
64
-
65
- await new Promise((resolve) => {
66
- child.on("close", (code) => {
67
- exitImpl(code || 0);
68
- resolve();
69
- });
70
- });
71
-
72
- return true;
73
- }
74
-
75
- export async function renderInstallIntro(
76
- { yes },
77
- { introImpl = intro, logImpl = log, isTTY = process.stdout.isTTY } = {}
78
- ) {
79
- if (isTTY && !yes) {
80
- await introImpl("🚀 CurdX-Flow Installer");
81
- return;
82
- }
83
-
84
- logImpl.title("🚀 CurdX-Flow Installer");
85
- }
86
-
87
- export function ensureClaudeCliAvailable(
88
- { logImpl = log, claudeVersionImpl = claudeVersion, exitImpl = process.exit } = {}
89
- ) {
90
- logImpl.blank();
91
- logImpl.step(1, INSTALL_STEP_COUNT, "Checking claude CLI...");
92
-
93
- const version = claudeVersionImpl();
94
- if (!version) {
95
- logImpl.err(
96
- "claude CLI not found. Install Claude Code from https://code.claude.com first."
97
- );
98
- exitImpl(1);
99
- return null;
100
- }
101
-
102
- logImpl.ok(`claude CLI found (${version})`);
103
- return version;
104
- }
105
-
106
- export function snapshotCurdxFlowInstall({ listPluginsImpl = listPlugins } = {}) {
107
- return listPluginsImpl().find((plugin) => plugin.name === "curdx-flow");
108
- }
109
-
110
- export async function resolveExistingInstallationAction(
111
- { prevCurdxFlow, yes, language },
112
- { selectImpl = select, logImpl = log, exitImpl = process.exit } = {}
113
- ) {
114
- if (!prevCurdxFlow || yes) {
115
- return { action: null, continueInstall: true };
116
- }
117
-
118
- logImpl.blank();
119
- const action = await selectImpl({
120
- message: language === "zh"
121
- ? "检测到已安装的版本。如何继续?"
122
- : "Existing installation detected. How would you like to proceed?",
123
- options: [
124
- {
125
- value: "upgrade",
126
- label: language === "zh" ? "升级到最新版本" : "Upgrade to latest version",
127
- hint: language === "zh"
128
- ? `当前: v${prevCurdxFlow.version}`
129
- : `Current: v${prevCurdxFlow.version}`,
130
- },
131
- {
132
- value: "reinstall",
133
- label: language === "zh" ? "重新安装(保留配置)" : "Reinstall (preserve config)",
134
- },
135
- {
136
- value: "reconfigure",
137
- label: language === "zh" ? "重新配置插件" : "Reconfigure plugins",
138
- },
139
- {
140
- value: "cancel",
141
- label: language === "zh" ? "取消" : "Cancel",
142
- },
143
- ],
144
- initialValue: "upgrade",
145
- });
146
-
147
- if (action === "cancel") {
148
- logImpl.info(language === "zh" ? "安装已取消" : "Installation cancelled");
149
- exitImpl(0);
150
- return { action, continueInstall: false };
151
- }
152
-
153
- if (action === "reconfigure") {
154
- logImpl.info(
155
- language === "zh"
156
- ? "重新配置模式:将重新提示插件选择和 API key 配置"
157
- : "Reconfigure mode: will re-prompt for plugin selection and API key configuration"
158
- );
159
- }
160
-
161
- return { action, continueInstall: true };
162
- }
163
-
164
- export async function runRecommendedPluginsStep(
165
- { noDeps, all, yes, language },
166
- {
167
- logImpl = log,
168
- installRecommendedPluginsImpl = installRecommendedPlugins,
169
- printNextStepsImpl = printNextSteps,
170
- } = {}
171
- ) {
172
- if (noDeps) {
173
- logImpl.blank();
174
- logImpl.step(4, INSTALL_STEP_COUNT, "Recommended plugins");
175
- logImpl.info("Skipping recommended plugins (--no-deps)");
176
- printNextStepsImpl();
177
- return false;
178
- }
179
-
180
- const installedRecommended = await installRecommendedPluginsImpl({ all, yes, language });
181
- if (!installedRecommended) {
182
- printNextStepsImpl();
183
- return false;
184
- }
185
-
186
- return true;
187
- }
188
-
189
- export function injectGlobalProtocolsStep(
190
- { logImpl = log, injectGlobalProtocolsImpl = injectGlobalProtocols } = {}
191
- ) {
192
- logImpl.blank();
193
- logImpl.step(5, INSTALL_STEP_COUNT, "Injecting global protocols into ~/.claude/CLAUDE.md...");
194
-
195
- try {
196
- const result = injectGlobalProtocolsImpl();
197
- if (result.action === "created") {
198
- logImpl.ok(`Global protocols injected ${color.dim(`(${GLOBAL_CLAUDE_MD})`)}`);
199
- } else if (result.action === "appended") {
200
- logImpl.ok(`Global protocols appended ${color.dim(`(${GLOBAL_CLAUDE_MD})`)}`);
201
- } else if (result.action === "upgraded") {
202
- logImpl.ok(`Global protocols upgraded ${color.dim(`(${GLOBAL_CLAUDE_MD})`)}`);
203
- } else {
204
- logImpl.info(`Global protocols up to date ${color.dim(`(${GLOBAL_CLAUDE_MD})`)}`);
205
- }
206
- } catch (err) {
207
- logImpl.warn(`Protocol injection failed: ${err.message} ${color.dim("(non-blocking)")}`);
208
- }
209
- }
package/cli/install.js DELETED
@@ -1,101 +0,0 @@
1
- /**
2
- * install command — install curdx-flow plugin + optional recommended plugins.
3
- */
4
-
5
- import {
6
- addRequiredPluginMarketplaces,
7
- installRequiredPlugins,
8
- registerBundledMcps,
9
- } from "./install-companions.js";
10
- import {
11
- addCurdxMarketplace,
12
- installCurdxFlowPlugin,
13
- } from "./install-curdx-plugin.js";
14
- import { resolveInstallLanguage } from "./install-language.js";
15
- import { printNextSteps } from "./install-next-steps.js";
16
- import { readShippedVersion } from "./install-paths.js";
17
- import {
18
- createInstallContext,
19
- ensureClaudeCliAvailable,
20
- injectGlobalProtocolsStep,
21
- maybeRestartWithUpdatedCli,
22
- renderInstallIntro,
23
- resolveExistingInstallationAction,
24
- runRecommendedPluginsStep,
25
- snapshotCurdxFlowInstall,
26
- } from "./install-workflow.js";
27
-
28
- export async function install(args = []) {
29
- const context = createInstallContext(args);
30
-
31
- if (await maybeRestartWithUpdatedCli(context)) {
32
- return;
33
- }
34
-
35
- await renderInstallIntro(context);
36
-
37
- // ---------- Step 0: Language selection ----------
38
- const { language, config } = await resolveInstallLanguage({ yes: context.yes });
39
-
40
- // ---------- Step 1: Check claude CLI ----------
41
- ensureClaudeCliAvailable();
42
-
43
- // Snapshot curdx-flow's pre-install version BEFORE Step 2 touches the
44
- // marketplace. Step 2 does `claude plugin marketplace remove` + `add` to
45
- // rebind to the current source, and the remove side-effect also drops
46
- // any plugins installed from that marketplace. If we only call
47
- // listPlugins() in Step 3, curdx-flow is already gone from the list and
48
- // we can't tell a fresh install apart from an upgrade — the Step 3
49
- // output then incorrectly says "installed" for both cases.
50
- const prevCurdxFlow = snapshotCurdxFlowInstall();
51
-
52
- // ---------- Step 1.5: Existing installation action menu ----------
53
- const existingInstall = await resolveExistingInstallationAction({
54
- prevCurdxFlow,
55
- yes: context.yes,
56
- language,
57
- });
58
- if (!existingInstall.continueInstall) {
59
- return;
60
- }
61
-
62
- await addCurdxMarketplace(context);
63
-
64
- // Claude Code resolves plugin dependencies during install. Register
65
- // required companion marketplaces before installing curdx-flow so its
66
- // cross-marketplace dependency on Context7 can be satisfied immediately.
67
- await addRequiredPluginMarketplaces({ logWarnings: false });
68
-
69
- // ---------- Step 3: Install curdx-flow plugin ----------
70
- // Read the version the marketplace is shipping so we can decide whether an
71
- // already-installed plugin needs an update (same name but stale version
72
- // previously silently skipped the upgrade — caused the beta.1 → beta.7 drift).
73
- const shippedVersion = readShippedVersion();
74
- await installCurdxFlowPlugin({ prevCurdxFlow, shippedVersion });
75
-
76
- // ---------- Step 3.5: Install required plugins + register user-level MCPs ----------
77
- await installRequiredPlugins({
78
- yes: context.yes,
79
- language,
80
- config,
81
- skipMarketplaceAdd: true,
82
- });
83
-
84
- // Beta.12: direct MCPs migrated from plugin.json bundling. See cli/registry.js
85
- // for the rationale. Context7 now uses Upstash's official plugin instead.
86
- await registerBundledMcps();
87
-
88
- // ---------- Step 4: Recommended plugins ----------
89
- const installedRecommended = await runRecommendedPluginsStep({
90
- noDeps: context.noDeps,
91
- all: context.all,
92
- yes: context.yes,
93
- language,
94
- });
95
- if (!installedRecommended) {
96
- return;
97
- }
98
-
99
- injectGlobalProtocolsStep();
100
- printNextSteps();
101
- }
@@ -1,41 +0,0 @@
1
- export function pluginMarketplaceAddArgs({ scope, marketplaceSource }) {
2
- return ["plugin", "marketplace", "add", "--scope", scope, marketplaceSource];
3
- }
4
-
5
- export function pluginMarketplaceUpdateArgs(marketplaceId) {
6
- return ["plugin", "marketplace", "update", marketplaceId];
7
- }
8
-
9
- export function pluginMarketplaceRemoveArgs(marketplaceId) {
10
- return ["plugin", "marketplace", "remove", marketplaceId];
11
- }
12
-
13
- export function pluginInstallArgs({ scope, installSpec }) {
14
- return ["plugin", "install", "--scope", scope, installSpec];
15
- }
16
-
17
- export function pluginUpdateArgs({ scope = "user", spec }) {
18
- return ["plugin", "update", "--scope", scope, spec];
19
- }
20
-
21
- export function pluginUninstallArgs({ scope, uninstallSpec, uninstallArgs = [] }) {
22
- return ["plugin", "uninstall", "--scope", scope, ...uninstallArgs, uninstallSpec];
23
- }
24
-
25
- export function mcpAddArgs({ scope = "user", name, command, args = [], env = [] }) {
26
- return [
27
- "mcp",
28
- "add",
29
- "--scope",
30
- scope,
31
- name,
32
- ...env.flatMap((value) => ["--env", value]),
33
- "--",
34
- command,
35
- ...args,
36
- ];
37
- }
38
-
39
- export function mcpRemoveArgs({ scope = "user", name }) {
40
- return ["mcp", "remove", "--scope", scope, name];
41
- }
@@ -1,47 +0,0 @@
1
- import { run } from "./process.js";
2
- import {
3
- mcpAddArgs,
4
- mcpRemoveArgs,
5
- pluginInstallArgs,
6
- pluginMarketplaceAddArgs,
7
- pluginMarketplaceRemoveArgs,
8
- pluginMarketplaceUpdateArgs,
9
- pluginUninstallArgs,
10
- pluginUpdateArgs,
11
- } from "./claude-commands.js";
12
-
13
- async function runClaude(args, { runner = run, silent = true } = {}) {
14
- return runner("claude", args, { silent });
15
- }
16
-
17
- export async function addPluginMarketplace(entry, options) {
18
- return runClaude(pluginMarketplaceAddArgs(entry), options);
19
- }
20
-
21
- export async function updatePluginMarketplace(marketplaceId, options) {
22
- return runClaude(pluginMarketplaceUpdateArgs(marketplaceId), options);
23
- }
24
-
25
- export async function removePluginMarketplace(marketplaceId, options) {
26
- return runClaude(pluginMarketplaceRemoveArgs(marketplaceId), options);
27
- }
28
-
29
- export async function installPlugin(entry, options) {
30
- return runClaude(pluginInstallArgs(entry), options);
31
- }
32
-
33
- export async function updatePlugin(spec, options) {
34
- return runClaude(pluginUpdateArgs({ spec }), options);
35
- }
36
-
37
- export async function uninstallPlugin(entry, options) {
38
- return runClaude(pluginUninstallArgs(entry), options);
39
- }
40
-
41
- export async function addMcp(entry, options) {
42
- return runClaude(mcpAddArgs(entry), options);
43
- }
44
-
45
- export async function removeMcp(entry, options) {
46
- return runClaude(mcpRemoveArgs(entry), options);
47
- }
package/cli/lib/claude.js DELETED
@@ -1,183 +0,0 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
-
5
- import { has, runSync } from "./process.js";
6
-
7
- const HOME = homedir();
8
-
9
- export function claudeVersion() {
10
- if (!has("claude")) return null;
11
- const res = runSync("claude", ["--version"]);
12
- if (res.code !== 0) return null;
13
- const m = res.stdout.match(/(\d+\.\d+\.\d+)/);
14
- return m ? m[1] : res.stdout.trim().split("\n")[0];
15
- }
16
-
17
- function normalizePluginError(error) {
18
- if (typeof error === "string") {
19
- return error;
20
- }
21
- if (error && typeof error === "object") {
22
- return error.message || error.code || JSON.stringify(error);
23
- }
24
- return String(error);
25
- }
26
-
27
- export function parsePluginListJson(output) {
28
- const trimmed = String(output || "").trim();
29
- if (!trimmed.startsWith("[")) {
30
- return null;
31
- }
32
-
33
- const arr = JSON.parse(trimmed);
34
- return arr.map((p) => {
35
- const id = String(p.id || p.name || "");
36
- const errors = Array.isArray(p.errors)
37
- ? p.errors.map(normalizePluginError).filter(Boolean)
38
- : [];
39
- const enabled = p.enabled !== false;
40
-
41
- return {
42
- id,
43
- name: id.split("@")[0],
44
- marketplaceId: id.split("@")[1] || undefined,
45
- version: p.version,
46
- status: errors.length > 0 ? "failed" : enabled ? "enabled" : "disabled",
47
- scope: p.scope,
48
- errors,
49
- raw: JSON.stringify(p),
50
- };
51
- });
52
- }
53
-
54
- export function listPlugins() {
55
- const j = runSync("claude", ["plugin", "list", "--json"]);
56
- if (j.code === 0) {
57
- try {
58
- const plugins = parsePluginListJson(j.stdout);
59
- if (plugins) {
60
- return plugins;
61
- }
62
- } catch {
63
- // JSON parse failed; fall through to legacy text parser.
64
- }
65
- }
66
-
67
- const res = runSync("claude", ["plugin", "list"]);
68
- if (res.code !== 0) return [];
69
- const plugins = [];
70
- const blocks = res.stdout.split(/\n\s*❯\s*/).slice(1);
71
- for (const block of blocks) {
72
- const lines = block.split("\n");
73
- const id = lines[0].trim();
74
- const name = id.split("@")[0];
75
- const version = (block.match(/Version:\s*(\S+)/) || [])[1];
76
- const status = block.includes("✔")
77
- ? "enabled"
78
- : block.includes("✘")
79
- ? "failed"
80
- : "unknown";
81
- plugins.push({
82
- id,
83
- name,
84
- marketplaceId: id.split("@")[1],
85
- version,
86
- status,
87
- raw: block,
88
- });
89
- }
90
- return plugins;
91
- }
92
-
93
- export function listPluginMarketplaces() {
94
- const j = runSync("claude", ["plugin", "marketplace", "list", "--json"]);
95
- if (j.code === 0 && j.stdout.trim().startsWith("[")) {
96
- try {
97
- return JSON.parse(j.stdout);
98
- } catch {
99
- return [];
100
- }
101
- }
102
- return [];
103
- }
104
-
105
- export function findPluginByRegistryEntry(plugins, registryEntry) {
106
- return plugins.find(
107
- (plugin) => plugin.id === registryEntry.id || plugin.name === registryEntry.name
108
- );
109
- }
110
-
111
- export function hasMarketplace(marketplaces, registryEntry) {
112
- if (!registryEntry.marketplaceSource) return true;
113
- return marketplaces.some((marketplace) => marketplace.name === registryEntry.marketplaceId);
114
- }
115
-
116
- export function readUserMcpConfig() {
117
- try {
118
- const path = join(HOME, ".claude.json");
119
- if (!existsSync(path)) return new Map();
120
- const cfg = JSON.parse(readFileSync(path, "utf-8"));
121
- const servers = cfg?.mcpServers || {};
122
- return new Map(Object.entries(servers));
123
- } catch {
124
- return new Map();
125
- }
126
- }
127
-
128
- export function findDuplicateMcps(mcps, userConfig) {
129
- const duplicates = [];
130
- for (const m of mcps) {
131
- if (m.plugin && userConfig.has(m.name)) {
132
- duplicates.push({
133
- name: m.name,
134
- userConfig: userConfig.get(m.name),
135
- pluginEntry: m,
136
- });
137
- }
138
- }
139
- return duplicates;
140
- }
141
-
142
- export function listMcps() {
143
- const res = runSync("claude", ["mcp", "list"]);
144
- if (res.code !== 0) return [];
145
- return parseMcpList(res.stdout);
146
- }
147
-
148
- export function parseMcpList(output) {
149
- const mcps = [];
150
- for (const raw of output.split("\n")) {
151
- const line = raw.trimEnd();
152
- if (!line) continue;
153
- if (line.startsWith("Checking") || line.startsWith("checking")) continue;
154
-
155
- const statusSplit = line.lastIndexOf(" - ");
156
- if (statusSplit === -1) continue;
157
- const statusRaw = line.slice(statusSplit + 3).trim();
158
- const beforeStatus = line.slice(0, statusSplit);
159
- const nameSplit = beforeStatus.indexOf(": ");
160
- if (nameSplit === -1) continue;
161
- const fullName = beforeStatus.slice(0, nameSplit).trim();
162
- const command = beforeStatus.slice(nameSplit + 2).trim();
163
-
164
- let plugin = null;
165
- let name = fullName;
166
- if (fullName.startsWith("plugin:")) {
167
- const parts = fullName.split(":");
168
- if (parts.length >= 3) {
169
- plugin = parts[1];
170
- name = parts.slice(2).join(":");
171
- }
172
- }
173
-
174
- const status = /Connected|✓/.test(statusRaw)
175
- ? "connected"
176
- : /Failed|✗/.test(statusRaw)
177
- ? "failed"
178
- : "unknown";
179
-
180
- mcps.push({ name, plugin, fullName, status, command });
181
- }
182
- return mcps;
183
- }
package/cli/lib/config.js DELETED
@@ -1,24 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
-
5
- const CONFIG_DIR = join(homedir(), ".claude");
6
- export const CONFIG_FILE = join(CONFIG_DIR, "curdx-flow-config.json");
7
-
8
- export function readConfig() {
9
- if (!existsSync(CONFIG_FILE)) {
10
- return {};
11
- }
12
- try {
13
- return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
14
- } catch {
15
- return {};
16
- }
17
- }
18
-
19
- export function writeConfig(config) {
20
- if (!existsSync(CONFIG_DIR)) {
21
- mkdirSync(CONFIG_DIR, { recursive: true });
22
- }
23
- writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), "utf-8");
24
- }