@_xtribe/cli 2.2.73 → 2.2.77

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.
@@ -120,32 +120,15 @@ if (Test-Path $TribeBinDir) {
120
120
  }`;
121
121
  } else {
122
122
  // Bash/Zsh with enhanced detection
123
- envScript = `#!/bin/bash
124
- # TRIBE CLI Environment
125
- # Generated on $(date) - Install ID: ${this.installId}
126
-
123
+ envScript = `#!/bin/sh
124
+ # TRIBE CLI Environment - PATH setup only (no commands executed at shell startup)
127
125
  TRIBE_BIN_DIR="$HOME/.tribe/bin"
128
-
129
- # Enhanced PATH detection - handles edge cases
130
- if [[ -d "$TRIBE_BIN_DIR" ]]; then
131
- # Check if already in PATH using multiple methods
132
- case ":$PATH:" in
133
- *":$TRIBE_BIN_DIR:"*)
134
- # Already in PATH, do nothing
135
- ;;
136
- *)
137
- # Add to PATH
138
- export PATH="$TRIBE_BIN_DIR:$PATH"
139
- ;;
140
- esac
141
- fi
142
-
143
- # Validate installation
144
- if command -v tribe >/dev/null 2>&1; then
145
- # Optional: Set additional TRIBE environment variables
146
- export TRIBE_HOME="$HOME/.tribe"
147
- export TRIBE_VERSION="$(tribe version 2>/dev/null || echo 'unknown')"
148
- fi`;
126
+ case ":$PATH:" in
127
+ *":$TRIBE_BIN_DIR:"*) ;;
128
+ *) [ -d "$TRIBE_BIN_DIR" ] && export PATH="$TRIBE_BIN_DIR:$PATH" ;;
129
+ esac
130
+ export TRIBE_HOME="$HOME/.tribe"
131
+ `;
149
132
  }
150
133
 
151
134
  fs.writeFileSync(envScriptPath, envScript);
@@ -106,16 +106,14 @@ async function installTribe() {
106
106
  function updatePath() {
107
107
  // Create tribe-env.sh script
108
108
  const tribeEnvPath = path.join(tribeDir, 'tribe-env.sh');
109
- const envScriptContent = `#!/bin/bash
110
- # TRIBE CLI Environment Setup
111
- # Auto-generated by TRIBE installer
112
-
113
- # Add TRIBE bin directory to PATH if not already present
109
+ const envScriptContent = `#!/bin/sh
110
+ # TRIBE CLI Environment - PATH setup only (no commands executed at shell startup)
114
111
  TRIBE_BIN_DIR="$HOME/.tribe/bin"
115
-
116
- if [[ -d "$TRIBE_BIN_DIR" ]] && [[ ":$PATH:" != *":$TRIBE_BIN_DIR:"* ]]; then
117
- export PATH="$TRIBE_BIN_DIR:$PATH"
118
- fi
112
+ case ":$PATH:" in
113
+ *":$TRIBE_BIN_DIR:"*) ;;
114
+ *) [ -d "$TRIBE_BIN_DIR" ] && export PATH="$TRIBE_BIN_DIR:$PATH" ;;
115
+ esac
116
+ export TRIBE_HOME="$HOME/.tribe"
119
117
  `;
120
118
 
121
119
  try {
package/install-tribe.js CHANGED
@@ -64,9 +64,49 @@ function showWelcome() {
64
64
  }
65
65
 
66
66
 
67
+ // Fetch latest release version from GitHub
68
+ async function getLatestVersion() {
69
+ return new Promise((resolve, reject) => {
70
+ const url = 'https://api.github.com/repos/TRIBE-INC/releases/releases/latest';
71
+ https.get(url, {
72
+ headers: { 'User-Agent': 'TRIBE-CLI-Installer' }
73
+ }, (response) => {
74
+ let data = '';
75
+ response.on('data', chunk => data += chunk);
76
+ response.on('end', () => {
77
+ try {
78
+ const release = JSON.parse(data);
79
+ resolve(release.tag_name); // e.g., "v2.2.74"
80
+ } catch (error) {
81
+ resolve(null); // Ignore errors, proceed with install
82
+ }
83
+ });
84
+ }).on('error', () => resolve(null));
85
+ });
86
+ }
87
+
88
+ // Get installed version by running tribe --version
89
+ function getInstalledVersion() {
90
+ const tribeDest = path.join(tribeBinDir, 'tribe');
91
+ if (!fs.existsSync(tribeDest)) return null;
92
+
93
+ try {
94
+ const output = execSync(`"${tribeDest}" --version 2>/dev/null || true`, {
95
+ encoding: 'utf8',
96
+ timeout: 5000
97
+ });
98
+ // Extract version like "v2.2.74" or "2.2.74"
99
+ const match = output.match(/v?(\d+\.\d+\.\d+)/);
100
+ return match ? `v${match[1]}` : null;
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+
67
106
  async function downloadFile(url, dest) {
68
107
  return new Promise((resolve, reject) => {
69
- const file = fs.createWriteStream(dest);
108
+ // Create file with execute permissions from the start (0755)
109
+ const file = fs.createWriteStream(dest, { mode: 0o755 });
70
110
  https.get(url, (response) => {
71
111
  if (response.statusCode === 302 || response.statusCode === 301) {
72
112
  return downloadFile(response.headers.location, dest).then(resolve, reject);
@@ -78,6 +118,12 @@ async function downloadFile(url, dest) {
78
118
  response.pipe(file);
79
119
  file.on('finish', () => {
80
120
  file.close();
121
+ // Ensure execute permissions are set after download completes
122
+ try {
123
+ fs.chmodSync(dest, 0o755);
124
+ } catch (e) {
125
+ // Ignore chmod errors - permissions were set during creation
126
+ }
81
127
  resolve();
82
128
  });
83
129
  }).on('error', reject);
@@ -87,9 +133,38 @@ async function downloadFile(url, dest) {
87
133
  async function installTribeCLI() {
88
134
  const tribeDest = path.join(tribeBinDir, 'tribe');
89
135
 
90
- // Check if update needed
136
+ // Check if update needed by comparing versions
91
137
  const exists = fs.existsSync(tribeDest);
92
- const spinner = ora(exists ? 'Updating CLI...' : 'Installing CLI...').start();
138
+ const installedVersion = getInstalledVersion();
139
+ const latestVersion = await getLatestVersion();
140
+
141
+ // Determine if we need to download
142
+ let needsDownload = !exists;
143
+ let statusMsg = 'Installing CLI...';
144
+
145
+ if (exists && latestVersion && installedVersion) {
146
+ // Compare versions (strip 'v' prefix for comparison)
147
+ const installed = installedVersion.replace(/^v/, '');
148
+ const latest = latestVersion.replace(/^v/, '');
149
+ if (installed !== latest) {
150
+ needsDownload = true;
151
+ statusMsg = `Updating CLI (${installedVersion} → ${latestVersion})...`;
152
+ } else {
153
+ statusMsg = `CLI is up to date (${latestVersion})`;
154
+ }
155
+ } else if (exists) {
156
+ // Can't determine versions, force update to be safe
157
+ needsDownload = true;
158
+ statusMsg = 'Updating CLI...';
159
+ }
160
+
161
+ const spinner = ora(statusMsg).start();
162
+
163
+ // Skip download if already up to date
164
+ if (exists && !needsDownload) {
165
+ spinner.succeed(`CLI is up to date (${latestVersion || 'latest'})`);
166
+ return true;
167
+ }
93
168
 
94
169
  try {
95
170
  // Clean up any existing tribe binaries first
@@ -105,7 +180,7 @@ async function installTribeCLI() {
105
180
  const downloadUrl = `https://github.com/${githubRepo}/releases/latest/download/tribe-${platform}-${arch}`;
106
181
 
107
182
  await downloadFile(downloadUrl, tribeDest);
108
- fs.chmodSync(tribeDest, '755');
183
+ fs.chmodSync(tribeDest, 0o755);
109
184
 
110
185
  // Remove macOS quarantine if needed
111
186
  if (platform === 'darwin') {
@@ -116,7 +191,20 @@ async function installTribeCLI() {
116
191
  }
117
192
  }
118
193
 
119
- spinner.succeed('CLI ready');
194
+ // Save version info for future update checks
195
+ if (latestVersion) {
196
+ try {
197
+ const versionFile = path.join(tribeDir, 'version.json');
198
+ fs.writeFileSync(versionFile, JSON.stringify({
199
+ version: latestVersion,
200
+ installedAt: new Date().toISOString()
201
+ }, null, 2));
202
+ } catch {
203
+ // Not critical
204
+ }
205
+ }
206
+
207
+ spinner.succeed(`CLI ready (${latestVersion || 'latest'})`);
120
208
  return true;
121
209
  } catch (error) {
122
210
  spinner.fail(`Installation failed: ${error.message}`);
@@ -166,7 +254,7 @@ async function installTribeCLIQuiet() {
166
254
  const downloadUrl = `https://github.com/${githubRepo}/releases/latest/download/tribe-${platform}-${arch}`;
167
255
 
168
256
  await downloadFile(downloadUrl, tribeDest);
169
- fs.chmodSync(tribeDest, '755');
257
+ fs.chmodSync(tribeDest, 0o755);
170
258
 
171
259
  // Also download tutor-collector binary (CRITICAL - this is the core product!)
172
260
  const tutorCollectorDest = path.join(tribeBinDir, 'tutor-collector');
@@ -180,7 +268,7 @@ async function installTribeCLIQuiet() {
180
268
  const communityUrl = `https://github.com/TRIBE-INC/tutor-server-community-release/releases/latest/download/tutor-collector-${platform}-${arch}`;
181
269
  await downloadFile(communityUrl, tutorCollectorDest);
182
270
  }
183
- fs.chmodSync(tutorCollectorDest, '755');
271
+ fs.chmodSync(tutorCollectorDest, 0o755);
184
272
 
185
273
  // Download realtime-sync binary (for tribe realtime command)
186
274
  const realtimeSyncDest = path.join(tribeBinDir, 'realtime-sync');
@@ -188,7 +276,7 @@ async function installTribeCLIQuiet() {
188
276
 
189
277
  try {
190
278
  await downloadFile(realtimeSyncUrl, realtimeSyncDest);
191
- fs.chmodSync(realtimeSyncDest, '755');
279
+ fs.chmodSync(realtimeSyncDest, 0o755);
192
280
  } catch (error) {
193
281
  // realtime-sync is optional, don't fail install if missing
194
282
  console.log('Note: realtime-sync not available in this release');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_xtribe/cli",
3
- "version": "2.2.73",
3
+ "version": "2.2.77",
4
4
  "description": "TRIBE - Privacy-first AI development analytics. Self-host your telemetry, skip authentication, or run completely offline. Your data stays on your machine.",
5
5
  "main": "install-tribe.js",
6
6
  "bin": {