@staff0rd/assist 0.10.1 → 0.14.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/README.md +55 -44
- package/dist/commands/deploy/build.yml +25 -25
- package/dist/commands/deploy/init.ts +29 -9
- package/dist/commands/deploy/redirect.ts +39 -0
- package/dist/commands/enable-ralph/index.ts +2 -7
- package/dist/commands/lint/init.ts +5 -7
- package/dist/index.js +399 -275
- package/package.json +53 -49
package/dist/index.js
CHANGED
|
@@ -1,17 +1,73 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { execSync as
|
|
4
|
+
import { execSync as execSync13 } from "child_process";
|
|
5
5
|
import { Command } from "commander";
|
|
6
6
|
|
|
7
7
|
// src/commands/commit.ts
|
|
8
8
|
import { execSync } from "child_process";
|
|
9
|
+
|
|
10
|
+
// src/shared/loadConfig.ts
|
|
11
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
12
|
+
import { basename, join } from "path";
|
|
13
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
14
|
+
function getConfigPath() {
|
|
15
|
+
const claudeConfigPath = join(process.cwd(), ".claude", "assist.yml");
|
|
16
|
+
if (existsSync(claudeConfigPath)) {
|
|
17
|
+
return claudeConfigPath;
|
|
18
|
+
}
|
|
19
|
+
return join(process.cwd(), "assist.yml");
|
|
20
|
+
}
|
|
21
|
+
function loadConfig() {
|
|
22
|
+
const configPath = getConfigPath();
|
|
23
|
+
if (!existsSync(configPath)) {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const content = readFileSync(configPath, "utf-8");
|
|
28
|
+
return parseYaml(content) || {};
|
|
29
|
+
} catch {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function saveConfig(config) {
|
|
34
|
+
const configPath = getConfigPath();
|
|
35
|
+
writeFileSync(configPath, stringifyYaml(config, { lineWidth: 0 }));
|
|
36
|
+
}
|
|
37
|
+
function getRepoName() {
|
|
38
|
+
const config = loadConfig();
|
|
39
|
+
if (config.devlog?.name) {
|
|
40
|
+
return config.devlog.name;
|
|
41
|
+
}
|
|
42
|
+
const packageJsonPath = join(process.cwd(), "package.json");
|
|
43
|
+
if (existsSync(packageJsonPath)) {
|
|
44
|
+
try {
|
|
45
|
+
const content = readFileSync(packageJsonPath, "utf-8");
|
|
46
|
+
const pkg = JSON.parse(content);
|
|
47
|
+
if (pkg.name) {
|
|
48
|
+
return pkg.name;
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return basename(process.cwd());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// src/commands/commit.ts
|
|
9
57
|
var MAX_MESSAGE_LENGTH = 50;
|
|
58
|
+
var CONVENTIONAL_COMMIT_REGEX = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(!)?(\(.+\))?!?: .+$/;
|
|
10
59
|
function commit(message) {
|
|
60
|
+
const config = loadConfig();
|
|
11
61
|
if (message.toLowerCase().includes("claude")) {
|
|
12
62
|
console.error("Error: Commit message must not reference Claude");
|
|
13
63
|
process.exit(1);
|
|
14
64
|
}
|
|
65
|
+
if (config.commit?.conventional && !CONVENTIONAL_COMMIT_REGEX.test(message)) {
|
|
66
|
+
console.error(
|
|
67
|
+
"Error: Commit message must follow conventional commit format (e.g., 'feat: add feature', 'fix(scope): fix bug')"
|
|
68
|
+
);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
15
71
|
if (message.length > MAX_MESSAGE_LENGTH) {
|
|
16
72
|
console.error(
|
|
17
73
|
`Error: Commit message must be ${MAX_MESSAGE_LENGTH} characters or less (current: ${message.length})`
|
|
@@ -19,9 +75,16 @@ function commit(message) {
|
|
|
19
75
|
process.exit(1);
|
|
20
76
|
}
|
|
21
77
|
try {
|
|
78
|
+
if (config.commit?.pull) {
|
|
79
|
+
execSync("git pull", { stdio: "inherit" });
|
|
80
|
+
}
|
|
22
81
|
execSync(`git commit -m "${message.replace(/"/g, '\\"')}"`, {
|
|
23
82
|
stdio: "inherit"
|
|
24
83
|
});
|
|
84
|
+
if (config.commit?.push) {
|
|
85
|
+
execSync("git push", { stdio: "inherit" });
|
|
86
|
+
console.log("Pushed to remote");
|
|
87
|
+
}
|
|
25
88
|
process.exit(0);
|
|
26
89
|
} catch (_error) {
|
|
27
90
|
process.exit(1);
|
|
@@ -30,11 +93,28 @@ function commit(message) {
|
|
|
30
93
|
|
|
31
94
|
// src/commands/deploy/init.ts
|
|
32
95
|
import { execSync as execSync2 } from "child_process";
|
|
33
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
34
|
-
import { dirname, join } from "path";
|
|
96
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
97
|
+
import { dirname, join as join2 } from "path";
|
|
35
98
|
import { fileURLToPath } from "url";
|
|
36
99
|
import chalk2 from "chalk";
|
|
100
|
+
import enquirer2 from "enquirer";
|
|
101
|
+
|
|
102
|
+
// src/shared/promptConfirm.ts
|
|
37
103
|
import enquirer from "enquirer";
|
|
104
|
+
async function promptConfirm(message, initial = true) {
|
|
105
|
+
const { confirmed } = await enquirer.prompt({
|
|
106
|
+
type: "confirm",
|
|
107
|
+
name: "confirmed",
|
|
108
|
+
message,
|
|
109
|
+
initial,
|
|
110
|
+
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
111
|
+
symbols: {
|
|
112
|
+
on: "[x]",
|
|
113
|
+
off: "[ ]"
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return confirmed;
|
|
117
|
+
}
|
|
38
118
|
|
|
39
119
|
// src/utils/printDiff.ts
|
|
40
120
|
import chalk from "chalk";
|
|
@@ -69,26 +149,26 @@ function printDiff(oldContent, newContent) {
|
|
|
69
149
|
var WORKFLOW_PATH = ".github/workflows/build.yml";
|
|
70
150
|
var __dirname2 = dirname(fileURLToPath(import.meta.url));
|
|
71
151
|
function getExistingSiteId() {
|
|
72
|
-
if (!
|
|
152
|
+
if (!existsSync2(WORKFLOW_PATH)) {
|
|
73
153
|
return null;
|
|
74
154
|
}
|
|
75
|
-
const content =
|
|
155
|
+
const content = readFileSync2(WORKFLOW_PATH, "utf-8");
|
|
76
156
|
const match = content.match(/-s\s+([a-f0-9-]{36})/);
|
|
77
157
|
return match ? match[1] : null;
|
|
78
158
|
}
|
|
79
159
|
function getTemplateContent(siteId) {
|
|
80
|
-
const templatePath =
|
|
81
|
-
const template =
|
|
160
|
+
const templatePath = join2(__dirname2, "commands/deploy/build.yml");
|
|
161
|
+
const template = readFileSync2(templatePath, "utf-8");
|
|
82
162
|
return template.replace("{{NETLIFY_SITE_ID}}", siteId);
|
|
83
163
|
}
|
|
84
164
|
async function updateWorkflow(siteId) {
|
|
85
165
|
const newContent = getTemplateContent(siteId);
|
|
86
166
|
const workflowDir = ".github/workflows";
|
|
87
|
-
if (!
|
|
167
|
+
if (!existsSync2(workflowDir)) {
|
|
88
168
|
mkdirSync(workflowDir, { recursive: true });
|
|
89
169
|
}
|
|
90
|
-
if (
|
|
91
|
-
const oldContent =
|
|
170
|
+
if (existsSync2(WORKFLOW_PATH)) {
|
|
171
|
+
const oldContent = readFileSync2(WORKFLOW_PATH, "utf-8");
|
|
92
172
|
if (oldContent === newContent) {
|
|
93
173
|
console.log(chalk2.green("build.yml is already up to date"));
|
|
94
174
|
return;
|
|
@@ -96,18 +176,13 @@ async function updateWorkflow(siteId) {
|
|
|
96
176
|
console.log(chalk2.yellow("\nbuild.yml will be updated:"));
|
|
97
177
|
console.log();
|
|
98
178
|
printDiff(oldContent, newContent);
|
|
99
|
-
const
|
|
100
|
-
type: "confirm",
|
|
101
|
-
name: "confirm",
|
|
102
|
-
message: chalk2.red("Update build.yml?"),
|
|
103
|
-
initial: true
|
|
104
|
-
});
|
|
179
|
+
const confirm = await promptConfirm(chalk2.red("Update build.yml?"));
|
|
105
180
|
if (!confirm) {
|
|
106
181
|
console.log("Skipped build.yml update");
|
|
107
182
|
return;
|
|
108
183
|
}
|
|
109
184
|
}
|
|
110
|
-
|
|
185
|
+
writeFileSync2(WORKFLOW_PATH, newContent);
|
|
111
186
|
console.log(chalk2.green(`
|
|
112
187
|
Created ${WORKFLOW_PATH}`));
|
|
113
188
|
}
|
|
@@ -121,10 +196,34 @@ async function init() {
|
|
|
121
196
|
return;
|
|
122
197
|
}
|
|
123
198
|
console.log("Creating Netlify site...\n");
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
199
|
+
try {
|
|
200
|
+
execSync2("netlify sites:create --disable-linking", {
|
|
201
|
+
stdio: "inherit"
|
|
202
|
+
});
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error instanceof Error && error.message.includes("command not found")) {
|
|
205
|
+
console.error(chalk2.red("\nNetlify CLI is not installed.\n"));
|
|
206
|
+
const install = await promptConfirm("Would you like to install it now?");
|
|
207
|
+
if (install) {
|
|
208
|
+
console.log(chalk2.dim("\nInstalling netlify-cli...\n"));
|
|
209
|
+
execSync2("npm install -g netlify-cli", { stdio: "inherit" });
|
|
210
|
+
console.log();
|
|
211
|
+
execSync2("netlify sites:create --disable-linking", {
|
|
212
|
+
stdio: "inherit"
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
console.log(
|
|
216
|
+
chalk2.yellow(
|
|
217
|
+
"\nInstall it manually with: npm install -g netlify-cli\n"
|
|
218
|
+
)
|
|
219
|
+
);
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const { siteId } = await enquirer2.prompt({
|
|
128
227
|
type: "input",
|
|
129
228
|
name: "siteId",
|
|
130
229
|
message: "Enter the Site ID from above:",
|
|
@@ -147,63 +246,46 @@ async function init() {
|
|
|
147
246
|
);
|
|
148
247
|
}
|
|
149
248
|
|
|
249
|
+
// src/commands/deploy/redirect.ts
|
|
250
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
251
|
+
import chalk3 from "chalk";
|
|
252
|
+
var TRAILING_SLASH_SCRIPT = ` <script>
|
|
253
|
+
if (!window.location.pathname.endsWith('/')) {
|
|
254
|
+
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
255
|
+
}
|
|
256
|
+
</script>`;
|
|
257
|
+
function redirect() {
|
|
258
|
+
const indexPath = "index.html";
|
|
259
|
+
if (!existsSync3(indexPath)) {
|
|
260
|
+
console.log(chalk3.yellow("No index.html found"));
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
const content = readFileSync3(indexPath, "utf-8");
|
|
264
|
+
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
265
|
+
console.log(chalk3.dim("Trailing slash script already present"));
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const headCloseIndex = content.indexOf("</head>");
|
|
269
|
+
if (headCloseIndex === -1) {
|
|
270
|
+
console.log(chalk3.red("Could not find </head> tag in index.html"));
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
|
|
274
|
+
writeFileSync3(indexPath, newContent);
|
|
275
|
+
console.log(chalk3.green("Added trailing slash redirect to index.html"));
|
|
276
|
+
}
|
|
277
|
+
|
|
150
278
|
// src/commands/devlog/list.ts
|
|
151
279
|
import { execSync as execSync4 } from "child_process";
|
|
152
280
|
import { basename as basename2 } from "path";
|
|
153
|
-
import
|
|
281
|
+
import chalk5 from "chalk";
|
|
154
282
|
|
|
155
283
|
// src/commands/devlog/shared.ts
|
|
156
284
|
import { execSync as execSync3 } from "child_process";
|
|
157
|
-
import
|
|
158
|
-
|
|
159
|
-
// src/shared/loadConfig.ts
|
|
160
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
161
|
-
import { basename, join as join2 } from "path";
|
|
162
|
-
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
163
|
-
function getConfigPath() {
|
|
164
|
-
const claudeConfigPath = join2(process.cwd(), ".claude", "assist.yml");
|
|
165
|
-
if (existsSync2(claudeConfigPath)) {
|
|
166
|
-
return claudeConfigPath;
|
|
167
|
-
}
|
|
168
|
-
return join2(process.cwd(), "assist.yml");
|
|
169
|
-
}
|
|
170
|
-
function loadConfig() {
|
|
171
|
-
const configPath = getConfigPath();
|
|
172
|
-
if (!existsSync2(configPath)) {
|
|
173
|
-
return {};
|
|
174
|
-
}
|
|
175
|
-
try {
|
|
176
|
-
const content = readFileSync2(configPath, "utf-8");
|
|
177
|
-
return parseYaml(content) || {};
|
|
178
|
-
} catch {
|
|
179
|
-
return {};
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
function saveConfig(config) {
|
|
183
|
-
const configPath = getConfigPath();
|
|
184
|
-
writeFileSync2(configPath, stringifyYaml(config, { lineWidth: 0 }));
|
|
185
|
-
}
|
|
186
|
-
function getRepoName() {
|
|
187
|
-
const config = loadConfig();
|
|
188
|
-
if (config.devlog?.name) {
|
|
189
|
-
return config.devlog.name;
|
|
190
|
-
}
|
|
191
|
-
const packageJsonPath = join2(process.cwd(), "package.json");
|
|
192
|
-
if (existsSync2(packageJsonPath)) {
|
|
193
|
-
try {
|
|
194
|
-
const content = readFileSync2(packageJsonPath, "utf-8");
|
|
195
|
-
const pkg = JSON.parse(content);
|
|
196
|
-
if (pkg.name) {
|
|
197
|
-
return pkg.name;
|
|
198
|
-
}
|
|
199
|
-
} catch {
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return basename(process.cwd());
|
|
203
|
-
}
|
|
285
|
+
import chalk4 from "chalk";
|
|
204
286
|
|
|
205
287
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
206
|
-
import { readdirSync, readFileSync as
|
|
288
|
+
import { readdirSync, readFileSync as readFileSync4 } from "fs";
|
|
207
289
|
import { homedir } from "os";
|
|
208
290
|
import { join as join3 } from "path";
|
|
209
291
|
var DEVLOG_DIR = join3(homedir(), "git/blog/src/content/devlog");
|
|
@@ -212,7 +294,7 @@ function loadDevlogEntries(repoName) {
|
|
|
212
294
|
try {
|
|
213
295
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
214
296
|
for (const file of files) {
|
|
215
|
-
const content =
|
|
297
|
+
const content = readFileSync4(join3(DEVLOG_DIR, file), "utf-8");
|
|
216
298
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
217
299
|
if (frontmatterMatch) {
|
|
218
300
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -261,13 +343,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
261
343
|
}
|
|
262
344
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
263
345
|
for (const commit2 of commits) {
|
|
264
|
-
console.log(` ${
|
|
346
|
+
console.log(` ${chalk4.yellow(commit2.hash)} ${commit2.message}`);
|
|
265
347
|
if (verbose) {
|
|
266
348
|
const visibleFiles = commit2.files.filter(
|
|
267
349
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
268
350
|
);
|
|
269
351
|
for (const file of visibleFiles) {
|
|
270
|
-
console.log(` ${
|
|
352
|
+
console.log(` ${chalk4.dim(file)}`);
|
|
271
353
|
}
|
|
272
354
|
}
|
|
273
355
|
}
|
|
@@ -320,12 +402,12 @@ function list(options) {
|
|
|
320
402
|
isFirst = false;
|
|
321
403
|
const entries = devlogEntries.get(date);
|
|
322
404
|
if (skipDays.has(date)) {
|
|
323
|
-
console.log(`${
|
|
405
|
+
console.log(`${chalk5.bold.blue(date)} ${chalk5.dim("skipped")}`);
|
|
324
406
|
} else if (entries && entries.length > 0) {
|
|
325
|
-
const entryInfo = entries.map((e) => `${
|
|
326
|
-
console.log(`${
|
|
407
|
+
const entryInfo = entries.map((e) => `${chalk5.green(e.version)} ${e.title}`).join(" | ");
|
|
408
|
+
console.log(`${chalk5.bold.blue(date)} ${entryInfo}`);
|
|
327
409
|
} else {
|
|
328
|
-
console.log(`${
|
|
410
|
+
console.log(`${chalk5.bold.blue(date)} ${chalk5.red("\u26A0 devlog missing")}`);
|
|
329
411
|
}
|
|
330
412
|
printCommitsWithFiles(dateCommits, ignore2, options.verbose ?? false);
|
|
331
413
|
}
|
|
@@ -333,7 +415,7 @@ function list(options) {
|
|
|
333
415
|
|
|
334
416
|
// src/commands/devlog/next.ts
|
|
335
417
|
import { execSync as execSync5 } from "child_process";
|
|
336
|
-
import
|
|
418
|
+
import chalk6 from "chalk";
|
|
337
419
|
|
|
338
420
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
339
421
|
import semver from "semver";
|
|
@@ -403,36 +485,36 @@ function next(options) {
|
|
|
403
485
|
const targetDate = dates[0];
|
|
404
486
|
if (!targetDate) {
|
|
405
487
|
if (lastInfo) {
|
|
406
|
-
console.log(
|
|
488
|
+
console.log(chalk6.dim("No commits after last versioned entry"));
|
|
407
489
|
} else {
|
|
408
|
-
console.log(
|
|
490
|
+
console.log(chalk6.dim("No commits found"));
|
|
409
491
|
}
|
|
410
492
|
return;
|
|
411
493
|
}
|
|
412
494
|
const commits = commitsByDate.get(targetDate) ?? [];
|
|
413
|
-
console.log(`${
|
|
495
|
+
console.log(`${chalk6.bold("name:")} ${repoName}`);
|
|
414
496
|
if (patchVersion && minorVersion) {
|
|
415
497
|
console.log(
|
|
416
|
-
`${
|
|
498
|
+
`${chalk6.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
417
499
|
);
|
|
418
500
|
} else {
|
|
419
|
-
console.log(`${
|
|
501
|
+
console.log(`${chalk6.bold("version:")} v0.1 (initial)`);
|
|
420
502
|
}
|
|
421
|
-
console.log(`${
|
|
503
|
+
console.log(`${chalk6.bold.blue(targetDate)}`);
|
|
422
504
|
printCommitsWithFiles(commits, ignore2, options.verbose ?? false);
|
|
423
505
|
}
|
|
424
506
|
|
|
425
507
|
// src/commands/devlog/skip.ts
|
|
426
|
-
import
|
|
508
|
+
import chalk7 from "chalk";
|
|
427
509
|
function skip(date) {
|
|
428
510
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
429
|
-
console.log(
|
|
511
|
+
console.log(chalk7.red("Invalid date format. Use YYYY-MM-DD"));
|
|
430
512
|
process.exit(1);
|
|
431
513
|
}
|
|
432
514
|
const config = loadConfig();
|
|
433
515
|
const skipDays = config.devlog?.skip?.days ?? [];
|
|
434
516
|
if (skipDays.includes(date)) {
|
|
435
|
-
console.log(
|
|
517
|
+
console.log(chalk7.yellow(`${date} is already in skip list`));
|
|
436
518
|
return;
|
|
437
519
|
}
|
|
438
520
|
skipDays.push(date);
|
|
@@ -445,19 +527,19 @@ function skip(date) {
|
|
|
445
527
|
}
|
|
446
528
|
};
|
|
447
529
|
saveConfig(config);
|
|
448
|
-
console.log(
|
|
530
|
+
console.log(chalk7.green(`Added ${date} to skip list`));
|
|
449
531
|
}
|
|
450
532
|
|
|
451
533
|
// src/commands/devlog/version.ts
|
|
452
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
534
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
453
535
|
import { join as join4 } from "path";
|
|
454
|
-
import
|
|
536
|
+
import chalk8 from "chalk";
|
|
455
537
|
import semver2 from "semver";
|
|
456
538
|
function getLatestVersion(repoName) {
|
|
457
539
|
try {
|
|
458
540
|
const files = readdirSync2(DEVLOG_DIR).filter((f) => f.endsWith(".md")).sort().reverse();
|
|
459
541
|
for (const file of files) {
|
|
460
|
-
const content =
|
|
542
|
+
const content = readFileSync5(join4(DEVLOG_DIR, file), "utf-8");
|
|
461
543
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
462
544
|
if (frontmatterMatch) {
|
|
463
545
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -488,17 +570,16 @@ function version() {
|
|
|
488
570
|
const name = getRepoName();
|
|
489
571
|
const lastVersion = getLatestVersion(name);
|
|
490
572
|
const nextVersion = lastVersion ? bumpPatchVersion(lastVersion) : null;
|
|
491
|
-
console.log(`${
|
|
492
|
-
console.log(`${
|
|
493
|
-
console.log(`${
|
|
573
|
+
console.log(`${chalk8.bold("name:")} ${name}`);
|
|
574
|
+
console.log(`${chalk8.bold("last:")} ${lastVersion ?? chalk8.dim("none")}`);
|
|
575
|
+
console.log(`${chalk8.bold("next:")} ${nextVersion ?? chalk8.dim("none")}`);
|
|
494
576
|
}
|
|
495
577
|
|
|
496
578
|
// src/commands/enable-ralph/index.ts
|
|
497
579
|
import * as fs from "fs";
|
|
498
580
|
import * as path from "path";
|
|
499
581
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
500
|
-
import
|
|
501
|
-
import enquirer2 from "enquirer";
|
|
582
|
+
import chalk9 from "chalk";
|
|
502
583
|
var __dirname3 = path.dirname(fileURLToPath2(import.meta.url));
|
|
503
584
|
function deepMerge(target, source) {
|
|
504
585
|
const result = { ...target };
|
|
@@ -536,18 +617,13 @@ async function enableRalph() {
|
|
|
536
617
|
const merged = deepMerge(targetData, sourceData);
|
|
537
618
|
const mergedContent = JSON.stringify(merged, null, " ") + "\n";
|
|
538
619
|
if (mergedContent === targetContent) {
|
|
539
|
-
console.log(
|
|
620
|
+
console.log(chalk9.green("settings.local.json already has ralph enabled"));
|
|
540
621
|
return;
|
|
541
622
|
}
|
|
542
|
-
console.log(
|
|
623
|
+
console.log(chalk9.yellow("\nChanges to settings.local.json:"));
|
|
543
624
|
console.log();
|
|
544
625
|
printDiff(targetContent, mergedContent);
|
|
545
|
-
const
|
|
546
|
-
type: "confirm",
|
|
547
|
-
name: "confirm",
|
|
548
|
-
message: "Apply these changes?",
|
|
549
|
-
initial: true
|
|
550
|
-
});
|
|
626
|
+
const confirm = await promptConfirm("Apply these changes?");
|
|
551
627
|
if (!confirm) {
|
|
552
628
|
console.log("Skipped");
|
|
553
629
|
return;
|
|
@@ -557,10 +633,10 @@ async function enableRalph() {
|
|
|
557
633
|
}
|
|
558
634
|
|
|
559
635
|
// src/commands/verify/init.ts
|
|
560
|
-
import
|
|
636
|
+
import chalk20 from "chalk";
|
|
561
637
|
|
|
562
638
|
// src/shared/promptMultiselect.ts
|
|
563
|
-
import
|
|
639
|
+
import chalk10 from "chalk";
|
|
564
640
|
import enquirer3 from "enquirer";
|
|
565
641
|
async function promptMultiselect(message, options) {
|
|
566
642
|
const { selected } = await enquirer3.prompt({
|
|
@@ -569,8 +645,15 @@ async function promptMultiselect(message, options) {
|
|
|
569
645
|
message,
|
|
570
646
|
choices: options.map((opt) => ({
|
|
571
647
|
name: opt.value,
|
|
572
|
-
message: `${opt.name} - ${
|
|
573
|
-
}))
|
|
648
|
+
message: `${opt.name} - ${chalk10.dim(opt.description)}`
|
|
649
|
+
})),
|
|
650
|
+
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
651
|
+
symbols: {
|
|
652
|
+
indicator: {
|
|
653
|
+
on: "[x]",
|
|
654
|
+
off: "[ ]"
|
|
655
|
+
}
|
|
656
|
+
}
|
|
574
657
|
});
|
|
575
658
|
return selected;
|
|
576
659
|
}
|
|
@@ -578,7 +661,7 @@ async function promptMultiselect(message, options) {
|
|
|
578
661
|
// src/shared/readPackageJson.ts
|
|
579
662
|
import * as fs2 from "fs";
|
|
580
663
|
import * as path2 from "path";
|
|
581
|
-
import
|
|
664
|
+
import chalk11 from "chalk";
|
|
582
665
|
function findPackageJson() {
|
|
583
666
|
const packageJsonPath = path2.join(process.cwd(), "package.json");
|
|
584
667
|
if (fs2.existsSync(packageJsonPath)) {
|
|
@@ -592,7 +675,7 @@ function readPackageJson(filePath) {
|
|
|
592
675
|
function requirePackageJson() {
|
|
593
676
|
const packageJsonPath = findPackageJson();
|
|
594
677
|
if (!packageJsonPath) {
|
|
595
|
-
console.error(
|
|
678
|
+
console.error(chalk11.red("No package.json found in current directory"));
|
|
596
679
|
process.exit(1);
|
|
597
680
|
}
|
|
598
681
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -630,13 +713,13 @@ var EXPECTED_SCRIPTS = {
|
|
|
630
713
|
};
|
|
631
714
|
|
|
632
715
|
// src/commands/verify/setup/setupBuild.ts
|
|
633
|
-
import
|
|
716
|
+
import chalk13 from "chalk";
|
|
634
717
|
|
|
635
718
|
// src/commands/verify/installPackage.ts
|
|
636
719
|
import { execSync as execSync6 } from "child_process";
|
|
637
720
|
import * as fs3 from "fs";
|
|
638
721
|
import * as path3 from "path";
|
|
639
|
-
import
|
|
722
|
+
import chalk12 from "chalk";
|
|
640
723
|
function writePackageJson(filePath, pkg) {
|
|
641
724
|
fs3.writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
642
725
|
`);
|
|
@@ -651,12 +734,12 @@ function addScript(pkg, name, command) {
|
|
|
651
734
|
};
|
|
652
735
|
}
|
|
653
736
|
function installPackage(name, cwd) {
|
|
654
|
-
console.log(
|
|
737
|
+
console.log(chalk12.dim(`Installing ${name}...`));
|
|
655
738
|
try {
|
|
656
739
|
execSync6(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
657
740
|
return true;
|
|
658
741
|
} catch {
|
|
659
|
-
console.error(
|
|
742
|
+
console.error(chalk12.red(`Failed to install ${name}`));
|
|
660
743
|
return false;
|
|
661
744
|
}
|
|
662
745
|
}
|
|
@@ -677,10 +760,10 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
677
760
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
678
761
|
`
|
|
679
762
|
);
|
|
680
|
-
console.log(
|
|
763
|
+
console.log(chalk12.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
681
764
|
}
|
|
682
765
|
} catch {
|
|
683
|
-
console.log(
|
|
766
|
+
console.log(chalk12.yellow("Warning: Could not update knip.json"));
|
|
684
767
|
}
|
|
685
768
|
}
|
|
686
769
|
function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
@@ -692,7 +775,7 @@ function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
|
692
775
|
|
|
693
776
|
// src/commands/verify/setup/setupBuild.ts
|
|
694
777
|
async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
|
|
695
|
-
console.log(
|
|
778
|
+
console.log(chalk13.blue("\nSetting up build verification..."));
|
|
696
779
|
let command;
|
|
697
780
|
if (hasVite && hasTypescript) {
|
|
698
781
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -701,16 +784,16 @@ async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
|
|
|
701
784
|
} else {
|
|
702
785
|
command = "tsc --noEmit";
|
|
703
786
|
}
|
|
704
|
-
console.log(
|
|
787
|
+
console.log(chalk13.dim(`Using: ${command}`));
|
|
705
788
|
const pkg = readPackageJson(packageJsonPath);
|
|
706
789
|
writePackageJson(packageJsonPath, addScript(pkg, "verify:build", command));
|
|
707
790
|
}
|
|
708
791
|
|
|
709
792
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
710
793
|
import * as path4 from "path";
|
|
711
|
-
import
|
|
794
|
+
import chalk14 from "chalk";
|
|
712
795
|
async function setupDuplicateCode(packageJsonPath) {
|
|
713
|
-
console.log(
|
|
796
|
+
console.log(chalk14.blue("\nSetting up jscpd..."));
|
|
714
797
|
const cwd = path4.dirname(packageJsonPath);
|
|
715
798
|
const pkg = readPackageJson(packageJsonPath);
|
|
716
799
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -726,9 +809,9 @@ async function setupDuplicateCode(packageJsonPath) {
|
|
|
726
809
|
|
|
727
810
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
728
811
|
import * as path5 from "path";
|
|
729
|
-
import
|
|
812
|
+
import chalk15 from "chalk";
|
|
730
813
|
async function setupHardcodedColors(packageJsonPath, hasOpenColor) {
|
|
731
|
-
console.log(
|
|
814
|
+
console.log(chalk15.blue("\nSetting up hardcoded colors check..."));
|
|
732
815
|
const cwd = path5.dirname(packageJsonPath);
|
|
733
816
|
if (!hasOpenColor) {
|
|
734
817
|
installPackage("open-color", cwd);
|
|
@@ -743,9 +826,9 @@ async function setupHardcodedColors(packageJsonPath, hasOpenColor) {
|
|
|
743
826
|
|
|
744
827
|
// src/commands/verify/setup/setupKnip.ts
|
|
745
828
|
import * as path6 from "path";
|
|
746
|
-
import
|
|
829
|
+
import chalk16 from "chalk";
|
|
747
830
|
async function setupKnip(packageJsonPath) {
|
|
748
|
-
console.log(
|
|
831
|
+
console.log(chalk16.blue("\nSetting up knip..."));
|
|
749
832
|
const cwd = path6.dirname(packageJsonPath);
|
|
750
833
|
const pkg = readPackageJson(packageJsonPath);
|
|
751
834
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -760,29 +843,107 @@ async function setupKnip(packageJsonPath) {
|
|
|
760
843
|
|
|
761
844
|
// src/commands/verify/setup/setupLint.ts
|
|
762
845
|
import * as path7 from "path";
|
|
763
|
-
import
|
|
846
|
+
import chalk18 from "chalk";
|
|
764
847
|
|
|
765
848
|
// src/commands/lint/init.ts
|
|
766
|
-
import { execSync as
|
|
767
|
-
import { existsSync as
|
|
849
|
+
import { execSync as execSync8 } from "child_process";
|
|
850
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
768
851
|
import { dirname as dirname7, join as join8 } from "path";
|
|
769
852
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
770
|
-
import
|
|
771
|
-
|
|
853
|
+
import chalk17 from "chalk";
|
|
854
|
+
|
|
855
|
+
// src/shared/removeEslint.ts
|
|
856
|
+
import { execSync as execSync7 } from "child_process";
|
|
857
|
+
import { existsSync as existsSync7, readFileSync as readFileSync9, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
|
|
858
|
+
function removeEslint(options = {}) {
|
|
859
|
+
const removedFromPackageJson = removeEslintFromPackageJson(options);
|
|
860
|
+
const removedConfigFiles = removeEslintConfigFiles();
|
|
861
|
+
if (removedFromPackageJson || removedConfigFiles) {
|
|
862
|
+
console.log("Running npm install...");
|
|
863
|
+
execSync7("npm install", { stdio: "inherit" });
|
|
864
|
+
return true;
|
|
865
|
+
}
|
|
866
|
+
return false;
|
|
867
|
+
}
|
|
868
|
+
function removeEslintFromPackageJson(options) {
|
|
869
|
+
const packageJsonPath = "package.json";
|
|
870
|
+
if (!existsSync7(packageJsonPath)) {
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
873
|
+
const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
874
|
+
let modified = false;
|
|
875
|
+
if (packageJson.dependencies) {
|
|
876
|
+
for (const key of Object.keys(packageJson.dependencies)) {
|
|
877
|
+
if (key.includes("eslint")) {
|
|
878
|
+
delete packageJson.dependencies[key];
|
|
879
|
+
modified = true;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
if (packageJson.devDependencies) {
|
|
884
|
+
for (const key of Object.keys(packageJson.devDependencies)) {
|
|
885
|
+
if (key.includes("eslint")) {
|
|
886
|
+
delete packageJson.devDependencies[key];
|
|
887
|
+
modified = true;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
if (packageJson.scripts) {
|
|
892
|
+
for (const key of Object.keys(packageJson.scripts)) {
|
|
893
|
+
const isEslintScript = key.includes("eslint") || packageJson.scripts[key].includes("eslint") || options.removeLintScripts && key.includes("lint");
|
|
894
|
+
if (isEslintScript) {
|
|
895
|
+
delete packageJson.scripts[key];
|
|
896
|
+
modified = true;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
if (modified) {
|
|
901
|
+
writeFileSync6(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
902
|
+
`);
|
|
903
|
+
console.log("Removed eslint references from package.json");
|
|
904
|
+
}
|
|
905
|
+
return modified;
|
|
906
|
+
}
|
|
907
|
+
function removeEslintConfigFiles() {
|
|
908
|
+
const eslintConfigFiles = [
|
|
909
|
+
"eslint.config.js",
|
|
910
|
+
"eslint.config.mjs",
|
|
911
|
+
"eslint.config.cjs",
|
|
912
|
+
".eslintrc",
|
|
913
|
+
".eslintrc.js",
|
|
914
|
+
".eslintrc.cjs",
|
|
915
|
+
".eslintrc.json",
|
|
916
|
+
".eslintrc.yaml",
|
|
917
|
+
".eslintrc.yml",
|
|
918
|
+
".eslintignore"
|
|
919
|
+
];
|
|
920
|
+
let removed = false;
|
|
921
|
+
for (const configFile of eslintConfigFiles) {
|
|
922
|
+
if (existsSync7(configFile)) {
|
|
923
|
+
unlinkSync(configFile);
|
|
924
|
+
console.log(`Removed ${configFile}`);
|
|
925
|
+
removed = true;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return removed;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// src/commands/lint/init.ts
|
|
772
932
|
var __dirname4 = dirname7(fileURLToPath3(import.meta.url));
|
|
773
933
|
async function init2() {
|
|
934
|
+
removeEslint();
|
|
774
935
|
const biomeConfigPath = "biome.json";
|
|
775
|
-
if (!
|
|
936
|
+
if (!existsSync8(biomeConfigPath)) {
|
|
776
937
|
console.log("Initializing Biome...");
|
|
777
|
-
|
|
938
|
+
execSync8("npx @biomejs/biome init", { stdio: "inherit" });
|
|
778
939
|
}
|
|
779
|
-
if (!
|
|
940
|
+
if (!existsSync8(biomeConfigPath)) {
|
|
780
941
|
console.log("No biome.json found, skipping linter config");
|
|
781
942
|
return;
|
|
782
943
|
}
|
|
783
944
|
const linterConfigPath = join8(__dirname4, "commands/lint/biome.linter.json");
|
|
784
|
-
const linterConfig = JSON.parse(
|
|
785
|
-
const biomeConfig = JSON.parse(
|
|
945
|
+
const linterConfig = JSON.parse(readFileSync10(linterConfigPath, "utf-8"));
|
|
946
|
+
const biomeConfig = JSON.parse(readFileSync10(biomeConfigPath, "utf-8"));
|
|
786
947
|
const oldContent = `${JSON.stringify(biomeConfig, null, 2)}
|
|
787
948
|
`;
|
|
788
949
|
biomeConfig.linter = linterConfig.linter;
|
|
@@ -795,26 +956,21 @@ async function init2() {
|
|
|
795
956
|
console.log("biome.json already has the correct linter config");
|
|
796
957
|
return;
|
|
797
958
|
}
|
|
798
|
-
console.log(
|
|
959
|
+
console.log(chalk17.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
799
960
|
console.log();
|
|
800
961
|
printDiff(oldContent, newContent);
|
|
801
|
-
const
|
|
802
|
-
type: "confirm",
|
|
803
|
-
name: "confirm",
|
|
804
|
-
message: chalk16.red("Update biome.json?"),
|
|
805
|
-
initial: true
|
|
806
|
-
});
|
|
962
|
+
const confirm = await promptConfirm(chalk17.red("Update biome.json?"));
|
|
807
963
|
if (!confirm) {
|
|
808
964
|
console.log("Skipped biome.json update");
|
|
809
965
|
return;
|
|
810
966
|
}
|
|
811
|
-
|
|
967
|
+
writeFileSync7(biomeConfigPath, newContent);
|
|
812
968
|
console.log("Updated biome.json with linter config");
|
|
813
969
|
}
|
|
814
970
|
|
|
815
971
|
// src/commands/verify/setup/setupLint.ts
|
|
816
972
|
async function setupLint(packageJsonPath) {
|
|
817
|
-
console.log(
|
|
973
|
+
console.log(chalk18.blue("\nSetting up biome..."));
|
|
818
974
|
const cwd = path7.dirname(packageJsonPath);
|
|
819
975
|
const pkg = readPackageJson(packageJsonPath);
|
|
820
976
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -832,9 +988,9 @@ async function setupLint(packageJsonPath) {
|
|
|
832
988
|
|
|
833
989
|
// src/commands/verify/setup/setupTest.ts
|
|
834
990
|
import * as path8 from "path";
|
|
835
|
-
import
|
|
991
|
+
import chalk19 from "chalk";
|
|
836
992
|
async function setupTest(packageJsonPath) {
|
|
837
|
-
console.log(
|
|
993
|
+
console.log(chalk19.blue("\nSetting up vitest..."));
|
|
838
994
|
const cwd = path8.dirname(packageJsonPath);
|
|
839
995
|
const pkg = readPackageJson(packageJsonPath);
|
|
840
996
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -977,16 +1133,16 @@ async function init3() {
|
|
|
977
1133
|
const setup = detectExistingSetup(pkg);
|
|
978
1134
|
const availableOptions = getAvailableOptions(setup);
|
|
979
1135
|
if (availableOptions.length === 0) {
|
|
980
|
-
console.log(
|
|
1136
|
+
console.log(chalk20.green("All verify scripts are already configured!"));
|
|
981
1137
|
return;
|
|
982
1138
|
}
|
|
983
|
-
console.log(
|
|
1139
|
+
console.log(chalk20.bold("Available verify scripts to add:\n"));
|
|
984
1140
|
const selected = await promptMultiselect(
|
|
985
1141
|
"Select verify scripts to add:",
|
|
986
1142
|
availableOptions
|
|
987
1143
|
);
|
|
988
1144
|
if (selected.length === 0) {
|
|
989
|
-
console.log(
|
|
1145
|
+
console.log(chalk20.yellow("No scripts selected"));
|
|
990
1146
|
return;
|
|
991
1147
|
}
|
|
992
1148
|
for (const choice of selected) {
|
|
@@ -1011,28 +1167,28 @@ async function init3() {
|
|
|
1011
1167
|
break;
|
|
1012
1168
|
}
|
|
1013
1169
|
}
|
|
1014
|
-
console.log(
|
|
1170
|
+
console.log(chalk20.green(`
|
|
1015
1171
|
Added ${selected.length} verify script(s):`));
|
|
1016
1172
|
for (const choice of selected) {
|
|
1017
|
-
console.log(
|
|
1173
|
+
console.log(chalk20.green(` - verify:${choice}`));
|
|
1018
1174
|
}
|
|
1019
|
-
console.log(
|
|
1175
|
+
console.log(chalk20.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
1020
1176
|
}
|
|
1021
1177
|
|
|
1022
1178
|
// src/commands/vscode/init.ts
|
|
1023
1179
|
import * as fs5 from "fs";
|
|
1024
1180
|
import * as path10 from "path";
|
|
1025
|
-
import
|
|
1181
|
+
import chalk22 from "chalk";
|
|
1026
1182
|
|
|
1027
1183
|
// src/commands/vscode/createLaunchJson.ts
|
|
1028
1184
|
import * as fs4 from "fs";
|
|
1029
1185
|
import * as path9 from "path";
|
|
1030
|
-
import
|
|
1186
|
+
import chalk21 from "chalk";
|
|
1031
1187
|
function ensureVscodeFolder() {
|
|
1032
1188
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
1033
1189
|
if (!fs4.existsSync(vscodeDir)) {
|
|
1034
1190
|
fs4.mkdirSync(vscodeDir);
|
|
1035
|
-
console.log(
|
|
1191
|
+
console.log(chalk21.dim("Created .vscode folder"));
|
|
1036
1192
|
}
|
|
1037
1193
|
}
|
|
1038
1194
|
function removeVscodeFromGitignore() {
|
|
@@ -1047,7 +1203,7 @@ function removeVscodeFromGitignore() {
|
|
|
1047
1203
|
);
|
|
1048
1204
|
if (filteredLines.length !== lines.length) {
|
|
1049
1205
|
fs4.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
1050
|
-
console.log(
|
|
1206
|
+
console.log(chalk21.dim("Removed .vscode references from .gitignore"));
|
|
1051
1207
|
}
|
|
1052
1208
|
}
|
|
1053
1209
|
function createLaunchJson() {
|
|
@@ -1065,7 +1221,7 @@ function createLaunchJson() {
|
|
|
1065
1221
|
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
1066
1222
|
fs4.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
1067
1223
|
`);
|
|
1068
|
-
console.log(
|
|
1224
|
+
console.log(chalk21.green("Created .vscode/launch.json"));
|
|
1069
1225
|
}
|
|
1070
1226
|
function createSettingsJson() {
|
|
1071
1227
|
const settings = {
|
|
@@ -1084,7 +1240,7 @@ function createSettingsJson() {
|
|
|
1084
1240
|
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
1085
1241
|
fs4.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
1086
1242
|
`);
|
|
1087
|
-
console.log(
|
|
1243
|
+
console.log(chalk21.green("Created .vscode/settings.json"));
|
|
1088
1244
|
}
|
|
1089
1245
|
function createExtensionsJson() {
|
|
1090
1246
|
const extensions = {
|
|
@@ -1096,7 +1252,7 @@ function createExtensionsJson() {
|
|
|
1096
1252
|
`${JSON.stringify(extensions, null, " ")}
|
|
1097
1253
|
`
|
|
1098
1254
|
);
|
|
1099
|
-
console.log(
|
|
1255
|
+
console.log(chalk21.green("Created .vscode/extensions.json"));
|
|
1100
1256
|
}
|
|
1101
1257
|
|
|
1102
1258
|
// src/commands/vscode/init.ts
|
|
@@ -1128,16 +1284,16 @@ async function init4() {
|
|
|
1128
1284
|
});
|
|
1129
1285
|
}
|
|
1130
1286
|
if (availableOptions.length === 0) {
|
|
1131
|
-
console.log(
|
|
1287
|
+
console.log(chalk22.green("VS Code configuration already exists!"));
|
|
1132
1288
|
return;
|
|
1133
1289
|
}
|
|
1134
|
-
console.log(
|
|
1290
|
+
console.log(chalk22.bold("Available VS Code configurations to add:\n"));
|
|
1135
1291
|
const selected = await promptMultiselect(
|
|
1136
1292
|
"Select configurations to add:",
|
|
1137
1293
|
availableOptions
|
|
1138
1294
|
);
|
|
1139
1295
|
if (selected.length === 0) {
|
|
1140
|
-
console.log(
|
|
1296
|
+
console.log(chalk22.yellow("No configurations selected"));
|
|
1141
1297
|
return;
|
|
1142
1298
|
}
|
|
1143
1299
|
removeVscodeFromGitignore();
|
|
@@ -1154,7 +1310,7 @@ async function init4() {
|
|
|
1154
1310
|
}
|
|
1155
1311
|
}
|
|
1156
1312
|
console.log(
|
|
1157
|
-
|
|
1313
|
+
chalk22.green(`
|
|
1158
1314
|
Added ${selected.length} VS Code configuration(s)`)
|
|
1159
1315
|
);
|
|
1160
1316
|
}
|
|
@@ -1168,7 +1324,7 @@ async function init5() {
|
|
|
1168
1324
|
// src/commands/lint/runFileNameCheck.ts
|
|
1169
1325
|
import fs7 from "fs";
|
|
1170
1326
|
import path12 from "path";
|
|
1171
|
-
import
|
|
1327
|
+
import chalk23 from "chalk";
|
|
1172
1328
|
|
|
1173
1329
|
// src/shared/findSourceFiles.ts
|
|
1174
1330
|
import fs6 from "fs";
|
|
@@ -1220,16 +1376,16 @@ function checkFileNames() {
|
|
|
1220
1376
|
function runFileNameCheck() {
|
|
1221
1377
|
const violations = checkFileNames();
|
|
1222
1378
|
if (violations.length > 0) {
|
|
1223
|
-
console.error(
|
|
1379
|
+
console.error(chalk23.red("\nFile name check failed:\n"));
|
|
1224
1380
|
console.error(
|
|
1225
|
-
|
|
1381
|
+
chalk23.red(
|
|
1226
1382
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
1227
1383
|
)
|
|
1228
1384
|
);
|
|
1229
1385
|
for (const violation of violations) {
|
|
1230
|
-
console.error(
|
|
1386
|
+
console.error(chalk23.red(` ${violation.filePath}`));
|
|
1231
1387
|
console.error(
|
|
1232
|
-
|
|
1388
|
+
chalk23.gray(
|
|
1233
1389
|
` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
|
|
1234
1390
|
`
|
|
1235
1391
|
)
|
|
@@ -1247,7 +1403,7 @@ function runFileNameCheck() {
|
|
|
1247
1403
|
|
|
1248
1404
|
// src/commands/lint/runStaticImportCheck.ts
|
|
1249
1405
|
import fs8 from "fs";
|
|
1250
|
-
import
|
|
1406
|
+
import chalk24 from "chalk";
|
|
1251
1407
|
function checkForDynamicImports(filePath) {
|
|
1252
1408
|
const content = fs8.readFileSync(filePath, "utf-8");
|
|
1253
1409
|
const lines = content.split("\n");
|
|
@@ -1277,15 +1433,15 @@ function checkStaticImports() {
|
|
|
1277
1433
|
function runStaticImportCheck() {
|
|
1278
1434
|
const violations = checkStaticImports();
|
|
1279
1435
|
if (violations.length > 0) {
|
|
1280
|
-
console.error(
|
|
1436
|
+
console.error(chalk24.red("\nStatic import check failed:\n"));
|
|
1281
1437
|
console.error(
|
|
1282
|
-
|
|
1438
|
+
chalk24.red(
|
|
1283
1439
|
" Dynamic imports (require() and import()) are not allowed. Use static imports instead.\n"
|
|
1284
1440
|
)
|
|
1285
1441
|
);
|
|
1286
1442
|
for (const violation of violations) {
|
|
1287
|
-
console.error(
|
|
1288
|
-
console.error(
|
|
1443
|
+
console.error(chalk24.red(` ${violation.filePath}:${violation.line}`));
|
|
1444
|
+
console.error(chalk24.gray(` ${violation.content}
|
|
1289
1445
|
`));
|
|
1290
1446
|
}
|
|
1291
1447
|
return false;
|
|
@@ -1306,64 +1462,25 @@ function lint() {
|
|
|
1306
1462
|
}
|
|
1307
1463
|
|
|
1308
1464
|
// src/commands/new/newProject.ts
|
|
1309
|
-
import { execSync as
|
|
1310
|
-
import { existsSync as
|
|
1465
|
+
import { execSync as execSync9 } from "child_process";
|
|
1466
|
+
import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
1311
1467
|
async function newProject() {
|
|
1312
1468
|
console.log("Initializing Vite with react-ts template...");
|
|
1313
|
-
|
|
1469
|
+
execSync9("npm create vite@latest . -- --template react-ts", {
|
|
1314
1470
|
stdio: "inherit"
|
|
1315
1471
|
});
|
|
1316
|
-
|
|
1317
|
-
removeEslintConfigFile();
|
|
1472
|
+
removeEslint({ removeLintScripts: true });
|
|
1318
1473
|
addViteBaseConfig();
|
|
1319
1474
|
await init5();
|
|
1320
1475
|
await init();
|
|
1321
1476
|
}
|
|
1322
|
-
function removeEslintFromPackageJson() {
|
|
1323
|
-
const packageJsonPath = "package.json";
|
|
1324
|
-
if (!existsSync9(packageJsonPath)) {
|
|
1325
|
-
console.log("No package.json found, skipping eslint removal");
|
|
1326
|
-
return;
|
|
1327
|
-
}
|
|
1328
|
-
const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
|
|
1329
|
-
let modified = false;
|
|
1330
|
-
if (packageJson.dependencies) {
|
|
1331
|
-
for (const key of Object.keys(packageJson.dependencies)) {
|
|
1332
|
-
if (key.includes("eslint")) {
|
|
1333
|
-
delete packageJson.dependencies[key];
|
|
1334
|
-
modified = true;
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
if (packageJson.devDependencies) {
|
|
1339
|
-
for (const key of Object.keys(packageJson.devDependencies)) {
|
|
1340
|
-
if (key.includes("eslint")) {
|
|
1341
|
-
delete packageJson.devDependencies[key];
|
|
1342
|
-
modified = true;
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
|
-
if (packageJson.scripts) {
|
|
1347
|
-
for (const key of Object.keys(packageJson.scripts)) {
|
|
1348
|
-
if (key.includes("eslint") || key.includes("lint") || packageJson.scripts[key].includes("eslint")) {
|
|
1349
|
-
delete packageJson.scripts[key];
|
|
1350
|
-
modified = true;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
if (modified) {
|
|
1355
|
-
writeFileSync7(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
1356
|
-
`);
|
|
1357
|
-
console.log("Removed eslint references from package.json");
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
1477
|
function addViteBaseConfig() {
|
|
1361
1478
|
const viteConfigPath = "vite.config.ts";
|
|
1362
|
-
if (!
|
|
1479
|
+
if (!existsSync11(viteConfigPath)) {
|
|
1363
1480
|
console.log("No vite.config.ts found, skipping base config");
|
|
1364
1481
|
return;
|
|
1365
1482
|
}
|
|
1366
|
-
const content =
|
|
1483
|
+
const content = readFileSync12(viteConfigPath, "utf-8");
|
|
1367
1484
|
if (content.includes("base:")) {
|
|
1368
1485
|
console.log("vite.config.ts already has base config");
|
|
1369
1486
|
return;
|
|
@@ -1373,39 +1490,20 @@ function addViteBaseConfig() {
|
|
|
1373
1490
|
'defineConfig({\n base: "./",'
|
|
1374
1491
|
);
|
|
1375
1492
|
if (updated !== content) {
|
|
1376
|
-
|
|
1493
|
+
writeFileSync9(viteConfigPath, updated);
|
|
1377
1494
|
console.log('Added base: "./" to vite.config.ts');
|
|
1378
1495
|
}
|
|
1379
1496
|
}
|
|
1380
|
-
function removeEslintConfigFile() {
|
|
1381
|
-
const eslintConfigFiles = [
|
|
1382
|
-
"eslint.config.js",
|
|
1383
|
-
"eslint.config.mjs",
|
|
1384
|
-
"eslint.config.cjs",
|
|
1385
|
-
".eslintrc",
|
|
1386
|
-
".eslintrc.js",
|
|
1387
|
-
".eslintrc.cjs",
|
|
1388
|
-
".eslintrc.json",
|
|
1389
|
-
".eslintrc.yaml",
|
|
1390
|
-
".eslintrc.yml"
|
|
1391
|
-
];
|
|
1392
|
-
for (const configFile of eslintConfigFiles) {
|
|
1393
|
-
if (existsSync9(configFile)) {
|
|
1394
|
-
unlinkSync(configFile);
|
|
1395
|
-
console.log(`Removed ${configFile}`);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
1497
|
|
|
1400
1498
|
// src/commands/prs.ts
|
|
1401
|
-
import { execSync as
|
|
1402
|
-
import
|
|
1403
|
-
import
|
|
1499
|
+
import { execSync as execSync10 } from "child_process";
|
|
1500
|
+
import chalk25 from "chalk";
|
|
1501
|
+
import enquirer4 from "enquirer";
|
|
1404
1502
|
var PAGE_SIZE = 10;
|
|
1405
1503
|
async function prs(options) {
|
|
1406
1504
|
const state = options.open ? "open" : options.closed ? "closed" : "all";
|
|
1407
1505
|
try {
|
|
1408
|
-
const result =
|
|
1506
|
+
const result = execSync10(
|
|
1409
1507
|
`gh pr list --state ${state} --json number,title,url,author,createdAt,mergedAt,closedAt,state,changedFiles --limit 100`,
|
|
1410
1508
|
{ encoding: "utf-8" }
|
|
1411
1509
|
);
|
|
@@ -1434,12 +1532,12 @@ async function displayPaginated(pullRequests) {
|
|
|
1434
1532
|
let currentPage = 0;
|
|
1435
1533
|
const getStatus = (pr) => {
|
|
1436
1534
|
if (pr.state === "MERGED" && pr.mergedAt) {
|
|
1437
|
-
return { label:
|
|
1535
|
+
return { label: chalk25.magenta("merged"), date: pr.mergedAt };
|
|
1438
1536
|
}
|
|
1439
1537
|
if (pr.state === "CLOSED" && pr.closedAt) {
|
|
1440
|
-
return { label:
|
|
1538
|
+
return { label: chalk25.red("closed"), date: pr.closedAt };
|
|
1441
1539
|
}
|
|
1442
|
-
return { label:
|
|
1540
|
+
return { label: chalk25.green("opened"), date: pr.createdAt };
|
|
1443
1541
|
};
|
|
1444
1542
|
const displayPage = (page) => {
|
|
1445
1543
|
const start = page * PAGE_SIZE;
|
|
@@ -1455,9 +1553,9 @@ Page ${page + 1} of ${totalPages} (${pullRequests.length} total)
|
|
|
1455
1553
|
const formattedDate = new Date(status.date).toISOString().split("T")[0];
|
|
1456
1554
|
const fileCount = pr.changedFiles.toLocaleString();
|
|
1457
1555
|
console.log(
|
|
1458
|
-
`${
|
|
1556
|
+
`${chalk25.cyan(`#${pr.number}`)} ${pr.title} ${chalk25.dim(`(${pr.author.login},`)} ${status.label} ${chalk25.dim(`${formattedDate})`)}`
|
|
1459
1557
|
);
|
|
1460
|
-
console.log(
|
|
1558
|
+
console.log(chalk25.dim(` ${fileCount} files | ${pr.url}`));
|
|
1461
1559
|
console.log();
|
|
1462
1560
|
}
|
|
1463
1561
|
};
|
|
@@ -1472,7 +1570,7 @@ Page ${page + 1} of ${totalPages} (${pullRequests.length} total)
|
|
|
1472
1570
|
if (hasNext) choices.push({ name: "Next page", value: "next" });
|
|
1473
1571
|
if (hasPrev) choices.push({ name: "Previous page", value: "prev" });
|
|
1474
1572
|
choices.push({ name: "Quit", value: "quit" });
|
|
1475
|
-
const { action } = await
|
|
1573
|
+
const { action } = await enquirer4.prompt({
|
|
1476
1574
|
type: "select",
|
|
1477
1575
|
name: "action",
|
|
1478
1576
|
message: "Navigate",
|
|
@@ -1495,7 +1593,7 @@ import { spawn } from "child_process";
|
|
|
1495
1593
|
import * as path13 from "path";
|
|
1496
1594
|
|
|
1497
1595
|
// src/commands/refactor/getViolations.ts
|
|
1498
|
-
import { execSync as
|
|
1596
|
+
import { execSync as execSync11 } from "child_process";
|
|
1499
1597
|
import fs10 from "fs";
|
|
1500
1598
|
import { minimatch } from "minimatch";
|
|
1501
1599
|
|
|
@@ -1535,7 +1633,7 @@ function getIgnoredFiles() {
|
|
|
1535
1633
|
}
|
|
1536
1634
|
|
|
1537
1635
|
// src/commands/refactor/logViolations.ts
|
|
1538
|
-
import
|
|
1636
|
+
import chalk26 from "chalk";
|
|
1539
1637
|
var DEFAULT_MAX_LINES = 100;
|
|
1540
1638
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
1541
1639
|
if (violations.length === 0) {
|
|
@@ -1544,43 +1642,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
1544
1642
|
}
|
|
1545
1643
|
return;
|
|
1546
1644
|
}
|
|
1547
|
-
console.error(
|
|
1645
|
+
console.error(chalk26.red(`
|
|
1548
1646
|
Refactor check failed:
|
|
1549
1647
|
`));
|
|
1550
|
-
console.error(
|
|
1648
|
+
console.error(chalk26.red(` The following files exceed ${maxLines} lines:
|
|
1551
1649
|
`));
|
|
1552
1650
|
for (const violation of violations) {
|
|
1553
|
-
console.error(
|
|
1651
|
+
console.error(chalk26.red(` ${violation.file} (${violation.lines} lines)`));
|
|
1554
1652
|
}
|
|
1555
1653
|
console.error(
|
|
1556
|
-
|
|
1654
|
+
chalk26.yellow(
|
|
1557
1655
|
`
|
|
1558
1656
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
1559
1657
|
way to refactor it, ignore it with:
|
|
1560
1658
|
`
|
|
1561
1659
|
)
|
|
1562
1660
|
);
|
|
1563
|
-
console.error(
|
|
1661
|
+
console.error(chalk26.gray(` assist refactor ignore <file>
|
|
1564
1662
|
`));
|
|
1565
1663
|
if (process.env.CLAUDECODE) {
|
|
1566
|
-
console.error(
|
|
1664
|
+
console.error(chalk26.cyan(`
|
|
1567
1665
|
## Extracting Code to New Files
|
|
1568
1666
|
`));
|
|
1569
1667
|
console.error(
|
|
1570
|
-
|
|
1668
|
+
chalk26.cyan(
|
|
1571
1669
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
1572
1670
|
`
|
|
1573
1671
|
)
|
|
1574
1672
|
);
|
|
1575
1673
|
console.error(
|
|
1576
|
-
|
|
1674
|
+
chalk26.cyan(
|
|
1577
1675
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
1578
1676
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
1579
1677
|
`
|
|
1580
1678
|
)
|
|
1581
1679
|
);
|
|
1582
1680
|
console.error(
|
|
1583
|
-
|
|
1681
|
+
chalk26.cyan(
|
|
1584
1682
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
1585
1683
|
domains, move it to a common/shared folder.
|
|
1586
1684
|
`
|
|
@@ -1600,7 +1698,7 @@ function getGitFiles(options) {
|
|
|
1600
1698
|
}
|
|
1601
1699
|
const files = /* @__PURE__ */ new Set();
|
|
1602
1700
|
if (options.staged || options.modified) {
|
|
1603
|
-
const staged =
|
|
1701
|
+
const staged = execSync11("git diff --cached --name-only", {
|
|
1604
1702
|
encoding: "utf-8"
|
|
1605
1703
|
});
|
|
1606
1704
|
for (const file of staged.trim().split("\n").filter(Boolean)) {
|
|
@@ -1608,7 +1706,7 @@ function getGitFiles(options) {
|
|
|
1608
1706
|
}
|
|
1609
1707
|
}
|
|
1610
1708
|
if (options.unstaged || options.modified) {
|
|
1611
|
-
const unstaged =
|
|
1709
|
+
const unstaged = execSync11("git diff --name-only", { encoding: "utf-8" });
|
|
1612
1710
|
for (const file of unstaged.trim().split("\n").filter(Boolean)) {
|
|
1613
1711
|
files.add(file);
|
|
1614
1712
|
}
|
|
@@ -1697,11 +1795,11 @@ async function check(pattern2, options) {
|
|
|
1697
1795
|
|
|
1698
1796
|
// src/commands/refactor/ignore.ts
|
|
1699
1797
|
import fs11 from "fs";
|
|
1700
|
-
import
|
|
1798
|
+
import chalk27 from "chalk";
|
|
1701
1799
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
1702
1800
|
function ignore(file) {
|
|
1703
1801
|
if (!fs11.existsSync(file)) {
|
|
1704
|
-
console.error(
|
|
1802
|
+
console.error(chalk27.red(`Error: File does not exist: ${file}`));
|
|
1705
1803
|
process.exit(1);
|
|
1706
1804
|
}
|
|
1707
1805
|
const content = fs11.readFileSync(file, "utf-8");
|
|
@@ -1717,7 +1815,7 @@ function ignore(file) {
|
|
|
1717
1815
|
fs11.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
1718
1816
|
}
|
|
1719
1817
|
console.log(
|
|
1720
|
-
|
|
1818
|
+
chalk27.green(
|
|
1721
1819
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
1722
1820
|
)
|
|
1723
1821
|
);
|
|
@@ -1789,6 +1887,33 @@ function add() {
|
|
|
1789
1887
|
console.log(`Added run configuration: ${name} -> ${display}`);
|
|
1790
1888
|
}
|
|
1791
1889
|
|
|
1890
|
+
// src/commands/statusLine.ts
|
|
1891
|
+
import * as readline from "readline";
|
|
1892
|
+
function formatNumber(num) {
|
|
1893
|
+
return num.toLocaleString("en-US");
|
|
1894
|
+
}
|
|
1895
|
+
async function statusLine() {
|
|
1896
|
+
const rl = readline.createInterface({
|
|
1897
|
+
input: process.stdin,
|
|
1898
|
+
output: process.stdout,
|
|
1899
|
+
terminal: false
|
|
1900
|
+
});
|
|
1901
|
+
let inputData = "";
|
|
1902
|
+
for await (const line of rl) {
|
|
1903
|
+
inputData += line;
|
|
1904
|
+
}
|
|
1905
|
+
const data = JSON.parse(inputData);
|
|
1906
|
+
const model = data.model.display_name;
|
|
1907
|
+
const totalInput = data.context_window.total_input_tokens;
|
|
1908
|
+
const totalOutput = data.context_window.total_output_tokens;
|
|
1909
|
+
const usedPct = data.context_window.used_percentage ?? 0;
|
|
1910
|
+
const formattedInput = formatNumber(totalInput);
|
|
1911
|
+
const formattedOutput = formatNumber(totalOutput);
|
|
1912
|
+
console.log(
|
|
1913
|
+
`${model} | Tokens - ${formattedOutput} \u2191 : ${formattedInput} \u2193 | Context - ${usedPct}%`
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1792
1917
|
// src/commands/sync.ts
|
|
1793
1918
|
import * as fs13 from "fs";
|
|
1794
1919
|
import * as os from "os";
|
|
@@ -1798,8 +1923,7 @@ import { fileURLToPath as fileURLToPath4 } from "url";
|
|
|
1798
1923
|
// src/commands/sync/syncSettings.ts
|
|
1799
1924
|
import * as fs12 from "fs";
|
|
1800
1925
|
import * as path14 from "path";
|
|
1801
|
-
import
|
|
1802
|
-
import enquirer6 from "enquirer";
|
|
1926
|
+
import chalk28 from "chalk";
|
|
1803
1927
|
async function syncSettings(claudeDir, targetBase) {
|
|
1804
1928
|
const source = path14.join(claudeDir, "settings.json");
|
|
1805
1929
|
const target = path14.join(targetBase, "settings.json");
|
|
@@ -1810,16 +1934,14 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
1810
1934
|
const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
|
|
1811
1935
|
if (normalizedSource !== normalizedTarget) {
|
|
1812
1936
|
console.log(
|
|
1813
|
-
|
|
1937
|
+
chalk28.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
|
|
1814
1938
|
);
|
|
1815
1939
|
console.log();
|
|
1816
1940
|
printDiff(targetContent, sourceContent);
|
|
1817
|
-
const
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
initial: false
|
|
1822
|
-
});
|
|
1941
|
+
const confirm = await promptConfirm(
|
|
1942
|
+
chalk28.red("Overwrite existing settings.json?"),
|
|
1943
|
+
false
|
|
1944
|
+
);
|
|
1823
1945
|
if (!confirm) {
|
|
1824
1946
|
console.log("Skipped settings.json");
|
|
1825
1947
|
return;
|
|
@@ -1852,11 +1974,11 @@ function syncCommands(claudeDir, targetBase) {
|
|
|
1852
1974
|
}
|
|
1853
1975
|
|
|
1854
1976
|
// src/commands/verify/hardcodedColors.ts
|
|
1855
|
-
import { execSync as
|
|
1977
|
+
import { execSync as execSync12 } from "child_process";
|
|
1856
1978
|
var pattern = "0x[0-9a-fA-F]{6}|#[0-9a-fA-F]{3,6}";
|
|
1857
1979
|
function hardcodedColors() {
|
|
1858
1980
|
try {
|
|
1859
|
-
const output =
|
|
1981
|
+
const output = execSync12(`grep -rEnH '${pattern}' src/`, {
|
|
1860
1982
|
encoding: "utf-8"
|
|
1861
1983
|
});
|
|
1862
1984
|
const lines = output.trim().split("\n");
|
|
@@ -1966,7 +2088,7 @@ program.command("init").description("Initialize VS Code and verify configuration
|
|
|
1966
2088
|
program.command("commit <message>").description("Create a git commit with validation").action(commit);
|
|
1967
2089
|
program.command("update").description("Update claude-code to the latest version").action(() => {
|
|
1968
2090
|
console.log("Updating claude-code...");
|
|
1969
|
-
|
|
2091
|
+
execSync13("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
|
|
1970
2092
|
});
|
|
1971
2093
|
program.command("prs").description("List pull requests for the current repository").option("--open", "List only open pull requests").option("--closed", "List only closed pull requests").action(prs);
|
|
1972
2094
|
var runCommand = program.command("run").description("Run a configured command from assist.yml").argument("<name>", "Name of the configured command").argument("[args...]", "Arguments to pass to the command").allowUnknownOption().action((name, args) => {
|
|
@@ -1999,5 +2121,7 @@ var vscodeCommand = program.command("vscode").description("VS Code configuration
|
|
|
1999
2121
|
vscodeCommand.command("init").description("Add VS Code configuration files").action(init4);
|
|
2000
2122
|
var deployCommand = program.command("deploy").description("Netlify deployment utilities");
|
|
2001
2123
|
deployCommand.command("init").description("Initialize Netlify project and configure deployment").action(init);
|
|
2124
|
+
deployCommand.command("redirect").description("Add trailing slash redirect script to index.html").action(redirect);
|
|
2002
2125
|
program.command("enable-ralph").description("Enable ralph-wiggum plugin for spacetraders").action(enableRalph);
|
|
2126
|
+
program.command("status-line").description("Format Claude Code status line from JSON stdin").action(statusLine);
|
|
2003
2127
|
program.parse();
|