@_xtribe/cli 1.0.19 → 1.0.20

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.
Files changed (2) hide show
  1. package/install-tribe.js +142 -33
  2. package/package.json +1 -1
package/install-tribe.js CHANGED
@@ -821,16 +821,107 @@ async function startContainerRuntime() {
821
821
  // Colima not running, need to start it
822
822
  }
823
823
 
824
- // Don't try to start Colima automatically - it takes too long
824
+ // Start Colima automatically
825
825
  if (await checkCommand('colima')) {
826
- spinner.stop(); // Stop the spinner before showing info
827
- console.log('');
828
- console.log(chalk.yellow(' ⚠️ Colima needs to be started before using TRIBE'));
829
- console.log(chalk.gray(' To start Colima with Kubernetes:'));
830
- console.log(chalk.cyan(' colima start --kubernetes'));
831
- console.log(chalk.gray(' This may take 2-5 minutes on first run'));
832
- console.log('');
833
- return true; // Return true since it's installed
826
+ spinner.text = 'Starting Colima with Kubernetes (this may take a few minutes on first run)...';
827
+
828
+ // Start Colima in the background
829
+ const { spawn } = require('child_process');
830
+ const colimaProcess = spawn('colima', ['start', '--kubernetes'], {
831
+ stdio: ['ignore', 'pipe', 'pipe'],
832
+ detached: false
833
+ });
834
+
835
+ let output = '';
836
+ let errorOutput = '';
837
+ let startupComplete = false;
838
+
839
+ // Monitor output
840
+ colimaProcess.stdout.on('data', (data) => {
841
+ output += data.toString();
842
+ // Update spinner with progress
843
+ const lines = data.toString().split('\n').filter(line => line.trim());
844
+ for (const line of lines) {
845
+ if (line.includes('starting ...')) {
846
+ const contextMatch = line.match(/context=(\w+)/);
847
+ if (contextMatch) {
848
+ spinner.text = `Starting Colima: ${contextMatch[1]}...`;
849
+ }
850
+ } else if (line.includes('provisioning ...')) {
851
+ const contextMatch = line.match(/context=(\w+)/);
852
+ if (contextMatch) {
853
+ spinner.text = `Provisioning ${contextMatch[1]}...`;
854
+ }
855
+ } else if (line.includes('done')) {
856
+ startupComplete = true;
857
+ }
858
+ }
859
+ });
860
+
861
+ colimaProcess.stderr.on('data', (data) => {
862
+ errorOutput += data.toString();
863
+ // Colima outputs progress to stderr, not stdout
864
+ const lines = data.toString().split('\n').filter(line => line.trim());
865
+ for (const line of lines) {
866
+ if (line.includes('starting ...')) {
867
+ const contextMatch = line.match(/context=(\w+)/);
868
+ if (contextMatch) {
869
+ spinner.text = `Starting Colima: ${contextMatch[1]}...`;
870
+ }
871
+ } else if (line.includes('provisioning ...')) {
872
+ const contextMatch = line.match(/context=(\w+)/);
873
+ if (contextMatch) {
874
+ spinner.text = `Provisioning ${contextMatch[1]}...`;
875
+ }
876
+ } else if (line.includes('done')) {
877
+ startupComplete = true;
878
+ }
879
+ }
880
+ });
881
+
882
+ // Wait for process to complete
883
+ const exitCode = await new Promise((resolve) => {
884
+ colimaProcess.on('exit', (code) => {
885
+ resolve(code);
886
+ });
887
+ });
888
+
889
+ if (exitCode === 0 && startupComplete) {
890
+ // Verify Colima is actually running
891
+ try {
892
+ execSync('colima status', { stdio: 'ignore' });
893
+ spinner.succeed('Colima started with Kubernetes');
894
+
895
+ // Give k3s a moment to initialize
896
+ spinner.text = 'Waiting for Kubernetes to initialize...';
897
+ await new Promise(resolve => setTimeout(resolve, 5000));
898
+
899
+ return true;
900
+ } catch {
901
+ spinner.fail('Colima started but is not responding');
902
+ return false;
903
+ }
904
+ } else {
905
+ spinner.fail('Failed to start Colima');
906
+ // Only show actual error messages, not progress
907
+ const actualErrors = errorOutput.split('\n')
908
+ .filter(line => line.trim() &&
909
+ !line.includes('level=info') &&
910
+ !line.includes('starting ...') &&
911
+ !line.includes('provisioning ...') &&
912
+ !line.includes('done'))
913
+ .join('\n');
914
+
915
+ if (actualErrors.trim()) {
916
+ console.log(chalk.red('Error output:'));
917
+ console.log(actualErrors);
918
+ }
919
+ console.log('');
920
+ console.log(chalk.yellow(' Please start Colima manually:'));
921
+ console.log(chalk.cyan(' colima start --kubernetes'));
922
+ console.log('');
923
+ return false;
924
+ }
834
925
  } else {
835
926
  spinner.warn('Colima not found');
836
927
  return false;
@@ -956,9 +1047,28 @@ async function verifyInstallation() {
956
1047
 
957
1048
  async function checkClusterExists() {
958
1049
  try {
959
- // Check if TRIBE namespace exists in any context
1050
+ // Check if TRIBE namespace exists
960
1051
  execSync('kubectl get namespace tribe-system', { stdio: 'ignore' });
961
- return true;
1052
+
1053
+ // Also check if key TRIBE pods are running
1054
+ const podsOutput = execSync('kubectl get pods -n tribe-system -o json', {
1055
+ encoding: 'utf8',
1056
+ stdio: 'pipe'
1057
+ });
1058
+
1059
+ const pods = JSON.parse(podsOutput);
1060
+ if (!pods.items || pods.items.length === 0) {
1061
+ return false; // Namespace exists but no pods
1062
+ }
1063
+
1064
+ // Check if essential pods exist (gitea, postgres, taskmaster)
1065
+ const essentialPods = ['gitea', 'postgres', 'taskmaster'];
1066
+ const runningPods = pods.items.filter(pod => {
1067
+ const podName = pod.metadata.name;
1068
+ return essentialPods.some(essential => podName.includes(essential));
1069
+ });
1070
+
1071
+ return runningPods.length >= essentialPods.length;
962
1072
  } catch {
963
1073
  return false;
964
1074
  }
@@ -1320,6 +1430,17 @@ async function cleanupOldInstallations() {
1320
1430
  async function forceCleanInstallation() {
1321
1431
  console.log(chalk.yellow('\n🧹 Performing force clean installation...\n'));
1322
1432
 
1433
+ // Clean up Kubernetes resources first (while cluster is running)
1434
+ try {
1435
+ execSync('kubectl delete namespace tribe-system --ignore-not-found=true', {
1436
+ stdio: 'ignore',
1437
+ timeout: 30000
1438
+ });
1439
+ log.success('Removed TRIBE namespace from cluster');
1440
+ } catch (error) {
1441
+ // Cluster might not be running or namespace doesn't exist
1442
+ }
1443
+
1323
1444
  // Uninstall global npm package if exists
1324
1445
  try {
1325
1446
  execSync('npm uninstall -g tribe-cli-global', {
@@ -1531,21 +1652,23 @@ async function main() {
1531
1652
  const verified = await verifyInstallation();
1532
1653
 
1533
1654
  // Try to start container runtime (after showing results)
1534
- await startContainerRuntime();
1655
+ const runtimeStarted = await startContainerRuntime();
1535
1656
 
1536
- if (verified) {
1657
+ // If we successfully started the runtime, we should continue with deployment
1658
+ if (verified || runtimeStarted) {
1537
1659
  // Check if cluster already exists
1538
1660
  const clusterExists = await checkClusterExists();
1539
1661
 
1540
1662
  if (!clusterExists && !global.skipCluster) {
1541
- // Prompt for cluster setup
1542
- const shouldSetup = await promptForClusterSetup();
1663
+ // If we just started Colima, automatically deploy the cluster
1664
+ // Don't prompt if we just started the runtime - deploy automatically
1665
+ const shouldSetup = runtimeStarted ? true : await promptForClusterSetup();
1543
1666
 
1544
1667
  if (shouldSetup) {
1545
1668
  console.log('');
1546
1669
 
1547
- // Start Colima with Kubernetes if on macOS
1548
- if (platform === 'darwin') {
1670
+ // Start Colima with Kubernetes if on macOS (skip if we just started it)
1671
+ if (platform === 'darwin' && !runtimeStarted) {
1549
1672
  const colimaStarted = await startColimaWithKubernetes();
1550
1673
  if (!colimaStarted) {
1551
1674
  log.error('Failed to start Colima. Please run manually:');
@@ -1562,22 +1685,8 @@ async function main() {
1562
1685
  console.log('\n' + chalk.bold.green('✨ TRIBE is ready!'));
1563
1686
  console.log('');
1564
1687
 
1565
- // Offer to set up PATH
1566
- if (global.envScriptCreated && !process.env.CI && !process.env.TRIBE_SKIP_PATH_PROMPT) {
1567
- const shouldSetupPath = await promptForPathSetup();
1568
- if (shouldSetupPath) {
1569
- // Run the setup-path logic inline
1570
- try {
1571
- const setupPath = require('./setup-path.js');
1572
- setupPath();
1573
- console.log('');
1574
- // PATH is now set up, update instructions
1575
- global.pathSetupComplete = true;
1576
- } catch (error) {
1577
- log.warning('Could not automatically set up PATH');
1578
- }
1579
- }
1580
- }
1688
+ // PATH was already set up automatically in setupPathEnvironment
1689
+ // No need to prompt again
1581
1690
 
1582
1691
  // Provide immediate access to tribe command
1583
1692
  if (global.pathSetupComplete) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_xtribe/cli",
3
- "version": "1.0.19",
3
+ "version": "1.0.20",
4
4
  "description": "TRIBE multi-agent development system - Zero to productive with one command",
5
5
  "main": "install-tribe.js",
6
6
  "bin": {