@benbenwu/zcf 3.6.4
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/LICENSE +21 -0
- package/README.md +193 -0
- package/bin/zcf.mjs +2 -0
- package/dist/chunks/api-providers.mjs +137 -0
- package/dist/chunks/claude-code-config-manager.mjs +731 -0
- package/dist/chunks/claude-code-incremental-manager.mjs +601 -0
- package/dist/chunks/codex-config-switch.mjs +394 -0
- package/dist/chunks/codex-provider-manager.mjs +197 -0
- package/dist/chunks/codex-uninstaller.mjs +422 -0
- package/dist/chunks/commands.mjs +118 -0
- package/dist/chunks/features.mjs +632 -0
- package/dist/chunks/simple-config.mjs +7904 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.mjs +2013 -0
- package/dist/i18n/locales/en/api.json +53 -0
- package/dist/i18n/locales/en/ccr.json +65 -0
- package/dist/i18n/locales/en/cli.json +55 -0
- package/dist/i18n/locales/en/codex.json +123 -0
- package/dist/i18n/locales/en/cometix.json +29 -0
- package/dist/i18n/locales/en/common.json +20 -0
- package/dist/i18n/locales/en/configuration.json +85 -0
- package/dist/i18n/locales/en/errors.json +26 -0
- package/dist/i18n/locales/en/installation.json +80 -0
- package/dist/i18n/locales/en/language.json +19 -0
- package/dist/i18n/locales/en/mcp.json +24 -0
- package/dist/i18n/locales/en/menu.json +51 -0
- package/dist/i18n/locales/en/multi-config.json +79 -0
- package/dist/i18n/locales/en/tools.json +15 -0
- package/dist/i18n/locales/en/uninstall.json +56 -0
- package/dist/i18n/locales/en/updater.json +25 -0
- package/dist/i18n/locales/en/workflow.json +23 -0
- package/dist/i18n/locales/zh-CN/api.json +53 -0
- package/dist/i18n/locales/zh-CN/ccr.json +65 -0
- package/dist/i18n/locales/zh-CN/cli.json +55 -0
- package/dist/i18n/locales/zh-CN/codex.json +123 -0
- package/dist/i18n/locales/zh-CN/cometix.json +29 -0
- package/dist/i18n/locales/zh-CN/common.json +20 -0
- package/dist/i18n/locales/zh-CN/configuration.json +85 -0
- package/dist/i18n/locales/zh-CN/errors.json +26 -0
- package/dist/i18n/locales/zh-CN/installation.json +80 -0
- package/dist/i18n/locales/zh-CN/language.json +19 -0
- package/dist/i18n/locales/zh-CN/mcp.json +24 -0
- package/dist/i18n/locales/zh-CN/menu.json +51 -0
- package/dist/i18n/locales/zh-CN/multi-config.json +79 -0
- package/dist/i18n/locales/zh-CN/tools.json +15 -0
- package/dist/i18n/locales/zh-CN/uninstall.json +56 -0
- package/dist/i18n/locales/zh-CN/updater.json +25 -0
- package/dist/i18n/locales/zh-CN/workflow.json +23 -0
- package/dist/index.d.mts +324 -0
- package/dist/index.d.ts +324 -0
- package/dist/index.mjs +19 -0
- package/dist/shared/zcf.DGjQxTq_.mjs +34 -0
- package/package.json +117 -0
- package/templates/CLAUDE.md +221 -0
- package/templates/claude-code/CLAUDE.md +250 -0
- package/templates/claude-code/common/settings.json +48 -0
- package/templates/claude-code/en/workflow/bmad/commands/bmad-init.md +275 -0
- package/templates/claude-code/en/workflow/common/agents/get-current-datetime.md +29 -0
- package/templates/claude-code/en/workflow/common/agents/init-architect.md +114 -0
- package/templates/claude-code/en/workflow/common/commands/init-project.md +53 -0
- package/templates/claude-code/en/workflow/plan/agents/planner.md +116 -0
- package/templates/claude-code/en/workflow/plan/agents/ui-ux-designer.md +91 -0
- package/templates/claude-code/en/workflow/plan/commands/feat.md +105 -0
- package/templates/claude-code/zh-CN/workflow/bmad/commands/bmad-init.md +275 -0
- package/templates/claude-code/zh-CN/workflow/common/agents/get-current-datetime.md +29 -0
- package/templates/claude-code/zh-CN/workflow/common/agents/init-architect.md +114 -0
- package/templates/claude-code/zh-CN/workflow/common/commands/init-project.md +53 -0
- package/templates/claude-code/zh-CN/workflow/plan/agents/planner.md +116 -0
- package/templates/claude-code/zh-CN/workflow/plan/agents/ui-ux-designer.md +91 -0
- package/templates/claude-code/zh-CN/workflow/plan/commands/feat.md +105 -0
- package/templates/codex/common/config.toml +0 -0
- package/templates/common/output-styles/en/engineer-professional.md +88 -0
- package/templates/common/output-styles/en/laowang-engineer.md +127 -0
- package/templates/common/output-styles/en/leibus-engineer.md +251 -0
- package/templates/common/output-styles/en/nekomata-engineer.md +120 -0
- package/templates/common/output-styles/en/ojousama-engineer.md +121 -0
- package/templates/common/output-styles/en/rem-engineer.md +173 -0
- package/templates/common/output-styles/zh-CN/engineer-professional.md +89 -0
- package/templates/common/output-styles/zh-CN/laowang-engineer.md +127 -0
- package/templates/common/output-styles/zh-CN/leibus-engineer.md +251 -0
- package/templates/common/output-styles/zh-CN/nekomata-engineer.md +120 -0
- package/templates/common/output-styles/zh-CN/ojousama-engineer.md +121 -0
- package/templates/common/output-styles/zh-CN/rem-engineer.md +179 -0
- package/templates/common/workflow/git/en/git-cleanBranches.md +102 -0
- package/templates/common/workflow/git/en/git-commit.md +205 -0
- package/templates/common/workflow/git/en/git-rollback.md +90 -0
- package/templates/common/workflow/git/en/git-worktree.md +276 -0
- package/templates/common/workflow/git/zh-CN/git-cleanBranches.md +102 -0
- package/templates/common/workflow/git/zh-CN/git-commit.md +205 -0
- package/templates/common/workflow/git/zh-CN/git-rollback.md +90 -0
- package/templates/common/workflow/git/zh-CN/git-worktree.md +276 -0
- package/templates/common/workflow/sixStep/en/workflow.md +251 -0
- package/templates/common/workflow/sixStep/zh-CN/workflow.md +215 -0
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,2013 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import cac from 'cac';
|
|
3
|
+
import ansis from 'ansis';
|
|
4
|
+
import { an as ensureI18nInitialized, ao as i18n, aQ as readCcrConfig, aL as isCcrInstalled, aM as installCcr, aR as configureCcrFeature, ar as promptBoolean, aS as handleExitPromptError, aT as handleGeneralError, aU as COMETIX_COMMAND_NAME, aV as COMETIX_COMMANDS, aW as installCometixLine, ap as addNumbersToChoices, aX as checkAndUpdateTools, aY as runCodexUpdate, aZ as resolveCodeType$1, aw as readJsonConfig, a_ as writeJsonConfig, t as ZCF_CONFIG_FILE, aG as readZcfConfig, D as DEFAULT_CODE_TOOL_TYPE, x as isCodeToolType, a$ as displayBanner, aE as updateZcfConfig, b0 as version, b1 as resolveAiOutputLanguage, b2 as updatePromptOnly, b3 as selectAndInstallWorkflows, b4 as checkClaudeCodeVersionAndPrompt, z as resolveCodeToolType$1, b5 as displayBannerWithInfo, v as CODE_TOOL_BANNERS, b6 as runCodexUninstall, b7 as configureCodexMcp, b8 as configureCodexApi, b9 as runCodexWorkflowImportWithLanguageSelection, ba as runCodexFullInit, i as init, bb as switchCodexProvider, bc as listCodexProviders, aB as readCodexConfig, bd as switchToOfficialLogin, be as switchToProvider, bf as readZcfConfigAsync, bg as initI18n, bh as selectScriptLanguage, aF as changeLanguage } from './chunks/simple-config.mjs';
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
|
+
import { join } from 'pathe';
|
|
9
|
+
import { runCcrStop, runCcrStart, runCcrRestart, runCcrStatus, runCcrUi } from './chunks/commands.mjs';
|
|
10
|
+
import { changeScriptLanguageFeature, configureCodexAiMemoryFeature, configureCodexDefaultModelFeature, configureEnvPermissionFeature, configureAiMemoryFeature, configureDefaultModelFeature, configureMcpFeature, configureApiFeature } from './chunks/features.mjs';
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
import { x, exec as exec$1 } from 'tinyexec';
|
|
13
|
+
import { exec, spawn } from 'node:child_process';
|
|
14
|
+
import { promisify } from 'node:util';
|
|
15
|
+
import { pathExists } from 'fs-extra';
|
|
16
|
+
import { m as moveToTrash } from './shared/zcf.DGjQxTq_.mjs';
|
|
17
|
+
import { ClaudeCodeConfigManager } from './chunks/claude-code-config-manager.mjs';
|
|
18
|
+
import 'dayjs';
|
|
19
|
+
import 'node:url';
|
|
20
|
+
import 'inquirer-toggle';
|
|
21
|
+
import 'ora';
|
|
22
|
+
import 'semver';
|
|
23
|
+
import '@rainbowatcher/toml-edit-js';
|
|
24
|
+
import 'node:fs/promises';
|
|
25
|
+
import 'i18next';
|
|
26
|
+
import 'i18next-fs-backend';
|
|
27
|
+
import 'trash';
|
|
28
|
+
|
|
29
|
+
function isCcrConfigured() {
|
|
30
|
+
const CCR_CONFIG_FILE = join(homedir(), ".claude-code-router", "config.json");
|
|
31
|
+
if (!existsSync(CCR_CONFIG_FILE)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const config = readCcrConfig();
|
|
35
|
+
return config !== null;
|
|
36
|
+
}
|
|
37
|
+
async function showCcrMenu() {
|
|
38
|
+
try {
|
|
39
|
+
ensureI18nInitialized();
|
|
40
|
+
console.log(`
|
|
41
|
+
${ansis.cyan("\u2550".repeat(50))}`);
|
|
42
|
+
console.log(ansis.bold.cyan(` ${i18n.t("ccr:ccrMenuTitle")}`));
|
|
43
|
+
console.log(`${ansis.cyan("\u2550".repeat(50))}
|
|
44
|
+
`);
|
|
45
|
+
console.log(` ${ansis.cyan("1.")} ${i18n.t("ccr:ccrMenuOptions.initCcr")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.initCcr")}`)}`);
|
|
46
|
+
console.log(` ${ansis.cyan("2.")} ${i18n.t("ccr:ccrMenuOptions.startUi")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.startUi")}`)}`);
|
|
47
|
+
console.log(` ${ansis.cyan("3.")} ${i18n.t("ccr:ccrMenuOptions.checkStatus")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.checkStatus")}`)}`);
|
|
48
|
+
console.log(` ${ansis.cyan("4.")} ${i18n.t("ccr:ccrMenuOptions.restart")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.restart")}`)}`);
|
|
49
|
+
console.log(` ${ansis.cyan("5.")} ${i18n.t("ccr:ccrMenuOptions.start")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.start")}`)}`);
|
|
50
|
+
console.log(` ${ansis.cyan("6.")} ${i18n.t("ccr:ccrMenuOptions.stop")} ${ansis.gray(`- ${i18n.t("ccr:ccrMenuDescriptions.stop")}`)}`);
|
|
51
|
+
console.log(` ${ansis.yellow("0.")} ${i18n.t("ccr:ccrMenuOptions.back")}`);
|
|
52
|
+
console.log("");
|
|
53
|
+
const { choice } = await inquirer.prompt({
|
|
54
|
+
type: "input",
|
|
55
|
+
name: "choice",
|
|
56
|
+
message: i18n.t("common:enterChoice"),
|
|
57
|
+
validate: (value) => {
|
|
58
|
+
const valid = ["1", "2", "3", "4", "5", "6", "0"];
|
|
59
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
switch (choice) {
|
|
63
|
+
case "1": {
|
|
64
|
+
const ccrStatus = await isCcrInstalled();
|
|
65
|
+
if (!ccrStatus.hasCorrectPackage) {
|
|
66
|
+
await installCcr();
|
|
67
|
+
} else {
|
|
68
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:ccrAlreadyInstalled")}`));
|
|
69
|
+
}
|
|
70
|
+
await configureCcrFeature();
|
|
71
|
+
console.log(ansis.green(`
|
|
72
|
+
\u2714 ${i18n.t("ccr:ccrSetupComplete")}`));
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case "2":
|
|
76
|
+
if (!isCcrConfigured()) {
|
|
77
|
+
console.log(ansis.yellow(`
|
|
78
|
+
\u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
|
|
79
|
+
console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
|
|
80
|
+
`));
|
|
81
|
+
} else {
|
|
82
|
+
const config = readCcrConfig();
|
|
83
|
+
await runCcrUi(config?.APIKEY);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
case "3":
|
|
87
|
+
if (!isCcrConfigured()) {
|
|
88
|
+
console.log(ansis.yellow(`
|
|
89
|
+
\u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
|
|
90
|
+
console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
|
|
91
|
+
`));
|
|
92
|
+
} else {
|
|
93
|
+
await runCcrStatus();
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case "4":
|
|
97
|
+
if (!isCcrConfigured()) {
|
|
98
|
+
console.log(ansis.yellow(`
|
|
99
|
+
\u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
|
|
100
|
+
console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
|
|
101
|
+
`));
|
|
102
|
+
} else {
|
|
103
|
+
await runCcrRestart();
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
case "5":
|
|
107
|
+
if (!isCcrConfigured()) {
|
|
108
|
+
console.log(ansis.yellow(`
|
|
109
|
+
\u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
|
|
110
|
+
console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
|
|
111
|
+
`));
|
|
112
|
+
} else {
|
|
113
|
+
await runCcrStart();
|
|
114
|
+
}
|
|
115
|
+
break;
|
|
116
|
+
case "6":
|
|
117
|
+
if (!isCcrConfigured()) {
|
|
118
|
+
console.log(ansis.yellow(`
|
|
119
|
+
\u26A0\uFE0F ${i18n.t("ccr:ccrNotConfigured")}`));
|
|
120
|
+
console.log(ansis.cyan(` ${i18n.t("ccr:pleaseInitFirst")}
|
|
121
|
+
`));
|
|
122
|
+
} else {
|
|
123
|
+
await runCcrStop();
|
|
124
|
+
}
|
|
125
|
+
break;
|
|
126
|
+
case "0":
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
if (choice !== "0") {
|
|
130
|
+
console.log(`
|
|
131
|
+
${ansis.dim("\u2500".repeat(50))}
|
|
132
|
+
`);
|
|
133
|
+
const continueInCcr = await promptBoolean({
|
|
134
|
+
message: i18n.t("common:returnToMenu"),
|
|
135
|
+
defaultValue: true
|
|
136
|
+
});
|
|
137
|
+
if (continueInCcr) {
|
|
138
|
+
return await showCcrMenu();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
if (!handleExitPromptError(error)) {
|
|
144
|
+
handleGeneralError(error);
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function executeCcusage(args = []) {
|
|
151
|
+
try {
|
|
152
|
+
const command = "npx";
|
|
153
|
+
const commandArgs = ["ccusage@latest", ...args || []];
|
|
154
|
+
console.log(ansis.cyan(i18n.t("tools:runningCcusage")));
|
|
155
|
+
console.log(ansis.gray(`$ npx ccusage@latest ${(args || []).join(" ")}`));
|
|
156
|
+
console.log("");
|
|
157
|
+
await x(command, commandArgs, {
|
|
158
|
+
nodeOptions: {
|
|
159
|
+
stdio: "inherit"
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error(ansis.red(i18n.t("tools:ccusageFailed")));
|
|
164
|
+
console.error(ansis.yellow(i18n.t("tools:checkNetworkConnection")));
|
|
165
|
+
if (process.env.DEBUG) {
|
|
166
|
+
console.error(ansis.gray(i18n.t("tools:errorDetails")), error);
|
|
167
|
+
}
|
|
168
|
+
if (process.env.NODE_ENV !== "test") {
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const execAsync = promisify(exec);
|
|
176
|
+
async function runCometixPrintConfig() {
|
|
177
|
+
ensureI18nInitialized();
|
|
178
|
+
try {
|
|
179
|
+
console.log(ansis.blue(`${i18n.t("cometix:printingConfig")}`));
|
|
180
|
+
const { stdout } = await execAsync(COMETIX_COMMANDS.PRINT_CONFIG);
|
|
181
|
+
console.log(stdout);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error.message.includes(`command not found: ${COMETIX_COMMAND_NAME}`)) {
|
|
184
|
+
console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`));
|
|
185
|
+
} else {
|
|
186
|
+
console.error(ansis.red(`\u2717 ${i18n.t("cometix:printConfigFailed")}: ${error}`));
|
|
187
|
+
}
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function runCometixTuiConfig() {
|
|
192
|
+
ensureI18nInitialized();
|
|
193
|
+
return new Promise((resolve, reject) => {
|
|
194
|
+
console.log(ansis.blue(`${i18n.t("cometix:enteringTuiConfig")}`));
|
|
195
|
+
const child = spawn(COMETIX_COMMAND_NAME, ["-c"], {
|
|
196
|
+
stdio: "inherit",
|
|
197
|
+
// This allows the TUI to interact directly with the terminal
|
|
198
|
+
shell: true
|
|
199
|
+
});
|
|
200
|
+
child.on("close", (code) => {
|
|
201
|
+
if (code === 0) {
|
|
202
|
+
console.log(ansis.green(`\u2713 ${i18n.t("cometix:tuiConfigSuccess")}`));
|
|
203
|
+
resolve();
|
|
204
|
+
} else {
|
|
205
|
+
const error = new Error(`${COMETIX_COMMAND_NAME} -c exited with code ${code}`);
|
|
206
|
+
console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`));
|
|
207
|
+
reject(error);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
child.on("error", (error) => {
|
|
211
|
+
if (error.message.includes(`command not found`) || error.message.includes("ENOENT")) {
|
|
212
|
+
console.error(ansis.red(`\u2717 ${i18n.t("cometix:commandNotFound")}`));
|
|
213
|
+
} else {
|
|
214
|
+
console.error(ansis.red(`\u2717 ${i18n.t("cometix:tuiConfigFailed")}: ${error.message}`));
|
|
215
|
+
}
|
|
216
|
+
reject(error);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function showCometixMenu() {
|
|
222
|
+
try {
|
|
223
|
+
ensureI18nInitialized();
|
|
224
|
+
console.log(`
|
|
225
|
+
${ansis.cyan("\u2550".repeat(50))}`);
|
|
226
|
+
console.log(ansis.bold.cyan(` ${i18n.t("cometix:cometixMenuTitle")}`));
|
|
227
|
+
console.log(`${ansis.cyan("\u2550".repeat(50))}
|
|
228
|
+
`);
|
|
229
|
+
console.log(` ${ansis.cyan("1.")} ${i18n.t("cometix:cometixMenuOptions.installOrUpdate")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.installOrUpdate")}`)}`);
|
|
230
|
+
console.log(` ${ansis.cyan("2.")} ${i18n.t("cometix:cometixMenuOptions.printConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.printConfig")}`)}`);
|
|
231
|
+
console.log(` ${ansis.cyan("3.")} ${i18n.t("cometix:cometixMenuOptions.customConfig")} ${ansis.gray(`- ${i18n.t("cometix:cometixMenuDescriptions.customConfig")}`)}`);
|
|
232
|
+
console.log(` ${ansis.yellow("0.")} ${i18n.t("cometix:cometixMenuOptions.back")}`);
|
|
233
|
+
console.log("");
|
|
234
|
+
const { choice } = await inquirer.prompt({
|
|
235
|
+
type: "input",
|
|
236
|
+
name: "choice",
|
|
237
|
+
message: i18n.t("common:enterChoice"),
|
|
238
|
+
validate: async (value) => {
|
|
239
|
+
const valid = ["1", "2", "3", "0"];
|
|
240
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
switch (choice) {
|
|
244
|
+
case "1":
|
|
245
|
+
await installCometixLine();
|
|
246
|
+
break;
|
|
247
|
+
case "2":
|
|
248
|
+
await runCometixPrintConfig();
|
|
249
|
+
break;
|
|
250
|
+
case "3":
|
|
251
|
+
await runCometixTuiConfig();
|
|
252
|
+
break;
|
|
253
|
+
case "0":
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
if (choice !== "0") {
|
|
257
|
+
console.log(`
|
|
258
|
+
${ansis.dim("\u2500".repeat(50))}
|
|
259
|
+
`);
|
|
260
|
+
const continueInCometix = await promptBoolean({
|
|
261
|
+
message: i18n.t("common:returnToMenu"),
|
|
262
|
+
defaultValue: true
|
|
263
|
+
});
|
|
264
|
+
if (continueInCometix) {
|
|
265
|
+
return await showCometixMenu();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return false;
|
|
269
|
+
} catch (error) {
|
|
270
|
+
if (!handleExitPromptError(error)) {
|
|
271
|
+
handleGeneralError(error);
|
|
272
|
+
}
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async function runCcusageFeature() {
|
|
278
|
+
ensureI18nInitialized();
|
|
279
|
+
console.log("");
|
|
280
|
+
console.log(ansis.cyan(i18n.t("menu:menuOptions.ccusage")));
|
|
281
|
+
console.log(ansis.gray(`${i18n.t("tools:ccusageDescription")}`));
|
|
282
|
+
console.log("");
|
|
283
|
+
const choices = [
|
|
284
|
+
{ name: i18n.t("tools:ccusageModes.daily"), value: "daily" },
|
|
285
|
+
{ name: i18n.t("tools:ccusageModes.monthly"), value: "monthly" },
|
|
286
|
+
{ name: i18n.t("tools:ccusageModes.session"), value: "session" },
|
|
287
|
+
{ name: i18n.t("tools:ccusageModes.blocks"), value: "blocks" },
|
|
288
|
+
{ name: i18n.t("tools:ccusageModes.custom"), value: "custom" },
|
|
289
|
+
{ name: i18n.t("common:back"), value: "back" }
|
|
290
|
+
];
|
|
291
|
+
const { mode } = await inquirer.prompt({
|
|
292
|
+
type: "list",
|
|
293
|
+
name: "mode",
|
|
294
|
+
message: i18n.t("tools:selectAnalysisMode"),
|
|
295
|
+
choices: addNumbersToChoices(choices)
|
|
296
|
+
});
|
|
297
|
+
if (mode === "back") {
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
let args = [];
|
|
301
|
+
if (mode === "custom") {
|
|
302
|
+
const { customArgs } = await inquirer.prompt({
|
|
303
|
+
type: "input",
|
|
304
|
+
name: "customArgs",
|
|
305
|
+
message: i18n.t("tools:enterCustomArgs"),
|
|
306
|
+
default: ""
|
|
307
|
+
});
|
|
308
|
+
if (customArgs === null || customArgs === void 0 || customArgs === "") {
|
|
309
|
+
args = [];
|
|
310
|
+
} else {
|
|
311
|
+
const argsString = String(customArgs).trim();
|
|
312
|
+
if (!argsString) {
|
|
313
|
+
args = [];
|
|
314
|
+
} else {
|
|
315
|
+
const argPattern = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
|
316
|
+
const matches = [];
|
|
317
|
+
let match = argPattern.exec(argsString);
|
|
318
|
+
while (match !== null) {
|
|
319
|
+
const value = match[1] || match[2] || match[3];
|
|
320
|
+
if (value) {
|
|
321
|
+
matches.push(value);
|
|
322
|
+
}
|
|
323
|
+
match = argPattern.exec(argsString);
|
|
324
|
+
}
|
|
325
|
+
args = matches;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
args = [mode];
|
|
330
|
+
}
|
|
331
|
+
console.log("");
|
|
332
|
+
await executeCcusage(args);
|
|
333
|
+
console.log("");
|
|
334
|
+
await inquirer.prompt({
|
|
335
|
+
type: "input",
|
|
336
|
+
name: "continue",
|
|
337
|
+
message: ansis.gray(i18n.t("tools:pressEnterToContinue"))
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async function runCcrMenuFeature() {
|
|
341
|
+
await showCcrMenu();
|
|
342
|
+
}
|
|
343
|
+
async function runCometixMenuFeature() {
|
|
344
|
+
await showCometixMenu();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
class ToolUpdateScheduler {
|
|
348
|
+
/**
|
|
349
|
+
* Update tools based on code type
|
|
350
|
+
* @param codeType - The code tool type to update
|
|
351
|
+
* @param skipPrompt - Whether to skip interactive prompts
|
|
352
|
+
*/
|
|
353
|
+
async updateByCodeType(codeType, skipPrompt = false) {
|
|
354
|
+
await ensureI18nInitialized();
|
|
355
|
+
switch (codeType) {
|
|
356
|
+
case "claude-code":
|
|
357
|
+
await this.updateClaudeCodeTools(skipPrompt);
|
|
358
|
+
break;
|
|
359
|
+
case "codex":
|
|
360
|
+
await this.updateCodexTools(skipPrompt);
|
|
361
|
+
break;
|
|
362
|
+
default:
|
|
363
|
+
throw new Error(`Unsupported code type: ${codeType}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Update Claude Code related tools
|
|
368
|
+
* @param skipPrompt - Whether to skip interactive prompts
|
|
369
|
+
*/
|
|
370
|
+
async updateClaudeCodeTools(skipPrompt) {
|
|
371
|
+
await checkAndUpdateTools(skipPrompt);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Update Codex tools
|
|
375
|
+
* @param skipPrompt - Whether to skip interactive prompts
|
|
376
|
+
*/
|
|
377
|
+
async updateCodexTools(skipPrompt) {
|
|
378
|
+
await runCodexUpdate(false, skipPrompt);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async function checkUpdates(options = {}) {
|
|
383
|
+
try {
|
|
384
|
+
const skipPrompt = options.skipPrompt || false;
|
|
385
|
+
let codeType;
|
|
386
|
+
try {
|
|
387
|
+
codeType = await resolveCodeType$1(options.codeType);
|
|
388
|
+
} catch (err) {
|
|
389
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
390
|
+
console.error(ansis.red(`${errorMessage}
|
|
391
|
+
Defaulting to "claude-code".`));
|
|
392
|
+
codeType = "claude-code";
|
|
393
|
+
}
|
|
394
|
+
const scheduler = new ToolUpdateScheduler();
|
|
395
|
+
await scheduler.updateByCodeType(codeType, skipPrompt);
|
|
396
|
+
} catch (error) {
|
|
397
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
398
|
+
console.error(ansis.red(`${i18n.t("updater:errorCheckingUpdates")} ${errorMessage}`));
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
class ZcfUninstaller {
|
|
404
|
+
_lang;
|
|
405
|
+
// Reserved for future i18n support
|
|
406
|
+
conflictResolution = /* @__PURE__ */ new Map();
|
|
407
|
+
constructor(lang = "en") {
|
|
408
|
+
this._lang = lang;
|
|
409
|
+
this.conflictResolution.set("claude-code", ["mcps"]);
|
|
410
|
+
void this._lang;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* 1. Remove outputStyle field from settings.json and output-styles directory
|
|
414
|
+
*/
|
|
415
|
+
async removeOutputStyles() {
|
|
416
|
+
const result = {
|
|
417
|
+
success: false,
|
|
418
|
+
removed: [],
|
|
419
|
+
removedConfigs: [],
|
|
420
|
+
errors: [],
|
|
421
|
+
warnings: []
|
|
422
|
+
};
|
|
423
|
+
try {
|
|
424
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
425
|
+
const outputStylesPath = join(homedir(), ".claude", "output-styles");
|
|
426
|
+
if (await pathExists(settingsPath)) {
|
|
427
|
+
const settings = readJsonConfig(settingsPath) || {};
|
|
428
|
+
if (settings.outputStyle) {
|
|
429
|
+
delete settings.outputStyle;
|
|
430
|
+
writeJsonConfig(settingsPath, settings);
|
|
431
|
+
result.removedConfigs.push("outputStyle field from settings.json");
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
435
|
+
}
|
|
436
|
+
if (await pathExists(outputStylesPath)) {
|
|
437
|
+
const trashResult = await moveToTrash(outputStylesPath);
|
|
438
|
+
if (!trashResult[0]?.success) {
|
|
439
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
440
|
+
}
|
|
441
|
+
result.removed.push("~/.claude/output-styles/");
|
|
442
|
+
} else {
|
|
443
|
+
result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
|
|
444
|
+
}
|
|
445
|
+
result.success = true;
|
|
446
|
+
} catch (error) {
|
|
447
|
+
result.errors.push(`Failed to remove output styles: ${error.message}`);
|
|
448
|
+
}
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* 2. Remove custom commands directory (commands/zcf/)
|
|
453
|
+
*/
|
|
454
|
+
async removeCustomCommands() {
|
|
455
|
+
const result = {
|
|
456
|
+
success: false,
|
|
457
|
+
removed: [],
|
|
458
|
+
removedConfigs: [],
|
|
459
|
+
errors: [],
|
|
460
|
+
warnings: []
|
|
461
|
+
};
|
|
462
|
+
try {
|
|
463
|
+
const commandsPath = join(homedir(), ".claude", "commands", "zcf");
|
|
464
|
+
if (await pathExists(commandsPath)) {
|
|
465
|
+
const trashResult = await moveToTrash(commandsPath);
|
|
466
|
+
if (!trashResult[0]?.success) {
|
|
467
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
468
|
+
}
|
|
469
|
+
result.removed.push("commands/zcf/");
|
|
470
|
+
result.success = true;
|
|
471
|
+
} else {
|
|
472
|
+
result.warnings.push(i18n.t("uninstall:commandsNotFound"));
|
|
473
|
+
result.success = true;
|
|
474
|
+
}
|
|
475
|
+
} catch (error) {
|
|
476
|
+
result.errors.push(`Failed to remove custom commands: ${error.message}`);
|
|
477
|
+
}
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* 3. Remove custom agents directory (agents/zcf/)
|
|
482
|
+
*/
|
|
483
|
+
async removeCustomAgents() {
|
|
484
|
+
const result = {
|
|
485
|
+
success: false,
|
|
486
|
+
removed: [],
|
|
487
|
+
removedConfigs: [],
|
|
488
|
+
errors: [],
|
|
489
|
+
warnings: []
|
|
490
|
+
};
|
|
491
|
+
try {
|
|
492
|
+
const agentsPath = join(homedir(), ".claude", "agents", "zcf");
|
|
493
|
+
if (await pathExists(agentsPath)) {
|
|
494
|
+
const trashResult = await moveToTrash(agentsPath);
|
|
495
|
+
if (!trashResult[0]?.success) {
|
|
496
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
497
|
+
}
|
|
498
|
+
result.removed.push("agents/zcf/");
|
|
499
|
+
result.success = true;
|
|
500
|
+
} else {
|
|
501
|
+
result.warnings.push(i18n.t("uninstall:agentsNotFound"));
|
|
502
|
+
result.success = true;
|
|
503
|
+
}
|
|
504
|
+
} catch (error) {
|
|
505
|
+
result.errors.push(`Failed to remove custom agents: ${error.message}`);
|
|
506
|
+
}
|
|
507
|
+
return result;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* 4. Remove global memory file (CLAUDE.md)
|
|
511
|
+
*/
|
|
512
|
+
async removeClaudeMd() {
|
|
513
|
+
const result = {
|
|
514
|
+
success: false,
|
|
515
|
+
removed: [],
|
|
516
|
+
removedConfigs: [],
|
|
517
|
+
errors: [],
|
|
518
|
+
warnings: []
|
|
519
|
+
};
|
|
520
|
+
try {
|
|
521
|
+
const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
|
|
522
|
+
if (await pathExists(claudeMdPath)) {
|
|
523
|
+
const trashResult = await moveToTrash(claudeMdPath);
|
|
524
|
+
if (!trashResult[0]?.success) {
|
|
525
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
526
|
+
}
|
|
527
|
+
result.removed.push("CLAUDE.md");
|
|
528
|
+
result.success = true;
|
|
529
|
+
} else {
|
|
530
|
+
result.warnings.push(i18n.t("uninstall:claudeMdNotFound"));
|
|
531
|
+
result.success = true;
|
|
532
|
+
}
|
|
533
|
+
} catch (error) {
|
|
534
|
+
result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`);
|
|
535
|
+
}
|
|
536
|
+
return result;
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* 5. Remove permissions and environment variables
|
|
540
|
+
*/
|
|
541
|
+
async removePermissionsAndEnvs() {
|
|
542
|
+
const result = {
|
|
543
|
+
success: false,
|
|
544
|
+
removed: [],
|
|
545
|
+
removedConfigs: [],
|
|
546
|
+
errors: [],
|
|
547
|
+
warnings: []
|
|
548
|
+
};
|
|
549
|
+
try {
|
|
550
|
+
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
551
|
+
if (await pathExists(settingsPath)) {
|
|
552
|
+
const settings = readJsonConfig(settingsPath) || {};
|
|
553
|
+
let modified = false;
|
|
554
|
+
if (settings.permissions) {
|
|
555
|
+
delete settings.permissions;
|
|
556
|
+
result.removedConfigs.push("permissions configuration");
|
|
557
|
+
modified = true;
|
|
558
|
+
}
|
|
559
|
+
if (settings.env) {
|
|
560
|
+
delete settings.env;
|
|
561
|
+
result.removedConfigs.push("environment variables");
|
|
562
|
+
modified = true;
|
|
563
|
+
}
|
|
564
|
+
if (modified) {
|
|
565
|
+
writeJsonConfig(settingsPath, settings);
|
|
566
|
+
}
|
|
567
|
+
result.success = true;
|
|
568
|
+
} else {
|
|
569
|
+
result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
|
|
570
|
+
result.success = true;
|
|
571
|
+
}
|
|
572
|
+
} catch (error) {
|
|
573
|
+
result.errors.push(`Failed to remove permissions and envs: ${error.message}`);
|
|
574
|
+
}
|
|
575
|
+
return result;
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* 6. Remove MCP servers from .claude.json (mcpServers field only)
|
|
579
|
+
*/
|
|
580
|
+
async removeMcps() {
|
|
581
|
+
const result = {
|
|
582
|
+
success: false,
|
|
583
|
+
removed: [],
|
|
584
|
+
removedConfigs: [],
|
|
585
|
+
errors: [],
|
|
586
|
+
warnings: []
|
|
587
|
+
};
|
|
588
|
+
try {
|
|
589
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
590
|
+
if (await pathExists(claudeJsonPath)) {
|
|
591
|
+
const config = readJsonConfig(claudeJsonPath) || {};
|
|
592
|
+
if (config.mcpServers) {
|
|
593
|
+
delete config.mcpServers;
|
|
594
|
+
writeJsonConfig(claudeJsonPath, config);
|
|
595
|
+
result.removedConfigs.push("mcpServers from .claude.json");
|
|
596
|
+
}
|
|
597
|
+
result.success = true;
|
|
598
|
+
} else {
|
|
599
|
+
result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
|
|
600
|
+
result.success = true;
|
|
601
|
+
}
|
|
602
|
+
} catch (error) {
|
|
603
|
+
result.errors.push(`Failed to remove MCP servers: ${error.message}`);
|
|
604
|
+
}
|
|
605
|
+
return result;
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* 7. Uninstall Claude Code Router and remove configuration
|
|
609
|
+
*/
|
|
610
|
+
async uninstallCcr() {
|
|
611
|
+
const result = {
|
|
612
|
+
success: false,
|
|
613
|
+
removed: [],
|
|
614
|
+
removedConfigs: [],
|
|
615
|
+
errors: [],
|
|
616
|
+
warnings: []
|
|
617
|
+
};
|
|
618
|
+
try {
|
|
619
|
+
const ccrPath = join(homedir(), ".claude-code-router");
|
|
620
|
+
if (await pathExists(ccrPath)) {
|
|
621
|
+
const trashResult = await moveToTrash(ccrPath);
|
|
622
|
+
if (!trashResult[0]?.success) {
|
|
623
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
624
|
+
}
|
|
625
|
+
result.removed.push(".claude-code-router/");
|
|
626
|
+
}
|
|
627
|
+
try {
|
|
628
|
+
await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]);
|
|
629
|
+
result.removed.push("@musistudio/claude-code-router package");
|
|
630
|
+
result.success = true;
|
|
631
|
+
} catch (npmError) {
|
|
632
|
+
if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
|
|
633
|
+
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
634
|
+
result.success = true;
|
|
635
|
+
} else {
|
|
636
|
+
result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
} catch (error) {
|
|
640
|
+
result.errors.push(`Failed to uninstall CCR: ${error.message}`);
|
|
641
|
+
}
|
|
642
|
+
return result;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* 8. Uninstall CCometixLine
|
|
646
|
+
*/
|
|
647
|
+
async uninstallCcline() {
|
|
648
|
+
const result = {
|
|
649
|
+
success: false,
|
|
650
|
+
removed: [],
|
|
651
|
+
removedConfigs: [],
|
|
652
|
+
errors: [],
|
|
653
|
+
warnings: []
|
|
654
|
+
};
|
|
655
|
+
try {
|
|
656
|
+
await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]);
|
|
657
|
+
result.removed.push("@cometix/ccline package");
|
|
658
|
+
result.success = true;
|
|
659
|
+
} catch (error) {
|
|
660
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
661
|
+
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
662
|
+
result.success = true;
|
|
663
|
+
} else {
|
|
664
|
+
result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
return result;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* 9. Uninstall Claude Code and remove entire .claude.json
|
|
671
|
+
*/
|
|
672
|
+
async uninstallClaudeCode() {
|
|
673
|
+
const result = {
|
|
674
|
+
success: false,
|
|
675
|
+
removed: [],
|
|
676
|
+
removedConfigs: [],
|
|
677
|
+
errors: [],
|
|
678
|
+
warnings: []
|
|
679
|
+
};
|
|
680
|
+
try {
|
|
681
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
682
|
+
if (await pathExists(claudeJsonPath)) {
|
|
683
|
+
const trashResult = await moveToTrash(claudeJsonPath);
|
|
684
|
+
if (!trashResult[0]?.success) {
|
|
685
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
686
|
+
}
|
|
687
|
+
result.removed.push(".claude.json (includes MCP configuration)");
|
|
688
|
+
}
|
|
689
|
+
try {
|
|
690
|
+
const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.br; });
|
|
691
|
+
const success = await uninstallCodeTool("claude-code");
|
|
692
|
+
if (success) {
|
|
693
|
+
result.removed.push("@anthropic-ai/claude-code");
|
|
694
|
+
result.success = true;
|
|
695
|
+
} else {
|
|
696
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: "" }));
|
|
697
|
+
}
|
|
698
|
+
} catch (npmError) {
|
|
699
|
+
if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
|
|
700
|
+
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
701
|
+
result.success = true;
|
|
702
|
+
} else {
|
|
703
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${npmError.message}` }));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
} catch (error) {
|
|
707
|
+
result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${error.message}` }));
|
|
708
|
+
}
|
|
709
|
+
return result;
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* 10. Remove backup files
|
|
713
|
+
*/
|
|
714
|
+
async removeBackups() {
|
|
715
|
+
const result = {
|
|
716
|
+
success: false,
|
|
717
|
+
removed: [],
|
|
718
|
+
removedConfigs: [],
|
|
719
|
+
errors: [],
|
|
720
|
+
warnings: []
|
|
721
|
+
};
|
|
722
|
+
try {
|
|
723
|
+
const backupPath = join(homedir(), ".claude", "backup");
|
|
724
|
+
if (await pathExists(backupPath)) {
|
|
725
|
+
const trashResult = await moveToTrash(backupPath);
|
|
726
|
+
if (!trashResult[0]?.success) {
|
|
727
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
728
|
+
}
|
|
729
|
+
result.removed.push("backup/");
|
|
730
|
+
result.success = true;
|
|
731
|
+
} else {
|
|
732
|
+
result.warnings.push(i18n.t("uninstall:backupsNotFound"));
|
|
733
|
+
result.success = true;
|
|
734
|
+
}
|
|
735
|
+
} catch (error) {
|
|
736
|
+
result.errors.push(`Failed to remove backups: ${error.message}`);
|
|
737
|
+
}
|
|
738
|
+
return result;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* 11. Remove ZCF preference configuration
|
|
742
|
+
*/
|
|
743
|
+
async removeZcfConfig() {
|
|
744
|
+
const result = {
|
|
745
|
+
success: false,
|
|
746
|
+
removed: [],
|
|
747
|
+
removedConfigs: [],
|
|
748
|
+
errors: [],
|
|
749
|
+
warnings: []
|
|
750
|
+
};
|
|
751
|
+
try {
|
|
752
|
+
const zcfConfigPath = ZCF_CONFIG_FILE;
|
|
753
|
+
const relativeName = zcfConfigPath.replace(homedir(), "~");
|
|
754
|
+
if (await pathExists(zcfConfigPath)) {
|
|
755
|
+
const trashResult = await moveToTrash(zcfConfigPath);
|
|
756
|
+
if (!trashResult[0]?.success) {
|
|
757
|
+
result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
|
|
758
|
+
}
|
|
759
|
+
result.removed.push(relativeName);
|
|
760
|
+
result.success = true;
|
|
761
|
+
} else {
|
|
762
|
+
result.warnings.push(i18n.t("uninstall:zcfConfigNotFound"));
|
|
763
|
+
result.success = true;
|
|
764
|
+
}
|
|
765
|
+
} catch (error) {
|
|
766
|
+
result.errors.push(`Failed to remove ZCF config: ${error.message}`);
|
|
767
|
+
}
|
|
768
|
+
return result;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Complete uninstall - remove all directories and packages
|
|
772
|
+
*/
|
|
773
|
+
async completeUninstall() {
|
|
774
|
+
const result = {
|
|
775
|
+
success: true,
|
|
776
|
+
removed: [],
|
|
777
|
+
removedConfigs: [],
|
|
778
|
+
errors: [],
|
|
779
|
+
warnings: []
|
|
780
|
+
};
|
|
781
|
+
try {
|
|
782
|
+
const directoriesToRemove = [
|
|
783
|
+
{ path: join(homedir(), ".claude"), name: "~/.claude/" },
|
|
784
|
+
{ path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
|
|
785
|
+
{ path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
|
|
786
|
+
];
|
|
787
|
+
for (const dir of directoriesToRemove) {
|
|
788
|
+
try {
|
|
789
|
+
if (await pathExists(dir.path)) {
|
|
790
|
+
const trashResult = await moveToTrash(dir.path);
|
|
791
|
+
if (!trashResult[0]?.success) {
|
|
792
|
+
result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
|
|
793
|
+
}
|
|
794
|
+
result.removed.push(dir.name);
|
|
795
|
+
}
|
|
796
|
+
} catch (error) {
|
|
797
|
+
result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
const packagesToUninstall = [
|
|
801
|
+
"@musistudio/claude-code-router",
|
|
802
|
+
"@cometix/ccline",
|
|
803
|
+
"@anthropic-ai/claude-code"
|
|
804
|
+
];
|
|
805
|
+
for (const pkg of packagesToUninstall) {
|
|
806
|
+
try {
|
|
807
|
+
await exec$1("npm", ["uninstall", "-g", pkg]);
|
|
808
|
+
result.removed.push(`${pkg} package`);
|
|
809
|
+
} catch (error) {
|
|
810
|
+
if (error.message.includes("not found") || error.message.includes("not installed")) {
|
|
811
|
+
if (pkg.includes("claude-code-router")) {
|
|
812
|
+
result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
|
|
813
|
+
} else if (pkg.includes("ccline")) {
|
|
814
|
+
result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
|
|
815
|
+
} else {
|
|
816
|
+
result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
|
|
817
|
+
}
|
|
818
|
+
} else {
|
|
819
|
+
result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
} catch (error) {
|
|
824
|
+
result.errors.push(`Complete uninstall failed: ${error.message}`);
|
|
825
|
+
result.success = false;
|
|
826
|
+
}
|
|
827
|
+
return result;
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Custom uninstall with conflict resolution
|
|
831
|
+
*/
|
|
832
|
+
async customUninstall(selectedItems) {
|
|
833
|
+
const resolvedItems = this.resolveConflicts(selectedItems);
|
|
834
|
+
const results = [];
|
|
835
|
+
for (const item of resolvedItems) {
|
|
836
|
+
try {
|
|
837
|
+
const result = await this.executeUninstallItem(item);
|
|
838
|
+
results.push(result);
|
|
839
|
+
} catch (error) {
|
|
840
|
+
results.push({
|
|
841
|
+
success: false,
|
|
842
|
+
removed: [],
|
|
843
|
+
removedConfigs: [],
|
|
844
|
+
errors: [`Failed to execute ${item}: ${error.message}`],
|
|
845
|
+
warnings: []
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
return results;
|
|
850
|
+
}
|
|
851
|
+
/**
|
|
852
|
+
* Resolve conflicts between uninstall items
|
|
853
|
+
*/
|
|
854
|
+
resolveConflicts(items) {
|
|
855
|
+
const resolved = [...items];
|
|
856
|
+
for (const [primary, conflicts] of this.conflictResolution) {
|
|
857
|
+
if (resolved.includes(primary)) {
|
|
858
|
+
conflicts.forEach((conflict) => {
|
|
859
|
+
const index = resolved.indexOf(conflict);
|
|
860
|
+
if (index > -1) {
|
|
861
|
+
resolved.splice(index, 1);
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
return resolved;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Execute uninstall for a specific item
|
|
870
|
+
*/
|
|
871
|
+
async executeUninstallItem(item) {
|
|
872
|
+
switch (item) {
|
|
873
|
+
case "output-styles":
|
|
874
|
+
return await this.removeOutputStyles();
|
|
875
|
+
case "commands":
|
|
876
|
+
return await this.removeCustomCommands();
|
|
877
|
+
case "agents":
|
|
878
|
+
return await this.removeCustomAgents();
|
|
879
|
+
case "claude-md":
|
|
880
|
+
return await this.removeClaudeMd();
|
|
881
|
+
case "permissions-envs":
|
|
882
|
+
return await this.removePermissionsAndEnvs();
|
|
883
|
+
case "mcps":
|
|
884
|
+
return await this.removeMcps();
|
|
885
|
+
case "ccr":
|
|
886
|
+
return await this.uninstallCcr();
|
|
887
|
+
case "ccline":
|
|
888
|
+
return await this.uninstallCcline();
|
|
889
|
+
case "claude-code":
|
|
890
|
+
return await this.uninstallClaudeCode();
|
|
891
|
+
case "backups":
|
|
892
|
+
return await this.removeBackups();
|
|
893
|
+
case "zcf-config":
|
|
894
|
+
return await this.removeZcfConfig();
|
|
895
|
+
default:
|
|
896
|
+
return {
|
|
897
|
+
success: false,
|
|
898
|
+
removed: [],
|
|
899
|
+
removedConfigs: [],
|
|
900
|
+
errors: [`Unknown uninstall item: ${item}`],
|
|
901
|
+
warnings: []
|
|
902
|
+
};
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
async function uninstall(options = {}) {
|
|
908
|
+
try {
|
|
909
|
+
ensureI18nInitialized();
|
|
910
|
+
let codeType;
|
|
911
|
+
if (options.codeType) {
|
|
912
|
+
try {
|
|
913
|
+
codeType = await resolveCodeType$1(options.codeType);
|
|
914
|
+
} catch (error) {
|
|
915
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
916
|
+
console.error(ansis.red(`${i18n.t("errors:generalError")} ${errorMessage}`));
|
|
917
|
+
const config = readZcfConfig();
|
|
918
|
+
codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
|
|
919
|
+
}
|
|
920
|
+
} else {
|
|
921
|
+
const config = readZcfConfig();
|
|
922
|
+
codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
|
|
923
|
+
}
|
|
924
|
+
const uninstaller = new ZcfUninstaller(options.lang || "en");
|
|
925
|
+
if (codeType === "codex") {
|
|
926
|
+
const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bq; });
|
|
927
|
+
await runCodexUninstall();
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
if (options.mode && options.mode !== "interactive") {
|
|
931
|
+
if (options.mode === "complete") {
|
|
932
|
+
await executeCompleteUninstall(uninstaller);
|
|
933
|
+
return;
|
|
934
|
+
} else if (options.mode === "custom" && options.items) {
|
|
935
|
+
let items;
|
|
936
|
+
if (typeof options.items === "string") {
|
|
937
|
+
items = options.items.split(",").map((item) => item.trim());
|
|
938
|
+
} else {
|
|
939
|
+
items = options.items;
|
|
940
|
+
}
|
|
941
|
+
await executeCustomUninstall(uninstaller, items);
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
await showInteractiveUninstall(uninstaller);
|
|
946
|
+
} catch (error) {
|
|
947
|
+
if (!handleExitPromptError(error)) {
|
|
948
|
+
handleGeneralError(error);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
async function showInteractiveUninstall(uninstaller) {
|
|
953
|
+
console.log(ansis.cyan.bold(i18n.t("uninstall:title")));
|
|
954
|
+
console.log("");
|
|
955
|
+
const { mainChoice } = await inquirer.prompt({
|
|
956
|
+
type: "list",
|
|
957
|
+
name: "mainChoice",
|
|
958
|
+
message: i18n.t("uninstall:selectMainOption"),
|
|
959
|
+
choices: addNumbersToChoices([
|
|
960
|
+
{
|
|
961
|
+
name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
|
|
962
|
+
value: "complete",
|
|
963
|
+
short: i18n.t("uninstall:completeUninstall")
|
|
964
|
+
},
|
|
965
|
+
{
|
|
966
|
+
name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
|
|
967
|
+
value: "custom",
|
|
968
|
+
short: i18n.t("uninstall:customUninstall")
|
|
969
|
+
}
|
|
970
|
+
])
|
|
971
|
+
});
|
|
972
|
+
if (!mainChoice) {
|
|
973
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
if (mainChoice === "complete") {
|
|
977
|
+
await executeCompleteUninstall(uninstaller);
|
|
978
|
+
} else {
|
|
979
|
+
await showCustomUninstallMenu(uninstaller);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
async function showCustomUninstallMenu(uninstaller) {
|
|
983
|
+
console.log("");
|
|
984
|
+
console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems")));
|
|
985
|
+
const { customItems } = await inquirer.prompt({
|
|
986
|
+
type: "checkbox",
|
|
987
|
+
name: "customItems",
|
|
988
|
+
message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`,
|
|
989
|
+
choices: [
|
|
990
|
+
{
|
|
991
|
+
name: i18n.t("uninstall:outputStyles"),
|
|
992
|
+
value: "output-styles"
|
|
993
|
+
},
|
|
994
|
+
{
|
|
995
|
+
name: i18n.t("uninstall:commands"),
|
|
996
|
+
value: "commands"
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
name: i18n.t("uninstall:agents"),
|
|
1000
|
+
value: "agents"
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
name: i18n.t("uninstall:claudeMd"),
|
|
1004
|
+
value: "claude-md"
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
name: i18n.t("uninstall:permissionsEnvs"),
|
|
1008
|
+
value: "permissions-envs"
|
|
1009
|
+
},
|
|
1010
|
+
{
|
|
1011
|
+
name: i18n.t("uninstall:mcps"),
|
|
1012
|
+
value: "mcps"
|
|
1013
|
+
},
|
|
1014
|
+
{
|
|
1015
|
+
name: i18n.t("uninstall:ccr"),
|
|
1016
|
+
value: "ccr"
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
name: i18n.t("uninstall:ccline"),
|
|
1020
|
+
value: "ccline"
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
name: i18n.t("uninstall:claudeCode"),
|
|
1024
|
+
value: "claude-code"
|
|
1025
|
+
},
|
|
1026
|
+
{
|
|
1027
|
+
name: i18n.t("uninstall:backups"),
|
|
1028
|
+
value: "backups"
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
name: i18n.t("uninstall:zcfConfig"),
|
|
1032
|
+
value: "zcf-config"
|
|
1033
|
+
}
|
|
1034
|
+
],
|
|
1035
|
+
validate: (answers) => {
|
|
1036
|
+
if (answers.length === 0) {
|
|
1037
|
+
return i18n.t("uninstall:selectAtLeastOne");
|
|
1038
|
+
}
|
|
1039
|
+
return true;
|
|
1040
|
+
}
|
|
1041
|
+
});
|
|
1042
|
+
if (!customItems || customItems.length === 0) {
|
|
1043
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
await executeCustomUninstall(uninstaller, customItems);
|
|
1047
|
+
}
|
|
1048
|
+
async function executeCompleteUninstall(uninstaller) {
|
|
1049
|
+
console.log("");
|
|
1050
|
+
console.log(ansis.red.bold(i18n.t("uninstall:executingComplete")));
|
|
1051
|
+
console.log(ansis.yellow(i18n.t("uninstall:completeWarning")));
|
|
1052
|
+
const confirm = await promptBoolean({
|
|
1053
|
+
message: i18n.t("uninstall:confirmComplete"),
|
|
1054
|
+
defaultValue: false
|
|
1055
|
+
});
|
|
1056
|
+
if (!confirm) {
|
|
1057
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
console.log("");
|
|
1061
|
+
console.log(ansis.cyan(i18n.t("uninstall:processingComplete")));
|
|
1062
|
+
const result = await uninstaller.completeUninstall();
|
|
1063
|
+
displayUninstallResult("complete", [result]);
|
|
1064
|
+
}
|
|
1065
|
+
async function executeCustomUninstall(uninstaller, items) {
|
|
1066
|
+
console.log("");
|
|
1067
|
+
console.log(ansis.cyan(i18n.t("uninstall:executingCustom")));
|
|
1068
|
+
console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
|
|
1069
|
+
items.forEach((item) => {
|
|
1070
|
+
console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
|
|
1071
|
+
});
|
|
1072
|
+
const confirm = await promptBoolean({
|
|
1073
|
+
message: i18n.t("uninstall:confirmCustom"),
|
|
1074
|
+
defaultValue: false
|
|
1075
|
+
});
|
|
1076
|
+
if (!confirm) {
|
|
1077
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
console.log("");
|
|
1081
|
+
console.log(ansis.cyan(i18n.t("uninstall:processingCustom")));
|
|
1082
|
+
const results = await uninstaller.customUninstall(items);
|
|
1083
|
+
displayUninstallResult("custom", results);
|
|
1084
|
+
}
|
|
1085
|
+
function displayUninstallResult(mode, results) {
|
|
1086
|
+
console.log("");
|
|
1087
|
+
console.log(ansis.cyan("\u2500".repeat(50)));
|
|
1088
|
+
let totalSuccess = 0;
|
|
1089
|
+
let totalErrors = 0;
|
|
1090
|
+
let totalWarnings = 0;
|
|
1091
|
+
results.forEach((result) => {
|
|
1092
|
+
if (result.success) {
|
|
1093
|
+
totalSuccess++;
|
|
1094
|
+
}
|
|
1095
|
+
if (result.removed && result.removed.length > 0) {
|
|
1096
|
+
console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
|
|
1097
|
+
result.removed.forEach((item) => {
|
|
1098
|
+
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
if (result.removedConfigs && result.removedConfigs.length > 0) {
|
|
1102
|
+
console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
|
|
1103
|
+
result.removedConfigs.forEach((item) => {
|
|
1104
|
+
console.log(ansis.gray(` \u2022 ${item}`));
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
if (result.errors && result.errors.length > 0) {
|
|
1108
|
+
totalErrors += result.errors.length;
|
|
1109
|
+
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
|
|
1110
|
+
result.errors.forEach((error) => {
|
|
1111
|
+
console.log(ansis.red(` \u2022 ${error}`));
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
1115
|
+
totalWarnings += result.warnings.length;
|
|
1116
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
|
|
1117
|
+
result.warnings.forEach((warning) => {
|
|
1118
|
+
console.log(ansis.yellow(` \u2022 ${warning}`));
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
|
|
1123
|
+
const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
|
|
1124
|
+
console.log("");
|
|
1125
|
+
console.log(ansis.cyan("\u2500".repeat(50)));
|
|
1126
|
+
if (mode === "complete") {
|
|
1127
|
+
if (totalErrors === 0) {
|
|
1128
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`));
|
|
1129
|
+
} else {
|
|
1130
|
+
console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`));
|
|
1131
|
+
}
|
|
1132
|
+
} else {
|
|
1133
|
+
if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
|
|
1134
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
|
|
1135
|
+
fileCount: totalRemovedFiles,
|
|
1136
|
+
configCount: totalRemovedConfigs
|
|
1137
|
+
})}`));
|
|
1138
|
+
} else if (totalRemovedFiles > 0) {
|
|
1139
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
|
|
1140
|
+
count: totalRemovedFiles
|
|
1141
|
+
})}`));
|
|
1142
|
+
} else if (totalRemovedConfigs > 0) {
|
|
1143
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
|
|
1144
|
+
count: totalRemovedConfigs
|
|
1145
|
+
})}`));
|
|
1146
|
+
} else {
|
|
1147
|
+
console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
|
|
1148
|
+
}
|
|
1149
|
+
if (totalErrors > 0) {
|
|
1150
|
+
console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`));
|
|
1151
|
+
}
|
|
1152
|
+
if (totalWarnings > 0) {
|
|
1153
|
+
console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`));
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
console.log("");
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
function resolveCodeToolType(optionValue, savedValue) {
|
|
1160
|
+
if (optionValue !== void 0) {
|
|
1161
|
+
const resolved = resolveCodeToolType$1(optionValue);
|
|
1162
|
+
if (resolved !== DEFAULT_CODE_TOOL_TYPE || optionValue === DEFAULT_CODE_TOOL_TYPE) {
|
|
1163
|
+
return resolved;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
if (savedValue && isCodeToolType(savedValue)) {
|
|
1167
|
+
return savedValue;
|
|
1168
|
+
}
|
|
1169
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1170
|
+
}
|
|
1171
|
+
async function update(options = {}) {
|
|
1172
|
+
try {
|
|
1173
|
+
if (!options.skipBanner) {
|
|
1174
|
+
displayBanner(i18n.t("cli:banner.updateSubtitle"));
|
|
1175
|
+
}
|
|
1176
|
+
const zcfConfig = readZcfConfig();
|
|
1177
|
+
const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
|
|
1178
|
+
options.codeType = codeToolType;
|
|
1179
|
+
if (codeToolType === "codex") {
|
|
1180
|
+
await runCodexUpdate();
|
|
1181
|
+
const newPreferredLang = options.configLang || zcfConfig?.preferredLang;
|
|
1182
|
+
if (newPreferredLang) {
|
|
1183
|
+
updateZcfConfig({
|
|
1184
|
+
version,
|
|
1185
|
+
preferredLang: newPreferredLang,
|
|
1186
|
+
codeToolType
|
|
1187
|
+
});
|
|
1188
|
+
} else {
|
|
1189
|
+
updateZcfConfig({
|
|
1190
|
+
version,
|
|
1191
|
+
codeToolType
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.bo; });
|
|
1197
|
+
const configLang = await resolveTemplateLanguage(
|
|
1198
|
+
options.configLang,
|
|
1199
|
+
// Command line option
|
|
1200
|
+
zcfConfig,
|
|
1201
|
+
options.skipPrompt
|
|
1202
|
+
// Non-interactive mode flag
|
|
1203
|
+
);
|
|
1204
|
+
const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt);
|
|
1205
|
+
console.log(ansis.cyan(`
|
|
1206
|
+
${i18n.t("configuration:updatingPrompts")}
|
|
1207
|
+
`));
|
|
1208
|
+
await updatePromptOnly(aiOutputLang);
|
|
1209
|
+
await selectAndInstallWorkflows(configLang);
|
|
1210
|
+
await checkClaudeCodeVersionAndPrompt(false);
|
|
1211
|
+
updateZcfConfig({
|
|
1212
|
+
version,
|
|
1213
|
+
templateLang: configLang,
|
|
1214
|
+
// 保存模板语言选择
|
|
1215
|
+
aiOutputLang,
|
|
1216
|
+
codeToolType
|
|
1217
|
+
});
|
|
1218
|
+
} catch (error) {
|
|
1219
|
+
if (!handleExitPromptError(error)) {
|
|
1220
|
+
handleGeneralError(error);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
const CODE_TOOL_LABELS = {
|
|
1226
|
+
"claude-code": "Claude Code",
|
|
1227
|
+
"codex": "Codex"
|
|
1228
|
+
};
|
|
1229
|
+
function getCurrentCodeTool() {
|
|
1230
|
+
const config = readZcfConfig();
|
|
1231
|
+
if (config?.codeToolType && isCodeToolType(config.codeToolType)) {
|
|
1232
|
+
return config.codeToolType;
|
|
1233
|
+
}
|
|
1234
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1235
|
+
}
|
|
1236
|
+
function printSeparator() {
|
|
1237
|
+
console.log(`
|
|
1238
|
+
${ansis.dim("\u2500".repeat(50))}
|
|
1239
|
+
`);
|
|
1240
|
+
}
|
|
1241
|
+
function getCodeToolLabel(codeTool) {
|
|
1242
|
+
return CODE_TOOL_LABELS[codeTool] || codeTool;
|
|
1243
|
+
}
|
|
1244
|
+
async function promptCodeToolSelection(current) {
|
|
1245
|
+
const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({
|
|
1246
|
+
name: label,
|
|
1247
|
+
value,
|
|
1248
|
+
short: label
|
|
1249
|
+
})));
|
|
1250
|
+
const { tool } = await inquirer.prompt({
|
|
1251
|
+
type: "list",
|
|
1252
|
+
name: "tool",
|
|
1253
|
+
message: i18n.t("menu:switchCodeToolPrompt"),
|
|
1254
|
+
default: current,
|
|
1255
|
+
choices
|
|
1256
|
+
});
|
|
1257
|
+
if (!tool) {
|
|
1258
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
return tool;
|
|
1262
|
+
}
|
|
1263
|
+
async function handleCodeToolSwitch(current) {
|
|
1264
|
+
const newTool = await promptCodeToolSelection(current);
|
|
1265
|
+
if (!newTool || newTool === current) {
|
|
1266
|
+
return false;
|
|
1267
|
+
}
|
|
1268
|
+
updateZcfConfig({ codeToolType: newTool });
|
|
1269
|
+
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`));
|
|
1270
|
+
return true;
|
|
1271
|
+
}
|
|
1272
|
+
function printOtherToolsSection() {
|
|
1273
|
+
console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`);
|
|
1274
|
+
console.log(
|
|
1275
|
+
` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
|
|
1276
|
+
);
|
|
1277
|
+
console.log(
|
|
1278
|
+
` ${ansis.cyan("U.")} ${i18n.t("menu:menuOptions.ccusage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccusage")}`)}`
|
|
1279
|
+
);
|
|
1280
|
+
console.log(
|
|
1281
|
+
` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
|
|
1282
|
+
);
|
|
1283
|
+
console.log("");
|
|
1284
|
+
}
|
|
1285
|
+
function printZcfSection(options) {
|
|
1286
|
+
console.log(" ------------ ZCF ------------");
|
|
1287
|
+
console.log(
|
|
1288
|
+
` ${ansis.cyan("0.")} ${i18n.t("menu:menuOptions.changeLanguage")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.changeLanguage")}`)}`
|
|
1289
|
+
);
|
|
1290
|
+
console.log(
|
|
1291
|
+
` ${ansis.cyan("S.")} ${i18n.t("menu:menuOptions.switchCodeTool")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.switchCodeTool")}`)}`
|
|
1292
|
+
);
|
|
1293
|
+
console.log(
|
|
1294
|
+
` ${ansis.cyan("-.")} ${options.uninstallOption} ${ansis.gray(`- ${options.uninstallDescription}`)}`
|
|
1295
|
+
);
|
|
1296
|
+
console.log(
|
|
1297
|
+
` ${ansis.cyan("+.")} ${options.updateOption} ${ansis.gray(`- ${options.updateDescription}`)}`
|
|
1298
|
+
);
|
|
1299
|
+
console.log(` ${ansis.red("Q.")} ${ansis.red(i18n.t("menu:menuOptions.exit"))}`);
|
|
1300
|
+
console.log("");
|
|
1301
|
+
}
|
|
1302
|
+
async function showClaudeCodeMenu() {
|
|
1303
|
+
console.log(ansis.cyan(i18n.t("menu:selectFunction")));
|
|
1304
|
+
console.log(" -------- Claude Code --------");
|
|
1305
|
+
console.log(
|
|
1306
|
+
` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.fullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.fullInit")}`)}`
|
|
1307
|
+
);
|
|
1308
|
+
console.log(
|
|
1309
|
+
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.importWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.importWorkflow")}`)}`
|
|
1310
|
+
);
|
|
1311
|
+
console.log(
|
|
1312
|
+
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.configureApiOrCcr")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureApiOrCcr")}`)}`
|
|
1313
|
+
);
|
|
1314
|
+
console.log(
|
|
1315
|
+
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.configureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureMcp")}`)}`
|
|
1316
|
+
);
|
|
1317
|
+
console.log(
|
|
1318
|
+
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.configureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureModel")}`)}`
|
|
1319
|
+
);
|
|
1320
|
+
console.log(
|
|
1321
|
+
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.configureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureAiMemory")}`)}`
|
|
1322
|
+
);
|
|
1323
|
+
console.log(
|
|
1324
|
+
` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`)}`
|
|
1325
|
+
);
|
|
1326
|
+
console.log("");
|
|
1327
|
+
printOtherToolsSection();
|
|
1328
|
+
printZcfSection({
|
|
1329
|
+
uninstallOption: i18n.t("menu:menuOptions.uninstall"),
|
|
1330
|
+
uninstallDescription: i18n.t("menu:menuDescriptions.uninstall"),
|
|
1331
|
+
updateOption: i18n.t("menu:menuOptions.checkUpdates"),
|
|
1332
|
+
updateDescription: i18n.t("menu:menuDescriptions.checkUpdates")
|
|
1333
|
+
});
|
|
1334
|
+
const { choice } = await inquirer.prompt({
|
|
1335
|
+
type: "input",
|
|
1336
|
+
name: "choice",
|
|
1337
|
+
message: i18n.t("common:enterChoice"),
|
|
1338
|
+
validate: (value) => {
|
|
1339
|
+
const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "s", "S", "q", "Q"];
|
|
1340
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1343
|
+
if (!choice) {
|
|
1344
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1345
|
+
return "exit";
|
|
1346
|
+
}
|
|
1347
|
+
const normalized = choice.toLowerCase();
|
|
1348
|
+
switch (normalized) {
|
|
1349
|
+
case "1":
|
|
1350
|
+
await init({ skipBanner: true });
|
|
1351
|
+
break;
|
|
1352
|
+
case "2":
|
|
1353
|
+
await update({ skipBanner: true });
|
|
1354
|
+
break;
|
|
1355
|
+
case "3":
|
|
1356
|
+
await configureApiFeature();
|
|
1357
|
+
break;
|
|
1358
|
+
case "4":
|
|
1359
|
+
await configureMcpFeature();
|
|
1360
|
+
break;
|
|
1361
|
+
case "5":
|
|
1362
|
+
await configureDefaultModelFeature();
|
|
1363
|
+
break;
|
|
1364
|
+
case "6":
|
|
1365
|
+
await configureAiMemoryFeature();
|
|
1366
|
+
break;
|
|
1367
|
+
case "7":
|
|
1368
|
+
await configureEnvPermissionFeature();
|
|
1369
|
+
break;
|
|
1370
|
+
case "r":
|
|
1371
|
+
await runCcrMenuFeature();
|
|
1372
|
+
printSeparator();
|
|
1373
|
+
return void 0;
|
|
1374
|
+
case "u":
|
|
1375
|
+
await runCcusageFeature();
|
|
1376
|
+
printSeparator();
|
|
1377
|
+
return void 0;
|
|
1378
|
+
case "l":
|
|
1379
|
+
await runCometixMenuFeature();
|
|
1380
|
+
printSeparator();
|
|
1381
|
+
return void 0;
|
|
1382
|
+
case "0": {
|
|
1383
|
+
const currentLang = i18n.language;
|
|
1384
|
+
await changeScriptLanguageFeature(currentLang);
|
|
1385
|
+
printSeparator();
|
|
1386
|
+
return void 0;
|
|
1387
|
+
}
|
|
1388
|
+
case "-":
|
|
1389
|
+
await uninstall();
|
|
1390
|
+
printSeparator();
|
|
1391
|
+
return void 0;
|
|
1392
|
+
case "+":
|
|
1393
|
+
await checkUpdates();
|
|
1394
|
+
printSeparator();
|
|
1395
|
+
return void 0;
|
|
1396
|
+
case "s": {
|
|
1397
|
+
const switched = await handleCodeToolSwitch("claude-code");
|
|
1398
|
+
if (switched) {
|
|
1399
|
+
return "switch";
|
|
1400
|
+
}
|
|
1401
|
+
printSeparator();
|
|
1402
|
+
return void 0;
|
|
1403
|
+
}
|
|
1404
|
+
case "q":
|
|
1405
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1406
|
+
return "exit";
|
|
1407
|
+
default:
|
|
1408
|
+
return void 0;
|
|
1409
|
+
}
|
|
1410
|
+
printSeparator();
|
|
1411
|
+
const shouldContinue = await promptBoolean({
|
|
1412
|
+
message: i18n.t("common:returnToMenu"),
|
|
1413
|
+
defaultValue: true
|
|
1414
|
+
});
|
|
1415
|
+
if (!shouldContinue) {
|
|
1416
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1417
|
+
return "exit";
|
|
1418
|
+
}
|
|
1419
|
+
return void 0;
|
|
1420
|
+
}
|
|
1421
|
+
async function showCodexMenu() {
|
|
1422
|
+
console.log(ansis.cyan(i18n.t("menu:selectFunction")));
|
|
1423
|
+
console.log(" -------- Codex --------");
|
|
1424
|
+
console.log(
|
|
1425
|
+
` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
|
|
1426
|
+
);
|
|
1427
|
+
console.log(
|
|
1428
|
+
` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
|
|
1429
|
+
);
|
|
1430
|
+
console.log(
|
|
1431
|
+
` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
|
|
1432
|
+
);
|
|
1433
|
+
console.log(
|
|
1434
|
+
` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
|
|
1435
|
+
);
|
|
1436
|
+
console.log(
|
|
1437
|
+
` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
|
|
1438
|
+
);
|
|
1439
|
+
console.log(
|
|
1440
|
+
` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
|
|
1441
|
+
);
|
|
1442
|
+
console.log("");
|
|
1443
|
+
printZcfSection({
|
|
1444
|
+
uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
|
|
1445
|
+
uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
|
|
1446
|
+
updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
|
|
1447
|
+
updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
|
|
1448
|
+
});
|
|
1449
|
+
const { choice } = await inquirer.prompt({
|
|
1450
|
+
type: "input",
|
|
1451
|
+
name: "choice",
|
|
1452
|
+
message: i18n.t("common:enterChoice"),
|
|
1453
|
+
validate: (value) => {
|
|
1454
|
+
const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
|
|
1455
|
+
return valid.includes(value) || i18n.t("common:invalidChoice");
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
if (!choice) {
|
|
1459
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1460
|
+
return "exit";
|
|
1461
|
+
}
|
|
1462
|
+
const normalized = choice.toLowerCase();
|
|
1463
|
+
switch (normalized) {
|
|
1464
|
+
case "1":
|
|
1465
|
+
await runCodexFullInit();
|
|
1466
|
+
break;
|
|
1467
|
+
case "2":
|
|
1468
|
+
await runCodexWorkflowImportWithLanguageSelection();
|
|
1469
|
+
break;
|
|
1470
|
+
case "3":
|
|
1471
|
+
await configureCodexApi();
|
|
1472
|
+
break;
|
|
1473
|
+
case "4":
|
|
1474
|
+
await configureCodexMcp();
|
|
1475
|
+
break;
|
|
1476
|
+
case "5":
|
|
1477
|
+
await configureCodexDefaultModelFeature();
|
|
1478
|
+
break;
|
|
1479
|
+
case "6":
|
|
1480
|
+
await configureCodexAiMemoryFeature();
|
|
1481
|
+
break;
|
|
1482
|
+
case "0": {
|
|
1483
|
+
const currentLang = i18n.language;
|
|
1484
|
+
await changeScriptLanguageFeature(currentLang);
|
|
1485
|
+
printSeparator();
|
|
1486
|
+
return void 0;
|
|
1487
|
+
}
|
|
1488
|
+
case "-":
|
|
1489
|
+
await runCodexUninstall();
|
|
1490
|
+
printSeparator();
|
|
1491
|
+
return void 0;
|
|
1492
|
+
case "+":
|
|
1493
|
+
await runCodexUpdate();
|
|
1494
|
+
printSeparator();
|
|
1495
|
+
return void 0;
|
|
1496
|
+
case "s": {
|
|
1497
|
+
const switched = await handleCodeToolSwitch("codex");
|
|
1498
|
+
if (switched) {
|
|
1499
|
+
return "switch";
|
|
1500
|
+
}
|
|
1501
|
+
printSeparator();
|
|
1502
|
+
return void 0;
|
|
1503
|
+
}
|
|
1504
|
+
case "q":
|
|
1505
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1506
|
+
return "exit";
|
|
1507
|
+
default:
|
|
1508
|
+
return void 0;
|
|
1509
|
+
}
|
|
1510
|
+
printSeparator();
|
|
1511
|
+
const shouldContinue = await promptBoolean({
|
|
1512
|
+
message: i18n.t("common:returnToMenu"),
|
|
1513
|
+
defaultValue: true
|
|
1514
|
+
});
|
|
1515
|
+
if (!shouldContinue) {
|
|
1516
|
+
console.log(ansis.cyan(i18n.t("common:goodbye")));
|
|
1517
|
+
return "exit";
|
|
1518
|
+
}
|
|
1519
|
+
return void 0;
|
|
1520
|
+
}
|
|
1521
|
+
async function showMainMenu(options = {}) {
|
|
1522
|
+
try {
|
|
1523
|
+
if (options.codeType) {
|
|
1524
|
+
try {
|
|
1525
|
+
const resolvedType = await resolveCodeType$1(options.codeType);
|
|
1526
|
+
const currentType = getCurrentCodeTool();
|
|
1527
|
+
if (resolvedType !== currentType) {
|
|
1528
|
+
updateZcfConfig({ codeToolType: resolvedType });
|
|
1529
|
+
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
|
|
1530
|
+
}
|
|
1531
|
+
} catch (err) {
|
|
1532
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1533
|
+
console.error(ansis.yellow(errorMessage));
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
let exitMenu = false;
|
|
1537
|
+
while (!exitMenu) {
|
|
1538
|
+
const codeTool = getCurrentCodeTool();
|
|
1539
|
+
displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "ZCF");
|
|
1540
|
+
const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
|
|
1541
|
+
if (result === "exit") {
|
|
1542
|
+
exitMenu = true;
|
|
1543
|
+
} else if (result === "switch") {
|
|
1544
|
+
continue;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
} catch (error) {
|
|
1548
|
+
if (!handleExitPromptError(error)) {
|
|
1549
|
+
handleGeneralError(error);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
async function ccr(options = {}) {
|
|
1555
|
+
try {
|
|
1556
|
+
if (!options.skipBanner) {
|
|
1557
|
+
displayBannerWithInfo();
|
|
1558
|
+
}
|
|
1559
|
+
const continueInCcr = await showCcrMenu();
|
|
1560
|
+
if (!continueInCcr && !options.skipBanner) {
|
|
1561
|
+
await showMainMenu();
|
|
1562
|
+
}
|
|
1563
|
+
} catch (error) {
|
|
1564
|
+
if (!handleExitPromptError(error)) {
|
|
1565
|
+
handleGeneralError(error);
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
async function configSwitchCommand(options) {
|
|
1571
|
+
try {
|
|
1572
|
+
ensureI18nInitialized();
|
|
1573
|
+
if (options.list) {
|
|
1574
|
+
await handleList(options.codeType);
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1577
|
+
if (options.target) {
|
|
1578
|
+
const resolvedCodeType = resolveCodeType(options.codeType);
|
|
1579
|
+
await handleDirectSwitch(resolvedCodeType, options.target);
|
|
1580
|
+
return;
|
|
1581
|
+
}
|
|
1582
|
+
await handleInteractiveSwitch(options.codeType);
|
|
1583
|
+
} catch (error) {
|
|
1584
|
+
if (process.env.NODE_ENV === "test" || process.env.VITEST) {
|
|
1585
|
+
throw error;
|
|
1586
|
+
}
|
|
1587
|
+
handleGeneralError(error);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
function resolveCodeType(codeType) {
|
|
1591
|
+
if (codeType !== void 0) {
|
|
1592
|
+
const resolved = resolveCodeToolType$1(codeType);
|
|
1593
|
+
return resolved;
|
|
1594
|
+
}
|
|
1595
|
+
const zcfConfig = readZcfConfig();
|
|
1596
|
+
if (zcfConfig?.codeToolType && isCodeToolType(zcfConfig.codeToolType)) {
|
|
1597
|
+
return zcfConfig.codeToolType;
|
|
1598
|
+
}
|
|
1599
|
+
return DEFAULT_CODE_TOOL_TYPE;
|
|
1600
|
+
}
|
|
1601
|
+
async function handleList(codeType) {
|
|
1602
|
+
const targetCodeType = resolveCodeType(codeType);
|
|
1603
|
+
if (targetCodeType === "claude-code") {
|
|
1604
|
+
await listClaudeCodeProfiles();
|
|
1605
|
+
} else if (targetCodeType === "codex") {
|
|
1606
|
+
await listCodexProvidersWithDisplay();
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
async function listCodexProvidersWithDisplay() {
|
|
1610
|
+
const providers = await listCodexProviders();
|
|
1611
|
+
const existingConfig = readCodexConfig();
|
|
1612
|
+
const currentProvider = existingConfig?.modelProvider;
|
|
1613
|
+
const isCommented = existingConfig?.modelProviderCommented;
|
|
1614
|
+
if (!providers || providers.length === 0) {
|
|
1615
|
+
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
1616
|
+
return;
|
|
1617
|
+
}
|
|
1618
|
+
console.log(ansis.bold(i18n.t("codex:listProvidersTitle")));
|
|
1619
|
+
console.log();
|
|
1620
|
+
if (currentProvider && !isCommented) {
|
|
1621
|
+
console.log(ansis.cyan(i18n.t("codex:currentProvider", { provider: currentProvider })));
|
|
1622
|
+
console.log();
|
|
1623
|
+
}
|
|
1624
|
+
providers.forEach((provider) => {
|
|
1625
|
+
const isCurrent = currentProvider === provider.id && !isCommented;
|
|
1626
|
+
const status = isCurrent ? ansis.green("\u25CF ") : " ";
|
|
1627
|
+
const current = isCurrent ? ansis.yellow(` (${i18n.t("common:current")})`) : "";
|
|
1628
|
+
console.log(`${status}${ansis.white(provider.name)}${current}`);
|
|
1629
|
+
console.log(` ${ansis.cyan(`ID: ${provider.id}`)} ${ansis.gray(`(${provider.baseUrl})`)}`);
|
|
1630
|
+
if (provider.tempEnvKey) {
|
|
1631
|
+
console.log(` ${ansis.gray(`Env: ${provider.tempEnvKey}`)}`);
|
|
1632
|
+
}
|
|
1633
|
+
console.log();
|
|
1634
|
+
});
|
|
1635
|
+
}
|
|
1636
|
+
async function listClaudeCodeProfiles() {
|
|
1637
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
1638
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1639
|
+
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
console.log(ansis.bold(i18n.t("multi-config:availableClaudeCodeProfiles")));
|
|
1643
|
+
console.log();
|
|
1644
|
+
const currentProfileId = config.currentProfileId;
|
|
1645
|
+
Object.values(config.profiles).forEach((profile) => {
|
|
1646
|
+
const isCurrent = profile.id === currentProfileId;
|
|
1647
|
+
const status = isCurrent ? ansis.green("\u25CF ") : " ";
|
|
1648
|
+
const current = isCurrent ? ansis.yellow(i18n.t("common:current")) : "";
|
|
1649
|
+
console.log(`${status}${ansis.white(profile.name)}${current}`);
|
|
1650
|
+
console.log(` ${ansis.cyan(`ID: ${profile.id}`)} ${ansis.gray(`(${profile.authType})`)}`);
|
|
1651
|
+
console.log();
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
async function handleDirectSwitch(codeType, target) {
|
|
1655
|
+
const resolvedCodeType = resolveCodeType(codeType);
|
|
1656
|
+
if (resolvedCodeType === "claude-code") {
|
|
1657
|
+
await handleClaudeCodeDirectSwitch(target);
|
|
1658
|
+
} else if (resolvedCodeType === "codex") {
|
|
1659
|
+
await switchCodexProvider(target);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
async function handleClaudeCodeDirectSwitch(target) {
|
|
1663
|
+
if (target === "official") {
|
|
1664
|
+
const result = await ClaudeCodeConfigManager.switchToOfficial();
|
|
1665
|
+
if (result.success) {
|
|
1666
|
+
try {
|
|
1667
|
+
await ClaudeCodeConfigManager.applyProfileSettings(null);
|
|
1668
|
+
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToOfficial")));
|
|
1669
|
+
} catch (error) {
|
|
1670
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1671
|
+
console.log(ansis.red(reason));
|
|
1672
|
+
}
|
|
1673
|
+
} else {
|
|
1674
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
|
|
1675
|
+
}
|
|
1676
|
+
} else if (target === "ccr") {
|
|
1677
|
+
const result = await ClaudeCodeConfigManager.switchToCcr();
|
|
1678
|
+
if (result.success) {
|
|
1679
|
+
try {
|
|
1680
|
+
const profile = ClaudeCodeConfigManager.getProfileById("ccr-proxy");
|
|
1681
|
+
await ClaudeCodeConfigManager.applyProfileSettings(profile);
|
|
1682
|
+
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToCcr")));
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1685
|
+
console.log(ansis.red(reason));
|
|
1686
|
+
}
|
|
1687
|
+
} else {
|
|
1688
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
|
|
1689
|
+
}
|
|
1690
|
+
} else {
|
|
1691
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
1692
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1693
|
+
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
const normalizedTarget = target.trim();
|
|
1697
|
+
let resolvedId = normalizedTarget;
|
|
1698
|
+
let resolvedProfile = config.profiles[normalizedTarget];
|
|
1699
|
+
if (!resolvedProfile) {
|
|
1700
|
+
const match = Object.entries(config.profiles).find(([, profile]) => profile.name === normalizedTarget);
|
|
1701
|
+
if (match) {
|
|
1702
|
+
resolvedId = match[0];
|
|
1703
|
+
resolvedProfile = match[1];
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
if (!resolvedProfile) {
|
|
1707
|
+
console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
const result = await ClaudeCodeConfigManager.switchProfile(resolvedId);
|
|
1711
|
+
if (result.success) {
|
|
1712
|
+
try {
|
|
1713
|
+
await ClaudeCodeConfigManager.applyProfileSettings({ ...resolvedProfile, id: resolvedId });
|
|
1714
|
+
console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToProfile", { name: resolvedProfile.name })));
|
|
1715
|
+
} catch (error) {
|
|
1716
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1717
|
+
console.log(ansis.red(reason));
|
|
1718
|
+
}
|
|
1719
|
+
} else {
|
|
1720
|
+
console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
async function handleInteractiveSwitch(codeType) {
|
|
1725
|
+
const resolvedCodeType = resolveCodeType(codeType);
|
|
1726
|
+
if (resolvedCodeType === "claude-code") {
|
|
1727
|
+
await handleClaudeCodeInteractiveSwitch();
|
|
1728
|
+
} else if (resolvedCodeType === "codex") {
|
|
1729
|
+
await handleCodexInteractiveSwitch();
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
async function handleClaudeCodeInteractiveSwitch() {
|
|
1733
|
+
const config = ClaudeCodeConfigManager.readConfig();
|
|
1734
|
+
if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
|
|
1735
|
+
console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
const currentProfileId = config.currentProfileId;
|
|
1739
|
+
const createClaudeCodeChoices = (profiles, currentProfileId2) => {
|
|
1740
|
+
const choices2 = [];
|
|
1741
|
+
const isOfficialMode = !currentProfileId2 || currentProfileId2 === "official";
|
|
1742
|
+
choices2.push({
|
|
1743
|
+
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
1744
|
+
value: "official"
|
|
1745
|
+
});
|
|
1746
|
+
const isCcrMode = currentProfileId2 === "ccr-proxy";
|
|
1747
|
+
choices2.push({
|
|
1748
|
+
name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
|
|
1749
|
+
value: "ccr"
|
|
1750
|
+
});
|
|
1751
|
+
Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
|
|
1752
|
+
const isCurrent = profile.id === currentProfileId2;
|
|
1753
|
+
choices2.push({
|
|
1754
|
+
name: isCurrent ? `${ansis.green("\u25CF ")}${profile.name} ${ansis.yellow("(current)")}` : ` ${profile.name}`,
|
|
1755
|
+
value: profile.id
|
|
1756
|
+
});
|
|
1757
|
+
});
|
|
1758
|
+
return choices2;
|
|
1759
|
+
};
|
|
1760
|
+
const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
|
|
1761
|
+
try {
|
|
1762
|
+
const { selectedConfig } = await inquirer.prompt([{
|
|
1763
|
+
type: "list",
|
|
1764
|
+
name: "selectedConfig",
|
|
1765
|
+
message: i18n.t("multi-config:selectClaudeCodeConfiguration"),
|
|
1766
|
+
choices: addNumbersToChoices(choices)
|
|
1767
|
+
}]);
|
|
1768
|
+
if (!selectedConfig) {
|
|
1769
|
+
console.log(ansis.yellow(i18n.t("multi-config:cancelled")));
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
await handleClaudeCodeDirectSwitch(selectedConfig);
|
|
1773
|
+
} catch (error) {
|
|
1774
|
+
if (error.name === "ExitPromptError") {
|
|
1775
|
+
console.log(ansis.cyan(`
|
|
1776
|
+
${i18n.t("common:goodbye")}`));
|
|
1777
|
+
return;
|
|
1778
|
+
}
|
|
1779
|
+
throw error;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
async function handleCodexInteractiveSwitch() {
|
|
1783
|
+
const providers = await listCodexProviders();
|
|
1784
|
+
if (!providers || providers.length === 0) {
|
|
1785
|
+
console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
const existingConfig = readCodexConfig();
|
|
1789
|
+
const currentProvider = existingConfig?.modelProvider;
|
|
1790
|
+
const isCommented = existingConfig?.modelProviderCommented;
|
|
1791
|
+
const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
|
|
1792
|
+
const choices2 = [];
|
|
1793
|
+
const isOfficialMode = !currentProvider2 || isCommented2;
|
|
1794
|
+
choices2.push({
|
|
1795
|
+
name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
|
|
1796
|
+
value: "official"
|
|
1797
|
+
});
|
|
1798
|
+
providers2.forEach((provider) => {
|
|
1799
|
+
const isCurrent = currentProvider2 === provider.id && !isCommented2;
|
|
1800
|
+
choices2.push({
|
|
1801
|
+
name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
|
|
1802
|
+
value: provider.id
|
|
1803
|
+
});
|
|
1804
|
+
});
|
|
1805
|
+
return choices2;
|
|
1806
|
+
};
|
|
1807
|
+
const choices = createApiConfigChoices(providers, currentProvider, isCommented);
|
|
1808
|
+
try {
|
|
1809
|
+
const { selectedConfig } = await inquirer.prompt([{
|
|
1810
|
+
type: "list",
|
|
1811
|
+
name: "selectedConfig",
|
|
1812
|
+
message: i18n.t("codex:apiConfigSwitchPrompt"),
|
|
1813
|
+
choices: addNumbersToChoices(choices)
|
|
1814
|
+
}]);
|
|
1815
|
+
if (!selectedConfig) {
|
|
1816
|
+
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
let success = false;
|
|
1820
|
+
if (selectedConfig === "official") {
|
|
1821
|
+
success = await switchToOfficialLogin();
|
|
1822
|
+
} else {
|
|
1823
|
+
success = await switchToProvider(selectedConfig);
|
|
1824
|
+
}
|
|
1825
|
+
if (!success) {
|
|
1826
|
+
console.log(ansis.red(i18n.t("common:operationFailed")));
|
|
1827
|
+
}
|
|
1828
|
+
} catch (error) {
|
|
1829
|
+
if (error.name === "ExitPromptError") {
|
|
1830
|
+
console.log(ansis.cyan(`
|
|
1831
|
+
${i18n.t("common:goodbye")}`));
|
|
1832
|
+
return;
|
|
1833
|
+
}
|
|
1834
|
+
throw error;
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
const configSwitch = {
|
|
1839
|
+
__proto__: null,
|
|
1840
|
+
configSwitchCommand: configSwitchCommand
|
|
1841
|
+
};
|
|
1842
|
+
|
|
1843
|
+
async function resolveAndSwitchLanguage(lang, options, skipPrompt = false) {
|
|
1844
|
+
const zcfConfig = await readZcfConfigAsync();
|
|
1845
|
+
const targetLang = options?.allLang || lang || options?.lang || zcfConfig?.preferredLang || (skipPrompt ? "en" : await selectScriptLanguage());
|
|
1846
|
+
if (i18n.isInitialized && i18n.language !== targetLang) {
|
|
1847
|
+
await changeLanguage(targetLang);
|
|
1848
|
+
}
|
|
1849
|
+
return targetLang;
|
|
1850
|
+
}
|
|
1851
|
+
async function withLanguageResolution(action, skipPrompt = false) {
|
|
1852
|
+
return async (...args) => {
|
|
1853
|
+
const options = args[0];
|
|
1854
|
+
const languageOptions = extractLanguageOptions(options);
|
|
1855
|
+
await resolveAndSwitchLanguage(void 0, languageOptions, skipPrompt || languageOptions.skipPrompt);
|
|
1856
|
+
return await action(...args);
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
function extractLanguageOptions(options) {
|
|
1860
|
+
if (!options || typeof options !== "object" || options === null) {
|
|
1861
|
+
return {};
|
|
1862
|
+
}
|
|
1863
|
+
const obj = options;
|
|
1864
|
+
return {
|
|
1865
|
+
lang: typeof obj.lang === "string" ? obj.lang : void 0,
|
|
1866
|
+
allLang: typeof obj.allLang === "string" ? obj.allLang : void 0,
|
|
1867
|
+
skipPrompt: typeof obj.skipPrompt === "boolean" ? obj.skipPrompt : void 0
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
function customizeHelp(sections) {
|
|
1871
|
+
sections.unshift({
|
|
1872
|
+
title: "",
|
|
1873
|
+
body: ansis.cyan.bold(`ZCF - Zero-Config Code Flow v${version}`)
|
|
1874
|
+
});
|
|
1875
|
+
sections.push({
|
|
1876
|
+
title: ansis.yellow(i18n.t("cli:help.commands")),
|
|
1877
|
+
body: [
|
|
1878
|
+
` ${ansis.cyan("zcf")} ${i18n.t("cli:help.commandDescriptions.showInteractiveMenuDefault")}`,
|
|
1879
|
+
` ${ansis.cyan("zcf init")} | ${ansis.cyan(
|
|
1880
|
+
"i"
|
|
1881
|
+
)} ${i18n.t("cli:help.commandDescriptions.initClaudeCodeConfig")}`,
|
|
1882
|
+
` ${ansis.cyan("zcf update")} | ${ansis.cyan("u")} ${i18n.t("cli:help.commandDescriptions.updateWorkflowFiles")}`,
|
|
1883
|
+
` ${ansis.cyan("zcf ccr")} ${i18n.t("cli:help.commandDescriptions.configureCcrProxy")}`,
|
|
1884
|
+
` ${ansis.cyan("zcf ccu")} [args] ${i18n.t("cli:help.commandDescriptions.claudeCodeUsageAnalysis")}`,
|
|
1885
|
+
` ${ansis.cyan("zcf uninstall")} ${i18n.t("cli:help.commandDescriptions.uninstallConfigurations")}`,
|
|
1886
|
+
` ${ansis.cyan("zcf check-updates")} ${i18n.t("cli:help.commandDescriptions.checkUpdateVersions")}`,
|
|
1887
|
+
"",
|
|
1888
|
+
ansis.gray(` ${i18n.t("cli:help.shortcuts")}`),
|
|
1889
|
+
` ${ansis.cyan("zcf i")} ${i18n.t("cli:help.shortcutDescriptions.quickInit")}`,
|
|
1890
|
+
` ${ansis.cyan("zcf u")} ${i18n.t("cli:help.shortcutDescriptions.quickUpdate")}`,
|
|
1891
|
+
` ${ansis.cyan("zcf check")} ${i18n.t("cli:help.shortcutDescriptions.quickCheckUpdates")}`
|
|
1892
|
+
].join("\n")
|
|
1893
|
+
});
|
|
1894
|
+
sections.push({
|
|
1895
|
+
title: ansis.yellow(i18n.t("cli:help.options")),
|
|
1896
|
+
body: [
|
|
1897
|
+
` ${ansis.green("--lang, -l")} <lang> ${i18n.t("cli:help.optionDescriptions.displayLanguage")} (zh-CN, en)`,
|
|
1898
|
+
` ${ansis.green("--config-lang, -c")} <lang> ${i18n.t("cli:help.optionDescriptions.configurationLanguage")} (zh-CN, en)`,
|
|
1899
|
+
` ${ansis.green("--force, -f")} ${i18n.t("cli:help.optionDescriptions.forceOverwrite")}`,
|
|
1900
|
+
` ${ansis.green("--help, -h")} ${i18n.t("cli:help.optionDescriptions.displayHelp")}`,
|
|
1901
|
+
` ${ansis.green("--version, -v")} ${i18n.t("cli:help.optionDescriptions.displayVersion")}`,
|
|
1902
|
+
"",
|
|
1903
|
+
ansis.gray(` ${i18n.t("cli:help.nonInteractiveMode")}`),
|
|
1904
|
+
` ${ansis.green("--skip-prompt, -s")} ${i18n.t("cli:help.optionDescriptions.skipAllPrompts")}`,
|
|
1905
|
+
` ${ansis.green("--api-type, -t")} <type> ${i18n.t("cli:help.optionDescriptions.apiType")} (auth_token, api_key, ccr_proxy, skip)`,
|
|
1906
|
+
` ${ansis.green("--api-key, -k")} <key> ${i18n.t("cli:help.optionDescriptions.apiKey")}`,
|
|
1907
|
+
` ${ansis.green("--api-url, -u")} <url> ${i18n.t("cli:help.optionDescriptions.customApiUrl")}`,
|
|
1908
|
+
` ${ansis.green("--api-model, -M")} <model> ${i18n.t("cli:help.optionDescriptions.apiModel")} (e.g., claude-sonnet-4-5)`,
|
|
1909
|
+
` ${ansis.green("--api-haiku-model, -H")} <model> ${i18n.t("cli:help.optionDescriptions.apiHaikuModel")} (e.g., claude-haiku-4-5)`,
|
|
1910
|
+
` ${ansis.green("--api-sonnet-model, -S")} <model> ${i18n.t("cli:help.optionDescriptions.apiSonnetModel")} (e.g., claude-sonnet-4-5)`,
|
|
1911
|
+
` ${ansis.green("--api-opus-model, -O")} <model> ${i18n.t("cli:help.optionDescriptions.apiOpusModel")} (e.g., claude-opus-4-5)`,
|
|
1912
|
+
` ${ansis.green("--ai-output-lang, -a")} <lang> ${i18n.t("cli:help.optionDescriptions.aiOutputLanguage")}`,
|
|
1913
|
+
` ${ansis.green("--all-lang, -g")} <lang> ${i18n.t("cli:help.optionDescriptions.setAllLanguageParams")}`,
|
|
1914
|
+
` ${ansis.green("--config-action, -r")} <action> ${i18n.t("cli:help.optionDescriptions.configHandling")} (${i18n.t("cli:help.defaults.prefix")} backup)`,
|
|
1915
|
+
` ${ansis.green("--mcp-services, -m")} <list> ${i18n.t("cli:help.optionDescriptions.mcpServices")} (${i18n.t("cli:help.defaults.prefix")} all non-key services)`,
|
|
1916
|
+
` ${ansis.green("--workflows, -w")} <list> ${i18n.t("cli:help.optionDescriptions.workflows")} (${i18n.t("cli:help.defaults.prefix")} all workflows)`,
|
|
1917
|
+
` ${ansis.green("--output-styles, -o")} <styles> ${i18n.t("cli:help.optionDescriptions.outputStyles")} (${i18n.t("cli:help.defaults.prefix")} all custom styles)`,
|
|
1918
|
+
` ${ansis.green("--default-output-style, -d")} <style> ${i18n.t("cli:help.optionDescriptions.defaultOutputStyle")} (${i18n.t("cli:help.defaults.prefix")} engineer-professional)`,
|
|
1919
|
+
` ${ansis.green("--code-type, -T")} <type> ${i18n.t("cli:help.optionDescriptions.codeToolType")} (claude-code, codex, cc=claude-code, cx=codex)`,
|
|
1920
|
+
` ${ansis.green("--install-cometix-line, -x")} <value> ${i18n.t("cli:help.optionDescriptions.installStatuslineTool")} (${i18n.t("cli:help.defaults.prefix")} true)`
|
|
1921
|
+
].join("\n")
|
|
1922
|
+
});
|
|
1923
|
+
sections.push({
|
|
1924
|
+
title: ansis.yellow(i18n.t("cli:help.examples")),
|
|
1925
|
+
body: [
|
|
1926
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.showInteractiveMenu")}`),
|
|
1927
|
+
` ${ansis.cyan("npx @benbenwu/zcf")}`,
|
|
1928
|
+
"",
|
|
1929
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.runFullInitialization")}`),
|
|
1930
|
+
` ${ansis.cyan("npx @benbenwu/zcf init")}`,
|
|
1931
|
+
` ${ansis.cyan("npx @benbenwu/zcf i")}`,
|
|
1932
|
+
"",
|
|
1933
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.updateWorkflowFilesOnly")}`),
|
|
1934
|
+
` ${ansis.cyan("npx @benbenwu/zcf u")}`,
|
|
1935
|
+
"",
|
|
1936
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.configureClaudeCodeRouter")}`),
|
|
1937
|
+
` ${ansis.cyan("npx @benbenwu/zcf ccr")}`,
|
|
1938
|
+
"",
|
|
1939
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.runClaudeCodeUsageAnalysis")}`),
|
|
1940
|
+
` ${ansis.cyan("npx @benbenwu/zcf ccu")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.dailyUsage")}`)}`,
|
|
1941
|
+
` ${ansis.cyan("npx @benbenwu/zcf ccu monthly --json")}`,
|
|
1942
|
+
"",
|
|
1943
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.uninstallConfigurations")}`),
|
|
1944
|
+
` ${ansis.cyan("npx @benbenwu/zcf uninstall")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.interactiveUninstall")}`)}`,
|
|
1945
|
+
"",
|
|
1946
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkAndUpdateTools")}`),
|
|
1947
|
+
` ${ansis.cyan("npx @benbenwu/zcf check-updates")} ${ansis.gray(`# ${i18n.t("cli:help.defaults.updateTools")}`)}`,
|
|
1948
|
+
` ${ansis.cyan("npx @benbenwu/zcf check")}`,
|
|
1949
|
+
"",
|
|
1950
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkClaudeCode")}`),
|
|
1951
|
+
` ${ansis.cyan("npx @benbenwu/zcf check --code-type claude-code")}`,
|
|
1952
|
+
` ${ansis.cyan("npx @benbenwu/zcf check -T cc")}`,
|
|
1953
|
+
"",
|
|
1954
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.checkCodex")}`),
|
|
1955
|
+
` ${ansis.cyan("npx @benbenwu/zcf check --code-type codex")}`,
|
|
1956
|
+
` ${ansis.cyan("npx @benbenwu/zcf check -T cx")}`,
|
|
1957
|
+
"",
|
|
1958
|
+
ansis.gray(` # ${i18n.t("cli:help.exampleDescriptions.nonInteractiveModeCicd")}`),
|
|
1959
|
+
` ${ansis.cyan('npx @benbenwu/zcf i --skip-prompt --api-type api_key --api-key "sk-ant-..."')}`,
|
|
1960
|
+
` ${ansis.cyan('npx @benbenwu/zcf i --skip-prompt --all-lang zh-CN --api-type api_key --api-key "key"')}`,
|
|
1961
|
+
` ${ansis.cyan("npx @benbenwu/zcf i --skip-prompt --api-type ccr_proxy")}`,
|
|
1962
|
+
""
|
|
1963
|
+
].join("\n")
|
|
1964
|
+
});
|
|
1965
|
+
return sections;
|
|
1966
|
+
}
|
|
1967
|
+
async function setupCommands(cli) {
|
|
1968
|
+
try {
|
|
1969
|
+
const zcfConfig = await readZcfConfigAsync();
|
|
1970
|
+
const defaultLang = zcfConfig?.preferredLang || "en";
|
|
1971
|
+
await initI18n(defaultLang);
|
|
1972
|
+
} catch {
|
|
1973
|
+
}
|
|
1974
|
+
cli.command("", "Show interactive menu (default)").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").action(await withLanguageResolution(async (options) => {
|
|
1975
|
+
await showMainMenu({ codeType: options.codeType });
|
|
1976
|
+
}));
|
|
1977
|
+
cli.command("init", "Initialize Claude Code configuration").alias("i").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--ai-output-lang, -a <lang>", "AI output language").option("--force, -f", "Force overwrite existing configuration").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").option("--config-action, -r <action>", `Config handling (new/backup/merge/docs-only/skip), ${i18n.t("cli:help.defaults.prefix")} backup`).option("--api-type, -t <type>", "API type (auth_token/api_key/ccr_proxy/skip)").option("--api-key, -k <key>", "API key (used for both API key and auth token types)").option("--api-url, -u <url>", "Custom API URL").option("--api-model, -M <model>", "Primary API model (e.g., claude-sonnet-4-5)").option("--api-haiku-model, -H <model>", "Default Haiku model (e.g., claude-haiku-4-5)").option("--api-sonnet-model, -S <model>", "Default Sonnet model (e.g., claude-sonnet-4-5)").option("--api-opus-model, -O <model>", "Default Opus model (e.g., claude-opus-4-5)").option("--provider, -p <provider>", "API provider preset (302ai, glm, minimax, kimi, custom)").option("--mcp-services, -m <services>", `Comma-separated MCP services to install (context7,mcp-deepwiki,Playwright,exa), "skip" to skip all, "all" for all non-key services, ${i18n.t("cli:help.defaults.prefix")} all`).option("--workflows, -w <workflows>", `Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, ${i18n.t("cli:help.defaults.prefix")} all`).option("--output-styles, -o <styles>", `Comma-separated output styles (engineer-professional,nekomata-engineer,laowang-engineer,default,explanatory,learning), "skip" to skip all, "all" for all custom styles, ${i18n.t("cli:help.defaults.prefix")} all`).option("--default-output-style, -d <style>", `Default output style, ${i18n.t("cli:help.defaults.prefix")} engineer-professional`).option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--install-cometix-line, -x <value>", `Install CCometixLine statusline tool (true/false), ${i18n.t("cli:help.defaults.prefix")} true`).option("--api-configs <configs>", "API configurations as JSON string for multiple profiles").option("--api-configs-file <file>", "Path to JSON file containing API configurations").action(await withLanguageResolution(async (options) => {
|
|
1978
|
+
await init(options);
|
|
1979
|
+
}));
|
|
1980
|
+
cli.command("update", "Update Claude Code prompts only").alias("u").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").action(await withLanguageResolution(async (options) => {
|
|
1981
|
+
await update(options);
|
|
1982
|
+
}));
|
|
1983
|
+
cli.command("ccr", "Configure Claude Code Router for model proxy").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").action(await withLanguageResolution(async () => {
|
|
1984
|
+
await ccr();
|
|
1985
|
+
}));
|
|
1986
|
+
cli.command("ccu [...args]", "Run Claude Code usage analysis tool").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").allowUnknownOptions().action(await withLanguageResolution(async (args) => {
|
|
1987
|
+
await executeCcusage(args);
|
|
1988
|
+
}));
|
|
1989
|
+
cli.command("config-switch [target]", "Switch Codex provider or Claude Code configuration, or list available configurations").alias("cs").option("--code-type, -T <type>", "Code tool type (claude-code, codex, cc, cx)").option("--lang <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--list, -l", "List available configurations").action(await withLanguageResolution(async (target, options) => {
|
|
1990
|
+
await configSwitchCommand({
|
|
1991
|
+
target,
|
|
1992
|
+
codeType: options.codeType,
|
|
1993
|
+
list: options.list
|
|
1994
|
+
});
|
|
1995
|
+
}));
|
|
1996
|
+
cli.command("uninstall", "Remove ZCF configurations and tools").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--mode, -m <mode>", "Uninstall mode (complete/custom/interactive), default: interactive").option("--items, -i <items>", "Comma-separated items for custom uninstall mode").action(await withLanguageResolution(async (options) => {
|
|
1997
|
+
await uninstall(options);
|
|
1998
|
+
}));
|
|
1999
|
+
cli.command("check-updates", "Check and update Claude Code and CCR to latest versions").alias("check").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").action(await withLanguageResolution(async (options) => {
|
|
2000
|
+
await checkUpdates(options);
|
|
2001
|
+
}));
|
|
2002
|
+
cli.help((sections) => customizeHelp(sections));
|
|
2003
|
+
cli.version(version);
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
async function main() {
|
|
2007
|
+
const cli = cac("zcf");
|
|
2008
|
+
await setupCommands(cli);
|
|
2009
|
+
cli.parse();
|
|
2010
|
+
}
|
|
2011
|
+
main().catch(console.error);
|
|
2012
|
+
|
|
2013
|
+
export { configSwitch as c };
|