@_xtribe/cli 1.0.0-beta.25 → 1.0.0-beta.26
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/install-tribe.js +297 -147
- package/package.json +1 -4
package/install-tribe.js
CHANGED
|
@@ -18,6 +18,7 @@ const arch = nodeArch === 'x64' ? 'amd64' : (nodeArch === 'arm64' || nodeArch ==
|
|
|
18
18
|
const homeDir = os.homedir();
|
|
19
19
|
const binDir = path.join(homeDir, 'bin');
|
|
20
20
|
const tribeDir = path.join(homeDir, '.tribe');
|
|
21
|
+
const tribeBinDir = path.join(tribeDir, 'bin');
|
|
21
22
|
|
|
22
23
|
// Ensure local bin directory exists
|
|
23
24
|
if (!fs.existsSync(binDir)) {
|
|
@@ -29,6 +30,11 @@ if (!fs.existsSync(tribeDir)) {
|
|
|
29
30
|
fs.mkdirSync(tribeDir, { recursive: true });
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
// Ensure TRIBE bin directory exists
|
|
34
|
+
if (!fs.existsSync(tribeBinDir)) {
|
|
35
|
+
fs.mkdirSync(tribeBinDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
const log = {
|
|
33
39
|
success: (msg) => console.log(chalk.green('✓'), msg),
|
|
34
40
|
error: (msg) => console.log(chalk.red('✗'), msg),
|
|
@@ -302,21 +308,160 @@ async function installKubectl() {
|
|
|
302
308
|
}
|
|
303
309
|
}
|
|
304
310
|
|
|
311
|
+
async function setupGlobalNpmCommand() {
|
|
312
|
+
const spinner = ora('Setting up global tribe command...').start();
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
// Create a temporary directory for the global package
|
|
316
|
+
const tempDir = path.join(os.tmpdir(), 'tribe-global-install-' + Date.now());
|
|
317
|
+
fs.mkdirSync(tempDir, { recursive: true });
|
|
318
|
+
|
|
319
|
+
// Create package.json for global command
|
|
320
|
+
const packageJson = {
|
|
321
|
+
name: 'tribe-cli-global',
|
|
322
|
+
version: '1.0.0',
|
|
323
|
+
description: 'TRIBE CLI global command',
|
|
324
|
+
bin: {
|
|
325
|
+
tribe: './tribe-wrapper.js'
|
|
326
|
+
},
|
|
327
|
+
files: ['tribe-wrapper.js'],
|
|
328
|
+
private: true
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
fs.writeFileSync(
|
|
332
|
+
path.join(tempDir, 'package.json'),
|
|
333
|
+
JSON.stringify(packageJson, null, 2)
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
// Create the wrapper script
|
|
337
|
+
const wrapperScript = `#!/usr/bin/env node
|
|
338
|
+
|
|
339
|
+
const { spawn } = require('child_process');
|
|
340
|
+
const fs = require('fs');
|
|
341
|
+
const path = require('path');
|
|
342
|
+
const os = require('os');
|
|
343
|
+
|
|
344
|
+
// Path to the actual tribe binary installed by the installer
|
|
345
|
+
const tribeBinaryPath = path.join(os.homedir(), '.tribe', 'bin', 'tribe');
|
|
346
|
+
|
|
347
|
+
// Check if tribe binary exists
|
|
348
|
+
if (!fs.existsSync(tribeBinaryPath)) {
|
|
349
|
+
console.error('Error: TRIBE CLI binary not found.');
|
|
350
|
+
console.error('Please reinstall using: npx @_xtribe/cli --force');
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Make sure binary is executable
|
|
355
|
+
try {
|
|
356
|
+
fs.accessSync(tribeBinaryPath, fs.constants.X_OK);
|
|
357
|
+
} catch (err) {
|
|
358
|
+
console.error('Error: TRIBE CLI binary is not executable.');
|
|
359
|
+
console.error('Please reinstall using: npx @_xtribe/cli --force');
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Forward all arguments to the actual tribe binary
|
|
364
|
+
const child = spawn(tribeBinaryPath, process.argv.slice(2), {
|
|
365
|
+
stdio: 'inherit',
|
|
366
|
+
env: process.env
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
child.on('exit', (code) => {
|
|
370
|
+
process.exit(code || 0);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
child.on('error', (err) => {
|
|
374
|
+
if (err.code === 'ENOENT') {
|
|
375
|
+
console.error('Error: TRIBE CLI binary not found at expected location.');
|
|
376
|
+
console.error('Please reinstall using: npx @_xtribe/cli --force');
|
|
377
|
+
} else {
|
|
378
|
+
console.error('Failed to execute tribe:', err.message);
|
|
379
|
+
}
|
|
380
|
+
process.exit(1);
|
|
381
|
+
});`;
|
|
382
|
+
|
|
383
|
+
const wrapperPath = path.join(tempDir, 'tribe-wrapper.js');
|
|
384
|
+
fs.writeFileSync(wrapperPath, wrapperScript);
|
|
385
|
+
fs.chmodSync(wrapperPath, '755');
|
|
386
|
+
|
|
387
|
+
// Install globally using npm
|
|
388
|
+
spinner.text = 'Installing tribe command globally...';
|
|
389
|
+
try {
|
|
390
|
+
// First try with --force to handle conflicts
|
|
391
|
+
execSync('npm install -g . --force', {
|
|
392
|
+
cwd: tempDir,
|
|
393
|
+
stdio: 'pipe'
|
|
394
|
+
});
|
|
395
|
+
spinner.succeed('Global tribe command installed successfully');
|
|
396
|
+
} catch (error) {
|
|
397
|
+
// Try with sudo if permission denied
|
|
398
|
+
if (error.message.includes('EACCES') || error.message.includes('permission')) {
|
|
399
|
+
spinner.warn('Global installation requires sudo permission');
|
|
400
|
+
log.info('Attempting with sudo...');
|
|
401
|
+
try {
|
|
402
|
+
execSync('sudo npm install -g . --force', {
|
|
403
|
+
cwd: tempDir,
|
|
404
|
+
stdio: 'inherit'
|
|
405
|
+
});
|
|
406
|
+
spinner.succeed('Global tribe command installed successfully (with sudo)');
|
|
407
|
+
} catch (sudoError) {
|
|
408
|
+
throw new Error('Failed to install globally. You may need to run with sudo or fix npm permissions.');
|
|
409
|
+
}
|
|
410
|
+
} else if (error.message.includes('EEXIST')) {
|
|
411
|
+
// Try to remove existing and retry
|
|
412
|
+
spinner.text = 'Removing conflicting global command...';
|
|
413
|
+
try {
|
|
414
|
+
execSync('npm uninstall -g tribe-cli-global @_xtribe/cli', { stdio: 'ignore' });
|
|
415
|
+
execSync('npm install -g . --force', {
|
|
416
|
+
cwd: tempDir,
|
|
417
|
+
stdio: 'pipe'
|
|
418
|
+
});
|
|
419
|
+
spinner.succeed('Global tribe command installed successfully (after cleanup)');
|
|
420
|
+
} catch (retryError) {
|
|
421
|
+
throw new Error('Failed to install globally due to conflicts. Try running: npm uninstall -g @_xtribe/cli');
|
|
422
|
+
}
|
|
423
|
+
} else {
|
|
424
|
+
throw error;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Clean up temp directory
|
|
429
|
+
try {
|
|
430
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
431
|
+
} catch (cleanupError) {
|
|
432
|
+
// Ignore cleanup errors
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
return true;
|
|
436
|
+
} catch (error) {
|
|
437
|
+
spinner.fail(`Failed to set up global command: ${error.message}`);
|
|
438
|
+
log.info('You can still use tribe via the direct path: ~/.tribe/bin/tribe');
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
305
443
|
async function installTribeCLI() {
|
|
306
444
|
const spinner = ora('Installing TRIBE CLI...').start();
|
|
307
445
|
|
|
308
446
|
try {
|
|
309
|
-
const tribeDest = path.join(
|
|
447
|
+
const tribeDest = path.join(tribeBinDir, 'tribe');
|
|
310
448
|
|
|
311
|
-
//
|
|
449
|
+
// Unconditionally remove existing binary to ensure a clean install
|
|
312
450
|
if (fs.existsSync(tribeDest)) {
|
|
451
|
+
spinner.text = 'Removing existing TRIBE CLI installation...';
|
|
452
|
+
fs.unlinkSync(tribeDest);
|
|
453
|
+
log.success('Removed existing TRIBE CLI');
|
|
454
|
+
spinner.text = 'Installing TRIBE CLI...'; // Reset spinner text
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Also remove old location if exists
|
|
458
|
+
const oldTribeDest = path.join(binDir, 'tribe');
|
|
459
|
+
if (fs.existsSync(oldTribeDest)) {
|
|
313
460
|
try {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// Binary exists but doesn't work, remove it
|
|
319
|
-
fs.unlinkSync(tribeDest);
|
|
461
|
+
fs.unlinkSync(oldTribeDest);
|
|
462
|
+
log.info('Removed old tribe binary from ~/bin');
|
|
463
|
+
} catch (e) {
|
|
464
|
+
// Ignore errors
|
|
320
465
|
}
|
|
321
466
|
}
|
|
322
467
|
|
|
@@ -584,114 +729,11 @@ async function startContainerRuntime() {
|
|
|
584
729
|
}
|
|
585
730
|
}
|
|
586
731
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
const rcFile = shell.includes('zsh') ? '.zshrc' : '.bashrc';
|
|
590
|
-
const rcPath = path.join(homeDir, rcFile);
|
|
591
|
-
|
|
592
|
-
const pathExport = `export PATH="${binDir}:$PATH"`;
|
|
593
|
-
|
|
594
|
-
try {
|
|
595
|
-
const rcContent = fs.existsSync(rcPath) ? fs.readFileSync(rcPath, 'utf8') : '';
|
|
596
|
-
if (!rcContent.includes(pathExport)) {
|
|
597
|
-
fs.appendFileSync(rcPath, `\n# Added by TRIBE CLI installer\n${pathExport}\n`);
|
|
598
|
-
log.success(`Updated ${rcFile} with PATH`);
|
|
599
|
-
}
|
|
600
|
-
} catch (error) {
|
|
601
|
-
log.warning(`Failed to update ${rcFile}: ${error.message}`);
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// Update current process PATH
|
|
605
|
-
process.env.PATH = `${binDir}:${process.env.PATH}`;
|
|
606
|
-
}
|
|
732
|
+
// PATH updates no longer needed - using npm global installation
|
|
733
|
+
// async function updatePath() { ... }
|
|
607
734
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
const pathExport = `export PATH="$HOME/bin:$PATH"`;
|
|
611
|
-
|
|
612
|
-
// Get current shell
|
|
613
|
-
const currentShell = process.env.SHELL || '/bin/sh';
|
|
614
|
-
const shellName = path.basename(currentShell);
|
|
615
|
-
|
|
616
|
-
// Platform-specific shell config files
|
|
617
|
-
const shellConfigs = {
|
|
618
|
-
'zsh': ['.zshrc'],
|
|
619
|
-
'bash': ['.bashrc', '.bash_profile'],
|
|
620
|
-
'sh': ['.profile'],
|
|
621
|
-
'fish': ['.config/fish/config.fish'],
|
|
622
|
-
'ksh': ['.kshrc'],
|
|
623
|
-
'tcsh': ['.tcshrc', '.cshrc']
|
|
624
|
-
};
|
|
625
|
-
|
|
626
|
-
// On Linux, also update .profile for login shells
|
|
627
|
-
if (platform === 'linux') {
|
|
628
|
-
shellConfigs['bash'].push('.profile');
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// Get config files for current shell
|
|
632
|
-
const configFiles = shellConfigs[shellName] || ['.profile'];
|
|
633
|
-
|
|
634
|
-
let updated = false;
|
|
635
|
-
|
|
636
|
-
for (const configFile of configFiles) {
|
|
637
|
-
const configPath = path.join(homeDir, configFile);
|
|
638
|
-
|
|
639
|
-
try {
|
|
640
|
-
// Create config file if it doesn't exist
|
|
641
|
-
if (!fs.existsSync(configPath)) {
|
|
642
|
-
// Handle fish shell special syntax
|
|
643
|
-
if (configFile.includes('fish')) {
|
|
644
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
645
|
-
fs.writeFileSync(configPath, `# Created by TRIBE installer\nset -gx PATH $HOME/bin $PATH\n`);
|
|
646
|
-
} else {
|
|
647
|
-
fs.writeFileSync(configPath, `# Created by TRIBE installer\n${pathExport}\n`);
|
|
648
|
-
}
|
|
649
|
-
updated = true;
|
|
650
|
-
continue;
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
// Check if PATH is already configured
|
|
654
|
-
const content = fs.readFileSync(configPath, 'utf8');
|
|
655
|
-
if (content.includes('$HOME/bin') || content.includes('~/bin')) {
|
|
656
|
-
continue; // Already configured
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
// Add PATH export
|
|
660
|
-
if (configFile.includes('fish')) {
|
|
661
|
-
fs.appendFileSync(configPath, `\n# Added by TRIBE installer\nset -gx PATH $HOME/bin $PATH\n`);
|
|
662
|
-
} else {
|
|
663
|
-
fs.appendFileSync(configPath, `\n# Added by TRIBE installer\n${pathExport}\n`);
|
|
664
|
-
}
|
|
665
|
-
updated = true;
|
|
666
|
-
} catch (error) {
|
|
667
|
-
log.warning(`Could not update ${configFile}: ${error.message}`);
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
if (updated) {
|
|
672
|
-
log.success(`Updated shell configuration`);
|
|
673
|
-
|
|
674
|
-
// Linux-specific: also update /etc/environment if we have permission
|
|
675
|
-
if (platform === 'linux' && process.getuid && process.getuid() === 0) {
|
|
676
|
-
try {
|
|
677
|
-
const envPath = '/etc/environment';
|
|
678
|
-
if (fs.existsSync(envPath)) {
|
|
679
|
-
const envContent = fs.readFileSync(envPath, 'utf8');
|
|
680
|
-
if (!envContent.includes('/usr/local/bin')) {
|
|
681
|
-
// Update system PATH
|
|
682
|
-
const newPath = envContent.replace(/PATH="([^"]*)"/, 'PATH="/usr/local/bin:$1"');
|
|
683
|
-
fs.writeFileSync(envPath, newPath);
|
|
684
|
-
log.success('Updated system PATH in /etc/environment');
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
} catch (error) {
|
|
688
|
-
// Ignore permission errors
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
log.info(`Run "source ~/${configFiles[0]}" or restart your terminal`);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
735
|
+
// Shell config updates no longer needed - using npm global installation
|
|
736
|
+
// async function updateShellConfig() { ... }
|
|
695
737
|
|
|
696
738
|
async function verifyInstallation() {
|
|
697
739
|
const spinner = ora('Verifying installation...').start();
|
|
@@ -902,7 +944,7 @@ async function deployTribeCluster() {
|
|
|
902
944
|
|
|
903
945
|
// Run tribe start command with deployment YAML path
|
|
904
946
|
spinner.text = 'Running TRIBE cluster deployment...';
|
|
905
|
-
const tribePath = path.join(
|
|
947
|
+
const tribePath = path.join(tribeBinDir, 'tribe');
|
|
906
948
|
|
|
907
949
|
// Set environment variable for the deployment YAML location
|
|
908
950
|
const env = {
|
|
@@ -1097,6 +1139,111 @@ async function cleanupOldInstallations() {
|
|
|
1097
1139
|
});
|
|
1098
1140
|
}
|
|
1099
1141
|
|
|
1142
|
+
async function forceCleanInstallation() {
|
|
1143
|
+
console.log(chalk.yellow('\n🧹 Performing force clean installation...\n'));
|
|
1144
|
+
|
|
1145
|
+
// Uninstall global npm package if exists
|
|
1146
|
+
try {
|
|
1147
|
+
execSync('npm uninstall -g tribe-cli-global', {
|
|
1148
|
+
stdio: 'ignore'
|
|
1149
|
+
});
|
|
1150
|
+
log.success('Removed global tribe command');
|
|
1151
|
+
} catch (error) {
|
|
1152
|
+
// It might not be installed, which is fine
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
// List of binaries to remove from ~/bin
|
|
1156
|
+
const binariesToRemove = ['tribe', 'kubectl', 'colima'];
|
|
1157
|
+
|
|
1158
|
+
for (const binary of binariesToRemove) {
|
|
1159
|
+
const binaryPath = path.join(binDir, binary);
|
|
1160
|
+
if (fs.existsSync(binaryPath)) {
|
|
1161
|
+
try {
|
|
1162
|
+
fs.unlinkSync(binaryPath);
|
|
1163
|
+
log.success(`Removed existing ${binary} binary from ~/bin`);
|
|
1164
|
+
} catch (error) {
|
|
1165
|
+
log.warning(`Could not remove ${binary}: ${error.message}`);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// Also clean from .tribe/bin
|
|
1171
|
+
const tribeBinariesToRemove = ['tribe'];
|
|
1172
|
+
for (const binary of tribeBinariesToRemove) {
|
|
1173
|
+
const binaryPath = path.join(tribeBinDir, binary);
|
|
1174
|
+
if (fs.existsSync(binaryPath)) {
|
|
1175
|
+
try {
|
|
1176
|
+
fs.unlinkSync(binaryPath);
|
|
1177
|
+
log.success(`Removed existing ${binary} binary from ~/.tribe/bin`);
|
|
1178
|
+
} catch (error) {
|
|
1179
|
+
log.warning(`Could not remove ${binary}: ${error.message}`);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
// Clean up TRIBE configuration directory
|
|
1185
|
+
if (fs.existsSync(tribeDir)) {
|
|
1186
|
+
try {
|
|
1187
|
+
// Keep important configs but remove deployment markers
|
|
1188
|
+
const deploymentMarker = path.join(tribeDir, '.cluster-deployed');
|
|
1189
|
+
if (fs.existsSync(deploymentMarker)) {
|
|
1190
|
+
fs.unlinkSync(deploymentMarker);
|
|
1191
|
+
log.success('Removed cluster deployment marker');
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
// Remove cached deployment YAML
|
|
1195
|
+
const deploymentYaml = path.join(tribeDir, 'tribe-deployment.yaml');
|
|
1196
|
+
if (fs.existsSync(deploymentYaml)) {
|
|
1197
|
+
fs.unlinkSync(deploymentYaml);
|
|
1198
|
+
log.success('Removed cached deployment configuration');
|
|
1199
|
+
}
|
|
1200
|
+
} catch (error) {
|
|
1201
|
+
log.warning(`Could not clean TRIBE directory: ${error.message}`);
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// Clean up npm cache for @_xtribe/cli
|
|
1206
|
+
try {
|
|
1207
|
+
execSync('npm cache clean --force @_xtribe/cli', {
|
|
1208
|
+
stdio: 'ignore',
|
|
1209
|
+
timeout: 10000
|
|
1210
|
+
});
|
|
1211
|
+
log.success('Cleared npm cache for @_xtribe/cli');
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
// npm cache clean might fail, but that's okay
|
|
1214
|
+
log.info('npm cache clean attempted (may have failed, which is okay)');
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
// Platform-specific cleanup
|
|
1218
|
+
if (platform === 'darwin') {
|
|
1219
|
+
// Check if Colima is running and stop it
|
|
1220
|
+
try {
|
|
1221
|
+
const colimaPath = await findCommand('colima');
|
|
1222
|
+
if (colimaPath) {
|
|
1223
|
+
const status = execSync(`${colimaPath} status 2>&1`, { encoding: 'utf8' });
|
|
1224
|
+
if (status.includes('is running')) {
|
|
1225
|
+
log.info('Stopping Colima...');
|
|
1226
|
+
execSync(`${colimaPath} stop`, { stdio: 'ignore', timeout: 30000 });
|
|
1227
|
+
log.success('Stopped Colima');
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
} catch (error) {
|
|
1231
|
+
// Colima might not be installed or running
|
|
1232
|
+
}
|
|
1233
|
+
} else if (platform === 'linux') {
|
|
1234
|
+
// Note about K3s - requires manual uninstall
|
|
1235
|
+
try {
|
|
1236
|
+
execSync('which k3s', { stdio: 'ignore' });
|
|
1237
|
+
log.warning('K3s detected. To fully remove K3s, run: /usr/local/bin/k3s-uninstall.sh');
|
|
1238
|
+
log.info('The installer will proceed, but K3s will remain installed');
|
|
1239
|
+
} catch {
|
|
1240
|
+
// K3s not installed
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
console.log(chalk.green('\n✓ Clean installation preparation complete\n'));
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1100
1247
|
async function main() {
|
|
1101
1248
|
console.log(chalk.bold.blue('\n🚀 TRIBE CLI Complete Installer\n'));
|
|
1102
1249
|
|
|
@@ -1168,13 +1315,9 @@ async function main() {
|
|
|
1168
1315
|
await cleanupOldInstallations();
|
|
1169
1316
|
|
|
1170
1317
|
log.info(`Detected: ${platform} (${arch})`);
|
|
1171
|
-
log.info(`Installing to: ${
|
|
1172
|
-
|
|
1173
|
-
// Update PATH first
|
|
1174
|
-
await updatePath();
|
|
1318
|
+
log.info(`Installing to: ${tribeBinDir}`);
|
|
1175
1319
|
|
|
1176
|
-
//
|
|
1177
|
-
await updateShellConfig();
|
|
1320
|
+
// No longer updating PATH - will use npm global install instead
|
|
1178
1321
|
|
|
1179
1322
|
const tasks = [];
|
|
1180
1323
|
|
|
@@ -1188,7 +1331,8 @@ async function main() {
|
|
|
1188
1331
|
// Common tools for all platforms
|
|
1189
1332
|
tasks.push(
|
|
1190
1333
|
{ name: 'kubectl', fn: installKubectl },
|
|
1191
|
-
{ name: 'TRIBE CLI', fn: installTribeCLI }
|
|
1334
|
+
{ name: 'TRIBE CLI', fn: installTribeCLI },
|
|
1335
|
+
{ name: 'Global tribe command', fn: setupGlobalNpmCommand }
|
|
1192
1336
|
);
|
|
1193
1337
|
|
|
1194
1338
|
let allSuccess = true;
|
|
@@ -1235,19 +1379,16 @@ async function main() {
|
|
|
1235
1379
|
console.log('');
|
|
1236
1380
|
|
|
1237
1381
|
// Provide immediate access to tribe command
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
log.
|
|
1241
|
-
console.log(chalk.
|
|
1242
|
-
console.log(chalk.yellow(` source ~/.${process.env.SHELL?.includes('zsh') ? 'zshrc' : 'bashrc'} # Or update PATH`));
|
|
1243
|
-
console.log(chalk.cyan(` alias tribe="${tribePath}" # Or create temporary alias`));
|
|
1244
|
-
console.log(' ' + chalk.gray('or restart your terminal'));
|
|
1382
|
+
log.info('TRIBE command is now available globally!');
|
|
1383
|
+
console.log(chalk.green(' tribe # Run from anywhere'));
|
|
1384
|
+
console.log(chalk.gray(' tribe --help # View available commands'));
|
|
1385
|
+
console.log(chalk.gray(' tribe status # Check cluster status'));
|
|
1245
1386
|
console.log('');
|
|
1246
1387
|
|
|
1247
1388
|
log.info('Quick start:');
|
|
1248
|
-
console.log(
|
|
1249
|
-
console.log(
|
|
1250
|
-
console.log(
|
|
1389
|
+
console.log(' tribe # Launch interactive CLI');
|
|
1390
|
+
console.log(' tribe status # Check cluster status');
|
|
1391
|
+
console.log(' tribe create-task # Create a new task');
|
|
1251
1392
|
console.log('');
|
|
1252
1393
|
log.info('First time? The CLI will guide you through creating your first project!');
|
|
1253
1394
|
} else {
|
|
@@ -1265,19 +1406,14 @@ async function main() {
|
|
|
1265
1406
|
console.log('');
|
|
1266
1407
|
|
|
1267
1408
|
// Provide immediate access to tribe command
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
log.info('To use tribe commands:');
|
|
1271
|
-
console.log(chalk.green(` ${tribePath} # Use full path now`));
|
|
1272
|
-
console.log(chalk.yellow(` source ~/.${process.env.SHELL?.includes('zsh') ? 'zshrc' : 'bashrc'} # Or update PATH`));
|
|
1273
|
-
console.log(chalk.cyan(` alias tribe="${tribePath}" # Or create temporary alias`));
|
|
1274
|
-
console.log(' ' + chalk.gray('or restart your terminal'));
|
|
1409
|
+
log.info('TRIBE command is now available globally!');
|
|
1410
|
+
console.log(chalk.green(' tribe # Run from anywhere'));
|
|
1275
1411
|
console.log('');
|
|
1276
1412
|
|
|
1277
1413
|
log.info('Commands:');
|
|
1278
|
-
console.log(
|
|
1279
|
-
console.log(
|
|
1280
|
-
console.log(
|
|
1414
|
+
console.log(' tribe # Launch interactive CLI');
|
|
1415
|
+
console.log(' tribe status # Check status');
|
|
1416
|
+
console.log(' tribe create-task # Create a new task');
|
|
1281
1417
|
}
|
|
1282
1418
|
} else {
|
|
1283
1419
|
console.log('\n' + chalk.bold('Next Steps:'));
|
|
@@ -1332,6 +1468,7 @@ if (require.main === module) {
|
|
|
1332
1468
|
console.log(' --verify Only verify existing installation');
|
|
1333
1469
|
console.log(' --dry-run Show what would be installed');
|
|
1334
1470
|
console.log(' --skip-cluster Skip cluster deployment (for testing)');
|
|
1471
|
+
console.log(' --force Force clean installation (removes existing installations)');
|
|
1335
1472
|
console.log('\nThis installer sets up the complete TRIBE development environment:');
|
|
1336
1473
|
|
|
1337
1474
|
if (platform === 'darwin') {
|
|
@@ -1374,10 +1511,23 @@ if (require.main === module) {
|
|
|
1374
1511
|
// Store skip-cluster flag
|
|
1375
1512
|
global.skipCluster = args.includes('--skip-cluster');
|
|
1376
1513
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1514
|
+
// Check for force flag
|
|
1515
|
+
if (args.includes('--force')) {
|
|
1516
|
+
forceCleanInstallation().then(() => {
|
|
1517
|
+
main().catch(error => {
|
|
1518
|
+
console.error(chalk.red('Installation failed:'), error.message);
|
|
1519
|
+
process.exit(1);
|
|
1520
|
+
});
|
|
1521
|
+
}).catch(error => {
|
|
1522
|
+
console.error(chalk.red('Force clean failed:'), error.message);
|
|
1523
|
+
process.exit(1);
|
|
1524
|
+
});
|
|
1525
|
+
} else {
|
|
1526
|
+
main().catch(error => {
|
|
1527
|
+
console.error(chalk.red('Installation failed:'), error.message);
|
|
1528
|
+
process.exit(1);
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1381
1531
|
}
|
|
1382
1532
|
|
|
1383
1533
|
module.exports = { main };
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@_xtribe/cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.26",
|
|
4
4
|
"description": "TRIBE multi-agent development system - Zero to productive with one command",
|
|
5
5
|
"main": "install-tribe.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"tribe": "install-tribe.js"
|
|
8
|
-
},
|
|
9
6
|
"scripts": {
|
|
10
7
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
8
|
},
|