ccjk 1.5.0 → 2.0.2

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 (56) hide show
  1. package/README.ja.md +249 -297
  2. package/README.ko.md +241 -290
  3. package/README.md +222 -364
  4. package/README.zh-CN.md +553 -295
  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-provider-manager.mjs +1 -1
  9. package/dist/chunks/codex-uninstaller.mjs +2 -2
  10. package/dist/chunks/commands.mjs +1 -1
  11. package/dist/chunks/features.mjs +10 -10
  12. package/dist/chunks/simple-config.mjs +321 -389
  13. package/dist/chunks/smart-guide.mjs +234 -0
  14. package/dist/cli.mjs +1795 -433
  15. package/dist/i18n/locales/en/configuration.json +12 -1
  16. package/dist/i18n/locales/en/marketplace.json +84 -0
  17. package/dist/i18n/locales/en/menu.json +38 -1
  18. package/dist/i18n/locales/en/skills.json +140 -0
  19. package/dist/i18n/locales/en/smartGuide.json +49 -0
  20. package/dist/i18n/locales/en/subagent.json +69 -0
  21. package/dist/i18n/locales/en/superpowers.json +58 -0
  22. package/dist/i18n/locales/zh-CN/configuration.json +12 -1
  23. package/dist/i18n/locales/zh-CN/marketplace.json +84 -0
  24. package/dist/i18n/locales/zh-CN/menu.json +38 -1
  25. package/dist/i18n/locales/zh-CN/skills.json +140 -0
  26. package/dist/i18n/locales/zh-CN/smartGuide.json +49 -0
  27. package/dist/i18n/locales/zh-CN/subagent.json +69 -0
  28. package/dist/i18n/locales/zh-CN/superpowers.json +58 -0
  29. package/dist/index.d.mts +1 -0
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.mjs +366 -7
  32. package/package.json +26 -27
  33. package/templates/common/skills/en/brainstorming.md +64 -0
  34. package/templates/common/skills/en/code-review.md +81 -0
  35. package/templates/common/skills/en/documentation-gen.md +808 -0
  36. package/templates/common/skills/en/executing-plans.md +75 -0
  37. package/templates/common/skills/en/git-commit.md +216 -0
  38. package/templates/common/skills/en/interview.md +223 -0
  39. package/templates/common/skills/en/migration-assistant.md +312 -0
  40. package/templates/common/skills/en/performance-profiling.md +576 -0
  41. package/templates/common/skills/en/pr-review.md +341 -0
  42. package/templates/common/skills/en/refactoring.md +384 -0
  43. package/templates/common/skills/en/security-audit.md +462 -0
  44. package/templates/common/skills/en/systematic-debugging.md +82 -0
  45. package/templates/common/skills/en/tdd-workflow.md +93 -0
  46. package/templates/common/skills/en/verification.md +81 -0
  47. package/templates/common/skills/en/workflow.md +370 -0
  48. package/templates/common/skills/en/writing-plans.md +78 -0
  49. package/templates/common/skills/zh-CN/documentation-gen.md +807 -0
  50. package/templates/common/skills/zh-CN/migration-assistant.md +318 -0
  51. package/templates/common/skills/zh-CN/performance-profiling.md +746 -0
  52. package/templates/common/skills/zh-CN/pr-review.md +341 -0
  53. package/templates/common/skills/zh-CN/refactoring.md +384 -0
  54. package/templates/common/skills/zh-CN/security-audit.md +462 -0
  55. package/templates/common/smart-guide/en/smart-guide.md +72 -0
  56. package/templates/common/smart-guide/zh-CN/smart-guide.md +72 -0
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';
5
- import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
4
+ import { S as STATUS, ch as i18n, n as runConfigWizard, ci as testApiConnection, m as displayCurrentStatus, cj as quickSetup, ck as format, k as COLORS, cl as getAllPresets, cm as ensureI18nInitialized, cn as readCcrConfig, co as isCcrInstalled, cp as installCcr, cq as configureCcrFeature, cr as promptBoolean, cs as handleExitPromptError, ct as handleGeneralError, cu as COMETIX_COMMAND_NAME, cv as COMETIX_COMMANDS, cw as installCometixLine, cx as addNumbersToChoices, cy as checkAndUpdateTools, aW as runCodexUpdate, cz as resolveCodeType$1, a2 as resolveCodeToolType$1, cA as readZcfConfig, $ as isCodeToolType, W as DEFAULT_CODE_TOOL_TYPE, a_ as switchCodexProvider, aM as listCodexProviders, aR as readCodexConfig, aD as switchToOfficialLogin, a$ as switchToProvider, cB as readJsonConfig, cC as writeJsonConfig, cD as moveToTrash, U as ZCF_CONFIG_FILE, ah as displayBanner, cE as updateZcfConfig, v as version, cF as resolveAiOutputLanguage, cG as updatePromptOnly, cH as selectAndInstallWorkflows, cI as checkClaudeCodeVersionAndPrompt, l as init, ai as displayBannerWithInfo, X as CODE_TOOL_BANNERS, y as CLAUDE_DIR, aV as runCodexUninstall, b5 as configureCodexMcp, aE as configureCodexApi, aY as runCodexWorkflowImportWithLanguageSelection, aT as runCodexFullInit, cJ as checkSuperpowersInstalled, cK as getSuperpowersSkills, cL as updateSuperpowers, cM as uninstallSuperpowers, cN as installSuperpowers, cO as installSuperpowersViaGit, q as commandExists, z as SETTINGS_FILE, _ as CODE_TOOL_INFO, bb as getToolStatus, bc as getAllToolsStatus, V as CODE_TOOL_TYPES, aj as boxify, be as installTool, cP as readZcfConfigAsync, cQ as initI18n, bV as quickSync, cf as checkAllVersions, cg as upgradeAll, i as detectAllConfigs, bB as displayConfigScan, c9 as displayPermissions, cR as selectScriptLanguage, cS as changeLanguage, bU as runOnboarding } from './chunks/simple-config.mjs';
5
+ import { existsSync, readdirSync, 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,124 +833,397 @@ 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 {
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}`)}`);
898
+ }
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;
907
+ }
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));
938
+ }
939
+ } else {
940
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToOfficial", { error: result.error })));
941
+ }
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));
952
+ }
953
+ } else {
954
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToCcr", { error: result.error })));
955
+ }
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];
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) {
978
+ try {
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));
984
+ }
985
+ } else {
986
+ console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
987
+ }
988
+ }
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"));
1150
+ }
1151
+ result.success = true;
1152
+ } catch (error) {
1153
+ result.errors.push(`Failed to remove output styles: ${error.message}`);
1154
+ }
1155
+ return result;
1156
+ }
1157
+ /**
1158
+ * 2. Remove custom commands directory (commands/ccjk/)
1159
+ */
1160
+ async removeCustomCommands() {
1161
+ const result = {
1162
+ success: false,
1163
+ removed: [],
1164
+ removedConfigs: [],
1165
+ errors: [],
1166
+ warnings: []
1167
+ };
1168
+ try {
1169
+ const commandsPath = join(homedir(), ".claude", "commands", "ccjk");
1170
+ if (await pathExists(commandsPath)) {
1171
+ const trashResult = await moveToTrash(commandsPath);
1172
+ if (!trashResult[0]?.success) {
1173
+ result.warnings.push(trashResult[0]?.error || "Failed to move to trash");
1174
+ }
1175
+ result.removed.push("commands/ccjk/");
1176
+ result.success = true;
1177
+ } else {
1178
+ result.warnings.push(i18n.t("uninstall:commandsNotFound"));
1179
+ result.success = true;
1180
+ }
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");
1203
+ }
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 {
604
1227
  const claudeMdPath = join(homedir(), ".claude", "CLAUDE.md");
605
1228
  if (await pathExists(claudeMdPath)) {
606
1229
  const trashResult = await moveToTrash(claudeMdPath);
@@ -770,7 +1393,7 @@ class ZcfUninstaller {
770
1393
  result.removed.push(".claude.json (includes MCP configuration)");
771
1394
  }
772
1395
  try {
773
- const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.db; });
1396
+ const { uninstallCodeTool } = await import('./chunks/simple-config.mjs').then(function (n) { return n.de; });
774
1397
  const success = await uninstallCodeTool("claude-code");
775
1398
  if (success) {
776
1399
  result.removed.push("@anthropic-ai/claude-code");
@@ -1006,7 +1629,7 @@ async function uninstall(options = {}) {
1006
1629
  }
1007
1630
  const uninstaller = new ZcfUninstaller(options.lang || "en");
1008
1631
  if (codeType === "codex") {
1009
- const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.da; });
1632
+ const { runCodexUninstall } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dd; });
1010
1633
  await runCodexUninstall();
1011
1634
  return;
1012
1635
  }
@@ -1276,7 +1899,7 @@ async function update(options = {}) {
1276
1899
  }
1277
1900
  return;
1278
1901
  }
1279
- const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.d9; });
1902
+ const { resolveTemplateLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.dc; });
1280
1903
  const configLang = await resolveTemplateLanguage(
1281
1904
  options.configLang,
1282
1905
  // Command line option
@@ -1325,39 +1948,458 @@ function printSeparator() {
1325
1948
  ${ansis.dim("\u2500".repeat(50))}
1326
1949
  `);
1327
1950
  }
1328
- function getCodeToolLabel(codeTool) {
1329
- return CODE_TOOL_LABELS[codeTool] || codeTool;
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");
2009
+ }
2010
+ });
2011
+ if (!choice) {
2012
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2013
+ return;
2014
+ }
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();
2030
+ }
2031
+ break;
2032
+ }
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();
2047
+ } else {
2048
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2049
+ }
2050
+ break;
2051
+ }
2052
+ case "3": {
2053
+ const status = await checkSuperpowersInstalled();
2054
+ if (!status.installed) {
2055
+ console.log(ansis.yellow(i18n.t("superpowers:status.notInstalled")));
2056
+ break;
2057
+ }
2058
+ await updateSuperpowers();
2059
+ break;
2060
+ }
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")));
2067
+ }
2068
+ break;
2069
+ }
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}`);
2083
+ });
2084
+ }
2085
+ break;
2086
+ }
2087
+ case "0":
2088
+ return;
2089
+ default:
2090
+ return;
2091
+ }
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");
2118
+ }
2119
+ });
2120
+ if (!choice) {
2121
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2122
+ return;
2123
+ }
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
+ }
2149
+ }
2150
+ break;
2151
+ }
2152
+ case "2": {
2153
+ console.log(ansis.cyan(i18n.t("marketplace:categories.plugin")));
2154
+ console.log(ansis.dim("Category browsing coming soon..."));
2155
+ break;
2156
+ }
2157
+ case "3": {
2158
+ try {
2159
+ const installed = await getInstalledPackages();
2160
+ if (installed.length === 0) {
2161
+ console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
2162
+ } else {
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
+ }
2169
+ }
2170
+ } catch {
2171
+ console.error(ansis.red(i18n.t("marketplace:listFailed")));
2172
+ }
2173
+ break;
2174
+ }
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;
2192
+ }
2193
+ case "0":
2194
+ return;
2195
+ default:
2196
+ return;
2197
+ }
2198
+ printSeparator();
2199
+ await showMarketplaceMenu();
2200
+ }
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"));
2205
+ console.log("");
2206
+ console.log(generateQuickActionsPanel(lang));
2207
+ console.log("");
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");
2215
+ }
2216
+ });
2217
+ if (!choice || choice === "0") {
2218
+ return;
2219
+ }
2220
+ if (choice === "?") {
2221
+ console.log("");
2222
+ console.log(generateSkillReferenceCard(lang));
2223
+ console.log("");
2224
+ printSeparator();
2225
+ await showQuickActionsMenu();
2226
+ return;
2227
+ }
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();
2239
+ }
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"));
2245
+ console.log("");
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");
2247
+ console.log("");
2248
+ console.log(` ${isZh ? "\u72B6\u6001" : "Status"}: ${installed ? ansis.green(isZh ? "\u5DF2\u542F\u7528" : "Enabled") : ansis.yellow(isZh ? "\u672A\u542F\u7528" : "Disabled")}`);
2249
+ console.log("");
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")}`);
2254
+ console.log("");
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");
2262
+ }
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;
2276
+ }
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;
2294
+ }
2295
+ }
2296
+ printSeparator();
2297
+ }
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");
2317
+ }
2318
+ });
2319
+ if (!choice) {
2320
+ console.log(ansis.yellow(i18n.t("common:cancelled")));
2321
+ return;
2322
+ }
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;
2328
+ }
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")));
2338
+ } else {
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}`);
2343
+ });
2344
+ }
2345
+ break;
2346
+ }
2347
+ case "3": {
2348
+ await update({ skipBanner: true });
2349
+ break;
2350
+ }
2351
+ case "4": {
2352
+ printSeparator();
2353
+ await showQuickActionsMenu();
2354
+ return;
2355
+ }
2356
+ case "5": {
2357
+ printSeparator();
2358
+ await showSmartGuideMenu();
2359
+ return;
2360
+ }
2361
+ case "0":
2362
+ return;
2363
+ default:
2364
+ return;
2365
+ }
2366
+ printSeparator();
2367
+ }
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,6 +2503,18 @@ async function showClaudeCodeMenu() {
1454
2503
  case "7":
1455
2504
  await configureEnvPermissionFeature();
1456
2505
  break;
2506
+ case "w":
2507
+ await showWorkflowsAndSkillsMenu();
2508
+ printSeparator();
2509
+ return void 0;
2510
+ case "o":
2511
+ await showOutputStylesMenu();
2512
+ printSeparator();
2513
+ return void 0;
2514
+ case "c":
2515
+ await showConfigSwitchMenu();
2516
+ printSeparator();
2517
+ return void 0;
1457
2518
  case "r":
1458
2519
  await runCcrMenuFeature();
1459
2520
  printSeparator();
@@ -1466,6 +2527,14 @@ async function showClaudeCodeMenu() {
1466
2527
  await runCometixMenuFeature();
1467
2528
  printSeparator();
1468
2529
  return void 0;
2530
+ case "p":
2531
+ await showSuperpowersMenu();
2532
+ printSeparator();
2533
+ return void 0;
2534
+ case "m":
2535
+ await showMarketplaceMenu();
2536
+ printSeparator();
2537
+ return void 0;
1469
2538
  case "0": {
1470
2539
  const currentLang = i18n.language;
1471
2540
  await changeScriptLanguageFeature(currentLang);
@@ -1605,8 +2674,77 @@ async function showCodexMenu() {
1605
2674
  }
1606
2675
  return void 0;
1607
2676
  }
2677
+ async function isFirstTimeUser() {
2678
+ const config = readZcfConfig();
2679
+ if (!config || !config.version) {
2680
+ return true;
2681
+ }
2682
+ if (!existsSync(join(CLAUDE_DIR, "commands"))) {
2683
+ return true;
2684
+ }
2685
+ return false;
2686
+ }
2687
+ async function showNewUserWelcome() {
2688
+ console.log("");
2689
+ console.log(ansis.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
2690
+ console.log(ansis.bold.cyan("\u2551") + ansis.bold.white(" \u{1F44B} \u6B22\u8FCE\u4F7F\u7528 CCJK\uFF01 ") + ansis.bold.cyan("\u2551"));
2691
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
2692
+ console.log(`${ansis.bold.cyan("\u2551")} CCJK \u5E2E\u52A9\u60A8\u5FEB\u901F\u914D\u7F6E Claude Code \u5F00\u53D1\u73AF\u5883 ${ansis.bold.cyan("\u2551")}`);
2693
+ console.log(`${ansis.bold.cyan("\u2551")} \u5305\u62EC API \u8BBE\u7F6E\u3001\u5DE5\u4F5C\u6D41\u6A21\u677F\u3001MCP \u670D\u52A1\u7B49 ${ansis.bold.cyan("\u2551")}`);
2694
+ console.log(ansis.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
2695
+ console.log("");
2696
+ const { mode } = await inquirer.prompt({
2697
+ type: "list",
2698
+ name: "mode",
2699
+ message: "\u8BF7\u9009\u62E9\uFF1A",
2700
+ choices: [
2701
+ {
2702
+ name: ansis.green("\u{1F680} \u5FEB\u901F\u5F00\u59CB") + ansis.dim(" - \u63A8\u8350\u65B0\u624B\uFF0C3\u5206\u949F\u5B8C\u6210\u914D\u7F6E"),
2703
+ value: "quick"
2704
+ },
2705
+ {
2706
+ name: ansis.cyan("\u2699\uFE0F \u5B8C\u6574\u914D\u7F6E") + ansis.dim(" - \u81EA\u5B9A\u4E49\u6240\u6709\u9009\u9879"),
2707
+ value: "full"
2708
+ },
2709
+ {
2710
+ name: ansis.yellow("\u{1F4D6} \u67E5\u770B\u5E2E\u52A9") + ansis.dim(" - \u4E86\u89E3 CCJK \u529F\u80FD"),
2711
+ value: "help"
2712
+ }
2713
+ ]
2714
+ });
2715
+ return mode;
2716
+ }
2717
+ async function showFeaturesOverview() {
2718
+ console.log("");
2719
+ console.log(ansis.bold.cyan("\u{1F4D6} CCJK \u529F\u80FD\u4ECB\u7ECD"));
2720
+ console.log("");
2721
+ console.log(ansis.cyan("\u6838\u5FC3\u529F\u80FD\uFF1A"));
2722
+ console.log(` ${ansis.green("\u2022")} API \u914D\u7F6E - \u652F\u6301 Auth Token\u3001API Key\u3001CCR \u4EE3\u7406`);
2723
+ console.log(` ${ansis.green("\u2022")} \u5DE5\u4F5C\u6D41\u6A21\u677F - Git\u3001SixStep\u3001Common Tools \u7B49\u9884\u8BBE\u5DE5\u4F5C\u6D41`);
2724
+ console.log(` ${ansis.green("\u2022")} MCP \u670D\u52A1 - \u4EE3\u7801\u5E93\u641C\u7D22\u3001\u6587\u4EF6\u7CFB\u7EDF\u3001\u7F51\u7EDC\u641C\u7D22\u7B49`);
2725
+ console.log(` ${ansis.green("\u2022")} \u8F93\u51FA\u98CE\u683C - \u591A\u79CD AI \u8F93\u51FA\u98CE\u683C\uFF08\u901F\u5EA6\u4F18\u5148\u3001\u67B6\u6784\u5E08\u3001\u7ED3\u5BF9\u7F16\u7A0B\u7B49\uFF09`);
2726
+ console.log("");
2727
+ console.log(ansis.cyan("\u63A8\u8350\u63D2\u4EF6\uFF1A"));
2728
+ console.log(` ${ansis.green("\u2022")} CCR - Claude Code Router \u4EE3\u7406\u5DE5\u5177`);
2729
+ console.log(` ${ansis.green("\u2022")} CCusage - API \u4F7F\u7528\u91CF\u7EDF\u8BA1\u5DE5\u5177`);
2730
+ console.log(` ${ansis.green("\u2022")} Cometix - \u72B6\u6001\u680F\u589E\u5F3A\u5DE5\u5177`);
2731
+ console.log(` ${ansis.green("\u2022")} Superpowers - \u6280\u80FD\u6269\u5C55\u7CFB\u7EDF`);
2732
+ console.log("");
2733
+ console.log(ansis.dim("\u6309 Enter \u7EE7\u7EED..."));
2734
+ await inquirer.prompt([{ type: "input", name: "continue", message: "" }]);
2735
+ }
1608
2736
  async function showMainMenu(options = {}) {
1609
2737
  try {
2738
+ if (await isFirstTimeUser()) {
2739
+ const mode = await showNewUserWelcome();
2740
+ if (mode === "quick") {
2741
+ await init({ skipPrompt: false });
2742
+ return;
2743
+ } else if (mode === "help") {
2744
+ await showFeaturesOverview();
2745
+ return showMainMenu(options);
2746
+ }
2747
+ }
1610
2748
  if (options.codeType) {
1611
2749
  try {
1612
2750
  const resolvedType = await resolveCodeType$1(options.codeType);
@@ -1746,300 +2884,217 @@ async function commit(options = {}) {
1746
2884
  } else {
1747
2885
  const suggested = await generateCommitMessage(allFiles);
1748
2886
  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}`)}`);
1833
- }
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;
1842
- }
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();
1853
- });
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);
1861
- }
1862
- }
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
- }
1906
- }
1907
- if (!resolvedProfile) {
1908
- console.log(ansis.red(i18n.t("multi-config:profileNameNotFound", { name: target })));
1909
- return;
1910
- }
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));
1919
- }
1920
- } else {
1921
- console.log(ansis.red(i18n.t("multi-config:failedToSwitchToProfile", { error: result.error })));
1922
- }
2887
+ type: "input",
2888
+ name: "commitMessage",
2889
+ message: "Commit message:",
2890
+ default: suggested.split("\n")[0]
2891
+ }]);
2892
+ message = commitMessage;
2893
+ }
2894
+ if (options.dryRun) {
2895
+ console.log(ansis.yellow("\n\u{1F50D} Dry run - no commit created"));
2896
+ console.log(ansis.gray("Would commit with:"));
2897
+ console.log(ansis.white(message));
2898
+ return;
2899
+ }
2900
+ try {
2901
+ await commitChanges(message);
2902
+ console.log(ansis.green("\n\u2713 Changes committed"));
2903
+ } catch (error) {
2904
+ console.log(ansis.red(`
2905
+ \u2717 Commit failed: ${error}`));
1923
2906
  }
1924
2907
  }
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();
2908
+
2909
+ async function checkClaudeCode() {
2910
+ const hasCommand = await commandExists("claude");
2911
+ if (hasCommand) {
2912
+ return { name: "Claude Code", status: "ok", message: "Installed" };
1931
2913
  }
2914
+ return {
2915
+ name: "Claude Code",
2916
+ status: "error",
2917
+ message: "Not installed",
2918
+ fix: "Run: npm install -g @anthropic-ai/claude-code"
2919
+ };
1932
2920
  }
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;
2921
+ async function checkClaudeDir() {
2922
+ if (existsSync(CLAUDE_DIR)) {
2923
+ return { name: "Config Directory", status: "ok", message: CLAUDE_DIR };
1938
2924
  }
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;
2925
+ return {
2926
+ name: "Config Directory",
2927
+ status: "error",
2928
+ message: "Does not exist",
2929
+ fix: "Run: npx ccjk init"
1960
2930
  };
1961
- const choices = createClaudeCodeChoices(config.profiles, currentProfileId);
1962
- 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;
2931
+ }
2932
+ async function checkSettings() {
2933
+ if (existsSync(SETTINGS_FILE)) {
2934
+ return { name: "settings.json", status: "ok", message: "Configured" };
2935
+ }
2936
+ return {
2937
+ name: "settings.json",
2938
+ status: "warning",
2939
+ message: "Not found",
2940
+ fix: "Run: npx ccjk init"
2941
+ };
2942
+ }
2943
+ async function checkWorkflows() {
2944
+ const commandsDir = join(CLAUDE_DIR, "commands");
2945
+ if (existsSync(commandsDir)) {
2946
+ try {
2947
+ const files = readdirSync(commandsDir, { recursive: true });
2948
+ const mdFiles = files.filter((f) => String(f).endsWith(".md"));
2949
+ return {
2950
+ name: "Workflows",
2951
+ status: "ok",
2952
+ message: `${mdFiles.length} commands installed`
2953
+ };
2954
+ } catch {
2955
+ return { name: "Workflows", status: "warning", message: "Cannot read directory" };
1972
2956
  }
1973
- await handleClaudeCodeDirectSwitch(selectedConfig);
1974
- } catch (error) {
1975
- if (error.name === "ExitPromptError") {
1976
- console.log(ansis.cyan(`
1977
- ${i18n.t("common:goodbye")}`));
1978
- return;
2957
+ }
2958
+ return {
2959
+ name: "Workflows",
2960
+ status: "warning",
2961
+ message: "Not installed",
2962
+ fix: "Run: npx ccjk update"
2963
+ };
2964
+ }
2965
+ async function checkMcp() {
2966
+ const mcpConfigPath = join(CLAUDE_DIR, "mcp.json");
2967
+ const settingsPath = SETTINGS_FILE;
2968
+ if (existsSync(settingsPath)) {
2969
+ try {
2970
+ const { readFileSync } = await import('node:fs');
2971
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
2972
+ if (settings.mcpServers && Object.keys(settings.mcpServers).length > 0) {
2973
+ const count = Object.keys(settings.mcpServers).length;
2974
+ return { name: "MCP Services", status: "ok", message: `${count} services configured` };
2975
+ }
2976
+ } catch {
1979
2977
  }
1980
- throw error;
1981
2978
  }
2979
+ if (existsSync(mcpConfigPath)) {
2980
+ return { name: "MCP Services", status: "ok", message: "Configured" };
2981
+ }
2982
+ return {
2983
+ name: "MCP Services",
2984
+ status: "warning",
2985
+ message: "Not configured",
2986
+ fix: "Run: npx ccjk init and select MCP services"
2987
+ };
1982
2988
  }
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;
2989
+ async function checkCcr() {
2990
+ const hasCcr = await commandExists("ccr");
2991
+ if (hasCcr) {
2992
+ return { name: "CCR Proxy", status: "ok", message: "Installed" };
1988
2993
  }
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;
2994
+ return {
2995
+ name: "CCR Proxy",
2996
+ status: "warning",
2997
+ message: "Not installed (optional)",
2998
+ fix: "Run: npx ccjk ccr to install"
2007
2999
  };
2008
- const choices = createApiConfigChoices(providers, currentProvider, isCommented);
2009
- 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);
2025
- }
2026
- if (!success) {
2027
- console.log(ansis.red(i18n.t("common:operationFailed")));
2028
- }
2029
- } catch (error) {
2030
- if (error.name === "ExitPromptError") {
2031
- console.log(ansis.cyan(`
2032
- ${i18n.t("common:goodbye")}`));
2033
- return;
3000
+ }
3001
+ async function checkOutputStyles() {
3002
+ const stylesDir = join(CLAUDE_DIR, "output-styles");
3003
+ if (existsSync(stylesDir)) {
3004
+ try {
3005
+ const files = readdirSync(stylesDir).filter((f) => f.endsWith(".md"));
3006
+ return {
3007
+ name: "Output Styles",
3008
+ status: "ok",
3009
+ message: `${files.length} styles available`
3010
+ };
3011
+ } catch {
3012
+ return { name: "Output Styles", status: "warning", message: "Cannot read directory" };
2034
3013
  }
2035
- throw error;
2036
3014
  }
3015
+ return {
3016
+ name: "Output Styles",
3017
+ status: "warning",
3018
+ message: "Not installed",
3019
+ fix: "Run: npx ccjk init"
3020
+ };
3021
+ }
3022
+ async function doctor() {
3023
+ console.log("");
3024
+ console.log(ansis.bold.cyan("\u{1F50D} CCJK Health Check"));
3025
+ console.log(ansis.dim("\u2500".repeat(50)));
3026
+ console.log("");
3027
+ const checks = [
3028
+ checkClaudeCode,
3029
+ checkClaudeDir,
3030
+ checkSettings,
3031
+ checkWorkflows,
3032
+ checkMcp,
3033
+ checkCcr,
3034
+ checkOutputStyles
3035
+ ];
3036
+ let hasErrors = false;
3037
+ let hasWarnings = false;
3038
+ for (const check of checks) {
3039
+ const result = await check();
3040
+ const statusIcon = result.status === "ok" ? ansis.green("\u2705") : result.status === "warning" ? ansis.yellow("\u26A0\uFE0F") : ansis.red("\u274C");
3041
+ const statusColor = result.status === "ok" ? ansis.green : result.status === "warning" ? ansis.yellow : ansis.red;
3042
+ console.log(`${statusIcon} ${ansis.bold(result.name)}: ${statusColor(result.message)}`);
3043
+ if (result.fix) {
3044
+ console.log(ansis.dim(` \u{1F4A1} Fix: ${result.fix}`));
3045
+ }
3046
+ if (result.status === "error")
3047
+ hasErrors = true;
3048
+ if (result.status === "warning")
3049
+ hasWarnings = true;
3050
+ }
3051
+ console.log("");
3052
+ console.log(ansis.dim("\u2500".repeat(50)));
3053
+ if (hasErrors) {
3054
+ console.log(ansis.red("\u274C Issues found - please follow the suggestions above"));
3055
+ } else if (hasWarnings) {
3056
+ console.log(ansis.yellow("\u26A0\uFE0F Configuration is functional, but some features may be limited"));
3057
+ } else {
3058
+ console.log(ansis.green("\u2705 All checks passed - CCJK is properly configured!"));
3059
+ }
3060
+ console.log("");
2037
3061
  }
2038
3062
 
2039
- const configSwitch = {
2040
- __proto__: null,
2041
- configSwitchCommand: configSwitchCommand
2042
- };
3063
+ async function showFeatures() {
3064
+ console.log("");
3065
+ console.log(ansis.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
3066
+ console.log(ansis.bold.cyan("\u2551") + ansis.bold.white(" \u{1F4E6} CCJK \u529F\u80FD\u4E00\u89C8 ") + ansis.bold.cyan("\u2551"));
3067
+ console.log(ansis.bold.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
3068
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
3069
+ console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u{1F527} CLI \u547D\u4EE4 ") + ansis.bold.cyan("\u2551"));
3070
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk init")} \u521D\u59CB\u5316\u73AF\u5883\u914D\u7F6E ${ansis.bold.cyan("\u2551")}`);
3071
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk update")} \u66F4\u65B0\u5DE5\u4F5C\u6D41\u548C\u6A21\u677F ${ansis.bold.cyan("\u2551")}`);
3072
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk cs")} \u5207\u6362 API \u914D\u7F6E ${ansis.bold.cyan("\u2551")}`);
3073
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk doctor")} \u8BCA\u65AD\u914D\u7F6E\u95EE\u9898 ${ansis.bold.cyan("\u2551")}`);
3074
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.cyan("ccjk ccr")} CCR \u4EE3\u7406\u7BA1\u7406 ${ansis.bold.cyan("\u2551")}`);
3075
+ console.log(`${ansis.bold.cyan("\u2551")} \u2514\u2500 ${ansis.cyan("ccjk ccu")} \u4F7F\u7528\u91CF\u7EDF\u8BA1 ${ansis.bold.cyan("\u2551")}`);
3076
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
3077
+ console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u{1F4CB} \u5DE5\u4F5C\u6D41\uFF08\u5728 Claude Code \u4E2D\u4F7F\u7528\uFF09 ") + ansis.bold.cyan("\u2551"));
3078
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/ccjk:workflow")} \u516D\u9636\u6BB5\u5F00\u53D1\u6D41\u7A0B ${ansis.bgGreen.black(" \u63A8\u8350 ")} ${ansis.bold.cyan("\u2551")}`);
3079
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/ccjk:feat")} \u529F\u80FD\u89C4\u5212\u6D41\u7A0B ${ansis.bold.cyan("\u2551")}`);
3080
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/git-commit")} \u667A\u80FD\u63D0\u4EA4 ${ansis.bgYellow.black(" \u70ED\u95E8 ")} ${ansis.bold.cyan("\u2551")}`);
3081
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.green("/git-rollback")} \u56DE\u6EDA\u66F4\u6539 ${ansis.bold.cyan("\u2551")}`);
3082
+ console.log(`${ansis.bold.cyan("\u2551")} \u2514\u2500 ${ansis.green("/git-cleanup")} \u6E05\u7406\u5206\u652F ${ansis.bold.cyan("\u2551")}`);
3083
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
3084
+ console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u{1F3A8} \u8F93\u51FA\u98CE\u683C ") + ansis.bold.cyan("\u2551"));
3085
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.magenta("senior-architect")} \u8D44\u6DF1\u67B6\u6784\u5E08\u98CE\u683C ${ansis.bold.cyan("\u2551")}`);
3086
+ console.log(`${ansis.bold.cyan("\u2551")} \u251C\u2500 ${ansis.magenta("pair-programmer")} \u7ED3\u5BF9\u7F16\u7A0B\u98CE\u683C ${ansis.bold.cyan("\u2551")}`);
3087
+ console.log(`${ansis.bold.cyan("\u2551")} \u2514\u2500 ${ansis.magenta("speed-coder")} \u5FEB\u901F\u7F16\u7801\u98CE\u683C ${ansis.bold.cyan("\u2551")}`);
3088
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
3089
+ console.log(ansis.bold.cyan("\u2551") + ansis.bold.yellow(" \u26A1 \u5FEB\u6377\u64CD\u4F5C\uFF08\u5728 Claude Code \u4E2D\u8F93\u5165\u6570\u5B57\uFF09 ") + ansis.bold.cyan("\u2551"));
3090
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.dim("1=\u667A\u80FD\u63D0\u4EA4 2=\u4EE3\u7801\u5BA1\u67E5 3=\u7F16\u5199\u6D4B\u8BD5 4=\u89C4\u5212\u529F\u80FD")} ${ansis.bold.cyan("\u2551")}`);
3091
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.dim("5=\u8C03\u8BD5\u95EE\u9898 6=\u5934\u8111\u98CE\u66B4 7=\u9A8C\u8BC1\u4EE3\u7801 8=\u5199\u6587\u6863")} ${ansis.bold.cyan("\u2551")}`);
3092
+ console.log(`${ansis.bold.cyan("\u2551")} ${ansis.bold.cyan("\u2551")}`);
3093
+ console.log(ansis.bold.cyan("\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"));
3094
+ console.log(ansis.bold.cyan("\u2551") + ansis.dim(" \u{1F4A1} \u63D0\u793A\uFF1A\u8F93\u5165 ccjk <\u547D\u4EE4> --help \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5 ") + ansis.bold.cyan("\u2551"));
3095
+ console.log(ansis.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
3096
+ console.log("");
3097
+ }
2043
3098
 
2044
3099
  const projectFoundationQuestions = [
2045
3100
  {
@@ -4942,6 +5997,217 @@ async function listInterviewSessions() {
4942
5997
  console.log("");
4943
5998
  }
4944
5999
 
6000
+ async function searchCommand(query, _options) {
6001
+ try {
6002
+ console.log(ansis.cyan(i18n.t("marketplace:searching", { query })));
6003
+ const results = await searchPackages({ query });
6004
+ if (results.packages.length === 0) {
6005
+ console.log(ansis.yellow(i18n.t("marketplace:noResults")));
6006
+ return;
6007
+ }
6008
+ console.log(ansis.green(i18n.t("marketplace:searchResults", { count: results.packages.length })));
6009
+ console.log();
6010
+ for (const pkg of results.packages) {
6011
+ const installed = await isPackageInstalled(pkg.name);
6012
+ const installedMark = installed ? ansis.green("\u2713") : ansis.gray("\u25CB");
6013
+ console.log(`${installedMark} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
6014
+ console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
6015
+ console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
6016
+ if (pkg.verified === "verified") {
6017
+ console.log(` ${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
6018
+ }
6019
+ console.log();
6020
+ }
6021
+ } catch (err) {
6022
+ console.error(ansis.red(i18n.t("marketplace:searchFailed")));
6023
+ console.error(err);
6024
+ throw err;
6025
+ }
6026
+ }
6027
+ async function installCommand(packageName, options) {
6028
+ try {
6029
+ if (await isPackageInstalled(packageName)) {
6030
+ console.log(ansis.yellow(`Package '${packageName}' is already installed`));
6031
+ return;
6032
+ }
6033
+ const pkg = await getPackage(packageName);
6034
+ if (!pkg) {
6035
+ console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
6036
+ throw new Error(`Package not found: ${packageName}`);
6037
+ }
6038
+ console.log(ansis.cyan(i18n.t("marketplace:installing", { name: packageName })));
6039
+ const result = await installPackage(packageName, {
6040
+ force: options.force,
6041
+ skipVerification: options.skipVerification
6042
+ });
6043
+ if (result.success) {
6044
+ console.log(ansis.green(i18n.t("marketplace:installSuccess", { name: packageName })));
6045
+ if (result.installedPath) {
6046
+ console.log(ansis.gray(`${i18n.t("marketplace:installedAt")}: ${result.installedPath}`));
6047
+ }
6048
+ } else {
6049
+ console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
6050
+ if (result.error) {
6051
+ console.error(ansis.red(i18n.t("marketplace:errors.installError", { error: result.error })));
6052
+ }
6053
+ throw new Error(`Install failed: ${packageName}`);
6054
+ }
6055
+ } catch (err) {
6056
+ console.error(ansis.red(i18n.t("marketplace:installFailed", { name: packageName })));
6057
+ console.error(err);
6058
+ throw err;
6059
+ }
6060
+ }
6061
+ async function uninstallCommand(packageName, options) {
6062
+ try {
6063
+ if (!await isPackageInstalled(packageName)) {
6064
+ console.error(ansis.red(i18n.t("marketplace:packageNotInstalled", { name: packageName })));
6065
+ throw new Error(`Package not installed: ${packageName}`);
6066
+ }
6067
+ console.log(ansis.cyan(i18n.t("marketplace:uninstalling", { name: packageName })));
6068
+ const result = await uninstallPackage(packageName, {
6069
+ force: options.force
6070
+ });
6071
+ if (result.success) {
6072
+ console.log(ansis.green(i18n.t("marketplace:uninstallSuccess", { name: packageName })));
6073
+ } else {
6074
+ console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
6075
+ if (result.error) {
6076
+ console.error(ansis.red(i18n.t("marketplace:errors.uninstallError", { error: result.error })));
6077
+ }
6078
+ throw new Error(`Uninstall failed: ${packageName}`);
6079
+ }
6080
+ } catch (err) {
6081
+ console.error(ansis.red(i18n.t("marketplace:uninstallFailed", { name: packageName })));
6082
+ console.error(err);
6083
+ throw err;
6084
+ }
6085
+ }
6086
+ async function updateCommand(packageName, _options) {
6087
+ try {
6088
+ if (packageName) {
6089
+ console.log(ansis.cyan(i18n.t("marketplace:updating", { name: packageName })));
6090
+ const result = await updatePackage(packageName);
6091
+ if (result.success) {
6092
+ console.log(ansis.green(i18n.t("marketplace:updateSuccess", { name: packageName })));
6093
+ } else {
6094
+ console.error(ansis.red(i18n.t("marketplace:updateFailed", { name: packageName })));
6095
+ if (result.error) {
6096
+ console.error(ansis.red(result.error));
6097
+ }
6098
+ throw new Error(`Update failed: ${packageName}`);
6099
+ }
6100
+ } else {
6101
+ console.log(ansis.cyan(i18n.t("marketplace:checkingUpdates")));
6102
+ const updates = await checkForUpdates();
6103
+ if (updates.length === 0) {
6104
+ console.log(ansis.green(i18n.t("marketplace:noUpdates")));
6105
+ return;
6106
+ }
6107
+ console.log(ansis.yellow(i18n.t("marketplace:updatesAvailable", { count: updates.length })));
6108
+ console.log();
6109
+ for (const update of updates) {
6110
+ console.log(` ${ansis.bold(update.id)}: ${ansis.gray(update.currentVersion)} \u2192 ${ansis.green(update.latestVersion)}`);
6111
+ }
6112
+ console.log();
6113
+ console.log(ansis.gray(i18n.t("marketplace:updateHint")));
6114
+ }
6115
+ } catch (err) {
6116
+ console.error(ansis.red(i18n.t("marketplace:updateCheckFailed")));
6117
+ console.error(err);
6118
+ throw err;
6119
+ }
6120
+ }
6121
+ async function listCommand(_options) {
6122
+ try {
6123
+ const installedList = await getInstalledPackages();
6124
+ if (installedList.length === 0) {
6125
+ console.log(ansis.yellow(i18n.t("marketplace:noInstalled")));
6126
+ return;
6127
+ }
6128
+ console.log(ansis.green(i18n.t("marketplace:installedPackages", { count: installedList.length })));
6129
+ console.log();
6130
+ for (const installed of installedList) {
6131
+ const pkg = installed.package;
6132
+ console.log(`${ansis.green("\u2713")} ${ansis.bold(pkg.name)} ${ansis.gray(`v${pkg.version}`)}`);
6133
+ console.log(` ${pkg.description.en || Object.values(pkg.description)[0]}`);
6134
+ console.log(` ${ansis.gray(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
6135
+ console.log();
6136
+ }
6137
+ } catch (err) {
6138
+ console.error(ansis.red(i18n.t("marketplace:listFailed")));
6139
+ console.error(err);
6140
+ throw err;
6141
+ }
6142
+ }
6143
+ async function infoCommand(packageName, _options) {
6144
+ try {
6145
+ const pkg = await getPackage(packageName);
6146
+ if (!pkg) {
6147
+ console.error(ansis.red(i18n.t("marketplace:packageNotFound", { name: packageName })));
6148
+ throw new Error(`Package not found: ${packageName}`);
6149
+ }
6150
+ const installed = await isPackageInstalled(packageName);
6151
+ console.log();
6152
+ console.log(ansis.bold.cyan(pkg.name));
6153
+ console.log(ansis.gray("\u2500".repeat(50)));
6154
+ console.log();
6155
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.description"))}: ${pkg.description.en || Object.values(pkg.description)[0]}`);
6156
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.version"))}: ${pkg.version}`);
6157
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.category"))}: ${pkg.category}`);
6158
+ if (pkg.author) {
6159
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.author"))}: ${pkg.author}`);
6160
+ }
6161
+ if (pkg.license) {
6162
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.license"))}: ${pkg.license}`);
6163
+ }
6164
+ if (pkg.repository) {
6165
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.repository"))}: ${pkg.repository}`);
6166
+ }
6167
+ if (pkg.downloads !== void 0) {
6168
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.downloads"))}: ${pkg.downloads.toLocaleString()}`);
6169
+ }
6170
+ if (pkg.rating !== void 0) {
6171
+ const stars = "\u2605".repeat(Math.round(pkg.rating));
6172
+ const emptyStars = "\u2606".repeat(5 - Math.round(pkg.rating));
6173
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.rating"))}: ${ansis.yellow(stars)}${ansis.gray(emptyStars)} (${pkg.rating}/5)`);
6174
+ }
6175
+ if (pkg.keywords && pkg.keywords.length > 0) {
6176
+ console.log(`${ansis.bold(i18n.t("marketplace:packageInfo.keywords"))}: ${pkg.keywords.join(", ")}`);
6177
+ }
6178
+ if (pkg.verified === "verified") {
6179
+ console.log(`${ansis.blue("\u2713")} ${i18n.t("marketplace:packageInfo.verified")}`);
6180
+ }
6181
+ console.log();
6182
+ console.log(`${ansis.bold("Status")}: ${installed ? ansis.green("Installed") : ansis.gray("Not installed")}`);
6183
+ console.log();
6184
+ } catch (err) {
6185
+ console.error(ansis.red(i18n.t("marketplace:infoFailed")));
6186
+ console.error(err);
6187
+ throw err;
6188
+ }
6189
+ }
6190
+ async function registerMarketplaceCommands(cli, withLanguageResolution) {
6191
+ 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) => {
6192
+ await searchCommand(query);
6193
+ }));
6194
+ 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) => {
6195
+ await installCommand(packageName, options);
6196
+ }));
6197
+ 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) => {
6198
+ await uninstallCommand(packageName, options);
6199
+ }));
6200
+ 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) => {
6201
+ await updateCommand(packageName);
6202
+ }));
6203
+ 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) => {
6204
+ await listCommand();
6205
+ }));
6206
+ 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) => {
6207
+ await infoCommand(packageName);
6208
+ }));
6209
+ }
6210
+
4945
6211
  const MCP_SERVERS = [
4946
6212
  { name: "Filesystem", description: "Secure file operations", package: "@modelcontextprotocol/server-filesystem", category: "core" },
4947
6213
  { name: "GitHub", description: "Repository management", package: "@modelcontextprotocol/server-github", category: "dev" },
@@ -5695,6 +6961,93 @@ async function toolsCommand(action = "list", target, options = {}) {
5695
6961
  }
5696
6962
  }
5697
6963
 
6964
+ const WORKFLOW_METADATA = {
6965
+ "workflow": { description: "\u516D\u9636\u6BB5\u5F00\u53D1\u6D41\u7A0B", tags: ["\u63A8\u8350", "\u6838\u5FC3"] },
6966
+ "feat": { description: "\u529F\u80FD\u89C4\u5212\u6D41\u7A0B", tags: ["\u63A8\u8350"] },
6967
+ "git-commit": { description: "\u667A\u80FD Git \u63D0\u4EA4", tags: ["\u70ED\u95E8", "Git"] },
6968
+ "git-rollback": { description: "\u56DE\u6EDA\u66F4\u6539", tags: ["Git"] },
6969
+ "git-cleanup": { description: "\u6E05\u7406\u5206\u652F", tags: ["Git"] },
6970
+ "git-worktree": { description: "\u5DE5\u4F5C\u6811\u7BA1\u7406", tags: ["Git"] },
6971
+ "bmad": { description: "BMad \u654F\u6377\u6D41\u7A0B", tags: ["\u654F\u6377"] },
6972
+ "spec": { description: "\u89C4\u683C\u9A71\u52A8\u5F00\u53D1", tags: ["\u89C4\u5212"] }
6973
+ };
6974
+ function getInstalledWorkflows() {
6975
+ const commandsDir = join(CLAUDE_DIR, "commands");
6976
+ const workflows = [];
6977
+ if (!existsSync(commandsDir)) {
6978
+ return workflows;
6979
+ }
6980
+ function scanDir(dir, prefix = "") {
6981
+ try {
6982
+ const items = readdirSync(dir, { withFileTypes: true });
6983
+ for (const item of items) {
6984
+ if (item.isDirectory()) {
6985
+ scanDir(join(dir, item.name), `${prefix}${item.name}/`);
6986
+ } else if (item.name.endsWith(".md")) {
6987
+ const name = item.name.replace(".md", "");
6988
+ const fullName = prefix ? `${prefix.replace(/\/$/, "")}:${name}` : name;
6989
+ const meta = WORKFLOW_METADATA[name] || {};
6990
+ workflows.push({
6991
+ name: `/${fullName}`,
6992
+ path: join(dir, item.name),
6993
+ description: meta.description,
6994
+ installed: true,
6995
+ tags: meta.tags
6996
+ });
6997
+ }
6998
+ }
6999
+ } catch {
7000
+ }
7001
+ }
7002
+ scanDir(commandsDir);
7003
+ return workflows;
7004
+ }
7005
+ function formatTags(tags) {
7006
+ if (!tags || tags.length === 0)
7007
+ return "";
7008
+ return tags.map((tag) => {
7009
+ switch (tag) {
7010
+ case "\u63A8\u8350":
7011
+ return ansis.bgGreen.black(` ${tag} `);
7012
+ case "\u70ED\u95E8":
7013
+ return ansis.bgYellow.black(` ${tag} `);
7014
+ case "\u6838\u5FC3":
7015
+ return ansis.bgBlue.white(` ${tag} `);
7016
+ case "Git":
7017
+ return ansis.bgMagenta.white(` ${tag} `);
7018
+ default:
7019
+ return ansis.bgGray.white(` ${tag} `);
7020
+ }
7021
+ }).join(" ");
7022
+ }
7023
+ async function showWorkflows() {
7024
+ console.log("");
7025
+ console.log(ansis.bold.cyan("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
7026
+ console.log(ansis.bold.cyan("\u2502") + ansis.bold.white(" \u{1F4CB} CCJK \u5DE5\u4F5C\u6D41\u7BA1\u7406 ") + ansis.bold.cyan("\u2502"));
7027
+ console.log(ansis.bold.cyan("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
7028
+ const workflows = getInstalledWorkflows();
7029
+ if (workflows.length === 0) {
7030
+ console.log(ansis.bold.cyan("\u2502") + ansis.yellow(" \u26A0\uFE0F \u672A\u5B89\u88C5\u4EFB\u4F55\u5DE5\u4F5C\u6D41 ") + ansis.bold.cyan("\u2502"));
7031
+ console.log(ansis.bold.cyan("\u2502") + ansis.dim(" \u8FD0\u884C npx ccjk init \u6216 npx ccjk update \u5B89\u88C5\u5DE5\u4F5C\u6D41 ") + ansis.bold.cyan("\u2502"));
7032
+ } else {
7033
+ console.log(ansis.bold.cyan("\u2502") + ansis.bold.green(` \u2705 \u5DF2\u5B89\u88C5\u5DE5\u4F5C\u6D41 (${workflows.length})`) + " ".repeat(42 - String(workflows.length).length) + ansis.bold.cyan("\u2502"));
7034
+ console.log(`${ansis.bold.cyan("\u2502")} ${ansis.bold.cyan("\u2502")}`);
7035
+ for (const wf of workflows) {
7036
+ const tags = formatTags(wf.tags);
7037
+ const desc = wf.description || "";
7038
+ const nameCol = ansis.green(wf.name.padEnd(20));
7039
+ const descCol = ansis.dim(desc.padEnd(25));
7040
+ console.log(ansis.bold.cyan("\u2502") + ` ${nameCol} ${descCol} ${tags}`.padEnd(60) + ansis.bold.cyan("\u2502"));
7041
+ }
7042
+ }
7043
+ console.log(`${ansis.bold.cyan("\u2502")} ${ansis.bold.cyan("\u2502")}`);
7044
+ console.log(ansis.bold.cyan("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"));
7045
+ console.log(ansis.bold.cyan("\u2502") + ansis.dim(" \u{1F4A1} \u5728 Claude Code \u4E2D\u8F93\u5165\u5DE5\u4F5C\u6D41\u540D\u79F0\u5373\u53EF\u4F7F\u7528 ") + ansis.bold.cyan("\u2502"));
7046
+ console.log(ansis.bold.cyan("\u2502") + ansis.dim(" \u4F8B\u5982: /ccjk:workflow \u5B9E\u73B0\u7528\u6237\u767B\u5F55\u529F\u80FD ") + ansis.bold.cyan("\u2502"));
7047
+ console.log(ansis.bold.cyan("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
7048
+ console.log("");
7049
+ }
7050
+
5698
7051
  async function resolveAndSwitchLanguage(lang, options, skipPrompt = false) {
5699
7052
  const ccjkConfig = await readZcfConfigAsync();
5700
7053
  const targetLang = options?.allLang || lang || options?.lang || ccjkConfig?.preferredLang || (skipPrompt ? "en" : await selectScriptLanguage());
@@ -5742,6 +7095,8 @@ function customizeHelp(sections) {
5742
7095
  ` ${ansis.cyan("ccjk quick")} Express interview (~10 questions)`,
5743
7096
  ` ${ansis.cyan("ccjk deep")} Deep dive interview (~40+ questions)`,
5744
7097
  ` ${ansis.cyan("ccjk mcp")} <action> MCP Server marketplace (search, trending, install)`,
7098
+ ` ${ansis.cyan("ccjk workflows")} | ${ansis.cyan("wf")} Manage installed workflows`,
7099
+ ` ${ansis.cyan("ccjk doctor")} Health check and diagnostics`,
5745
7100
  ` ${ansis.cyan("ccjk uninstall")} ${i18n.t("cli:help.commandDescriptions.uninstallConfigurations")}`,
5746
7101
  ` ${ansis.cyan("ccjk check-updates")} ${i18n.t("cli:help.commandDescriptions.checkUpdateVersions")}`,
5747
7102
  "",
@@ -5876,8 +7231,8 @@ async function setupCommands(cli) {
5876
7231
  cli.command("sync", "Quick sync - update knowledge base from current project").action(async () => {
5877
7232
  await quickSync();
5878
7233
  });
5879
- cli.command("doctor", "Run environment health check").option("--fix", "Attempt to fix issues automatically").action(async (options) => {
5880
- await runDoctor(options.fix);
7234
+ cli.command("doctor", "Run environment health check").action(async () => {
7235
+ await doctor();
5881
7236
  });
5882
7237
  cli.command("versions", "Check Claude Code, CCJK, and plugin versions").alias("ver").action(async () => {
5883
7238
  await checkAllVersions();
@@ -5945,6 +7300,7 @@ async function setupCommands(cli) {
5945
7300
  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
7301
  await mcpMarket(action, args, options);
5947
7302
  }));
7303
+ await registerMarketplaceCommands(cli, withLanguageResolution);
5948
7304
  cli.command("session <action> [id]", "Manage sessions (save, list, restore, export)").action(async (action, id) => {
5949
7305
  if (action === "save") {
5950
7306
  await saveSession();
@@ -5958,6 +7314,12 @@ async function setupCommands(cli) {
5958
7314
  console.error(`Unknown action: ${action}. Use: save, list, restore, or export`);
5959
7315
  }
5960
7316
  });
7317
+ cli.command("features", "Show all available features").action(async () => {
7318
+ await showFeatures();
7319
+ });
7320
+ cli.command("workflows", "Manage installed workflows").alias("wf").option("--lang, -l <lang>", "Display language (zh-CN, en)").action(await withLanguageResolution(async () => {
7321
+ await showWorkflows();
7322
+ }));
5961
7323
  cli.help((sections) => customizeHelp(sections));
5962
7324
  cli.version(version);
5963
7325
  }