sickbay 1.16.2 → 1.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{DiffApp-DeNEtlY7.js → DiffApp-39aMGuNc.js} +2 -2
- package/dist/{DiffApp-DeNEtlY7.js.map → DiffApp-39aMGuNc.js.map} +1 -1
- package/dist/{FixApp-MWXohP60.js → FixApp-CFotJ2y8.js} +77 -16
- package/dist/FixApp-CFotJ2y8.js.map +1 -0
- package/dist/{TrendApp-DOBt7ITA.js → TrendApp-D_YTj9kI.js} +2 -2
- package/dist/{TrendApp-DOBt7ITA.js.map → TrendApp-D_YTj9kI.js.map} +1 -1
- package/dist/{TuiApp-D4Wn81Qv.js → TuiApp-B3l1OC7M.js} +8 -8
- package/dist/{TuiApp-D4Wn81Qv.js.map → TuiApp-B3l1OC7M.js.map} +1 -1
- package/dist/badge-CTayKnYV.js +56 -0
- package/dist/badge-CTayKnYV.js.map +1 -0
- package/dist/{history-DVegAwFp.js → history-C9hu3f6s.js} +22 -5
- package/dist/history-C9hu3f6s.js.map +1 -0
- package/dist/index.js +21 -20
- package/dist/index.js.map +1 -1
- package/dist/{init-Dn7eDMEp.js → init-Czn8P7An.js} +2 -2
- package/dist/{init-Dn7eDMEp.js.map → init-Czn8P7An.js.map} +1 -1
- package/dist/{web-D5etye5Q.js → web-CFBLfBdc.js} +27 -22
- package/dist/web-CFBLfBdc.js.map +1 -0
- package/package.json +1 -1
- package/dist/FixApp-MWXohP60.js.map +0 -1
- package/dist/badge-DB3y0fWt.js +0 -37
- package/dist/badge-DB3y0fWt.js.map +0 -1
- package/dist/history-DVegAwFp.js.map +0 -1
- package/dist/web-D5etye5Q.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -130,7 +130,7 @@ function Header({ projectName }) {
|
|
|
130
130
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
131
131
|
flexDirection: "column",
|
|
132
132
|
marginBottom: 1
|
|
133
|
-
}, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.16.
|
|
133
|
+
}, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.16.3")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, {
|
|
134
134
|
bold: true,
|
|
135
135
|
color: "white"
|
|
136
136
|
}, projectName)));
|
|
@@ -294,7 +294,7 @@ function App({ projectPath, checks, openWeb, enableAI, verbose, quotes, isMonore
|
|
|
294
294
|
setProjectName(`monorepo (${r.packages.length} packages)`);
|
|
295
295
|
try {
|
|
296
296
|
const { getDependencyTree } = await import("./dist-Bjhxbcak.js").then((n) => n.s);
|
|
297
|
-
const { saveDepTree } = await import("./history-
|
|
297
|
+
const { saveDepTree } = await import("./history-C9hu3f6s.js").then((n) => n.n);
|
|
298
298
|
const packages = {};
|
|
299
299
|
for (const pkg of r.packages) packages[pkg.name] = await getDependencyTree(pkg.path, r.packageManager);
|
|
300
300
|
saveDepTree(projectPath, { packages });
|
|
@@ -302,7 +302,7 @@ function App({ projectPath, checks, openWeb, enableAI, verbose, quotes, isMonore
|
|
|
302
302
|
if (openWeb) {
|
|
303
303
|
setPhase("opening-web");
|
|
304
304
|
try {
|
|
305
|
-
const { serveWeb } = await import("./web-
|
|
305
|
+
const { serveWeb } = await import("./web-CFBLfBdc.js");
|
|
306
306
|
const { default: openBrowser } = await import("open");
|
|
307
307
|
let aiService;
|
|
308
308
|
if (enableAI && process.env.ANTHROPIC_API_KEY) {
|
|
@@ -357,19 +357,19 @@ function App({ projectPath, checks, openWeb, enableAI, verbose, quotes, isMonore
|
|
|
357
357
|
setProjectName(r.projectInfo.name);
|
|
358
358
|
setReport(r);
|
|
359
359
|
try {
|
|
360
|
-
const { saveEntry, saveLastReport } = await import("./history-
|
|
360
|
+
const { saveEntry, saveLastReport } = await import("./history-C9hu3f6s.js").then((n) => n.n);
|
|
361
361
|
saveEntry(r);
|
|
362
362
|
saveLastReport(r);
|
|
363
363
|
} catch {}
|
|
364
364
|
try {
|
|
365
365
|
const { getDependencyTree } = await import("./dist-Bjhxbcak.js").then((n) => n.s);
|
|
366
|
-
const { saveDepTree } = await import("./history-
|
|
366
|
+
const { saveDepTree } = await import("./history-C9hu3f6s.js").then((n) => n.n);
|
|
367
367
|
saveDepTree(projectPath, await getDependencyTree(projectPath, r.projectInfo.packageManager));
|
|
368
368
|
} catch {}
|
|
369
369
|
if (openWeb) {
|
|
370
370
|
setPhase("opening-web");
|
|
371
371
|
try {
|
|
372
|
-
const { serveWeb } = await import("./web-
|
|
372
|
+
const { serveWeb } = await import("./web-CFBLfBdc.js");
|
|
373
373
|
const { default: openBrowser } = await import("open");
|
|
374
374
|
let aiService;
|
|
375
375
|
if (enableAI && process.env.ANTHROPIC_API_KEY) {
|
|
@@ -469,7 +469,7 @@ config({
|
|
|
469
469
|
quiet: true
|
|
470
470
|
});
|
|
471
471
|
const program = new Command();
|
|
472
|
-
program.name("sickbay").description("React project health check CLI").version("1.16.
|
|
472
|
+
program.name("sickbay").description("React project health check CLI").version("1.16.3", "-v, --version").enablePositionalOptions().passThroughOptions().option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single named package (monorepo only)").option("--json", "output raw JSON report").option("--web", "open web dashboard after scan").option("--no-ai", "disable AI features").option("--no-quotes", "suppress personality quotes in output").option("--verbose", "show verbose output").action(async (options) => {
|
|
473
473
|
if (!existsSync(options.path)) {
|
|
474
474
|
process.stderr.write(`Error: path does not exist: ${options.path}\n`);
|
|
475
475
|
process.exit(1);
|
|
@@ -484,7 +484,7 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
484
484
|
const updatePromise = (async () => {
|
|
485
485
|
try {
|
|
486
486
|
const { checkForUpdate } = await import("./update-check-C7bNNfvf.js");
|
|
487
|
-
return await checkForUpdate("1.16.
|
|
487
|
+
return await checkForUpdate("1.16.3");
|
|
488
488
|
} catch {
|
|
489
489
|
return null;
|
|
490
490
|
}
|
|
@@ -550,13 +550,13 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
550
550
|
quotes: options.quotes
|
|
551
551
|
});
|
|
552
552
|
try {
|
|
553
|
-
const { saveEntry, saveLastReport } = await import("./history-
|
|
553
|
+
const { saveEntry, saveLastReport } = await import("./history-C9hu3f6s.js").then((n) => n.n);
|
|
554
554
|
saveEntry(report);
|
|
555
555
|
saveLastReport(report);
|
|
556
556
|
} catch {}
|
|
557
557
|
try {
|
|
558
558
|
const { getDependencyTree } = await import("./dist-Bjhxbcak.js").then((n) => n.s);
|
|
559
|
-
const { saveDepTree } = await import("./history-
|
|
559
|
+
const { saveDepTree } = await import("./history-C9hu3f6s.js").then((n) => n.n);
|
|
560
560
|
const tree = await getDependencyTree(options.path, report.projectInfo.packageManager);
|
|
561
561
|
saveDepTree(options.path, tree);
|
|
562
562
|
} catch {}
|
|
@@ -576,19 +576,19 @@ program.name("sickbay").description("React project health check CLI").version("1
|
|
|
576
576
|
});
|
|
577
577
|
program.command("init").description("Initialize .sickbay/ folder and run an initial baseline scan").option("-p, --path <path>", "project path to initialize", process.cwd()).option("--sync", "add newly available checks to existing config without touching existing entries").option("--reset-config", "regenerate config from scratch (overwrites existing)").action(async (options) => {
|
|
578
578
|
if (options.resetConfig) {
|
|
579
|
-
const { generateConfigFile } = await import("./init-
|
|
579
|
+
const { generateConfigFile } = await import("./init-Czn8P7An.js");
|
|
580
580
|
await generateConfigFile(options.path, { force: true });
|
|
581
581
|
return;
|
|
582
582
|
}
|
|
583
583
|
if (options.sync) {
|
|
584
|
-
const { syncConfigFile } = await import("./init-
|
|
584
|
+
const { syncConfigFile } = await import("./init-Czn8P7An.js");
|
|
585
585
|
await syncConfigFile(options.path);
|
|
586
586
|
return;
|
|
587
587
|
}
|
|
588
|
-
const { initSickbay } = await import("./init-
|
|
588
|
+
const { initSickbay } = await import("./init-Czn8P7An.js");
|
|
589
589
|
await initSickbay(options.path);
|
|
590
590
|
});
|
|
591
|
-
program.command("fix").description("Interactively fix issues found by sickbay scan").option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single package (monorepo only)").option("--all", "apply all available fixes without prompting").option("--dry-run", "show what would be fixed without executing").option("--verbose", "show verbose output").action(async (options) => {
|
|
591
|
+
program.command("fix").description("Interactively fix issues found by sickbay scan").option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--package <name>", "scope to a single package (monorepo only)").option("--all", "apply all available fixes without prompting").option("--dry-run", "show what would be fixed without executing").option("--skip-git-check", "skip the uncommitted-changes warning before applying source-modifying fixes").option("--verbose", "show verbose output").action(async (options) => {
|
|
592
592
|
if (options.path && options.path !== process.cwd()) {
|
|
593
593
|
const projectEnvPath = join(options.path, ".env");
|
|
594
594
|
if (existsSync(projectEnvPath)) config({
|
|
@@ -598,7 +598,7 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
|
|
|
598
598
|
}
|
|
599
599
|
const { resolveProject } = await import("./resolve-package-DS27JBhN.js");
|
|
600
600
|
const resolution = await resolveProject(options.path, options.package);
|
|
601
|
-
const { FixApp } = await import("./FixApp-
|
|
601
|
+
const { FixApp } = await import("./FixApp-CFotJ2y8.js");
|
|
602
602
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
603
603
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
604
604
|
render(React.createElement(FixApp, {
|
|
@@ -606,6 +606,7 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
|
|
|
606
606
|
checks,
|
|
607
607
|
applyAll: options.all ?? false,
|
|
608
608
|
dryRun: options.dryRun ?? false,
|
|
609
|
+
skipGitCheck: options.skipGitCheck ?? false,
|
|
609
610
|
verbose: options.verbose ?? false,
|
|
610
611
|
isMonorepo: resolution.isMonorepo && !resolution.targetPath,
|
|
611
612
|
packagePaths: resolution.isMonorepo ? resolution.packagePaths : void 0,
|
|
@@ -623,7 +624,7 @@ program.command("trend").description("Show score history and trends over time").
|
|
|
623
624
|
const { resolveProject } = await import("./resolve-package-DS27JBhN.js");
|
|
624
625
|
const resolution = await resolveProject(options.path, options.package);
|
|
625
626
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
626
|
-
const { TrendApp } = await import("./TrendApp-
|
|
627
|
+
const { TrendApp } = await import("./TrendApp-D_YTj9kI.js");
|
|
627
628
|
render(React.createElement(TrendApp, {
|
|
628
629
|
projectPath,
|
|
629
630
|
last: parseInt(options.last, 10),
|
|
@@ -654,7 +655,7 @@ program.command("stats").description("Show a quick codebase overview and project
|
|
|
654
655
|
}));
|
|
655
656
|
});
|
|
656
657
|
program.command("tui").description("Launch the persistent developer dashboard").option("-p, --path <path>", "project path to monitor", process.cwd()).option("--no-watch", "disable file-watching auto-refresh").option("--no-quotes", "suppress personality quotes in output").option("--refresh <seconds>", "auto-refresh interval in seconds", "300").option("-c, --checks <checks>", "comma-separated list of checks to run").action(async (options) => {
|
|
657
|
-
const { TuiApp } = await import("./TuiApp-
|
|
658
|
+
const { TuiApp } = await import("./TuiApp-B3l1OC7M.js");
|
|
658
659
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
659
660
|
render(React.createElement(TuiApp, {
|
|
660
661
|
projectPath: options.path,
|
|
@@ -689,7 +690,7 @@ program.command("badge").description("Generate a health score badge for your REA
|
|
|
689
690
|
const { resolveProject } = await import("./resolve-package-DS27JBhN.js");
|
|
690
691
|
const resolution = await resolveProject(options.path, options.package);
|
|
691
692
|
const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
|
|
692
|
-
const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } = await import("./badge-
|
|
693
|
+
const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } = await import("./badge-CTayKnYV.js");
|
|
693
694
|
let score = options.scan ? null : loadScoreFromLastReport(projectPath);
|
|
694
695
|
if (score === null) {
|
|
695
696
|
const { runSickbay } = await import("./dist-Bjhxbcak.js").then((n) => n.s);
|
|
@@ -698,7 +699,7 @@ program.command("badge").description("Generate a health score badge for your REA
|
|
|
698
699
|
quotes: false
|
|
699
700
|
});
|
|
700
701
|
try {
|
|
701
|
-
const { saveEntry, saveLastReport } = await import("./history-
|
|
702
|
+
const { saveEntry, saveLastReport } = await import("./history-C9hu3f6s.js").then((n) => n.n);
|
|
702
703
|
saveEntry(report);
|
|
703
704
|
saveLastReport(report);
|
|
704
705
|
} catch {}
|
|
@@ -724,7 +725,7 @@ program.command("diff <branch>").description("Compare health score against anoth
|
|
|
724
725
|
});
|
|
725
726
|
}
|
|
726
727
|
const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
|
|
727
|
-
const { DiffApp } = await import("./DiffApp-
|
|
728
|
+
const { DiffApp } = await import("./DiffApp-39aMGuNc.js");
|
|
728
729
|
render(React.createElement(DiffApp, {
|
|
729
730
|
projectPath: options.path,
|
|
730
731
|
branch,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Spinner","formatDuration"],"sources":["../src/lib/issue-grouping.ts","../src/lib/messages.ts","../src/components/BestPractices.tsx","../src/components/ScoreBar.tsx","../src/components/CheckResult.tsx","../src/components/Header.tsx","../src/components/ProgressList.tsx","../src/components/QuickWins.tsx","../src/components/Summary.tsx","../src/components/UpdateNotice.tsx","../src/components/App.tsx","../src/index.ts"],"sourcesContent":["import type { CheckResult } from 'sickbay-core';\n\nexport function extractPatternStem(message: string): string {\n const idx = message.indexOf(' \\u2014 ');\n return idx >= 0 ? message.slice(idx + 3) : message;\n}\n\nexport function countUniqueIssues(checks: CheckResult[]): {\n critical: number;\n warnings: number;\n info: number;\n totalCritical: number;\n totalWarnings: number;\n totalInfo: number;\n} {\n const seen = { critical: new Set<string>(), warning: new Set<string>(), info: new Set<string>() };\n const totals = { critical: 0, warning: 0, info: 0 };\n\n for (const check of checks) {\n for (const issue of check.issues) {\n const stem = extractPatternStem(issue.message);\n const key = `${check.id}::${stem}`;\n seen[issue.severity].add(key);\n totals[issue.severity]++;\n }\n }\n\n return {\n critical: seen.critical.size,\n warnings: seen.warning.size,\n info: seen.info.size,\n totalCritical: totals.critical,\n totalWarnings: totals.warning,\n totalInfo: totals.info,\n };\n}\n","export const LOADING_MESSAGES = [\n 'Scanning for pre-existing conditions…',\n 'Counting packages… still counting…',\n 'Still here. Still scanning...',\n 'The unused dependencies know what they did...',\n 'Every unused export is a tiny cry for help...',\n \"Checking if 'TODO: fix later' was ever fixed later...\",\n 'Your secrets are safe with us. Unlike your .env file...',\n 'Good things take time. This is one of the good things. Probably...',\n 'npm audit found issues. npm audit --fix found different issues.',\n 'This is fine...',\n 'Evaluating life choices. Yours. Via package.json.',\n 'Almost done. (This is not a legally binding statement.)',\n 'node_modules: depth unknown. Will not attempt.',\n 'Performing checks. Results may vary...',\n];\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\nimport type { SickbayReport } from 'sickbay-core';\n\ninterface BestPracticesProps {\n report: SickbayReport;\n}\n\nexport function BestPractices({ report }: BestPracticesProps) {\n const recs = report.recommendations;\n if (!recs || recs.length === 0) return null;\n\n const sorted = [...recs].sort((a, b) => {\n const order = { recommend: 0, suggest: 1 };\n return order[a.severity] - order[b.severity];\n });\n\n const display = sorted.slice(0, 5);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>💡 Advisor:</Text>\n {display.map((rec) => (\n <Box key={rec.id} marginLeft={2}>\n <Text color={rec.severity === 'recommend' ? 'yellow' : 'gray'}>\n {rec.severity === 'recommend' ? '● ' : '○ '}\n </Text>\n <Text bold>{rec.title}</Text>\n <Text dimColor> — {rec.message}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\n/**\n * Component to display a horizontal score bar representing the overall health score.\n * The bar is filled proportionally to the score and colored based on thresholds:\n * - Green for 80 and above\n * - Yellow for 60-79\n * - Red for below 60\n */\n\ninterface ScoreBarProps {\n score: number;\n width?: number;\n}\n\nexport function ScoreBar({ score, width = 20 }: ScoreBarProps) {\n const filled = Math.round((score / 100) * width);\n const empty = width - filled;\n const color = score >= 80 ? 'green' : score >= 60 ? 'yellow' : 'red';\n\n return (\n <Box>\n <Text color={color}>{'█'.repeat(filled)}</Text>\n <Text dimColor>{'░'.repeat(empty)}</Text>\n <Text color={color}> {score}/100</Text>\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\nimport { ScoreBar } from './ScoreBar.js';\n\nimport type { CheckResult as CheckResultType } from 'sickbay-core';\n\nconst STATUS_ICONS = {\n pass: '✓',\n warning: '⚠',\n fail: '✗',\n skipped: '○',\n};\n\nconst CATEGORY_ICONS: Record<string, string> = {\n dependencies: '📦',\n security: '✔',\n 'code-quality': '✔',\n performance: '⚡',\n git: '✔',\n};\n\ninterface CheckResultProps {\n result: CheckResultType;\n}\n\nexport function CheckResultRow({ result }: CheckResultProps) {\n const statusColor =\n result.status === 'pass'\n ? 'green'\n : result.status === 'fail'\n ? 'red'\n : result.status === 'skipped'\n ? 'gray'\n : 'yellow';\n const icon = CATEGORY_ICONS[result.category] ?? '•';\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>{icon} </Text>\n <Text bold>{result.name}</Text>\n <Text dimColor> via {result.toolsUsed.join(', ')}</Text>\n </Box>\n <Box marginLeft={2}>\n <ScoreBar score={result.score} width={16} />\n <Text color={statusColor}>\n {' '}\n {STATUS_ICONS[result.status]} {result.status}\n </Text>\n </Box>\n {result.issues.slice(0, 3).map((issue) => (\n <Box key={`${issue.severity}-${issue.message}`} marginLeft={2}>\n <Text\n color={\n issue.severity === 'critical'\n ? 'red'\n : issue.severity === 'warning'\n ? 'yellow'\n : 'gray'\n }\n >\n {issue.severity === 'critical' ? ' ✗' : issue.severity === 'warning' ? ' ⚠' : ' ℹ'}{' '}\n {issue.message}\n </Text>\n </Box>\n ))}\n {result.issues.length > 3 && (\n <Box marginLeft={4}>\n <Text dimColor>... and {result.issues.length - 3} more</Text>\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\ndeclare const __VERSION__: string;\n\nconst ASCII_ART = `\n███████ ██ ██████ ██ ██ ██████ █████ ██ ██ \n██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n███████ ██ ██ █████ ██████ ███████ ████ \n ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n███████ ██ ██████ ██ ██ ██████ ██ ██ ██ \n\nA vitals health check for your app\n`.trim();\n\ninterface HeaderProps {\n projectName?: string;\n}\n\nexport function Header({ projectName }: HeaderProps) {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"green\">{ASCII_ART}</Text>\n <Box marginTop={1}>\n <Text dimColor> v{__VERSION__}</Text>\n </Box>\n {projectName && (\n <Box marginTop={1}>\n <Text dimColor> Analyzing </Text>\n <Text bold color=\"white\">\n {projectName}\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n","import React, { useState, useEffect } from 'react';\n\nimport { Box, Text } from 'ink';\n\nconst SPINNER_FRAMES = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];\n\nfunction Spinner() {\n const [frame, setFrame] = useState(0);\n useEffect(() => {\n const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), 80);\n return () => clearInterval(id);\n }, []);\n return <Text color=\"green\">{SPINNER_FRAMES[frame]}</Text>;\n}\n\ninterface ProgressItem {\n name: string;\n status: 'pending' | 'running' | 'done';\n}\n\ninterface ProgressListProps {\n items: ProgressItem[];\n}\n\nexport function ProgressList({ items }: ProgressListProps) {\n return (\n <Box flexDirection=\"column\">\n {items.map((item) => (\n <Box key={item.name}>\n {item.status === 'running' ? (\n <Spinner />\n ) : item.status === 'done' ? (\n <Text color=\"green\">✓</Text>\n ) : (\n <Text dimColor>○</Text>\n )}\n <Text> {item.name}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\nimport type { SickbayReport } from 'sickbay-core';\n\n/**\n * Component to display quick wins based on the report's issues that have fixes available.\n * It shows up to 5 fixable issues, sorted by severity (critical > warning > info).\n */\n\ninterface QuickWinsProps {\n report: SickbayReport;\n}\n\nfunction replacePackageManager(cmd: string, pm: string): string {\n if (pm === 'npm') return cmd;\n const install = pm === 'pnpm' ? 'pnpm add' : pm === 'yarn' ? 'yarn add' : 'bun add';\n const uninstall = pm === 'pnpm' ? 'pnpm remove' : pm === 'yarn' ? 'yarn remove' : 'bun remove';\n const update = pm === 'pnpm' ? 'pnpm update' : pm === 'yarn' ? 'yarn upgrade' : 'bun update';\n const auditFix =\n pm === 'pnpm' ? 'pnpm audit --fix' : pm === 'yarn' ? 'yarn npm audit --fix' : 'bun audit';\n return cmd\n .replace(/^npm install(?=\\s)/, install)\n .replace(/^npm uninstall(?=\\s)/, uninstall)\n .replace(/^npm update(?=\\s)/, update)\n .replace(/^npm audit fix/, auditFix);\n}\n\nexport function QuickWins({ report }: QuickWinsProps) {\n const pm = report.projectInfo?.packageManager ?? 'npm';\n const fixes = report.checks\n .flatMap((c) => c.issues)\n .filter((i) => i.fix?.command)\n .sort((a, b) => {\n const order = { critical: 0, warning: 1, info: 2 };\n return order[a.severity] - order[b.severity];\n })\n .slice(0, 5);\n\n if (fixes.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>🔥 Quick Wins:</Text>\n {fixes.map((fix) => (\n <Box key={`${fix.severity}-${fix.message}`} marginLeft={2}>\n <Text dimColor>→ </Text>\n <Text>{fix.fix!.description}</Text>\n {fix.fix!.command && (\n <Text dimColor>: {replacePackageManager(fix.fix!.command, pm)}</Text>\n )}\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\nimport { getScoreEmoji } from 'sickbay-core';\n\nimport { countUniqueIssues } from '../lib/issue-grouping.js';\nimport { ScoreBar } from './ScoreBar.js';\n\nimport type { SickbayReport } from 'sickbay-core';\n\n/**\n * Summary component displays the overall health score of the project along with a breakdown of critical issues, warnings, and info.\n * It uses the ScoreBar component to visually represent the overall score and color-codes the counts of issues based on severity.\n */\n\ninterface SummaryProps {\n report: SickbayReport;\n scanDuration?: number | null;\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n const seconds = ms / 1000;\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.round(seconds % 60);\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function Summary({ report, scanDuration }: SummaryProps) {\n const u = countUniqueIssues(report.checks);\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{'━'.repeat(52)}</Text>\n <Box marginTop={1}>\n <Text bold>Overall Health Score: </Text>\n <ScoreBar score={report.overallScore} width={12} />\n <Text> {getScoreEmoji(report.overallScore)}</Text>\n {scanDuration != null && <Text dimColor> {formatDuration(scanDuration)}</Text>}\n </Box>\n <Box marginTop={1}>\n <Text color=\"red\">\n {' '}\n ✗ {u.critical} critical\n {u.totalCritical > u.critical ? ` (${u.totalCritical} total)` : ''}\n </Text>\n <Text color=\"yellow\">\n {' '}\n ⚠ {u.warnings} warning{u.warnings !== 1 ? 's' : ''}\n {u.totalWarnings > u.warnings ? ` (${u.totalWarnings} total)` : ''}\n </Text>\n <Text color=\"gray\"> i {u.info} info</Text>\n </Box>\n {report.quote && (\n <Box marginTop={1}>\n <Text italic dimColor>\n \"{report.quote.text}\"\n </Text>\n <Text dimColor> — {report.quote.source}</Text>\n </Box>\n )}\n {report.config?.hasCustomConfig && (\n <Box marginTop={1}>\n <Text dimColor italic>\n Custom config active\n {report.config.disabledChecks.length > 0 &&\n ` (${report.config.disabledChecks.length} check${report.config.disabledChecks.length === 1 ? '' : 's'} disabled)`}\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\ninterface UpdateNoticeProps {\n currentVersion: string;\n latestVersion: string;\n}\n\nexport function UpdateNotice({ currentVersion, latestVersion }: UpdateNoticeProps) {\n const line1 = `Update available: ${currentVersion} → ${latestVersion}`;\n const line2 = 'npx sickbay@latest (one-time run)';\n const line3 = 'npm i -g sickbay@latest (global install)';\n const maxLength = Math.max(line1.length, line2.length, line3.length);\n const padding = 2;\n const boxWidth = maxLength + padding * 2;\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"yellow\" dimColor>\n {`╭${'─'.repeat(boxWidth)}╮`}\n </Text>\n <Box paddingX={padding}>\n <Text color=\"yellow\" dimColor>\n {line1}\n </Text>\n </Box>\n <Box paddingX={padding}>\n <Text color=\"yellow\" dimColor>\n {line2}\n </Text>\n </Box>\n <Box paddingX={padding}>\n <Text color=\"yellow\" dimColor>\n {line3}\n </Text>\n </Box>\n <Text color=\"yellow\" dimColor>\n {`╰${'─'.repeat(boxWidth)}╯`}\n </Text>\n </Box>\n );\n}\n","import React, { useState, useEffect, useRef } from 'react';\n\nimport { Box, Text, useApp } from 'ink';\nimport Gradient from 'ink-gradient';\nimport Spinner from 'ink-spinner';\nimport { runSickbay, runSickbayMonorepo } from 'sickbay-core';\n\nimport { countUniqueIssues } from '../lib/issue-grouping.js';\nimport { LOADING_MESSAGES } from '../lib/messages.js';\nimport { BestPractices } from './BestPractices.js';\nimport { CheckResultRow } from './CheckResult.js';\nimport { Header } from './Header.js';\nimport { ProgressList } from './ProgressList.js';\nimport { QuickWins } from './QuickWins.js';\nimport { Summary } from './Summary.js';\nimport { UpdateNotice } from './UpdateNotice.js';\n\nimport type { UpdateInfo } from '../lib/update-check.js';\nimport type { SickbayReport, MonorepoReport, PackageReport } from 'sickbay-core';\n\ninterface AppProps {\n projectPath: string;\n checks?: string[];\n openWeb?: boolean;\n enableAI?: boolean;\n verbose?: boolean;\n quotes?: boolean;\n isMonorepo?: boolean;\n updatePromise?: Promise<UpdateInfo | null>;\n}\n\ntype Phase = 'loading' | 'results' | 'opening-web' | 'error';\n\ninterface ProgressItem {\n name: string;\n status: 'pending' | 'running' | 'done';\n}\n\nfunction scoreBar(score: number, width = 10): string {\n const filled = Math.round((score / 100) * width);\n return '█'.repeat(filled) + '░'.repeat(width - filled);\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n const seconds = ms / 1000;\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.round(seconds % 60);\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function App({\n projectPath,\n checks,\n openWeb,\n enableAI,\n verbose,\n quotes,\n isMonorepo,\n updatePromise,\n}: AppProps) {\n const { exit } = useApp();\n const [phase, setPhase] = useState<Phase>('loading');\n const [report, setReport] = useState<SickbayReport | null>(null);\n const [monorepoReport, setMonorepoReport] = useState<MonorepoReport | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [progress, setProgress] = useState<ProgressItem[]>([]);\n const [webUrl, setWebUrl] = useState<string | null>(null);\n const [projectName, setProjectName] = useState<string | undefined>();\n const [scanningPackage, setScanningPackage] = useState<string | undefined>();\n const [loadingMsgIdx, setLoadingMsgIdx] = useState(0);\n const [scanDuration, setScanDuration] = useState<number | null>(null);\n const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);\n const hasRun = useRef(false);\n const scanStartTime = useRef<number>(0);\n\n useEffect(() => {\n if (!isMonorepo) return;\n const id = setInterval(() => {\n setLoadingMsgIdx((i) => (i + 1) % LOADING_MESSAGES.length);\n }, 4000);\n return () => clearInterval(id);\n }, [isMonorepo]);\n\n useEffect(() => {\n if (updatePromise) {\n updatePromise.then((info) => {\n if (info) setUpdateInfo(info);\n });\n }\n }, [updatePromise]);\n\n useEffect(() => {\n // Prevent double execution (React 18+ can run effects twice in dev/certain conditions)\n if (hasRun.current) return;\n hasRun.current = true;\n\n scanStartTime.current = Date.now();\n\n if (isMonorepo) {\n runSickbayMonorepo({\n projectPath,\n checks,\n verbose,\n quotes,\n onPackageStart: (name) => setScanningPackage(name),\n onPackageComplete: () => setScanningPackage(undefined),\n })\n .then(async (r) => {\n setScanDuration(Date.now() - scanStartTime.current);\n setMonorepoReport(r);\n setProjectName(`monorepo (${r.packages.length} packages)`);\n\n // Cache dependency tree for web dashboard\n try {\n const { getDependencyTree } = await import('sickbay-core');\n const { saveDepTree } = await import('../lib/history.js');\n const packages: Record<string, unknown> = {};\n for (const pkg of r.packages) {\n packages[pkg.name] = await getDependencyTree(pkg.path, r.packageManager);\n }\n saveDepTree(projectPath, { packages });\n } catch {\n /* dep tree is optional */\n }\n\n if (openWeb) {\n setPhase('opening-web');\n try {\n const { serveWeb } = await import('../commands/web.js');\n const { default: openBrowser } = await import('open');\n\n let aiService;\n if (enableAI && process.env.ANTHROPIC_API_KEY) {\n const { createAIService } = await import('../services/ai.js');\n aiService = createAIService(process.env.ANTHROPIC_API_KEY);\n }\n\n const url = await serveWeb(r, 3030, aiService);\n setWebUrl(url);\n await openBrowser(url);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setPhase('error');\n setTimeout(() => exit(), 100);\n }\n } else {\n setPhase('results');\n setTimeout(() => exit(), 100);\n }\n })\n .catch((err) => {\n setError(err.message ?? String(err));\n setPhase('error');\n setTimeout(() => exit(err), 100);\n });\n return;\n }\n\n runSickbay({\n projectPath,\n checks,\n verbose,\n quotes,\n onRunnersReady: (names) => {\n setProgress(names.map((name) => ({ name, status: 'pending' as const })));\n },\n onCheckStart: (name) => {\n setProgress((prev) => prev.map((p) => (p.name === name ? { ...p, status: 'running' } : p)));\n },\n onCheckComplete: (result) => {\n if (result.status === 'skipped') {\n setProgress((prev) => prev.filter((p) => p.name !== result.id));\n } else {\n setProgress((prev) =>\n prev.map((p) => (p.name === result.id ? { ...p, status: 'done' } : p)),\n );\n }\n },\n })\n .then(async (r) => {\n setScanDuration(Date.now() - scanStartTime.current);\n setProjectName(r.projectInfo.name);\n setReport(r);\n\n // Auto-save to trend history and last-report snapshot\n try {\n const { saveEntry, saveLastReport } = await import('../lib/history.js');\n saveEntry(r);\n saveLastReport(r);\n } catch {\n // Non-critical — silently ignore history save failures\n }\n\n // Cache dependency tree for web dashboard\n try {\n const { getDependencyTree } = await import('sickbay-core');\n const { saveDepTree } = await import('../lib/history.js');\n const tree = await getDependencyTree(projectPath, r.projectInfo.packageManager);\n saveDepTree(projectPath, tree);\n } catch {\n /* dep tree is optional, don't break the scan */\n }\n\n if (openWeb) {\n setPhase('opening-web');\n try {\n const { serveWeb } = await import('../commands/web.js');\n const { default: openBrowser } = await import('open');\n\n // Create AI service if enabled and API key exists\n let aiService;\n if (enableAI && process.env.ANTHROPIC_API_KEY) {\n const { createAIService } = await import('../services/ai.js');\n aiService = createAIService(process.env.ANTHROPIC_API_KEY);\n }\n\n const url = await serveWeb(r, 3030, aiService);\n setWebUrl(url);\n await openBrowser(url);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setPhase('error');\n setTimeout(() => exit(), 100);\n return;\n }\n // Keep process alive — user closes with Ctrl+C\n } else {\n setPhase('results');\n setTimeout(() => exit(), 100);\n }\n })\n .catch((err) => {\n setError(err.message ?? String(err));\n setPhase('error');\n setTimeout(() => exit(err), 100);\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header projectName={projectName} />\n\n {updateInfo && (\n <UpdateNotice\n currentVersion={updateInfo.currentVersion}\n latestVersion={updateInfo.latestVersion}\n />\n )}\n\n {phase === 'loading' && (\n <Box flexDirection=\"column\">\n {isMonorepo ? (\n <Box flexDirection=\"column\">\n <Box>\n <Text color=\"magenta\">\n <Spinner type=\"dots\" />\n </Text>\n <Text dimColor> {LOADING_MESSAGES[loadingMsgIdx]}</Text>\n </Box>\n {scanningPackage && (\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>→ </Text>\n <Text color=\"cyan\">{scanningPackage}</Text>\n </Box>\n )}\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n <Text dimColor>Running health checks...</Text>\n <Box marginTop={1} marginLeft={2}>\n <ProgressList items={progress} />\n </Box>\n </Box>\n )}\n </Box>\n )}\n\n {phase === 'error' && (\n <Box>\n <Text color=\"red\">✗ Error: {error}</Text>\n </Box>\n )}\n\n {phase === 'results' && monorepoReport && (\n <MonorepoSummaryTable report={monorepoReport} scanDuration={scanDuration} />\n )}\n\n {phase === 'results' && report && (\n <Box flexDirection=\"column\">\n {report.checks\n .filter((c) => c.status !== 'skipped')\n .map((check) => (\n <CheckResultRow key={check.id} result={check} />\n ))}\n <Summary report={report} scanDuration={scanDuration} />\n <QuickWins report={report} />\n <BestPractices report={report} />\n <Box marginTop={1}>\n <Text dimColor>View detailed report: </Text>\n <Text color=\"cyan\">sickbay --web</Text>\n </Box>\n </Box>\n )}\n\n {phase === 'opening-web' && (monorepoReport ?? report) && (\n <Box flexDirection=\"column\">\n {monorepoReport ? (\n <MonorepoSummaryTable report={monorepoReport} scanDuration={scanDuration} />\n ) : report ? (\n <>\n {report.checks\n .filter((c) => c.status !== 'skipped')\n .map((check) => (\n <CheckResultRow key={check.id} result={check} />\n ))}\n <Summary report={report} scanDuration={scanDuration} />\n </>\n ) : null}\n <Box marginTop={1}>\n {webUrl ? (\n <>\n <Text color=\"green\">✓ Dashboard running at </Text>\n <Text color=\"cyan\">{webUrl}</Text>\n <Text dimColor> (Ctrl+C to stop)</Text>\n </>\n ) : (\n <Text>\n <Text color=\"magenta\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n <Gradient name=\"retro\">Launching dashboard with AI insights...</Gradient>\n </Text>\n )}\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction MonorepoSummaryTable({\n report,\n scanDuration,\n}: {\n report: MonorepoReport;\n scanDuration: number | null;\n}) {\n const scoreColor = (score: number) => (score >= 80 ? 'green' : score >= 60 ? 'yellow' : 'red');\n\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold>Monorepo · </Text>\n <Text dimColor>{report.monorepoType} workspaces · </Text>\n <Text>{report.packages.length} packages</Text>\n </Box>\n {report.packages.map((pkg: PackageReport) => (\n <Box key={pkg.path} marginLeft={2} gap={1}>\n <Text color={scoreColor(pkg.score)}>{scoreBar(pkg.score)}</Text>\n <Text bold color={scoreColor(pkg.score)}>\n {String(pkg.score).padStart(3)}\n </Text>\n <Text>{pkg.name}</Text>\n <Text dimColor>{pkg.framework}</Text>\n {pkg.summary.critical > 0 && <Text color=\"red\"> {pkg.summary.critical} critical</Text>}\n </Box>\n ))}\n <Box marginTop={1} gap={2}>\n <Text bold>Overall: </Text>\n <Text color={scoreColor(report.overallScore)} bold>\n {report.overallScore}\n </Text>\n <Text dimColor>· </Text>\n {(() => {\n const u = countUniqueIssues(report.packages.flatMap((p) => p.checks));\n return (\n <>\n <Text color=\"red\">\n {u.critical} critical\n {u.totalCritical > u.critical ? ` (${u.totalCritical} total)` : ''}\n </Text>\n <Text dimColor>· </Text>\n <Text color=\"yellow\">\n {u.warnings} warnings\n {u.totalWarnings > u.warnings ? ` (${u.totalWarnings} total)` : ''}\n </Text>\n </>\n );\n })()}\n {scanDuration !== null && (\n <>\n <Text dimColor>· </Text>\n <Text dimColor>{formatDuration(scanDuration)}</Text>\n </>\n )}\n </Box>\n {report.quote && (\n <Box marginTop={1}>\n <Text italic dimColor>\n \"{report.quote.text}\"\n </Text>\n <Text dimColor> — {report.quote.source}</Text>\n </Box>\n )}\n <Box marginTop={1}>\n <Text dimColor>Per-package details: </Text>\n <Text color=\"cyan\">sickbay --web</Text>\n </Box>\n </Box>\n );\n}\n","#!/usr/bin/env node\nimport { existsSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nimport React from 'react';\n\nimport { Command } from 'commander';\nimport { config } from 'dotenv';\nimport { render } from 'ink';\n\nimport { App } from './components/App.js';\n\ndeclare const __VERSION__: string;\n\n/**\n * Entry point for the Sickbay CLI application.\n * This script sets up the command-line interface using Commander, loads environment variables, and renders the appropriate Ink components based on user commands.\n * It supports multiple commands including the default scan, trend analysis, stats overview, and a doctor command for diagnosing project issues.\n * Each command can output results in JSON format or render an interactive UI in the terminal.\n */\n\n// Load .env from global config first (~/.sickbay/.env)\nconst globalConfigPath = join(homedir(), '.sickbay', '.env');\nif (existsSync(globalConfigPath)) {\n config({ path: globalConfigPath, debug: false, quiet: true });\n}\n\n// Load .env from current directory (overrides global)\nconfig({ debug: false, quiet: true });\n\nconst program = new Command();\n\nprogram\n .name('sickbay')\n .description('React project health check CLI')\n .version(__VERSION__, '-v, --version')\n .enablePositionalOptions()\n .passThroughOptions()\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .option('--package <name>', 'scope to a single named package (monorepo only)')\n .option('--json', 'output raw JSON report')\n .option('--web', 'open web dashboard after scan')\n .option('--no-ai', 'disable AI features')\n .option('--no-quotes', 'suppress personality quotes in output')\n .option('--verbose', 'show verbose output')\n .action(async (options) => {\n // Validate --path exists before doing any I/O\n if (!existsSync(options.path)) {\n process.stderr.write(`Error: path does not exist: ${options.path}\\n`);\n process.exit(1);\n }\n\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n // Non-blocking update check\n const updatePromise = (async () => {\n try {\n const { checkForUpdate } = await import('./lib/update-check.js');\n return await checkForUpdate(__VERSION__);\n } catch {\n return null;\n }\n })();\n\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n\n const { detectMonorepo, runSickbay, runSickbayMonorepo, getAvailableChecks } =\n await import('sickbay-core');\n\n // Warn early if any --checks IDs don't match known check names\n if (checks && checks.length > 0) {\n const knownNames = new Set(getAvailableChecks().map((c) => c.name));\n const unknown = checks.filter((c: string) => !knownNames.has(c));\n if (unknown.length > 0) {\n process.stderr.write(`Warning: unknown check ID(s): ${unknown.join(', ')}\\n`);\n }\n }\n\n const monorepoInfo = await detectMonorepo(options.path);\n\n // --package flag: scope to a single named package within a monorepo\n if (options.package && monorepoInfo.isMonorepo) {\n const { readFileSync } = await import('fs');\n const targetPath = monorepoInfo.packagePaths.find((p) => {\n try {\n const pkg = JSON.parse(readFileSync(join(p, 'package.json'), 'utf-8'));\n return pkg.name === options.package || pkg.name?.endsWith(`/${options.package}`);\n } catch {\n return false;\n }\n });\n\n if (!targetPath) {\n process.stderr.write(`Package \"${options.package}\" not found in monorepo\\n`);\n process.exit(1);\n }\n\n if (options.json) {\n const report = await runSickbay({\n projectPath: targetPath,\n checks,\n verbose: options.verbose,\n quotes: options.quotes,\n });\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n process.exit(0);\n }\n\n render(\n React.createElement(App, {\n projectPath: targetPath,\n checks,\n openWeb: options.web,\n enableAI: options.ai !== false,\n verbose: options.verbose,\n quotes: options.quotes,\n updatePromise,\n }),\n );\n return;\n }\n\n if (options.json) {\n if (monorepoInfo.isMonorepo) {\n const report = await runSickbayMonorepo({\n projectPath: options.path,\n checks,\n verbose: options.verbose,\n quotes: options.quotes,\n });\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n process.exit(0);\n }\n\n const report = await runSickbay({\n projectPath: options.path,\n checks,\n verbose: options.verbose,\n quotes: options.quotes,\n });\n\n // Auto-save to trend history and last-report snapshot\n try {\n const { saveEntry, saveLastReport } = await import('./lib/history.js');\n saveEntry(report);\n saveLastReport(report);\n } catch {\n // Non-critical\n }\n\n // Cache dependency tree\n try {\n const { getDependencyTree } = await import('sickbay-core');\n const { saveDepTree } = await import('./lib/history.js');\n const tree = await getDependencyTree(options.path, report.projectInfo.packageManager);\n saveDepTree(options.path, tree);\n } catch {\n /* dep tree is optional */\n }\n\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n process.exit(0);\n }\n\n render(\n React.createElement(App, {\n projectPath: options.path,\n checks,\n openWeb: options.web,\n enableAI: options.ai !== false,\n verbose: options.verbose,\n quotes: options.quotes,\n isMonorepo: monorepoInfo.isMonorepo,\n updatePromise,\n }),\n );\n });\n\n// --- sickbay init ---\nprogram\n .command('init')\n .description('Initialize .sickbay/ folder and run an initial baseline scan')\n .option('-p, --path <path>', 'project path to initialize', process.cwd())\n .option(\n '--sync',\n 'add newly available checks to existing config without touching existing entries',\n )\n .option('--reset-config', 'regenerate config from scratch (overwrites existing)')\n .action(async (options) => {\n if (options.resetConfig) {\n const { generateConfigFile } = await import('./commands/init.js');\n await generateConfigFile(options.path, { force: true });\n return;\n }\n if (options.sync) {\n const { syncConfigFile } = await import('./commands/init.js');\n await syncConfigFile(options.path);\n return;\n }\n const { initSickbay } = await import('./commands/init.js');\n await initSickbay(options.path);\n });\n\n// --- sickbay fix ---\nprogram\n .command('fix')\n .description('Interactively fix issues found by sickbay scan')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--all', 'apply all available fixes without prompting')\n .option('--dry-run', 'show what would be fixed without executing')\n .option('--verbose', 'show verbose output')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const { FixApp } = await import('./components/FixApp.js');\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n render(\n React.createElement(FixApp, {\n projectPath,\n checks,\n applyAll: options.all ?? false,\n dryRun: options.dryRun ?? false,\n verbose: options.verbose ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay trend ---\nprogram\n .command('trend')\n .description('Show score history and trends over time')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-n, --last <count>', 'number of recent scans to show', '20')\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--json', 'output trend data as JSON')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { TrendApp } = await import('./components/TrendApp.js');\n render(\n React.createElement(TrendApp, {\n projectPath,\n last: parseInt(options.last, 10),\n jsonOutput: options.json ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay stats ---\nprogram\n .command('stats')\n .description('Show a quick codebase overview and project summary')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--json', 'output stats as JSON')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { StatsApp } = await import('./components/StatsApp.js');\n render(\n React.createElement(StatsApp, {\n projectPath,\n jsonOutput: options.json ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay tui ---\nprogram\n .command('tui')\n .description('Launch the persistent developer dashboard')\n .option('-p, --path <path>', 'project path to monitor', process.cwd())\n .option('--no-watch', 'disable file-watching auto-refresh')\n .option('--no-quotes', 'suppress personality quotes in output')\n .option('--refresh <seconds>', 'auto-refresh interval in seconds', '300')\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .action(async (options) => {\n const { TuiApp } = await import('./components/tui/TuiApp.js');\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n render(\n React.createElement(TuiApp, {\n projectPath: options.path,\n checks,\n watchEnabled: options.watch !== false,\n refreshInterval: parseInt(options.refresh, 10),\n quotes: options.quotes,\n }),\n { exitOnCtrlC: true },\n );\n });\n\n// --- sickbay doctor ---\nprogram\n .command('doctor')\n .description('Diagnose project setup and configuration issues')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--fix', 'auto-scaffold missing configuration files')\n .option('--json', 'output diagnostic results as JSON')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { DoctorApp } = await import('./components/DoctorApp.js');\n render(\n React.createElement(DoctorApp, {\n projectPath,\n autoFix: options.fix ?? false,\n jsonOutput: options.json ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay badge ---\nprogram\n .command('badge')\n .description('Generate a health score badge for your README')\n .option('-p, --path <path>', 'project path', process.cwd())\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--html', 'output HTML <img> tag instead of markdown')\n .option('--url', 'output bare badge URL only')\n .option('--label <text>', 'custom badge label', 'sickbay')\n .option('--scan', 'run a fresh scan instead of using last report')\n .action(async (options) => {\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } =\n await import('./commands/badge.js');\n\n let score = options.scan ? null : loadScoreFromLastReport(projectPath);\n\n if (score === null) {\n const { runSickbay } = await import('sickbay-core');\n const report = await runSickbay({ projectPath, quotes: false });\n\n try {\n const { saveEntry, saveLastReport } = await import('./lib/history.js');\n saveEntry(report);\n saveLastReport(report);\n } catch {\n // Non-critical\n }\n\n score = report.overallScore;\n }\n\n let output: string;\n if (options.url) {\n output = badgeUrl(score, options.label);\n } else if (options.html) {\n output = badgeHtml(score, options.label);\n } else {\n output = badgeMarkdown(score, options.label);\n }\n\n process.stdout.write(output + '\\n');\n process.exit(0);\n });\n\n// --- sickbay claude ---\nprogram\n .command('claude')\n .description('Generate a Claude Code skill file for your project')\n .option('-p, --path <path>', 'project path', process.cwd())\n .action(async (options) => {\n const { generateClaudeSkill } = await import('./commands/claude.js');\n generateClaudeSkill(options.path);\n });\n\n// --- sickbay diff ---\nprogram\n .command('diff <branch>')\n .description('Compare health score against another branch')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .option('--json', 'output diff as JSON')\n .option('--verbose', 'show verbose output')\n .action(async (branch, options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n\n const { DiffApp } = await import('./components/DiffApp.js');\n render(\n React.createElement(DiffApp, {\n projectPath: options.path,\n branch,\n jsonOutput: options.json ?? false,\n checks,\n verbose: options.verbose,\n }),\n );\n });\n\nprogram.parse();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["Spinner","formatDuration"],"sources":["../src/lib/issue-grouping.ts","../src/lib/messages.ts","../src/components/BestPractices.tsx","../src/components/ScoreBar.tsx","../src/components/CheckResult.tsx","../src/components/Header.tsx","../src/components/ProgressList.tsx","../src/components/QuickWins.tsx","../src/components/Summary.tsx","../src/components/UpdateNotice.tsx","../src/components/App.tsx","../src/index.ts"],"sourcesContent":["import type { CheckResult } from 'sickbay-core';\n\nexport function extractPatternStem(message: string): string {\n const idx = message.indexOf(' \\u2014 ');\n return idx >= 0 ? message.slice(idx + 3) : message;\n}\n\nexport function countUniqueIssues(checks: CheckResult[]): {\n critical: number;\n warnings: number;\n info: number;\n totalCritical: number;\n totalWarnings: number;\n totalInfo: number;\n} {\n const seen = { critical: new Set<string>(), warning: new Set<string>(), info: new Set<string>() };\n const totals = { critical: 0, warning: 0, info: 0 };\n\n for (const check of checks) {\n for (const issue of check.issues) {\n const stem = extractPatternStem(issue.message);\n const key = `${check.id}::${stem}`;\n seen[issue.severity].add(key);\n totals[issue.severity]++;\n }\n }\n\n return {\n critical: seen.critical.size,\n warnings: seen.warning.size,\n info: seen.info.size,\n totalCritical: totals.critical,\n totalWarnings: totals.warning,\n totalInfo: totals.info,\n };\n}\n","export const LOADING_MESSAGES = [\n 'Scanning for pre-existing conditions…',\n 'Counting packages… still counting…',\n 'Still here. Still scanning...',\n 'The unused dependencies know what they did...',\n 'Every unused export is a tiny cry for help...',\n \"Checking if 'TODO: fix later' was ever fixed later...\",\n 'Your secrets are safe with us. Unlike your .env file...',\n 'Good things take time. This is one of the good things. Probably...',\n 'npm audit found issues. npm audit --fix found different issues.',\n 'This is fine...',\n 'Evaluating life choices. Yours. Via package.json.',\n 'Almost done. (This is not a legally binding statement.)',\n 'node_modules: depth unknown. Will not attempt.',\n 'Performing checks. Results may vary...',\n];\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\nimport type { SickbayReport } from 'sickbay-core';\n\ninterface BestPracticesProps {\n report: SickbayReport;\n}\n\nexport function BestPractices({ report }: BestPracticesProps) {\n const recs = report.recommendations;\n if (!recs || recs.length === 0) return null;\n\n const sorted = [...recs].sort((a, b) => {\n const order = { recommend: 0, suggest: 1 };\n return order[a.severity] - order[b.severity];\n });\n\n const display = sorted.slice(0, 5);\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>💡 Advisor:</Text>\n {display.map((rec) => (\n <Box key={rec.id} marginLeft={2}>\n <Text color={rec.severity === 'recommend' ? 'yellow' : 'gray'}>\n {rec.severity === 'recommend' ? '● ' : '○ '}\n </Text>\n <Text bold>{rec.title}</Text>\n <Text dimColor> — {rec.message}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\n/**\n * Component to display a horizontal score bar representing the overall health score.\n * The bar is filled proportionally to the score and colored based on thresholds:\n * - Green for 80 and above\n * - Yellow for 60-79\n * - Red for below 60\n */\n\ninterface ScoreBarProps {\n score: number;\n width?: number;\n}\n\nexport function ScoreBar({ score, width = 20 }: ScoreBarProps) {\n const filled = Math.round((score / 100) * width);\n const empty = width - filled;\n const color = score >= 80 ? 'green' : score >= 60 ? 'yellow' : 'red';\n\n return (\n <Box>\n <Text color={color}>{'█'.repeat(filled)}</Text>\n <Text dimColor>{'░'.repeat(empty)}</Text>\n <Text color={color}> {score}/100</Text>\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\nimport { ScoreBar } from './ScoreBar.js';\n\nimport type { CheckResult as CheckResultType } from 'sickbay-core';\n\nconst STATUS_ICONS = {\n pass: '✓',\n warning: '⚠',\n fail: '✗',\n skipped: '○',\n};\n\nconst CATEGORY_ICONS: Record<string, string> = {\n dependencies: '📦',\n security: '✔',\n 'code-quality': '✔',\n performance: '⚡',\n git: '✔',\n};\n\ninterface CheckResultProps {\n result: CheckResultType;\n}\n\nexport function CheckResultRow({ result }: CheckResultProps) {\n const statusColor =\n result.status === 'pass'\n ? 'green'\n : result.status === 'fail'\n ? 'red'\n : result.status === 'skipped'\n ? 'gray'\n : 'yellow';\n const icon = CATEGORY_ICONS[result.category] ?? '•';\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text>{icon} </Text>\n <Text bold>{result.name}</Text>\n <Text dimColor> via {result.toolsUsed.join(', ')}</Text>\n </Box>\n <Box marginLeft={2}>\n <ScoreBar score={result.score} width={16} />\n <Text color={statusColor}>\n {' '}\n {STATUS_ICONS[result.status]} {result.status}\n </Text>\n </Box>\n {result.issues.slice(0, 3).map((issue) => (\n <Box key={`${issue.severity}-${issue.message}`} marginLeft={2}>\n <Text\n color={\n issue.severity === 'critical'\n ? 'red'\n : issue.severity === 'warning'\n ? 'yellow'\n : 'gray'\n }\n >\n {issue.severity === 'critical' ? ' ✗' : issue.severity === 'warning' ? ' ⚠' : ' ℹ'}{' '}\n {issue.message}\n </Text>\n </Box>\n ))}\n {result.issues.length > 3 && (\n <Box marginLeft={4}>\n <Text dimColor>... and {result.issues.length - 3} more</Text>\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\ndeclare const __VERSION__: string;\n\nconst ASCII_ART = `\n███████ ██ ██████ ██ ██ ██████ █████ ██ ██ \n██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n███████ ██ ██ █████ ██████ ███████ ████ \n ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ \n███████ ██ ██████ ██ ██ ██████ ██ ██ ██ \n\nA vitals health check for your app\n`.trim();\n\ninterface HeaderProps {\n projectName?: string;\n}\n\nexport function Header({ projectName }: HeaderProps) {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"green\">{ASCII_ART}</Text>\n <Box marginTop={1}>\n <Text dimColor> v{__VERSION__}</Text>\n </Box>\n {projectName && (\n <Box marginTop={1}>\n <Text dimColor> Analyzing </Text>\n <Text bold color=\"white\">\n {projectName}\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n","import React, { useState, useEffect } from 'react';\n\nimport { Box, Text } from 'ink';\n\nconst SPINNER_FRAMES = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];\n\nfunction Spinner() {\n const [frame, setFrame] = useState(0);\n useEffect(() => {\n const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), 80);\n return () => clearInterval(id);\n }, []);\n return <Text color=\"green\">{SPINNER_FRAMES[frame]}</Text>;\n}\n\ninterface ProgressItem {\n name: string;\n status: 'pending' | 'running' | 'done';\n}\n\ninterface ProgressListProps {\n items: ProgressItem[];\n}\n\nexport function ProgressList({ items }: ProgressListProps) {\n return (\n <Box flexDirection=\"column\">\n {items.map((item) => (\n <Box key={item.name}>\n {item.status === 'running' ? (\n <Spinner />\n ) : item.status === 'done' ? (\n <Text color=\"green\">✓</Text>\n ) : (\n <Text dimColor>○</Text>\n )}\n <Text> {item.name}</Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\nimport type { SickbayReport } from 'sickbay-core';\n\n/**\n * Component to display quick wins based on the report's issues that have fixes available.\n * It shows up to 5 fixable issues, sorted by severity (critical > warning > info).\n */\n\ninterface QuickWinsProps {\n report: SickbayReport;\n}\n\nfunction replacePackageManager(cmd: string, pm: string): string {\n if (pm === 'npm') return cmd;\n const install = pm === 'pnpm' ? 'pnpm add' : pm === 'yarn' ? 'yarn add' : 'bun add';\n const uninstall = pm === 'pnpm' ? 'pnpm remove' : pm === 'yarn' ? 'yarn remove' : 'bun remove';\n const update = pm === 'pnpm' ? 'pnpm update' : pm === 'yarn' ? 'yarn upgrade' : 'bun update';\n const auditFix =\n pm === 'pnpm' ? 'pnpm audit --fix' : pm === 'yarn' ? 'yarn npm audit --fix' : 'bun audit';\n return cmd\n .replace(/^npm install(?=\\s)/, install)\n .replace(/^npm uninstall(?=\\s)/, uninstall)\n .replace(/^npm update(?=\\s)/, update)\n .replace(/^npm audit fix/, auditFix);\n}\n\nexport function QuickWins({ report }: QuickWinsProps) {\n const pm = report.projectInfo?.packageManager ?? 'npm';\n const fixes = report.checks\n .flatMap((c) => c.issues)\n .filter((i) => i.fix?.command)\n .sort((a, b) => {\n const order = { critical: 0, warning: 1, info: 2 };\n return order[a.severity] - order[b.severity];\n })\n .slice(0, 5);\n\n if (fixes.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>🔥 Quick Wins:</Text>\n {fixes.map((fix) => (\n <Box key={`${fix.severity}-${fix.message}`} marginLeft={2}>\n <Text dimColor>→ </Text>\n <Text>{fix.fix!.description}</Text>\n {fix.fix!.command && (\n <Text dimColor>: {replacePackageManager(fix.fix!.command, pm)}</Text>\n )}\n </Box>\n ))}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\nimport { getScoreEmoji } from 'sickbay-core';\n\nimport { countUniqueIssues } from '../lib/issue-grouping.js';\nimport { ScoreBar } from './ScoreBar.js';\n\nimport type { SickbayReport } from 'sickbay-core';\n\n/**\n * Summary component displays the overall health score of the project along with a breakdown of critical issues, warnings, and info.\n * It uses the ScoreBar component to visually represent the overall score and color-codes the counts of issues based on severity.\n */\n\ninterface SummaryProps {\n report: SickbayReport;\n scanDuration?: number | null;\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n const seconds = ms / 1000;\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.round(seconds % 60);\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function Summary({ report, scanDuration }: SummaryProps) {\n const u = countUniqueIssues(report.checks);\n\n return (\n <Box flexDirection=\"column\">\n <Text dimColor>{'━'.repeat(52)}</Text>\n <Box marginTop={1}>\n <Text bold>Overall Health Score: </Text>\n <ScoreBar score={report.overallScore} width={12} />\n <Text> {getScoreEmoji(report.overallScore)}</Text>\n {scanDuration != null && <Text dimColor> {formatDuration(scanDuration)}</Text>}\n </Box>\n <Box marginTop={1}>\n <Text color=\"red\">\n {' '}\n ✗ {u.critical} critical\n {u.totalCritical > u.critical ? ` (${u.totalCritical} total)` : ''}\n </Text>\n <Text color=\"yellow\">\n {' '}\n ⚠ {u.warnings} warning{u.warnings !== 1 ? 's' : ''}\n {u.totalWarnings > u.warnings ? ` (${u.totalWarnings} total)` : ''}\n </Text>\n <Text color=\"gray\"> i {u.info} info</Text>\n </Box>\n {report.quote && (\n <Box marginTop={1}>\n <Text italic dimColor>\n \"{report.quote.text}\"\n </Text>\n <Text dimColor> — {report.quote.source}</Text>\n </Box>\n )}\n {report.config?.hasCustomConfig && (\n <Box marginTop={1}>\n <Text dimColor italic>\n Custom config active\n {report.config.disabledChecks.length > 0 &&\n ` (${report.config.disabledChecks.length} check${report.config.disabledChecks.length === 1 ? '' : 's'} disabled)`}\n </Text>\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\n\nimport { Box, Text } from 'ink';\n\ninterface UpdateNoticeProps {\n currentVersion: string;\n latestVersion: string;\n}\n\nexport function UpdateNotice({ currentVersion, latestVersion }: UpdateNoticeProps) {\n const line1 = `Update available: ${currentVersion} → ${latestVersion}`;\n const line2 = 'npx sickbay@latest (one-time run)';\n const line3 = 'npm i -g sickbay@latest (global install)';\n const maxLength = Math.max(line1.length, line2.length, line3.length);\n const padding = 2;\n const boxWidth = maxLength + padding * 2;\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"yellow\" dimColor>\n {`╭${'─'.repeat(boxWidth)}╮`}\n </Text>\n <Box paddingX={padding}>\n <Text color=\"yellow\" dimColor>\n {line1}\n </Text>\n </Box>\n <Box paddingX={padding}>\n <Text color=\"yellow\" dimColor>\n {line2}\n </Text>\n </Box>\n <Box paddingX={padding}>\n <Text color=\"yellow\" dimColor>\n {line3}\n </Text>\n </Box>\n <Text color=\"yellow\" dimColor>\n {`╰${'─'.repeat(boxWidth)}╯`}\n </Text>\n </Box>\n );\n}\n","import React, { useState, useEffect, useRef } from 'react';\n\nimport { Box, Text, useApp } from 'ink';\nimport Gradient from 'ink-gradient';\nimport Spinner from 'ink-spinner';\nimport { runSickbay, runSickbayMonorepo } from 'sickbay-core';\n\nimport { countUniqueIssues } from '../lib/issue-grouping.js';\nimport { LOADING_MESSAGES } from '../lib/messages.js';\nimport { BestPractices } from './BestPractices.js';\nimport { CheckResultRow } from './CheckResult.js';\nimport { Header } from './Header.js';\nimport { ProgressList } from './ProgressList.js';\nimport { QuickWins } from './QuickWins.js';\nimport { Summary } from './Summary.js';\nimport { UpdateNotice } from './UpdateNotice.js';\n\nimport type { UpdateInfo } from '../lib/update-check.js';\nimport type { SickbayReport, MonorepoReport, PackageReport } from 'sickbay-core';\n\ninterface AppProps {\n projectPath: string;\n checks?: string[];\n openWeb?: boolean;\n enableAI?: boolean;\n verbose?: boolean;\n quotes?: boolean;\n isMonorepo?: boolean;\n updatePromise?: Promise<UpdateInfo | null>;\n}\n\ntype Phase = 'loading' | 'results' | 'opening-web' | 'error';\n\ninterface ProgressItem {\n name: string;\n status: 'pending' | 'running' | 'done';\n}\n\nfunction scoreBar(score: number, width = 10): string {\n const filled = Math.round((score / 100) * width);\n return '█'.repeat(filled) + '░'.repeat(width - filled);\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n const seconds = ms / 1000;\n if (seconds < 60) return `${seconds.toFixed(1)}s`;\n const minutes = Math.floor(seconds / 60);\n const remainingSeconds = Math.round(seconds % 60);\n return `${minutes}m ${remainingSeconds}s`;\n}\n\nexport function App({\n projectPath,\n checks,\n openWeb,\n enableAI,\n verbose,\n quotes,\n isMonorepo,\n updatePromise,\n}: AppProps) {\n const { exit } = useApp();\n const [phase, setPhase] = useState<Phase>('loading');\n const [report, setReport] = useState<SickbayReport | null>(null);\n const [monorepoReport, setMonorepoReport] = useState<MonorepoReport | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [progress, setProgress] = useState<ProgressItem[]>([]);\n const [webUrl, setWebUrl] = useState<string | null>(null);\n const [projectName, setProjectName] = useState<string | undefined>();\n const [scanningPackage, setScanningPackage] = useState<string | undefined>();\n const [loadingMsgIdx, setLoadingMsgIdx] = useState(0);\n const [scanDuration, setScanDuration] = useState<number | null>(null);\n const [updateInfo, setUpdateInfo] = useState<UpdateInfo | null>(null);\n const hasRun = useRef(false);\n const scanStartTime = useRef<number>(0);\n\n useEffect(() => {\n if (!isMonorepo) return;\n const id = setInterval(() => {\n setLoadingMsgIdx((i) => (i + 1) % LOADING_MESSAGES.length);\n }, 4000);\n return () => clearInterval(id);\n }, [isMonorepo]);\n\n useEffect(() => {\n if (updatePromise) {\n updatePromise.then((info) => {\n if (info) setUpdateInfo(info);\n });\n }\n }, [updatePromise]);\n\n useEffect(() => {\n // Prevent double execution (React 18+ can run effects twice in dev/certain conditions)\n if (hasRun.current) return;\n hasRun.current = true;\n\n scanStartTime.current = Date.now();\n\n if (isMonorepo) {\n runSickbayMonorepo({\n projectPath,\n checks,\n verbose,\n quotes,\n onPackageStart: (name) => setScanningPackage(name),\n onPackageComplete: () => setScanningPackage(undefined),\n })\n .then(async (r) => {\n setScanDuration(Date.now() - scanStartTime.current);\n setMonorepoReport(r);\n setProjectName(`monorepo (${r.packages.length} packages)`);\n\n // Cache dependency tree for web dashboard\n try {\n const { getDependencyTree } = await import('sickbay-core');\n const { saveDepTree } = await import('../lib/history.js');\n const packages: Record<string, unknown> = {};\n for (const pkg of r.packages) {\n packages[pkg.name] = await getDependencyTree(pkg.path, r.packageManager);\n }\n saveDepTree(projectPath, { packages });\n } catch {\n /* dep tree is optional */\n }\n\n if (openWeb) {\n setPhase('opening-web');\n try {\n const { serveWeb } = await import('../commands/web.js');\n const { default: openBrowser } = await import('open');\n\n let aiService;\n if (enableAI && process.env.ANTHROPIC_API_KEY) {\n const { createAIService } = await import('../services/ai.js');\n aiService = createAIService(process.env.ANTHROPIC_API_KEY);\n }\n\n const url = await serveWeb(r, 3030, aiService);\n setWebUrl(url);\n await openBrowser(url);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setPhase('error');\n setTimeout(() => exit(), 100);\n }\n } else {\n setPhase('results');\n setTimeout(() => exit(), 100);\n }\n })\n .catch((err) => {\n setError(err.message ?? String(err));\n setPhase('error');\n setTimeout(() => exit(err), 100);\n });\n return;\n }\n\n runSickbay({\n projectPath,\n checks,\n verbose,\n quotes,\n onRunnersReady: (names) => {\n setProgress(names.map((name) => ({ name, status: 'pending' as const })));\n },\n onCheckStart: (name) => {\n setProgress((prev) => prev.map((p) => (p.name === name ? { ...p, status: 'running' } : p)));\n },\n onCheckComplete: (result) => {\n if (result.status === 'skipped') {\n setProgress((prev) => prev.filter((p) => p.name !== result.id));\n } else {\n setProgress((prev) =>\n prev.map((p) => (p.name === result.id ? { ...p, status: 'done' } : p)),\n );\n }\n },\n })\n .then(async (r) => {\n setScanDuration(Date.now() - scanStartTime.current);\n setProjectName(r.projectInfo.name);\n setReport(r);\n\n // Auto-save to trend history and last-report snapshot\n try {\n const { saveEntry, saveLastReport } = await import('../lib/history.js');\n saveEntry(r);\n saveLastReport(r);\n } catch {\n // Non-critical — silently ignore history save failures\n }\n\n // Cache dependency tree for web dashboard\n try {\n const { getDependencyTree } = await import('sickbay-core');\n const { saveDepTree } = await import('../lib/history.js');\n const tree = await getDependencyTree(projectPath, r.projectInfo.packageManager);\n saveDepTree(projectPath, tree);\n } catch {\n /* dep tree is optional, don't break the scan */\n }\n\n if (openWeb) {\n setPhase('opening-web');\n try {\n const { serveWeb } = await import('../commands/web.js');\n const { default: openBrowser } = await import('open');\n\n // Create AI service if enabled and API key exists\n let aiService;\n if (enableAI && process.env.ANTHROPIC_API_KEY) {\n const { createAIService } = await import('../services/ai.js');\n aiService = createAIService(process.env.ANTHROPIC_API_KEY);\n }\n\n const url = await serveWeb(r, 3030, aiService);\n setWebUrl(url);\n await openBrowser(url);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n setPhase('error');\n setTimeout(() => exit(), 100);\n return;\n }\n // Keep process alive — user closes with Ctrl+C\n } else {\n setPhase('results');\n setTimeout(() => exit(), 100);\n }\n })\n .catch((err) => {\n setError(err.message ?? String(err));\n setPhase('error');\n setTimeout(() => exit(err), 100);\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header projectName={projectName} />\n\n {updateInfo && (\n <UpdateNotice\n currentVersion={updateInfo.currentVersion}\n latestVersion={updateInfo.latestVersion}\n />\n )}\n\n {phase === 'loading' && (\n <Box flexDirection=\"column\">\n {isMonorepo ? (\n <Box flexDirection=\"column\">\n <Box>\n <Text color=\"magenta\">\n <Spinner type=\"dots\" />\n </Text>\n <Text dimColor> {LOADING_MESSAGES[loadingMsgIdx]}</Text>\n </Box>\n {scanningPackage && (\n <Box marginTop={1} marginLeft={2}>\n <Text dimColor>→ </Text>\n <Text color=\"cyan\">{scanningPackage}</Text>\n </Box>\n )}\n </Box>\n ) : (\n <Box flexDirection=\"column\">\n <Text dimColor>Running health checks...</Text>\n <Box marginTop={1} marginLeft={2}>\n <ProgressList items={progress} />\n </Box>\n </Box>\n )}\n </Box>\n )}\n\n {phase === 'error' && (\n <Box>\n <Text color=\"red\">✗ Error: {error}</Text>\n </Box>\n )}\n\n {phase === 'results' && monorepoReport && (\n <MonorepoSummaryTable report={monorepoReport} scanDuration={scanDuration} />\n )}\n\n {phase === 'results' && report && (\n <Box flexDirection=\"column\">\n {report.checks\n .filter((c) => c.status !== 'skipped')\n .map((check) => (\n <CheckResultRow key={check.id} result={check} />\n ))}\n <Summary report={report} scanDuration={scanDuration} />\n <QuickWins report={report} />\n <BestPractices report={report} />\n <Box marginTop={1}>\n <Text dimColor>View detailed report: </Text>\n <Text color=\"cyan\">sickbay --web</Text>\n </Box>\n </Box>\n )}\n\n {phase === 'opening-web' && (monorepoReport ?? report) && (\n <Box flexDirection=\"column\">\n {monorepoReport ? (\n <MonorepoSummaryTable report={monorepoReport} scanDuration={scanDuration} />\n ) : report ? (\n <>\n {report.checks\n .filter((c) => c.status !== 'skipped')\n .map((check) => (\n <CheckResultRow key={check.id} result={check} />\n ))}\n <Summary report={report} scanDuration={scanDuration} />\n </>\n ) : null}\n <Box marginTop={1}>\n {webUrl ? (\n <>\n <Text color=\"green\">✓ Dashboard running at </Text>\n <Text color=\"cyan\">{webUrl}</Text>\n <Text dimColor> (Ctrl+C to stop)</Text>\n </>\n ) : (\n <Text>\n <Text color=\"magenta\">\n <Spinner type=\"dots\" />\n </Text>{' '}\n <Gradient name=\"retro\">Launching dashboard with AI insights...</Gradient>\n </Text>\n )}\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n\nfunction MonorepoSummaryTable({\n report,\n scanDuration,\n}: {\n report: MonorepoReport;\n scanDuration: number | null;\n}) {\n const scoreColor = (score: number) => (score >= 80 ? 'green' : score >= 60 ? 'yellow' : 'red');\n\n return (\n <Box flexDirection=\"column\">\n <Box marginBottom={1}>\n <Text bold>Monorepo · </Text>\n <Text dimColor>{report.monorepoType} workspaces · </Text>\n <Text>{report.packages.length} packages</Text>\n </Box>\n {report.packages.map((pkg: PackageReport) => (\n <Box key={pkg.path} marginLeft={2} gap={1}>\n <Text color={scoreColor(pkg.score)}>{scoreBar(pkg.score)}</Text>\n <Text bold color={scoreColor(pkg.score)}>\n {String(pkg.score).padStart(3)}\n </Text>\n <Text>{pkg.name}</Text>\n <Text dimColor>{pkg.framework}</Text>\n {pkg.summary.critical > 0 && <Text color=\"red\"> {pkg.summary.critical} critical</Text>}\n </Box>\n ))}\n <Box marginTop={1} gap={2}>\n <Text bold>Overall: </Text>\n <Text color={scoreColor(report.overallScore)} bold>\n {report.overallScore}\n </Text>\n <Text dimColor>· </Text>\n {(() => {\n const u = countUniqueIssues(report.packages.flatMap((p) => p.checks));\n return (\n <>\n <Text color=\"red\">\n {u.critical} critical\n {u.totalCritical > u.critical ? ` (${u.totalCritical} total)` : ''}\n </Text>\n <Text dimColor>· </Text>\n <Text color=\"yellow\">\n {u.warnings} warnings\n {u.totalWarnings > u.warnings ? ` (${u.totalWarnings} total)` : ''}\n </Text>\n </>\n );\n })()}\n {scanDuration !== null && (\n <>\n <Text dimColor>· </Text>\n <Text dimColor>{formatDuration(scanDuration)}</Text>\n </>\n )}\n </Box>\n {report.quote && (\n <Box marginTop={1}>\n <Text italic dimColor>\n \"{report.quote.text}\"\n </Text>\n <Text dimColor> — {report.quote.source}</Text>\n </Box>\n )}\n <Box marginTop={1}>\n <Text dimColor>Per-package details: </Text>\n <Text color=\"cyan\">sickbay --web</Text>\n </Box>\n </Box>\n );\n}\n","#!/usr/bin/env node\nimport { existsSync } from 'fs';\nimport { homedir } from 'os';\nimport { join } from 'path';\n\nimport React from 'react';\n\nimport { Command } from 'commander';\nimport { config } from 'dotenv';\nimport { render } from 'ink';\n\nimport { App } from './components/App.js';\n\ndeclare const __VERSION__: string;\n\n/**\n * Entry point for the Sickbay CLI application.\n * This script sets up the command-line interface using Commander, loads environment variables, and renders the appropriate Ink components based on user commands.\n * It supports multiple commands including the default scan, trend analysis, stats overview, and a doctor command for diagnosing project issues.\n * Each command can output results in JSON format or render an interactive UI in the terminal.\n */\n\n// Load .env from global config first (~/.sickbay/.env)\nconst globalConfigPath = join(homedir(), '.sickbay', '.env');\nif (existsSync(globalConfigPath)) {\n config({ path: globalConfigPath, debug: false, quiet: true });\n}\n\n// Load .env from current directory (overrides global)\nconfig({ debug: false, quiet: true });\n\nconst program = new Command();\n\nprogram\n .name('sickbay')\n .description('React project health check CLI')\n .version(__VERSION__, '-v, --version')\n .enablePositionalOptions()\n .passThroughOptions()\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .option('--package <name>', 'scope to a single named package (monorepo only)')\n .option('--json', 'output raw JSON report')\n .option('--web', 'open web dashboard after scan')\n .option('--no-ai', 'disable AI features')\n .option('--no-quotes', 'suppress personality quotes in output')\n .option('--verbose', 'show verbose output')\n .action(async (options) => {\n // Validate --path exists before doing any I/O\n if (!existsSync(options.path)) {\n process.stderr.write(`Error: path does not exist: ${options.path}\\n`);\n process.exit(1);\n }\n\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n // Non-blocking update check\n const updatePromise = (async () => {\n try {\n const { checkForUpdate } = await import('./lib/update-check.js');\n return await checkForUpdate(__VERSION__);\n } catch {\n return null;\n }\n })();\n\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n\n const { detectMonorepo, runSickbay, runSickbayMonorepo, getAvailableChecks } =\n await import('sickbay-core');\n\n // Warn early if any --checks IDs don't match known check names\n if (checks && checks.length > 0) {\n const knownNames = new Set(getAvailableChecks().map((c) => c.name));\n const unknown = checks.filter((c: string) => !knownNames.has(c));\n if (unknown.length > 0) {\n process.stderr.write(`Warning: unknown check ID(s): ${unknown.join(', ')}\\n`);\n }\n }\n\n const monorepoInfo = await detectMonorepo(options.path);\n\n // --package flag: scope to a single named package within a monorepo\n if (options.package && monorepoInfo.isMonorepo) {\n const { readFileSync } = await import('fs');\n const targetPath = monorepoInfo.packagePaths.find((p) => {\n try {\n const pkg = JSON.parse(readFileSync(join(p, 'package.json'), 'utf-8'));\n return pkg.name === options.package || pkg.name?.endsWith(`/${options.package}`);\n } catch {\n return false;\n }\n });\n\n if (!targetPath) {\n process.stderr.write(`Package \"${options.package}\" not found in monorepo\\n`);\n process.exit(1);\n }\n\n if (options.json) {\n const report = await runSickbay({\n projectPath: targetPath,\n checks,\n verbose: options.verbose,\n quotes: options.quotes,\n });\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n process.exit(0);\n }\n\n render(\n React.createElement(App, {\n projectPath: targetPath,\n checks,\n openWeb: options.web,\n enableAI: options.ai !== false,\n verbose: options.verbose,\n quotes: options.quotes,\n updatePromise,\n }),\n );\n return;\n }\n\n if (options.json) {\n if (monorepoInfo.isMonorepo) {\n const report = await runSickbayMonorepo({\n projectPath: options.path,\n checks,\n verbose: options.verbose,\n quotes: options.quotes,\n });\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n process.exit(0);\n }\n\n const report = await runSickbay({\n projectPath: options.path,\n checks,\n verbose: options.verbose,\n quotes: options.quotes,\n });\n\n // Auto-save to trend history and last-report snapshot\n try {\n const { saveEntry, saveLastReport } = await import('./lib/history.js');\n saveEntry(report);\n saveLastReport(report);\n } catch {\n // Non-critical\n }\n\n // Cache dependency tree\n try {\n const { getDependencyTree } = await import('sickbay-core');\n const { saveDepTree } = await import('./lib/history.js');\n const tree = await getDependencyTree(options.path, report.projectInfo.packageManager);\n saveDepTree(options.path, tree);\n } catch {\n /* dep tree is optional */\n }\n\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n process.exit(0);\n }\n\n render(\n React.createElement(App, {\n projectPath: options.path,\n checks,\n openWeb: options.web,\n enableAI: options.ai !== false,\n verbose: options.verbose,\n quotes: options.quotes,\n isMonorepo: monorepoInfo.isMonorepo,\n updatePromise,\n }),\n );\n });\n\n// --- sickbay init ---\nprogram\n .command('init')\n .description('Initialize .sickbay/ folder and run an initial baseline scan')\n .option('-p, --path <path>', 'project path to initialize', process.cwd())\n .option(\n '--sync',\n 'add newly available checks to existing config without touching existing entries',\n )\n .option('--reset-config', 'regenerate config from scratch (overwrites existing)')\n .action(async (options) => {\n if (options.resetConfig) {\n const { generateConfigFile } = await import('./commands/init.js');\n await generateConfigFile(options.path, { force: true });\n return;\n }\n if (options.sync) {\n const { syncConfigFile } = await import('./commands/init.js');\n await syncConfigFile(options.path);\n return;\n }\n const { initSickbay } = await import('./commands/init.js');\n await initSickbay(options.path);\n });\n\n// --- sickbay fix ---\nprogram\n .command('fix')\n .description('Interactively fix issues found by sickbay scan')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--all', 'apply all available fixes without prompting')\n .option('--dry-run', 'show what would be fixed without executing')\n .option(\n '--skip-git-check',\n 'skip the uncommitted-changes warning before applying source-modifying fixes',\n )\n .option('--verbose', 'show verbose output')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const { FixApp } = await import('./components/FixApp.js');\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n render(\n React.createElement(FixApp, {\n projectPath,\n checks,\n applyAll: options.all ?? false,\n dryRun: options.dryRun ?? false,\n skipGitCheck: options.skipGitCheck ?? false,\n verbose: options.verbose ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay trend ---\nprogram\n .command('trend')\n .description('Show score history and trends over time')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-n, --last <count>', 'number of recent scans to show', '20')\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--json', 'output trend data as JSON')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { TrendApp } = await import('./components/TrendApp.js');\n render(\n React.createElement(TrendApp, {\n projectPath,\n last: parseInt(options.last, 10),\n jsonOutput: options.json ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay stats ---\nprogram\n .command('stats')\n .description('Show a quick codebase overview and project summary')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--json', 'output stats as JSON')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { StatsApp } = await import('./components/StatsApp.js');\n render(\n React.createElement(StatsApp, {\n projectPath,\n jsonOutput: options.json ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay tui ---\nprogram\n .command('tui')\n .description('Launch the persistent developer dashboard')\n .option('-p, --path <path>', 'project path to monitor', process.cwd())\n .option('--no-watch', 'disable file-watching auto-refresh')\n .option('--no-quotes', 'suppress personality quotes in output')\n .option('--refresh <seconds>', 'auto-refresh interval in seconds', '300')\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .action(async (options) => {\n const { TuiApp } = await import('./components/tui/TuiApp.js');\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n render(\n React.createElement(TuiApp, {\n projectPath: options.path,\n checks,\n watchEnabled: options.watch !== false,\n refreshInterval: parseInt(options.refresh, 10),\n quotes: options.quotes,\n }),\n { exitOnCtrlC: true },\n );\n });\n\n// --- sickbay doctor ---\nprogram\n .command('doctor')\n .description('Diagnose project setup and configuration issues')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--fix', 'auto-scaffold missing configuration files')\n .option('--json', 'output diagnostic results as JSON')\n .action(async (options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { DoctorApp } = await import('./components/DoctorApp.js');\n render(\n React.createElement(DoctorApp, {\n projectPath,\n autoFix: options.fix ?? false,\n jsonOutput: options.json ?? false,\n isMonorepo: resolution.isMonorepo && !resolution.targetPath,\n packagePaths: resolution.isMonorepo ? resolution.packagePaths : undefined,\n packageNames: resolution.isMonorepo ? resolution.packageNames : undefined,\n }),\n );\n });\n\n// --- sickbay badge ---\nprogram\n .command('badge')\n .description('Generate a health score badge for your README')\n .option('-p, --path <path>', 'project path', process.cwd())\n .option('--package <name>', 'scope to a single package (monorepo only)')\n .option('--html', 'output HTML <img> tag instead of markdown')\n .option('--url', 'output bare badge URL only')\n .option('--label <text>', 'custom badge label', 'sickbay')\n .option('--scan', 'run a fresh scan instead of using last report')\n .action(async (options) => {\n const { resolveProject } = await import('./lib/resolve-package.js');\n const resolution = await resolveProject(options.path, options.package);\n\n const projectPath = resolution.isMonorepo\n ? (resolution.targetPath ?? options.path)\n : resolution.targetPath;\n\n const { loadScoreFromLastReport, badgeUrl, badgeMarkdown, badgeHtml } =\n await import('./commands/badge.js');\n\n let score = options.scan ? null : loadScoreFromLastReport(projectPath);\n\n if (score === null) {\n const { runSickbay } = await import('sickbay-core');\n const report = await runSickbay({ projectPath, quotes: false });\n\n try {\n const { saveEntry, saveLastReport } = await import('./lib/history.js');\n saveEntry(report);\n saveLastReport(report);\n } catch {\n // Non-critical\n }\n\n score = report.overallScore;\n }\n\n let output: string;\n if (options.url) {\n output = badgeUrl(score, options.label);\n } else if (options.html) {\n output = badgeHtml(score, options.label);\n } else {\n output = badgeMarkdown(score, options.label);\n }\n\n process.stdout.write(output + '\\n');\n process.exit(0);\n });\n\n// --- sickbay claude ---\nprogram\n .command('claude')\n .description('Generate a Claude Code skill file for your project')\n .option('-p, --path <path>', 'project path', process.cwd())\n .action(async (options) => {\n const { generateClaudeSkill } = await import('./commands/claude.js');\n generateClaudeSkill(options.path);\n });\n\n// --- sickbay diff ---\nprogram\n .command('diff <branch>')\n .description('Compare health score against another branch')\n .option('-p, --path <path>', 'project path to analyze', process.cwd())\n .option('-c, --checks <checks>', 'comma-separated list of checks to run')\n .option('--json', 'output diff as JSON')\n .option('--verbose', 'show verbose output')\n .action(async (branch, options) => {\n // Load .env from project path if it differs from cwd\n if (options.path && options.path !== process.cwd()) {\n const projectEnvPath = join(options.path, '.env');\n if (existsSync(projectEnvPath)) {\n config({ path: projectEnvPath, override: true });\n }\n }\n\n const checks = options.checks\n ? options.checks.split(',').map((s: string) => s.trim())\n : undefined;\n\n const { DiffApp } = await import('./components/DiffApp.js');\n render(\n React.createElement(DiffApp, {\n projectPath: options.path,\n branch,\n jsonOutput: options.json ?? false,\n checks,\n verbose: options.verbose,\n }),\n );\n });\n\nprogram.parse();\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as getAvailableChecks, d as runSickbayMonorepo, i as detectMonorepo, r as detectContext, u as runSickbay } from "./dist-Bjhxbcak.js";
|
|
2
|
-
import { i as saveEntry } from "./history-
|
|
2
|
+
import { i as saveEntry } from "./history-C9hu3f6s.js";
|
|
3
3
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
//#region src/commands/init.ts
|
|
@@ -196,4 +196,4 @@ async function initSickbay(projectPath) {
|
|
|
196
196
|
//#endregion
|
|
197
197
|
export { generateConfigFile, initSickbay, syncConfigFile };
|
|
198
198
|
|
|
199
|
-
//# sourceMappingURL=init-
|
|
199
|
+
//# sourceMappingURL=init-Czn8P7An.js.map
|