@staff0rd/assist 0.13.3 → 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 +10 -0
- package/dist/commands/deploy/redirect.ts +39 -0
- package/dist/index.js +150 -120
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
A CLI tool for enforcing determinism in LLM development workflow automation.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
|
+
You can install `assist` globally using npm:
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install -g @staff0rd/assist
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Local Development
|
|
6
13
|
|
|
7
14
|
```bash
|
|
8
15
|
# Clone the repository
|
|
@@ -27,6 +34,9 @@ After installation, the `assist` command will be available globally.
|
|
|
27
34
|
- `assist new` - Initialize a new Vite React TypeScript project
|
|
28
35
|
- `assist sync` - Copy command files to `~/.claude/commands`
|
|
29
36
|
- `assist commit <message>` - Create a git commit with validation
|
|
37
|
+
- `assist prs` - List pull requests for the current repository
|
|
38
|
+
- `assist run <name>` - Run a configured command from assist.yml
|
|
39
|
+
- `assist run add` - Add a new run configuration to assist.yml
|
|
30
40
|
- `assist update` - Update claude-code to the latest version
|
|
31
41
|
- `assist verify` - Run all verify:* scripts from package.json in parallel
|
|
32
42
|
- `assist verify init` - Add verify scripts to a project
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
|
|
4
|
+
const TRAILING_SLASH_SCRIPT = ` <script>
|
|
5
|
+
if (!window.location.pathname.endsWith('/')) {
|
|
6
|
+
window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
|
|
7
|
+
}
|
|
8
|
+
</script>`;
|
|
9
|
+
|
|
10
|
+
export function redirect(): void {
|
|
11
|
+
const indexPath = "index.html";
|
|
12
|
+
|
|
13
|
+
if (!existsSync(indexPath)) {
|
|
14
|
+
console.log(chalk.yellow("No index.html found"));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const content = readFileSync(indexPath, "utf-8");
|
|
19
|
+
|
|
20
|
+
if (content.includes("window.location.pathname.endsWith('/')")) {
|
|
21
|
+
console.log(chalk.dim("Trailing slash script already present"));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const headCloseIndex = content.indexOf("</head>");
|
|
26
|
+
if (headCloseIndex === -1) {
|
|
27
|
+
console.log(chalk.red("Could not find </head> tag in index.html"));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const newContent =
|
|
32
|
+
content.slice(0, headCloseIndex) +
|
|
33
|
+
TRAILING_SLASH_SCRIPT +
|
|
34
|
+
"\n " +
|
|
35
|
+
content.slice(headCloseIndex);
|
|
36
|
+
|
|
37
|
+
writeFileSync(indexPath, newContent);
|
|
38
|
+
console.log(chalk.green("Added trailing slash redirect to index.html"));
|
|
39
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -246,17 +246,46 @@ async function init() {
|
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
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
|
+
|
|
249
278
|
// src/commands/devlog/list.ts
|
|
250
279
|
import { execSync as execSync4 } from "child_process";
|
|
251
280
|
import { basename as basename2 } from "path";
|
|
252
|
-
import
|
|
281
|
+
import chalk5 from "chalk";
|
|
253
282
|
|
|
254
283
|
// src/commands/devlog/shared.ts
|
|
255
284
|
import { execSync as execSync3 } from "child_process";
|
|
256
|
-
import
|
|
285
|
+
import chalk4 from "chalk";
|
|
257
286
|
|
|
258
287
|
// src/commands/devlog/loadDevlogEntries.ts
|
|
259
|
-
import { readdirSync, readFileSync as
|
|
288
|
+
import { readdirSync, readFileSync as readFileSync4 } from "fs";
|
|
260
289
|
import { homedir } from "os";
|
|
261
290
|
import { join as join3 } from "path";
|
|
262
291
|
var DEVLOG_DIR = join3(homedir(), "git/blog/src/content/devlog");
|
|
@@ -265,7 +294,7 @@ function loadDevlogEntries(repoName) {
|
|
|
265
294
|
try {
|
|
266
295
|
const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
|
|
267
296
|
for (const file of files) {
|
|
268
|
-
const content =
|
|
297
|
+
const content = readFileSync4(join3(DEVLOG_DIR, file), "utf-8");
|
|
269
298
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
270
299
|
if (frontmatterMatch) {
|
|
271
300
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -314,13 +343,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
|
|
|
314
343
|
}
|
|
315
344
|
function printCommitsWithFiles(commits, ignore2, verbose) {
|
|
316
345
|
for (const commit2 of commits) {
|
|
317
|
-
console.log(` ${
|
|
346
|
+
console.log(` ${chalk4.yellow(commit2.hash)} ${commit2.message}`);
|
|
318
347
|
if (verbose) {
|
|
319
348
|
const visibleFiles = commit2.files.filter(
|
|
320
349
|
(file) => !ignore2.some((p) => file.startsWith(p))
|
|
321
350
|
);
|
|
322
351
|
for (const file of visibleFiles) {
|
|
323
|
-
console.log(` ${
|
|
352
|
+
console.log(` ${chalk4.dim(file)}`);
|
|
324
353
|
}
|
|
325
354
|
}
|
|
326
355
|
}
|
|
@@ -373,12 +402,12 @@ function list(options) {
|
|
|
373
402
|
isFirst = false;
|
|
374
403
|
const entries = devlogEntries.get(date);
|
|
375
404
|
if (skipDays.has(date)) {
|
|
376
|
-
console.log(`${
|
|
405
|
+
console.log(`${chalk5.bold.blue(date)} ${chalk5.dim("skipped")}`);
|
|
377
406
|
} else if (entries && entries.length > 0) {
|
|
378
|
-
const entryInfo = entries.map((e) => `${
|
|
379
|
-
console.log(`${
|
|
407
|
+
const entryInfo = entries.map((e) => `${chalk5.green(e.version)} ${e.title}`).join(" | ");
|
|
408
|
+
console.log(`${chalk5.bold.blue(date)} ${entryInfo}`);
|
|
380
409
|
} else {
|
|
381
|
-
console.log(`${
|
|
410
|
+
console.log(`${chalk5.bold.blue(date)} ${chalk5.red("\u26A0 devlog missing")}`);
|
|
382
411
|
}
|
|
383
412
|
printCommitsWithFiles(dateCommits, ignore2, options.verbose ?? false);
|
|
384
413
|
}
|
|
@@ -386,7 +415,7 @@ function list(options) {
|
|
|
386
415
|
|
|
387
416
|
// src/commands/devlog/next.ts
|
|
388
417
|
import { execSync as execSync5 } from "child_process";
|
|
389
|
-
import
|
|
418
|
+
import chalk6 from "chalk";
|
|
390
419
|
|
|
391
420
|
// src/commands/devlog/getLastVersionInfo.ts
|
|
392
421
|
import semver from "semver";
|
|
@@ -456,36 +485,36 @@ function next(options) {
|
|
|
456
485
|
const targetDate = dates[0];
|
|
457
486
|
if (!targetDate) {
|
|
458
487
|
if (lastInfo) {
|
|
459
|
-
console.log(
|
|
488
|
+
console.log(chalk6.dim("No commits after last versioned entry"));
|
|
460
489
|
} else {
|
|
461
|
-
console.log(
|
|
490
|
+
console.log(chalk6.dim("No commits found"));
|
|
462
491
|
}
|
|
463
492
|
return;
|
|
464
493
|
}
|
|
465
494
|
const commits = commitsByDate.get(targetDate) ?? [];
|
|
466
|
-
console.log(`${
|
|
495
|
+
console.log(`${chalk6.bold("name:")} ${repoName}`);
|
|
467
496
|
if (patchVersion && minorVersion) {
|
|
468
497
|
console.log(
|
|
469
|
-
`${
|
|
498
|
+
`${chalk6.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
|
|
470
499
|
);
|
|
471
500
|
} else {
|
|
472
|
-
console.log(`${
|
|
501
|
+
console.log(`${chalk6.bold("version:")} v0.1 (initial)`);
|
|
473
502
|
}
|
|
474
|
-
console.log(`${
|
|
503
|
+
console.log(`${chalk6.bold.blue(targetDate)}`);
|
|
475
504
|
printCommitsWithFiles(commits, ignore2, options.verbose ?? false);
|
|
476
505
|
}
|
|
477
506
|
|
|
478
507
|
// src/commands/devlog/skip.ts
|
|
479
|
-
import
|
|
508
|
+
import chalk7 from "chalk";
|
|
480
509
|
function skip(date) {
|
|
481
510
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
482
|
-
console.log(
|
|
511
|
+
console.log(chalk7.red("Invalid date format. Use YYYY-MM-DD"));
|
|
483
512
|
process.exit(1);
|
|
484
513
|
}
|
|
485
514
|
const config = loadConfig();
|
|
486
515
|
const skipDays = config.devlog?.skip?.days ?? [];
|
|
487
516
|
if (skipDays.includes(date)) {
|
|
488
|
-
console.log(
|
|
517
|
+
console.log(chalk7.yellow(`${date} is already in skip list`));
|
|
489
518
|
return;
|
|
490
519
|
}
|
|
491
520
|
skipDays.push(date);
|
|
@@ -498,19 +527,19 @@ function skip(date) {
|
|
|
498
527
|
}
|
|
499
528
|
};
|
|
500
529
|
saveConfig(config);
|
|
501
|
-
console.log(
|
|
530
|
+
console.log(chalk7.green(`Added ${date} to skip list`));
|
|
502
531
|
}
|
|
503
532
|
|
|
504
533
|
// src/commands/devlog/version.ts
|
|
505
|
-
import { readdirSync as readdirSync2, readFileSync as
|
|
534
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
506
535
|
import { join as join4 } from "path";
|
|
507
|
-
import
|
|
536
|
+
import chalk8 from "chalk";
|
|
508
537
|
import semver2 from "semver";
|
|
509
538
|
function getLatestVersion(repoName) {
|
|
510
539
|
try {
|
|
511
540
|
const files = readdirSync2(DEVLOG_DIR).filter((f) => f.endsWith(".md")).sort().reverse();
|
|
512
541
|
for (const file of files) {
|
|
513
|
-
const content =
|
|
542
|
+
const content = readFileSync5(join4(DEVLOG_DIR, file), "utf-8");
|
|
514
543
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
515
544
|
if (frontmatterMatch) {
|
|
516
545
|
const frontmatter = frontmatterMatch[1];
|
|
@@ -541,16 +570,16 @@ function version() {
|
|
|
541
570
|
const name = getRepoName();
|
|
542
571
|
const lastVersion = getLatestVersion(name);
|
|
543
572
|
const nextVersion = lastVersion ? bumpPatchVersion(lastVersion) : null;
|
|
544
|
-
console.log(`${
|
|
545
|
-
console.log(`${
|
|
546
|
-
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")}`);
|
|
547
576
|
}
|
|
548
577
|
|
|
549
578
|
// src/commands/enable-ralph/index.ts
|
|
550
579
|
import * as fs from "fs";
|
|
551
580
|
import * as path from "path";
|
|
552
581
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
553
|
-
import
|
|
582
|
+
import chalk9 from "chalk";
|
|
554
583
|
var __dirname3 = path.dirname(fileURLToPath2(import.meta.url));
|
|
555
584
|
function deepMerge(target, source) {
|
|
556
585
|
const result = { ...target };
|
|
@@ -588,10 +617,10 @@ async function enableRalph() {
|
|
|
588
617
|
const merged = deepMerge(targetData, sourceData);
|
|
589
618
|
const mergedContent = JSON.stringify(merged, null, " ") + "\n";
|
|
590
619
|
if (mergedContent === targetContent) {
|
|
591
|
-
console.log(
|
|
620
|
+
console.log(chalk9.green("settings.local.json already has ralph enabled"));
|
|
592
621
|
return;
|
|
593
622
|
}
|
|
594
|
-
console.log(
|
|
623
|
+
console.log(chalk9.yellow("\nChanges to settings.local.json:"));
|
|
595
624
|
console.log();
|
|
596
625
|
printDiff(targetContent, mergedContent);
|
|
597
626
|
const confirm = await promptConfirm("Apply these changes?");
|
|
@@ -604,10 +633,10 @@ async function enableRalph() {
|
|
|
604
633
|
}
|
|
605
634
|
|
|
606
635
|
// src/commands/verify/init.ts
|
|
607
|
-
import
|
|
636
|
+
import chalk20 from "chalk";
|
|
608
637
|
|
|
609
638
|
// src/shared/promptMultiselect.ts
|
|
610
|
-
import
|
|
639
|
+
import chalk10 from "chalk";
|
|
611
640
|
import enquirer3 from "enquirer";
|
|
612
641
|
async function promptMultiselect(message, options) {
|
|
613
642
|
const { selected } = await enquirer3.prompt({
|
|
@@ -616,7 +645,7 @@ async function promptMultiselect(message, options) {
|
|
|
616
645
|
message,
|
|
617
646
|
choices: options.map((opt) => ({
|
|
618
647
|
name: opt.value,
|
|
619
|
-
message: `${opt.name} - ${
|
|
648
|
+
message: `${opt.name} - ${chalk10.dim(opt.description)}`
|
|
620
649
|
})),
|
|
621
650
|
// @ts-expect-error - enquirer types don't include symbols but it's supported
|
|
622
651
|
symbols: {
|
|
@@ -632,7 +661,7 @@ async function promptMultiselect(message, options) {
|
|
|
632
661
|
// src/shared/readPackageJson.ts
|
|
633
662
|
import * as fs2 from "fs";
|
|
634
663
|
import * as path2 from "path";
|
|
635
|
-
import
|
|
664
|
+
import chalk11 from "chalk";
|
|
636
665
|
function findPackageJson() {
|
|
637
666
|
const packageJsonPath = path2.join(process.cwd(), "package.json");
|
|
638
667
|
if (fs2.existsSync(packageJsonPath)) {
|
|
@@ -646,7 +675,7 @@ function readPackageJson(filePath) {
|
|
|
646
675
|
function requirePackageJson() {
|
|
647
676
|
const packageJsonPath = findPackageJson();
|
|
648
677
|
if (!packageJsonPath) {
|
|
649
|
-
console.error(
|
|
678
|
+
console.error(chalk11.red("No package.json found in current directory"));
|
|
650
679
|
process.exit(1);
|
|
651
680
|
}
|
|
652
681
|
const pkg = readPackageJson(packageJsonPath);
|
|
@@ -684,13 +713,13 @@ var EXPECTED_SCRIPTS = {
|
|
|
684
713
|
};
|
|
685
714
|
|
|
686
715
|
// src/commands/verify/setup/setupBuild.ts
|
|
687
|
-
import
|
|
716
|
+
import chalk13 from "chalk";
|
|
688
717
|
|
|
689
718
|
// src/commands/verify/installPackage.ts
|
|
690
719
|
import { execSync as execSync6 } from "child_process";
|
|
691
720
|
import * as fs3 from "fs";
|
|
692
721
|
import * as path3 from "path";
|
|
693
|
-
import
|
|
722
|
+
import chalk12 from "chalk";
|
|
694
723
|
function writePackageJson(filePath, pkg) {
|
|
695
724
|
fs3.writeFileSync(filePath, `${JSON.stringify(pkg, null, 2)}
|
|
696
725
|
`);
|
|
@@ -705,12 +734,12 @@ function addScript(pkg, name, command) {
|
|
|
705
734
|
};
|
|
706
735
|
}
|
|
707
736
|
function installPackage(name, cwd) {
|
|
708
|
-
console.log(
|
|
737
|
+
console.log(chalk12.dim(`Installing ${name}...`));
|
|
709
738
|
try {
|
|
710
739
|
execSync6(`npm install -D ${name}`, { stdio: "inherit", cwd });
|
|
711
740
|
return true;
|
|
712
741
|
} catch {
|
|
713
|
-
console.error(
|
|
742
|
+
console.error(chalk12.red(`Failed to install ${name}`));
|
|
714
743
|
return false;
|
|
715
744
|
}
|
|
716
745
|
}
|
|
@@ -731,10 +760,10 @@ function addToKnipIgnoreBinaries(cwd, binary) {
|
|
|
731
760
|
`${JSON.stringify(knipConfig, null, " ")}
|
|
732
761
|
`
|
|
733
762
|
);
|
|
734
|
-
console.log(
|
|
763
|
+
console.log(chalk12.dim(`Added '${binary}' to knip.json ignoreBinaries`));
|
|
735
764
|
}
|
|
736
765
|
} catch {
|
|
737
|
-
console.log(
|
|
766
|
+
console.log(chalk12.yellow("Warning: Could not update knip.json"));
|
|
738
767
|
}
|
|
739
768
|
}
|
|
740
769
|
function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
@@ -746,7 +775,7 @@ function setupVerifyScript(packageJsonPath, scriptName, command) {
|
|
|
746
775
|
|
|
747
776
|
// src/commands/verify/setup/setupBuild.ts
|
|
748
777
|
async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
|
|
749
|
-
console.log(
|
|
778
|
+
console.log(chalk13.blue("\nSetting up build verification..."));
|
|
750
779
|
let command;
|
|
751
780
|
if (hasVite && hasTypescript) {
|
|
752
781
|
command = "tsc -b && vite build --logLevel error";
|
|
@@ -755,16 +784,16 @@ async function setupBuild(packageJsonPath, hasVite, hasTypescript) {
|
|
|
755
784
|
} else {
|
|
756
785
|
command = "tsc --noEmit";
|
|
757
786
|
}
|
|
758
|
-
console.log(
|
|
787
|
+
console.log(chalk13.dim(`Using: ${command}`));
|
|
759
788
|
const pkg = readPackageJson(packageJsonPath);
|
|
760
789
|
writePackageJson(packageJsonPath, addScript(pkg, "verify:build", command));
|
|
761
790
|
}
|
|
762
791
|
|
|
763
792
|
// src/commands/verify/setup/setupDuplicateCode.ts
|
|
764
793
|
import * as path4 from "path";
|
|
765
|
-
import
|
|
794
|
+
import chalk14 from "chalk";
|
|
766
795
|
async function setupDuplicateCode(packageJsonPath) {
|
|
767
|
-
console.log(
|
|
796
|
+
console.log(chalk14.blue("\nSetting up jscpd..."));
|
|
768
797
|
const cwd = path4.dirname(packageJsonPath);
|
|
769
798
|
const pkg = readPackageJson(packageJsonPath);
|
|
770
799
|
const hasJscpd = !!pkg.dependencies?.jscpd || !!pkg.devDependencies?.jscpd;
|
|
@@ -780,9 +809,9 @@ async function setupDuplicateCode(packageJsonPath) {
|
|
|
780
809
|
|
|
781
810
|
// src/commands/verify/setup/setupHardcodedColors.ts
|
|
782
811
|
import * as path5 from "path";
|
|
783
|
-
import
|
|
812
|
+
import chalk15 from "chalk";
|
|
784
813
|
async function setupHardcodedColors(packageJsonPath, hasOpenColor) {
|
|
785
|
-
console.log(
|
|
814
|
+
console.log(chalk15.blue("\nSetting up hardcoded colors check..."));
|
|
786
815
|
const cwd = path5.dirname(packageJsonPath);
|
|
787
816
|
if (!hasOpenColor) {
|
|
788
817
|
installPackage("open-color", cwd);
|
|
@@ -797,9 +826,9 @@ async function setupHardcodedColors(packageJsonPath, hasOpenColor) {
|
|
|
797
826
|
|
|
798
827
|
// src/commands/verify/setup/setupKnip.ts
|
|
799
828
|
import * as path6 from "path";
|
|
800
|
-
import
|
|
829
|
+
import chalk16 from "chalk";
|
|
801
830
|
async function setupKnip(packageJsonPath) {
|
|
802
|
-
console.log(
|
|
831
|
+
console.log(chalk16.blue("\nSetting up knip..."));
|
|
803
832
|
const cwd = path6.dirname(packageJsonPath);
|
|
804
833
|
const pkg = readPackageJson(packageJsonPath);
|
|
805
834
|
if (!pkg.devDependencies?.knip && !installPackage("knip", cwd)) {
|
|
@@ -814,18 +843,18 @@ async function setupKnip(packageJsonPath) {
|
|
|
814
843
|
|
|
815
844
|
// src/commands/verify/setup/setupLint.ts
|
|
816
845
|
import * as path7 from "path";
|
|
817
|
-
import
|
|
846
|
+
import chalk18 from "chalk";
|
|
818
847
|
|
|
819
848
|
// src/commands/lint/init.ts
|
|
820
849
|
import { execSync as execSync8 } from "child_process";
|
|
821
|
-
import { existsSync as
|
|
850
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
|
|
822
851
|
import { dirname as dirname7, join as join8 } from "path";
|
|
823
852
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
824
|
-
import
|
|
853
|
+
import chalk17 from "chalk";
|
|
825
854
|
|
|
826
855
|
// src/shared/removeEslint.ts
|
|
827
856
|
import { execSync as execSync7 } from "child_process";
|
|
828
|
-
import { existsSync as
|
|
857
|
+
import { existsSync as existsSync7, readFileSync as readFileSync9, unlinkSync, writeFileSync as writeFileSync6 } from "fs";
|
|
829
858
|
function removeEslint(options = {}) {
|
|
830
859
|
const removedFromPackageJson = removeEslintFromPackageJson(options);
|
|
831
860
|
const removedConfigFiles = removeEslintConfigFiles();
|
|
@@ -838,10 +867,10 @@ function removeEslint(options = {}) {
|
|
|
838
867
|
}
|
|
839
868
|
function removeEslintFromPackageJson(options) {
|
|
840
869
|
const packageJsonPath = "package.json";
|
|
841
|
-
if (!
|
|
870
|
+
if (!existsSync7(packageJsonPath)) {
|
|
842
871
|
return false;
|
|
843
872
|
}
|
|
844
|
-
const packageJson = JSON.parse(
|
|
873
|
+
const packageJson = JSON.parse(readFileSync9(packageJsonPath, "utf-8"));
|
|
845
874
|
let modified = false;
|
|
846
875
|
if (packageJson.dependencies) {
|
|
847
876
|
for (const key of Object.keys(packageJson.dependencies)) {
|
|
@@ -869,7 +898,7 @@ function removeEslintFromPackageJson(options) {
|
|
|
869
898
|
}
|
|
870
899
|
}
|
|
871
900
|
if (modified) {
|
|
872
|
-
|
|
901
|
+
writeFileSync6(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
873
902
|
`);
|
|
874
903
|
console.log("Removed eslint references from package.json");
|
|
875
904
|
}
|
|
@@ -890,7 +919,7 @@ function removeEslintConfigFiles() {
|
|
|
890
919
|
];
|
|
891
920
|
let removed = false;
|
|
892
921
|
for (const configFile of eslintConfigFiles) {
|
|
893
|
-
if (
|
|
922
|
+
if (existsSync7(configFile)) {
|
|
894
923
|
unlinkSync(configFile);
|
|
895
924
|
console.log(`Removed ${configFile}`);
|
|
896
925
|
removed = true;
|
|
@@ -904,17 +933,17 @@ var __dirname4 = dirname7(fileURLToPath3(import.meta.url));
|
|
|
904
933
|
async function init2() {
|
|
905
934
|
removeEslint();
|
|
906
935
|
const biomeConfigPath = "biome.json";
|
|
907
|
-
if (!
|
|
936
|
+
if (!existsSync8(biomeConfigPath)) {
|
|
908
937
|
console.log("Initializing Biome...");
|
|
909
938
|
execSync8("npx @biomejs/biome init", { stdio: "inherit" });
|
|
910
939
|
}
|
|
911
|
-
if (!
|
|
940
|
+
if (!existsSync8(biomeConfigPath)) {
|
|
912
941
|
console.log("No biome.json found, skipping linter config");
|
|
913
942
|
return;
|
|
914
943
|
}
|
|
915
944
|
const linterConfigPath = join8(__dirname4, "commands/lint/biome.linter.json");
|
|
916
|
-
const linterConfig = JSON.parse(
|
|
917
|
-
const biomeConfig = JSON.parse(
|
|
945
|
+
const linterConfig = JSON.parse(readFileSync10(linterConfigPath, "utf-8"));
|
|
946
|
+
const biomeConfig = JSON.parse(readFileSync10(biomeConfigPath, "utf-8"));
|
|
918
947
|
const oldContent = `${JSON.stringify(biomeConfig, null, 2)}
|
|
919
948
|
`;
|
|
920
949
|
biomeConfig.linter = linterConfig.linter;
|
|
@@ -927,21 +956,21 @@ async function init2() {
|
|
|
927
956
|
console.log("biome.json already has the correct linter config");
|
|
928
957
|
return;
|
|
929
958
|
}
|
|
930
|
-
console.log(
|
|
959
|
+
console.log(chalk17.yellow("\n\u26A0\uFE0F biome.json will be updated:"));
|
|
931
960
|
console.log();
|
|
932
961
|
printDiff(oldContent, newContent);
|
|
933
|
-
const confirm = await promptConfirm(
|
|
962
|
+
const confirm = await promptConfirm(chalk17.red("Update biome.json?"));
|
|
934
963
|
if (!confirm) {
|
|
935
964
|
console.log("Skipped biome.json update");
|
|
936
965
|
return;
|
|
937
966
|
}
|
|
938
|
-
|
|
967
|
+
writeFileSync7(biomeConfigPath, newContent);
|
|
939
968
|
console.log("Updated biome.json with linter config");
|
|
940
969
|
}
|
|
941
970
|
|
|
942
971
|
// src/commands/verify/setup/setupLint.ts
|
|
943
972
|
async function setupLint(packageJsonPath) {
|
|
944
|
-
console.log(
|
|
973
|
+
console.log(chalk18.blue("\nSetting up biome..."));
|
|
945
974
|
const cwd = path7.dirname(packageJsonPath);
|
|
946
975
|
const pkg = readPackageJson(packageJsonPath);
|
|
947
976
|
if (!pkg.devDependencies?.["@biomejs/biome"]) {
|
|
@@ -959,9 +988,9 @@ async function setupLint(packageJsonPath) {
|
|
|
959
988
|
|
|
960
989
|
// src/commands/verify/setup/setupTest.ts
|
|
961
990
|
import * as path8 from "path";
|
|
962
|
-
import
|
|
991
|
+
import chalk19 from "chalk";
|
|
963
992
|
async function setupTest(packageJsonPath) {
|
|
964
|
-
console.log(
|
|
993
|
+
console.log(chalk19.blue("\nSetting up vitest..."));
|
|
965
994
|
const cwd = path8.dirname(packageJsonPath);
|
|
966
995
|
const pkg = readPackageJson(packageJsonPath);
|
|
967
996
|
if (!pkg.devDependencies?.vitest && !installPackage("vitest", cwd)) {
|
|
@@ -1104,16 +1133,16 @@ async function init3() {
|
|
|
1104
1133
|
const setup = detectExistingSetup(pkg);
|
|
1105
1134
|
const availableOptions = getAvailableOptions(setup);
|
|
1106
1135
|
if (availableOptions.length === 0) {
|
|
1107
|
-
console.log(
|
|
1136
|
+
console.log(chalk20.green("All verify scripts are already configured!"));
|
|
1108
1137
|
return;
|
|
1109
1138
|
}
|
|
1110
|
-
console.log(
|
|
1139
|
+
console.log(chalk20.bold("Available verify scripts to add:\n"));
|
|
1111
1140
|
const selected = await promptMultiselect(
|
|
1112
1141
|
"Select verify scripts to add:",
|
|
1113
1142
|
availableOptions
|
|
1114
1143
|
);
|
|
1115
1144
|
if (selected.length === 0) {
|
|
1116
|
-
console.log(
|
|
1145
|
+
console.log(chalk20.yellow("No scripts selected"));
|
|
1117
1146
|
return;
|
|
1118
1147
|
}
|
|
1119
1148
|
for (const choice of selected) {
|
|
@@ -1138,28 +1167,28 @@ async function init3() {
|
|
|
1138
1167
|
break;
|
|
1139
1168
|
}
|
|
1140
1169
|
}
|
|
1141
|
-
console.log(
|
|
1170
|
+
console.log(chalk20.green(`
|
|
1142
1171
|
Added ${selected.length} verify script(s):`));
|
|
1143
1172
|
for (const choice of selected) {
|
|
1144
|
-
console.log(
|
|
1173
|
+
console.log(chalk20.green(` - verify:${choice}`));
|
|
1145
1174
|
}
|
|
1146
|
-
console.log(
|
|
1175
|
+
console.log(chalk20.dim("\nRun 'assist verify' to run all verify scripts"));
|
|
1147
1176
|
}
|
|
1148
1177
|
|
|
1149
1178
|
// src/commands/vscode/init.ts
|
|
1150
1179
|
import * as fs5 from "fs";
|
|
1151
1180
|
import * as path10 from "path";
|
|
1152
|
-
import
|
|
1181
|
+
import chalk22 from "chalk";
|
|
1153
1182
|
|
|
1154
1183
|
// src/commands/vscode/createLaunchJson.ts
|
|
1155
1184
|
import * as fs4 from "fs";
|
|
1156
1185
|
import * as path9 from "path";
|
|
1157
|
-
import
|
|
1186
|
+
import chalk21 from "chalk";
|
|
1158
1187
|
function ensureVscodeFolder() {
|
|
1159
1188
|
const vscodeDir = path9.join(process.cwd(), ".vscode");
|
|
1160
1189
|
if (!fs4.existsSync(vscodeDir)) {
|
|
1161
1190
|
fs4.mkdirSync(vscodeDir);
|
|
1162
|
-
console.log(
|
|
1191
|
+
console.log(chalk21.dim("Created .vscode folder"));
|
|
1163
1192
|
}
|
|
1164
1193
|
}
|
|
1165
1194
|
function removeVscodeFromGitignore() {
|
|
@@ -1174,7 +1203,7 @@ function removeVscodeFromGitignore() {
|
|
|
1174
1203
|
);
|
|
1175
1204
|
if (filteredLines.length !== lines.length) {
|
|
1176
1205
|
fs4.writeFileSync(gitignorePath, filteredLines.join("\n"));
|
|
1177
|
-
console.log(
|
|
1206
|
+
console.log(chalk21.dim("Removed .vscode references from .gitignore"));
|
|
1178
1207
|
}
|
|
1179
1208
|
}
|
|
1180
1209
|
function createLaunchJson() {
|
|
@@ -1192,7 +1221,7 @@ function createLaunchJson() {
|
|
|
1192
1221
|
const launchPath = path9.join(process.cwd(), ".vscode", "launch.json");
|
|
1193
1222
|
fs4.writeFileSync(launchPath, `${JSON.stringify(launchConfig, null, " ")}
|
|
1194
1223
|
`);
|
|
1195
|
-
console.log(
|
|
1224
|
+
console.log(chalk21.green("Created .vscode/launch.json"));
|
|
1196
1225
|
}
|
|
1197
1226
|
function createSettingsJson() {
|
|
1198
1227
|
const settings = {
|
|
@@ -1211,7 +1240,7 @@ function createSettingsJson() {
|
|
|
1211
1240
|
const settingsPath = path9.join(process.cwd(), ".vscode", "settings.json");
|
|
1212
1241
|
fs4.writeFileSync(settingsPath, `${JSON.stringify(settings, null, " ")}
|
|
1213
1242
|
`);
|
|
1214
|
-
console.log(
|
|
1243
|
+
console.log(chalk21.green("Created .vscode/settings.json"));
|
|
1215
1244
|
}
|
|
1216
1245
|
function createExtensionsJson() {
|
|
1217
1246
|
const extensions = {
|
|
@@ -1223,7 +1252,7 @@ function createExtensionsJson() {
|
|
|
1223
1252
|
`${JSON.stringify(extensions, null, " ")}
|
|
1224
1253
|
`
|
|
1225
1254
|
);
|
|
1226
|
-
console.log(
|
|
1255
|
+
console.log(chalk21.green("Created .vscode/extensions.json"));
|
|
1227
1256
|
}
|
|
1228
1257
|
|
|
1229
1258
|
// src/commands/vscode/init.ts
|
|
@@ -1255,16 +1284,16 @@ async function init4() {
|
|
|
1255
1284
|
});
|
|
1256
1285
|
}
|
|
1257
1286
|
if (availableOptions.length === 0) {
|
|
1258
|
-
console.log(
|
|
1287
|
+
console.log(chalk22.green("VS Code configuration already exists!"));
|
|
1259
1288
|
return;
|
|
1260
1289
|
}
|
|
1261
|
-
console.log(
|
|
1290
|
+
console.log(chalk22.bold("Available VS Code configurations to add:\n"));
|
|
1262
1291
|
const selected = await promptMultiselect(
|
|
1263
1292
|
"Select configurations to add:",
|
|
1264
1293
|
availableOptions
|
|
1265
1294
|
);
|
|
1266
1295
|
if (selected.length === 0) {
|
|
1267
|
-
console.log(
|
|
1296
|
+
console.log(chalk22.yellow("No configurations selected"));
|
|
1268
1297
|
return;
|
|
1269
1298
|
}
|
|
1270
1299
|
removeVscodeFromGitignore();
|
|
@@ -1281,7 +1310,7 @@ async function init4() {
|
|
|
1281
1310
|
}
|
|
1282
1311
|
}
|
|
1283
1312
|
console.log(
|
|
1284
|
-
|
|
1313
|
+
chalk22.green(`
|
|
1285
1314
|
Added ${selected.length} VS Code configuration(s)`)
|
|
1286
1315
|
);
|
|
1287
1316
|
}
|
|
@@ -1295,7 +1324,7 @@ async function init5() {
|
|
|
1295
1324
|
// src/commands/lint/runFileNameCheck.ts
|
|
1296
1325
|
import fs7 from "fs";
|
|
1297
1326
|
import path12 from "path";
|
|
1298
|
-
import
|
|
1327
|
+
import chalk23 from "chalk";
|
|
1299
1328
|
|
|
1300
1329
|
// src/shared/findSourceFiles.ts
|
|
1301
1330
|
import fs6 from "fs";
|
|
@@ -1347,16 +1376,16 @@ function checkFileNames() {
|
|
|
1347
1376
|
function runFileNameCheck() {
|
|
1348
1377
|
const violations = checkFileNames();
|
|
1349
1378
|
if (violations.length > 0) {
|
|
1350
|
-
console.error(
|
|
1379
|
+
console.error(chalk23.red("\nFile name check failed:\n"));
|
|
1351
1380
|
console.error(
|
|
1352
|
-
|
|
1381
|
+
chalk23.red(
|
|
1353
1382
|
" Files without classes or React components should not start with a capital letter.\n"
|
|
1354
1383
|
)
|
|
1355
1384
|
);
|
|
1356
1385
|
for (const violation of violations) {
|
|
1357
|
-
console.error(
|
|
1386
|
+
console.error(chalk23.red(` ${violation.filePath}`));
|
|
1358
1387
|
console.error(
|
|
1359
|
-
|
|
1388
|
+
chalk23.gray(
|
|
1360
1389
|
` Rename to: ${violation.fileName.charAt(0).toLowerCase()}${violation.fileName.slice(1)}
|
|
1361
1390
|
`
|
|
1362
1391
|
)
|
|
@@ -1374,7 +1403,7 @@ function runFileNameCheck() {
|
|
|
1374
1403
|
|
|
1375
1404
|
// src/commands/lint/runStaticImportCheck.ts
|
|
1376
1405
|
import fs8 from "fs";
|
|
1377
|
-
import
|
|
1406
|
+
import chalk24 from "chalk";
|
|
1378
1407
|
function checkForDynamicImports(filePath) {
|
|
1379
1408
|
const content = fs8.readFileSync(filePath, "utf-8");
|
|
1380
1409
|
const lines = content.split("\n");
|
|
@@ -1404,15 +1433,15 @@ function checkStaticImports() {
|
|
|
1404
1433
|
function runStaticImportCheck() {
|
|
1405
1434
|
const violations = checkStaticImports();
|
|
1406
1435
|
if (violations.length > 0) {
|
|
1407
|
-
console.error(
|
|
1436
|
+
console.error(chalk24.red("\nStatic import check failed:\n"));
|
|
1408
1437
|
console.error(
|
|
1409
|
-
|
|
1438
|
+
chalk24.red(
|
|
1410
1439
|
" Dynamic imports (require() and import()) are not allowed. Use static imports instead.\n"
|
|
1411
1440
|
)
|
|
1412
1441
|
);
|
|
1413
1442
|
for (const violation of violations) {
|
|
1414
|
-
console.error(
|
|
1415
|
-
console.error(
|
|
1443
|
+
console.error(chalk24.red(` ${violation.filePath}:${violation.line}`));
|
|
1444
|
+
console.error(chalk24.gray(` ${violation.content}
|
|
1416
1445
|
`));
|
|
1417
1446
|
}
|
|
1418
1447
|
return false;
|
|
@@ -1434,7 +1463,7 @@ function lint() {
|
|
|
1434
1463
|
|
|
1435
1464
|
// src/commands/new/newProject.ts
|
|
1436
1465
|
import { execSync as execSync9 } from "child_process";
|
|
1437
|
-
import { existsSync as
|
|
1466
|
+
import { existsSync as existsSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "fs";
|
|
1438
1467
|
async function newProject() {
|
|
1439
1468
|
console.log("Initializing Vite with react-ts template...");
|
|
1440
1469
|
execSync9("npm create vite@latest . -- --template react-ts", {
|
|
@@ -1447,11 +1476,11 @@ async function newProject() {
|
|
|
1447
1476
|
}
|
|
1448
1477
|
function addViteBaseConfig() {
|
|
1449
1478
|
const viteConfigPath = "vite.config.ts";
|
|
1450
|
-
if (!
|
|
1479
|
+
if (!existsSync11(viteConfigPath)) {
|
|
1451
1480
|
console.log("No vite.config.ts found, skipping base config");
|
|
1452
1481
|
return;
|
|
1453
1482
|
}
|
|
1454
|
-
const content =
|
|
1483
|
+
const content = readFileSync12(viteConfigPath, "utf-8");
|
|
1455
1484
|
if (content.includes("base:")) {
|
|
1456
1485
|
console.log("vite.config.ts already has base config");
|
|
1457
1486
|
return;
|
|
@@ -1461,14 +1490,14 @@ function addViteBaseConfig() {
|
|
|
1461
1490
|
'defineConfig({\n base: "./",'
|
|
1462
1491
|
);
|
|
1463
1492
|
if (updated !== content) {
|
|
1464
|
-
|
|
1493
|
+
writeFileSync9(viteConfigPath, updated);
|
|
1465
1494
|
console.log('Added base: "./" to vite.config.ts');
|
|
1466
1495
|
}
|
|
1467
1496
|
}
|
|
1468
1497
|
|
|
1469
1498
|
// src/commands/prs.ts
|
|
1470
1499
|
import { execSync as execSync10 } from "child_process";
|
|
1471
|
-
import
|
|
1500
|
+
import chalk25 from "chalk";
|
|
1472
1501
|
import enquirer4 from "enquirer";
|
|
1473
1502
|
var PAGE_SIZE = 10;
|
|
1474
1503
|
async function prs(options) {
|
|
@@ -1503,12 +1532,12 @@ async function displayPaginated(pullRequests) {
|
|
|
1503
1532
|
let currentPage = 0;
|
|
1504
1533
|
const getStatus = (pr) => {
|
|
1505
1534
|
if (pr.state === "MERGED" && pr.mergedAt) {
|
|
1506
|
-
return { label:
|
|
1535
|
+
return { label: chalk25.magenta("merged"), date: pr.mergedAt };
|
|
1507
1536
|
}
|
|
1508
1537
|
if (pr.state === "CLOSED" && pr.closedAt) {
|
|
1509
|
-
return { label:
|
|
1538
|
+
return { label: chalk25.red("closed"), date: pr.closedAt };
|
|
1510
1539
|
}
|
|
1511
|
-
return { label:
|
|
1540
|
+
return { label: chalk25.green("opened"), date: pr.createdAt };
|
|
1512
1541
|
};
|
|
1513
1542
|
const displayPage = (page) => {
|
|
1514
1543
|
const start = page * PAGE_SIZE;
|
|
@@ -1524,9 +1553,9 @@ Page ${page + 1} of ${totalPages} (${pullRequests.length} total)
|
|
|
1524
1553
|
const formattedDate = new Date(status.date).toISOString().split("T")[0];
|
|
1525
1554
|
const fileCount = pr.changedFiles.toLocaleString();
|
|
1526
1555
|
console.log(
|
|
1527
|
-
`${
|
|
1556
|
+
`${chalk25.cyan(`#${pr.number}`)} ${pr.title} ${chalk25.dim(`(${pr.author.login},`)} ${status.label} ${chalk25.dim(`${formattedDate})`)}`
|
|
1528
1557
|
);
|
|
1529
|
-
console.log(
|
|
1558
|
+
console.log(chalk25.dim(` ${fileCount} files | ${pr.url}`));
|
|
1530
1559
|
console.log();
|
|
1531
1560
|
}
|
|
1532
1561
|
};
|
|
@@ -1604,7 +1633,7 @@ function getIgnoredFiles() {
|
|
|
1604
1633
|
}
|
|
1605
1634
|
|
|
1606
1635
|
// src/commands/refactor/logViolations.ts
|
|
1607
|
-
import
|
|
1636
|
+
import chalk26 from "chalk";
|
|
1608
1637
|
var DEFAULT_MAX_LINES = 100;
|
|
1609
1638
|
function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
1610
1639
|
if (violations.length === 0) {
|
|
@@ -1613,43 +1642,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
|
|
|
1613
1642
|
}
|
|
1614
1643
|
return;
|
|
1615
1644
|
}
|
|
1616
|
-
console.error(
|
|
1645
|
+
console.error(chalk26.red(`
|
|
1617
1646
|
Refactor check failed:
|
|
1618
1647
|
`));
|
|
1619
|
-
console.error(
|
|
1648
|
+
console.error(chalk26.red(` The following files exceed ${maxLines} lines:
|
|
1620
1649
|
`));
|
|
1621
1650
|
for (const violation of violations) {
|
|
1622
|
-
console.error(
|
|
1651
|
+
console.error(chalk26.red(` ${violation.file} (${violation.lines} lines)`));
|
|
1623
1652
|
}
|
|
1624
1653
|
console.error(
|
|
1625
|
-
|
|
1654
|
+
chalk26.yellow(
|
|
1626
1655
|
`
|
|
1627
1656
|
Each file needs to be sensibly refactored, or if there is no sensible
|
|
1628
1657
|
way to refactor it, ignore it with:
|
|
1629
1658
|
`
|
|
1630
1659
|
)
|
|
1631
1660
|
);
|
|
1632
|
-
console.error(
|
|
1661
|
+
console.error(chalk26.gray(` assist refactor ignore <file>
|
|
1633
1662
|
`));
|
|
1634
1663
|
if (process.env.CLAUDECODE) {
|
|
1635
|
-
console.error(
|
|
1664
|
+
console.error(chalk26.cyan(`
|
|
1636
1665
|
## Extracting Code to New Files
|
|
1637
1666
|
`));
|
|
1638
1667
|
console.error(
|
|
1639
|
-
|
|
1668
|
+
chalk26.cyan(
|
|
1640
1669
|
` When extracting logic from one file to another, consider where the extracted code belongs:
|
|
1641
1670
|
`
|
|
1642
1671
|
)
|
|
1643
1672
|
);
|
|
1644
1673
|
console.error(
|
|
1645
|
-
|
|
1674
|
+
chalk26.cyan(
|
|
1646
1675
|
` 1. Keep related logic together: If the extracted code is tightly coupled to the
|
|
1647
1676
|
original file's domain, create a new folder containing both the original and extracted files.
|
|
1648
1677
|
`
|
|
1649
1678
|
)
|
|
1650
1679
|
);
|
|
1651
1680
|
console.error(
|
|
1652
|
-
|
|
1681
|
+
chalk26.cyan(
|
|
1653
1682
|
` 2. Share common utilities: If the extracted code can be reused across multiple
|
|
1654
1683
|
domains, move it to a common/shared folder.
|
|
1655
1684
|
`
|
|
@@ -1766,11 +1795,11 @@ async function check(pattern2, options) {
|
|
|
1766
1795
|
|
|
1767
1796
|
// src/commands/refactor/ignore.ts
|
|
1768
1797
|
import fs11 from "fs";
|
|
1769
|
-
import
|
|
1798
|
+
import chalk27 from "chalk";
|
|
1770
1799
|
var REFACTOR_YML_PATH2 = "refactor.yml";
|
|
1771
1800
|
function ignore(file) {
|
|
1772
1801
|
if (!fs11.existsSync(file)) {
|
|
1773
|
-
console.error(
|
|
1802
|
+
console.error(chalk27.red(`Error: File does not exist: ${file}`));
|
|
1774
1803
|
process.exit(1);
|
|
1775
1804
|
}
|
|
1776
1805
|
const content = fs11.readFileSync(file, "utf-8");
|
|
@@ -1786,7 +1815,7 @@ function ignore(file) {
|
|
|
1786
1815
|
fs11.writeFileSync(REFACTOR_YML_PATH2, entry);
|
|
1787
1816
|
}
|
|
1788
1817
|
console.log(
|
|
1789
|
-
|
|
1818
|
+
chalk27.green(
|
|
1790
1819
|
`Added ${file} to refactor ignore list (max ${maxLines} lines)`
|
|
1791
1820
|
)
|
|
1792
1821
|
);
|
|
@@ -1894,7 +1923,7 @@ import { fileURLToPath as fileURLToPath4 } from "url";
|
|
|
1894
1923
|
// src/commands/sync/syncSettings.ts
|
|
1895
1924
|
import * as fs12 from "fs";
|
|
1896
1925
|
import * as path14 from "path";
|
|
1897
|
-
import
|
|
1926
|
+
import chalk28 from "chalk";
|
|
1898
1927
|
async function syncSettings(claudeDir, targetBase) {
|
|
1899
1928
|
const source = path14.join(claudeDir, "settings.json");
|
|
1900
1929
|
const target = path14.join(targetBase, "settings.json");
|
|
@@ -1905,12 +1934,12 @@ async function syncSettings(claudeDir, targetBase) {
|
|
|
1905
1934
|
const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
|
|
1906
1935
|
if (normalizedSource !== normalizedTarget) {
|
|
1907
1936
|
console.log(
|
|
1908
|
-
|
|
1937
|
+
chalk28.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
|
|
1909
1938
|
);
|
|
1910
1939
|
console.log();
|
|
1911
1940
|
printDiff(targetContent, sourceContent);
|
|
1912
1941
|
const confirm = await promptConfirm(
|
|
1913
|
-
|
|
1942
|
+
chalk28.red("Overwrite existing settings.json?"),
|
|
1914
1943
|
false
|
|
1915
1944
|
);
|
|
1916
1945
|
if (!confirm) {
|
|
@@ -2092,6 +2121,7 @@ var vscodeCommand = program.command("vscode").description("VS Code configuration
|
|
|
2092
2121
|
vscodeCommand.command("init").description("Add VS Code configuration files").action(init4);
|
|
2093
2122
|
var deployCommand = program.command("deploy").description("Netlify deployment utilities");
|
|
2094
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);
|
|
2095
2125
|
program.command("enable-ralph").description("Enable ralph-wiggum plugin for spacetraders").action(enableRalph);
|
|
2096
2126
|
program.command("status-line").description("Format Claude Code status line from JSON stdin").action(statusLine);
|
|
2097
2127
|
program.parse();
|