sickbay 1.14.3 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Header
3
- } from "./chunk-QM2YFOB3.js";
3
+ } from "./chunk-SC444YPU.js";
4
4
  import "./chunk-JSBRDJBE.js";
5
5
 
6
6
  // src/components/DiffApp.tsx
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-RH2MTL2L.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-QM2YFOB3.js";
6
+ } from "./chunk-SC444YPU.js";
7
7
  import {
8
8
  detectPackageManager,
9
9
  detectProject
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-MBVA75EM.js";
7
7
  import {
8
8
  Header
9
- } from "./chunk-QM2YFOB3.js";
9
+ } from "./chunk-SC444YPU.js";
10
10
  import {
11
11
  runSickbay
12
12
  } from "./chunk-CYUCJO47.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-RH2MTL2L.js";
4
4
  import {
5
5
  Header
6
- } from "./chunk-QM2YFOB3.js";
6
+ } from "./chunk-SC444YPU.js";
7
7
  import {
8
8
  detectProject
9
9
  } from "./chunk-CYUCJO47.js";
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-RH2MTL2L.js";
8
8
  import {
9
9
  Header
10
- } from "./chunk-QM2YFOB3.js";
10
+ } from "./chunk-SC444YPU.js";
11
11
  import "./chunk-CYUCJO47.js";
12
12
  import {
13
13
  detectRegressions,
@@ -690,7 +690,7 @@ function TuiApp({
690
690
  return () => timers.forEach(clearTimeout);
691
691
  }, []);
692
692
  useEffect7(() => {
693
- checkForUpdate("1.14.2").then((info) => {
693
+ checkForUpdate("1.14.3").then((info) => {
694
694
  if (info) setUpdateInfo(info);
695
695
  });
696
696
  }, []);
@@ -11,7 +11,7 @@ var ASCII_ART = `
11
11
  A vitals health check for your app
12
12
  `.trim();
13
13
  function Header({ projectName }) {
14
- return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.14.2")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "white" }, projectName)));
14
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React.createElement(Text, { color: "green" }, ASCII_ART), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " v", "1.14.3")), projectName && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, " Analyzing "), /* @__PURE__ */ React.createElement(Text, { bold: true, color: "white" }, projectName)));
15
15
  }
16
16
 
17
17
  export {
@@ -0,0 +1,118 @@
1
+ import "./chunk-JSBRDJBE.js";
2
+
3
+ // src/commands/claude.ts
4
+ import { mkdirSync, writeFileSync } from "fs";
5
+ import { join } from "path";
6
+ var SKILL_CONTENT = `---
7
+ name: sickbay
8
+ description: Understand Sickbay health reports, scores, issues, config, and CLI commands
9
+ ---
10
+
11
+ # Sickbay \u2014 Project Health Reports
12
+
13
+ Sickbay is a zero-config health check CLI for JS/TS projects. It produces structured
14
+ JSON reports scoring a project across five categories. Use this skill when you encounter
15
+ \`.sickbay/\` files, \`sickbay.config.ts\`, or when asked to interpret health results.
16
+
17
+ ## Report Locations
18
+
19
+ | File | Purpose |
20
+ |------|---------|
21
+ | \`.sickbay/last-report.json\` | Most recent scan result |
22
+ | \`.sickbay/baseline.json\` | Committed team baseline (created by \`sickbay init\`) |
23
+ | \`.sickbay/history.json\` | Local trend history (gitignored) |
24
+
25
+ ## Report Schema
26
+
27
+ \`\`\`ts
28
+ interface SickbayReport {
29
+ overallScore: number; // 0-100 weighted average
30
+ checks: CheckResult[]; // individual check results
31
+ summary: { critical: number; warnings: number; info: number };
32
+ projectInfo: { name, framework, packageManager, totalDependencies, ... };
33
+ }
34
+
35
+ interface CheckResult {
36
+ id: string; // e.g. "knip", "npm-audit", "complexity"
37
+ category: "dependencies" | "security" | "code-quality" | "performance" | "git";
38
+ score: number; // 0-100
39
+ status: "pass" | "warning" | "fail" | "skipped";
40
+ issues: Issue[];
41
+ }
42
+
43
+ interface Issue {
44
+ severity: "critical" | "warning" | "info";
45
+ message: string;
46
+ file?: string; // affected file path
47
+ fix?: {
48
+ command?: string; // shell command to run
49
+ description: string; // human-readable fix
50
+ codeChange?: { before: string; after: string };
51
+ };
52
+ }
53
+ \`\`\`
54
+
55
+ ## Score Interpretation
56
+
57
+ | Range | Rating | Color |
58
+ |-------|--------|-------|
59
+ | 80-100 | Good | Green |
60
+ | 60-79 | Fair | Yellow |
61
+ | 0-59 | Needs work | Red |
62
+
63
+ Category weights: security 30%, dependencies 25%, code-quality 25%, performance 15%, git 5%.
64
+
65
+ ## Acting on Issues
66
+
67
+ 1. **Read the report**: parse \`.sickbay/last-report.json\`
68
+ 2. **Prioritize**: fix \`critical\` severity issues first
69
+ 3. **Use fix suggestions**: if \`issue.fix.command\` exists, run it; if \`issue.fix.codeChange\` exists, apply the diff
70
+ 4. **Verify**: re-run \`sickbay\` to confirm the score improved
71
+
72
+ ## Configuration (\`sickbay.config.ts\`)
73
+
74
+ \`\`\`ts
75
+ export default {
76
+ checks: {
77
+ knip: true, // enable (default)
78
+ 'source-map-explorer': false, // disable entirely
79
+ 'npm-audit': {
80
+ suppress: [ // hide accepted findings (improves score)
81
+ { match: 'lodash', reason: 'pinned, CVE does not affect us' },
82
+ ],
83
+ },
84
+ complexity: {
85
+ thresholds: { general: 15 }, // override default thresholds
86
+ },
87
+ },
88
+ exclude: ['dist/**', 'coverage/**'], // global file exclusions
89
+ weights: { security: 0.4 }, // override category weights
90
+ }
91
+ \`\`\`
92
+
93
+ ## CLI Commands
94
+
95
+ | Command | Purpose |
96
+ |---------|---------|
97
+ | \`sickbay\` | Run a full scan (terminal UI) |
98
+ | \`sickbay --json\` | Output raw JSON report |
99
+ | \`sickbay --web\` | Open web dashboard after scan |
100
+ | \`sickbay fix\` | Interactively apply fix suggestions |
101
+ | \`sickbay diff <branch>\` | Compare score against another branch |
102
+ | \`sickbay trend\` | Show score history over time |
103
+ | \`sickbay init\` | Scaffold config + baseline |
104
+ | \`sickbay doctor\` | Diagnose project setup issues |
105
+ | \`sickbay badge\` | Generate a README health badge |
106
+ | \`sickbay stats\` | Quick codebase overview |
107
+ `;
108
+ function generateClaudeSkill(projectPath) {
109
+ const skillsDir = join(projectPath, ".claude", "skills");
110
+ mkdirSync(skillsDir, { recursive: true });
111
+ const skillPath = join(skillsDir, "sickbay.md");
112
+ writeFileSync(skillPath, SKILL_CONTENT);
113
+ console.log(`Created ${skillPath}`);
114
+ console.log("\nClaude Code will now understand your Sickbay reports, config, and CLI commands.");
115
+ }
116
+ export {
117
+ generateClaudeSkill
118
+ };
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-TYG7ZQBP.js";
9
9
  import {
10
10
  Header
11
- } from "./chunk-QM2YFOB3.js";
11
+ } from "./chunk-SC444YPU.js";
12
12
  import {
13
13
  getScoreEmoji,
14
14
  runSickbay,
@@ -304,7 +304,7 @@ if (existsSync(globalConfigPath)) {
304
304
  }
305
305
  config({ debug: false, quiet: true });
306
306
  var program = new Command();
307
- program.name("sickbay").description("React project health check CLI").version("1.14.2", "-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) => {
307
+ program.name("sickbay").description("React project health check CLI").version("1.14.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) => {
308
308
  if (options.path && options.path !== process.cwd()) {
309
309
  const projectEnvPath = join(options.path, ".env");
310
310
  if (existsSync(projectEnvPath)) {
@@ -314,7 +314,7 @@ program.name("sickbay").description("React project health check CLI").version("1
314
314
  const updatePromise = (async () => {
315
315
  try {
316
316
  const { checkForUpdate } = await import("./update-check-QLG6GA4Z.js");
317
- return await checkForUpdate("1.14.2");
317
+ return await checkForUpdate("1.14.3");
318
318
  } catch {
319
319
  return null;
320
320
  }
@@ -432,7 +432,7 @@ program.command("fix").description("Interactively fix issues found by sickbay sc
432
432
  }
433
433
  const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
434
434
  const resolution = await resolveProject(options.path, options.package);
435
- const { FixApp } = await import("./FixApp-BX5LBIOP.js");
435
+ const { FixApp } = await import("./FixApp-KWZGPY7S.js");
436
436
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
437
437
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
438
438
  render(
@@ -458,7 +458,7 @@ program.command("trend").description("Show score history and trends over time").
458
458
  const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
459
459
  const resolution = await resolveProject(options.path, options.package);
460
460
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
461
- const { TrendApp } = await import("./TrendApp-EM6DST33.js");
461
+ const { TrendApp } = await import("./TrendApp-SD3RNUWW.js");
462
462
  render(
463
463
  React6.createElement(TrendApp, {
464
464
  projectPath,
@@ -480,7 +480,7 @@ program.command("stats").description("Show a quick codebase overview and project
480
480
  const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
481
481
  const resolution = await resolveProject(options.path, options.package);
482
482
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
483
- const { StatsApp } = await import("./StatsApp-WQAEKOY6.js");
483
+ const { StatsApp } = await import("./StatsApp-FB2D43F4.js");
484
484
  render(
485
485
  React6.createElement(StatsApp, {
486
486
  projectPath,
@@ -492,7 +492,7 @@ program.command("stats").description("Show a quick codebase overview and project
492
492
  );
493
493
  });
494
494
  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) => {
495
- const { TuiApp } = await import("./TuiApp-QXEQ7VC4.js");
495
+ const { TuiApp } = await import("./TuiApp-TY43I636.js");
496
496
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
497
497
  render(
498
498
  React6.createElement(TuiApp, {
@@ -515,7 +515,7 @@ program.command("doctor").description("Diagnose project setup and configuration
515
515
  const { resolveProject } = await import("./resolve-package-WMVAEA6D.js");
516
516
  const resolution = await resolveProject(options.path, options.package);
517
517
  const projectPath = resolution.isMonorepo ? resolution.targetPath ?? options.path : resolution.targetPath;
518
- const { DoctorApp } = await import("./DoctorApp-JUMQMGJD.js");
518
+ const { DoctorApp } = await import("./DoctorApp-IH7C6S5J.js");
519
519
  render(
520
520
  React6.createElement(DoctorApp, {
521
521
  projectPath,
@@ -555,6 +555,10 @@ program.command("badge").description("Generate a health score badge for your REA
555
555
  process.stdout.write(output + "\n");
556
556
  process.exit(0);
557
557
  });
558
+ program.command("claude").description("Generate a Claude Code skill file for your project").option("-p, --path <path>", "project path", process.cwd()).action(async (options) => {
559
+ const { generateClaudeSkill } = await import("./claude-MGZYWSIQ.js");
560
+ generateClaudeSkill(options.path);
561
+ });
558
562
  program.command("diff <branch>").description("Compare health score against another branch").option("-p, --path <path>", "project path to analyze", process.cwd()).option("-c, --checks <checks>", "comma-separated list of checks to run").option("--json", "output diff as JSON").option("--verbose", "show verbose output").action(async (branch, options) => {
559
563
  if (options.path && options.path !== process.cwd()) {
560
564
  const projectEnvPath = join(options.path, ".env");
@@ -563,7 +567,7 @@ program.command("diff <branch>").description("Compare health score against anoth
563
567
  }
564
568
  }
565
569
  const checks = options.checks ? options.checks.split(",").map((s) => s.trim()) : void 0;
566
- const { DiffApp } = await import("./DiffApp-XTG4L4FO.js");
570
+ const { DiffApp } = await import("./DiffApp-3MJBZD76.js");
567
571
  render(
568
572
  React6.createElement(DiffApp, {
569
573
  projectPath: options.path,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sickbay",
3
- "version": "1.14.3",
3
+ "version": "1.15.0",
4
4
  "description": "Zero-config health check CLI for JavaScript and TypeScript projects",
5
5
  "license": "MIT",
6
6
  "repository": {