@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.
- package/CHANGELOG.md +21 -34
- package/LICENSE +1 -1
- package/README.md +28 -79
- package/dist/index.mjs +995 -0
- package/package.json +33 -42
- package/.claude-plugin/marketplace.json +0 -48
- package/.claude-plugin/plugin.json +0 -70
- package/agent-preamble/preamble.md +0 -314
- package/agents/flow-adversary.md +0 -202
- package/agents/flow-architect.md +0 -197
- package/agents/flow-brownfield-analyst.md +0 -142
- package/agents/flow-debugger.md +0 -321
- package/agents/flow-edge-hunter.md +0 -288
- package/agents/flow-executor.md +0 -269
- package/agents/flow-orchestrator.md +0 -145
- package/agents/flow-planner.md +0 -246
- package/agents/flow-product-designer.md +0 -159
- package/agents/flow-qa-engineer.md +0 -282
- package/agents/flow-researcher.md +0 -165
- package/agents/flow-reviewer.md +0 -303
- package/agents/flow-security-auditor.md +0 -401
- package/agents/flow-triage-analyst.md +0 -272
- package/agents/flow-ui-researcher.md +0 -229
- package/agents/flow-ux-designer.md +0 -221
- package/agents/flow-verifier.md +0 -349
- package/bin/curdx-flow +0 -5
- package/bin/curdx-flow.js +0 -54
- package/cli/README.md +0 -104
- package/cli/doctor-workflow.js +0 -483
- package/cli/doctor.js +0 -73
- package/cli/help.js +0 -59
- package/cli/install-bundled-mcps.js +0 -37
- package/cli/install-companions.js +0 -19
- package/cli/install-context7-config.js +0 -80
- package/cli/install-curdx-plugin.js +0 -96
- package/cli/install-language.js +0 -35
- package/cli/install-next-steps.js +0 -29
- package/cli/install-options.js +0 -9
- package/cli/install-paths.js +0 -52
- package/cli/install-recommended-plugins.js +0 -104
- package/cli/install-required-plugins.js +0 -57
- package/cli/install-self-update.js +0 -62
- package/cli/install-workflow.js +0 -209
- package/cli/install.js +0 -101
- package/cli/lib/claude-commands.js +0 -41
- package/cli/lib/claude-ops.js +0 -47
- package/cli/lib/claude.js +0 -183
- package/cli/lib/config.js +0 -24
- package/cli/lib/doctor-claude-settings.js +0 -1186
- package/cli/lib/doctor-report.js +0 -978
- package/cli/lib/doctor-runtime-environment.js +0 -196
- package/cli/lib/frontmatter.js +0 -44
- package/cli/lib/json-schema.js +0 -57
- package/cli/lib/logging.js +0 -25
- package/cli/lib/process.js +0 -60
- package/cli/lib/prompts.js +0 -135
- package/cli/lib/runtime.js +0 -107
- package/cli/lib/semver.js +0 -109
- package/cli/lib/version.js +0 -12
- package/cli/protocols-body.md +0 -22
- package/cli/protocols.js +0 -162
- package/cli/registry.js +0 -123
- package/cli/router.js +0 -49
- package/cli/uninstall-actions.js +0 -360
- package/cli/uninstall-workflow.js +0 -146
- package/cli/uninstall.js +0 -42
- package/cli/upgrade-workflow.js +0 -80
- package/cli/upgrade.js +0 -91
- package/cli/utils.js +0 -40
- package/gates/adversarial-review-gate.md +0 -219
- package/gates/coverage-audit-gate.md +0 -182
- package/gates/devex-gate.md +0 -254
- package/gates/edge-case-gate.md +0 -194
- package/gates/karpathy-gate.md +0 -130
- package/gates/security-gate.md +0 -218
- package/gates/tdd-gate.md +0 -182
- package/gates/test-quality-gate.md +0 -59
- package/gates/verification-gate.md +0 -179
- package/hooks/hooks.json +0 -58
- package/hooks/scripts/common.sh +0 -46
- package/hooks/scripts/inject-karpathy.sh +0 -53
- package/hooks/scripts/quick-mode-guard.sh +0 -68
- package/hooks/scripts/session-start.sh +0 -90
- package/hooks/scripts/stop-watcher.sh +0 -230
- package/hooks/scripts/subagent-artifact-guard.sh +0 -159
- package/hooks/scripts/subagent-statusline.sh +0 -105
- package/knowledge/artifact-output-discipline.md +0 -24
- package/knowledge/artifact-summary-contracts.md +0 -50
- package/knowledge/atomic-commits.md +0 -262
- package/knowledge/claude-code-runtime-contracts.md +0 -219
- package/knowledge/epic-decomposition.md +0 -307
- package/knowledge/execution-strategies.md +0 -303
- package/knowledge/karpathy-guidelines.md +0 -219
- package/knowledge/planning-reviews.md +0 -211
- package/knowledge/poc-first-workflow.md +0 -223
- package/knowledge/review-feedback-intake.md +0 -57
- package/knowledge/spec-driven-development.md +0 -180
- package/knowledge/systematic-debugging.md +0 -378
- package/knowledge/two-stage-review.md +0 -249
- package/knowledge/wave-execution.md +0 -403
- package/monitors/monitors.json +0 -8
- package/monitors/scripts/flow-state-monitor.sh +0 -99
- package/output-styles/curdx-evidence-first.md +0 -34
- package/schemas/agent-frontmatter.schema.json +0 -63
- package/schemas/config.schema.json +0 -134
- package/schemas/gate-frontmatter.schema.json +0 -30
- package/schemas/hooks.schema.json +0 -115
- package/schemas/output-style-frontmatter.schema.json +0 -22
- package/schemas/plugin-manifest.schema.json +0 -436
- package/schemas/plugin-settings.schema.json +0 -29
- package/schemas/skill-frontmatter.schema.json +0 -177
- package/schemas/spec-frontmatter.schema.json +0 -42
- package/schemas/spec-state.schema.json +0 -147
- package/settings.json +0 -7
- package/skills/brownfield-index/SKILL.md +0 -53
- package/skills/brownfield-index/references/applicability.md +0 -12
- package/skills/brownfield-index/references/handoff.md +0 -8
- package/skills/brownfield-index/references/index-contract.md +0 -10
- package/skills/browser-qa/SKILL.md +0 -39
- package/skills/browser-qa/references/handoff.md +0 -6
- package/skills/browser-qa/references/prerequisites.md +0 -10
- package/skills/browser-qa/references/qa-contract.md +0 -20
- package/skills/cancel/SKILL.md +0 -41
- package/skills/cancel/references/destructive-mode.md +0 -17
- package/skills/cancel/references/reporting.md +0 -18
- package/skills/cancel/references/state-recovery.md +0 -30
- package/skills/cancel/references/target-resolution.md +0 -7
- package/skills/debug/SKILL.md +0 -45
- package/skills/debug/references/context-gathering.md +0 -11
- package/skills/debug/references/failure-guard.md +0 -25
- package/skills/debug/references/intake.md +0 -12
- package/skills/debug/references/phase-workflow.md +0 -34
- package/skills/debug/references/reporting.md +0 -20
- package/skills/epic/SKILL.md +0 -39
- package/skills/epic/references/epic-artifacts.md +0 -20
- package/skills/epic/references/epic-intake.md +0 -9
- package/skills/epic/references/slice-handoff.md +0 -16
- package/skills/fast/SKILL.md +0 -62
- package/skills/fast/references/applicability.md +0 -25
- package/skills/fast/references/clarification.md +0 -20
- package/skills/fast/references/execution-contract.md +0 -56
- package/skills/help/SKILL.md +0 -55
- package/skills/help/references/dispatch.md +0 -20
- package/skills/help/references/overview.md +0 -39
- package/skills/help/references/troubleshoot.md +0 -47
- package/skills/help/references/workflow.md +0 -37
- package/skills/implement/SKILL.md +0 -96
- package/skills/implement/references/error-recovery.md +0 -36
- package/skills/implement/references/linear-execution.md +0 -32
- package/skills/implement/references/preflight.md +0 -43
- package/skills/implement/references/progress-contract.md +0 -32
- package/skills/implement/references/state-init.md +0 -33
- package/skills/implement/references/stop-hook-execution.md +0 -36
- package/skills/implement/references/strategy-router.md +0 -38
- package/skills/implement/references/subagent-execution.md +0 -43
- package/skills/implement/references/wave-execution.md +0 -162
- package/skills/init/SKILL.md +0 -49
- package/skills/init/references/gitignore-and-health.md +0 -26
- package/skills/init/references/next-steps.md +0 -22
- package/skills/init/references/preflight.md +0 -15
- package/skills/init/references/scaffold-contract.md +0 -27
- package/skills/review/SKILL.md +0 -82
- package/skills/review/references/optional-passes.md +0 -48
- package/skills/review/references/preflight.md +0 -38
- package/skills/review/references/report-contract.md +0 -49
- package/skills/review/references/reporting.md +0 -20
- package/skills/review/references/stage-execution.md +0 -32
- package/skills/security-audit/SKILL.md +0 -47
- package/skills/security-audit/references/audit-contract.md +0 -21
- package/skills/security-audit/references/gate-handoff.md +0 -8
- package/skills/security-audit/references/scope-and-depth.md +0 -9
- package/skills/spec/SKILL.md +0 -100
- package/skills/spec/references/artifact-landing.md +0 -31
- package/skills/spec/references/phase-execution.md +0 -50
- package/skills/spec/references/planning-review.md +0 -31
- package/skills/spec/references/preflight-and-routing.md +0 -46
- package/skills/spec/references/reporting.md +0 -21
- package/skills/start/SKILL.md +0 -84
- package/skills/start/references/branch-routing.md +0 -51
- package/skills/start/references/mode-semantics.md +0 -12
- package/skills/start/references/preflight.md +0 -13
- package/skills/start/references/reporting.md +0 -20
- package/skills/start/references/state-seeding.md +0 -44
- package/skills/start/references/workflow-handoff.md +0 -26
- package/skills/status/SKILL.md +0 -41
- package/skills/status/references/gather-contract.md +0 -27
- package/skills/status/references/health-rules.md +0 -27
- package/skills/status/references/output-contract.md +0 -24
- package/skills/status/references/preflight.md +0 -10
- package/skills/status/references/recovery-hints.md +0 -18
- package/skills/ui-sketch/SKILL.md +0 -39
- package/skills/ui-sketch/references/brief-intake.md +0 -10
- package/skills/ui-sketch/references/iteration-handoff.md +0 -5
- package/skills/ui-sketch/references/variant-contract.md +0 -15
- package/skills/verify/SKILL.md +0 -56
- package/skills/verify/references/evidence-workflow.md +0 -39
- package/skills/verify/references/output-contract.md +0 -23
- package/skills/verify/references/preflight.md +0 -11
- package/skills/verify/references/report-handoff.md +0 -35
- package/skills/verify/references/strict-mode.md +0 -12
- package/templates/CONTEXT.md.tmpl +0 -53
- package/templates/PROJECT.md.tmpl +0 -59
- package/templates/ROADMAP.md.tmpl +0 -50
- package/templates/STATE.md.tmpl +0 -49
- package/templates/config.json.tmpl +0 -51
- package/templates/design.md.tmpl +0 -83
- package/templates/progress.md.tmpl +0 -77
- package/templates/requirements.md.tmpl +0 -76
- package/templates/research.md.tmpl +0 -83
- package/templates/tasks.md.tmpl +0 -107
package/cli/install-workflow.js
DELETED
|
@@ -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
|
-
}
|
package/cli/lib/claude-ops.js
DELETED
|
@@ -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
|
-
}
|