@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/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 execSync12 } from "child_process";
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 (!existsSync(WORKFLOW_PATH)) {
152
+ if (!existsSync2(WORKFLOW_PATH)) {
73
153
  return null;
74
154
  }
75
- const content = readFileSync(WORKFLOW_PATH, "utf-8");
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 = join(__dirname2, "commands/deploy/build.yml");
81
- const template = readFileSync(templatePath, "utf-8");
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 (!existsSync(workflowDir)) {
167
+ if (!existsSync2(workflowDir)) {
88
168
  mkdirSync(workflowDir, { recursive: true });
89
169
  }
90
- if (existsSync(WORKFLOW_PATH)) {
91
- const oldContent = readFileSync(WORKFLOW_PATH, "utf-8");
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 { confirm } = await enquirer.prompt({
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
- writeFileSync(WORKFLOW_PATH, newContent);
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
- execSync2("netlify sites:create --disable-linking", {
125
- stdio: "inherit"
126
- });
127
- const { siteId } = await enquirer.prompt({
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 chalk4 from "chalk";
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 chalk3 from "chalk";
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 readFileSync3 } from "fs";
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 = readFileSync3(join3(DEVLOG_DIR, file), "utf-8");
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(` ${chalk3.yellow(commit2.hash)} ${commit2.message}`);
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(` ${chalk3.dim(file)}`);
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(`${chalk4.bold.blue(date)} ${chalk4.dim("skipped")}`);
405
+ console.log(`${chalk5.bold.blue(date)} ${chalk5.dim("skipped")}`);
324
406
  } else if (entries && entries.length > 0) {
325
- const entryInfo = entries.map((e) => `${chalk4.green(e.version)} ${e.title}`).join(" | ");
326
- console.log(`${chalk4.bold.blue(date)} ${entryInfo}`);
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(`${chalk4.bold.blue(date)} ${chalk4.red("\u26A0 devlog missing")}`);
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 chalk5 from "chalk";
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(chalk5.dim("No commits after last versioned entry"));
488
+ console.log(chalk6.dim("No commits after last versioned entry"));
407
489
  } else {
408
- console.log(chalk5.dim("No commits found"));
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(`${chalk5.bold("name:")} ${repoName}`);
495
+ console.log(`${chalk6.bold("name:")} ${repoName}`);
414
496
  if (patchVersion && minorVersion) {
415
497
  console.log(
416
- `${chalk5.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
498
+ `${chalk6.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
417
499
  );
418
500
  } else {
419
- console.log(`${chalk5.bold("version:")} v0.1 (initial)`);
501
+ console.log(`${chalk6.bold("version:")} v0.1 (initial)`);
420
502
  }
421
- console.log(`${chalk5.bold.blue(targetDate)}`);
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 chalk6 from "chalk";
508
+ import chalk7 from "chalk";
427
509
  function skip(date) {
428
510
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
429
- console.log(chalk6.red("Invalid date format. Use YYYY-MM-DD"));
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(chalk6.yellow(`${date} is already in skip list`));
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(chalk6.green(`Added ${date} to skip list`));
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 readFileSync4 } from "fs";
534
+ import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
453
535
  import { join as join4 } from "path";
454
- import chalk7 from "chalk";
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 = readFileSync4(join4(DEVLOG_DIR, file), "utf-8");
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(`${chalk7.bold("name:")} ${name}`);
492
- console.log(`${chalk7.bold("last:")} ${lastVersion ?? chalk7.dim("none")}`);
493
- console.log(`${chalk7.bold("next:")} ${nextVersion ?? chalk7.dim("none")}`);
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 chalk8 from "chalk";
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(chalk8.green("settings.local.json already has ralph enabled"));
620
+ console.log(chalk9.green("settings.local.json already has ralph enabled"));
540
621
  return;
541
622
  }
542
- console.log(chalk8.yellow("\nChanges to settings.local.json:"));
623
+ console.log(chalk9.yellow("\nChanges to settings.local.json:"));
543
624
  console.log();
544
625
  printDiff(targetContent, mergedContent);
545
- const { confirm } = await enquirer2.prompt({
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 chalk19 from "chalk";
636
+ import chalk20 from "chalk";
561
637
 
562
638
  // src/shared/promptMultiselect.ts
563
- import chalk9 from "chalk";
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} - ${chalk9.dim(opt.description)}`
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 chalk10 from "chalk";
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(chalk10.red("No package.json found in current directory"));
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 chalk12 from "chalk";
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 chalk11 from "chalk";
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(chalk11.dim(`Installing ${name}...`));
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(chalk11.red(`Failed to install ${name}`));
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(chalk11.dim(`Added '${binary}' to knip.json ignoreBinaries`));
763
+ console.log(chalk12.dim(`Added '${binary}' to knip.json ignoreBinaries`));
681
764
  }
682
765
  } catch {
683
- console.log(chalk11.yellow("Warning: Could not update knip.json"));
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(chalk12.blue("\nSetting up build verification..."));
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(chalk12.dim(`Using: ${command}`));
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 chalk13 from "chalk";
794
+ import chalk14 from "chalk";
712
795
  async function setupDuplicateCode(packageJsonPath) {
713
- console.log(chalk13.blue("\nSetting up jscpd..."));
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 chalk14 from "chalk";
812
+ import chalk15 from "chalk";
730
813
  async function setupHardcodedColors(packageJsonPath, hasOpenColor) {
731
- console.log(chalk14.blue("\nSetting up hardcoded colors check..."));
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 chalk15 from "chalk";
829
+ import chalk16 from "chalk";
747
830
  async function setupKnip(packageJsonPath) {
748
- console.log(chalk15.blue("\nSetting up knip..."));
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 chalk17 from "chalk";
846
+ import chalk18 from "chalk";
764
847
 
765
848
  // src/commands/lint/init.ts
766
- import { execSync as execSync7 } from "child_process";
767
- import { existsSync as existsSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
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 chalk16 from "chalk";
771
- import enquirer4 from "enquirer";
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 (!existsSync6(biomeConfigPath)) {
936
+ if (!existsSync8(biomeConfigPath)) {
776
937
  console.log("Initializing Biome...");
777
- execSync7("npx @biomejs/biome init", { stdio: "inherit" });
938
+ execSync8("npx @biomejs/biome init", { stdio: "inherit" });
778
939
  }
779
- if (!existsSync6(biomeConfigPath)) {
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(readFileSync8(linterConfigPath, "utf-8"));
785
- const biomeConfig = JSON.parse(readFileSync8(biomeConfigPath, "utf-8"));
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(chalk16.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
959
+ console.log(chalk17.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
799
960
  console.log();
800
961
  printDiff(oldContent, newContent);
801
- const { confirm } = await enquirer4.prompt({
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
- writeFileSync5(biomeConfigPath, newContent);
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(chalk17.blue("\nSetting up biome..."));
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 chalk18 from "chalk";
991
+ import chalk19 from "chalk";
836
992
  async function setupTest(packageJsonPath) {
837
- console.log(chalk18.blue("\nSetting up vitest..."));
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(chalk19.green("All verify scripts are already configured!"));
1136
+ console.log(chalk20.green("All verify scripts are already configured!"));
981
1137
  return;
982
1138
  }
983
- console.log(chalk19.bold("Available verify scripts to add:\n"));
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(chalk19.yellow("No scripts selected"));
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(chalk19.green(`
1170
+ console.log(chalk20.green(`
1015
1171
  Added ${selected.length} verify script(s):`));
1016
1172
  for (const choice of selected) {
1017
- console.log(chalk19.green(` - verify:${choice}`));
1173
+ console.log(chalk20.green(` - verify:${choice}`));
1018
1174
  }
1019
- console.log(chalk19.dim("\nRun 'assist verify' to run all verify scripts"));
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 chalk21 from "chalk";
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 chalk20 from "chalk";
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(chalk20.dim("Created .vscode folder"));
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(chalk20.dim("Removed .vscode references from .gitignore"));
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(chalk20.green("Created .vscode/launch.json"));
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(chalk20.green("Created .vscode/settings.json"));
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(chalk20.green("Created .vscode/extensions.json"));
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(chalk21.green("VS Code configuration already exists!"));
1287
+ console.log(chalk22.green("VS Code configuration already exists!"));
1132
1288
  return;
1133
1289
  }
1134
- console.log(chalk21.bold("Available VS Code configurations to add:\n"));
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(chalk21.yellow("No configurations selected"));
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
- chalk21.green(`
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 chalk22 from "chalk";
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(chalk22.red("\nFile name check failed:\n"));
1379
+ console.error(chalk23.red("\nFile name check failed:\n"));
1224
1380
  console.error(
1225
- chalk22.red(
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(chalk22.red(` ${violation.filePath}`));
1386
+ console.error(chalk23.red(` ${violation.filePath}`));
1231
1387
  console.error(
1232
- chalk22.gray(
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 chalk23 from "chalk";
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(chalk23.red("\nStatic import check failed:\n"));
1436
+ console.error(chalk24.red("\nStatic import check failed:\n"));
1281
1437
  console.error(
1282
- chalk23.red(
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(chalk23.red(` ${violation.filePath}:${violation.line}`));
1288
- console.error(chalk23.gray(` ${violation.content}
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 execSync8 } from "child_process";
1310
- import { existsSync as existsSync9, readFileSync as readFileSync10, unlinkSync, writeFileSync as writeFileSync7 } from "fs";
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
- execSync8("npm create vite@latest . -- --template react-ts", {
1469
+ execSync9("npm create vite@latest . -- --template react-ts", {
1314
1470
  stdio: "inherit"
1315
1471
  });
1316
- removeEslintFromPackageJson();
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 (!existsSync9(viteConfigPath)) {
1479
+ if (!existsSync11(viteConfigPath)) {
1363
1480
  console.log("No vite.config.ts found, skipping base config");
1364
1481
  return;
1365
1482
  }
1366
- const content = readFileSync10(viteConfigPath, "utf-8");
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
- writeFileSync7(viteConfigPath, updated);
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 execSync9 } from "child_process";
1402
- import chalk24 from "chalk";
1403
- import enquirer5 from "enquirer";
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 = execSync9(
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: chalk24.magenta("merged"), date: pr.mergedAt };
1535
+ return { label: chalk25.magenta("merged"), date: pr.mergedAt };
1438
1536
  }
1439
1537
  if (pr.state === "CLOSED" && pr.closedAt) {
1440
- return { label: chalk24.red("closed"), date: pr.closedAt };
1538
+ return { label: chalk25.red("closed"), date: pr.closedAt };
1441
1539
  }
1442
- return { label: chalk24.green("opened"), date: pr.createdAt };
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
- `${chalk24.cyan(`#${pr.number}`)} ${pr.title} ${chalk24.dim(`(${pr.author.login},`)} ${status.label} ${chalk24.dim(`${formattedDate})`)}`
1556
+ `${chalk25.cyan(`#${pr.number}`)} ${pr.title} ${chalk25.dim(`(${pr.author.login},`)} ${status.label} ${chalk25.dim(`${formattedDate})`)}`
1459
1557
  );
1460
- console.log(chalk24.dim(` ${fileCount} files | ${pr.url}`));
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 enquirer5.prompt({
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 execSync10 } from "child_process";
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 chalk25 from "chalk";
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(chalk25.red(`
1645
+ console.error(chalk26.red(`
1548
1646
  Refactor check failed:
1549
1647
  `));
1550
- console.error(chalk25.red(` The following files exceed ${maxLines} lines:
1648
+ console.error(chalk26.red(` The following files exceed ${maxLines} lines:
1551
1649
  `));
1552
1650
  for (const violation of violations) {
1553
- console.error(chalk25.red(` ${violation.file} (${violation.lines} lines)`));
1651
+ console.error(chalk26.red(` ${violation.file} (${violation.lines} lines)`));
1554
1652
  }
1555
1653
  console.error(
1556
- chalk25.yellow(
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(chalk25.gray(` assist refactor ignore <file>
1661
+ console.error(chalk26.gray(` assist refactor ignore <file>
1564
1662
  `));
1565
1663
  if (process.env.CLAUDECODE) {
1566
- console.error(chalk25.cyan(`
1664
+ console.error(chalk26.cyan(`
1567
1665
  ## Extracting Code to New Files
1568
1666
  `));
1569
1667
  console.error(
1570
- chalk25.cyan(
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
- chalk25.cyan(
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
- chalk25.cyan(
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 = execSync10("git diff --cached --name-only", {
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 = execSync10("git diff --name-only", { encoding: "utf-8" });
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 chalk26 from "chalk";
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(chalk26.red(`Error: File does not exist: ${file}`));
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
- chalk26.green(
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 chalk27 from "chalk";
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
- chalk27.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
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 { confirm } = await enquirer6.prompt({
1818
- type: "confirm",
1819
- name: "confirm",
1820
- message: chalk27.red("Overwrite existing settings.json?"),
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 execSync11 } from "child_process";
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 = execSync11(`grep -rEnH '${pattern}' src/`, {
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
- execSync12("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
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();