ccjk 9.6.1 → 9.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/chunks/boost.mjs +246 -7
  2. package/dist/chunks/ccjk-mcp.mjs +1 -1
  3. package/dist/chunks/ccr.mjs +25 -28
  4. package/dist/chunks/check-updates.mjs +4 -3
  5. package/dist/chunks/claude-code-config-manager.mjs +1 -1
  6. package/dist/chunks/claude-code-incremental-manager.mjs +1 -1
  7. package/dist/chunks/claude-config.mjs +1 -1
  8. package/dist/chunks/codex-config-switch.mjs +3 -4
  9. package/dist/chunks/codex-provider-manager.mjs +1 -2
  10. package/dist/chunks/codex.mjs +204 -3
  11. package/dist/chunks/config-switch.mjs +2 -3
  12. package/dist/chunks/config.mjs +1 -1
  13. package/dist/chunks/doctor.mjs +1 -1
  14. package/dist/chunks/features.mjs +24 -15
  15. package/dist/chunks/hook-installer.mjs +44 -0
  16. package/dist/chunks/index3.mjs +32 -32
  17. package/dist/chunks/init.mjs +129 -87
  18. package/dist/chunks/installer2.mjs +1 -1
  19. package/dist/chunks/interview.mjs +1 -1
  20. package/dist/chunks/mcp.mjs +1058 -17
  21. package/dist/chunks/menu.mjs +140 -56
  22. package/dist/chunks/package.mjs +2 -210
  23. package/dist/chunks/platform.mjs +1 -1
  24. package/dist/chunks/quick-setup.mjs +35 -18
  25. package/dist/chunks/simple-config.mjs +1 -1
  26. package/dist/{shared/ccjk.q1koQxEE.mjs → chunks/smart-defaults.mjs} +77 -79
  27. package/dist/chunks/status.mjs +208 -101
  28. package/dist/chunks/thinking.mjs +1 -1
  29. package/dist/chunks/uninstall.mjs +6 -4
  30. package/dist/chunks/update.mjs +4 -7
  31. package/dist/chunks/version-checker.mjs +1 -1
  32. package/dist/cli.mjs +4 -80
  33. package/dist/index.d.mts +17 -1482
  34. package/dist/index.d.ts +17 -1482
  35. package/dist/index.mjs +12 -4191
  36. package/dist/shared/{ccjk.CSkyCZIM.mjs → ccjk.Bndhan7G.mjs} +4 -242
  37. package/dist/shared/ccjk.CeE8RLG2.mjs +62 -0
  38. package/dist/shared/ccjk.DKojSRzw.mjs +266 -0
  39. package/dist/shared/{ccjk.CItD1fpl.mjs → ccjk.DvIrK0wz.mjs} +1 -1
  40. package/dist/shared/ccjk.LsPZ2PYo.mjs +1048 -0
  41. package/package.json +1 -1
  42. package/dist/chunks/api-adapter.mjs +0 -180
  43. package/dist/chunks/cli.mjs +0 -2227
  44. package/dist/chunks/context-menu.mjs +0 -913
  45. package/dist/chunks/hooks-sync.mjs +0 -1627
  46. package/dist/chunks/mcp-market.mjs +0 -1077
  47. package/dist/chunks/mcp-server.mjs +0 -776
  48. package/dist/chunks/project-detector.mjs +0 -131
  49. package/dist/chunks/provider-registry.mjs +0 -92
  50. package/dist/chunks/setup-wizard.mjs +0 -362
  51. package/dist/chunks/tools.mjs +0 -143
  52. package/dist/chunks/workflows2.mjs +0 -232
  53. package/dist/shared/ccjk.C0pb50xH.mjs +0 -347
  54. package/dist/shared/ccjk.ChMkBmdL.mjs +0 -490
  55. package/dist/shared/ccjk.CtSfXUSh.mjs +0 -209
  56. package/dist/shared/ccjk.xfAjmbJp.mjs +0 -75
@@ -2,20 +2,21 @@ import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'pathe';
5
- import { b as getPlatform } from '../chunks/platform.mjs';
6
- import { DEFAULT_CODE_TOOL_TYPE } from '../chunks/constants.mjs';
7
- import { i18n } from '../chunks/index.mjs';
8
- import { readZcfConfigAsync, saveZcfConfig } from '../chunks/ccjk-config.mjs';
5
+ import { d as getPlatform } from './platform.mjs';
6
+ import { s as scanProject } from '../shared/ccjk.DKojSRzw.mjs';
7
+ import 'node:process';
8
+ import 'tinyexec';
9
9
 
10
10
  class SmartDefaultsDetector {
11
11
  /**
12
12
  * Detect environment and generate smart defaults
13
13
  */
14
- async detect() {
14
+ async detect(cwd) {
15
15
  const platform = getPlatform();
16
16
  const apiKey = this.detectApiKey();
17
17
  const apiProvider = this.detectApiProvider(apiKey);
18
18
  const ccVersion = this.detectClaudeCodeVersion();
19
+ const projectContext = scanProject(cwd);
19
20
  return {
20
21
  // Environment detection
21
22
  platform,
@@ -23,18 +24,18 @@ class SmartDefaultsDetector {
23
24
  // API configuration
24
25
  apiKey,
25
26
  apiProvider,
26
- // Recommended MCP services based on platform
27
- mcpServices: this.getRecommendedMcpServices(platform),
28
- // Essential skills (common 5)
29
- skills: [
27
+ // Recommended MCP services based on platform + project
28
+ mcpServices: this.getRecommendedMcpServices(platform, projectContext),
29
+ // Essential skills — reduced in CI/container (non-interactive)
30
+ skills: projectContext.runtime.isCI || projectContext.runtime.isContainer ? ["ccjk:git-commit"] : [
30
31
  "ccjk:git-commit",
31
32
  "ccjk:feat",
32
33
  "ccjk:workflow",
33
34
  "ccjk:init-project",
34
35
  "ccjk:git-worktree"
35
36
  ],
36
- // Core agents (universal 2)
37
- agents: [
37
+ // Core agents — skip in CI/container (non-interactive)
38
+ agents: projectContext.runtime.isCI || projectContext.runtime.isContainer ? [] : [
38
39
  "typescript-cli-architect",
39
40
  "ccjk-testing-specialist"
40
41
  ],
@@ -43,7 +44,7 @@ class SmartDefaultsDetector {
43
44
  // Workflow preferences
44
45
  workflows: {
45
46
  outputStyle: "engineer-professional",
46
- gitWorkflow: "conventional-commits",
47
+ gitWorkflow: projectContext.usesConventionalCommits ? "conventional-commits" : "conventional-commits",
47
48
  sixStepWorkflow: true
48
49
  },
49
50
  // Tool integrations
@@ -54,7 +55,13 @@ class SmartDefaultsDetector {
54
55
  },
55
56
  // Claude Code native features
56
57
  claudeCodeVersion: ccVersion,
57
- nativeFeatures: this.detectNativeFeatures(ccVersion)
58
+ nativeFeatures: this.detectNativeFeatures(ccVersion),
59
+ // Project context
60
+ projectContext,
61
+ // Recommended hooks based on project toolchain
62
+ recommendedHooks: this.getRecommendedHooks(projectContext),
63
+ // SSH session flag for quick-setup notice
64
+ sshDetected: projectContext.runtime.isSSH || void 0
58
65
  };
59
66
  }
60
67
  /**
@@ -200,20 +207,67 @@ class SmartDefaultsDetector {
200
207
  return ccusagePaths.some((path) => existsSync(path));
201
208
  }
202
209
  /**
203
- * Get recommended MCP services based on environment
210
+ * Get recommended MCP services based on environment + project context
204
211
  */
205
- getRecommendedMcpServices(platform) {
212
+ getRecommendedMcpServices(platform, project) {
213
+ const runtime = project?.runtime;
214
+ if (runtime?.isCI) {
215
+ return ["context7", "mcp-deepwiki"];
216
+ }
217
+ if (runtime?.isContainer) {
218
+ return ["context7", "mcp-deepwiki"];
219
+ }
206
220
  const core = ["context7", "mcp-deepwiki", "open-websearch"];
207
- if (platform === "darwin") {
208
- return [...core, "Playwright", "sqlite"];
221
+ const extras = [];
222
+ const hasBrowser = runtime?.hasBrowser ?? (platform === "darwin" || platform === "win32");
223
+ if (hasBrowser) {
224
+ extras.push("Playwright");
225
+ }
226
+ extras.push("sqlite");
227
+ if (project && ["typescript", "java", "csharp"].includes(project.language)) {
228
+ if (!runtime?.isHeadless) {
229
+ extras.push("serena");
230
+ }
209
231
  }
210
- if (platform === "linux") {
211
- return [...core, "sqlite"];
232
+ return [...core, ...extras];
233
+ }
234
+ /**
235
+ * Get recommended hook template IDs based on project toolchain
236
+ */
237
+ getRecommendedHooks(project) {
238
+ const runtime = project.runtime;
239
+ if (runtime.isCI) {
240
+ const hooks2 = [];
241
+ if (project.linter !== "none") hooks2.push("pre-commit-lint-check");
242
+ if (project.testRunner !== "none") hooks2.push("test-before-commit");
243
+ return hooks2;
212
244
  }
213
- if (platform === "win32") {
214
- return [...core, "Playwright", "sqlite"];
245
+ if (runtime.isContainer) {
246
+ const hooks2 = [];
247
+ if (project.linter !== "none") hooks2.push("pre-commit-lint-check");
248
+ if (project.testRunner !== "none") hooks2.push("test-before-commit");
249
+ return hooks2;
215
250
  }
216
- return core;
251
+ const hooks = [];
252
+ if (!runtime.isHeadless) {
253
+ hooks.push("block-dev-server");
254
+ }
255
+ hooks.push("git-push-confirm");
256
+ const jsLangs = ["typescript", "javascript"];
257
+ if (jsLangs.includes(project.language)) {
258
+ hooks.push("warn-console-log");
259
+ }
260
+ hooks.push("block-unwanted-docs");
261
+ if (project.testRunner !== "none") {
262
+ hooks.push("test-before-commit");
263
+ }
264
+ if (project.formatter !== "none") {
265
+ hooks.push("auto-format-on-save");
266
+ }
267
+ if (project.linter !== "none") {
268
+ hooks.push("pre-commit-lint-check");
269
+ }
270
+ return hooks;
217
271
  }
218
272
  /**
219
273
  * Get recommended skills based on user type
@@ -273,60 +327,4 @@ function detectCodeToolType() {
273
327
  return SmartDefaultsDetector.detectCodeToolType();
274
328
  }
275
329
 
276
- const CODE_TYPE_ABBREVIATIONS = {
277
- cc: "claude-code",
278
- cx: "codex"
279
- };
280
- async function resolveCodeType(codeTypeParam) {
281
- if (codeTypeParam) {
282
- const normalizedParam = codeTypeParam.toLowerCase().trim();
283
- if (normalizedParam in CODE_TYPE_ABBREVIATIONS) {
284
- return CODE_TYPE_ABBREVIATIONS[normalizedParam];
285
- }
286
- if (isValidCodeType(normalizedParam)) {
287
- return normalizedParam;
288
- }
289
- const validAbbreviations = Object.keys(CODE_TYPE_ABBREVIATIONS);
290
- const validFullTypes = Object.values(CODE_TYPE_ABBREVIATIONS);
291
- const validOptions = [...validAbbreviations, ...validFullTypes].join(", ");
292
- let defaultValue = DEFAULT_CODE_TOOL_TYPE;
293
- try {
294
- const config = await readZcfConfigAsync();
295
- if (config?.codeToolType && isValidCodeType(config.codeToolType)) {
296
- defaultValue = config.codeToolType;
297
- }
298
- } catch {
299
- }
300
- throw new Error(
301
- i18n.t("errors:invalidCodeType", { value: codeTypeParam, validOptions, defaultValue })
302
- );
303
- }
304
- try {
305
- const freshDetected = detectCodeToolType();
306
- if (isValidCodeType(freshDetected)) {
307
- try {
308
- const config = await readZcfConfigAsync();
309
- if (config && config.codeToolType !== freshDetected) {
310
- config.codeToolType = freshDetected;
311
- await saveZcfConfig(config);
312
- }
313
- } catch {
314
- }
315
- return freshDetected;
316
- }
317
- } catch {
318
- }
319
- try {
320
- const config = await readZcfConfigAsync();
321
- if (config?.codeToolType && isValidCodeType(config.codeToolType)) {
322
- return config.codeToolType;
323
- }
324
- } catch {
325
- }
326
- return DEFAULT_CODE_TOOL_TYPE;
327
- }
328
- function isValidCodeType(value) {
329
- return ["claude-code", "codex"].includes(value);
330
- }
331
-
332
- export { detectSmartDefaults as d, resolveCodeType as r };
330
+ export { SmartDefaultsDetector, detectCodeToolType, detectSmartDefaults };
@@ -1,10 +1,12 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import process__default from 'node:process';
1
4
  import ansis from 'ansis';
2
- import { r as runHealthCheck, a as analyzeProject, g as getRecommendations } from '../shared/ccjk.CSkyCZIM.mjs';
3
- import 'node:fs';
4
- import 'node:process';
5
- import 'pathe';
5
+ import { join } from 'pathe';
6
+ import { s as scanProject } from '../shared/ccjk.DKojSRzw.mjs';
7
+ import { r as runHealthCheck } from '../shared/ccjk.Bndhan7G.mjs';
8
+ import 'node:child_process';
6
9
  import './constants.mjs';
7
- import 'node:os';
8
10
  import './index.mjs';
9
11
  import 'node:url';
10
12
  import 'i18next';
@@ -23,132 +25,237 @@ const STATUS_ICONS = {
23
25
  warn: ansis.yellow("\u26A0"),
24
26
  fail: ansis.red("\u2717")
25
27
  };
26
- function stripAnsi(s) {
27
- return s.replace(/\x1B\[[0-9;]*m/g, "");
28
+ const INSTALLED = ansis.green("\u2713");
29
+ const MISSING = ansis.gray("\u2212");
30
+ function label(text) {
31
+ return ansis.gray(text);
28
32
  }
29
- function renderBox(lines, width = 55) {
30
- const top = ansis.gray("\u256D" + "\u2500".repeat(width - 2) + "\u256E");
31
- const bot = ansis.gray("\u2570" + "\u2500".repeat(width - 2) + "\u256F");
32
- const pad = (s) => {
33
- const stripped = stripAnsi(s);
34
- const remaining = width - 4 - stripped.length;
35
- return ansis.gray("\u2502") + " " + s + " ".repeat(Math.max(0, remaining)) + " " + ansis.gray("\u2502");
36
- };
37
- return [top, ...lines.map(pad), bot].join("\n");
33
+ function val(text) {
34
+ return ansis.white(text);
35
+ }
36
+ function heading(text) {
37
+ return ansis.cyan.bold(text);
38
+ }
39
+ function divider() {
40
+ return ansis.gray("\u2500".repeat(44));
38
41
  }
39
42
  function renderScoreBar(score) {
40
43
  const filled = Math.round(score / 5);
41
44
  const empty = 20 - filled;
42
45
  let bar = "";
43
- if (score >= 80) bar = ansis.green("\u2588".repeat(filled));
44
- else if (score >= 50) bar = ansis.yellow("\u2588".repeat(filled));
46
+ if (score >= 80)
47
+ bar = ansis.green("\u2588".repeat(filled));
48
+ else if (score >= 50)
49
+ bar = ansis.yellow("\u2588".repeat(filled));
45
50
  else bar = ansis.red("\u2588".repeat(filled));
46
51
  bar += ansis.gray("\u2591".repeat(empty));
47
52
  return bar;
48
53
  }
49
- function renderHeader(report, profile) {
50
- const gradeColor = GRADE_COLORS[report.grade] || ((s) => s);
54
+ function loadInstalledSettings() {
55
+ const settingsPath = join(homedir(), ".claude", "settings.json");
56
+ try {
57
+ if (!existsSync(settingsPath)) return { mcpServers: {}, hooks: {} };
58
+ const data = JSON.parse(readFileSync(settingsPath, "utf-8"));
59
+ return {
60
+ mcpServers: data.mcpServers || {},
61
+ hooks: data.hooks || {}
62
+ };
63
+ } catch {
64
+ return { mcpServers: {}, hooks: {} };
65
+ }
66
+ }
67
+ async function loadSmartDefaults() {
68
+ try {
69
+ const { detectSmartDefaults } = await import('./smart-defaults.mjs');
70
+ return await detectSmartDefaults();
71
+ } catch {
72
+ return null;
73
+ }
74
+ }
75
+ function renderProjectSection(ctx) {
51
76
  const lines = [];
52
- lines.push("");
53
- lines.push(ansis.cyan.bold("\u{1F9E0} CCJK Brain Dashboard"));
54
- lines.push("");
55
- lines.push(`${renderScoreBar(report.totalScore)} ${gradeColor(report.grade)} ${ansis.bold(`${report.totalScore}/100`)}`);
56
- lines.push("");
57
- if (profile.projectName) {
58
- const stackParts = [];
59
- if (profile.language !== "unknown") stackParts.push(profile.language);
60
- stackParts.push(...profile.frameworks.slice(0, 3));
61
- const stack = stackParts.length > 0 ? ansis.gray(` (${stackParts.join(", ")})`) : "";
62
- lines.push(ansis.gray("Project: ") + ansis.white(profile.projectName) + stack);
77
+ lines.push(heading("Project"));
78
+ const fields = [
79
+ ["Language", ctx.language],
80
+ ["Framework", ctx.framework],
81
+ ["Test Runner", ctx.testRunner],
82
+ ["Pkg Manager", ctx.packageManager],
83
+ ["Linter", ctx.linter],
84
+ ["Formatter", ctx.formatter],
85
+ ["Database", ctx.database === "none" ? "none" : ctx.database]
86
+ ];
87
+ for (const [k, v] of fields) {
88
+ const display = v === "none" || v === "unknown" ? ansis.gray(v) : val(v);
89
+ lines.push(` ${label(`${k}:`.padEnd(14))} ${display}`);
90
+ }
91
+ const flags = [];
92
+ if (ctx.isMonorepo) flags.push("monorepo");
93
+ if (ctx.hasDocker) flags.push("docker");
94
+ if (ctx.hasCI) flags.push("CI");
95
+ if (ctx.hasGitHooks) flags.push("git-hooks");
96
+ if (ctx.usesConventionalCommits) flags.push("conventional-commits");
97
+ if (flags.length > 0) {
98
+ lines.push(` ${label("Flags:".padEnd(14))} ${val(flags.join(", "))}`);
63
99
  }
64
100
  return lines;
65
101
  }
66
- function renderSetupStatus(results) {
102
+ function renderRuntimeSection(ctx) {
67
103
  const lines = [];
68
- lines.push("");
69
- lines.push(ansis.yellow.bold("Setup Status"));
70
- lines.push("");
71
- for (const r of results) {
72
- const icon = STATUS_ICONS[r.status] || "?";
73
- const name = r.name.padEnd(16);
74
- const msg = r.status === "pass" ? ansis.green(r.message) : r.status === "warn" ? ansis.yellow(r.message) : ansis.red(r.message);
75
- lines.push(`${icon} ${ansis.bold(name)} ${msg}`);
104
+ lines.push(heading("Runtime"));
105
+ const rt = ctx.runtime;
106
+ lines.push(` ${label("Platform:".padEnd(14))} ${val(process__default.platform)} ${ansis.gray(`(${process__default.arch})`)}`);
107
+ const envFlags = [];
108
+ if (rt.isContainer) envFlags.push("container");
109
+ if (rt.isHeadless) envFlags.push("headless");
110
+ if (rt.isSSH) envFlags.push("SSH");
111
+ if (rt.isCI) envFlags.push("CI");
112
+ if (rt.isWSL) envFlags.push("WSL");
113
+ if (envFlags.length > 0) {
114
+ lines.push(` ${label("Environment:".padEnd(14))} ${val(envFlags.join(", "))}`);
115
+ } else {
116
+ lines.push(` ${label("Environment:".padEnd(14))} ${ansis.gray("standard")}`);
76
117
  }
118
+ lines.push(` ${label("Browser:".padEnd(14))} ${rt.hasBrowser ? ansis.green("available") : ansis.gray("unavailable")}`);
77
119
  return lines;
78
120
  }
79
- function renderRecommendations(recs, maxShow = 4) {
80
- if (recs.length === 0) return [];
121
+ function renderMcpSection(recommended, installed) {
81
122
  const lines = [];
82
- lines.push("");
83
- lines.push(ansis.yellow.bold("Recommendations"));
84
- lines.push("");
85
- for (const rec of recs.slice(0, maxShow)) {
86
- const icon = rec.priority === "high" ? ansis.red("\u2192") : ansis.yellow("\u2192");
87
- lines.push(`${icon} ${rec.description}`);
88
- if (rec.command) {
89
- lines.push(` ${ansis.cyan(rec.command)}`);
90
- }
123
+ lines.push(heading("MCP Services"));
124
+ const installedNames = Object.keys(installed);
125
+ if (recommended.length === 0 && installedNames.length === 0) {
126
+ lines.push(` ${ansis.gray("No MCP services detected")}`);
127
+ return lines;
91
128
  }
92
- if (recs.length > maxShow) {
93
- lines.push(ansis.gray(` ... and ${recs.length - maxShow} more`));
129
+ const shown = /* @__PURE__ */ new Set();
130
+ for (const svc of recommended) {
131
+ const isInstalled = installedNames.some(
132
+ (name) => name.toLowerCase().includes(svc.toLowerCase()) || svc.toLowerCase().includes(name.toLowerCase())
133
+ );
134
+ const icon = isInstalled ? INSTALLED : MISSING;
135
+ lines.push(` ${icon} ${isInstalled ? val(svc) : ansis.gray(svc)}`);
136
+ shown.add(svc.toLowerCase());
137
+ }
138
+ for (const name of installedNames) {
139
+ if (!shown.has(name.toLowerCase()) && !recommended.some((r) => r.toLowerCase() === name.toLowerCase())) {
140
+ lines.push(` ${INSTALLED} ${val(name)} ${ansis.gray("(extra)")}`);
141
+ }
94
142
  }
95
143
  return lines;
96
144
  }
97
- function renderProjectRecs(profile) {
98
- const { skills, mcpServices } = getRecommendations(profile);
99
- if (skills.length === 0 && mcpServices.length === 0) return [];
145
+ function renderHooksSection(recommended, installed) {
100
146
  const lines = [];
101
- lines.push("");
102
- lines.push(ansis.yellow.bold("For Your Project"));
103
- lines.push("");
104
- if (skills.length > 0) {
105
- lines.push(`${ansis.cyan(String(skills.length))} skills match your stack:`);
106
- for (const s of skills.slice(0, 3)) {
107
- lines.push(` ${ansis.green("+")} ${s.name} ${ansis.gray(`- ${s.reason}`)}`);
147
+ lines.push(heading("Hooks"));
148
+ const installedEvents = Object.keys(installed);
149
+ const hasAnyHooks = installedEvents.length > 0;
150
+ if (recommended.length === 0 && !hasAnyHooks) {
151
+ lines.push(` ${ansis.gray("No hooks detected")}`);
152
+ return lines;
153
+ }
154
+ for (const hookId of recommended) {
155
+ const isInstalled = hasAnyHooks;
156
+ const icon = isInstalled ? INSTALLED : MISSING;
157
+ lines.push(` ${icon} ${isInstalled ? val(hookId) : ansis.gray(hookId)}`);
158
+ }
159
+ if (hasAnyHooks) {
160
+ const totalHookCount = installedEvents.reduce((sum, event) => {
161
+ const eventHooks = installed[event];
162
+ return sum + (Array.isArray(eventHooks) ? eventHooks.length : 0);
163
+ }, 0);
164
+ if (totalHookCount > 0) {
165
+ lines.push(` ${ansis.gray(`${totalHookCount} hook(s) across ${installedEvents.length} event(s)`)}`);
108
166
  }
109
- lines.push(` ${ansis.cyan("ccjk ccjk:skills --dry-run")}`);
110
167
  }
111
- if (mcpServices.length > 0) {
112
- lines.push(`${ansis.cyan(String(mcpServices.length))} MCP services recommended`);
113
- lines.push(` ${ansis.cyan("ccjk ccjk:mcp --dry-run")}`);
168
+ return lines;
169
+ }
170
+ function renderClaudeCodeSection(defaults) {
171
+ const lines = [];
172
+ lines.push(heading("Claude Code"));
173
+ const version = defaults?.claudeCodeVersion;
174
+ lines.push(` ${label("Version:".padEnd(14))} ${version ? val(version) : ansis.gray("not detected")}`);
175
+ if (defaults?.nativeFeatures) {
176
+ const nf = defaults.nativeFeatures;
177
+ const features = [];
178
+ if (nf.hooks) features.push("hooks");
179
+ if (nf.memory) features.push("memory");
180
+ if (nf.subagents) features.push("subagents");
181
+ if (nf.toolSearch) features.push("tool-search");
182
+ if (features.length > 0) {
183
+ lines.push(` ${label("Features:".padEnd(14))} ${val(features.join(", "))}`);
184
+ }
114
185
  }
115
186
  return lines;
116
187
  }
117
- function renderQuickActions() {
118
- return [
119
- "",
120
- ansis.yellow.bold("Quick Actions"),
121
- "",
122
- `${ansis.cyan("ccjk boost")} Auto-apply recommendations`,
123
- `${ansis.cyan("ccjk ccjk:skills")} Install project-matched skills`,
124
- `${ansis.cyan("ccjk ccjk:mcp")} Install recommended MCP services`,
125
- `${ansis.cyan("ccjk doctor")} Full environment diagnostics`
126
- ];
188
+ function renderHealthSection(report, compact) {
189
+ const lines = [];
190
+ lines.push(heading("Brain Dashboard"));
191
+ const gradeColor = GRADE_COLORS[report.grade] || ((s) => s);
192
+ const scoreBar = renderScoreBar(report.totalScore);
193
+ lines.push(` ${label("Score:".padEnd(14))} ${scoreBar} ${gradeColor(report.grade)} ${ansis.gray(`(${report.totalScore}/100)`)}`);
194
+ if (!compact) {
195
+ lines.push("");
196
+ for (const r of report.results) {
197
+ const icon = STATUS_ICONS[r.status];
198
+ const scoreText = ansis.gray(`${r.score}/${r.weight}`);
199
+ lines.push(` ${icon} ${r.name.padEnd(18)} ${scoreText.padEnd(10)} ${ansis.gray(r.message)}`);
200
+ }
201
+ }
202
+ if (report.recommendations.length > 0) {
203
+ lines.push("");
204
+ lines.push(ansis.yellow.bold(" Recommendations:"));
205
+ for (const rec of report.recommendations.slice(0, 3)) {
206
+ const priority = rec.priority === "high" ? ansis.red("!") : rec.priority === "medium" ? ansis.yellow("\u2022") : ansis.gray("\xB7");
207
+ lines.push(` ${priority} ${rec.title}`);
208
+ if (rec.command) {
209
+ lines.push(` ${ansis.gray("\u2192")} ${ansis.cyan(rec.command)}`);
210
+ }
211
+ }
212
+ }
213
+ return lines;
127
214
  }
128
- async function status(options = {}) {
129
- const [report, profile] = await Promise.all([
130
- runHealthCheck(),
131
- Promise.resolve(analyzeProject())
132
- ]);
133
- if (options.json) {
134
- console.log(JSON.stringify({
135
- score: report.totalScore,
136
- grade: report.grade,
137
- results: report.results.map((r) => ({ name: r.name, status: r.status, score: r.score, message: r.message })),
138
- recommendations: report.recommendations,
139
- project: { name: profile.projectName, language: profile.language, frameworks: profile.frameworks, tags: profile.tags }
140
- }, null, 2));
141
- return;
215
+ async function statusCommand(options = {}) {
216
+ try {
217
+ const [ctx, defaults, installed, health] = await Promise.all([
218
+ scanProject(),
219
+ loadSmartDefaults(),
220
+ Promise.resolve(loadInstalledSettings()),
221
+ runHealthCheck()
222
+ ]);
223
+ if (options.json) {
224
+ console.log(JSON.stringify({
225
+ project: ctx,
226
+ smartDefaults: defaults,
227
+ installed,
228
+ health
229
+ }, null, 2));
230
+ return;
231
+ }
232
+ const sections = [];
233
+ sections.push(renderProjectSection(ctx));
234
+ sections.push(renderRuntimeSection(ctx));
235
+ if (defaults) {
236
+ sections.push(renderMcpSection(defaults.mcpServices, installed.mcpServers));
237
+ sections.push(renderHooksSection(defaults.recommendedHooks, installed.hooks));
238
+ sections.push(renderClaudeCodeSection(defaults));
239
+ } else {
240
+ sections.push(renderMcpSection([], installed.mcpServers));
241
+ sections.push(renderHooksSection([], installed.hooks));
242
+ sections.push(renderClaudeCodeSection(null));
243
+ }
244
+ sections.push(renderHealthSection(health, options.compact || false));
245
+ console.log();
246
+ for (let i = 0; i < sections.length; i++) {
247
+ console.log(sections[i].join("\n"));
248
+ if (i < sections.length - 1) {
249
+ console.log();
250
+ console.log(divider());
251
+ console.log();
252
+ }
253
+ }
254
+ console.log();
255
+ } catch (error) {
256
+ console.error(ansis.red("Error running status command:"), error);
257
+ process__default.exit(1);
142
258
  }
143
- const allLines = [
144
- ...renderHeader(report, profile),
145
- ...renderSetupStatus(report.results),
146
- ...renderRecommendations(report.recommendations),
147
- ...renderProjectRecs(profile),
148
- ...renderQuickActions(),
149
- ""
150
- ];
151
- console.log(renderBox(allLines));
152
259
  }
153
260
 
154
- export { status };
261
+ export { statusCommand };
@@ -3,7 +3,7 @@ import inquirer from 'inquirer';
3
3
  import { SETTINGS_FILE } from './constants.mjs';
4
4
  import { i18n } from './index.mjs';
5
5
  import { readJsonConfig, writeJsonConfig } from './json-config.mjs';
6
- import { a as handleExitPromptError, h as handleGeneralError } from '../shared/ccjk.CItD1fpl.mjs';
6
+ import { h as handleExitPromptError, a as handleGeneralError } from '../shared/ccjk.DvIrK0wz.mjs';
7
7
  import 'node:os';
8
8
  import 'pathe';
9
9
  import 'node:fs';
@@ -3,8 +3,8 @@ import inquirer from 'inquirer';
3
3
  import { ZCF_CONFIG_FILE, DEFAULT_CODE_TOOL_TYPE, isCodeToolType } from './constants.mjs';
4
4
  import { i18n, ensureI18nInitialized } from './index.mjs';
5
5
  import { readZcfConfig } from './ccjk-config.mjs';
6
- import { r as resolveCodeType } from '../shared/ccjk.q1koQxEE.mjs';
7
- import { a as handleExitPromptError, h as handleGeneralError } from '../shared/ccjk.CItD1fpl.mjs';
6
+ import { r as resolveCodeType } from '../shared/ccjk.CeE8RLG2.mjs';
7
+ import { h as handleExitPromptError, a as handleGeneralError } from '../shared/ccjk.DvIrK0wz.mjs';
8
8
  import { a as addNumbersToChoices } from '../shared/ccjk.BFQ7yr5S.mjs';
9
9
  import { p as promptBoolean } from '../shared/ccjk.DHbrGcgg.mjs';
10
10
  import { promises } from 'node:fs';
@@ -21,10 +21,12 @@ import 'smol-toml';
21
21
  import './fs-operations.mjs';
22
22
  import 'node:crypto';
23
23
  import 'node:fs/promises';
24
- import 'dayjs';
24
+ import './smart-defaults.mjs';
25
25
  import 'node:child_process';
26
26
  import './platform.mjs';
27
+ import '../shared/ccjk.DKojSRzw.mjs';
27
28
  import 'inquirer-toggle';
29
+ import 'dayjs';
28
30
  import 'trash';
29
31
 
30
32
  async function pathExists(p) {
@@ -558,7 +560,7 @@ async function uninstall(options = {}) {
558
560
  }
559
561
  const uninstaller = new ZcfUninstaller(options.lang || "en");
560
562
  if (codeType === "codex") {
561
- const { runCodexUninstall } = await import('./codex.mjs').then(function (n) { return n.i; });
563
+ const { runCodexUninstall } = await import('./codex.mjs').then(function (n) { return n.m; });
562
564
  await runCodexUninstall();
563
565
  return;
564
566
  }
@@ -5,11 +5,10 @@ import { SETTINGS_FILE, DEFAULT_CODE_TOOL_TYPE, resolveCodeToolType as resolveCo
5
5
  import { i18n } from './index.mjs';
6
6
  import { a as displayBanner } from '../shared/ccjk.Br91zBIG.mjs';
7
7
  import { readZcfConfig, updateZcfConfig } from './ccjk-config.mjs';
8
- import { e as runCodexUpdate } from './codex.mjs';
9
- import { f as copyConfigFiles } from './config.mjs';
10
- import { n as needsMigration, m as migrateSettingsForTokenRetrieval, d as displayMigrationResult, p as promptMigration, s as selectAndInstallWorkflows } from '../shared/ccjk.C0pb50xH.mjs';
11
- import { u as updatePromptOnly } from '../shared/ccjk.ChMkBmdL.mjs';
12
- import { a as handleExitPromptError, h as handleGeneralError } from '../shared/ccjk.CItD1fpl.mjs';
8
+ import { d as runCodexUpdate } from './codex.mjs';
9
+ import { a as copyConfigFiles } from './config.mjs';
10
+ import { n as needsMigration, a as migrateSettingsForTokenRetrieval, d as displayMigrationResult, p as promptMigration, u as updatePromptOnly, s as selectAndInstallWorkflows } from '../shared/ccjk.LsPZ2PYo.mjs';
11
+ import { h as handleExitPromptError, a as handleGeneralError } from '../shared/ccjk.DvIrK0wz.mjs';
13
12
  import { resolveAiOutputLanguage } from './prompts.mjs';
14
13
  import { checkClaudeCodeVersionAndPrompt } from './version-checker.mjs';
15
14
  import 'node:os';
@@ -32,10 +31,8 @@ import './platform.mjs';
32
31
  import '../shared/ccjk.BFQ7yr5S.mjs';
33
32
  import '../shared/ccjk.DHbrGcgg.mjs';
34
33
  import 'inquirer-toggle';
35
- import '../shared/ccjk.CtSfXUSh.mjs';
36
34
  import 'node:child_process';
37
35
  import './claude-config.mjs';
38
- import './workflows2.mjs';
39
36
  import 'node:path';
40
37
  import 'node:util';
41
38
 
@@ -4,7 +4,7 @@ import * as path from 'node:path';
4
4
  import process__default from 'node:process';
5
5
  import { promisify } from 'node:util';
6
6
  import * as semver from 'semver';
7
- import { b as getPlatform, f as findCommandPath, c as getHomebrewCommandPaths } from './platform.mjs';
7
+ import { d as getPlatform, f as findCommandPath, e as getHomebrewCommandPaths } from './platform.mjs';
8
8
  import 'node:os';
9
9
  import 'pathe';
10
10
  import 'tinyexec';