ccjk 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.ja.md +249 -297
  2. package/README.ko.md +241 -290
  3. package/README.md +216 -360
  4. package/README.zh-CN.md +234 -311
  5. package/dist/chunks/claude-code-config-manager.mjs +7 -7
  6. package/dist/chunks/claude-code-incremental-manager.mjs +1 -1
  7. package/dist/chunks/codex-config-switch.mjs +3 -3
  8. package/dist/chunks/codex-uninstaller.mjs +2 -2
  9. package/dist/chunks/features.mjs +10 -10
  10. package/dist/chunks/simple-config.mjs +388 -45
  11. package/dist/chunks/smart-guide.mjs +234 -0
  12. package/dist/cli.mjs +2325 -1317
  13. package/dist/i18n/locales/en/marketplace.json +84 -0
  14. package/dist/i18n/locales/en/menu.json +38 -1
  15. package/dist/i18n/locales/en/skills.json +140 -0
  16. package/dist/i18n/locales/en/smartGuide.json +49 -0
  17. package/dist/i18n/locales/en/subagent.json +69 -0
  18. package/dist/i18n/locales/en/superpowers.json +58 -0
  19. package/dist/i18n/locales/en/workflow.json +28 -9
  20. package/dist/i18n/locales/zh-CN/marketplace.json +84 -0
  21. package/dist/i18n/locales/zh-CN/menu.json +38 -1
  22. package/dist/i18n/locales/zh-CN/skills.json +140 -0
  23. package/dist/i18n/locales/zh-CN/smartGuide.json +49 -0
  24. package/dist/i18n/locales/zh-CN/subagent.json +69 -0
  25. package/dist/i18n/locales/zh-CN/superpowers.json +58 -0
  26. package/dist/i18n/locales/zh-CN/workflow.json +28 -9
  27. package/dist/index.d.mts +1 -0
  28. package/dist/index.d.ts +1 -0
  29. package/package.json +26 -27
  30. package/templates/claude-code/en/workflow/essential/commands/feat.md +196 -51
  31. package/templates/claude-code/zh-CN/workflow/essential/commands/feat.md +194 -51
  32. package/templates/common/skills/en/brainstorming.md +64 -0
  33. package/templates/common/skills/en/code-review.md +81 -0
  34. package/templates/common/skills/en/documentation-gen.md +808 -0
  35. package/templates/common/skills/en/executing-plans.md +75 -0
  36. package/templates/common/skills/en/git-commit.md +216 -0
  37. package/templates/common/skills/en/interview.md +223 -0
  38. package/templates/common/skills/en/migration-assistant.md +312 -0
  39. package/templates/common/skills/en/performance-profiling.md +576 -0
  40. package/templates/common/skills/en/pr-review.md +341 -0
  41. package/templates/common/skills/en/refactoring.md +384 -0
  42. package/templates/common/skills/en/security-audit.md +462 -0
  43. package/templates/common/skills/en/systematic-debugging.md +82 -0
  44. package/templates/common/skills/en/tdd-workflow.md +93 -0
  45. package/templates/common/skills/en/verification.md +81 -0
  46. package/templates/common/skills/en/workflow.md +370 -0
  47. package/templates/common/skills/en/writing-plans.md +78 -0
  48. package/templates/common/skills/zh-CN/documentation-gen.md +807 -0
  49. package/templates/common/skills/zh-CN/migration-assistant.md +318 -0
  50. package/templates/common/skills/zh-CN/performance-profiling.md +746 -0
  51. package/templates/common/skills/zh-CN/pr-review.md +341 -0
  52. package/templates/common/skills/zh-CN/refactoring.md +384 -0
  53. package/templates/common/skills/zh-CN/security-audit.md +462 -0
  54. package/templates/common/smart-guide/en/smart-guide.md +72 -0
  55. package/templates/common/smart-guide/zh-CN/smart-guide.md +72 -0
  56. package/templates/common/workflow/sixStep/en/workflow.md +137 -31
  57. package/templates/common/workflow/sixStep/zh-CN/workflow.md +152 -10
package/dist/cli.mjs CHANGED
@@ -1,20 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import cac from 'cac';
3
3
  import ansis from 'ansis';
4
- import { S as STATUS, cj as i18n, r as runConfigWizard, ck as testApiConnection, h as displayCurrentStatus, cl as quickSetup, cm as format, g as COLORS, cn as getAllPresets, co as ensureI18nInitialized, cp as readCcrConfig, cq as isCcrInstalled, cr as installCcr, cs as configureCcrFeature, ct as promptBoolean, cu as handleExitPromptError, cv as handleGeneralError, cw as COMETIX_COMMAND_NAME, cx as COMETIX_COMMANDS, cy as installCometixLine, cz as addNumbersToChoices, cA as checkAndUpdateTools, aR as runCodexUpdate, cB as resolveCodeType$1, cC as readJsonConfig, cD as writeJsonConfig, cE as moveToTrash, N as ZCF_CONFIG_FILE, cF as readZcfConfig, P as DEFAULT_CODE_TOOL_TYPE, U as isCodeToolType, ab as displayBanner, cG as updateZcfConfig, cH as version, cI as resolveAiOutputLanguage, cJ as updatePromptOnly, cK as selectAndInstallWorkflows, cL as checkClaudeCodeVersionAndPrompt, X as resolveCodeToolType$1, ac as displayBannerWithInfo, Q as CODE_TOOL_BANNERS, aQ as runCodexUninstall, b0 as configureCodexMcp, az as configureCodexApi, aT as runCodexWorkflowImportWithLanguageSelection, aO as runCodexFullInit, i as init, aV as switchCodexProvider, aH as listCodexProviders, aM as readCodexConfig, ay as switchToOfficialLogin, aW as switchToProvider, T as CODE_TOOL_INFO, b6 as getToolStatus, b7 as getAllToolsStatus, O as CODE_TOOL_TYPES, ae as boxify, b9 as installTool, cM as readZcfConfigAsync, cN as initI18n, bU as quickSync, bA as runDoctor, ch as checkAllVersions, ci as upgradeAll, bs as detectAllConfigs, bx as displayConfigScan, c9 as displayPermissions, cO as selectScriptLanguage, cP as changeLanguage, bT as runOnboarding } from './chunks/simple-config.mjs';
4
+ import { S as STATUS, cj as i18n, r as runConfigWizard, ck as testApiConnection, h as displayCurrentStatus, cl as quickSetup, cm as format, g as COLORS, cn as getAllPresets, co as ensureI18nInitialized, cp as readCcrConfig, cq as isCcrInstalled, cr as installCcr, cs as configureCcrFeature, ct as promptBoolean, cu as handleExitPromptError, cv as handleGeneralError, cw as COMETIX_COMMAND_NAME, cx as COMETIX_COMMANDS, cy as installCometixLine, cz as addNumbersToChoices, cA as checkAndUpdateTools, aR as runCodexUpdate, cB as resolveCodeType$1, X as resolveCodeToolType$1, cC as readZcfConfig, U as isCodeToolType, P as DEFAULT_CODE_TOOL_TYPE, aV as switchCodexProvider, aH as listCodexProviders, aM as readCodexConfig, ay as switchToOfficialLogin, aW as switchToProvider, cD as readJsonConfig, cE as writeJsonConfig, cF as moveToTrash, N as ZCF_CONFIG_FILE, ab as displayBanner, cG as updateZcfConfig, cH as version, cI as resolveAiOutputLanguage, cJ as updatePromptOnly, cK as selectAndInstallWorkflows, cL as checkClaudeCodeVersionAndPrompt, ac as displayBannerWithInfo, Q as CODE_TOOL_BANNERS, aQ as runCodexUninstall, b0 as configureCodexMcp, az as configureCodexApi, aT as runCodexWorkflowImportWithLanguageSelection, aO as runCodexFullInit, i as init, cM as checkSuperpowersInstalled, cN as getSuperpowersSkills, cO as updateSuperpowers, cP as uninstallSuperpowers, cQ as installSuperpowers, cR as installSuperpowersViaGit, T as CODE_TOOL_INFO, b6 as getToolStatus, b7 as getAllToolsStatus, O as CODE_TOOL_TYPES, ae as boxify, b9 as installTool, cS as readZcfConfigAsync, cT as initI18n, bU as quickSync, bA as runDoctor, ch as checkAllVersions, ci as upgradeAll, bs as detectAllConfigs, bx as displayConfigScan, c9 as displayPermissions, cU as selectScriptLanguage, cV as changeLanguage, bT as runOnboarding } from './chunks/simple-config.mjs';
5
5
  import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
6
6
  import { homedir } from 'node:os';
7
7
  import inquirer from 'inquirer';
8
8
  import { join, resolve as resolve$1 } from 'pathe';
9
9
  import { runCcrStop, runCcrStart, runCcrRestart, runCcrStatus, runCcrUi } from './chunks/commands.mjs';
10
10
  import { changeScriptLanguageFeature, configureCodexAiMemoryFeature, configureCodexDefaultModelFeature, configureEnvPermissionFeature, configureAiMemoryFeature, configureDefaultModelFeature, configureMcpFeature, configureApiFeature } from './chunks/features.mjs';
11
+ import { readFile, mkdir, writeFile, rm, readdir } from 'node:fs/promises';
12
+ import { isSmartGuideInstalled, generateSkillReferenceCard, removeSmartGuide, injectSmartGuide, generateQuickActionsPanel, QUICK_ACTIONS } from './chunks/smart-guide.mjs';
11
13
  import process$1 from 'node:process';
12
14
  import { x, exec as exec$1 } from 'tinyexec';
13
15
  import { spawn, exec } from 'node:child_process';
14
16
  import { promisify } from 'node:util';
15
- import { pathExists } from 'fs-extra';
16
17
  import { ClaudeCodeConfigManager } from './chunks/claude-code-config-manager.mjs';
17
- import { writeFile, readFile, mkdir, readdir } from 'node:fs/promises';
18
+ import { pathExists } from 'fs-extra';
18
19
  import { join as join$1, resolve, dirname } from 'node:path';
19
20
  import { randomUUID } from 'node:crypto';
20
21
  import ora from 'ora';
@@ -230,6 +231,355 @@ ${ansis.dim("\u2500".repeat(50))}
230
231
  }
231
232
  }
232
233
 
234
+ const DEFAULT_REGISTRY_URL = "https://registry.ccjk.dev/v1";
235
+ const DEFAULT_CACHE_CONFIG = {
236
+ cacheDir: join(homedir(), ".ccjk", "cache"),
237
+ ttl: 3600,
238
+ // 1 hour
239
+ enabled: true
240
+ };
241
+ const BUILTIN_PACKAGES = [
242
+ // Built-in packages will be added here in future versions
243
+ ];
244
+ function getCacheFilePath(cacheDir) {
245
+ return join(cacheDir, "registry-cache.json");
246
+ }
247
+ async function isCacheValid(cacheDir, ttl) {
248
+ const cachePath = getCacheFilePath(cacheDir);
249
+ if (!existsSync(cachePath)) {
250
+ return false;
251
+ }
252
+ try {
253
+ const content = await readFile(cachePath, "utf-8");
254
+ const cache = JSON.parse(content);
255
+ const cacheTime = new Date(cache.lastUpdated).getTime();
256
+ const now = Date.now();
257
+ return now - cacheTime < ttl * 1e3;
258
+ } catch {
259
+ return false;
260
+ }
261
+ }
262
+ async function readCachedRegistry(cacheDir) {
263
+ const cachePath = getCacheFilePath(cacheDir);
264
+ if (!existsSync(cachePath)) {
265
+ return null;
266
+ }
267
+ try {
268
+ const content = await readFile(cachePath, "utf-8");
269
+ return JSON.parse(content);
270
+ } catch {
271
+ return null;
272
+ }
273
+ }
274
+ async function writeCacheRegistry(cacheDir, registry) {
275
+ await mkdir(cacheDir, { recursive: true });
276
+ const cachePath = getCacheFilePath(cacheDir);
277
+ await writeFile(cachePath, JSON.stringify(registry, null, 2));
278
+ }
279
+ async function fetchRemoteRegistry(registryUrl = DEFAULT_REGISTRY_URL, timeout = 3e4) {
280
+ const controller = new AbortController();
281
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
282
+ try {
283
+ const response = await fetch(`${registryUrl}/registry.json`, {
284
+ signal: controller.signal,
285
+ headers: {
286
+ "Accept": "application/json",
287
+ "User-Agent": "ccjk-cli"
288
+ }
289
+ });
290
+ if (!response.ok) {
291
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
292
+ }
293
+ return await response.json();
294
+ } finally {
295
+ clearTimeout(timeoutId);
296
+ }
297
+ }
298
+ async function getRegistry(options = {}) {
299
+ const cacheConfig = { ...DEFAULT_CACHE_CONFIG, ...options.cache };
300
+ const registryUrl = options.registryUrl || DEFAULT_REGISTRY_URL;
301
+ if (cacheConfig.enabled && !options.forceRefresh) {
302
+ const cacheValid = await isCacheValid(cacheConfig.cacheDir, cacheConfig.ttl);
303
+ if (cacheValid) {
304
+ const cached = await readCachedRegistry(cacheConfig.cacheDir);
305
+ if (cached) {
306
+ return cached;
307
+ }
308
+ }
309
+ }
310
+ try {
311
+ const registry = await fetchRemoteRegistry(registryUrl);
312
+ if (cacheConfig.enabled) {
313
+ await writeCacheRegistry(cacheConfig.cacheDir, registry);
314
+ }
315
+ return registry;
316
+ } catch {
317
+ const cached = await readCachedRegistry(cacheConfig.cacheDir);
318
+ if (cached) {
319
+ return cached;
320
+ }
321
+ return {
322
+ version: "1.0.0",
323
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
324
+ url: registryUrl,
325
+ packages: BUILTIN_PACKAGES,
326
+ categories: {
327
+ "plugin": 0,
328
+ "skill": 0,
329
+ "workflow": 0,
330
+ "agent": 0,
331
+ "mcp-service": 0,
332
+ "output-style": 0,
333
+ "bundle": 0
334
+ }
335
+ };
336
+ }
337
+ }
338
+ async function searchPackages(options = {}) {
339
+ const registry = await getRegistry();
340
+ let packages = [...registry.packages];
341
+ if (options.query) {
342
+ const query = options.query.toLowerCase();
343
+ packages = packages.filter(
344
+ (pkg) => pkg.name.toLowerCase().includes(query) || pkg.id.toLowerCase().includes(query) || pkg.keywords.some((k) => k.toLowerCase().includes(query)) || Object.values(pkg.description).some((d) => d.toLowerCase().includes(query))
345
+ );
346
+ }
347
+ if (options.category) {
348
+ packages = packages.filter((pkg) => pkg.category === options.category);
349
+ }
350
+ if (options.author) {
351
+ packages = packages.filter(
352
+ (pkg) => pkg.author.toLowerCase().includes(options.author.toLowerCase())
353
+ );
354
+ }
355
+ if (options.verified) {
356
+ packages = packages.filter((pkg) => pkg.verified === options.verified);
357
+ }
358
+ if (options.keywords?.length) {
359
+ packages = packages.filter(
360
+ (pkg) => options.keywords.some((k) => pkg.keywords.includes(k))
361
+ );
362
+ }
363
+ if (options.minRating) {
364
+ packages = packages.filter((pkg) => pkg.rating >= options.minRating);
365
+ }
366
+ if (options.supportedTool) {
367
+ packages = packages.filter(
368
+ (pkg) => pkg.supportedTools?.includes(options.supportedTool)
369
+ );
370
+ }
371
+ const sortBy = options.sortBy || "downloads";
372
+ const sortDir = options.sortDir || "desc";
373
+ packages.sort((a, b) => {
374
+ let comparison = 0;
375
+ switch (sortBy) {
376
+ case "downloads":
377
+ comparison = a.downloads - b.downloads;
378
+ break;
379
+ case "rating":
380
+ comparison = a.rating - b.rating;
381
+ break;
382
+ case "updated":
383
+ comparison = new Date(a.updatedAt).getTime() - new Date(b.updatedAt).getTime();
384
+ break;
385
+ case "created":
386
+ comparison = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
387
+ break;
388
+ case "name":
389
+ comparison = a.name.localeCompare(b.name);
390
+ break;
391
+ }
392
+ return sortDir === "desc" ? -comparison : comparison;
393
+ });
394
+ const total = packages.length;
395
+ const offset = options.offset || 0;
396
+ const limit = options.limit || 20;
397
+ packages = packages.slice(offset, offset + limit);
398
+ return {
399
+ packages,
400
+ total,
401
+ offset,
402
+ limit,
403
+ query: options.query,
404
+ filters: options
405
+ };
406
+ }
407
+ async function getPackage(packageId) {
408
+ const registry = await getRegistry();
409
+ return registry.packages.find((pkg) => pkg.id === packageId) || null;
410
+ }
411
+
412
+ const DEFAULT_INSTALL_DIR = join(homedir(), ".ccjk", "packages");
413
+ const INSTALLED_MANIFEST = join(homedir(), ".ccjk", "installed-packages.json");
414
+ async function getInstalledPackages() {
415
+ if (!existsSync(INSTALLED_MANIFEST)) {
416
+ return [];
417
+ }
418
+ try {
419
+ const content = await readFile(INSTALLED_MANIFEST, "utf-8");
420
+ return JSON.parse(content);
421
+ } catch {
422
+ return [];
423
+ }
424
+ }
425
+ async function saveInstalledPackages(packages) {
426
+ const dir = join(homedir(), ".ccjk");
427
+ await mkdir(dir, { recursive: true });
428
+ await writeFile(INSTALLED_MANIFEST, JSON.stringify(packages, null, 2));
429
+ }
430
+ async function isPackageInstalled(packageId) {
431
+ const installed = await getInstalledPackages();
432
+ return installed.some((pkg) => pkg.package.id === packageId);
433
+ }
434
+ async function installPackage(packageId, options = {}) {
435
+ const startTime = Date.now();
436
+ try {
437
+ const alreadyInstalled = await isPackageInstalled(packageId);
438
+ if (alreadyInstalled && !options.force) {
439
+ const pkg2 = await getPackage(packageId);
440
+ if (!pkg2) {
441
+ return {
442
+ success: false,
443
+ package: {},
444
+ error: i18n.t("marketplace:packageNotFound", { name: packageId })
445
+ };
446
+ }
447
+ return {
448
+ success: true,
449
+ package: pkg2,
450
+ alreadyInstalled: true,
451
+ durationMs: Date.now() - startTime
452
+ };
453
+ }
454
+ const pkg = await getPackage(packageId);
455
+ if (!pkg) {
456
+ return {
457
+ success: false,
458
+ package: {},
459
+ error: i18n.t("marketplace:packageNotFound", { name: packageId })
460
+ };
461
+ }
462
+ const warnings = [];
463
+ if (options.codeToolType && pkg.supportedTools) {
464
+ if (!pkg.supportedTools.includes(options.codeToolType)) {
465
+ warnings.push(
466
+ i18n.t("marketplace:incompatibleTool", {
467
+ tool: options.codeToolType,
468
+ supported: pkg.supportedTools.join(", ")
469
+ })
470
+ );
471
+ }
472
+ }
473
+ const targetDir = options.targetDir || DEFAULT_INSTALL_DIR;
474
+ const installPath = join(targetDir, pkg.id);
475
+ await mkdir(installPath, { recursive: true });
476
+ const installed = await getInstalledPackages();
477
+ const installedPackage = {
478
+ package: pkg,
479
+ path: installPath,
480
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
481
+ source: "marketplace",
482
+ enabled: true
483
+ };
484
+ const existingIndex = installed.findIndex((p) => p.package.id === pkg.id);
485
+ if (existingIndex >= 0) {
486
+ installed[existingIndex] = installedPackage;
487
+ } else {
488
+ installed.push(installedPackage);
489
+ }
490
+ await saveInstalledPackages(installed);
491
+ return {
492
+ success: true,
493
+ package: pkg,
494
+ installedPath: installPath,
495
+ warnings: warnings.length > 0 ? warnings : void 0,
496
+ durationMs: Date.now() - startTime
497
+ };
498
+ } catch (error) {
499
+ return {
500
+ success: false,
501
+ package: {},
502
+ error: error instanceof Error ? error.message : String(error),
503
+ durationMs: Date.now() - startTime
504
+ };
505
+ }
506
+ }
507
+ async function uninstallPackage(packageId, options = {}) {
508
+ try {
509
+ const installed = await getInstalledPackages();
510
+ const pkg = installed.find((p) => p.package.id === packageId);
511
+ if (!pkg) {
512
+ return {
513
+ success: false,
514
+ packageId,
515
+ error: i18n.t("marketplace:packageNotInstalled", { name: packageId })
516
+ };
517
+ }
518
+ if (!options.force) {
519
+ const dependents = installed.filter(
520
+ (p) => p.package.dependencies && Object.keys(p.package.dependencies).includes(packageId)
521
+ );
522
+ if (dependents.length > 0) {
523
+ return {
524
+ success: false,
525
+ packageId,
526
+ error: i18n.t("marketplace:packageHasDependents", {
527
+ name: packageId,
528
+ dependents: dependents.map((p) => p.package.name).join(", ")
529
+ })
530
+ };
531
+ }
532
+ }
533
+ if (existsSync(pkg.path)) {
534
+ await rm(pkg.path, { recursive: true, force: true });
535
+ }
536
+ const updated = installed.filter((p) => p.package.id !== packageId);
537
+ await saveInstalledPackages(updated);
538
+ return {
539
+ success: true,
540
+ packageId
541
+ };
542
+ } catch (error) {
543
+ return {
544
+ success: false,
545
+ packageId,
546
+ error: error instanceof Error ? error.message : String(error)
547
+ };
548
+ }
549
+ }
550
+ async function updatePackage(packageId) {
551
+ const uninstallResult = await uninstallPackage(packageId, { keepConfig: true });
552
+ if (!uninstallResult.success) {
553
+ return {
554
+ success: false,
555
+ package: {},
556
+ error: uninstallResult.error
557
+ };
558
+ }
559
+ return await installPackage(packageId, { force: true });
560
+ }
561
+ async function checkForUpdates() {
562
+ const installed = await getInstalledPackages();
563
+ const updates = [];
564
+ for (const installedPkg of installed) {
565
+ const latestPkg = await getPackage(installedPkg.package.id);
566
+ if (!latestPkg)
567
+ continue;
568
+ if (latestPkg.version !== installedPkg.package.version) {
569
+ updates.push({
570
+ id: installedPkg.package.id,
571
+ currentVersion: installedPkg.package.version,
572
+ latestVersion: latestPkg.version,
573
+ breaking: false,
574
+ // TODO: Implement semver comparison
575
+ changelog: latestPkg.changelog,
576
+ releaseDate: latestPkg.updatedAt
577
+ });
578
+ }
579
+ }
580
+ return updates;
581
+ }
582
+
233
583
  async function executeCcusage(args = []) {
234
584
  try {
235
585
  const command = "npx";
@@ -483,276 +833,331 @@ Defaulting to "claude-code".`));
483
833
  }
484
834
  }
485
835
 
486
- class ZcfUninstaller {
487
- _lang;
488
- // Reserved for future i18n support
489
- conflictResolution = /* @__PURE__ */ new Map();
490
- constructor(lang = "en") {
491
- this._lang = lang;
492
- this.conflictResolution.set("claude-code", ["mcps"]);
493
- void this._lang;
494
- }
495
- /**
496
- * 1. Remove outputStyle field from settings.json and output-styles directory
497
- */
498
- async removeOutputStyles() {
499
- const result = {
500
- success: false,
501
- removed: [],
502
- removedConfigs: [],
503
- errors: [],
504
- warnings: []
505
- };
506
- try {
507
- const settingsPath = join(homedir(), ".claude", "settings.json");
508
- const outputStylesPath = join(homedir(), ".claude", "output-styles");
509
- if (await pathExists(settingsPath)) {
510
- const settings = readJsonConfig(settingsPath) || {};
511
- if (settings.outputStyle) {
512
- delete settings.outputStyle;
513
- writeJsonConfig(settingsPath, settings);
514
- result.removedConfigs.push("outputStyle field from settings.json");
515
- }
516
- } else {
517
- result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
518
- }
519
- if (await pathExists(outputStylesPath)) {
520
- const trashResult = await moveToTrash(outputStylesPath);
521
- if (!trashResult[0]?.success) {
522
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
523
- }
524
- result.removed.push("~/.claude/output-styles/");
525
- } else {
526
- result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
527
- }
528
- result.success = true;
529
- } catch (error) {
530
- result.errors.push(`Failed to remove output styles: ${error.message}`);
836
+ async function configSwitchCommand(options) {
837
+ try {
838
+ ensureI18nInitialized();
839
+ if (options.list) {
840
+ await handleList(options.codeType);
841
+ return;
531
842
  }
532
- return result;
533
- }
534
- /**
535
- * 2. Remove custom commands directory (commands/ccjk/)
536
- */
537
- async removeCustomCommands() {
538
- const result = {
539
- success: false,
540
- removed: [],
541
- removedConfigs: [],
542
- errors: [],
543
- warnings: []
544
- };
545
- try {
546
- const commandsPath = join(homedir(), ".claude", "commands", "ccjk");
547
- if (await pathExists(commandsPath)) {
548
- const trashResult = await moveToTrash(commandsPath);
549
- if (!trashResult[0]?.success) {
550
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
551
- }
552
- result.removed.push("commands/ccjk/");
553
- result.success = true;
554
- } else {
555
- result.warnings.push(i18n.t("uninstall:commandsNotFound"));
556
- result.success = true;
557
- }
558
- } catch (error) {
559
- result.errors.push(`Failed to remove custom commands: ${error.message}`);
843
+ if (options.target) {
844
+ const resolvedCodeType = resolveCodeType(options.codeType);
845
+ await handleDirectSwitch(resolvedCodeType, options.target);
846
+ return;
560
847
  }
561
- return result;
562
- }
563
- /**
564
- * 3. Remove custom agents directory (agents/ccjk/)
565
- */
566
- async removeCustomAgents() {
567
- const result = {
568
- success: false,
569
- removed: [],
570
- removedConfigs: [],
571
- errors: [],
572
- warnings: []
573
- };
574
- try {
575
- const agentsPath = join(homedir(), ".claude", "agents", "ccjk");
576
- if (await pathExists(agentsPath)) {
577
- const trashResult = await moveToTrash(agentsPath);
578
- if (!trashResult[0]?.success) {
579
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
580
- }
581
- result.removed.push("agents/ccjk/");
582
- result.success = true;
583
- } else {
584
- result.warnings.push(i18n.t("uninstall:agentsNotFound"));
585
- result.success = true;
586
- }
587
- } catch (error) {
588
- result.errors.push(`Failed to remove custom agents: ${error.message}`);
848
+ await handleInteractiveSwitch(options.codeType);
849
+ } catch (error) {
850
+ if (process$1.env.NODE_ENV === "test" || process$1.env.VITEST) {
851
+ throw error;
589
852
  }
590
- return result;
853
+ handleGeneralError(error);
591
854
  }
592
- /**
593
- * 4. Remove global memory file (CLAUDE.md)
594
- */
595
- async removeClaudeMd() {
596
- const result = {
597
- success: false,
598
- removed: [],
599
- removedConfigs: [],
600
- errors: [],
601
- warnings: []
602
- };
603
- try {
604
- const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
605
- if (await pathExists(claudeMdPath)) {
606
- const trashResult = await moveToTrash(claudeMdPath);
607
- if (!trashResult[0]?.success) {
608
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
609
- }
610
- result.removed.push("CLAUDE.md");
611
- result.success = true;
612
- } else {
613
- result.warnings.push(i18n.t("uninstall:claudeMdNotFound"));
614
- result.success = true;
615
- }
616
- } catch (error) {
617
- result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`);
855
+ }
856
+ function resolveCodeType(codeType) {
857
+ if (codeType !== void 0) {
858
+ const resolved = resolveCodeToolType$1(codeType);
859
+ return resolved;
860
+ }
861
+ const zcfConfig = readZcfConfig();
862
+ if (zcfConfig?.codeToolType && isCodeToolType(zcfConfig.codeToolType)) {
863
+ return zcfConfig.codeToolType;
864
+ }
865
+ return DEFAULT_CODE_TOOL_TYPE;
866
+ }
867
+ async function handleList(codeType) {
868
+ const targetCodeType = resolveCodeType(codeType);
869
+ if (targetCodeType === "claude-code") {
870
+ await listClaudeCodeProfiles();
871
+ } else if (targetCodeType === "codex") {
872
+ await listCodexProvidersWithDisplay();
873
+ }
874
+ }
875
+ async function listCodexProvidersWithDisplay() {
876
+ const providers = await listCodexProviders();
877
+ const existingConfig = readCodexConfig();
878
+ const currentProvider = existingConfig?.modelProvider;
879
+ const isCommented = existingConfig?.modelProviderCommented;
880
+ if (!providers || providers.length === 0) {
881
+ console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
882
+ return;
883
+ }
884
+ console.log(ansis.bold(i18n.t("codex:listProvidersTitle")));
885
+ console.log();
886
+ if (currentProvider && !isCommented) {
887
+ console.log(ansis.cyan(i18n.t("codex:currentProvider", { provider: currentProvider })));
888
+ console.log();
889
+ }
890
+ providers.forEach((provider) => {
891
+ const isCurrent = currentProvider === provider.id && !isCommented;
892
+ const status = isCurrent ? ansis.green("\u25CF ") : " ";
893
+ const current = isCurrent ? ansis.yellow(` (${i18n.t("common:current")})`) : "";
894
+ console.log(`${status}${ansis.white(provider.name)}${current}`);
895
+ console.log(` ${ansis.cyan(`ID: ${provider.id}`)} ${ansis.gray(`(${provider.baseUrl})`)}`);
896
+ if (provider.tempEnvKey) {
897
+ console.log(` ${ansis.gray(`Env: ${provider.tempEnvKey}`)}`);
618
898
  }
619
- return result;
899
+ console.log();
900
+ });
901
+ }
902
+ async function listClaudeCodeProfiles() {
903
+ const config = ClaudeCodeConfigManager.readConfig();
904
+ if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
905
+ console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
906
+ return;
620
907
  }
621
- /**
622
- * 5. Remove permissions and environment variables
623
- */
624
- async removePermissionsAndEnvs() {
625
- const result = {
626
- success: false,
627
- removed: [],
628
- removedConfigs: [],
629
- errors: [],
630
- warnings: []
631
- };
632
- try {
633
- const settingsPath = join(homedir(), ".claude", "settings.json");
634
- if (await pathExists(settingsPath)) {
635
- const settings = readJsonConfig(settingsPath) || {};
636
- let modified = false;
637
- if (settings.permissions) {
638
- delete settings.permissions;
639
- result.removedConfigs.push("permissions configuration");
640
- modified = true;
641
- }
642
- if (settings.env) {
643
- delete settings.env;
644
- result.removedConfigs.push("environment variables");
645
- modified = true;
646
- }
647
- if (modified) {
648
- writeJsonConfig(settingsPath, settings);
649
- }
650
- result.success = true;
651
- } else {
652
- result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
653
- result.success = true;
908
+ console.log(ansis.bold(i18n.t("multi-config:availableClaudeCodeProfiles")));
909
+ console.log();
910
+ const currentProfileId = config.currentProfileId;
911
+ Object.values(config.profiles).forEach((profile) => {
912
+ const isCurrent = profile.id === currentProfileId;
913
+ const status = isCurrent ? ansis.green("\u25CF ") : " ";
914
+ const current = isCurrent ? ansis.yellow(i18n.t("common:current")) : "";
915
+ console.log(`${status}${ansis.white(profile.name)}${current}`);
916
+ console.log(` ${ansis.cyan(`ID: ${profile.id}`)} ${ansis.gray(`(${profile.authType})`)}`);
917
+ console.log();
918
+ });
919
+ }
920
+ async function handleDirectSwitch(codeType, target) {
921
+ const resolvedCodeType = resolveCodeType(codeType);
922
+ if (resolvedCodeType === "claude-code") {
923
+ await handleClaudeCodeDirectSwitch(target);
924
+ } else if (resolvedCodeType === "codex") {
925
+ await switchCodexProvider(target);
926
+ }
927
+ }
928
+ async function handleClaudeCodeDirectSwitch(target) {
929
+ if (target === "official") {
930
+ const result = await ClaudeCodeConfigManager.switchToOfficial();
931
+ if (result.success) {
932
+ try {
933
+ await ClaudeCodeConfigManager.applyProfileSettings(null);
934
+ console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToOfficial")));
935
+ } catch (error) {
936
+ const reason = error instanceof Error ? error.message : String(error);
937
+ console.log(ansis.red(reason));
654
938
  }
655
- } catch (error) {
656
- result.errors.push(`Failed to remove permissions and envs: ${error.message}`);
939
+ } else {
940
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
657
941
  }
658
- return result;
659
- }
660
- /**
661
- * 6. Remove MCP servers from .claude.json (mcpServers field only)
662
- */
663
- async removeMcps() {
664
- const result = {
665
- success: false,
666
- removed: [],
667
- removedConfigs: [],
668
- errors: [],
669
- warnings: []
670
- };
671
- try {
672
- const claudeJsonPath = join(homedir(), ".claude.json");
673
- if (await pathExists(claudeJsonPath)) {
674
- const config = readJsonConfig(claudeJsonPath) || {};
675
- if (config.mcpServers) {
676
- delete config.mcpServers;
677
- writeJsonConfig(claudeJsonPath, config);
678
- result.removedConfigs.push("mcpServers from .claude.json");
679
- }
680
- result.success = true;
681
- } else {
682
- result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
683
- result.success = true;
942
+ } else if (target === "ccr") {
943
+ const result = await ClaudeCodeConfigManager.switchToCcr();
944
+ if (result.success) {
945
+ try {
946
+ const profile = ClaudeCodeConfigManager.getProfileById("ccr-proxy");
947
+ await ClaudeCodeConfigManager.applyProfileSettings(profile);
948
+ console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToCcr")));
949
+ } catch (error) {
950
+ const reason = error instanceof Error ? error.message : String(error);
951
+ console.log(ansis.red(reason));
684
952
  }
685
- } catch (error) {
686
- result.errors.push(`Failed to remove MCP servers: ${error.message}`);
953
+ } else {
954
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
687
955
  }
688
- return result;
689
- }
690
- /**
691
- * 7. Uninstall Claude Code Router and remove configuration
692
- */
693
- async uninstallCcr() {
694
- const result = {
695
- success: false,
696
- removed: [],
697
- removedConfigs: [],
698
- errors: [],
699
- warnings: []
700
- };
701
- try {
702
- const ccrPath = join(homedir(), ".claude-code-router");
703
- if (await pathExists(ccrPath)) {
704
- const trashResult = await moveToTrash(ccrPath);
705
- if (!trashResult[0]?.success) {
706
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
707
- }
708
- result.removed.push(".claude-code-router/");
956
+ } else {
957
+ const config = ClaudeCodeConfigManager.readConfig();
958
+ if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
959
+ console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
960
+ return;
961
+ }
962
+ const normalizedTarget = target.trim();
963
+ let resolvedId = normalizedTarget;
964
+ let resolvedProfile = config.profiles[normalizedTarget];
965
+ if (!resolvedProfile) {
966
+ const match = Object.entries(config.profiles).find(([, profile]) => profile.name === normalizedTarget);
967
+ if (match) {
968
+ resolvedId = match[0];
969
+ resolvedProfile = match[1];
709
970
  }
971
+ }
972
+ if (!resolvedProfile) {
973
+ console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
974
+ return;
975
+ }
976
+ const result = await ClaudeCodeConfigManager.switchProfile(resolvedId);
977
+ if (result.success) {
710
978
  try {
711
- await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]);
712
- result.removed.push("@musistudio/claude-code-router package");
713
- result.success = true;
714
- } catch (npmError) {
715
- if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
716
- result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
717
- result.success = true;
718
- } else {
719
- result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
720
- }
979
+ await ClaudeCodeConfigManager.applyProfileSettings({ ...resolvedProfile, id: resolvedId });
980
+ console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToProfile", { name: resolvedProfile.name })));
981
+ } catch (error) {
982
+ const reason = error instanceof Error ? error.message : String(error);
983
+ console.log(ansis.red(reason));
721
984
  }
722
- } catch (error) {
723
- result.errors.push(`Failed to uninstall CCR: ${error.message}`);
985
+ } else {
986
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
724
987
  }
725
- return result;
726
988
  }
727
- /**
728
- * 8. Uninstall CCometixLine
729
- */
730
- async uninstallCcline() {
731
- const result = {
732
- success: false,
733
- removed: [],
734
- removedConfigs: [],
735
- errors: [],
736
- warnings: []
737
- };
738
- try {
739
- await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]);
740
- result.removed.push("@cometix/ccline package");
741
- result.success = true;
742
- } catch (error) {
743
- if (error.message.includes("not found") || error.message.includes("not installed")) {
744
- result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
745
- result.success = true;
746
- } else {
747
- result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`);
989
+ }
990
+ async function handleInteractiveSwitch(codeType) {
991
+ const resolvedCodeType = resolveCodeType(codeType);
992
+ if (resolvedCodeType === "claude-code") {
993
+ await handleClaudeCodeInteractiveSwitch();
994
+ } else if (resolvedCodeType === "codex") {
995
+ await handleCodexInteractiveSwitch();
996
+ }
997
+ }
998
+ async function handleClaudeCodeInteractiveSwitch() {
999
+ const config = ClaudeCodeConfigManager.readConfig();
1000
+ if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1001
+ console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1002
+ return;
1003
+ }
1004
+ const currentProfileId = config.currentProfileId;
1005
+ const createClaudeCodeChoices = (profiles, currentProfileId2) => {
1006
+ const choices2 = [];
1007
+ const isOfficialMode = !currentProfileId2 || currentProfileId2 === "official";
1008
+ choices2.push({
1009
+ name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("codex:useOfficialLogin")}`,
1010
+ value: "official"
1011
+ });
1012
+ const isCcrMode = currentProfileId2 === "ccr-proxy";
1013
+ choices2.push({
1014
+ name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
1015
+ value: "ccr"
1016
+ });
1017
+ Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
1018
+ const isCurrent = profile.id === currentProfileId2;
1019
+ choices2.push({
1020
+ name: isCurrent ? `${ansis.green("\u25CF ")}${profile.name} ${ansis.yellow("(current)")}` : ` ${profile.name}`,
1021
+ value: profile.id
1022
+ });
1023
+ });
1024
+ return choices2;
1025
+ };
1026
+ const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
1027
+ try {
1028
+ const { selectedConfig } = await inquirer.prompt([{
1029
+ type: "list",
1030
+ name: "selectedConfig",
1031
+ message: i18n.t("multi-config:selectClaudeCodeConfiguration"),
1032
+ choices: addNumbersToChoices(choices)
1033
+ }]);
1034
+ if (!selectedConfig) {
1035
+ console.log(ansis.yellow(i18n.t("multi-config:cancelled")));
1036
+ return;
1037
+ }
1038
+ await handleClaudeCodeDirectSwitch(selectedConfig);
1039
+ } catch (error) {
1040
+ if (error.name === "ExitPromptError") {
1041
+ console.log(ansis.cyan(`
1042
+ ${i18n.t("common:goodbye")}`));
1043
+ return;
1044
+ }
1045
+ throw error;
1046
+ }
1047
+ }
1048
+ async function handleCodexInteractiveSwitch() {
1049
+ const providers = await listCodexProviders();
1050
+ if (!providers || providers.length === 0) {
1051
+ console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
1052
+ return;
1053
+ }
1054
+ const existingConfig = readCodexConfig();
1055
+ const currentProvider = existingConfig?.modelProvider;
1056
+ const isCommented = existingConfig?.modelProviderCommented;
1057
+ const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
1058
+ const choices2 = [];
1059
+ const isOfficialMode = !currentProvider2 || isCommented2;
1060
+ choices2.push({
1061
+ name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
1062
+ value: "official"
1063
+ });
1064
+ providers2.forEach((provider) => {
1065
+ const isCurrent = currentProvider2 === provider.id && !isCommented2;
1066
+ choices2.push({
1067
+ name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
1068
+ value: provider.id
1069
+ });
1070
+ });
1071
+ return choices2;
1072
+ };
1073
+ const choices = createApiConfigChoices(providers, currentProvider, isCommented);
1074
+ try {
1075
+ const { selectedConfig } = await inquirer.prompt([{
1076
+ type: "list",
1077
+ name: "selectedConfig",
1078
+ message: i18n.t("codex:apiConfigSwitchPrompt"),
1079
+ choices: addNumbersToChoices(choices)
1080
+ }]);
1081
+ if (!selectedConfig) {
1082
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1083
+ return;
1084
+ }
1085
+ let success = false;
1086
+ if (selectedConfig === "official") {
1087
+ success = await switchToOfficialLogin();
1088
+ } else {
1089
+ success = await switchToProvider(selectedConfig);
1090
+ }
1091
+ if (!success) {
1092
+ console.log(ansis.red(i18n.t("common:operationFailed")));
1093
+ }
1094
+ } catch (error) {
1095
+ if (error.name === "ExitPromptError") {
1096
+ console.log(ansis.cyan(`
1097
+ ${i18n.t("common:goodbye")}`));
1098
+ return;
1099
+ }
1100
+ throw error;
1101
+ }
1102
+ }
1103
+
1104
+ const configSwitch = {
1105
+ __proto__: null,
1106
+ configSwitchCommand: configSwitchCommand
1107
+ };
1108
+
1109
+ class ZcfUninstaller {
1110
+ _lang;
1111
+ // Reserved for future i18n support
1112
+ conflictResolution = /* @__PURE__ */ new Map();
1113
+ constructor(lang = "en") {
1114
+ this._lang = lang;
1115
+ this.conflictResolution.set("claude-code", ["mcps"]);
1116
+ void this._lang;
1117
+ }
1118
+ /**
1119
+ * 1. Remove outputStyle field from settings.json and output-styles directory
1120
+ */
1121
+ async removeOutputStyles() {
1122
+ const result = {
1123
+ success: false,
1124
+ removed: [],
1125
+ removedConfigs: [],
1126
+ errors: [],
1127
+ warnings: []
1128
+ };
1129
+ try {
1130
+ const settingsPath = join(homedir(), ".claude", "settings.json");
1131
+ const outputStylesPath = join(homedir(), ".claude", "output-styles");
1132
+ if (await pathExists(settingsPath)) {
1133
+ const settings = readJsonConfig(settingsPath) || {};
1134
+ if (settings.outputStyle) {
1135
+ delete settings.outputStyle;
1136
+ writeJsonConfig(settingsPath, settings);
1137
+ result.removedConfigs.push("outputStyle field from settings.json");
1138
+ }
1139
+ } else {
1140
+ result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
1141
+ }
1142
+ if (await pathExists(outputStylesPath)) {
1143
+ const trashResult = await moveToTrash(outputStylesPath);
1144
+ if (!trashResult[0]?.success) {
1145
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
1146
+ }
1147
+ result.removed.push("~/.claude/output-styles/");
1148
+ } else {
1149
+ result.warnings.push(i18n.t("uninstall:outputStylesDirectoryNotFound"));
748
1150
  }
1151
+ result.success = true;
1152
+ } catch (error) {
1153
+ result.errors.push(`Failed to remove output styles: ${error.message}`);
749
1154
  }
750
1155
  return result;
751
1156
  }
752
1157
  /**
753
- * 9. Uninstall Claude Code and remove entire .claude.json
1158
+ * 2. Remove custom commands directory (commands/ccjk/)
754
1159
  */
755
- async uninstallClaudeCode() {
1160
+ async removeCustomCommands() {
756
1161
  const result = {
757
1162
  success: false,
758
1163
  removed: [],
@@ -761,603 +1166,1240 @@ class ZcfUninstaller {
761
1166
  warnings: []
762
1167
  };
763
1168
  try {
764
- const claudeJsonPath = join(homedir(), ".claude.json");
765
- if (await pathExists(claudeJsonPath)) {
766
- const trashResult = await moveToTrash(claudeJsonPath);
1169
+ const commandsPath = join(homedir(), ".claude", "commands", "ccjk");
1170
+ if (await pathExists(commandsPath)) {
1171
+ const trashResult = await moveToTrash(commandsPath);
767
1172
  if (!trashResult[0]?.success) {
768
1173
  result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
769
1174
  }
770
- result.removed.push(".claude.json (includes MCP configuration)");
1175
+ result.removed.push("commands/ccjk/");
1176
+ result.success = true;
1177
+ } else {
1178
+ result.warnings.push(i18n.t("uninstall:commandsNotFound"));
1179
+ result.success = true;
771
1180
  }
772
- try {
773
- const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.db; });
774
- const success = await uninstallCodeTool("claude-code");
775
- if (success) {
776
- result.removed.push("@anthropic-ai/claude-code");
777
- result.success = true;
778
- } else {
779
- result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: "" }));
1181
+ } catch (error) {
1182
+ result.errors.push(`Failed to remove custom commands: ${error.message}`);
1183
+ }
1184
+ return result;
1185
+ }
1186
+ /**
1187
+ * 3. Remove custom agents directory (agents/ccjk/)
1188
+ */
1189
+ async removeCustomAgents() {
1190
+ const result = {
1191
+ success: false,
1192
+ removed: [],
1193
+ removedConfigs: [],
1194
+ errors: [],
1195
+ warnings: []
1196
+ };
1197
+ try {
1198
+ const agentsPath = join(homedir(), ".claude", "agents", "ccjk");
1199
+ if (await pathExists(agentsPath)) {
1200
+ const trashResult = await moveToTrash(agentsPath);
1201
+ if (!trashResult[0]?.success) {
1202
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
780
1203
  }
781
- } catch (npmError) {
782
- if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
783
- result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
784
- result.success = true;
785
- } else {
786
- result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${npmError.message}` }));
1204
+ result.removed.push("agents/ccjk/");
1205
+ result.success = true;
1206
+ } else {
1207
+ result.warnings.push(i18n.t("uninstall:agentsNotFound"));
1208
+ result.success = true;
1209
+ }
1210
+ } catch (error) {
1211
+ result.errors.push(`Failed to remove custom agents: ${error.message}`);
1212
+ }
1213
+ return result;
1214
+ }
1215
+ /**
1216
+ * 4. Remove global memory file (CLAUDE.md)
1217
+ */
1218
+ async removeClaudeMd() {
1219
+ const result = {
1220
+ success: false,
1221
+ removed: [],
1222
+ removedConfigs: [],
1223
+ errors: [],
1224
+ warnings: []
1225
+ };
1226
+ try {
1227
+ const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
1228
+ if (await pathExists(claudeMdPath)) {
1229
+ const trashResult = await moveToTrash(claudeMdPath);
1230
+ if (!trashResult[0]?.success) {
1231
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
787
1232
  }
1233
+ result.removed.push("CLAUDE.md");
1234
+ result.success = true;
1235
+ } else {
1236
+ result.warnings.push(i18n.t("uninstall:claudeMdNotFound"));
1237
+ result.success = true;
788
1238
  }
789
1239
  } catch (error) {
790
- result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${error.message}` }));
1240
+ result.errors.push(`Failed to remove CLAUDE.md: ${error.message}`);
1241
+ }
1242
+ return result;
1243
+ }
1244
+ /**
1245
+ * 5. Remove permissions and environment variables
1246
+ */
1247
+ async removePermissionsAndEnvs() {
1248
+ const result = {
1249
+ success: false,
1250
+ removed: [],
1251
+ removedConfigs: [],
1252
+ errors: [],
1253
+ warnings: []
1254
+ };
1255
+ try {
1256
+ const settingsPath = join(homedir(), ".claude", "settings.json");
1257
+ if (await pathExists(settingsPath)) {
1258
+ const settings = readJsonConfig(settingsPath) || {};
1259
+ let modified = false;
1260
+ if (settings.permissions) {
1261
+ delete settings.permissions;
1262
+ result.removedConfigs.push("permissions configuration");
1263
+ modified = true;
1264
+ }
1265
+ if (settings.env) {
1266
+ delete settings.env;
1267
+ result.removedConfigs.push("environment variables");
1268
+ modified = true;
1269
+ }
1270
+ if (modified) {
1271
+ writeJsonConfig(settingsPath, settings);
1272
+ }
1273
+ result.success = true;
1274
+ } else {
1275
+ result.warnings.push(i18n.t("uninstall:settingsJsonNotFound"));
1276
+ result.success = true;
1277
+ }
1278
+ } catch (error) {
1279
+ result.errors.push(`Failed to remove permissions and envs: ${error.message}`);
1280
+ }
1281
+ return result;
1282
+ }
1283
+ /**
1284
+ * 6. Remove MCP servers from .claude.json (mcpServers field only)
1285
+ */
1286
+ async removeMcps() {
1287
+ const result = {
1288
+ success: false,
1289
+ removed: [],
1290
+ removedConfigs: [],
1291
+ errors: [],
1292
+ warnings: []
1293
+ };
1294
+ try {
1295
+ const claudeJsonPath = join(homedir(), ".claude.json");
1296
+ if (await pathExists(claudeJsonPath)) {
1297
+ const config = readJsonConfig(claudeJsonPath) || {};
1298
+ if (config.mcpServers) {
1299
+ delete config.mcpServers;
1300
+ writeJsonConfig(claudeJsonPath, config);
1301
+ result.removedConfigs.push("mcpServers from .claude.json");
1302
+ }
1303
+ result.success = true;
1304
+ } else {
1305
+ result.warnings.push(i18n.t("uninstall:claudeJsonNotFound"));
1306
+ result.success = true;
1307
+ }
1308
+ } catch (error) {
1309
+ result.errors.push(`Failed to remove MCP servers: ${error.message}`);
1310
+ }
1311
+ return result;
1312
+ }
1313
+ /**
1314
+ * 7. Uninstall Claude Code Router and remove configuration
1315
+ */
1316
+ async uninstallCcr() {
1317
+ const result = {
1318
+ success: false,
1319
+ removed: [],
1320
+ removedConfigs: [],
1321
+ errors: [],
1322
+ warnings: []
1323
+ };
1324
+ try {
1325
+ const ccrPath = join(homedir(), ".claude-code-router");
1326
+ if (await pathExists(ccrPath)) {
1327
+ const trashResult = await moveToTrash(ccrPath);
1328
+ if (!trashResult[0]?.success) {
1329
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
1330
+ }
1331
+ result.removed.push(".claude-code-router/");
1332
+ }
1333
+ try {
1334
+ await exec$1("npm", ["uninstall", "-g", "@musistudio/claude-code-router"]);
1335
+ result.removed.push("@musistudio/claude-code-router package");
1336
+ result.success = true;
1337
+ } catch (npmError) {
1338
+ if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
1339
+ result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
1340
+ result.success = true;
1341
+ } else {
1342
+ result.errors.push(`Failed to uninstall CCR package: ${npmError.message}`);
1343
+ }
1344
+ }
1345
+ } catch (error) {
1346
+ result.errors.push(`Failed to uninstall CCR: ${error.message}`);
1347
+ }
1348
+ return result;
1349
+ }
1350
+ /**
1351
+ * 8. Uninstall CCometixLine
1352
+ */
1353
+ async uninstallCcline() {
1354
+ const result = {
1355
+ success: false,
1356
+ removed: [],
1357
+ removedConfigs: [],
1358
+ errors: [],
1359
+ warnings: []
1360
+ };
1361
+ try {
1362
+ await exec$1("npm", ["uninstall", "-g", "@cometix/ccline"]);
1363
+ result.removed.push("@cometix/ccline package");
1364
+ result.success = true;
1365
+ } catch (error) {
1366
+ if (error.message.includes("not found") || error.message.includes("not installed")) {
1367
+ result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
1368
+ result.success = true;
1369
+ } else {
1370
+ result.errors.push(`Failed to uninstall CCometixLine: ${error.message}`);
1371
+ }
1372
+ }
1373
+ return result;
1374
+ }
1375
+ /**
1376
+ * 9. Uninstall Claude Code and remove entire .claude.json
1377
+ */
1378
+ async uninstallClaudeCode() {
1379
+ const result = {
1380
+ success: false,
1381
+ removed: [],
1382
+ removedConfigs: [],
1383
+ errors: [],
1384
+ warnings: []
1385
+ };
1386
+ try {
1387
+ const claudeJsonPath = join(homedir(), ".claude.json");
1388
+ if (await pathExists(claudeJsonPath)) {
1389
+ const trashResult = await moveToTrash(claudeJsonPath);
1390
+ if (!trashResult[0]?.success) {
1391
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
1392
+ }
1393
+ result.removed.push(".claude.json (includes MCP configuration)");
1394
+ }
1395
+ try {
1396
+ const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dh; });
1397
+ const success = await uninstallCodeTool("claude-code");
1398
+ if (success) {
1399
+ result.removed.push("@anthropic-ai/claude-code");
1400
+ result.success = true;
1401
+ } else {
1402
+ result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: "" }));
1403
+ }
1404
+ } catch (npmError) {
1405
+ if (npmError.message.includes("not found") || npmError.message.includes("not installed")) {
1406
+ result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
1407
+ result.success = true;
1408
+ } else {
1409
+ result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${npmError.message}` }));
1410
+ }
1411
+ }
1412
+ } catch (error) {
1413
+ result.errors.push(i18n.t("uninstall:uninstallFailed", { codeType: i18n.t("common:claudeCode"), message: `: ${error.message}` }));
1414
+ }
1415
+ return result;
1416
+ }
1417
+ /**
1418
+ * 10. Remove backup files
1419
+ */
1420
+ async removeBackups() {
1421
+ const result = {
1422
+ success: false,
1423
+ removed: [],
1424
+ removedConfigs: [],
1425
+ errors: [],
1426
+ warnings: []
1427
+ };
1428
+ try {
1429
+ const backupPath = join(homedir(), ".claude", "backup");
1430
+ if (await pathExists(backupPath)) {
1431
+ const trashResult = await moveToTrash(backupPath);
1432
+ if (!trashResult[0]?.success) {
1433
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
1434
+ }
1435
+ result.removed.push("backup/");
1436
+ result.success = true;
1437
+ } else {
1438
+ result.warnings.push(i18n.t("uninstall:backupsNotFound"));
1439
+ result.success = true;
1440
+ }
1441
+ } catch (error) {
1442
+ result.errors.push(`Failed to remove backups: ${error.message}`);
1443
+ }
1444
+ return result;
1445
+ }
1446
+ /**
1447
+ * 11. Remove CCJK preference configuration
1448
+ */
1449
+ async removeZcfConfig() {
1450
+ const result = {
1451
+ success: false,
1452
+ removed: [],
1453
+ removedConfigs: [],
1454
+ errors: [],
1455
+ warnings: []
1456
+ };
1457
+ try {
1458
+ const zcfConfigPath = ZCF_CONFIG_FILE;
1459
+ const relativeName = zcfConfigPath.replace(homedir(), "~");
1460
+ if (await pathExists(zcfConfigPath)) {
1461
+ const trashResult = await moveToTrash(zcfConfigPath);
1462
+ if (!trashResult[0]?.success) {
1463
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
1464
+ }
1465
+ result.removed.push(relativeName);
1466
+ result.success = true;
1467
+ } else {
1468
+ result.warnings.push(i18n.t("uninstall:ccjkConfigNotFound"));
1469
+ result.success = true;
1470
+ }
1471
+ } catch (error) {
1472
+ result.errors.push(`Failed to remove CCJK config: ${error.message}`);
1473
+ }
1474
+ return result;
1475
+ }
1476
+ /**
1477
+ * Complete uninstall - remove all directories and packages
1478
+ */
1479
+ async completeUninstall() {
1480
+ const result = {
1481
+ success: true,
1482
+ removed: [],
1483
+ removedConfigs: [],
1484
+ errors: [],
1485
+ warnings: []
1486
+ };
1487
+ try {
1488
+ const directoriesToRemove = [
1489
+ { path: join(homedir(), ".claude"), name: "~/.claude/" },
1490
+ { path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
1491
+ { path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
1492
+ ];
1493
+ for (const dir of directoriesToRemove) {
1494
+ try {
1495
+ if (await pathExists(dir.path)) {
1496
+ const trashResult = await moveToTrash(dir.path);
1497
+ if (!trashResult[0]?.success) {
1498
+ result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
1499
+ }
1500
+ result.removed.push(dir.name);
1501
+ }
1502
+ } catch (error) {
1503
+ result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
1504
+ }
1505
+ }
1506
+ const packagesToUninstall = [
1507
+ "@musistudio/claude-code-router",
1508
+ "@cometix/ccline",
1509
+ "@anthropic-ai/claude-code"
1510
+ ];
1511
+ for (const pkg of packagesToUninstall) {
1512
+ try {
1513
+ await exec$1("npm", ["uninstall", "-g", pkg]);
1514
+ result.removed.push(`${pkg} package`);
1515
+ } catch (error) {
1516
+ if (error.message.includes("not found") || error.message.includes("not installed")) {
1517
+ if (pkg.includes("claude-code-router")) {
1518
+ result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
1519
+ } else if (pkg.includes("ccline")) {
1520
+ result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
1521
+ } else {
1522
+ result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
1523
+ }
1524
+ } else {
1525
+ result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
1526
+ }
1527
+ }
1528
+ }
1529
+ } catch (error) {
1530
+ result.errors.push(`Complete uninstall failed: ${error.message}`);
1531
+ result.success = false;
1532
+ }
1533
+ return result;
1534
+ }
1535
+ /**
1536
+ * Custom uninstall with conflict resolution
1537
+ */
1538
+ async customUninstall(selectedItems) {
1539
+ const resolvedItems = this.resolveConflicts(selectedItems);
1540
+ const results = [];
1541
+ for (const item of resolvedItems) {
1542
+ try {
1543
+ const result = await this.executeUninstallItem(item);
1544
+ results.push(result);
1545
+ } catch (error) {
1546
+ results.push({
1547
+ success: false,
1548
+ removed: [],
1549
+ removedConfigs: [],
1550
+ errors: [`Failed to execute ${item}: ${error.message}`],
1551
+ warnings: []
1552
+ });
1553
+ }
1554
+ }
1555
+ return results;
1556
+ }
1557
+ /**
1558
+ * Resolve conflicts between uninstall items
1559
+ */
1560
+ resolveConflicts(items) {
1561
+ const resolved = [...items];
1562
+ for (const [primary, conflicts] of this.conflictResolution) {
1563
+ if (resolved.includes(primary)) {
1564
+ conflicts.forEach((conflict) => {
1565
+ const index = resolved.indexOf(conflict);
1566
+ if (index > -1) {
1567
+ resolved.splice(index, 1);
1568
+ }
1569
+ });
1570
+ }
1571
+ }
1572
+ return resolved;
1573
+ }
1574
+ /**
1575
+ * Execute uninstall for a specific item
1576
+ */
1577
+ async executeUninstallItem(item) {
1578
+ switch (item) {
1579
+ case "output-styles":
1580
+ return await this.removeOutputStyles();
1581
+ case "commands":
1582
+ return await this.removeCustomCommands();
1583
+ case "agents":
1584
+ return await this.removeCustomAgents();
1585
+ case "claude-md":
1586
+ return await this.removeClaudeMd();
1587
+ case "permissions-envs":
1588
+ return await this.removePermissionsAndEnvs();
1589
+ case "mcps":
1590
+ return await this.removeMcps();
1591
+ case "ccr":
1592
+ return await this.uninstallCcr();
1593
+ case "ccline":
1594
+ return await this.uninstallCcline();
1595
+ case "claude-code":
1596
+ return await this.uninstallClaudeCode();
1597
+ case "backups":
1598
+ return await this.removeBackups();
1599
+ case "ccjk-config":
1600
+ return await this.removeZcfConfig();
1601
+ default:
1602
+ return {
1603
+ success: false,
1604
+ removed: [],
1605
+ removedConfigs: [],
1606
+ errors: [`Unknown uninstall item: ${item}`],
1607
+ warnings: []
1608
+ };
1609
+ }
1610
+ }
1611
+ }
1612
+
1613
+ async function uninstall(options = {}) {
1614
+ try {
1615
+ ensureI18nInitialized();
1616
+ let codeType;
1617
+ if (options.codeType) {
1618
+ try {
1619
+ codeType = await resolveCodeType$1(options.codeType);
1620
+ } catch (error) {
1621
+ const errorMessage = error instanceof Error ? error.message : String(error);
1622
+ console.error(ansis.red(`${i18n.t("errors:generalError")} ${errorMessage}`));
1623
+ const config = readZcfConfig();
1624
+ codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
1625
+ }
1626
+ } else {
1627
+ const config = readZcfConfig();
1628
+ codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
1629
+ }
1630
+ const uninstaller = new ZcfUninstaller(options.lang || "en");
1631
+ if (codeType === "codex") {
1632
+ const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dg; });
1633
+ await runCodexUninstall();
1634
+ return;
1635
+ }
1636
+ if (options.mode && options.mode !== "interactive") {
1637
+ if (options.mode === "complete") {
1638
+ await executeCompleteUninstall(uninstaller);
1639
+ return;
1640
+ } else if (options.mode === "custom" && options.items) {
1641
+ let items;
1642
+ if (typeof options.items === "string") {
1643
+ items = options.items.split(",").map((item) => item.trim());
1644
+ } else {
1645
+ items = options.items;
1646
+ }
1647
+ await executeCustomUninstall(uninstaller, items);
1648
+ return;
1649
+ }
1650
+ }
1651
+ await showInteractiveUninstall(uninstaller);
1652
+ } catch (error) {
1653
+ if (!handleExitPromptError(error)) {
1654
+ handleGeneralError(error);
1655
+ }
1656
+ }
1657
+ }
1658
+ async function showInteractiveUninstall(uninstaller) {
1659
+ console.log(ansis.cyan.bold(i18n.t("uninstall:title")));
1660
+ console.log("");
1661
+ const { mainChoice } = await inquirer.prompt({
1662
+ type: "list",
1663
+ name: "mainChoice",
1664
+ message: i18n.t("uninstall:selectMainOption"),
1665
+ choices: addNumbersToChoices([
1666
+ {
1667
+ name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
1668
+ value: "complete",
1669
+ short: i18n.t("uninstall:completeUninstall")
1670
+ },
1671
+ {
1672
+ name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
1673
+ value: "custom",
1674
+ short: i18n.t("uninstall:customUninstall")
1675
+ }
1676
+ ])
1677
+ });
1678
+ if (!mainChoice) {
1679
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1680
+ return;
1681
+ }
1682
+ if (mainChoice === "complete") {
1683
+ await executeCompleteUninstall(uninstaller);
1684
+ } else {
1685
+ await showCustomUninstallMenu(uninstaller);
1686
+ }
1687
+ }
1688
+ async function showCustomUninstallMenu(uninstaller) {
1689
+ console.log("");
1690
+ console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems")));
1691
+ const { customItems } = await inquirer.prompt({
1692
+ type: "checkbox",
1693
+ name: "customItems",
1694
+ message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`,
1695
+ choices: [
1696
+ {
1697
+ name: i18n.t("uninstall:outputStyles"),
1698
+ value: "output-styles"
1699
+ },
1700
+ {
1701
+ name: i18n.t("uninstall:commands"),
1702
+ value: "commands"
1703
+ },
1704
+ {
1705
+ name: i18n.t("uninstall:agents"),
1706
+ value: "agents"
1707
+ },
1708
+ {
1709
+ name: i18n.t("uninstall:claudeMd"),
1710
+ value: "claude-md"
1711
+ },
1712
+ {
1713
+ name: i18n.t("uninstall:permissionsEnvs"),
1714
+ value: "permissions-envs"
1715
+ },
1716
+ {
1717
+ name: i18n.t("uninstall:mcps"),
1718
+ value: "mcps"
1719
+ },
1720
+ {
1721
+ name: i18n.t("uninstall:ccr"),
1722
+ value: "ccr"
1723
+ },
1724
+ {
1725
+ name: i18n.t("uninstall:ccline"),
1726
+ value: "ccline"
1727
+ },
1728
+ {
1729
+ name: i18n.t("uninstall:claudeCode"),
1730
+ value: "claude-code"
1731
+ },
1732
+ {
1733
+ name: i18n.t("uninstall:backups"),
1734
+ value: "backups"
1735
+ },
1736
+ {
1737
+ name: i18n.t("uninstall:ccjkConfig"),
1738
+ value: "ccjk-config"
1739
+ }
1740
+ ],
1741
+ validate: (answers) => {
1742
+ if (answers.length === 0) {
1743
+ return i18n.t("uninstall:selectAtLeastOne");
1744
+ }
1745
+ return true;
1746
+ }
1747
+ });
1748
+ if (!customItems || customItems.length === 0) {
1749
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1750
+ return;
1751
+ }
1752
+ await executeCustomUninstall(uninstaller, customItems);
1753
+ }
1754
+ async function executeCompleteUninstall(uninstaller) {
1755
+ console.log("");
1756
+ console.log(ansis.red.bold(i18n.t("uninstall:executingComplete")));
1757
+ console.log(ansis.yellow(i18n.t("uninstall:completeWarning")));
1758
+ const confirm = await promptBoolean({
1759
+ message: i18n.t("uninstall:confirmComplete"),
1760
+ defaultValue: false
1761
+ });
1762
+ if (!confirm) {
1763
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1764
+ return;
1765
+ }
1766
+ console.log("");
1767
+ console.log(ansis.cyan(i18n.t("uninstall:processingComplete")));
1768
+ const result = await uninstaller.completeUninstall();
1769
+ displayUninstallResult("complete", [result]);
1770
+ }
1771
+ async function executeCustomUninstall(uninstaller, items) {
1772
+ console.log("");
1773
+ console.log(ansis.cyan(i18n.t("uninstall:executingCustom")));
1774
+ console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
1775
+ items.forEach((item) => {
1776
+ console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
1777
+ });
1778
+ const confirm = await promptBoolean({
1779
+ message: i18n.t("uninstall:confirmCustom"),
1780
+ defaultValue: false
1781
+ });
1782
+ if (!confirm) {
1783
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1784
+ return;
1785
+ }
1786
+ console.log("");
1787
+ console.log(ansis.cyan(i18n.t("uninstall:processingCustom")));
1788
+ const results = await uninstaller.customUninstall(items);
1789
+ displayUninstallResult("custom", results);
1790
+ }
1791
+ function displayUninstallResult(mode, results) {
1792
+ console.log("");
1793
+ console.log(ansis.cyan("\u2500".repeat(50)));
1794
+ let totalSuccess = 0;
1795
+ let totalErrors = 0;
1796
+ let totalWarnings = 0;
1797
+ results.forEach((result) => {
1798
+ if (result.success) {
1799
+ totalSuccess++;
1800
+ }
1801
+ if (result.removed && result.removed.length > 0) {
1802
+ console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
1803
+ result.removed.forEach((item) => {
1804
+ console.log(ansis.gray(` \u2022 ${item}`));
1805
+ });
1806
+ }
1807
+ if (result.removedConfigs && result.removedConfigs.length > 0) {
1808
+ console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
1809
+ result.removedConfigs.forEach((item) => {
1810
+ console.log(ansis.gray(` \u2022 ${item}`));
1811
+ });
1812
+ }
1813
+ if (result.errors && result.errors.length > 0) {
1814
+ totalErrors += result.errors.length;
1815
+ console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
1816
+ result.errors.forEach((error) => {
1817
+ console.log(ansis.red(` \u2022 ${error}`));
1818
+ });
1819
+ }
1820
+ if (result.warnings && result.warnings.length > 0) {
1821
+ totalWarnings += result.warnings.length;
1822
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
1823
+ result.warnings.forEach((warning) => {
1824
+ console.log(ansis.yellow(` \u2022 ${warning}`));
1825
+ });
1826
+ }
1827
+ });
1828
+ const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
1829
+ const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
1830
+ console.log("");
1831
+ console.log(ansis.cyan("\u2500".repeat(50)));
1832
+ if (mode === "complete") {
1833
+ if (totalErrors === 0) {
1834
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`));
1835
+ } else {
1836
+ console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`));
1837
+ }
1838
+ } else {
1839
+ if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
1840
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
1841
+ fileCount: totalRemovedFiles,
1842
+ configCount: totalRemovedConfigs
1843
+ })}`));
1844
+ } else if (totalRemovedFiles > 0) {
1845
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
1846
+ count: totalRemovedFiles
1847
+ })}`));
1848
+ } else if (totalRemovedConfigs > 0) {
1849
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
1850
+ count: totalRemovedConfigs
1851
+ })}`));
1852
+ } else {
1853
+ console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
1854
+ }
1855
+ if (totalErrors > 0) {
1856
+ console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`));
1857
+ }
1858
+ if (totalWarnings > 0) {
1859
+ console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`));
1860
+ }
1861
+ }
1862
+ console.log("");
1863
+ }
1864
+
1865
+ function resolveCodeToolType(optionValue, savedValue) {
1866
+ if (optionValue !== void 0) {
1867
+ const resolved = resolveCodeToolType$1(optionValue);
1868
+ if (resolved !== DEFAULT_CODE_TOOL_TYPE || optionValue === DEFAULT_CODE_TOOL_TYPE) {
1869
+ return resolved;
1870
+ }
1871
+ }
1872
+ if (savedValue && isCodeToolType(savedValue)) {
1873
+ return savedValue;
1874
+ }
1875
+ return DEFAULT_CODE_TOOL_TYPE;
1876
+ }
1877
+ async function update(options = {}) {
1878
+ try {
1879
+ if (!options.skipBanner) {
1880
+ displayBanner(i18n.t("cli:banner.updateSubtitle"));
1881
+ }
1882
+ const zcfConfig = readZcfConfig();
1883
+ const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
1884
+ options.codeType = codeToolType;
1885
+ if (codeToolType === "codex") {
1886
+ await runCodexUpdate();
1887
+ const newPreferredLang = options.configLang || zcfConfig?.preferredLang;
1888
+ if (newPreferredLang) {
1889
+ updateZcfConfig({
1890
+ version,
1891
+ preferredLang: newPreferredLang,
1892
+ codeToolType
1893
+ });
1894
+ } else {
1895
+ updateZcfConfig({
1896
+ version,
1897
+ codeToolType
1898
+ });
1899
+ }
1900
+ return;
1901
+ }
1902
+ const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.df; });
1903
+ const configLang = await resolveTemplateLanguage(
1904
+ options.configLang,
1905
+ // Command line option
1906
+ zcfConfig,
1907
+ options.skipPrompt
1908
+ // Non-interactive mode flag
1909
+ );
1910
+ const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt);
1911
+ console.log(ansis.cyan(`
1912
+ ${i18n.t("configuration:updatingPrompts")}
1913
+ `));
1914
+ await updatePromptOnly(aiOutputLang);
1915
+ await selectAndInstallWorkflows(configLang);
1916
+ await checkClaudeCodeVersionAndPrompt(false);
1917
+ updateZcfConfig({
1918
+ version,
1919
+ templateLang: configLang,
1920
+ // 保存模板语言选择
1921
+ aiOutputLang,
1922
+ codeToolType
1923
+ });
1924
+ } catch (error) {
1925
+ if (!handleExitPromptError(error)) {
1926
+ handleGeneralError(error);
1927
+ }
1928
+ }
1929
+ }
1930
+
1931
+ const CODE_TOOL_LABELS = {
1932
+ "claude-code": "Claude Code",
1933
+ "codex": "Codex",
1934
+ "aider": "Aider",
1935
+ "continue": "Continue",
1936
+ "cline": "Cline",
1937
+ "cursor": "Cursor"
1938
+ };
1939
+ function getCurrentCodeTool() {
1940
+ const config = readZcfConfig();
1941
+ if (config?.codeToolType && isCodeToolType(config.codeToolType)) {
1942
+ return config.codeToolType;
1943
+ }
1944
+ return DEFAULT_CODE_TOOL_TYPE;
1945
+ }
1946
+ function printSeparator() {
1947
+ console.log(`
1948
+ ${ansis.dim("\u2500".repeat(50))}
1949
+ `);
1950
+ }
1951
+ function getCodeToolLabel(codeTool) {
1952
+ return CODE_TOOL_LABELS[codeTool] || codeTool;
1953
+ }
1954
+ async function promptCodeToolSelection(current) {
1955
+ const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({
1956
+ name: label,
1957
+ value,
1958
+ short: label
1959
+ })));
1960
+ const { tool } = await inquirer.prompt({
1961
+ type: "list",
1962
+ name: "tool",
1963
+ message: i18n.t("menu:switchCodeToolPrompt"),
1964
+ default: current,
1965
+ choices
1966
+ });
1967
+ if (!tool) {
1968
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
1969
+ return null;
1970
+ }
1971
+ return tool;
1972
+ }
1973
+ async function handleCodeToolSwitch(current) {
1974
+ const newTool = await promptCodeToolSelection(current);
1975
+ if (!newTool || newTool === current) {
1976
+ return false;
1977
+ }
1978
+ updateZcfConfig({ codeToolType: newTool });
1979
+ console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`));
1980
+ return true;
1981
+ }
1982
+ async function showSuperpowersMenu() {
1983
+ console.log(ansis.cyan(i18n.t("superpowers:menu.title")));
1984
+ console.log(" -------- Superpowers --------");
1985
+ console.log(
1986
+ ` ${ansis.cyan("1.")} ${i18n.t("superpowers:menu.install")} ${ansis.gray(`- ${i18n.t("superpowers:menu.installDesc")}`)}`
1987
+ );
1988
+ console.log(
1989
+ ` ${ansis.cyan("2.")} ${i18n.t("superpowers:menu.uninstall")} ${ansis.gray(`- ${i18n.t("superpowers:menu.uninstallDesc")}`)}`
1990
+ );
1991
+ console.log(
1992
+ ` ${ansis.cyan("3.")} ${i18n.t("superpowers:menu.update")} ${ansis.gray(`- ${i18n.t("superpowers:menu.updateDesc")}`)}`
1993
+ );
1994
+ console.log(
1995
+ ` ${ansis.cyan("4.")} ${i18n.t("superpowers:menu.checkStatus")} ${ansis.gray(`- ${i18n.t("superpowers:menu.checkStatusDesc")}`)}`
1996
+ );
1997
+ console.log(
1998
+ ` ${ansis.cyan("5.")} ${i18n.t("superpowers:menu.viewSkills")} ${ansis.gray(`- ${i18n.t("superpowers:menu.viewSkillsDesc")}`)}`
1999
+ );
2000
+ console.log(` ${ansis.cyan("0.")} ${i18n.t("superpowers:menu.back")}`);
2001
+ console.log("");
2002
+ const { choice } = await inquirer.prompt({
2003
+ type: "input",
2004
+ name: "choice",
2005
+ message: i18n.t("common:enterChoice"),
2006
+ validate: (value) => {
2007
+ const valid = ["1", "2", "3", "4", "5", "0"];
2008
+ return valid.includes(value) || i18n.t("common:invalidChoice");
791
2009
  }
792
- return result;
2010
+ });
2011
+ if (!choice) {
2012
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2013
+ return;
793
2014
  }
794
- /**
795
- * 10. Remove backup files
796
- */
797
- async removeBackups() {
798
- const result = {
799
- success: false,
800
- removed: [],
801
- removedConfigs: [],
802
- errors: [],
803
- warnings: []
804
- };
805
- try {
806
- const backupPath = join(homedir(), ".claude", "backup");
807
- if (await pathExists(backupPath)) {
808
- const trashResult = await moveToTrash(backupPath);
809
- if (!trashResult[0]?.success) {
810
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
811
- }
812
- result.removed.push("backup/");
813
- result.success = true;
814
- } else {
815
- result.warnings.push(i18n.t("uninstall:backupsNotFound"));
816
- result.success = true;
2015
+ switch (choice) {
2016
+ case "1": {
2017
+ const { method } = await inquirer.prompt({
2018
+ type: "list",
2019
+ name: "method",
2020
+ message: i18n.t("superpowers:install.selectMethod"),
2021
+ choices: addNumbersToChoices([
2022
+ { name: i18n.t("superpowers:install.methodNpm"), value: "npm" },
2023
+ { name: i18n.t("superpowers:install.methodGit"), value: "git" }
2024
+ ])
2025
+ });
2026
+ if (method === "npm") {
2027
+ await installSuperpowers({ lang: i18n.language });
2028
+ } else if (method === "git") {
2029
+ await installSuperpowersViaGit();
817
2030
  }
818
- } catch (error) {
819
- result.errors.push(`Failed to remove backups: ${error.message}`);
2031
+ break;
820
2032
  }
821
- return result;
822
- }
823
- /**
824
- * 11. Remove CCJK preference configuration
825
- */
826
- async removeZcfConfig() {
827
- const result = {
828
- success: false,
829
- removed: [],
830
- removedConfigs: [],
831
- errors: [],
832
- warnings: []
833
- };
834
- try {
835
- const zcfConfigPath = ZCF_CONFIG_FILE;
836
- const relativeName = zcfConfigPath.replace(homedir(), "~");
837
- if (await pathExists(zcfConfigPath)) {
838
- const trashResult = await moveToTrash(zcfConfigPath);
839
- if (!trashResult[0]?.success) {
840
- result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
841
- }
842
- result.removed.push(relativeName);
843
- result.success = true;
2033
+ case "2": {
2034
+ const status = await checkSuperpowersInstalled();
2035
+ if (!status.installed) {
2036
+ console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
2037
+ break;
2038
+ }
2039
+ const { confirm } = await inquirer.prompt({
2040
+ type: "confirm",
2041
+ name: "confirm",
2042
+ message: i18n.t("superpowers:uninstall.confirm"),
2043
+ default: false
2044
+ });
2045
+ if (confirm) {
2046
+ await uninstallSuperpowers();
844
2047
  } else {
845
- result.warnings.push(i18n.t("uninstall:ccjkConfigNotFound"));
846
- result.success = true;
2048
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
847
2049
  }
848
- } catch (error) {
849
- result.errors.push(`Failed to remove CCJK config: ${error.message}`);
2050
+ break;
850
2051
  }
851
- return result;
852
- }
853
- /**
854
- * Complete uninstall - remove all directories and packages
855
- */
856
- async completeUninstall() {
857
- const result = {
858
- success: true,
859
- removed: [],
860
- removedConfigs: [],
861
- errors: [],
862
- warnings: []
863
- };
864
- try {
865
- const directoriesToRemove = [
866
- { path: join(homedir(), ".claude"), name: "~/.claude/" },
867
- { path: join(homedir(), ".claude.json"), name: "~/.claude.json" },
868
- { path: join(homedir(), ".claude-code-router"), name: "~/.claude-code-router/" }
869
- ];
870
- for (const dir of directoriesToRemove) {
871
- try {
872
- if (await pathExists(dir.path)) {
873
- const trashResult = await moveToTrash(dir.path);
874
- if (!trashResult[0]?.success) {
875
- result.warnings.push(`Failed to move ${dir.name} to trash: ${trashResult[0]?.error || "Unknown error"}`);
876
- }
877
- result.removed.push(dir.name);
878
- }
879
- } catch (error) {
880
- result.warnings.push(`Failed to remove ${dir.name}: ${error.message}`);
881
- }
882
- }
883
- const packagesToUninstall = [
884
- "@musistudio/claude-code-router",
885
- "@cometix/ccline",
886
- "@anthropic-ai/claude-code"
887
- ];
888
- for (const pkg of packagesToUninstall) {
889
- try {
890
- await exec$1("npm", ["uninstall", "-g", pkg]);
891
- result.removed.push(`${pkg} package`);
892
- } catch (error) {
893
- if (error.message.includes("not found") || error.message.includes("not installed")) {
894
- if (pkg.includes("claude-code-router")) {
895
- result.warnings.push(i18n.t("uninstall:ccrPackageNotFound"));
896
- } else if (pkg.includes("ccline")) {
897
- result.warnings.push(i18n.t("uninstall:cclinePackageNotFound"));
898
- } else {
899
- result.warnings.push(i18n.t("uninstall:claudeCodePackageNotFound"));
900
- }
901
- } else {
902
- result.warnings.push(`Failed to uninstall ${pkg}: ${error.message}`);
903
- }
904
- }
2052
+ case "3": {
2053
+ const status = await checkSuperpowersInstalled();
2054
+ if (!status.installed) {
2055
+ console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
2056
+ break;
905
2057
  }
906
- } catch (error) {
907
- result.errors.push(`Complete uninstall failed: ${error.message}`);
908
- result.success = false;
2058
+ await updateSuperpowers();
2059
+ break;
909
2060
  }
910
- return result;
911
- }
912
- /**
913
- * Custom uninstall with conflict resolution
914
- */
915
- async customUninstall(selectedItems) {
916
- const resolvedItems = this.resolveConflicts(selectedItems);
917
- const results = [];
918
- for (const item of resolvedItems) {
919
- try {
920
- const result = await this.executeUninstallItem(item);
921
- results.push(result);
922
- } catch (error) {
923
- results.push({
924
- success: false,
925
- removed: [],
926
- removedConfigs: [],
927
- errors: [`Failed to execute ${item}: ${error.message}`],
928
- warnings: []
929
- });
2061
+ case "4": {
2062
+ const status = await checkSuperpowersInstalled();
2063
+ if (status.installed) {
2064
+ console.log(ansis.green(`\u2714 ${i18n.t("superpowers:status.installed")}`));
2065
+ } else {
2066
+ console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
930
2067
  }
2068
+ break;
931
2069
  }
932
- return results;
933
- }
934
- /**
935
- * Resolve conflicts between uninstall items
936
- */
937
- resolveConflicts(items) {
938
- const resolved = [...items];
939
- for (const [primary, conflicts] of this.conflictResolution) {
940
- if (resolved.includes(primary)) {
941
- conflicts.forEach((conflict) => {
942
- const index = resolved.indexOf(conflict);
943
- if (index > -1) {
944
- resolved.splice(index, 1);
945
- }
2070
+ case "5": {
2071
+ const status = await checkSuperpowersInstalled();
2072
+ if (!status.installed) {
2073
+ console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
2074
+ break;
2075
+ }
2076
+ const skills = await getSuperpowersSkills();
2077
+ if (skills.length === 0) {
2078
+ console.log(ansis.yellow(i18n.t("superpowers:skills.noSkills")));
2079
+ } else {
2080
+ console.log(ansis.cyan(i18n.t("superpowers:skills.available")));
2081
+ skills.forEach((skill) => {
2082
+ console.log(` ${ansis.green("\u2022")} ${skill}`);
946
2083
  });
947
2084
  }
2085
+ break;
948
2086
  }
949
- return resolved;
2087
+ case "0":
2088
+ return;
2089
+ default:
2090
+ return;
950
2091
  }
951
- /**
952
- * Execute uninstall for a specific item
953
- */
954
- async executeUninstallItem(item) {
955
- switch (item) {
956
- case "output-styles":
957
- return await this.removeOutputStyles();
958
- case "commands":
959
- return await this.removeCustomCommands();
960
- case "agents":
961
- return await this.removeCustomAgents();
962
- case "claude-md":
963
- return await this.removeClaudeMd();
964
- case "permissions-envs":
965
- return await this.removePermissionsAndEnvs();
966
- case "mcps":
967
- return await this.removeMcps();
968
- case "ccr":
969
- return await this.uninstallCcr();
970
- case "ccline":
971
- return await this.uninstallCcline();
972
- case "claude-code":
973
- return await this.uninstallClaudeCode();
974
- case "backups":
975
- return await this.removeBackups();
976
- case "ccjk-config":
977
- return await this.removeZcfConfig();
978
- default:
979
- return {
980
- success: false,
981
- removed: [],
982
- removedConfigs: [],
983
- errors: [`Unknown uninstall item: ${item}`],
984
- warnings: []
985
- };
2092
+ printSeparator();
2093
+ }
2094
+ async function showMarketplaceMenu() {
2095
+ console.log(ansis.cyan(i18n.t("marketplace:menu.title")));
2096
+ console.log(" -------- Marketplace --------");
2097
+ console.log(
2098
+ ` ${ansis.cyan("1.")} ${i18n.t("marketplace:menu.search")} ${ansis.gray(`- ${i18n.t("marketplace:commands.search")}`)}`
2099
+ );
2100
+ console.log(
2101
+ ` ${ansis.cyan("2.")} ${i18n.t("marketplace:menu.browse")} ${ansis.gray(`- Browse by category`)}`
2102
+ );
2103
+ console.log(
2104
+ ` ${ansis.cyan("3.")} ${i18n.t("marketplace:menu.installed")} ${ansis.gray(`- ${i18n.t("marketplace:commands.list")}`)}`
2105
+ );
2106
+ console.log(
2107
+ ` ${ansis.cyan("4.")} ${i18n.t("marketplace:menu.updates")} ${ansis.gray(`- ${i18n.t("marketplace:commands.update")}`)}`
2108
+ );
2109
+ console.log(` ${ansis.cyan("0.")} ${i18n.t("marketplace:menu.back")}`);
2110
+ console.log("");
2111
+ const { choice } = await inquirer.prompt({
2112
+ type: "input",
2113
+ name: "choice",
2114
+ message: i18n.t("common:enterChoice"),
2115
+ validate: (value) => {
2116
+ const valid = ["1", "2", "3", "4", "0"];
2117
+ return valid.includes(value) || i18n.t("common:invalidChoice");
986
2118
  }
2119
+ });
2120
+ if (!choice) {
2121
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2122
+ return;
987
2123
  }
988
- }
989
-
990
- async function uninstall(options = {}) {
991
- try {
992
- ensureI18nInitialized();
993
- let codeType;
994
- if (options.codeType) {
995
- try {
996
- codeType = await resolveCodeType$1(options.codeType);
997
- } catch (error) {
998
- const errorMessage = error instanceof Error ? error.message : String(error);
999
- console.error(ansis.red(`${i18n.t("errors:generalError")} ${errorMessage}`));
1000
- const config = readZcfConfig();
1001
- codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
2124
+ switch (choice) {
2125
+ case "1": {
2126
+ const { query } = await inquirer.prompt({
2127
+ type: "input",
2128
+ name: "query",
2129
+ message: i18n.t("marketplace:prompts.searchQuery")
2130
+ });
2131
+ if (query) {
2132
+ console.log(i18n.t("marketplace:searching", { query }));
2133
+ try {
2134
+ const result = await searchPackages({ query, limit: 10 });
2135
+ if (result.packages.length === 0) {
2136
+ console.log(ansis.yellow(i18n.t("marketplace:noResults")));
2137
+ } else {
2138
+ console.log(ansis.green(i18n.t("marketplace:searchResults", { count: result.total })));
2139
+ console.log("");
2140
+ for (const pkg of result.packages) {
2141
+ console.log(` ${ansis.cyan(pkg.id)} ${ansis.gray(`v${pkg.version}`)}`);
2142
+ const description = pkg.description.en || Object.values(pkg.description)[0] || "";
2143
+ console.log(` ${ansis.dim(description)}`);
2144
+ }
2145
+ }
2146
+ } catch {
2147
+ console.error(ansis.red(i18n.t("marketplace:searchFailed")));
2148
+ }
1002
2149
  }
1003
- } else {
1004
- const config = readZcfConfig();
1005
- codeType = config?.codeToolType && isCodeToolType(config.codeToolType) ? config.codeToolType : DEFAULT_CODE_TOOL_TYPE;
2150
+ break;
1006
2151
  }
1007
- const uninstaller = new ZcfUninstaller(options.lang || "en");
1008
- if (codeType === "codex") {
1009
- const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.da; });
1010
- await runCodexUninstall();
1011
- return;
2152
+ case "2": {
2153
+ console.log(ansis.cyan(i18n.t("marketplace:categories.plugin")));
2154
+ console.log(ansis.dim("Category browsing coming soon..."));
2155
+ break;
1012
2156
  }
1013
- if (options.mode && options.mode !== "interactive") {
1014
- if (options.mode === "complete") {
1015
- await executeCompleteUninstall(uninstaller);
1016
- return;
1017
- } else if (options.mode === "custom" && options.items) {
1018
- let items;
1019
- if (typeof options.items === "string") {
1020
- items = options.items.split(",").map((item) => item.trim());
2157
+ case "3": {
2158
+ try {
2159
+ const installed = await getInstalledPackages();
2160
+ if (installed.length === 0) {
2161
+ console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
1021
2162
  } else {
1022
- items = options.items;
2163
+ console.log(ansis.green(i18n.t("marketplace:installedPackages", { count: installed.length })));
2164
+ console.log("");
2165
+ for (const pkg of installed) {
2166
+ const status = pkg.enabled ? ansis.green("\u25CF") : ansis.gray("\u25CB");
2167
+ console.log(` ${status} ${ansis.cyan(pkg.package.id)} ${ansis.gray(`v${pkg.package.version}`)}`);
2168
+ }
1023
2169
  }
1024
- await executeCustomUninstall(uninstaller, items);
1025
- return;
2170
+ } catch {
2171
+ console.error(ansis.red(i18n.t("marketplace:listFailed")));
1026
2172
  }
2173
+ break;
1027
2174
  }
1028
- await showInteractiveUninstall(uninstaller);
1029
- } catch (error) {
1030
- if (!handleExitPromptError(error)) {
1031
- handleGeneralError(error);
2175
+ case "4": {
2176
+ console.log(i18n.t("marketplace:checkingUpdates"));
2177
+ try {
2178
+ const updates = await checkForUpdates();
2179
+ if (updates.length === 0) {
2180
+ console.log(ansis.green(i18n.t("marketplace:noUpdates")));
2181
+ } else {
2182
+ console.log(ansis.cyan(i18n.t("marketplace:updatesAvailable", { count: updates.length })));
2183
+ console.log("");
2184
+ for (const update2 of updates) {
2185
+ console.log(` ${ansis.cyan(update2.id)}: ${update2.currentVersion} \u2192 ${ansis.green(update2.latestVersion)}`);
2186
+ }
2187
+ }
2188
+ } catch {
2189
+ console.error(ansis.red(i18n.t("marketplace:updateCheckFailed")));
2190
+ }
2191
+ break;
1032
2192
  }
2193
+ case "0":
2194
+ return;
2195
+ default:
2196
+ return;
1033
2197
  }
2198
+ printSeparator();
2199
+ await showMarketplaceMenu();
1034
2200
  }
1035
- async function showInteractiveUninstall(uninstaller) {
1036
- console.log(ansis.cyan.bold(i18n.t("uninstall:title")));
2201
+ async function showQuickActionsMenu() {
2202
+ const lang = i18n.language;
2203
+ const isZh = lang === "zh-CN";
2204
+ console.log(ansis.cyan(isZh ? "\u{1F680} \u5FEB\u6377\u64CD\u4F5C" : "\u{1F680} Quick Actions"));
1037
2205
  console.log("");
1038
- const { mainChoice } = await inquirer.prompt({
1039
- type: "list",
1040
- name: "mainChoice",
1041
- message: i18n.t("uninstall:selectMainOption"),
1042
- choices: addNumbersToChoices([
1043
- {
1044
- name: `${i18n.t("uninstall:completeUninstall")} - ${ansis.gray(i18n.t("uninstall:completeUninstallDesc"))}`,
1045
- value: "complete",
1046
- short: i18n.t("uninstall:completeUninstall")
1047
- },
1048
- {
1049
- name: `${i18n.t("uninstall:customUninstall")} - ${ansis.gray(i18n.t("uninstall:customUninstallDesc"))}`,
1050
- value: "custom",
1051
- short: i18n.t("uninstall:customUninstall")
1052
- }
1053
- ])
1054
- });
1055
- if (!mainChoice) {
1056
- console.log(ansis.yellow(i18n.t("common:cancelled")));
1057
- return;
1058
- }
1059
- if (mainChoice === "complete") {
1060
- await executeCompleteUninstall(uninstaller);
1061
- } else {
1062
- await showCustomUninstallMenu(uninstaller);
1063
- }
1064
- }
1065
- async function showCustomUninstallMenu(uninstaller) {
2206
+ console.log(generateQuickActionsPanel(lang));
1066
2207
  console.log("");
1067
- console.log(ansis.cyan(i18n.t("uninstall:selectCustomItems")));
1068
- const { customItems } = await inquirer.prompt({
1069
- type: "checkbox",
1070
- name: "customItems",
1071
- message: `${i18n.t("uninstall:selectItemsToRemove")} ${i18n.t("common:multiSelectHint")}`,
1072
- choices: [
1073
- {
1074
- name: i18n.t("uninstall:outputStyles"),
1075
- value: "output-styles"
1076
- },
1077
- {
1078
- name: i18n.t("uninstall:commands"),
1079
- value: "commands"
1080
- },
1081
- {
1082
- name: i18n.t("uninstall:agents"),
1083
- value: "agents"
1084
- },
1085
- {
1086
- name: i18n.t("uninstall:claudeMd"),
1087
- value: "claude-md"
1088
- },
1089
- {
1090
- name: i18n.t("uninstall:permissionsEnvs"),
1091
- value: "permissions-envs"
1092
- },
1093
- {
1094
- name: i18n.t("uninstall:mcps"),
1095
- value: "mcps"
1096
- },
1097
- {
1098
- name: i18n.t("uninstall:ccr"),
1099
- value: "ccr"
1100
- },
1101
- {
1102
- name: i18n.t("uninstall:ccline"),
1103
- value: "ccline"
1104
- },
1105
- {
1106
- name: i18n.t("uninstall:claudeCode"),
1107
- value: "claude-code"
1108
- },
1109
- {
1110
- name: i18n.t("uninstall:backups"),
1111
- value: "backups"
1112
- },
1113
- {
1114
- name: i18n.t("uninstall:ccjkConfig"),
1115
- value: "ccjk-config"
1116
- }
1117
- ],
1118
- validate: (answers) => {
1119
- if (answers.length === 0) {
1120
- return i18n.t("uninstall:selectAtLeastOne");
1121
- }
1122
- return true;
2208
+ const { choice } = await inquirer.prompt({
2209
+ type: "input",
2210
+ name: "choice",
2211
+ message: isZh ? "\u8F93\u5165\u6570\u5B57 (1-8) \u6216 0 \u8FD4\u56DE:" : "Enter number (1-8) or 0 to go back:",
2212
+ validate: (value) => {
2213
+ const valid = ["1", "2", "3", "4", "5", "6", "7", "8", "0", "?"];
2214
+ return valid.includes(value) || (isZh ? "\u8BF7\u8F93\u5165\u6709\u6548\u9009\u9879" : "Please enter a valid option");
1123
2215
  }
1124
2216
  });
1125
- if (!customItems || customItems.length === 0) {
1126
- console.log(ansis.yellow(i18n.t("common:cancelled")));
2217
+ if (!choice || choice === "0") {
1127
2218
  return;
1128
2219
  }
1129
- await executeCustomUninstall(uninstaller, customItems);
1130
- }
1131
- async function executeCompleteUninstall(uninstaller) {
1132
- console.log("");
1133
- console.log(ansis.red.bold(i18n.t("uninstall:executingComplete")));
1134
- console.log(ansis.yellow(i18n.t("uninstall:completeWarning")));
1135
- const confirm = await promptBoolean({
1136
- message: i18n.t("uninstall:confirmComplete"),
1137
- defaultValue: false
1138
- });
1139
- if (!confirm) {
1140
- console.log(ansis.yellow(i18n.t("common:cancelled")));
2220
+ if (choice === "?") {
2221
+ console.log("");
2222
+ console.log(generateSkillReferenceCard(lang));
2223
+ console.log("");
2224
+ printSeparator();
2225
+ await showQuickActionsMenu();
1141
2226
  return;
1142
2227
  }
1143
- console.log("");
1144
- console.log(ansis.cyan(i18n.t("uninstall:processingComplete")));
1145
- const result = await uninstaller.completeUninstall();
1146
- displayUninstallResult("complete", [result]);
2228
+ const actionNum = Number.parseInt(choice, 10);
2229
+ const action = QUICK_ACTIONS.find((a) => a.id === actionNum);
2230
+ if (action) {
2231
+ const actionName = isZh ? action.nameZh : action.name;
2232
+ console.log("");
2233
+ console.log(ansis.green(`\u2714 ${isZh ? "\u6267\u884C" : "Executing"}: ${action.icon} ${actionName}`));
2234
+ console.log(ansis.gray(`${isZh ? "\u547D\u4EE4" : "Command"}: ${action.command}`));
2235
+ console.log("");
2236
+ console.log(ansis.cyan(isZh ? `\u{1F4A1} \u63D0\u793A: \u5728 Claude Code \u4E2D\u8F93\u5165 "${action.command}" \u6216\u76F4\u63A5\u8F93\u5165 "${choice}" \u6765\u6267\u884C\u6B64\u64CD\u4F5C` : `\u{1F4A1} Tip: In Claude Code, type "${action.command}" or just "${choice}" to execute this action`));
2237
+ }
2238
+ printSeparator();
1147
2239
  }
1148
- async function executeCustomUninstall(uninstaller, items) {
2240
+ async function showSmartGuideMenu() {
2241
+ const lang = i18n.language;
2242
+ const isZh = lang === "zh-CN";
2243
+ const installed = await isSmartGuideInstalled();
2244
+ console.log(ansis.cyan(isZh ? "\u{1F3AF} \u667A\u80FD\u52A9\u624B" : "\u{1F3AF} Smart Assistant"));
1149
2245
  console.log("");
1150
- console.log(ansis.cyan(i18n.t("uninstall:executingCustom")));
1151
- console.log(ansis.gray(i18n.t("uninstall:selectedItems")));
1152
- items.forEach((item) => {
1153
- console.log(` \u2022 ${i18n.t(`uninstall:${item}`)}`);
1154
- });
1155
- const confirm = await promptBoolean({
1156
- message: i18n.t("uninstall:confirmCustom"),
1157
- defaultValue: false
1158
- });
1159
- if (!confirm) {
1160
- console.log(ansis.yellow(i18n.t("common:cancelled")));
1161
- return;
1162
- }
2246
+ console.log(isZh ? "\u667A\u80FD\u52A9\u624B\u8BA9\u4F60\u5728 Claude Code \u4E2D\u901A\u8FC7\u8F93\u5165\u6570\u5B57\u5FEB\u901F\u6267\u884C\u64CD\u4F5C" : "Smart Assistant lets you execute actions by typing numbers in Claude Code");
1163
2247
  console.log("");
1164
- console.log(ansis.cyan(i18n.t("uninstall:processingCustom")));
1165
- const results = await uninstaller.customUninstall(items);
1166
- displayUninstallResult("custom", results);
1167
- }
1168
- function displayUninstallResult(mode, results) {
2248
+ console.log(` ${isZh ? "\u72B6\u6001" : "Status"}: ${installed ? ansis.green(isZh ? "\u5DF2\u542F\u7528" : "Enabled") : ansis.yellow(isZh ? "\u672A\u542F\u7528" : "Disabled")}`);
1169
2249
  console.log("");
1170
- console.log(ansis.cyan("\u2500".repeat(50)));
1171
- let totalSuccess = 0;
1172
- let totalErrors = 0;
1173
- let totalWarnings = 0;
1174
- results.forEach((result) => {
1175
- if (result.success) {
1176
- totalSuccess++;
1177
- }
1178
- if (result.removed && result.removed.length > 0) {
1179
- console.log(ansis.green(`\u{1F5D1}\uFE0F ${i18n.t("uninstall:movedToTrash")}:`));
1180
- result.removed.forEach((item) => {
1181
- console.log(ansis.gray(` \u2022 ${item}`));
1182
- });
1183
- }
1184
- if (result.removedConfigs && result.removedConfigs.length > 0) {
1185
- console.log(ansis.green(`\u2714 ${i18n.t("uninstall:removedConfigs")}:`));
1186
- result.removedConfigs.forEach((item) => {
1187
- console.log(ansis.gray(` \u2022 ${item}`));
1188
- });
1189
- }
1190
- if (result.errors && result.errors.length > 0) {
1191
- totalErrors += result.errors.length;
1192
- console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errors")}:`));
1193
- result.errors.forEach((error) => {
1194
- console.log(ansis.red(` \u2022 ${error}`));
1195
- });
1196
- }
1197
- if (result.warnings && result.warnings.length > 0) {
1198
- totalWarnings += result.warnings.length;
1199
- console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warnings")}:`));
1200
- result.warnings.forEach((warning) => {
1201
- console.log(ansis.yellow(` \u2022 ${warning}`));
1202
- });
1203
- }
1204
- });
1205
- const totalRemovedFiles = results.reduce((count, result) => count + (result.removed?.length || 0), 0);
1206
- const totalRemovedConfigs = results.reduce((count, result) => count + (result.removedConfigs?.length || 0), 0);
2250
+ console.log(` ${ansis.cyan("1.")} ${installed ? isZh ? "\u66F4\u65B0\u667A\u80FD\u52A9\u624B" : "Update Smart Assistant" : isZh ? "\u542F\u7528\u667A\u80FD\u52A9\u624B" : "Enable Smart Assistant"}`);
2251
+ console.log(` ${ansis.cyan("2.")} ${isZh ? "\u7981\u7528\u667A\u80FD\u52A9\u624B" : "Disable Smart Assistant"}`);
2252
+ console.log(` ${ansis.cyan("3.")} ${isZh ? "\u67E5\u770B\u6280\u80FD\u901F\u67E5\u5361" : "View Skills Reference Card"}`);
2253
+ console.log(` ${ansis.cyan("0.")} ${i18n.t("common:back")}`);
1207
2254
  console.log("");
1208
- console.log(ansis.cyan("\u2500".repeat(50)));
1209
- if (mode === "complete") {
1210
- if (totalErrors === 0) {
1211
- console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:completeSuccess")}`));
1212
- } else {
1213
- console.log(ansis.yellow.bold(`\u26A0 ${i18n.t("uninstall:completePartialSuccess")}`));
1214
- }
1215
- } else {
1216
- if (totalRemovedFiles > 0 && totalRemovedConfigs > 0) {
1217
- console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessBoth", {
1218
- fileCount: totalRemovedFiles,
1219
- configCount: totalRemovedConfigs
1220
- })}`));
1221
- } else if (totalRemovedFiles > 0) {
1222
- console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessFiles", {
1223
- count: totalRemovedFiles
1224
- })}`));
1225
- } else if (totalRemovedConfigs > 0) {
1226
- console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccessConfigs", {
1227
- count: totalRemovedConfigs
1228
- })}`));
1229
- } else {
1230
- console.log(ansis.green.bold(`\u2714 ${i18n.t("uninstall:customSuccess", { count: totalSuccess })}`));
2255
+ const { choice } = await inquirer.prompt({
2256
+ type: "input",
2257
+ name: "choice",
2258
+ message: i18n.t("common:enterChoice"),
2259
+ validate: (value) => {
2260
+ const valid = ["1", "2", "3", "0"];
2261
+ return valid.includes(value) || i18n.t("common:invalidChoice");
1231
2262
  }
1232
- if (totalErrors > 0) {
1233
- console.log(ansis.red(`\u2716 ${i18n.t("uninstall:errorsCount", { count: totalErrors })}`));
2263
+ });
2264
+ if (!choice || choice === "0") {
2265
+ return;
2266
+ }
2267
+ switch (choice) {
2268
+ case "1": {
2269
+ const success = await injectSmartGuide(lang);
2270
+ if (success) {
2271
+ console.log(ansis.green(`\u2714 ${isZh ? "\u667A\u80FD\u52A9\u624B\u5DF2\u542F\u7528" : "Smart Assistant enabled"}`));
2272
+ } else {
2273
+ console.log(ansis.red(isZh ? "\u542F\u7528\u5931\u8D25" : "Failed to enable"));
2274
+ }
2275
+ break;
1234
2276
  }
1235
- if (totalWarnings > 0) {
1236
- console.log(ansis.yellow(`\u26A0 ${i18n.t("uninstall:warningsCount", { count: totalWarnings })}`));
2277
+ case "2": {
2278
+ if (!installed) {
2279
+ console.log(ansis.yellow(isZh ? "\u667A\u80FD\u52A9\u624B\u672A\u542F\u7528" : "Smart Assistant is not enabled"));
2280
+ break;
2281
+ }
2282
+ const success = await removeSmartGuide();
2283
+ if (success) {
2284
+ console.log(ansis.green(`\u2714 ${isZh ? "\u667A\u80FD\u52A9\u624B\u5DF2\u7981\u7528" : "Smart Assistant disabled"}`));
2285
+ } else {
2286
+ console.log(ansis.red(isZh ? "\u7981\u7528\u5931\u8D25" : "Failed to disable"));
2287
+ }
2288
+ break;
2289
+ }
2290
+ case "3": {
2291
+ console.log("");
2292
+ console.log(generateSkillReferenceCard(lang));
2293
+ break;
1237
2294
  }
1238
2295
  }
1239
- console.log("");
2296
+ printSeparator();
1240
2297
  }
1241
-
1242
- function resolveCodeToolType(optionValue, savedValue) {
1243
- if (optionValue !== void 0) {
1244
- const resolved = resolveCodeToolType$1(optionValue);
1245
- if (resolved !== DEFAULT_CODE_TOOL_TYPE || optionValue === DEFAULT_CODE_TOOL_TYPE) {
1246
- return resolved;
2298
+ async function showWorkflowsAndSkillsMenu() {
2299
+ const lang = i18n.language;
2300
+ const isZh = lang === "zh-CN";
2301
+ console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.workflowsTitle")));
2302
+ console.log(" -------- Workflows & Skills --------");
2303
+ console.log(` ${ansis.cyan("1.")} ${i18n.t("menu:ccjkFeatures.viewInstalledWorkflows")}`);
2304
+ console.log(` ${ansis.cyan("2.")} ${i18n.t("menu:ccjkFeatures.viewInstalledSkills")}`);
2305
+ console.log(` ${ansis.cyan("3.")} ${i18n.t("menu:ccjkFeatures.installNewWorkflow")}`);
2306
+ console.log(` ${ansis.cyan("4.")} ${isZh ? "\u{1F680} \u5FEB\u6377\u64CD\u4F5C\u9762\u677F" : "\u{1F680} Quick Actions Panel"}`);
2307
+ console.log(` ${ansis.cyan("5.")} ${isZh ? "\u{1F3AF} \u667A\u80FD\u52A9\u624B\u8BBE\u7F6E" : "\u{1F3AF} Smart Assistant Settings"}`);
2308
+ console.log(` ${ansis.cyan("0.")} ${i18n.t("common:back")}`);
2309
+ console.log("");
2310
+ const { choice } = await inquirer.prompt({
2311
+ type: "input",
2312
+ name: "choice",
2313
+ message: i18n.t("common:enterChoice"),
2314
+ validate: (value) => {
2315
+ const valid = ["1", "2", "3", "4", "5", "0"];
2316
+ return valid.includes(value) || i18n.t("common:invalidChoice");
1247
2317
  }
2318
+ });
2319
+ if (!choice) {
2320
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2321
+ return;
1248
2322
  }
1249
- if (savedValue && isCodeToolType(savedValue)) {
1250
- return savedValue;
1251
- }
1252
- return DEFAULT_CODE_TOOL_TYPE;
1253
- }
1254
- async function update(options = {}) {
1255
- try {
1256
- if (!options.skipBanner) {
1257
- displayBanner(i18n.t("cli:banner.updateSubtitle"));
2323
+ switch (choice) {
2324
+ case "1": {
2325
+ console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.availableStyles")));
2326
+ console.log(ansis.dim("Feature coming soon - will show installed workflows"));
2327
+ break;
1258
2328
  }
1259
- const zcfConfig = readZcfConfig();
1260
- const codeToolType = resolveCodeToolType(options.codeType, zcfConfig?.codeToolType);
1261
- options.codeType = codeToolType;
1262
- if (codeToolType === "codex") {
1263
- await runCodexUpdate();
1264
- const newPreferredLang = options.configLang || zcfConfig?.preferredLang;
1265
- if (newPreferredLang) {
1266
- updateZcfConfig({
1267
- version,
1268
- preferredLang: newPreferredLang,
1269
- codeToolType
1270
- });
2329
+ case "2": {
2330
+ const status = await checkSuperpowersInstalled();
2331
+ if (!status.installed) {
2332
+ console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
2333
+ break;
2334
+ }
2335
+ const skills = await getSuperpowersSkills();
2336
+ if (skills.length === 0) {
2337
+ console.log(ansis.yellow(i18n.t("menu:ccjkFeatures.noSkillsInstalled")));
1271
2338
  } else {
1272
- updateZcfConfig({
1273
- version,
1274
- codeToolType
2339
+ console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.skillCount", { count: skills.length })));
2340
+ console.log("");
2341
+ skills.forEach((skill) => {
2342
+ console.log(` ${ansis.green("\u2022")} ${skill}`);
1275
2343
  });
1276
2344
  }
2345
+ break;
2346
+ }
2347
+ case "3": {
2348
+ await update({ skipBanner: true });
2349
+ break;
2350
+ }
2351
+ case "4": {
2352
+ printSeparator();
2353
+ await showQuickActionsMenu();
1277
2354
  return;
1278
2355
  }
1279
- const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.d9; });
1280
- const configLang = await resolveTemplateLanguage(
1281
- options.configLang,
1282
- // Command line option
1283
- zcfConfig,
1284
- options.skipPrompt
1285
- // Non-interactive mode flag
1286
- );
1287
- const aiOutputLang = await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig, options.skipPrompt);
1288
- console.log(ansis.cyan(`
1289
- ${i18n.t("configuration:updatingPrompts")}
1290
- `));
1291
- await updatePromptOnly(aiOutputLang);
1292
- await selectAndInstallWorkflows(configLang);
1293
- await checkClaudeCodeVersionAndPrompt(false);
1294
- updateZcfConfig({
1295
- version,
1296
- templateLang: configLang,
1297
- // 保存模板语言选择
1298
- aiOutputLang,
1299
- codeToolType
1300
- });
1301
- } catch (error) {
1302
- if (!handleExitPromptError(error)) {
1303
- handleGeneralError(error);
2356
+ case "5": {
2357
+ printSeparator();
2358
+ await showSmartGuideMenu();
2359
+ return;
1304
2360
  }
2361
+ case "0":
2362
+ return;
2363
+ default:
2364
+ return;
1305
2365
  }
2366
+ printSeparator();
1306
2367
  }
1307
-
1308
- const CODE_TOOL_LABELS = {
1309
- "claude-code": "Claude Code",
1310
- "codex": "Codex",
1311
- "aider": "Aider",
1312
- "continue": "Continue",
1313
- "cline": "Cline",
1314
- "cursor": "Cursor"
1315
- };
1316
- function getCurrentCodeTool() {
1317
- const config = readZcfConfig();
1318
- if (config?.codeToolType && isCodeToolType(config.codeToolType)) {
1319
- return config.codeToolType;
1320
- }
1321
- return DEFAULT_CODE_TOOL_TYPE;
1322
- }
1323
- function printSeparator() {
1324
- console.log(`
1325
- ${ansis.dim("\u2500".repeat(50))}
1326
- `);
1327
- }
1328
- function getCodeToolLabel(codeTool) {
1329
- return CODE_TOOL_LABELS[codeTool] || codeTool;
2368
+ async function showOutputStylesMenu() {
2369
+ console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.outputStylesTitle")));
2370
+ console.log("");
2371
+ console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.availableStyles")));
2372
+ console.log(` ${ansis.green("\u2022")} speed-coder`);
2373
+ console.log(` ${ansis.green("\u2022")} senior-architect`);
2374
+ console.log(` ${ansis.green("\u2022")} pair-programmer`);
2375
+ console.log(` ${ansis.green("\u2022")} expert-concise`);
2376
+ console.log(` ${ansis.green("\u2022")} teaching-mode`);
2377
+ console.log(` ${ansis.green("\u2022")} casual-friendly`);
2378
+ console.log(` ${ansis.green("\u2022")} technical-precise`);
2379
+ console.log("");
2380
+ console.log(ansis.dim('Tip: Output styles are configured during initialization or via "Configure Claude global memory"'));
2381
+ printSeparator();
1330
2382
  }
1331
- async function promptCodeToolSelection(current) {
1332
- const choices = addNumbersToChoices(Object.entries(CODE_TOOL_LABELS).map(([value, label]) => ({
1333
- name: label,
1334
- value,
1335
- short: label
1336
- })));
1337
- const { tool } = await inquirer.prompt({
1338
- type: "list",
1339
- name: "tool",
1340
- message: i18n.t("menu:switchCodeToolPrompt"),
1341
- default: current,
1342
- choices
1343
- });
1344
- if (!tool) {
1345
- console.log(ansis.yellow(i18n.t("common:cancelled")));
1346
- return null;
1347
- }
1348
- return tool;
2383
+ async function showConfigSwitchMenu() {
2384
+ console.log(ansis.cyan(i18n.t("menu:ccjkFeatures.configSwitchTitle")));
2385
+ console.log("");
2386
+ await configSwitchCommand({ codeType: "claude-code" });
1349
2387
  }
1350
- async function handleCodeToolSwitch(current) {
1351
- const newTool = await promptCodeToolSelection(current);
1352
- if (!newTool || newTool === current) {
1353
- return false;
1354
- }
1355
- updateZcfConfig({ codeToolType: newTool });
1356
- console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(newTool) })}`));
1357
- return true;
2388
+ function printCcjkFeaturesSection() {
2389
+ console.log(` -------- ${i18n.t("menu:menuSections.ccjkFeatures")} --------`);
2390
+ console.log(
2391
+ ` ${ansis.cyan("W.")} ${i18n.t("menu:menuOptions.workflowsAndSkills")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.workflowsAndSkills")}`)}`
2392
+ );
2393
+ console.log(
2394
+ ` ${ansis.cyan("O.")} ${i18n.t("menu:menuOptions.outputStyles")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.outputStyles")}`)}`
2395
+ );
2396
+ console.log(
2397
+ ` ${ansis.cyan("C.")} ${i18n.t("menu:menuOptions.configSwitch")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configSwitch")}`)}`
2398
+ );
2399
+ console.log("");
1358
2400
  }
1359
- function printOtherToolsSection() {
1360
- console.log(` --------- ${i18n.t("menu:menuSections.otherTools")} ----------`);
2401
+ function printRecommendedPluginsSection() {
2402
+ console.log(` -------- ${i18n.t("menu:menuSections.recommendedPlugins")} --------`);
1361
2403
  console.log(
1362
2404
  ` ${ansis.cyan("R.")} ${i18n.t("menu:menuOptions.ccrManagement")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.ccrManagement")}`)}`
1363
2405
  );
@@ -1367,6 +2409,12 @@ function printOtherToolsSection() {
1367
2409
  console.log(
1368
2410
  ` ${ansis.cyan("L.")} ${i18n.t("menu:menuOptions.cometixLine")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.cometixLine")}`)}`
1369
2411
  );
2412
+ console.log(
2413
+ ` ${ansis.cyan("P.")} ${i18n.t("menu:menuOptions.superpowers")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.superpowers")}`)}`
2414
+ );
2415
+ console.log(
2416
+ ` ${ansis.cyan("M.")} ${i18n.t("menu:menuOptions.marketplace")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.marketplace")}`)}`
2417
+ );
1370
2418
  console.log("");
1371
2419
  }
1372
2420
  function printZcfSection(options) {
@@ -1411,7 +2459,8 @@ async function showClaudeCodeMenu() {
1411
2459
  ` ${ansis.cyan("7.")} ${i18n.t("menu:menuOptions.configureEnvPermission")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.configureEnvPermission")}`)}`
1412
2460
  );
1413
2461
  console.log("");
1414
- printOtherToolsSection();
2462
+ printCcjkFeaturesSection();
2463
+ printRecommendedPluginsSection();
1415
2464
  printZcfSection({
1416
2465
  uninstallOption: i18n.t("menu:menuOptions.uninstall"),
1417
2466
  uninstallDescription: i18n.t("menu:menuDescriptions.uninstall"),
@@ -1423,7 +2472,7 @@ async function showClaudeCodeMenu() {
1423
2472
  name: "choice",
1424
2473
  message: i18n.t("common:enterChoice"),
1425
2474
  validate: (value) => {
1426
- const valid = ["1", "2", "3", "4", "5", "6", "7", "r", "R", "u", "U", "l", "L", "0", "-", "+", "s", "S", "q", "Q"];
2475
+ const valid = ["1", "2", "3", "4", "5", "6", "7", "w", "W", "o", "O", "c", "C", "r", "R", "u", "U", "l", "L", "p", "P", "m", "M", "0", "-", "+", "s", "S", "q", "Q"];
1427
2476
  return valid.includes(value) || i18n.t("common:invalidChoice");
1428
2477
  }
1429
2478
  });
@@ -1454,118 +2503,38 @@ async function showClaudeCodeMenu() {
1454
2503
  case "7":
1455
2504
  await configureEnvPermissionFeature();
1456
2505
  break;
1457
- case "r":
1458
- await runCcrMenuFeature();
2506
+ case "w":
2507
+ await showWorkflowsAndSkillsMenu();
1459
2508
  printSeparator();
1460
2509
  return void 0;
1461
- case "u":
1462
- await runCcusageFeature();
2510
+ case "o":
2511
+ await showOutputStylesMenu();
1463
2512
  printSeparator();
1464
2513
  return void 0;
1465
- case "l":
1466
- await runCometixMenuFeature();
2514
+ case "c":
2515
+ await showConfigSwitchMenu();
1467
2516
  printSeparator();
1468
2517
  return void 0;
1469
- case "0": {
1470
- const currentLang = i18n.language;
1471
- await changeScriptLanguageFeature(currentLang);
2518
+ case "r":
2519
+ await runCcrMenuFeature();
1472
2520
  printSeparator();
1473
2521
  return void 0;
1474
- }
1475
- case "-":
1476
- await uninstall();
2522
+ case "u":
2523
+ await runCcusageFeature();
1477
2524
  printSeparator();
1478
2525
  return void 0;
1479
- case "+":
1480
- await checkUpdates();
2526
+ case "l":
2527
+ await runCometixMenuFeature();
1481
2528
  printSeparator();
1482
2529
  return void 0;
1483
- case "s": {
1484
- const switched = await handleCodeToolSwitch("claude-code");
1485
- if (switched) {
1486
- return "switch";
1487
- }
2530
+ case "p":
2531
+ await showSuperpowersMenu();
1488
2532
  printSeparator();
1489
- return void 0;
1490
- }
1491
- case "q":
1492
- console.log(ansis.cyan(i18n.t("common:goodbye")));
1493
- return "exit";
1494
- default:
1495
- return void 0;
1496
- }
1497
- printSeparator();
1498
- const shouldContinue = await promptBoolean({
1499
- message: i18n.t("common:returnToMenu"),
1500
- defaultValue: true
1501
- });
1502
- if (!shouldContinue) {
1503
- console.log(ansis.cyan(i18n.t("common:goodbye")));
1504
- return "exit";
1505
- }
1506
- return void 0;
1507
- }
1508
- async function showCodexMenu() {
1509
- console.log(ansis.cyan(i18n.t("menu:selectFunction")));
1510
- console.log(" -------- Codex --------");
1511
- console.log(
1512
- ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
1513
- );
1514
- console.log(
1515
- ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
1516
- );
1517
- console.log(
1518
- ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
1519
- );
1520
- console.log(
1521
- ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
1522
- );
1523
- console.log(
1524
- ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
1525
- );
1526
- console.log(
1527
- ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
1528
- );
1529
- console.log("");
1530
- printZcfSection({
1531
- uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
1532
- uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
1533
- updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
1534
- updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
1535
- });
1536
- const { choice } = await inquirer.prompt({
1537
- type: "input",
1538
- name: "choice",
1539
- message: i18n.t("common:enterChoice"),
1540
- validate: (value) => {
1541
- const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
1542
- return valid.includes(value) || i18n.t("common:invalidChoice");
1543
- }
1544
- });
1545
- if (!choice) {
1546
- console.log(ansis.yellow(i18n.t("common:cancelled")));
1547
- return "exit";
1548
- }
1549
- const normalized = choice.toLowerCase();
1550
- switch (normalized) {
1551
- case "1":
1552
- await runCodexFullInit();
1553
- break;
1554
- case "2":
1555
- await runCodexWorkflowImportWithLanguageSelection();
1556
- break;
1557
- case "3":
1558
- await configureCodexApi();
1559
- break;
1560
- case "4":
1561
- await configureCodexMcp();
1562
- break;
1563
- case "5":
1564
- await configureCodexDefaultModelFeature();
1565
- break;
1566
- case "6":
1567
- await configureCodexAiMemoryFeature();
1568
- break;
2533
+ return void 0;
2534
+ case "m":
2535
+ await showMarketplaceMenu();
2536
+ printSeparator();
2537
+ return void 0;
1569
2538
  case "0": {
1570
2539
  const currentLang = i18n.language;
1571
2540
  await changeScriptLanguageFeature(currentLang);
@@ -1573,473 +2542,300 @@ async function showCodexMenu() {
1573
2542
  return void 0;
1574
2543
  }
1575
2544
  case "-":
1576
- await runCodexUninstall();
2545
+ await uninstall();
1577
2546
  printSeparator();
1578
2547
  return void 0;
1579
2548
  case "+":
1580
- await runCodexUpdate();
2549
+ await checkUpdates();
1581
2550
  printSeparator();
1582
2551
  return void 0;
1583
2552
  case "s": {
1584
- const switched = await handleCodeToolSwitch("codex");
2553
+ const switched = await handleCodeToolSwitch("claude-code");
1585
2554
  if (switched) {
1586
- return "switch";
1587
- }
1588
- printSeparator();
1589
- return void 0;
1590
- }
1591
- case "q":
1592
- console.log(ansis.cyan(i18n.t("common:goodbye")));
1593
- return "exit";
1594
- default:
1595
- return void 0;
1596
- }
1597
- printSeparator();
1598
- const shouldContinue = await promptBoolean({
1599
- message: i18n.t("common:returnToMenu"),
1600
- defaultValue: true
1601
- });
1602
- if (!shouldContinue) {
1603
- console.log(ansis.cyan(i18n.t("common:goodbye")));
1604
- return "exit";
1605
- }
1606
- return void 0;
1607
- }
1608
- async function showMainMenu(options = {}) {
1609
- try {
1610
- if (options.codeType) {
1611
- try {
1612
- const resolvedType = await resolveCodeType$1(options.codeType);
1613
- const currentType = getCurrentCodeTool();
1614
- if (resolvedType !== currentType) {
1615
- updateZcfConfig({ codeToolType: resolvedType });
1616
- console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
1617
- }
1618
- } catch (err) {
1619
- const errorMessage = err instanceof Error ? err.message : String(err);
1620
- console.error(ansis.yellow(errorMessage));
1621
- }
1622
- }
1623
- let exitMenu = false;
1624
- while (!exitMenu) {
1625
- const codeTool = getCurrentCodeTool();
1626
- displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "CCJK");
1627
- const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
1628
- if (result === "exit") {
1629
- exitMenu = true;
1630
- } else if (result === "switch") {
1631
- continue;
1632
- }
1633
- }
1634
- } catch (error) {
1635
- if (!handleExitPromptError(error)) {
1636
- handleGeneralError(error);
1637
- }
1638
- }
1639
- }
1640
-
1641
- async function ccr(options = {}) {
1642
- try {
1643
- if (!options.skipBanner) {
1644
- displayBannerWithInfo();
1645
- }
1646
- const continueInCcr = await showCcrMenu();
1647
- if (!continueInCcr && !options.skipBanner) {
1648
- await showMainMenu();
1649
- }
1650
- } catch (error) {
1651
- if (!handleExitPromptError(error)) {
1652
- handleGeneralError(error);
1653
- }
1654
- }
1655
- }
1656
-
1657
- async function checkGitRepo() {
1658
- try {
1659
- await exec$1("git", ["rev-parse", "--git-dir"]);
1660
- return true;
1661
- } catch {
1662
- return false;
1663
- }
1664
- }
1665
- async function getGitStatus() {
1666
- const isRepo = await checkGitRepo();
1667
- if (!isRepo)
1668
- return { isRepo: false, hasChanges: false, staged: [], unstaged: [], untracked: [] };
1669
- const { stdout } = await exec$1("git", ["status", "--porcelain"]);
1670
- const lines = stdout.trim().split("\n").filter(Boolean);
1671
- const staged = [];
1672
- const unstaged = [];
1673
- const untracked = [];
1674
- for (const line of lines) {
1675
- const [s1, s2] = line.substring(0, 2);
1676
- const file = line.substring(3);
1677
- if (s1 !== " " && s1 !== "?")
1678
- staged.push(file);
1679
- if (s2 !== " ")
1680
- unstaged.push(file);
1681
- if (line.startsWith("??"))
1682
- untracked.push(file);
1683
- }
1684
- return {
1685
- isRepo: true,
1686
- hasChanges: staged.length + unstaged.length + untracked.length > 0,
1687
- staged,
1688
- unstaged,
1689
- untracked
1690
- };
1691
- }
1692
- async function generateCommitMessage(files) {
1693
- if (files.length === 0)
1694
- return "chore: update files";
1695
- const { stdout: diff } = await exec$1("git", ["diff", "--cached", "--stat"]);
1696
- const hasTest = files.some((f) => f.includes("test") || f.includes("spec"));
1697
- const hasDocs = files.some((f) => f.endsWith(".md"));
1698
- const hasConfig = files.some((f) => f.endsWith(".json") || f.endsWith(".yaml"));
1699
- const hasTs = files.some((f) => f.endsWith(".ts"));
1700
- const type = hasTest ? "test" : hasDocs ? "docs" : hasConfig ? "config" : hasTs ? "feat" : "chore";
1701
- const scope = files.length === 1 ? files[0].split("/")[0] : void 0;
1702
- const fileList = files.length <= 3 ? files.join(", ") : `${files.length} files`;
1703
- const message = scope ? `${type}(${scope}): update ${fileList}` : `${type}: update ${fileList}`;
1704
- return `${message}
1705
-
1706
- ${diff.trim()}`;
1707
- }
1708
- async function stageAllChanges() {
1709
- await exec$1("git", ["add", "-A"]);
1710
- }
1711
- async function commitChanges(message) {
1712
- await exec$1("git", ["commit", "-m", message]);
1713
- }
1714
-
1715
- async function commit(options = {}) {
1716
- if (!await checkGitRepo()) {
1717
- console.log(ansis.red("\u2717 Not a git repository"));
1718
- return;
1719
- }
1720
- const status = await getGitStatus();
1721
- if (!status.hasChanges) {
1722
- console.log(ansis.yellow("No changes to commit"));
1723
- return;
1724
- }
1725
- console.log(ansis.cyan("\n\u{1F4DD} Changes detected:"));
1726
- if (status.staged.length > 0) {
1727
- console.log(ansis.green(` Staged: ${status.staged.length} files`));
1728
- status.staged.forEach((f) => console.log(ansis.gray(` ${f}`)));
1729
- }
1730
- if (status.unstaged.length > 0)
1731
- console.log(ansis.yellow(` Unstaged: ${status.unstaged.length} files`));
1732
- if (status.untracked.length > 0)
1733
- console.log(ansis.yellow(` Untracked: ${status.untracked.length} files`));
1734
- if (status.unstaged.length > 0 || status.untracked.length > 0) {
1735
- await stageAllChanges();
1736
- console.log(ansis.green("\n\u2713 All changes staged"));
1737
- }
1738
- const allFiles = [...status.staged, ...status.unstaged, ...status.untracked];
1739
- let message;
1740
- if (options.message) {
1741
- message = options.message;
1742
- } else if (options.auto) {
1743
- message = await generateCommitMessage(allFiles);
1744
- console.log(ansis.cyan("\n\u{1F4AC} Generated commit message:"));
1745
- console.log(ansis.white(message));
1746
- } else {
1747
- const suggested = await generateCommitMessage(allFiles);
1748
- const { commitMessage } = await inquirer.prompt([{
1749
- type: "input",
1750
- name: "commitMessage",
1751
- message: "Commit message:",
1752
- default: suggested.split("\n")[0]
1753
- }]);
1754
- message = commitMessage;
1755
- }
1756
- if (options.dryRun) {
1757
- console.log(ansis.yellow("\n\u{1F50D} Dry run - no commit created"));
1758
- console.log(ansis.gray("Would commit with:"));
1759
- console.log(ansis.white(message));
1760
- return;
1761
- }
1762
- try {
1763
- await commitChanges(message);
1764
- console.log(ansis.green("\n\u2713 Changes committed"));
1765
- } catch (error) {
1766
- console.log(ansis.red(`
1767
- \u2717 Commit failed: ${error}`));
1768
- }
1769
- }
1770
-
1771
- async function configSwitchCommand(options) {
1772
- try {
1773
- ensureI18nInitialized();
1774
- if (options.list) {
1775
- await handleList(options.codeType);
1776
- return;
1777
- }
1778
- if (options.target) {
1779
- const resolvedCodeType = resolveCodeType(options.codeType);
1780
- await handleDirectSwitch(resolvedCodeType, options.target);
1781
- return;
1782
- }
1783
- await handleInteractiveSwitch(options.codeType);
1784
- } catch (error) {
1785
- if (process$1.env.NODE_ENV === "test" || process$1.env.VITEST) {
1786
- throw error;
1787
- }
1788
- handleGeneralError(error);
1789
- }
1790
- }
1791
- function resolveCodeType(codeType) {
1792
- if (codeType !== void 0) {
1793
- const resolved = resolveCodeToolType$1(codeType);
1794
- return resolved;
1795
- }
1796
- const zcfConfig = readZcfConfig();
1797
- if (zcfConfig?.codeToolType && isCodeToolType(zcfConfig.codeToolType)) {
1798
- return zcfConfig.codeToolType;
1799
- }
1800
- return DEFAULT_CODE_TOOL_TYPE;
1801
- }
1802
- async function handleList(codeType) {
1803
- const targetCodeType = resolveCodeType(codeType);
1804
- if (targetCodeType === "claude-code") {
1805
- await listClaudeCodeProfiles();
1806
- } else if (targetCodeType === "codex") {
1807
- await listCodexProvidersWithDisplay();
1808
- }
1809
- }
1810
- async function listCodexProvidersWithDisplay() {
1811
- const providers = await listCodexProviders();
1812
- const existingConfig = readCodexConfig();
1813
- const currentProvider = existingConfig?.modelProvider;
1814
- const isCommented = existingConfig?.modelProviderCommented;
1815
- if (!providers || providers.length === 0) {
1816
- console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
1817
- return;
1818
- }
1819
- console.log(ansis.bold(i18n.t("codex:listProvidersTitle")));
1820
- console.log();
1821
- if (currentProvider && !isCommented) {
1822
- console.log(ansis.cyan(i18n.t("codex:currentProvider", { provider: currentProvider })));
1823
- console.log();
1824
- }
1825
- providers.forEach((provider) => {
1826
- const isCurrent = currentProvider === provider.id && !isCommented;
1827
- const status = isCurrent ? ansis.green("\u25CF ") : " ";
1828
- const current = isCurrent ? ansis.yellow(` (${i18n.t("common:current")})`) : "";
1829
- console.log(`${status}${ansis.white(provider.name)}${current}`);
1830
- console.log(` ${ansis.cyan(`ID: ${provider.id}`)} ${ansis.gray(`(${provider.baseUrl})`)}`);
1831
- if (provider.tempEnvKey) {
1832
- console.log(` ${ansis.gray(`Env: ${provider.tempEnvKey}`)}`);
2555
+ return "switch";
2556
+ }
2557
+ printSeparator();
2558
+ return void 0;
1833
2559
  }
1834
- console.log();
1835
- });
1836
- }
1837
- async function listClaudeCodeProfiles() {
1838
- const config = ClaudeCodeConfigManager.readConfig();
1839
- if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1840
- console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1841
- return;
2560
+ case "q":
2561
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
2562
+ return "exit";
2563
+ default:
2564
+ return void 0;
1842
2565
  }
1843
- console.log(ansis.bold(i18n.t("multi-config:availableClaudeCodeProfiles")));
1844
- console.log();
1845
- const currentProfileId = config.currentProfileId;
1846
- Object.values(config.profiles).forEach((profile) => {
1847
- const isCurrent = profile.id === currentProfileId;
1848
- const status = isCurrent ? ansis.green("\u25CF ") : " ";
1849
- const current = isCurrent ? ansis.yellow(i18n.t("common:current")) : "";
1850
- console.log(`${status}${ansis.white(profile.name)}${current}`);
1851
- console.log(` ${ansis.cyan(`ID: ${profile.id}`)} ${ansis.gray(`(${profile.authType})`)}`);
1852
- console.log();
2566
+ printSeparator();
2567
+ const shouldContinue = await promptBoolean({
2568
+ message: i18n.t("common:returnToMenu"),
2569
+ defaultValue: true
1853
2570
  });
1854
- }
1855
- async function handleDirectSwitch(codeType, target) {
1856
- const resolvedCodeType = resolveCodeType(codeType);
1857
- if (resolvedCodeType === "claude-code") {
1858
- await handleClaudeCodeDirectSwitch(target);
1859
- } else if (resolvedCodeType === "codex") {
1860
- await switchCodexProvider(target);
2571
+ if (!shouldContinue) {
2572
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
2573
+ return "exit";
1861
2574
  }
2575
+ return void 0;
1862
2576
  }
1863
- async function handleClaudeCodeDirectSwitch(target) {
1864
- if (target === "official") {
1865
- const result = await ClaudeCodeConfigManager.switchToOfficial();
1866
- if (result.success) {
1867
- try {
1868
- await ClaudeCodeConfigManager.applyProfileSettings(null);
1869
- console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToOfficial")));
1870
- } catch (error) {
1871
- const reason = error instanceof Error ? error.message : String(error);
1872
- console.log(ansis.red(reason));
1873
- }
1874
- } else {
1875
- console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
1876
- }
1877
- } else if (target === "ccr") {
1878
- const result = await ClaudeCodeConfigManager.switchToCcr();
1879
- if (result.success) {
1880
- try {
1881
- const profile = ClaudeCodeConfigManager.getProfileById("ccr-proxy");
1882
- await ClaudeCodeConfigManager.applyProfileSettings(profile);
1883
- console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToCcr")));
1884
- } catch (error) {
1885
- const reason = error instanceof Error ? error.message : String(error);
1886
- console.log(ansis.red(reason));
1887
- }
1888
- } else {
1889
- console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
1890
- }
1891
- } else {
1892
- const config = ClaudeCodeConfigManager.readConfig();
1893
- if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1894
- console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1895
- return;
1896
- }
1897
- const normalizedTarget = target.trim();
1898
- let resolvedId = normalizedTarget;
1899
- let resolvedProfile = config.profiles[normalizedTarget];
1900
- if (!resolvedProfile) {
1901
- const match = Object.entries(config.profiles).find(([, profile]) => profile.name === normalizedTarget);
1902
- if (match) {
1903
- resolvedId = match[0];
1904
- resolvedProfile = match[1];
1905
- }
2577
+ async function showCodexMenu() {
2578
+ console.log(ansis.cyan(i18n.t("menu:selectFunction")));
2579
+ console.log(" -------- Codex --------");
2580
+ console.log(
2581
+ ` ${ansis.cyan("1.")} ${i18n.t("menu:menuOptions.codexFullInit")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexFullInit")}`)}`
2582
+ );
2583
+ console.log(
2584
+ ` ${ansis.cyan("2.")} ${i18n.t("menu:menuOptions.codexImportWorkflow")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexImportWorkflow")}`)}`
2585
+ );
2586
+ console.log(
2587
+ ` ${ansis.cyan("3.")} ${i18n.t("menu:menuOptions.codexConfigureApi")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureApi")}`)}`
2588
+ );
2589
+ console.log(
2590
+ ` ${ansis.cyan("4.")} ${i18n.t("menu:menuOptions.codexConfigureMcp")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureMcp")}`)}`
2591
+ );
2592
+ console.log(
2593
+ ` ${ansis.cyan("5.")} ${i18n.t("menu:menuOptions.codexConfigureModel")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureModel")}`)}`
2594
+ );
2595
+ console.log(
2596
+ ` ${ansis.cyan("6.")} ${i18n.t("menu:menuOptions.codexConfigureAiMemory")} ${ansis.gray(`- ${i18n.t("menu:menuDescriptions.codexConfigureAiMemory")}`)}`
2597
+ );
2598
+ console.log("");
2599
+ printZcfSection({
2600
+ uninstallOption: i18n.t("menu:menuOptions.codexUninstall"),
2601
+ uninstallDescription: i18n.t("menu:menuDescriptions.codexUninstall"),
2602
+ updateOption: i18n.t("menu:menuOptions.codexCheckUpdates"),
2603
+ updateDescription: i18n.t("menu:menuDescriptions.codexCheckUpdates")
2604
+ });
2605
+ const { choice } = await inquirer.prompt({
2606
+ type: "input",
2607
+ name: "choice",
2608
+ message: i18n.t("common:enterChoice"),
2609
+ validate: (value) => {
2610
+ const valid = ["1", "2", "3", "4", "5", "6", "0", "-", "+", "s", "S", "q", "Q"];
2611
+ return valid.includes(value) || i18n.t("common:invalidChoice");
1906
2612
  }
1907
- if (!resolvedProfile) {
1908
- console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
1909
- return;
2613
+ });
2614
+ if (!choice) {
2615
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2616
+ return "exit";
2617
+ }
2618
+ const normalized = choice.toLowerCase();
2619
+ switch (normalized) {
2620
+ case "1":
2621
+ await runCodexFullInit();
2622
+ break;
2623
+ case "2":
2624
+ await runCodexWorkflowImportWithLanguageSelection();
2625
+ break;
2626
+ case "3":
2627
+ await configureCodexApi();
2628
+ break;
2629
+ case "4":
2630
+ await configureCodexMcp();
2631
+ break;
2632
+ case "5":
2633
+ await configureCodexDefaultModelFeature();
2634
+ break;
2635
+ case "6":
2636
+ await configureCodexAiMemoryFeature();
2637
+ break;
2638
+ case "0": {
2639
+ const currentLang = i18n.language;
2640
+ await changeScriptLanguageFeature(currentLang);
2641
+ printSeparator();
2642
+ return void 0;
1910
2643
  }
1911
- const result = await ClaudeCodeConfigManager.switchProfile(resolvedId);
1912
- if (result.success) {
1913
- try {
1914
- await ClaudeCodeConfigManager.applyProfileSettings({ ...resolvedProfile, id: resolvedId });
1915
- console.log(ansis.green(i18n.t("multi-config:successfullySwitchedToProfile", { name: resolvedProfile.name })));
1916
- } catch (error) {
1917
- const reason = error instanceof Error ? error.message : String(error);
1918
- console.log(ansis.red(reason));
2644
+ case "-":
2645
+ await runCodexUninstall();
2646
+ printSeparator();
2647
+ return void 0;
2648
+ case "+":
2649
+ await runCodexUpdate();
2650
+ printSeparator();
2651
+ return void 0;
2652
+ case "s": {
2653
+ const switched = await handleCodeToolSwitch("codex");
2654
+ if (switched) {
2655
+ return "switch";
1919
2656
  }
1920
- } else {
1921
- console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
2657
+ printSeparator();
2658
+ return void 0;
1922
2659
  }
2660
+ case "q":
2661
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
2662
+ return "exit";
2663
+ default:
2664
+ return void 0;
1923
2665
  }
1924
- }
1925
- async function handleInteractiveSwitch(codeType) {
1926
- const resolvedCodeType = resolveCodeType(codeType);
1927
- if (resolvedCodeType === "claude-code") {
1928
- await handleClaudeCodeInteractiveSwitch();
1929
- } else if (resolvedCodeType === "codex") {
1930
- await handleCodexInteractiveSwitch();
2666
+ printSeparator();
2667
+ const shouldContinue = await promptBoolean({
2668
+ message: i18n.t("common:returnToMenu"),
2669
+ defaultValue: true
2670
+ });
2671
+ if (!shouldContinue) {
2672
+ console.log(ansis.cyan(i18n.t("common:goodbye")));
2673
+ return "exit";
1931
2674
  }
2675
+ return void 0;
1932
2676
  }
1933
- async function handleClaudeCodeInteractiveSwitch() {
1934
- const config = ClaudeCodeConfigManager.readConfig();
1935
- if (!config || !config.profiles || Object.keys(config.profiles).length === 0) {
1936
- console.log(ansis.yellow(i18n.t("multi-config:noClaudeCodeProfilesAvailable")));
1937
- return;
1938
- }
1939
- const currentProfileId = config.currentProfileId;
1940
- const createClaudeCodeChoices = (profiles, currentProfileId2) => {
1941
- const choices2 = [];
1942
- const isOfficialMode = !currentProfileId2 || currentProfileId2 === "official";
1943
- choices2.push({
1944
- name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("codex:useOfficialLogin")}`,
1945
- value: "official"
1946
- });
1947
- const isCcrMode = currentProfileId2 === "ccr-proxy";
1948
- choices2.push({
1949
- name: isCcrMode ? `${ansis.green("\u25CF ")}${i18n.t("multi-config:ccrProxyOption")} ${ansis.yellow(`(${i18n.t("common:current")})`)}` : ` ${i18n.t("multi-config:ccrProxyOption")}`,
1950
- value: "ccr"
1951
- });
1952
- Object.values(profiles).filter((profile) => profile.id !== "ccr-proxy").forEach((profile) => {
1953
- const isCurrent = profile.id === currentProfileId2;
1954
- choices2.push({
1955
- name: isCurrent ? `${ansis.green("\u25CF ")}${profile.name} ${ansis.yellow("(current)")}` : ` ${profile.name}`,
1956
- value: profile.id
1957
- });
1958
- });
1959
- return choices2;
1960
- };
1961
- const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
2677
+ async function showMainMenu(options = {}) {
1962
2678
  try {
1963
- const { selectedConfig } = await inquirer.prompt([{
1964
- type: "list",
1965
- name: "selectedConfig",
1966
- message: i18n.t("multi-config:selectClaudeCodeConfiguration"),
1967
- choices: addNumbersToChoices(choices)
1968
- }]);
1969
- if (!selectedConfig) {
1970
- console.log(ansis.yellow(i18n.t("multi-config:cancelled")));
1971
- return;
2679
+ if (options.codeType) {
2680
+ try {
2681
+ const resolvedType = await resolveCodeType$1(options.codeType);
2682
+ const currentType = getCurrentCodeTool();
2683
+ if (resolvedType !== currentType) {
2684
+ updateZcfConfig({ codeToolType: resolvedType });
2685
+ console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
2686
+ }
2687
+ } catch (err) {
2688
+ const errorMessage = err instanceof Error ? err.message : String(err);
2689
+ console.error(ansis.yellow(errorMessage));
2690
+ }
2691
+ }
2692
+ let exitMenu = false;
2693
+ while (!exitMenu) {
2694
+ const codeTool = getCurrentCodeTool();
2695
+ displayBannerWithInfo(CODE_TOOL_BANNERS[codeTool] || "CCJK");
2696
+ const result = codeTool === "codex" ? await showCodexMenu() : await showClaudeCodeMenu();
2697
+ if (result === "exit") {
2698
+ exitMenu = true;
2699
+ } else if (result === "switch") {
2700
+ continue;
2701
+ }
1972
2702
  }
1973
- await handleClaudeCodeDirectSwitch(selectedConfig);
1974
2703
  } catch (error) {
1975
- if (error.name === "ExitPromptError") {
1976
- console.log(ansis.cyan(`
1977
- ${i18n.t("common:goodbye")}`));
1978
- return;
2704
+ if (!handleExitPromptError(error)) {
2705
+ handleGeneralError(error);
1979
2706
  }
1980
- throw error;
1981
2707
  }
1982
2708
  }
1983
- async function handleCodexInteractiveSwitch() {
1984
- const providers = await listCodexProviders();
1985
- if (!providers || providers.length === 0) {
1986
- console.log(ansis.yellow(i18n.t("codex:noProvidersAvailable")));
1987
- return;
1988
- }
1989
- const existingConfig = readCodexConfig();
1990
- const currentProvider = existingConfig?.modelProvider;
1991
- const isCommented = existingConfig?.modelProviderCommented;
1992
- const createApiConfigChoices = (providers2, currentProvider2, isCommented2) => {
1993
- const choices2 = [];
1994
- const isOfficialMode = !currentProvider2 || isCommented2;
1995
- choices2.push({
1996
- name: isOfficialMode ? `${ansis.green("\u25CF ")}${i18n.t("codex:useOfficialLogin")} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${i18n.t("codex:useOfficialLogin")}`,
1997
- value: "official"
1998
- });
1999
- providers2.forEach((provider) => {
2000
- const isCurrent = currentProvider2 === provider.id && !isCommented2;
2001
- choices2.push({
2002
- name: isCurrent ? `${ansis.green("\u25CF ")}${provider.name} - ${ansis.gray(provider.id)} ${ansis.yellow("(\u5F53\u524D)")}` : ` ${provider.name} - ${ansis.gray(provider.id)}`,
2003
- value: provider.id
2004
- });
2005
- });
2006
- return choices2;
2007
- };
2008
- const choices = createApiConfigChoices(providers, currentProvider, isCommented);
2709
+
2710
+ async function ccr(options = {}) {
2009
2711
  try {
2010
- const { selectedConfig } = await inquirer.prompt([{
2011
- type: "list",
2012
- name: "selectedConfig",
2013
- message: i18n.t("codex:apiConfigSwitchPrompt"),
2014
- choices: addNumbersToChoices(choices)
2015
- }]);
2016
- if (!selectedConfig) {
2017
- console.log(ansis.yellow(i18n.t("common:cancelled")));
2018
- return;
2019
- }
2020
- let success = false;
2021
- if (selectedConfig === "official") {
2022
- success = await switchToOfficialLogin();
2023
- } else {
2024
- success = await switchToProvider(selectedConfig);
2712
+ if (!options.skipBanner) {
2713
+ displayBannerWithInfo();
2025
2714
  }
2026
- if (!success) {
2027
- console.log(ansis.red(i18n.t("common:operationFailed")));
2715
+ const continueInCcr = await showCcrMenu();
2716
+ if (!continueInCcr && !options.skipBanner) {
2717
+ await showMainMenu();
2028
2718
  }
2029
2719
  } catch (error) {
2030
- if (error.name === "ExitPromptError") {
2031
- console.log(ansis.cyan(`
2032
- ${i18n.t("common:goodbye")}`));
2033
- return;
2720
+ if (!handleExitPromptError(error)) {
2721
+ handleGeneralError(error);
2034
2722
  }
2035
- throw error;
2036
2723
  }
2037
2724
  }
2038
2725
 
2039
- const configSwitch = {
2040
- __proto__: null,
2041
- configSwitchCommand: configSwitchCommand
2042
- };
2726
+ async function checkGitRepo() {
2727
+ try {
2728
+ await exec$1("git", ["rev-parse", "--git-dir"]);
2729
+ return true;
2730
+ } catch {
2731
+ return false;
2732
+ }
2733
+ }
2734
+ async function getGitStatus() {
2735
+ const isRepo = await checkGitRepo();
2736
+ if (!isRepo)
2737
+ return { isRepo: false, hasChanges: false, staged: [], unstaged: [], untracked: [] };
2738
+ const { stdout } = await exec$1("git", ["status", "--porcelain"]);
2739
+ const lines = stdout.trim().split("\n").filter(Boolean);
2740
+ const staged = [];
2741
+ const unstaged = [];
2742
+ const untracked = [];
2743
+ for (const line of lines) {
2744
+ const [s1, s2] = line.substring(0, 2);
2745
+ const file = line.substring(3);
2746
+ if (s1 !== " " && s1 !== "?")
2747
+ staged.push(file);
2748
+ if (s2 !== " ")
2749
+ unstaged.push(file);
2750
+ if (line.startsWith("??"))
2751
+ untracked.push(file);
2752
+ }
2753
+ return {
2754
+ isRepo: true,
2755
+ hasChanges: staged.length + unstaged.length + untracked.length > 0,
2756
+ staged,
2757
+ unstaged,
2758
+ untracked
2759
+ };
2760
+ }
2761
+ async function generateCommitMessage(files) {
2762
+ if (files.length === 0)
2763
+ return "chore: update files";
2764
+ const { stdout: diff } = await exec$1("git", ["diff", "--cached", "--stat"]);
2765
+ const hasTest = files.some((f) => f.includes("test") || f.includes("spec"));
2766
+ const hasDocs = files.some((f) => f.endsWith(".md"));
2767
+ const hasConfig = files.some((f) => f.endsWith(".json") || f.endsWith(".yaml"));
2768
+ const hasTs = files.some((f) => f.endsWith(".ts"));
2769
+ const type = hasTest ? "test" : hasDocs ? "docs" : hasConfig ? "config" : hasTs ? "feat" : "chore";
2770
+ const scope = files.length === 1 ? files[0].split("/")[0] : void 0;
2771
+ const fileList = files.length <= 3 ? files.join(", ") : `${files.length} files`;
2772
+ const message = scope ? `${type}(${scope}): update ${fileList}` : `${type}: update ${fileList}`;
2773
+ return `${message}
2774
+
2775
+ ${diff.trim()}`;
2776
+ }
2777
+ async function stageAllChanges() {
2778
+ await exec$1("git", ["add", "-A"]);
2779
+ }
2780
+ async function commitChanges(message) {
2781
+ await exec$1("git", ["commit", "-m", message]);
2782
+ }
2783
+
2784
+ async function commit(options = {}) {
2785
+ if (!await checkGitRepo()) {
2786
+ console.log(ansis.red("\u2717 Not a git repository"));
2787
+ return;
2788
+ }
2789
+ const status = await getGitStatus();
2790
+ if (!status.hasChanges) {
2791
+ console.log(ansis.yellow("No changes to commit"));
2792
+ return;
2793
+ }
2794
+ console.log(ansis.cyan("\n\u{1F4DD} Changes detected:"));
2795
+ if (status.staged.length > 0) {
2796
+ console.log(ansis.green(` Staged: ${status.staged.length} files`));
2797
+ status.staged.forEach((f) => console.log(ansis.gray(` ${f}`)));
2798
+ }
2799
+ if (status.unstaged.length > 0)
2800
+ console.log(ansis.yellow(` Unstaged: ${status.unstaged.length} files`));
2801
+ if (status.untracked.length > 0)
2802
+ console.log(ansis.yellow(` Untracked: ${status.untracked.length} files`));
2803
+ if (status.unstaged.length > 0 || status.untracked.length > 0) {
2804
+ await stageAllChanges();
2805
+ console.log(ansis.green("\n\u2713 All changes staged"));
2806
+ }
2807
+ const allFiles = [...status.staged, ...status.unstaged, ...status.untracked];
2808
+ let message;
2809
+ if (options.message) {
2810
+ message = options.message;
2811
+ } else if (options.auto) {
2812
+ message = await generateCommitMessage(allFiles);
2813
+ console.log(ansis.cyan("\n\u{1F4AC} Generated commit message:"));
2814
+ console.log(ansis.white(message));
2815
+ } else {
2816
+ const suggested = await generateCommitMessage(allFiles);
2817
+ const { commitMessage } = await inquirer.prompt([{
2818
+ type: "input",
2819
+ name: "commitMessage",
2820
+ message: "Commit message:",
2821
+ default: suggested.split("\n")[0]
2822
+ }]);
2823
+ message = commitMessage;
2824
+ }
2825
+ if (options.dryRun) {
2826
+ console.log(ansis.yellow("\n\u{1F50D} Dry run - no commit created"));
2827
+ console.log(ansis.gray("Would commit with:"));
2828
+ console.log(ansis.white(message));
2829
+ return;
2830
+ }
2831
+ try {
2832
+ await commitChanges(message);
2833
+ console.log(ansis.green("\n\u2713 Changes committed"));
2834
+ } catch (error) {
2835
+ console.log(ansis.red(`
2836
+ \u2717 Commit failed: ${error}`));
2837
+ }
2838
+ }
2043
2839
 
2044
2840
  const projectFoundationQuestions = [
2045
2841
  {
@@ -4942,6 +5738,217 @@ async function listInterviewSessions() {
4942
5738
  console.log("");
4943
5739
  }
4944
5740
 
5741
+ async function searchCommand(query, _options) {
5742
+ try {
5743
+ console.log(ansis.cyan(i18n.t("marketplace:searching", { query })));
5744
+ const results = await searchPackages({ query });
5745
+ if (results.packages.length === 0) {
5746
+ console.log(ansis.yellow(i18n.t("marketplace:noResults")));
5747
+ return;
5748
+ }
5749
+ console.log(ansis.green(i18n.t("marketplace:searchResults", { count: results.packages.length })));
5750
+ console.log();
5751
+ for (const pkg of results.packages) {
5752
+ const installed = await isPackageInstalled(pkg.name);
5753
+ const installedMark = installed ? ansis.green("\u2713") : ansis.gray("\u25CB");
5754
+ console.log(`${installedMark} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
5755
+ console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
5756
+ console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
5757
+ if (pkg.verified === "verified") {
5758
+ console.log(` ${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
5759
+ }
5760
+ console.log();
5761
+ }
5762
+ } catch (err) {
5763
+ console.error(ansis.red(i18n.t("marketplace:searchFailed")));
5764
+ console.error(err);
5765
+ throw err;
5766
+ }
5767
+ }
5768
+ async function installCommand(packageName, options) {
5769
+ try {
5770
+ if (await isPackageInstalled(packageName)) {
5771
+ console.log(ansis.yellow(`Package '${packageName}' is already installed`));
5772
+ return;
5773
+ }
5774
+ const pkg = await getPackage(packageName);
5775
+ if (!pkg) {
5776
+ console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
5777
+ throw new Error(`Package not found: ${packageName}`);
5778
+ }
5779
+ console.log(ansis.cyan(i18n.t("marketplace:installing", { name: packageName })));
5780
+ const result = await installPackage(packageName, {
5781
+ force: options.force,
5782
+ skipVerification: options.skipVerification
5783
+ });
5784
+ if (result.success) {
5785
+ console.log(ansis.green(i18n.t("marketplace:installSuccess", { name: packageName })));
5786
+ if (result.installedPath) {
5787
+ console.log(ansis.gray(`${i18n.t("marketplace:installedAt")}: ${result.installedPath}`));
5788
+ }
5789
+ } else {
5790
+ console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
5791
+ if (result.error) {
5792
+ console.error(ansis.red(i18n.t("marketplace:errors.installError", { error: result.error })));
5793
+ }
5794
+ throw new Error(`Install failed: ${packageName}`);
5795
+ }
5796
+ } catch (err) {
5797
+ console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
5798
+ console.error(err);
5799
+ throw err;
5800
+ }
5801
+ }
5802
+ async function uninstallCommand(packageName, options) {
5803
+ try {
5804
+ if (!await isPackageInstalled(packageName)) {
5805
+ console.error(ansis.red(i18n.t("marketplace:packageNotInstalled", { name: packageName })));
5806
+ throw new Error(`Package not installed: ${packageName}`);
5807
+ }
5808
+ console.log(ansis.cyan(i18n.t("marketplace:uninstalling", { name: packageName })));
5809
+ const result = await uninstallPackage(packageName, {
5810
+ force: options.force
5811
+ });
5812
+ if (result.success) {
5813
+ console.log(ansis.green(i18n.t("marketplace:uninstallSuccess", { name: packageName })));
5814
+ } else {
5815
+ console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
5816
+ if (result.error) {
5817
+ console.error(ansis.red(i18n.t("marketplace:errors.uninstallError", { error: result.error })));
5818
+ }
5819
+ throw new Error(`Uninstall failed: ${packageName}`);
5820
+ }
5821
+ } catch (err) {
5822
+ console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
5823
+ console.error(err);
5824
+ throw err;
5825
+ }
5826
+ }
5827
+ async function updateCommand(packageName, _options) {
5828
+ try {
5829
+ if (packageName) {
5830
+ console.log(ansis.cyan(i18n.t("marketplace:updating", { name: packageName })));
5831
+ const result = await updatePackage(packageName);
5832
+ if (result.success) {
5833
+ console.log(ansis.green(i18n.t("marketplace:updateSuccess", { name: packageName })));
5834
+ } else {
5835
+ console.error(ansis.red(i18n.t("marketplace:updateFailed", { name: packageName })));
5836
+ if (result.error) {
5837
+ console.error(ansis.red(result.error));
5838
+ }
5839
+ throw new Error(`Update failed: ${packageName}`);
5840
+ }
5841
+ } else {
5842
+ console.log(ansis.cyan(i18n.t("marketplace:checkingUpdates")));
5843
+ const updates = await checkForUpdates();
5844
+ if (updates.length === 0) {
5845
+ console.log(ansis.green(i18n.t("marketplace:noUpdates")));
5846
+ return;
5847
+ }
5848
+ console.log(ansis.yellow(i18n.t("marketplace:updatesAvailable", { count: updates.length })));
5849
+ console.log();
5850
+ for (const update of updates) {
5851
+ console.log(` ${ansis.bold(update.id)}: ${ansis.gray(update.currentVersion)} \u2192 ${ansis.green(update.latestVersion)}`);
5852
+ }
5853
+ console.log();
5854
+ console.log(ansis.gray(i18n.t("marketplace:updateHint")));
5855
+ }
5856
+ } catch (err) {
5857
+ console.error(ansis.red(i18n.t("marketplace:updateCheckFailed")));
5858
+ console.error(err);
5859
+ throw err;
5860
+ }
5861
+ }
5862
+ async function listCommand(_options) {
5863
+ try {
5864
+ const installedList = await getInstalledPackages();
5865
+ if (installedList.length === 0) {
5866
+ console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
5867
+ return;
5868
+ }
5869
+ console.log(ansis.green(i18n.t("marketplace:installedPackages", { count: installedList.length })));
5870
+ console.log();
5871
+ for (const installed of installedList) {
5872
+ const pkg = installed.package;
5873
+ console.log(`${ansis.green("\u2713")} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
5874
+ console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
5875
+ console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
5876
+ console.log();
5877
+ }
5878
+ } catch (err) {
5879
+ console.error(ansis.red(i18n.t("marketplace:listFailed")));
5880
+ console.error(err);
5881
+ throw err;
5882
+ }
5883
+ }
5884
+ async function infoCommand(packageName, _options) {
5885
+ try {
5886
+ const pkg = await getPackage(packageName);
5887
+ if (!pkg) {
5888
+ console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
5889
+ throw new Error(`Package not found: ${packageName}`);
5890
+ }
5891
+ const installed = await isPackageInstalled(packageName);
5892
+ console.log();
5893
+ console.log(ansis.bold.cyan(pkg.name));
5894
+ console.log(ansis.gray("\u2500".repeat(50)));
5895
+ console.log();
5896
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.description"))}: ${pkg.description.en || Object.values(pkg.description)[0]}`);
5897
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.version"))}: ${pkg.version}`);
5898
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
5899
+ if (pkg.author) {
5900
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.author"))}: ${pkg.author}`);
5901
+ }
5902
+ if (pkg.license) {
5903
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.license"))}: ${pkg.license}`);
5904
+ }
5905
+ if (pkg.repository) {
5906
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.repository"))}: ${pkg.repository}`);
5907
+ }
5908
+ if (pkg.downloads !== void 0) {
5909
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.downloads"))}: ${pkg.downloads.toLocaleString()}`);
5910
+ }
5911
+ if (pkg.rating !== void 0) {
5912
+ const stars = "\u2605".repeat(Math.round(pkg.rating));
5913
+ const emptyStars = "\u2606".repeat(5 - Math.round(pkg.rating));
5914
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.rating"))}: ${ansis.yellow(stars)}${ansis.gray(emptyStars)} (${pkg.rating}/5)`);
5915
+ }
5916
+ if (pkg.keywords && pkg.keywords.length > 0) {
5917
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.keywords"))}: ${pkg.keywords.join(", ")}`);
5918
+ }
5919
+ if (pkg.verified === "verified") {
5920
+ console.log(`${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
5921
+ }
5922
+ console.log();
5923
+ console.log(`${ansis.bold("Status")}: ${installed ? ansis.green("Installed") : ansis.gray("Not installed")}`);
5924
+ console.log();
5925
+ } catch (err) {
5926
+ console.error(ansis.red(i18n.t("marketplace:infoFailed")));
5927
+ console.error(err);
5928
+ throw err;
5929
+ }
5930
+ }
5931
+ async function registerMarketplaceCommands(cli, withLanguageResolution) {
5932
+ cli.command("marketplace:search <query>", i18n.t("marketplace:commands.search")).alias("mp:search").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (query, options) => {
5933
+ await searchCommand(query);
5934
+ }));
5935
+ cli.command("marketplace:install <package>", i18n.t("marketplace:commands.install")).alias("mp:install").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).option("--force, -f", i18n.t("marketplace:options.force")).option("--skip-verification", i18n.t("marketplace:options.skipVerification")).action(await withLanguageResolution(async (packageName, options) => {
5936
+ await installCommand(packageName, options);
5937
+ }));
5938
+ cli.command("marketplace:uninstall <package>", i18n.t("marketplace:commands.uninstall")).alias("mp:uninstall").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).option("--force, -f", i18n.t("marketplace:options.force")).action(await withLanguageResolution(async (packageName, options) => {
5939
+ await uninstallCommand(packageName, options);
5940
+ }));
5941
+ cli.command("marketplace:update [package]", i18n.t("marketplace:commands.update")).alias("mp:update").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (packageName, options) => {
5942
+ await updateCommand(packageName);
5943
+ }));
5944
+ cli.command("marketplace:list", i18n.t("marketplace:commands.list")).alias("mp:list").alias("mp:ls").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (options) => {
5945
+ await listCommand();
5946
+ }));
5947
+ cli.command("marketplace:info <package>", i18n.t("marketplace:commands.info")).alias("mp:info").option("--lang, -l <lang>", i18n.t("marketplace:options.lang")).action(await withLanguageResolution(async (packageName, options) => {
5948
+ await infoCommand(packageName);
5949
+ }));
5950
+ }
5951
+
4945
5952
  const MCP_SERVERS = [
4946
5953
  { name: "Filesystem", description: "Secure file operations", package: "@modelcontextprotocol/server-filesystem", category: "core" },
4947
5954
  { name: "GitHub", description: "Repository management", package: "@modelcontextprotocol/server-github", category: "dev" },
@@ -5945,6 +6952,7 @@ async function setupCommands(cli) {
5945
6952
  cli.command("mcp <action> [...args]", "MCP Server marketplace (search, trending, install)").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(await withLanguageResolution(async (action, args, options) => {
5946
6953
  await mcpMarket(action, args, options);
5947
6954
  }));
6955
+ await registerMarketplaceCommands(cli, withLanguageResolution);
5948
6956
  cli.command("session <action> [id]", "Manage sessions (save, list, restore, export)").action(async (action, id) => {
5949
6957
  if (action === "save") {
5950
6958
  await saveSession();