maxsimcli 1.0.6 → 1.0.8
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/.tsbuildinfo +1 -1
- package/dist/assets/templates/workflows/help.md +0 -8
- package/dist/install.cjs +5566 -198
- package/dist/install.cjs.map +1 -1
- package/dist/install.js +185 -231
- package/dist/install.js.map +1 -1
- package/package.json +6 -4
- package/dist/assets/templates/commands/maxsim/join-discord.md +0 -18
package/dist/install.js
CHANGED
|
@@ -32,19 +32,18 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
const fs = __importStar(require("node:fs"));
|
|
37
40
|
const path = __importStar(require("node:path"));
|
|
38
41
|
const os = __importStar(require("node:os"));
|
|
39
|
-
const readline = __importStar(require("node:readline"));
|
|
40
42
|
const crypto = __importStar(require("node:crypto"));
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
44
|
+
const ora_1 = __importDefault(require("ora"));
|
|
45
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
41
46
|
const adapters_1 = require("@maxsim/adapters");
|
|
42
|
-
// Colors
|
|
43
|
-
const cyan = '\x1b[36m';
|
|
44
|
-
const green = '\x1b[32m';
|
|
45
|
-
const yellow = '\x1b[33m';
|
|
46
|
-
const dim = '\x1b[2m';
|
|
47
|
-
const reset = '\x1b[0m';
|
|
48
47
|
// Get version from package.json
|
|
49
48
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
50
49
|
const pkg = require('../package.json');
|
|
@@ -120,21 +119,16 @@ function getOpencodeGlobalDir() {
|
|
|
120
119
|
return adapters_1.opencodeAdapter.getGlobalDir();
|
|
121
120
|
}
|
|
122
121
|
const banner = '\n' +
|
|
123
|
-
cyan +
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
' \u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d' +
|
|
130
|
-
reset +
|
|
122
|
+
chalk_1.default.cyan(' \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\n' +
|
|
123
|
+
' \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u255a\u2588\u2588\u2557\u2588\u2588\u2554\u255d\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255d\u2588\u2588\u2551\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2551\n' +
|
|
124
|
+
' \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u255a\u2588\u2588\u2588\u2554\u255d \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\n' +
|
|
125
|
+
' \u2588\u2588\u2551\u255a\u2588\u2588\u2554\u255d\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2554\u2588\u2588\u2557 \u255a\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551\u255a\u2588\u2588\u2554\u255d\u2588\u2588\u2551\n' +
|
|
126
|
+
' \u2588\u2588\u2551 \u255a\u2550\u255d \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u255d \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551 \u255a\u2550\u255d \u2588\u2588\u2551\n' +
|
|
127
|
+
' \u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d') +
|
|
131
128
|
'\n' +
|
|
132
129
|
'\n' +
|
|
133
130
|
' MAXSIM ' +
|
|
134
|
-
dim +
|
|
135
|
-
'v' +
|
|
136
|
-
pkg.version +
|
|
137
|
-
reset +
|
|
131
|
+
chalk_1.default.dim('v' + pkg.version) +
|
|
138
132
|
'\n' +
|
|
139
133
|
' A meta-prompting, context engineering and spec-driven\n' +
|
|
140
134
|
' development system for Claude Code, OpenCode, Gemini, and Codex.\n';
|
|
@@ -144,7 +138,7 @@ function parseConfigDirArg() {
|
|
|
144
138
|
if (configDirIndex !== -1) {
|
|
145
139
|
const nextArg = args[configDirIndex + 1];
|
|
146
140
|
if (!nextArg || nextArg.startsWith('-')) {
|
|
147
|
-
console.error(` ${yellow
|
|
141
|
+
console.error(` ${chalk_1.default.yellow('--config-dir requires a path argument')}`);
|
|
148
142
|
process.exit(1);
|
|
149
143
|
}
|
|
150
144
|
return nextArg;
|
|
@@ -153,7 +147,7 @@ function parseConfigDirArg() {
|
|
|
153
147
|
if (configDirArg) {
|
|
154
148
|
const value = configDirArg.split('=')[1];
|
|
155
149
|
if (!value) {
|
|
156
|
-
console.error(` ${yellow
|
|
150
|
+
console.error(` ${chalk_1.default.yellow('--config-dir requires a non-empty path')}`);
|
|
157
151
|
process.exit(1);
|
|
158
152
|
}
|
|
159
153
|
return value;
|
|
@@ -166,7 +160,7 @@ const forceStatusline = args.includes('--force-statusline');
|
|
|
166
160
|
console.log(banner);
|
|
167
161
|
// Show help if requested
|
|
168
162
|
if (hasHelp) {
|
|
169
|
-
console.log(` ${yellow
|
|
163
|
+
console.log(` ${chalk_1.default.yellow('Usage:')} npx maxsimcli [options]\n\n ${chalk_1.default.yellow('Options:')}\n ${chalk_1.default.cyan('-g, --global')} Install globally (to config directory)\n ${chalk_1.default.cyan('-l, --local')} Install locally (to current directory)\n ${chalk_1.default.cyan('--claude')} Install for Claude Code only\n ${chalk_1.default.cyan('--opencode')} Install for OpenCode only\n ${chalk_1.default.cyan('--gemini')} Install for Gemini only\n ${chalk_1.default.cyan('--codex')} Install for Codex only\n ${chalk_1.default.cyan('--all')} Install for all runtimes\n ${chalk_1.default.cyan('-u, --uninstall')} Uninstall MAXSIM (remove all MAXSIM files)\n ${chalk_1.default.cyan('-c, --config-dir <path>')} Specify custom config directory\n ${chalk_1.default.cyan('-h, --help')} Show this help message\n ${chalk_1.default.cyan('--force-statusline')} Replace existing statusline config\n\n ${chalk_1.default.yellow('Examples:')}\n ${chalk_1.default.dim('# Interactive install (prompts for runtime and location)')}\n npx maxsimcli\n\n ${chalk_1.default.dim('# Install for Claude Code globally')}\n npx maxsimcli --claude --global\n\n ${chalk_1.default.dim('# Install for Gemini globally')}\n npx maxsimcli --gemini --global\n\n ${chalk_1.default.dim('# Install for Codex globally')}\n npx maxsimcli --codex --global\n\n ${chalk_1.default.dim('# Install for all runtimes globally')}\n npx maxsimcli --all --global\n\n ${chalk_1.default.dim('# Install to custom config directory')}\n npx maxsimcli --codex --global --config-dir ~/.codex-work\n\n ${chalk_1.default.dim('# Install to current project only')}\n npx maxsimcli --claude --local\n\n ${chalk_1.default.dim('# Uninstall MAXSIM from Codex globally')}\n npx maxsimcli --codex --global --uninstall\n\n ${chalk_1.default.yellow('Notes:')}\n The --config-dir option is useful when you have multiple configurations.\n It takes priority over CLAUDE_CONFIG_DIR / GEMINI_CONFIG_DIR / CODEX_HOME environment variables.\n`);
|
|
170
164
|
process.exit(0);
|
|
171
165
|
}
|
|
172
166
|
// Cache for attribution settings (populated once per runtime during install)
|
|
@@ -377,7 +371,7 @@ function cleanupOrphanedFiles(configDir) {
|
|
|
377
371
|
const fullPath = path.join(configDir, relPath);
|
|
378
372
|
if (fs.existsSync(fullPath)) {
|
|
379
373
|
fs.unlinkSync(fullPath);
|
|
380
|
-
console.log(` ${green
|
|
374
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed orphaned ${relPath}`);
|
|
381
375
|
}
|
|
382
376
|
}
|
|
383
377
|
}
|
|
@@ -414,7 +408,7 @@ function cleanupOrphanedHooks(settings) {
|
|
|
414
408
|
}
|
|
415
409
|
}
|
|
416
410
|
if (cleanedHooks) {
|
|
417
|
-
console.log(` ${green
|
|
411
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed orphaned hook registrations`);
|
|
418
412
|
}
|
|
419
413
|
const statusLine = settings.statusLine;
|
|
420
414
|
if (statusLine &&
|
|
@@ -422,7 +416,7 @@ function cleanupOrphanedHooks(settings) {
|
|
|
422
416
|
statusLine.command.includes('statusline.js') &&
|
|
423
417
|
!statusLine.command.includes('maxsim-statusline.js')) {
|
|
424
418
|
statusLine.command = statusLine.command.replace(/statusline\.js/, 'maxsim-statusline.js');
|
|
425
|
-
console.log(` ${green
|
|
419
|
+
console.log(` ${chalk_1.default.green('\u2713')} Updated statusline path (statusline.js \u2192 maxsim-statusline.js)`);
|
|
426
420
|
}
|
|
427
421
|
return settings;
|
|
428
422
|
}
|
|
@@ -446,9 +440,9 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
446
440
|
runtimeLabel = 'Gemini';
|
|
447
441
|
if (runtime === 'codex')
|
|
448
442
|
runtimeLabel = 'Codex';
|
|
449
|
-
console.log(` Uninstalling MAXSIM from ${cyan
|
|
443
|
+
console.log(` Uninstalling MAXSIM from ${chalk_1.default.cyan(runtimeLabel)} at ${chalk_1.default.cyan(locationLabel)}\n`);
|
|
450
444
|
if (!fs.existsSync(targetDir)) {
|
|
451
|
-
console.log(` ${yellow
|
|
445
|
+
console.log(` ${chalk_1.default.yellow('\u26a0')} Directory does not exist: ${locationLabel}`);
|
|
452
446
|
console.log(` Nothing to uninstall.\n`);
|
|
453
447
|
return;
|
|
454
448
|
}
|
|
@@ -464,7 +458,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
464
458
|
removedCount++;
|
|
465
459
|
}
|
|
466
460
|
}
|
|
467
|
-
console.log(` ${green
|
|
461
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed MAXSIM commands from command/`);
|
|
468
462
|
}
|
|
469
463
|
}
|
|
470
464
|
else if (isCodex) {
|
|
@@ -480,7 +474,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
480
474
|
}
|
|
481
475
|
if (skillCount > 0) {
|
|
482
476
|
removedCount++;
|
|
483
|
-
console.log(` ${green
|
|
477
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed ${skillCount} Codex skills`);
|
|
484
478
|
}
|
|
485
479
|
}
|
|
486
480
|
}
|
|
@@ -489,7 +483,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
489
483
|
if (fs.existsSync(maxsimCommandsDir)) {
|
|
490
484
|
fs.rmSync(maxsimCommandsDir, { recursive: true });
|
|
491
485
|
removedCount++;
|
|
492
|
-
console.log(` ${green
|
|
486
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed commands/maxsim/`);
|
|
493
487
|
}
|
|
494
488
|
}
|
|
495
489
|
// 2. Remove maxsim directory
|
|
@@ -497,7 +491,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
497
491
|
if (fs.existsSync(maxsimDir)) {
|
|
498
492
|
fs.rmSync(maxsimDir, { recursive: true });
|
|
499
493
|
removedCount++;
|
|
500
|
-
console.log(` ${green
|
|
494
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed maxsim/`);
|
|
501
495
|
}
|
|
502
496
|
// 3. Remove MAXSIM agents
|
|
503
497
|
const agentsDir = path.join(targetDir, 'agents');
|
|
@@ -512,7 +506,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
512
506
|
}
|
|
513
507
|
if (agentCount > 0) {
|
|
514
508
|
removedCount++;
|
|
515
|
-
console.log(` ${green
|
|
509
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed ${agentCount} MAXSIM agents`);
|
|
516
510
|
}
|
|
517
511
|
}
|
|
518
512
|
// 4. Remove MAXSIM hooks
|
|
@@ -534,7 +528,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
534
528
|
}
|
|
535
529
|
if (hookCount > 0) {
|
|
536
530
|
removedCount++;
|
|
537
|
-
console.log(` ${green
|
|
531
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed ${hookCount} MAXSIM hooks`);
|
|
538
532
|
}
|
|
539
533
|
}
|
|
540
534
|
// 5. Remove MAXSIM package.json (CommonJS mode marker)
|
|
@@ -545,7 +539,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
545
539
|
if (content === '{"type":"commonjs"}') {
|
|
546
540
|
fs.unlinkSync(pkgJsonPath);
|
|
547
541
|
removedCount++;
|
|
548
|
-
console.log(` ${green
|
|
542
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed MAXSIM package.json`);
|
|
549
543
|
}
|
|
550
544
|
}
|
|
551
545
|
catch {
|
|
@@ -563,7 +557,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
563
557
|
statusLine.command.includes('maxsim-statusline')) {
|
|
564
558
|
delete settings.statusLine;
|
|
565
559
|
settingsModified = true;
|
|
566
|
-
console.log(` ${green
|
|
560
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed MAXSIM statusline from settings`);
|
|
567
561
|
}
|
|
568
562
|
const settingsHooks = settings.hooks;
|
|
569
563
|
if (settingsHooks && settingsHooks.SessionStart) {
|
|
@@ -579,7 +573,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
579
573
|
});
|
|
580
574
|
if (settingsHooks.SessionStart.length < before) {
|
|
581
575
|
settingsModified = true;
|
|
582
|
-
console.log(` ${green
|
|
576
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed MAXSIM hooks from settings`);
|
|
583
577
|
}
|
|
584
578
|
if (settingsHooks.SessionStart.length === 0) {
|
|
585
579
|
delete settingsHooks.SessionStart;
|
|
@@ -597,7 +591,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
597
591
|
});
|
|
598
592
|
if (settingsHooks.PostToolUse.length < before) {
|
|
599
593
|
settingsModified = true;
|
|
600
|
-
console.log(` ${green
|
|
594
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed context monitor hook from settings`);
|
|
601
595
|
}
|
|
602
596
|
if (settingsHooks.PostToolUse.length === 0) {
|
|
603
597
|
delete settingsHooks.PostToolUse;
|
|
@@ -644,7 +638,7 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
644
638
|
if (modified) {
|
|
645
639
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
646
640
|
removedCount++;
|
|
647
|
-
console.log(` ${green
|
|
641
|
+
console.log(` ${chalk_1.default.green('\u2713')} Removed MAXSIM permissions from opencode.json`);
|
|
648
642
|
}
|
|
649
643
|
}
|
|
650
644
|
catch {
|
|
@@ -653,10 +647,10 @@ function uninstall(isGlobal, runtime = 'claude') {
|
|
|
653
647
|
}
|
|
654
648
|
}
|
|
655
649
|
if (removedCount === 0) {
|
|
656
|
-
console.log(` ${yellow
|
|
650
|
+
console.log(` ${chalk_1.default.yellow('\u26a0')} No MAXSIM files found to remove.`);
|
|
657
651
|
}
|
|
658
652
|
console.log(`
|
|
659
|
-
${green
|
|
653
|
+
${chalk_1.default.green('Done!')} MAXSIM has been uninstalled from ${runtimeLabel}.
|
|
660
654
|
Your other files and settings have been preserved.
|
|
661
655
|
`);
|
|
662
656
|
}
|
|
@@ -729,9 +723,9 @@ function configureOpencodePermissions(isGlobal = true) {
|
|
|
729
723
|
config = parseJsonc(content);
|
|
730
724
|
}
|
|
731
725
|
catch (e) {
|
|
732
|
-
console.log(` ${yellow
|
|
733
|
-
console.log(` ${dim
|
|
734
|
-
console.log(` ${dim
|
|
726
|
+
console.log(` ${chalk_1.default.yellow('\u26a0')} Could not parse opencode.json - skipping permission config`);
|
|
727
|
+
console.log(` ${chalk_1.default.dim(`Reason: ${e.message}`)}`);
|
|
728
|
+
console.log(` ${chalk_1.default.dim('Your config was NOT modified. Fix the syntax manually if needed.')}`);
|
|
735
729
|
return;
|
|
736
730
|
}
|
|
737
731
|
}
|
|
@@ -763,25 +757,25 @@ function configureOpencodePermissions(isGlobal = true) {
|
|
|
763
757
|
return;
|
|
764
758
|
}
|
|
765
759
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
|
|
766
|
-
console.log(` ${green
|
|
760
|
+
console.log(` ${chalk_1.default.green('\u2713')} Configured read permission for MAXSIM docs`);
|
|
767
761
|
}
|
|
768
762
|
/**
|
|
769
763
|
* Verify a directory exists and contains files
|
|
770
764
|
*/
|
|
771
765
|
function verifyInstalled(dirPath, description) {
|
|
772
766
|
if (!fs.existsSync(dirPath)) {
|
|
773
|
-
console.error(` ${yellow
|
|
767
|
+
console.error(` ${chalk_1.default.yellow('\u2717')} Failed to install ${description}: directory not created`);
|
|
774
768
|
return false;
|
|
775
769
|
}
|
|
776
770
|
try {
|
|
777
771
|
const entries = fs.readdirSync(dirPath);
|
|
778
772
|
if (entries.length === 0) {
|
|
779
|
-
console.error(` ${yellow
|
|
773
|
+
console.error(` ${chalk_1.default.yellow('\u2717')} Failed to install ${description}: directory is empty`);
|
|
780
774
|
return false;
|
|
781
775
|
}
|
|
782
776
|
}
|
|
783
777
|
catch (e) {
|
|
784
|
-
console.error(` ${yellow
|
|
778
|
+
console.error(` ${chalk_1.default.yellow('\u2717')} Failed to install ${description}: ${e.message}`);
|
|
785
779
|
return false;
|
|
786
780
|
}
|
|
787
781
|
return true;
|
|
@@ -791,7 +785,7 @@ function verifyInstalled(dirPath, description) {
|
|
|
791
785
|
*/
|
|
792
786
|
function verifyFileInstalled(filePath, description) {
|
|
793
787
|
if (!fs.existsSync(filePath)) {
|
|
794
|
-
console.error(` ${yellow
|
|
788
|
+
console.error(` ${chalk_1.default.yellow('\u2717')} Failed to install ${description}: file not created`);
|
|
795
789
|
return false;
|
|
796
790
|
}
|
|
797
791
|
return true;
|
|
@@ -918,16 +912,14 @@ function saveLocalPatches(configDir) {
|
|
|
918
912
|
};
|
|
919
913
|
fs.writeFileSync(path.join(patchesDir, 'backup-meta.json'), JSON.stringify(meta, null, 2));
|
|
920
914
|
console.log(' ' +
|
|
921
|
-
yellow +
|
|
922
|
-
'i' +
|
|
923
|
-
reset +
|
|
915
|
+
chalk_1.default.yellow('i') +
|
|
924
916
|
' Found ' +
|
|
925
917
|
modified.length +
|
|
926
918
|
' locally modified MAXSIM file(s) \u2014 backed up to ' +
|
|
927
919
|
PATCHES_DIR_NAME +
|
|
928
920
|
'/');
|
|
929
921
|
for (const f of modified) {
|
|
930
|
-
console.log(' ' + dim
|
|
922
|
+
console.log(' ' + chalk_1.default.dim(f));
|
|
931
923
|
}
|
|
932
924
|
}
|
|
933
925
|
return modified;
|
|
@@ -955,25 +947,18 @@ function reportLocalPatches(configDir, runtime = 'claude') {
|
|
|
955
947
|
: '/maxsim:reapply-patches';
|
|
956
948
|
console.log('');
|
|
957
949
|
console.log(' ' +
|
|
958
|
-
yellow +
|
|
959
|
-
'Local patches detected' +
|
|
960
|
-
reset +
|
|
950
|
+
chalk_1.default.yellow('Local patches detected') +
|
|
961
951
|
' (from v' +
|
|
962
952
|
meta.from_version +
|
|
963
953
|
'):');
|
|
964
954
|
for (const f of meta.files) {
|
|
965
|
-
console.log(' ' + cyan
|
|
955
|
+
console.log(' ' + chalk_1.default.cyan(f));
|
|
966
956
|
}
|
|
967
957
|
console.log('');
|
|
968
958
|
console.log(' Your modifications are saved in ' +
|
|
969
|
-
cyan +
|
|
970
|
-
PATCHES_DIR_NAME +
|
|
971
|
-
'/' +
|
|
972
|
-
reset);
|
|
959
|
+
chalk_1.default.cyan(PATCHES_DIR_NAME + '/'));
|
|
973
960
|
console.log(' Run ' +
|
|
974
|
-
cyan +
|
|
975
|
-
reapplyCommand +
|
|
976
|
-
reset +
|
|
961
|
+
chalk_1.default.cyan(reapplyCommand) +
|
|
977
962
|
' to merge them into the new version.');
|
|
978
963
|
console.log(' Or manually compare and merge the files.');
|
|
979
964
|
console.log('');
|
|
@@ -1002,13 +987,14 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1002
987
|
runtimeLabel = 'Gemini';
|
|
1003
988
|
if (isCodex)
|
|
1004
989
|
runtimeLabel = 'Codex';
|
|
1005
|
-
console.log(` Installing for ${cyan
|
|
990
|
+
console.log(` Installing for ${chalk_1.default.cyan(runtimeLabel)} to ${chalk_1.default.cyan(locationLabel)}\n`);
|
|
1006
991
|
const failures = [];
|
|
1007
992
|
// Save any locally modified MAXSIM files before they get wiped
|
|
1008
993
|
saveLocalPatches(targetDir);
|
|
1009
994
|
// Clean up orphaned files from previous versions
|
|
1010
995
|
cleanupOrphanedFiles(targetDir);
|
|
1011
996
|
// OpenCode uses command/ (flat), Codex uses skills/, Claude/Gemini use commands/maxsim/
|
|
997
|
+
let spinner = (0, ora_1.default)({ text: 'Installing commands...', color: 'cyan' }).start();
|
|
1012
998
|
if (isOpencode) {
|
|
1013
999
|
const commandDir = path.join(targetDir, 'command');
|
|
1014
1000
|
fs.mkdirSync(commandDir, { recursive: true });
|
|
@@ -1018,9 +1004,10 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1018
1004
|
const count = fs
|
|
1019
1005
|
.readdirSync(commandDir)
|
|
1020
1006
|
.filter((f) => f.startsWith('maxsim-')).length;
|
|
1021
|
-
|
|
1007
|
+
spinner.succeed(chalk_1.default.green('✓') + ` Installed ${count} commands to command/`);
|
|
1022
1008
|
}
|
|
1023
1009
|
else {
|
|
1010
|
+
spinner.fail('Failed to install commands');
|
|
1024
1011
|
failures.push('command/maxsim-*');
|
|
1025
1012
|
}
|
|
1026
1013
|
}
|
|
@@ -1030,9 +1017,10 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1030
1017
|
copyCommandsAsCodexSkills(maxsimSrc, skillsDir, 'maxsim', pathPrefix, runtime);
|
|
1031
1018
|
const installedSkillNames = listCodexSkillNames(skillsDir);
|
|
1032
1019
|
if (installedSkillNames.length > 0) {
|
|
1033
|
-
|
|
1020
|
+
spinner.succeed(chalk_1.default.green('✓') + ` Installed ${installedSkillNames.length} skills to skills/`);
|
|
1034
1021
|
}
|
|
1035
1022
|
else {
|
|
1023
|
+
spinner.fail('Failed to install skills');
|
|
1036
1024
|
failures.push('skills/maxsim-*');
|
|
1037
1025
|
}
|
|
1038
1026
|
}
|
|
@@ -1043,15 +1031,17 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1043
1031
|
const maxsimDest = path.join(commandsDir, 'maxsim');
|
|
1044
1032
|
copyWithPathReplacement(maxsimSrc, maxsimDest, pathPrefix, runtime, true);
|
|
1045
1033
|
if (verifyInstalled(maxsimDest, 'commands/maxsim')) {
|
|
1046
|
-
|
|
1034
|
+
spinner.succeed(chalk_1.default.green('✓') + ' Installed commands/maxsim');
|
|
1047
1035
|
}
|
|
1048
1036
|
else {
|
|
1037
|
+
spinner.fail('Failed to install commands/maxsim');
|
|
1049
1038
|
failures.push('commands/maxsim');
|
|
1050
1039
|
}
|
|
1051
1040
|
}
|
|
1052
1041
|
// Copy maxsim directory content (workflows, templates, references) with path replacement
|
|
1053
1042
|
// Templates package layout: workflows/, templates/, references/ at root
|
|
1054
1043
|
// Install target: maxsim/workflows/, maxsim/templates/, maxsim/references/
|
|
1044
|
+
spinner = (0, ora_1.default)({ text: 'Installing workflows and templates...', color: 'cyan' }).start();
|
|
1055
1045
|
const skillDest = path.join(targetDir, 'maxsim');
|
|
1056
1046
|
const maxsimSubdirs = ['workflows', 'templates', 'references'];
|
|
1057
1047
|
if (fs.existsSync(skillDest)) {
|
|
@@ -1066,14 +1056,16 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1066
1056
|
}
|
|
1067
1057
|
}
|
|
1068
1058
|
if (verifyInstalled(skillDest, 'maxsim')) {
|
|
1069
|
-
|
|
1059
|
+
spinner.succeed(chalk_1.default.green('✓') + ' Installed maxsim');
|
|
1070
1060
|
}
|
|
1071
1061
|
else {
|
|
1062
|
+
spinner.fail('Failed to install maxsim');
|
|
1072
1063
|
failures.push('maxsim');
|
|
1073
1064
|
}
|
|
1074
1065
|
// Copy agents to agents directory
|
|
1075
1066
|
const agentsSrc = path.join(src, 'agents');
|
|
1076
1067
|
if (fs.existsSync(agentsSrc)) {
|
|
1068
|
+
spinner = (0, ora_1.default)({ text: 'Installing agents...', color: 'cyan' }).start();
|
|
1077
1069
|
const agentsDest = path.join(targetDir, 'agents');
|
|
1078
1070
|
fs.mkdirSync(agentsDest, { recursive: true });
|
|
1079
1071
|
// Remove old MAXSIM agents before copying new ones
|
|
@@ -1104,9 +1096,10 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1104
1096
|
}
|
|
1105
1097
|
}
|
|
1106
1098
|
if (verifyInstalled(agentsDest, 'agents')) {
|
|
1107
|
-
|
|
1099
|
+
spinner.succeed(chalk_1.default.green('✓') + ' Installed agents');
|
|
1108
1100
|
}
|
|
1109
1101
|
else {
|
|
1102
|
+
spinner.fail('Failed to install agents');
|
|
1110
1103
|
failures.push('agents');
|
|
1111
1104
|
}
|
|
1112
1105
|
}
|
|
@@ -1114,11 +1107,13 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1114
1107
|
const changelogSrc = path.join(src, '..', 'CHANGELOG.md');
|
|
1115
1108
|
const changelogDest = path.join(targetDir, 'maxsim', 'CHANGELOG.md');
|
|
1116
1109
|
if (fs.existsSync(changelogSrc)) {
|
|
1110
|
+
spinner = (0, ora_1.default)({ text: 'Installing CHANGELOG.md...', color: 'cyan' }).start();
|
|
1117
1111
|
fs.copyFileSync(changelogSrc, changelogDest);
|
|
1118
1112
|
if (verifyFileInstalled(changelogDest, 'CHANGELOG.md')) {
|
|
1119
|
-
|
|
1113
|
+
spinner.succeed(chalk_1.default.green('✓') + ' Installed CHANGELOG.md');
|
|
1120
1114
|
}
|
|
1121
1115
|
else {
|
|
1116
|
+
spinner.fail('Failed to install CHANGELOG.md');
|
|
1122
1117
|
failures.push('CHANGELOG.md');
|
|
1123
1118
|
}
|
|
1124
1119
|
}
|
|
@@ -1126,11 +1121,13 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1126
1121
|
const claudeMdSrc = path.join(src, 'CLAUDE.md');
|
|
1127
1122
|
const claudeMdDest = path.join(targetDir, 'CLAUDE.md');
|
|
1128
1123
|
if (fs.existsSync(claudeMdSrc)) {
|
|
1124
|
+
spinner = (0, ora_1.default)({ text: 'Installing CLAUDE.md...', color: 'cyan' }).start();
|
|
1129
1125
|
fs.copyFileSync(claudeMdSrc, claudeMdDest);
|
|
1130
1126
|
if (verifyFileInstalled(claudeMdDest, 'CLAUDE.md')) {
|
|
1131
|
-
|
|
1127
|
+
spinner.succeed(chalk_1.default.green('✓') + ' Installed CLAUDE.md');
|
|
1132
1128
|
}
|
|
1133
1129
|
else {
|
|
1130
|
+
spinner.fail('Failed to install CLAUDE.md');
|
|
1134
1131
|
failures.push('CLAUDE.md');
|
|
1135
1132
|
}
|
|
1136
1133
|
}
|
|
@@ -1138,7 +1135,7 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1138
1135
|
const versionDest = path.join(targetDir, 'maxsim', 'VERSION');
|
|
1139
1136
|
fs.writeFileSync(versionDest, pkg.version);
|
|
1140
1137
|
if (verifyFileInstalled(versionDest, 'VERSION')) {
|
|
1141
|
-
console.log(` ${green
|
|
1138
|
+
console.log(` ${chalk_1.default.green('\u2713')} Wrote VERSION (${pkg.version})`);
|
|
1142
1139
|
}
|
|
1143
1140
|
else {
|
|
1144
1141
|
failures.push('VERSION');
|
|
@@ -1147,7 +1144,7 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1147
1144
|
// Write package.json to force CommonJS mode for MAXSIM scripts
|
|
1148
1145
|
const pkgJsonDest = path.join(targetDir, 'package.json');
|
|
1149
1146
|
fs.writeFileSync(pkgJsonDest, '{"type":"commonjs"}\n');
|
|
1150
|
-
console.log(` ${green
|
|
1147
|
+
console.log(` ${chalk_1.default.green('\u2713')} Wrote package.json (CommonJS mode)`);
|
|
1151
1148
|
// Copy hooks from bundled assets directory (copied from @maxsim/hooks/dist at build time)
|
|
1152
1149
|
let hooksSrc = null;
|
|
1153
1150
|
const bundledHooksDir = path.resolve(__dirname, 'assets', 'hooks');
|
|
@@ -1155,9 +1152,10 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1155
1152
|
hooksSrc = bundledHooksDir;
|
|
1156
1153
|
}
|
|
1157
1154
|
else {
|
|
1158
|
-
console.warn(` ${yellow}
|
|
1155
|
+
console.warn(` ${chalk_1.default.yellow('!')} bundled hooks not found - hooks will not be installed`);
|
|
1159
1156
|
}
|
|
1160
1157
|
if (hooksSrc) {
|
|
1158
|
+
spinner = (0, ora_1.default)({ text: 'Installing hooks...', color: 'cyan' }).start();
|
|
1161
1159
|
const hooksDest = path.join(targetDir, 'hooks');
|
|
1162
1160
|
fs.mkdirSync(hooksDest, { recursive: true });
|
|
1163
1161
|
const hookEntries = fs.readdirSync(hooksSrc);
|
|
@@ -1173,20 +1171,21 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1173
1171
|
}
|
|
1174
1172
|
}
|
|
1175
1173
|
if (verifyInstalled(hooksDest, 'hooks')) {
|
|
1176
|
-
|
|
1174
|
+
spinner.succeed(chalk_1.default.green('✓') + ' Installed hooks (bundled)');
|
|
1177
1175
|
}
|
|
1178
1176
|
else {
|
|
1177
|
+
spinner.fail('Failed to install hooks');
|
|
1179
1178
|
failures.push('hooks');
|
|
1180
1179
|
}
|
|
1181
1180
|
}
|
|
1182
1181
|
}
|
|
1183
1182
|
if (failures.length > 0) {
|
|
1184
|
-
console.error(`\n ${yellow
|
|
1183
|
+
console.error(`\n ${chalk_1.default.yellow('Installation incomplete!')} Failed: ${failures.join(', ')}`);
|
|
1185
1184
|
process.exit(1);
|
|
1186
1185
|
}
|
|
1187
1186
|
// Write file manifest for future modification detection
|
|
1188
1187
|
writeManifest(targetDir, runtime);
|
|
1189
|
-
console.log(` ${green
|
|
1188
|
+
console.log(` ${chalk_1.default.green('\u2713')} Wrote file manifest (${MANIFEST_NAME})`);
|
|
1190
1189
|
// Report any backed-up local patches
|
|
1191
1190
|
reportLocalPatches(targetDir, runtime);
|
|
1192
1191
|
if (isCodex) {
|
|
@@ -1217,7 +1216,7 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1217
1216
|
const experimental = settings.experimental;
|
|
1218
1217
|
if (!experimental.enableAgents) {
|
|
1219
1218
|
experimental.enableAgents = true;
|
|
1220
|
-
console.log(` ${green
|
|
1219
|
+
console.log(` ${chalk_1.default.green('\u2713')} Enabled experimental agents`);
|
|
1221
1220
|
}
|
|
1222
1221
|
}
|
|
1223
1222
|
// Configure SessionStart hook for update checking (skip for opencode)
|
|
@@ -1240,7 +1239,7 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1240
1239
|
},
|
|
1241
1240
|
],
|
|
1242
1241
|
});
|
|
1243
|
-
console.log(` ${green
|
|
1242
|
+
console.log(` ${chalk_1.default.green('\u2713')} Configured update check hook`);
|
|
1244
1243
|
}
|
|
1245
1244
|
// Configure PostToolUse hook for context window monitoring
|
|
1246
1245
|
if (!installHooks.PostToolUse) {
|
|
@@ -1257,7 +1256,7 @@ function install(isGlobal, runtime = 'claude') {
|
|
|
1257
1256
|
},
|
|
1258
1257
|
],
|
|
1259
1258
|
});
|
|
1260
|
-
console.log(` ${green
|
|
1259
|
+
console.log(` ${chalk_1.default.green('\u2713')} Configured context window monitor hook`);
|
|
1261
1260
|
}
|
|
1262
1261
|
}
|
|
1263
1262
|
return { settingsPath, settings, statuslineCommand, runtime };
|
|
@@ -1273,7 +1272,7 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
1273
1272
|
type: 'command',
|
|
1274
1273
|
command: statuslineCommand,
|
|
1275
1274
|
};
|
|
1276
|
-
console.log(` ${green
|
|
1275
|
+
console.log(` ${chalk_1.default.green('\u2713')} Configured statusline`);
|
|
1277
1276
|
}
|
|
1278
1277
|
if (!isCodex && settingsPath && settings) {
|
|
1279
1278
|
(0, adapters_1.writeSettings)(settingsPath, settings);
|
|
@@ -1294,143 +1293,91 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
|
|
|
1294
1293
|
if (runtime === 'codex')
|
|
1295
1294
|
command = '$maxsim-help';
|
|
1296
1295
|
console.log(`
|
|
1297
|
-
${green
|
|
1296
|
+
${chalk_1.default.green('Done!')} Launch ${program} and run ${chalk_1.default.cyan(command)}.
|
|
1298
1297
|
|
|
1299
|
-
${cyan
|
|
1298
|
+
${chalk_1.default.cyan('Join the community:')} https://discord.gg/5JJgD5svVS
|
|
1300
1299
|
`);
|
|
1301
1300
|
}
|
|
1302
1301
|
/**
|
|
1303
|
-
* Handle statusline configuration
|
|
1302
|
+
* Handle statusline configuration — returns true if MAXSIM statusline should be installed
|
|
1304
1303
|
*/
|
|
1305
|
-
function handleStatusline(settings, isInteractive
|
|
1304
|
+
async function handleStatusline(settings, isInteractive) {
|
|
1306
1305
|
const hasExisting = settings.statusLine != null;
|
|
1307
|
-
if (!hasExisting)
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
if (forceStatusline) {
|
|
1312
|
-
callback(true);
|
|
1313
|
-
return;
|
|
1314
|
-
}
|
|
1306
|
+
if (!hasExisting)
|
|
1307
|
+
return true;
|
|
1308
|
+
if (forceStatusline)
|
|
1309
|
+
return true;
|
|
1315
1310
|
if (!isInteractive) {
|
|
1316
|
-
console.log(
|
|
1317
|
-
console.log(
|
|
1318
|
-
|
|
1319
|
-
return;
|
|
1311
|
+
console.log(chalk_1.default.yellow('⚠') + ' Skipping statusline (already configured)');
|
|
1312
|
+
console.log(' Use ' + chalk_1.default.cyan('--force-statusline') + ' to replace\n');
|
|
1313
|
+
return false;
|
|
1320
1314
|
}
|
|
1321
1315
|
const statusLine = settings.statusLine;
|
|
1322
1316
|
const existingCmd = statusLine.command || statusLine.url || '(custom)';
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
console.log(`
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
${cyan}1${reset}) Keep existing
|
|
1338
|
-
${cyan}2${reset}) Replace with MAXSIM statusline
|
|
1339
|
-
`);
|
|
1340
|
-
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
|
1341
|
-
rl.close();
|
|
1342
|
-
const choice = answer.trim() || '1';
|
|
1343
|
-
callback(choice === '2');
|
|
1317
|
+
console.log();
|
|
1318
|
+
console.log(chalk_1.default.yellow('⚠ Existing statusline detected'));
|
|
1319
|
+
console.log();
|
|
1320
|
+
console.log(' Your current statusline:');
|
|
1321
|
+
console.log(' ' + chalk_1.default.dim(`command: ${existingCmd}`));
|
|
1322
|
+
console.log();
|
|
1323
|
+
console.log(' MAXSIM includes a statusline showing:');
|
|
1324
|
+
console.log(' • Model name');
|
|
1325
|
+
console.log(' • Current task (from todo list)');
|
|
1326
|
+
console.log(' • Context window usage (color-coded)');
|
|
1327
|
+
console.log();
|
|
1328
|
+
const shouldReplace = await (0, prompts_1.confirm)({
|
|
1329
|
+
message: 'Replace with MAXSIM statusline?',
|
|
1330
|
+
default: false,
|
|
1344
1331
|
});
|
|
1332
|
+
return shouldReplace;
|
|
1345
1333
|
}
|
|
1346
1334
|
/**
|
|
1347
|
-
* Prompt for runtime selection
|
|
1335
|
+
* Prompt for runtime selection (multi-select)
|
|
1348
1336
|
*/
|
|
1349
|
-
function promptRuntime(
|
|
1350
|
-
const
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
process.exit(0);
|
|
1360
|
-
}
|
|
1361
|
-
});
|
|
1362
|
-
console.log(` ${yellow}Which runtime(s) would you like to install for?${reset}\n\n ${cyan}1${reset}) Claude Code ${dim}(~/.claude)${reset}
|
|
1363
|
-
${cyan}2${reset}) OpenCode ${dim}(~/.config/opencode)${reset} - open source, free models
|
|
1364
|
-
${cyan}3${reset}) Gemini ${dim}(~/.gemini)${reset}
|
|
1365
|
-
${cyan}4${reset}) Codex ${dim}(~/.codex)${reset}
|
|
1366
|
-
${cyan}5${reset}) All
|
|
1367
|
-
`);
|
|
1368
|
-
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
|
1369
|
-
answered = true;
|
|
1370
|
-
rl.close();
|
|
1371
|
-
const choice = answer.trim() || '1';
|
|
1372
|
-
if (choice === '5') {
|
|
1373
|
-
callback(['claude', 'opencode', 'gemini', 'codex']);
|
|
1374
|
-
}
|
|
1375
|
-
else if (choice === '4') {
|
|
1376
|
-
callback(['codex']);
|
|
1377
|
-
}
|
|
1378
|
-
else if (choice === '3') {
|
|
1379
|
-
callback(['gemini']);
|
|
1380
|
-
}
|
|
1381
|
-
else if (choice === '2') {
|
|
1382
|
-
callback(['opencode']);
|
|
1383
|
-
}
|
|
1384
|
-
else {
|
|
1385
|
-
callback(['claude']);
|
|
1386
|
-
}
|
|
1337
|
+
async function promptRuntime() {
|
|
1338
|
+
const selected = await (0, prompts_1.checkbox)({
|
|
1339
|
+
message: 'Which runtime(s) would you like to install for?',
|
|
1340
|
+
choices: [
|
|
1341
|
+
{ name: 'Claude Code ' + chalk_1.default.dim('(~/.claude)'), value: 'claude', checked: true },
|
|
1342
|
+
{ name: 'OpenCode ' + chalk_1.default.dim('(~/.config/opencode)') + ' — open source, free models', value: 'opencode' },
|
|
1343
|
+
{ name: 'Gemini ' + chalk_1.default.dim('(~/.gemini)'), value: 'gemini' },
|
|
1344
|
+
{ name: 'Codex ' + chalk_1.default.dim('(~/.codex)'), value: 'codex' },
|
|
1345
|
+
],
|
|
1346
|
+
validate: (choices) => choices.length > 0 || 'Please select at least one runtime',
|
|
1387
1347
|
});
|
|
1348
|
+
return selected;
|
|
1388
1349
|
}
|
|
1389
1350
|
/**
|
|
1390
1351
|
* Prompt for install location
|
|
1391
1352
|
*/
|
|
1392
|
-
function promptLocation(runtimes) {
|
|
1353
|
+
async function promptLocation(runtimes) {
|
|
1393
1354
|
if (!process.stdin.isTTY) {
|
|
1394
|
-
console.log(
|
|
1395
|
-
|
|
1396
|
-
return;
|
|
1355
|
+
console.log(chalk_1.default.yellow('Non-interactive terminal detected, defaulting to global install') + '\n');
|
|
1356
|
+
return true; // isGlobal
|
|
1397
1357
|
}
|
|
1398
|
-
const rl = readline.createInterface({
|
|
1399
|
-
input: process.stdin,
|
|
1400
|
-
output: process.stdout,
|
|
1401
|
-
});
|
|
1402
|
-
let answered = false;
|
|
1403
|
-
rl.on('close', () => {
|
|
1404
|
-
if (!answered) {
|
|
1405
|
-
answered = true;
|
|
1406
|
-
console.log(`\n ${yellow}Installation cancelled${reset}\n`);
|
|
1407
|
-
process.exit(0);
|
|
1408
|
-
}
|
|
1409
|
-
});
|
|
1410
1358
|
const pathExamples = runtimes
|
|
1411
|
-
.map((r) =>
|
|
1412
|
-
const globalPath = getGlobalDir(r, explicitConfigDir);
|
|
1413
|
-
return globalPath.replace(os.homedir(), '~');
|
|
1414
|
-
})
|
|
1415
|
-
.join(', ');
|
|
1416
|
-
const localExamples = runtimes
|
|
1417
|
-
.map((r) => `./${getDirName(r)}`)
|
|
1359
|
+
.map((r) => getGlobalDir(r, explicitConfigDir).replace(os.homedir(), '~'))
|
|
1418
1360
|
.join(', ');
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1361
|
+
const localExamples = runtimes.map((r) => `./${getDirName(r)}`).join(', ');
|
|
1362
|
+
const choice = await (0, prompts_1.select)({
|
|
1363
|
+
message: 'Where would you like to install?',
|
|
1364
|
+
choices: [
|
|
1365
|
+
{
|
|
1366
|
+
name: 'Global ' + chalk_1.default.dim(`(${pathExamples})`) + ' — available in all projects',
|
|
1367
|
+
value: 'global',
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
name: 'Local ' + chalk_1.default.dim(`(${localExamples})`) + ' — this project only',
|
|
1371
|
+
value: 'local',
|
|
1372
|
+
},
|
|
1373
|
+
],
|
|
1428
1374
|
});
|
|
1375
|
+
return choice === 'global';
|
|
1429
1376
|
}
|
|
1430
1377
|
/**
|
|
1431
1378
|
* Install MAXSIM for all selected runtimes
|
|
1432
1379
|
*/
|
|
1433
|
-
function installAllRuntimes(runtimes, isGlobal, isInteractive) {
|
|
1380
|
+
async function installAllRuntimes(runtimes, isGlobal, isInteractive) {
|
|
1434
1381
|
const results = [];
|
|
1435
1382
|
for (const runtime of runtimes) {
|
|
1436
1383
|
const result = install(isGlobal, runtime);
|
|
@@ -1438,58 +1385,65 @@ function installAllRuntimes(runtimes, isGlobal, isInteractive) {
|
|
|
1438
1385
|
}
|
|
1439
1386
|
const statuslineRuntimes = ['claude', 'gemini'];
|
|
1440
1387
|
const primaryStatuslineResult = results.find((r) => statuslineRuntimes.includes(r.runtime));
|
|
1441
|
-
|
|
1442
|
-
for (const result of results) {
|
|
1443
|
-
const useStatusline = statuslineRuntimes.includes(result.runtime) && shouldInstallStatusline;
|
|
1444
|
-
finishInstall(result.settingsPath, result.settings, result.statuslineCommand, useStatusline, result.runtime, isGlobal);
|
|
1445
|
-
}
|
|
1446
|
-
};
|
|
1388
|
+
let shouldInstallStatusline = false;
|
|
1447
1389
|
if (primaryStatuslineResult && primaryStatuslineResult.settings) {
|
|
1448
|
-
handleStatusline(primaryStatuslineResult.settings, isInteractive
|
|
1390
|
+
shouldInstallStatusline = await handleStatusline(primaryStatuslineResult.settings, isInteractive);
|
|
1449
1391
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1392
|
+
for (const result of results) {
|
|
1393
|
+
const useStatusline = statuslineRuntimes.includes(result.runtime) && shouldInstallStatusline;
|
|
1394
|
+
finishInstall(result.settingsPath, result.settings, result.statuslineCommand, useStatusline, result.runtime, isGlobal);
|
|
1452
1395
|
}
|
|
1453
1396
|
}
|
|
1454
1397
|
// Main logic
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
}
|
|
1459
|
-
else if (explicitConfigDir && hasLocal) {
|
|
1460
|
-
console.error(` ${yellow}Cannot use --config-dir with --local${reset}`);
|
|
1461
|
-
process.exit(1);
|
|
1462
|
-
}
|
|
1463
|
-
else if (hasUninstall) {
|
|
1464
|
-
if (!hasGlobal && !hasLocal) {
|
|
1465
|
-
console.error(` ${yellow}--uninstall requires --global or --local${reset}`);
|
|
1398
|
+
(async () => {
|
|
1399
|
+
if (hasGlobal && hasLocal) {
|
|
1400
|
+
console.error(chalk_1.default.yellow('Cannot specify both --global and --local'));
|
|
1466
1401
|
process.exit(1);
|
|
1467
1402
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1403
|
+
else if (explicitConfigDir && hasLocal) {
|
|
1404
|
+
console.error(chalk_1.default.yellow('Cannot use --config-dir with --local'));
|
|
1405
|
+
process.exit(1);
|
|
1471
1406
|
}
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1407
|
+
else if (hasUninstall) {
|
|
1408
|
+
if (!hasGlobal && !hasLocal) {
|
|
1409
|
+
console.error(chalk_1.default.yellow('--uninstall requires --global or --local'));
|
|
1410
|
+
process.exit(1);
|
|
1411
|
+
}
|
|
1412
|
+
const runtimes = selectedRuntimes.length > 0 ? selectedRuntimes : ['claude'];
|
|
1413
|
+
for (const runtime of runtimes) {
|
|
1414
|
+
uninstall(hasGlobal, runtime);
|
|
1415
|
+
}
|
|
1476
1416
|
}
|
|
1477
|
-
else {
|
|
1478
|
-
|
|
1417
|
+
else if (selectedRuntimes.length > 0) {
|
|
1418
|
+
if (!hasGlobal && !hasLocal) {
|
|
1419
|
+
const isGlobal = await promptLocation(selectedRuntimes);
|
|
1420
|
+
await installAllRuntimes(selectedRuntimes, isGlobal, true);
|
|
1421
|
+
}
|
|
1422
|
+
else {
|
|
1423
|
+
await installAllRuntimes(selectedRuntimes, hasGlobal, false);
|
|
1424
|
+
}
|
|
1479
1425
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
installAllRuntimes(['claude'], hasGlobal, false);
|
|
1483
|
-
}
|
|
1484
|
-
else {
|
|
1485
|
-
if (!process.stdin.isTTY) {
|
|
1486
|
-
console.log(` ${yellow}Non-interactive terminal detected, defaulting to Claude Code global install${reset}\n`);
|
|
1487
|
-
installAllRuntimes(['claude'], true, false);
|
|
1426
|
+
else if (hasGlobal || hasLocal) {
|
|
1427
|
+
await installAllRuntimes(['claude'], hasGlobal, false);
|
|
1488
1428
|
}
|
|
1489
1429
|
else {
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1430
|
+
if (!process.stdin.isTTY) {
|
|
1431
|
+
console.log(chalk_1.default.yellow('Non-interactive terminal detected, defaulting to Claude Code global install') + '\n');
|
|
1432
|
+
await installAllRuntimes(['claude'], true, false);
|
|
1433
|
+
}
|
|
1434
|
+
else {
|
|
1435
|
+
const runtimes = await promptRuntime();
|
|
1436
|
+
const isGlobal = await promptLocation(runtimes);
|
|
1437
|
+
await installAllRuntimes(runtimes, isGlobal, true);
|
|
1438
|
+
}
|
|
1493
1439
|
}
|
|
1494
|
-
}
|
|
1440
|
+
})().catch((err) => {
|
|
1441
|
+
if (err instanceof Error && err.message.includes('User force closed')) {
|
|
1442
|
+
// User pressed Ctrl+C during an @inquirer/prompts prompt — exit cleanly
|
|
1443
|
+
console.log('\n' + chalk_1.default.yellow('Installation cancelled') + '\n');
|
|
1444
|
+
process.exit(0);
|
|
1445
|
+
}
|
|
1446
|
+
console.error(chalk_1.default.red('Unexpected error:'), err);
|
|
1447
|
+
process.exit(1);
|
|
1448
|
+
});
|
|
1495
1449
|
//# sourceMappingURL=install.js.map
|