@cynicalsally/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +332 -0
  3. package/dist/commands/login.d.ts +3 -0
  4. package/dist/commands/login.d.ts.map +1 -0
  5. package/dist/commands/login.js +54 -0
  6. package/dist/commands/login.js.map +1 -0
  7. package/dist/commands/logout.d.ts +3 -0
  8. package/dist/commands/logout.d.ts.map +1 -0
  9. package/dist/commands/logout.js +15 -0
  10. package/dist/commands/logout.js.map +1 -0
  11. package/dist/commands/mcp.d.ts +3 -0
  12. package/dist/commands/mcp.d.ts.map +1 -0
  13. package/dist/commands/mcp.js +47 -0
  14. package/dist/commands/mcp.js.map +1 -0
  15. package/dist/commands/results.d.ts +3 -0
  16. package/dist/commands/results.d.ts.map +1 -0
  17. package/dist/commands/results.js +60 -0
  18. package/dist/commands/results.js.map +1 -0
  19. package/dist/commands/roast.d.ts +3 -0
  20. package/dist/commands/roast.d.ts.map +1 -0
  21. package/dist/commands/roast.js +233 -0
  22. package/dist/commands/roast.js.map +1 -0
  23. package/dist/commands/tools.d.ts +8 -0
  24. package/dist/commands/tools.d.ts.map +1 -0
  25. package/dist/commands/tools.js +460 -0
  26. package/dist/commands/tools.js.map +1 -0
  27. package/dist/commands/upgrade.d.ts +3 -0
  28. package/dist/commands/upgrade.d.ts.map +1 -0
  29. package/dist/commands/upgrade.js +82 -0
  30. package/dist/commands/upgrade.js.map +1 -0
  31. package/dist/commands/usage.d.ts +3 -0
  32. package/dist/commands/usage.d.ts.map +1 -0
  33. package/dist/commands/usage.js +87 -0
  34. package/dist/commands/usage.js.map +1 -0
  35. package/dist/index.d.ts +3 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +60 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/mcp-server.d.ts +12 -0
  40. package/dist/mcp-server.d.ts.map +1 -0
  41. package/dist/mcp-server.js +266 -0
  42. package/dist/mcp-server.js.map +1 -0
  43. package/dist/utils/api.d.ts +108 -0
  44. package/dist/utils/api.d.ts.map +1 -0
  45. package/dist/utils/api.js +79 -0
  46. package/dist/utils/api.js.map +1 -0
  47. package/dist/utils/background.d.ts +9 -0
  48. package/dist/utils/background.d.ts.map +1 -0
  49. package/dist/utils/background.js +91 -0
  50. package/dist/utils/background.js.map +1 -0
  51. package/dist/utils/config.d.ts +13 -0
  52. package/dist/utils/config.d.ts.map +1 -0
  53. package/dist/utils/config.js +65 -0
  54. package/dist/utils/config.js.map +1 -0
  55. package/dist/utils/files.d.ts +14 -0
  56. package/dist/utils/files.d.ts.map +1 -0
  57. package/dist/utils/files.js +141 -0
  58. package/dist/utils/files.js.map +1 -0
  59. package/dist/utils/flavor.d.ts +48 -0
  60. package/dist/utils/flavor.d.ts.map +1 -0
  61. package/dist/utils/flavor.js +79 -0
  62. package/dist/utils/flavor.js.map +1 -0
  63. package/dist/utils/git.d.ts +29 -0
  64. package/dist/utils/git.d.ts.map +1 -0
  65. package/dist/utils/git.js +90 -0
  66. package/dist/utils/git.js.map +1 -0
  67. package/dist/utils/output.d.ts +5 -0
  68. package/dist/utils/output.d.ts.map +1 -0
  69. package/dist/utils/output.js +206 -0
  70. package/dist/utils/output.js.map +1 -0
  71. package/dist/utils/report.d.ts +12 -0
  72. package/dist/utils/report.d.ts.map +1 -0
  73. package/dist/utils/report.js +190 -0
  74. package/dist/utils/report.js.map +1 -0
  75. package/package.json +54 -0
@@ -0,0 +1,90 @@
1
+ import { execSync } from "node:child_process";
2
+ /**
3
+ * Check if we're inside a git repository.
4
+ */
5
+ export function isGitRepo() {
6
+ try {
7
+ execSync("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ /**
15
+ * Get staged changes as a unified diff.
16
+ */
17
+ export function getStagedChanges() {
18
+ return execSync("git diff --cached", { encoding: "utf-8", maxBuffer: 5_000_000 });
19
+ }
20
+ /**
21
+ * Get unstaged (working directory) changes as a unified diff.
22
+ */
23
+ export function getUnstagedChanges() {
24
+ return execSync("git diff", { encoding: "utf-8", maxBuffer: 5_000_000 });
25
+ }
26
+ /**
27
+ * Get the last commit as a unified diff.
28
+ */
29
+ export function getLastCommitDiff() {
30
+ return execSync("git diff HEAD~1..HEAD", { encoding: "utf-8", maxBuffer: 5_000_000 });
31
+ }
32
+ /**
33
+ * Get branch diff (current branch vs target branch).
34
+ */
35
+ export function getBranchDiff(branch) {
36
+ // Sanitize branch name to prevent command injection
37
+ const safeBranch = branch.replace(/[^a-zA-Z0-9_.\-/]/g, "");
38
+ return execSync(`git diff ${safeBranch}...HEAD`, {
39
+ encoding: "utf-8",
40
+ maxBuffer: 5_000_000,
41
+ });
42
+ }
43
+ /**
44
+ * Parse a unified diff into a files array for the API.
45
+ *
46
+ * Extracts the changed files and their full content from the diff.
47
+ * For new/modified files, includes the "after" state.
48
+ */
49
+ export function parseDiffToFiles(diff) {
50
+ if (!diff.trim())
51
+ return [];
52
+ const files = [];
53
+ const chunks = diff.split(/^diff --git /m).filter(Boolean);
54
+ for (const chunk of chunks) {
55
+ try {
56
+ const headerMatch = chunk.match(/^a\/(.+?) b\/(.+)/m);
57
+ if (!headerMatch || !headerMatch[2])
58
+ continue;
59
+ const filePath = headerMatch[2].trim();
60
+ if (!filePath)
61
+ continue;
62
+ // Skip deleted files and binary files
63
+ if (chunk.includes("deleted file mode"))
64
+ continue;
65
+ if (chunk.includes("Binary files"))
66
+ continue;
67
+ const lines = chunk.split("\n");
68
+ const contentLines = [];
69
+ for (const line of lines) {
70
+ if (line.startsWith("+++"))
71
+ continue;
72
+ if (line.startsWith("+")) {
73
+ contentLines.push(line.slice(1));
74
+ }
75
+ }
76
+ if (contentLines.length > 0) {
77
+ files.push({
78
+ path: filePath,
79
+ content: contentLines.join("\n"),
80
+ });
81
+ }
82
+ }
83
+ catch {
84
+ // Skip malformed chunks silently
85
+ continue;
86
+ }
87
+ }
88
+ return files;
89
+ }
90
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type RoastResponse } from "./api.js";
2
+ export declare function printSally(): void;
3
+ export declare function handleApiError(err: unknown): void;
4
+ export declare function displayRoast(response: RoastResponse): void;
5
+ //# sourceMappingURL=output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,KAAK,aAAa,EAAmB,MAAM,UAAU,CAAC;AAMzE,wBAAgB,UAAU,IAAI,IAAI,CAgBjC;AAmFD,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAejD;AAMD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAuG1D"}
@@ -0,0 +1,206 @@
1
+ import chalk from "chalk";
2
+ import { ApiError } from "./api.js";
3
+ // ---------------------------------------------------------------------------
4
+ // Sally ASCII Art
5
+ // ---------------------------------------------------------------------------
6
+ export function printSally() {
7
+ const h = chalk.hex("#8B6914"); // hair
8
+ const f = chalk.hex("#F5D6B8"); // skin
9
+ const g = chalk.gray; // glasses + blazer
10
+ const w = chalk.white; // eyes
11
+ console.log(h(" ▄██████▄"));
12
+ console.log(h(" ████████████"));
13
+ console.log(h(" ██") + f("██████████"));
14
+ console.log(h(" █") + f("█") + g("┌──┐") + f("██") + g("┌──┐") + f("█"));
15
+ console.log(h(" █") + f("█") + g("│") + w("◔ ") + g("│") + f("██") + g("│") + w("◔ ") + g("│") + f("█"));
16
+ console.log(h(" ") + f("█") + g("└──┘") + f("██") + g("└──┘") + f("█"));
17
+ console.log(" " + f("████████████"));
18
+ console.log(" " + f("███") + chalk.hex("#CC8888")("━") + f("████"));
19
+ console.log(" " + g("▓▓▓▓▓▓▓▓"));
20
+ console.log(" " + g("▓▓▓▓▓▓▓▓▓▓"));
21
+ }
22
+ // ---------------------------------------------------------------------------
23
+ // Helpers
24
+ // ---------------------------------------------------------------------------
25
+ const TERMINAL_WIDTH = Math.min(process.stdout.columns || 80, 90);
26
+ const CONTENT_WIDTH = TERMINAL_WIDTH - 6; // 4 indent + 2 margin
27
+ function colorScore(score) {
28
+ const formatted = score.toFixed(1);
29
+ if (score < 4)
30
+ return chalk.red.bold(formatted);
31
+ if (score < 7)
32
+ return chalk.yellow.bold(formatted);
33
+ return chalk.green.bold(formatted);
34
+ }
35
+ function scoreBar(score) {
36
+ const filled = Math.round(score);
37
+ const empty = 10 - filled;
38
+ const bar = chalk.magenta("\u2588".repeat(filled)) + chalk.gray("\u2591".repeat(empty));
39
+ return `[${bar}]`;
40
+ }
41
+ function colorSeverity(severity) {
42
+ switch (severity) {
43
+ case "critical": return chalk.red.bold("CRITICAL");
44
+ case "major": return chalk.yellow.bold("MAJOR");
45
+ case "minor": return chalk.gray("minor");
46
+ default: return chalk.gray(severity);
47
+ }
48
+ }
49
+ /** Highlight `backtick` code references in cyan */
50
+ function highlightCode(text) {
51
+ return text.replace(/`([^`]+)`/g, (_, code) => chalk.cyan(`\`${code}\``));
52
+ }
53
+ /** Wrap text to fit terminal width, preserving indent */
54
+ function wrapText(text, indent, width) {
55
+ const words = text.split(/\s+/);
56
+ const lines = [];
57
+ let current = "";
58
+ for (const word of words) {
59
+ // Strip chalk codes for length calculation
60
+ const plainCurrent = current.replace(/\x1b\[[0-9;]*m/g, "");
61
+ const plainWord = word.replace(/\x1b\[[0-9;]*m/g, "");
62
+ if (plainCurrent.length + plainWord.length + 1 > width && current) {
63
+ lines.push(indent + current);
64
+ current = word;
65
+ }
66
+ else {
67
+ current = current ? current + " " + word : word;
68
+ }
69
+ }
70
+ if (current)
71
+ lines.push(indent + current);
72
+ return lines;
73
+ }
74
+ function divider() {
75
+ console.log(chalk.gray(" " + "\u2500".repeat(Math.min(56, TERMINAL_WIDTH - 4))));
76
+ }
77
+ function printWrapped(text, indent = " ", color = chalk.white) {
78
+ const highlighted = highlightCode(text);
79
+ const lines = wrapText(highlighted, "", CONTENT_WIDTH);
80
+ for (const line of lines) {
81
+ console.log(color(indent + line));
82
+ }
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Shared error handling (#6: consistent across roast + tools)
86
+ // ---------------------------------------------------------------------------
87
+ function printUpgradePrompt() {
88
+ console.log(chalk.magenta.bold(" Full Suite") + chalk.gray(" — everything Sally has to offer:\n"));
89
+ console.log(chalk.gray(" •") + chalk.white(" 500 Quick Roasts + 100 Full Truth deep-dives/month"));
90
+ console.log(chalk.gray(" •") + chalk.white(" Unlimited explain, refactor, review-pr, brainstorm, frontend, marketing"));
91
+ console.log(chalk.gray(" •") + chalk.white(" Sally's coffee-powered priority processing\n"));
92
+ console.log(chalk.gray(" Run ") + chalk.cyan("sally upgrade") + chalk.gray(" — your code isn't going to review itself.\n"));
93
+ }
94
+ export function handleApiError(err) {
95
+ if (err instanceof ApiError) {
96
+ console.log(chalk.red(`\n${err.message}\n`));
97
+ if (err.statusCode === 401) {
98
+ console.log(chalk.gray(" I don't know you. ") + chalk.cyan("sally login your@email.com") + "\n");
99
+ }
100
+ if (err.statusCode === 402 || err.statusCode === 429) {
101
+ printUpgradePrompt();
102
+ }
103
+ }
104
+ else if (err instanceof TypeError) {
105
+ console.log(chalk.red("\nCan't reach the server.") + chalk.gray(" Either I'm napping or your internet is trash.\n"));
106
+ }
107
+ else {
108
+ const msg = err instanceof Error ? err.message : String(err);
109
+ console.log(chalk.red(`\nSomething unexpected: ${msg}`) + chalk.gray("\nI blame your machine.\n"));
110
+ }
111
+ }
112
+ // ---------------------------------------------------------------------------
113
+ // Display
114
+ // ---------------------------------------------------------------------------
115
+ export function displayRoast(response) {
116
+ const { data, voice, meta } = response;
117
+ // Header
118
+ console.log(chalk.magenta.bold(" \u2620 SALLY'S CODE REVIEW"));
119
+ console.log(chalk.gray(` ${meta.mode === "full_truth" ? "Full Truth" : "Quick Roast"} \u2022 ${meta.files_reviewed} file${meta.files_reviewed !== 1 ? "s" : ""} reviewed \u2022 ${meta.model || "claude"}`));
120
+ console.log();
121
+ // Score
122
+ console.log(` ${chalk.gray("Score:")} ${colorScore(data.score)}/10 ${scoreBar(data.score)}`);
123
+ console.log();
124
+ divider();
125
+ console.log();
126
+ // Parse roast into sections (first = intro, last = verdict, middle = observations)
127
+ const paragraphs = voice.roast.split("\n\n").filter((p) => p.trim());
128
+ if (paragraphs.length > 0) {
129
+ // Intro — Sally's opening take
130
+ printWrapped(paragraphs[0], " ", chalk.white.italic);
131
+ console.log();
132
+ // Observations — numbered, with visual distinction
133
+ const observations = paragraphs.slice(1, -1);
134
+ if (observations.length > 0) {
135
+ divider();
136
+ console.log();
137
+ for (let i = 0; i < observations.length; i++) {
138
+ const num = chalk.magenta.bold(` ${i + 1}.`);
139
+ const lines = wrapText(highlightCode(observations[i]), "", CONTENT_WIDTH);
140
+ // First line with number
141
+ if (lines.length > 0) {
142
+ console.log(`${num} ${chalk.white(lines[0])}`);
143
+ }
144
+ // Remaining lines indented
145
+ for (let j = 1; j < lines.length; j++) {
146
+ console.log(chalk.white(` ${lines[j]}`));
147
+ }
148
+ console.log();
149
+ }
150
+ }
151
+ // Final verdict
152
+ if (paragraphs.length > 1) {
153
+ divider();
154
+ console.log();
155
+ console.log(chalk.gray(" VERDICT"));
156
+ console.log();
157
+ printWrapped(paragraphs[paragraphs.length - 1], " ", chalk.white.bold);
158
+ console.log();
159
+ }
160
+ }
161
+ // Issues (full_truth mode)
162
+ if (data.issues && data.issues.length > 0) {
163
+ divider();
164
+ console.log();
165
+ console.log(chalk.magenta.bold(" TOP ISSUES"));
166
+ console.log();
167
+ for (let i = 0; i < data.issues.length; i++) {
168
+ const issue = data.issues[i];
169
+ console.log(` ${chalk.white.bold(`${i + 1}.`)} ${colorSeverity(issue.severity)} ${chalk.cyan(issue.issue_code)}`);
170
+ console.log(` ${chalk.white.bold(issue.title)}`);
171
+ printWrapped(issue.description, " ", chalk.gray);
172
+ if (issue.evidence && issue.evidence.length > 0) {
173
+ for (const e of issue.evidence) {
174
+ console.log(` ${chalk.yellow("\u2192")} ${chalk.gray(highlightCode(e))}`);
175
+ }
176
+ }
177
+ if (issue.fix) {
178
+ console.log(` ${chalk.green("\u2713")} ${chalk.green(highlightCode(issue.fix))}`);
179
+ }
180
+ console.log();
181
+ }
182
+ }
183
+ // Actionable fixes
184
+ if (data.actionable_fixes && data.actionable_fixes.length > 0) {
185
+ divider();
186
+ console.log();
187
+ console.log(chalk.green.bold(" ACTIONABLE FIXES"));
188
+ console.log();
189
+ for (const fix of data.actionable_fixes) {
190
+ printWrapped(`\u2713 ${fix}`, " ", chalk.green);
191
+ }
192
+ console.log();
193
+ }
194
+ // Bright side & hardest sneer
195
+ divider();
196
+ console.log();
197
+ if (voice.bright_side) {
198
+ printWrapped(`\u2728 ${voice.bright_side}`, " ", chalk.green.italic);
199
+ }
200
+ if (voice.hardest_sneer) {
201
+ console.log();
202
+ printWrapped(`\uD83D\uDD25 ${voice.hardest_sneer}`, " ", chalk.red.bold);
203
+ }
204
+ console.log();
205
+ }
206
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RoastResponse, ToolResponse } from "./api.js";
2
+ /**
3
+ * Save a Full Truth review as a markdown report.
4
+ * Returns the file path if saved, null if skipped/failed.
5
+ */
6
+ export declare function saveReport(response: RoastResponse, source: string): string | null;
7
+ /**
8
+ * Save a premium tool response as a markdown report.
9
+ * Returns the file path if saved, null if skipped/failed.
10
+ */
11
+ export declare function saveToolReport(response: ToolResponse): string | null;
12
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/utils/report.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAc,YAAY,EAAE,MAAM,UAAU,CAAC;AA+BxE;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA4EjF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,IAAI,CA0FpE"}
@@ -0,0 +1,190 @@
1
+ import { writeFileSync, mkdirSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ const REPORT_DIR = ".sally";
4
+ /** Ensure .sally/ directory exists in the project root */
5
+ function ensureReportDir() {
6
+ const dir = join(process.cwd(), REPORT_DIR);
7
+ if (!existsSync(dir)) {
8
+ mkdirSync(dir, { recursive: true });
9
+ }
10
+ return dir;
11
+ }
12
+ /** Shared voice footer for all report types (#5: deduplicated) */
13
+ function appendVoiceFooter(lines, voice) {
14
+ lines.push("---");
15
+ lines.push("");
16
+ if (voice.bright_side) {
17
+ lines.push(`> ✨ ${voice.bright_side}`);
18
+ lines.push("");
19
+ }
20
+ if (voice.hardest_sneer) {
21
+ lines.push(`> 🔥 ${voice.hardest_sneer}`);
22
+ lines.push("");
23
+ }
24
+ lines.push("---");
25
+ lines.push("");
26
+ lines.push("*Generated by [Cynical Sally](https://cynicalsally.com)*");
27
+ lines.push("");
28
+ }
29
+ /**
30
+ * Save a Full Truth review as a markdown report.
31
+ * Returns the file path if saved, null if skipped/failed.
32
+ */
33
+ export function saveReport(response, source) {
34
+ try {
35
+ const { data, voice, meta } = response;
36
+ const date = new Date().toISOString().split("T")[0];
37
+ const dir = ensureReportDir();
38
+ const filename = `review-${date}.md`;
39
+ const filepath = join(dir, filename);
40
+ const lines = [];
41
+ lines.push(`# Sally's ${meta.mode === "full_truth" ? "Full Truth" : "Quick Roast"} Review`);
42
+ lines.push("");
43
+ lines.push(`**Date:** ${date}`);
44
+ lines.push(`**Source:** ${source}`);
45
+ lines.push(`**Files reviewed:** ${meta.files_reviewed}`);
46
+ lines.push(`**Score:** ${data.score.toFixed(1)}/10`);
47
+ lines.push("");
48
+ lines.push("---");
49
+ lines.push("");
50
+ lines.push("## Sally's Verdict");
51
+ lines.push("");
52
+ const paragraphs = voice.roast.split("\n\n");
53
+ for (const p of paragraphs) {
54
+ lines.push(p);
55
+ lines.push("");
56
+ }
57
+ if (data.issues && data.issues.length > 0) {
58
+ lines.push("---");
59
+ lines.push("");
60
+ lines.push("## Top Issues");
61
+ lines.push("");
62
+ for (let i = 0; i < data.issues.length; i++) {
63
+ const issue = data.issues[i];
64
+ const severity = issue.severity.toUpperCase();
65
+ lines.push(`### ${i + 1}. \`${issue.issue_code}\` — ${severity}`);
66
+ lines.push("");
67
+ lines.push(`**${issue.title}**`);
68
+ lines.push("");
69
+ lines.push(issue.description);
70
+ lines.push("");
71
+ if (issue.evidence && issue.evidence.length > 0) {
72
+ for (const e of issue.evidence) {
73
+ lines.push(`- → ${e}`);
74
+ }
75
+ lines.push("");
76
+ }
77
+ if (issue.fix) {
78
+ lines.push(`**Fix:** ${issue.fix}`);
79
+ lines.push("");
80
+ }
81
+ }
82
+ }
83
+ if (data.actionable_fixes && data.actionable_fixes.length > 0) {
84
+ lines.push("---");
85
+ lines.push("");
86
+ lines.push("## Actionable Fixes");
87
+ lines.push("");
88
+ for (const fix of data.actionable_fixes) {
89
+ lines.push(`- ✓ ${fix}`);
90
+ }
91
+ lines.push("");
92
+ }
93
+ appendVoiceFooter(lines, voice);
94
+ writeFileSync(filepath, lines.join("\n"), "utf-8");
95
+ return filepath;
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ }
101
+ /**
102
+ * Save a premium tool response as a markdown report.
103
+ * Returns the file path if saved, null if skipped/failed.
104
+ */
105
+ export function saveToolReport(response) {
106
+ try {
107
+ const date = new Date().toISOString().split("T")[0];
108
+ const time = new Date().toISOString().split("T")[1].slice(0, 5).replace(":", "");
109
+ const dir = ensureReportDir();
110
+ const toolLabel = response.tool.replace("_", "-");
111
+ const filename = `${toolLabel}-${date}-${time}.md`;
112
+ const filepath = join(dir, filename);
113
+ const lines = [];
114
+ const displayTool = response.tool.replace("_", " ");
115
+ lines.push(`# Sally's ${displayTool}`);
116
+ lines.push("");
117
+ lines.push(`**Date:** ${date}`);
118
+ lines.push(`**Tool:** ${displayTool}`);
119
+ lines.push("");
120
+ lines.push("---");
121
+ lines.push("");
122
+ // Messages
123
+ if (response.messages && response.messages.length > 0) {
124
+ for (const msg of response.messages) {
125
+ lines.push(msg.text);
126
+ lines.push("");
127
+ }
128
+ }
129
+ // Score
130
+ const score = response.data.scorecard;
131
+ if (typeof score === "number") {
132
+ lines.push(`**Score:** ${score.toFixed(1)}/10`);
133
+ lines.push("");
134
+ }
135
+ // Verdict
136
+ const verdict = response.data.verdict;
137
+ if (verdict) {
138
+ lines.push(`**Verdict:** ${verdict}`);
139
+ lines.push("");
140
+ }
141
+ // Refactors
142
+ const refactors = response.data.refactors;
143
+ if (refactors && refactors.length > 0) {
144
+ lines.push("## Refactoring Suggestions");
145
+ lines.push("");
146
+ for (let i = 0; i < refactors.length; i++) {
147
+ const r = refactors[i];
148
+ lines.push(`### ${i + 1}. ${r.priority.toUpperCase()} — ${r.title}`);
149
+ if (r.before)
150
+ lines.push(`\`\`\`\n// Before\n${r.before}\n\`\`\``);
151
+ if (r.after)
152
+ lines.push(`\`\`\`\n// After\n${r.after}\n\`\`\``);
153
+ lines.push("");
154
+ }
155
+ }
156
+ // Issues
157
+ const issues = response.data.issues;
158
+ if (issues && issues.length > 0) {
159
+ lines.push("## Issues");
160
+ lines.push("");
161
+ for (let i = 0; i < issues.length; i++) {
162
+ const issue = issues[i];
163
+ lines.push(`### ${i + 1}. ${issue.severity.toUpperCase()} [${issue.category}]`);
164
+ lines.push(issue.description);
165
+ if (issue.fix)
166
+ lines.push(`**Fix:** ${issue.fix}`);
167
+ lines.push("");
168
+ }
169
+ }
170
+ // Rewrites
171
+ const rewrites = response.data.rewrites;
172
+ if (rewrites && rewrites.length > 0) {
173
+ lines.push("## Copy Rewrites");
174
+ lines.push("");
175
+ for (const rw of rewrites) {
176
+ lines.push(`- **Before:** "${rw.original}"`);
177
+ lines.push(` **After:** "${rw.improved}"`);
178
+ lines.push(` *${rw.why}*`);
179
+ lines.push("");
180
+ }
181
+ }
182
+ appendVoiceFooter(lines, response.voice);
183
+ writeFileSync(filepath, lines.join("\n"), "utf-8");
184
+ return filepath;
185
+ }
186
+ catch {
187
+ return null;
188
+ }
189
+ }
190
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/utils/report.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@cynicalsally/cli",
3
+ "version": "0.1.0",
4
+ "description": "Brutally honest code reviews. Because 'You're absolutely right' is probably absolutely wrong.",
5
+ "author": "Thomas Geelens",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "sally": "./dist/index.js",
10
+ "sally-mcp": "./dist/mcp-server.js"
11
+ },
12
+ "main": "./dist/index.js",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsc --watch",
19
+ "start": "node dist/index.js",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "code-review",
24
+ "cli",
25
+ "ai",
26
+ "linter",
27
+ "roast",
28
+ "cynical-sally",
29
+ "developer-tools",
30
+ "code-quality"
31
+ ],
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/w1ckedxt/cynicalsally-cli.git"
35
+ },
36
+ "homepage": "https://cynicalsally.com",
37
+ "bugs": {
38
+ "url": "https://github.com/w1ckedxt/cynicalsally-cli/issues"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ },
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1.27.1",
45
+ "chalk": "^5.4.1",
46
+ "commander": "^13.1.0",
47
+ "inquirer": "^12.4.2",
48
+ "ora": "^8.2.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.13.5",
52
+ "typescript": "^5.7.3"
53
+ }
54
+ }