@_xtribe/cli 2.0.3 → 2.0.4

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 CHANGED
@@ -639,13 +639,30 @@ async function installTribeCLI() {
639
639
  // Multiple sources for reliability
640
640
  // For testing, use a direct URL to our releases folder
641
641
  const isTestEnv = process.env.TRIBE_TEST_BINARY_URL;
642
+ const testBinary = process.env.TRIBE_TEST_BINARY;
642
643
  const githubRepo = process.env.TRIBE_INSTALLER_REPO || 'TRIBE-INC/releases';
643
644
 
645
+ // If we have a test binary file, use it directly
646
+ if (testBinary && fs.existsSync(testBinary)) {
647
+ spinner.text = 'Using test binary...';
648
+ fs.copyFileSync(testBinary, tribeDest);
649
+ fs.chmodSync(tribeDest, '755');
650
+ spinner.succeed('✓ TRIBE CLI installed from test binary');
651
+ return true;
652
+ }
653
+
644
654
  let downloadUrl = '';
645
655
 
646
656
  try {
647
- spinner.text = 'Fetching latest release information from GitHub...';
648
- const response = await fetch(`https://api.github.com/repos/${githubRepo}/releases`);
657
+ const versionChannel = global.versionChannel || 'latest';
658
+ spinner.text = `Fetching ${versionChannel} release information from GitHub...`;
659
+ const response = await fetch(`https://api.github.com/repos/${githubRepo}/releases`, {
660
+ headers: {
661
+ 'User-Agent': 'TRIBE-Installer',
662
+ // Add token if available in environment
663
+ ...(process.env.GITHUB_TOKEN ? { 'Authorization': `token ${process.env.GITHUB_TOKEN}` } : {})
664
+ }
665
+ });
649
666
  if (!response.ok) {
650
667
  throw new Error(`GitHub API returned ${response.status}`);
651
668
  }
@@ -653,23 +670,75 @@ async function installTribeCLI() {
653
670
  if (!releases || releases.length === 0) {
654
671
  throw new Error('No releases found');
655
672
  }
656
- const latestRelease = releases[0];
673
+
674
+ // Filter releases based on version channel
675
+ let filteredReleases = releases.filter(r => !r.draft);
676
+
677
+ if (versionChannel === 'beta') {
678
+ // For beta, look for releases with 'beta' in tag name
679
+ filteredReleases = filteredReleases.filter(r => r.tag_name.includes('beta'));
680
+ spinner.text = 'Looking for beta releases...';
681
+ } else if (versionChannel === 'latest') {
682
+ // For latest, exclude beta releases
683
+ filteredReleases = filteredReleases.filter(r => !r.tag_name.includes('beta'));
684
+ spinner.text = 'Looking for stable releases...';
685
+ } else {
686
+ // For specific version, look for exact match
687
+ filteredReleases = filteredReleases.filter(r => r.tag_name === versionChannel);
688
+ spinner.text = `Looking for version ${versionChannel}...`;
689
+ }
690
+
691
+ if (filteredReleases.length === 0) {
692
+ throw new Error(`No releases found for channel: ${versionChannel}`);
693
+ }
694
+
695
+ // Find a release with the binary we need
696
+ let foundRelease = null;
657
697
  const assetName = `tribe-${platform}-${arch}`;
658
- const asset = latestRelease.assets.find(a => a.name === assetName);
659
-
660
- if (!asset) {
661
- throw new Error(`No binary found for ${platform}-${arch} in release ${latestRelease.tag_name}`);
698
+
699
+ for (const release of filteredReleases) {
700
+ const asset = release.assets?.find(a => a.name === assetName || a.name === `${assetName}.exe`);
701
+ if (asset) {
702
+ foundRelease = release;
703
+ downloadUrl = asset.browser_download_url;
704
+ spinner.text = `Found binary in ${versionChannel} release: ${release.tag_name}`;
705
+ break;
706
+ }
707
+ }
708
+
709
+ if (!foundRelease) {
710
+ // No release has the binary, try constructing URL from first filtered release
711
+ const firstRelease = filteredReleases[0];
712
+ if (firstRelease) {
713
+ downloadUrl = `https://github.com/${githubRepo}/releases/download/${firstRelease.tag_name}/tribe-${platform}-${arch}`;
714
+ spinner.text = `Trying ${versionChannel} release: ${firstRelease.tag_name}`;
715
+ } else {
716
+ throw new Error(`No suitable release found for channel: ${versionChannel}`);
717
+ }
662
718
  }
663
-
664
- downloadUrl = asset.browser_download_url;
665
- spinner.text = `Found latest release: ${latestRelease.tag_name}`;
666
719
  } catch (error) {
667
- spinner.fail(`Failed to get release info: ${error.message}`);
668
- // Fallback to other methods if the API fails
720
+ log.warning(`Failed to get release info: ${error.message}`);
721
+ // Try to get the latest release tag directly
722
+ try {
723
+ const tagResponse = await fetch(`https://api.github.com/repos/${githubRepo}/releases`, {
724
+ headers: { 'User-Agent': 'TRIBE-Installer' }
725
+ });
726
+ if (tagResponse.ok) {
727
+ const releases = await tagResponse.json();
728
+ if (releases && releases.length > 0) {
729
+ const tag = releases[0].tag_name;
730
+ // Construct direct download URL
731
+ downloadUrl = `https://github.com/${githubRepo}/releases/download/${tag}/tribe-${platform}-${arch}`;
732
+ spinner.text = `Using direct download for release: ${tag}`;
733
+ }
734
+ }
735
+ } catch (e) {
736
+ // Ignore and use fallback URLs
737
+ }
669
738
  }
670
739
 
671
- // Check if there's a local build available
672
- const localBuildPath = path.join(__dirname, '..', '..', '..', 'sdk', 'cmd', 'cli-gui', 'tribe');
740
+ // Check if there's a local build available (use tribe-new, not cli-gui)
741
+ const localBuildPath = path.join(__dirname, '..', '..', '..', 'sdk', 'cmd', 'tribe-new', 'tribe');
673
742
  const hasLocalBuild = fs.existsSync(localBuildPath);
674
743
 
675
744
  const sources = isTestEnv ? [isTestEnv] : [
@@ -993,6 +1062,9 @@ async function verifyInstallation() {
993
1062
  results[tool] = await checkCommand(tool);
994
1063
  }
995
1064
 
1065
+ // Store results globally for later use
1066
+ global.installationChecks = results;
1067
+
996
1068
  // Special check for container runtime
997
1069
  let containerWorking = false;
998
1070
  if (platform === 'darwin') {
@@ -1523,6 +1595,17 @@ async function forceCleanInstallation() {
1523
1595
  log.info('npm cache clean attempted (may have failed, which is okay)');
1524
1596
  }
1525
1597
 
1598
+ // Remove first-install marker to allow auto-launch
1599
+ const firstInstallMarker = path.join(tribeDir, '.first-install-complete');
1600
+ if (fs.existsSync(firstInstallMarker)) {
1601
+ try {
1602
+ fs.unlinkSync(firstInstallMarker);
1603
+ log.success('Removed first-install marker');
1604
+ } catch (error) {
1605
+ log.warning(`Could not remove first-install marker: ${error.message}`);
1606
+ }
1607
+ }
1608
+
1526
1609
  // Platform-specific cleanup
1527
1610
  if (platform === 'darwin') {
1528
1611
  // Check if Colima is running and stop it
@@ -1554,29 +1637,12 @@ async function forceCleanInstallation() {
1554
1637
  }
1555
1638
 
1556
1639
  async function main() {
1557
- // Fire-themed ASCII art with modern Unicode design
1558
- console.log('');
1559
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` ░▒▓`) + chalk.red(` `) + chalk.yellow(` ▓▒░ `) + chalk.red(`░▒▓█▓▒░`));
1560
- console.log(chalk.red(` ░▒▓█████▓▒░ ░▒▓█████▓▒░`) + chalk.yellow(` ░▒▓██`) + chalk.red(` `) + chalk.yellow(` ▓██▓▒░ `) + chalk.red(`░▒▓█████▓▒░`));
1561
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░`) + chalk.yellow(`░▒▓██`) + chalk.red(` `) + chalk.yellow(`▓██▓▒░ `) + chalk.red(`░▒▓█▓▒░░▒▓█▓▒░`));
1562
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░`) + chalk.yellow(` ░▒▓██`) + chalk.red(``) + chalk.yellow(`▓██▓▒░ `) + chalk.red(`░▒▓█▓▒░ ░▒▓█▓▒░`));
1563
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` ░▒▓██`) + chalk.red(``) + chalk.yellow(`██▓▒░ `) + chalk.red(`░▒▓█▓▒░ ░▒▓█▓▒░`));
1564
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` ░▒▓`) + chalk.red(`██`) + chalk.yellow(`▓▒░ `) + chalk.red(`░▒▓█▓▒░ ░▒▓█▓▒░`));
1565
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` ░▒`) + chalk.red(`▓`) + chalk.yellow(`▒░ `) + chalk.red(`░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░`));
1566
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` `) + chalk.red(`░`) + chalk.yellow(` `) + chalk.red(`░▒▓█▓▒░ ░▒▓█████▓▒░`));
1567
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` `) + chalk.red(`░▒▓█▓▒░ ░▒▓█▓▒░`));
1568
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░`) + chalk.yellow(` `) + chalk.red(`░▒▓█▓▒░ ░▒▓█▓▒░`));
1569
- console.log(chalk.red(` ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒`) + chalk.red(`▓█▓▒░ ░▒▓█▓▒░`));
1570
- console.log('');
1571
- console.log(chalk.yellow(` ╔═══════════════════════════════════╗`));
1572
- console.log(chalk.yellow(` ║ `) + chalk.white.bold(`Multi-Agent Orchestration System`) + chalk.yellow(` ║`));
1573
- console.log(chalk.yellow(` ╚═══════════════════════════════════╝`));
1574
- console.log('');
1640
+ console.log(chalk.bold.blue('\n🚀 TRIBE CLI Installer\n'));
1575
1641
 
1576
1642
  // Detect and display platform info
1577
1643
  const displayArch = process.arch === 'x64' ? 'amd64' : process.arch;
1578
- console.log(chalk.cyan(`Platform: ${platform} (${displayArch})`));
1579
- console.log(chalk.cyan(`Node: ${process.version}`));
1644
+ console.log(chalk.gray(`Platform: ${platform} (${displayArch})`));
1645
+ console.log(chalk.gray(`Node: ${process.version}`));
1580
1646
  console.log('');
1581
1647
 
1582
1648
  // Check for unsupported platforms early
@@ -1678,6 +1744,16 @@ async function main() {
1678
1744
  // Verify everything first
1679
1745
  const verified = await verifyInstallation();
1680
1746
 
1747
+ // If critical components failed (especially TRIBE CLI), exit with error
1748
+ if (!allSuccess) {
1749
+ // Check specifically if TRIBE CLI installation failed
1750
+ const tribeBinaryExists = fs.existsSync(path.join(tribeBinDir, 'tribe'));
1751
+ if (!tribeBinaryExists) {
1752
+ console.error(chalk.red('\n❌ Installation failed: TRIBE CLI could not be installed'));
1753
+ process.exit(1);
1754
+ }
1755
+ }
1756
+
1681
1757
  // Try to start container runtime (after showing results)
1682
1758
  const runtimeStarted = await startContainerRuntime();
1683
1759
 
@@ -1824,6 +1900,22 @@ async function main() {
1824
1900
  log.info('Then run: tribe start');
1825
1901
  }
1826
1902
 
1903
+ // Auto-launch handling (only for successful installations)
1904
+ const checks = global.installationChecks || {};
1905
+ if (checks.kubectl && checks.tribe) {
1906
+ try {
1907
+ const autoLaunch = require('./install-tribe-autolaunch.js');
1908
+ if (autoLaunch.shouldAutoLaunch()) {
1909
+ console.log(''); // Spacing before auto-launch
1910
+ await autoLaunch.handleAutoLaunch();
1911
+ // If auto-launch takes over, we won't reach here
1912
+ }
1913
+ } catch (error) {
1914
+ // Silently ignore auto-launch errors to not break the installer
1915
+ // Auto-launch is a nice-to-have feature, not critical
1916
+ }
1917
+ }
1918
+
1827
1919
  // Exit cleanly
1828
1920
  process.exit(0);
1829
1921
  }
@@ -1836,15 +1928,43 @@ if (!global.fetch) {
1836
1928
  if (require.main === module) {
1837
1929
  const args = process.argv.slice(2);
1838
1930
 
1931
+ // Parse version/channel flags
1932
+ let versionChannel = 'latest'; // default to latest stable
1933
+ const versionArg = args.find(arg => arg.startsWith('--version='));
1934
+ const channelArg = args.find(arg => arg.startsWith('--channel='));
1935
+
1936
+ if (versionArg) {
1937
+ versionChannel = versionArg.split('=')[1];
1938
+ } else if (channelArg) {
1939
+ versionChannel = channelArg.split('=')[1];
1940
+ } else if (args.includes('--beta')) {
1941
+ versionChannel = 'beta';
1942
+ } else if (args.includes('--latest')) {
1943
+ versionChannel = 'latest';
1944
+ }
1945
+
1946
+ // Store globally for use in download functions
1947
+ global.versionChannel = versionChannel;
1948
+
1839
1949
  if (args.includes('--help') || args.includes('-h')) {
1840
1950
  console.log(chalk.bold.blue('TRIBE CLI Installer\n'));
1841
1951
  console.log('Usage: npx @_xtribe/cli [options]\n');
1842
1952
  console.log('Options:');
1843
- console.log(' --help, -h Show this help message');
1844
- console.log(' --verify Only verify existing installation');
1845
- console.log(' --dry-run Show what would be installed');
1846
- console.log(' --skip-cluster Skip cluster deployment (for testing)');
1847
- console.log(' --force Force clean installation (removes existing installations)');
1953
+ console.log(' --help, -h Show this help message');
1954
+ console.log(' --verify Only verify existing installation');
1955
+ console.log(' --dry-run Show what would be installed');
1956
+ console.log(' --skip-cluster Skip cluster deployment (for testing)');
1957
+ console.log(' --no-start Alias for --skip-cluster (for CI environments)');
1958
+ console.log(' --force Force clean installation (removes existing installations)');
1959
+ console.log(' --latest Install latest stable release (default)');
1960
+ console.log(' --beta Install latest beta release');
1961
+ console.log(' --version=TAG Install specific version tag');
1962
+ console.log(' --channel=CHANNEL Install from specific channel (latest/beta)');
1963
+ console.log('\nVersion Examples:');
1964
+ console.log(' npx @_xtribe/cli@latest # Latest stable (equivalent to --latest)');
1965
+ console.log(' npx @_xtribe/cli@beta # Latest beta');
1966
+ console.log(' npx @_xtribe/cli --beta # Latest beta (flag version)');
1967
+ console.log(' npx @_xtribe/cli --version=v1.2.3 # Specific version');
1848
1968
  console.log('\nThis installer sets up the complete TRIBE development environment:');
1849
1969
 
1850
1970
  if (platform === 'darwin') {
@@ -1877,6 +1997,7 @@ if (require.main === module) {
1877
1997
  console.log(chalk.bold.blue('🔍 TRIBE CLI Installation Preview\n'));
1878
1998
  log.info(`Platform: ${platform} (${arch})`);
1879
1999
  log.info(`Install directory: ${binDir}`);
2000
+ log.info(`Version channel: ${versionChannel}`);
1880
2001
  console.log('\nWould install:');
1881
2002
  console.log('• Colima - Container runtime with Kubernetes (macOS only)');
1882
2003
  console.log('• kubectl - Kubernetes CLI');
@@ -1884,8 +2005,8 @@ if (require.main === module) {
1884
2005
  process.exit(0);
1885
2006
  }
1886
2007
 
1887
- // Store skip-cluster flag
1888
- global.skipCluster = args.includes('--skip-cluster');
2008
+ // Store skip-cluster flag (--no-start is an alias)
2009
+ global.skipCluster = args.includes('--skip-cluster') || args.includes('--no-start');
1889
2010
 
1890
2011
  // Check for force flag
1891
2012
  if (args.includes('--force')) {
package/install.sh ADDED
@@ -0,0 +1,52 @@
1
+ #!/bin/bash
2
+ # TRIBE Quick Installer
3
+ # This script provides a one-command installation with immediate PATH access
4
+
5
+ # Source constants
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ source "$SCRIPT_DIR/../../../constants.sh" 2>/dev/null || true
8
+
9
+ # If constants not found, define locally
10
+ if [ -z "$TRIBE_INSTALL_COMMAND" ]; then
11
+ TRIBE_INSTALL_COMMAND="npx @_xtribe/cli"
12
+ fi
13
+
14
+ # Colors
15
+ RED='\033[0;31m'
16
+ GREEN='\033[0;32m'
17
+ BLUE='\033[0;34m'
18
+ YELLOW='\033[1;33m'
19
+ NC='\033[0m' # No Color
20
+
21
+ echo -e "${BLUE}🚀 TRIBE Quick Installer${NC}"
22
+ echo ""
23
+
24
+ # Download and run the installer
25
+ echo "Installing TRIBE components..."
26
+ ${TRIBE_INSTALL_COMMAND}@latest "$@"
27
+
28
+ # Check if installation was successful
29
+ if [ -f ~/.tribe/tribe-env.sh ]; then
30
+ # Source the environment file
31
+ source ~/.tribe/tribe-env.sh
32
+
33
+ echo ""
34
+ echo -e "${GREEN}✅ Installation complete!${NC}"
35
+ echo -e "${GREEN}✅ PATH configured for this session!${NC}"
36
+ echo ""
37
+
38
+ # Verify tribe is available
39
+ if command -v tribe &> /dev/null; then
40
+ echo -e "${YELLOW}You can now use the 'tribe' command immediately!${NC}"
41
+ echo ""
42
+ echo "Try these commands:"
43
+ echo -e " ${GREEN}tribe${NC} - Launch TRIBE"
44
+ echo -e " ${GREEN}tribe status${NC} - Check cluster status"
45
+ else
46
+ echo -e "${YELLOW}Run this command to use tribe:${NC}"
47
+ echo -e " ${GREEN}source ~/.tribe/tribe-env.sh${NC}"
48
+ fi
49
+ else
50
+ echo -e "${RED}❌ Installation may have failed${NC}"
51
+ exit 1
52
+ fi
package/package.json CHANGED
@@ -1,35 +1,27 @@
1
1
  {
2
2
  "name": "@_xtribe/cli",
3
- "version": "2.0.3",
4
- "description": "Deploy a team of AI agents that write production-ready code. Transform natural language into working software with autonomous Claude-powered developers.",
3
+ "version": "2.0.4",
4
+ "description": "TRIBE multi-agent development system - Zero to productive with one command",
5
5
  "main": "install-tribe.js",
6
6
  "bin": {
7
- "tribe": "install-tribe.js"
7
+ "cli": "./index.js",
8
+ "install-tribe": "./install-tribe.js",
9
+ "setup-path": "./setup-path.js"
8
10
  },
9
11
  "scripts": {
10
12
  "test": "echo \"Error: no test specified\" && exit 1"
11
13
  },
12
14
  "keywords": [
13
- "ai",
14
- "claude",
15
- "anthropic",
16
- "code-generation",
17
- "ai-agents",
18
- "multi-agent",
19
- "autonomous-development",
20
- "ai-developer",
21
- "code-assistant",
22
- "llm",
23
15
  "tribe",
24
16
  "cli",
25
17
  "kubernetes",
26
18
  "docker",
27
19
  "colima",
20
+ "multi-agent",
21
+ "ai",
28
22
  "development",
29
- "automation",
30
- "devtools",
31
- "productivity",
32
- "natural-language-programming"
23
+ "autonomous",
24
+ "agents"
33
25
  ],
34
26
  "engines": {
35
27
  "node": ">=16.0.0"
@@ -44,25 +36,33 @@
44
36
  "registry": "https://registry.npmjs.org/"
45
37
  },
46
38
  "files": [
39
+ "index.js",
47
40
  "install-tribe.js",
41
+ "install-tribe-minimal.js",
42
+ "install-tribe-autolaunch.js",
43
+ "setup-path.js",
44
+ "install.sh",
45
+ "tribe-deployment.yaml",
48
46
  "README.md",
47
+ "AUTOLAUNCH_IMPLEMENTATION.md",
49
48
  "package.json"
50
49
  ],
51
50
  "dependencies": {
51
+ "adm-zip": "^0.5.9",
52
52
  "chalk": "^4.1.2",
53
- "ora": "^5.4.1",
54
53
  "node-fetch": "^2.6.7",
54
+ "ora": "^5.4.1",
55
55
  "tar": "^6.1.15",
56
56
  "which": "^2.0.2"
57
57
  },
58
58
  "repository": {
59
59
  "type": "git",
60
- "url": "git+https://github.com/0zen/0zen.git"
60
+ "url": "git+https://github.com/TRIBE-INC/0zen.git"
61
61
  },
62
- "author": "0zen",
62
+ "author": "TRIBE-INC",
63
63
  "license": "MIT",
64
- "homepage": "https://github.com/0zen/0zen",
64
+ "homepage": "https://github.com/TRIBE-INC/0zen",
65
65
  "bugs": {
66
- "url": "https://github.com/0zen/0zen/issues"
66
+ "url": "https://github.com/TRIBE-INC/0zen/issues"
67
67
  }
68
68
  }
package/setup-path.js ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const os = require('os');
5
+ const path = require('path');
6
+ const chalk = require('chalk');
7
+
8
+ const homeDir = os.homedir();
9
+ const tribeEnvPath = path.join(homeDir, '.tribe', 'tribe-env.sh');
10
+
11
+ // Detect user's shell
12
+ function detectShell() {
13
+ const shell = process.env.SHELL || '';
14
+ if (shell.includes('zsh')) return 'zsh';
15
+ if (shell.includes('bash')) return 'bash';
16
+ if (shell.includes('fish')) return 'fish';
17
+ return 'unknown';
18
+ }
19
+
20
+ // Get shell config file
21
+ function getShellConfigFile() {
22
+ const shell = detectShell();
23
+ const configFiles = {
24
+ 'zsh': ['.zshrc', '.zprofile'],
25
+ 'bash': ['.bashrc', '.bash_profile', '.profile'],
26
+ 'fish': ['.config/fish/config.fish']
27
+ };
28
+
29
+ const candidates = configFiles[shell] || [];
30
+
31
+ // Check which config file exists
32
+ for (const file of candidates) {
33
+ const fullPath = path.join(homeDir, file);
34
+ if (fs.existsSync(fullPath)) {
35
+ return fullPath;
36
+ }
37
+ }
38
+
39
+ // If none exist, use the first candidate
40
+ if (candidates.length > 0) {
41
+ return path.join(homeDir, candidates[0]);
42
+ }
43
+
44
+ return null;
45
+ }
46
+
47
+ function setupPath() {
48
+ console.log(chalk.bold('🔧 TRIBE PATH Setup\n'));
49
+
50
+ // Check if tribe-env.sh exists
51
+ if (!fs.existsSync(tribeEnvPath)) {
52
+ console.log(chalk.red('Error: TRIBE environment script not found.'));
53
+ console.log('Please run the installer first: npx @_xtribe/cli');
54
+ process.exit(1);
55
+ }
56
+
57
+ const shellConfig = getShellConfigFile();
58
+ const shell = detectShell();
59
+
60
+ if (!shellConfig) {
61
+ console.log(chalk.yellow('Could not detect shell configuration file.'));
62
+ console.log('\nPlease manually add this line to your shell config:');
63
+ console.log(chalk.green(` source ~/.tribe/tribe-env.sh`));
64
+ return;
65
+ }
66
+
67
+ // Check if already added
68
+ try {
69
+ const content = fs.readFileSync(shellConfig, 'utf8');
70
+ if (content.includes('source ~/.tribe/tribe-env.sh') ||
71
+ content.includes('source $HOME/.tribe/tribe-env.sh') ||
72
+ content.includes('. ~/.tribe/tribe-env.sh')) {
73
+ console.log(chalk.green('✓ PATH already configured!'));
74
+ console.log('\nTo use tribe in your current session:');
75
+ console.log(chalk.green(` source ~/.tribe/tribe-env.sh`));
76
+ return;
77
+ }
78
+ } catch (e) {
79
+ // File doesn't exist yet, that's ok
80
+ }
81
+
82
+ // Add to shell config
83
+ const sourceCommand = '\n# TRIBE CLI\nsource ~/.tribe/tribe-env.sh\n';
84
+
85
+ try {
86
+ fs.appendFileSync(shellConfig, sourceCommand);
87
+ console.log(chalk.green(`✓ Added TRIBE to your ${shell} configuration!`));
88
+ console.log(` Configuration file: ${shellConfig}`);
89
+ console.log('\nTo use tribe in your current session:');
90
+ console.log(chalk.green(` source ~/.tribe/tribe-env.sh`));
91
+ console.log('\nOr open a new terminal window.');
92
+ } catch (error) {
93
+ console.log(chalk.red(`Error updating ${shellConfig}: ${error.message}`));
94
+ console.log('\nPlease manually add this line to your shell config:');
95
+ console.log(chalk.green(` source ~/.tribe/tribe-env.sh`));
96
+ }
97
+ }
98
+
99
+ // Export for use by other modules
100
+ module.exports = setupPath;
101
+
102
+ // Add to package.json bin entry
103
+ if (require.main === module) {
104
+ setupPath();
105
+ }