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.
- package/dist/{DiffApp-XTG4L4FO.js → DiffApp-3MJBZD76.js} +1 -1
- package/dist/{DoctorApp-JUMQMGJD.js → DoctorApp-IH7C6S5J.js} +1 -1
- package/dist/{FixApp-BX5LBIOP.js → FixApp-KWZGPY7S.js} +1 -1
- package/dist/{StatsApp-WQAEKOY6.js → StatsApp-FB2D43F4.js} +1 -1
- package/dist/{TrendApp-EM6DST33.js → TrendApp-SD3RNUWW.js} +1 -1
- package/dist/{TuiApp-QXEQ7VC4.js → TuiApp-TY43I636.js} +1 -1
- package/dist/{chunk-QM2YFOB3.js → chunk-SC444YPU.js} +1 -1
- package/dist/claude-MGZYWSIQ.js +118 -0
- package/dist/index.js +13 -9
- package/package.json +1 -1
|
@@ -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.
|
|
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-
|
|
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.
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
570
|
+
const { DiffApp } = await import("./DiffApp-3MJBZD76.js");
|
|
567
571
|
render(
|
|
568
572
|
React6.createElement(DiffApp, {
|
|
569
573
|
projectPath: options.path,
|