@fredlackey/devutils 0.0.11 → 0.0.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fredlackey/devutils",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "A globally-installable Node.js CLI toolkit for bootstrapping and configuring development environments across any machine.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -203,6 +203,10 @@ async function install_ubuntu() {
203
203
 
204
204
  console.log('Installing Balena Etcher...');
205
205
 
206
+ // Update package lists first to ensure dependencies can be resolved
207
+ // This is important for fresh systems where package lists may be stale
208
+ await shell.exec('sudo DEBIAN_FRONTEND=noninteractive apt-get update -y');
209
+
206
210
  // Install the .deb package using apt-get
207
211
  // DEBIAN_FRONTEND=noninteractive ensures no interactive prompts
208
212
  const installResult = await shell.exec(
@@ -49,9 +49,25 @@ const HOMEBREW_CASK_NAME = 'bambu-studio';
49
49
 
50
50
  /**
51
51
  * The Flatpak application ID for Bambu Studio on Flathub.
52
+ * Note: AppImage is now preferred over Flatpak for Linux installations.
52
53
  */
53
54
  const FLATPAK_APP_ID = 'com.bambulab.BambuStudio';
54
55
 
56
+ /**
57
+ * The GitHub repository for Bambu Studio releases.
58
+ */
59
+ const GITHUB_REPO = 'bambulab/BambuStudio';
60
+
61
+ /**
62
+ * The installation directory for AppImage executables.
63
+ */
64
+ const APPIMAGE_INSTALL_DIR = '/usr/local/bin';
65
+
66
+ /**
67
+ * The desktop entry installation directory.
68
+ */
69
+ const DESKTOP_ENTRY_DIR = '/usr/share/applications';
70
+
55
71
  /**
56
72
  * The Chocolatey package name for Bambu Studio on Windows.
57
73
  */
@@ -72,6 +88,30 @@ function isInstalledOnMacOS() {
72
88
  return macosApps.isAppInstalled(MACOS_APP_NAME);
73
89
  }
74
90
 
91
+ /**
92
+ * Checks if Bambu Studio AppImage is installed in the system.
93
+ * Looks for the executable in common installation paths.
94
+ *
95
+ * @returns {boolean} True if Bambu Studio AppImage is installed
96
+ */
97
+ function isAppImageInstalled() {
98
+ // Check common installation paths
99
+ const commonPaths = [
100
+ '/usr/local/bin/bambu-studio',
101
+ '/usr/local/bin/BambuStudio',
102
+ '/opt/bambu-studio/bambu-studio'
103
+ ];
104
+
105
+ for (const path of commonPaths) {
106
+ if (fs.existsSync(path)) {
107
+ return true;
108
+ }
109
+ }
110
+
111
+ // Check if bambu-studio or BambuStudio command exists in PATH
112
+ return shell.commandExists('bambu-studio') || shell.commandExists('BambuStudio');
113
+ }
114
+
75
115
  /**
76
116
  * Checks if Flatpak is available on the system.
77
117
  * Flatpak is required for Linux installations (Ubuntu, WSL, Amazon Linux).
@@ -85,6 +125,7 @@ function isFlatpakAvailable() {
85
125
  /**
86
126
  * Checks if Bambu Studio is installed via Flatpak.
87
127
  * Queries the Flatpak list for the Bambu Studio application ID.
128
+ * Checks both system-level and user-level installations.
88
129
  *
89
130
  * @returns {Promise<boolean>} True if Bambu Studio is installed via Flatpak
90
131
  */
@@ -93,8 +134,14 @@ async function isInstalledViaFlatpak() {
93
134
  return false;
94
135
  }
95
136
 
96
- // Check if the Flatpak app is installed by looking for it in the list
97
- const result = await shell.exec(`flatpak list --app | grep -i "${FLATPAK_APP_ID}"`);
137
+ // Check system-level installation
138
+ let result = await shell.exec(`flatpak list --app | grep -i "${FLATPAK_APP_ID}"`);
139
+ if (result.code === 0 && result.stdout.includes(FLATPAK_APP_ID)) {
140
+ return true;
141
+ }
142
+
143
+ // Check user-level installation
144
+ result = await shell.exec(`flatpak list --app --user | grep -i "${FLATPAK_APP_ID}"`);
98
145
  return result.code === 0 && result.stdout.includes(FLATPAK_APP_ID);
99
146
  }
100
147
 
@@ -140,6 +187,191 @@ async function isInstalledOnRaspbian() {
140
187
  return false;
141
188
  }
142
189
 
190
+ /**
191
+ * Gets the latest AppImage download URL from GitHub releases.
192
+ * Detects the system architecture and chooses the appropriate AppImage variant.
193
+ *
194
+ * @returns {Promise<{url: string, filename: string} | null>} Download URL and filename, or null if not found
195
+ */
196
+ async function getLatestAppImageUrl() {
197
+ try {
198
+ // Fetch the latest release info from GitHub API
199
+ const apiUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
200
+ const result = await shell.exec(`curl -s "${apiUrl}"`);
201
+
202
+ if (result.code !== 0 || !result.stdout) {
203
+ console.error('Failed to fetch latest release information from GitHub.');
204
+ return null;
205
+ }
206
+
207
+ const release = JSON.parse(result.stdout);
208
+ const assets = release.assets || [];
209
+
210
+ // Determine which AppImage to download based on Ubuntu version or distribution
211
+ // Prefer ubuntu-22.04 for broader compatibility, unless on a newer system
212
+ let preferredVariant = 'ubuntu-22.04';
213
+
214
+ // Check if running Ubuntu 24.04 or newer
215
+ if (fs.existsSync('/etc/os-release')) {
216
+ const osReleaseResult = await shell.exec('cat /etc/os-release | grep VERSION_ID');
217
+ if (osReleaseResult.code === 0 && osReleaseResult.stdout.includes('24.04')) {
218
+ preferredVariant = 'ubuntu-24.04';
219
+ }
220
+ }
221
+
222
+ // Look for AppImage assets (prioritize preferred variant, then Fedora, then any Ubuntu)
223
+ let selectedAsset = null;
224
+
225
+ // First try: preferred Ubuntu variant
226
+ selectedAsset = assets.find(asset =>
227
+ asset.name.endsWith('.AppImage') &&
228
+ asset.name.includes(preferredVariant)
229
+ );
230
+
231
+ // Second try: Fedora variant (good for RHEL-based systems)
232
+ if (!selectedAsset) {
233
+ selectedAsset = assets.find(asset =>
234
+ asset.name.endsWith('.AppImage') &&
235
+ asset.name.includes('fedora')
236
+ );
237
+ }
238
+
239
+ // Third try: any Ubuntu variant
240
+ if (!selectedAsset) {
241
+ selectedAsset = assets.find(asset =>
242
+ asset.name.endsWith('.AppImage') &&
243
+ asset.name.includes('ubuntu')
244
+ );
245
+ }
246
+
247
+ // Last resort: any AppImage
248
+ if (!selectedAsset) {
249
+ selectedAsset = assets.find(asset => asset.name.endsWith('.AppImage'));
250
+ }
251
+
252
+ if (!selectedAsset) {
253
+ console.error('No AppImage found in the latest release.');
254
+ return null;
255
+ }
256
+
257
+ return {
258
+ url: selectedAsset.browser_download_url,
259
+ filename: selectedAsset.name
260
+ };
261
+ } catch (error) {
262
+ console.error('Error fetching AppImage URL:', error.message);
263
+ return null;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * Creates a desktop entry file for Bambu Studio AppImage.
269
+ * This allows the application to appear in desktop menus.
270
+ *
271
+ * @param {string} execPath - The full path to the AppImage executable
272
+ * @returns {Promise<boolean>} True if desktop entry was created successfully
273
+ */
274
+ async function createDesktopEntry(execPath) {
275
+ const desktopEntry = `[Desktop Entry]
276
+ Name=Bambu Studio
277
+ Comment=3D printing slicer for Bambu Lab printers
278
+ Exec=${execPath}
279
+ Icon=bambu-studio
280
+ Terminal=false
281
+ Type=Application
282
+ Categories=Graphics;3DGraphics;Engineering;
283
+ MimeType=model/stl;application/x-3mf;model/x.stl-binary;model/x.stl-ascii;application/sla;
284
+ `;
285
+
286
+ const desktopFilePath = path.join(DESKTOP_ENTRY_DIR, 'bambu-studio.desktop');
287
+
288
+ try {
289
+ // Create desktop entry directory if it doesn't exist
290
+ await shell.exec(`sudo mkdir -p ${DESKTOP_ENTRY_DIR}`);
291
+
292
+ // Write desktop entry file
293
+ const tempFile = `/tmp/bambu-studio.desktop`;
294
+ fs.writeFileSync(tempFile, desktopEntry);
295
+
296
+ const copyResult = await shell.exec(`sudo mv ${tempFile} ${desktopFilePath}`);
297
+ if (copyResult.code !== 0) {
298
+ console.error('Failed to create desktop entry:', copyResult.stderr);
299
+ return false;
300
+ }
301
+
302
+ // Make desktop entry executable
303
+ await shell.exec(`sudo chmod 644 ${desktopFilePath}`);
304
+
305
+ // Update desktop database
306
+ await shell.exec('sudo update-desktop-database 2>/dev/null || true');
307
+
308
+ return true;
309
+ } catch (error) {
310
+ console.error('Error creating desktop entry:', error.message);
311
+ return false;
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Downloads and installs Bambu Studio AppImage.
317
+ * AppImages are self-contained executables that work across Linux distributions.
318
+ *
319
+ * @returns {Promise<boolean>} True if installation succeeded
320
+ */
321
+ async function installAppImage() {
322
+ console.log('Fetching latest Bambu Studio AppImage from GitHub...');
323
+
324
+ // Get the download URL
325
+ const downloadInfo = await getLatestAppImageUrl();
326
+ if (!downloadInfo) {
327
+ console.error('Could not determine AppImage download URL.');
328
+ return false;
329
+ }
330
+
331
+ console.log(`Found AppImage: ${downloadInfo.filename}`);
332
+ console.log('Downloading Bambu Studio AppImage...');
333
+ console.log('Note: This may take several minutes depending on your connection.');
334
+
335
+ // Download the AppImage to /tmp
336
+ const tempPath = `/tmp/${downloadInfo.filename}`;
337
+ const downloadResult = await shell.exec(`curl -L -o "${tempPath}" "${downloadInfo.url}"`);
338
+
339
+ if (downloadResult.code !== 0) {
340
+ console.error('Failed to download AppImage:', downloadResult.stderr);
341
+ return false;
342
+ }
343
+
344
+ console.log('AppImage downloaded successfully.');
345
+
346
+ // Make the AppImage executable
347
+ console.log('Installing AppImage...');
348
+ const chmodResult = await shell.exec(`chmod +x "${tempPath}"`);
349
+ if (chmodResult.code !== 0) {
350
+ console.error('Failed to make AppImage executable:', chmodResult.stderr);
351
+ return false;
352
+ }
353
+
354
+ // Install to /usr/local/bin with a simplified name
355
+ const installPath = `${APPIMAGE_INSTALL_DIR}/bambu-studio`;
356
+ const installResult = await shell.exec(`sudo mv "${tempPath}" "${installPath}"`);
357
+
358
+ if (installResult.code !== 0) {
359
+ console.error('Failed to install AppImage:', installResult.stderr);
360
+ return false;
361
+ }
362
+
363
+ console.log(`Bambu Studio installed to ${installPath}`);
364
+
365
+ // Create desktop entry
366
+ console.log('Creating desktop entry...');
367
+ const desktopCreated = await createDesktopEntry(installPath);
368
+ if (!desktopCreated) {
369
+ console.log('Warning: Desktop entry creation failed. You can still launch from command line.');
370
+ }
371
+
372
+ return true;
373
+ }
374
+
143
375
  /**
144
376
  * Installs Flatpak if not already present on a Debian-based system.
145
377
  * This is a prerequisite for installing Bambu Studio on Linux via Flatpak.
@@ -189,43 +421,59 @@ function hasDisplayEnvironment() {
189
421
  * Adds the Flathub repository if not already configured.
190
422
  * Flathub is the source for the Bambu Studio Flatpak package.
191
423
  *
192
- * @returns {Promise<boolean>} True if Flathub is available after this function
424
+ * Tries system-level installation first, falls back to user-level if system bus unavailable.
425
+ * This enables installation in Docker/containerized environments with limited D-Bus access.
426
+ *
427
+ * @returns {Promise<{success: boolean, userLevel: boolean}>} Result object with success status and whether user-level was used
193
428
  */
194
429
  async function ensureFlathubConfigured() {
195
- // Check if Flathub is already configured
196
- const checkResult = await shell.exec('flatpak remote-list | grep -i flathub');
430
+ // Check if Flathub is already configured (system-level)
431
+ let checkResult = await shell.exec('flatpak remote-list | grep -i flathub');
197
432
  if (checkResult.code === 0 && checkResult.stdout.includes('flathub')) {
198
- return true;
433
+ return { success: true, userLevel: false };
434
+ }
435
+
436
+ // Check if Flathub is already configured (user-level)
437
+ checkResult = await shell.exec('flatpak remote-list --user | grep -i flathub');
438
+ if (checkResult.code === 0 && checkResult.stdout.includes('flathub')) {
439
+ return { success: true, userLevel: true };
199
440
  }
200
441
 
201
442
  console.log('Adding Flathub repository...');
202
443
 
203
- // Add Flathub repository (--if-not-exists prevents errors if already added)
204
- const addResult = await shell.exec(
444
+ // Try system-level first (preferred for desktop systems)
445
+ let addResult = await shell.exec(
205
446
  'flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo'
206
447
  );
207
448
 
208
- if (addResult.code !== 0) {
209
- console.error('Failed to add Flathub repository:', addResult.stderr);
449
+ if (addResult.code === 0) {
450
+ console.log('Flathub repository added successfully.');
451
+ return { success: true, userLevel: false };
452
+ }
210
453
 
211
- // Provide helpful context if this is likely a headless/Docker environment
212
- if (addResult.stderr.includes('system bus') || addResult.stderr.includes('D-Bus')) {
213
- console.log('');
214
- console.log('This error typically occurs in headless or containerized environments.');
215
- console.log('Bambu Studio is a GUI application and requires:');
216
- console.log(' 1. A desktop environment (GNOME, KDE, XFCE, etc.)');
217
- console.log(' 2. X11 or Wayland display server');
218
- console.log(' 3. D-Bus system bus');
219
- console.log('');
220
- console.log('If you are in a Docker container or headless server, Bambu Studio');
221
- console.log('cannot be installed or run. Use a desktop Linux system instead.');
222
- }
454
+ // If system-level fails due to D-Bus issues, try user-level installation
455
+ if (addResult.stderr.includes('system bus') || addResult.stderr.includes('D-Bus')) {
456
+ console.log('System-level Flatpak unavailable (no system D-Bus). Trying user-level installation...');
223
457
 
224
- return false;
458
+ addResult = await shell.exec(
459
+ 'flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo'
460
+ );
461
+
462
+ if (addResult.code === 0) {
463
+ console.log('Flathub repository added successfully (user-level).');
464
+ return { success: true, userLevel: true };
465
+ }
225
466
  }
226
467
 
227
- console.log('Flathub repository added successfully.');
228
- return true;
468
+ // Both system and user-level failed
469
+ console.error('Failed to add Flathub repository:', addResult.stderr);
470
+ console.log('');
471
+ console.log('Troubleshooting:');
472
+ console.log(' 1. Ensure D-Bus is running (for GUI applications)');
473
+ console.log(' 2. Try manually: flatpak remote-add --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo');
474
+ console.log(' 3. If in Docker, ensure the container has proper D-Bus configuration');
475
+
476
+ return { success: false, userLevel: false };
229
477
  }
230
478
 
231
479
  /**
@@ -308,25 +556,23 @@ async function install_macos() {
308
556
  }
309
557
 
310
558
  /**
311
- * Install Bambu Studio on Ubuntu/Debian using Flatpak from Flathub.
559
+ * Install Bambu Studio on Ubuntu/Debian using AppImage from GitHub.
312
560
  *
313
- * IMPORTANT: There is no official APT or Snap package for Bambu Studio.
314
- * Flatpak from Flathub is the recommended installation method for Linux.
561
+ * IMPORTANT: AppImage is now the preferred installation method for Linux.
562
+ * AppImages are self-contained executables that work in Docker containers
563
+ * and don't require user namespaces or D-Bus configuration.
315
564
  *
316
565
  * Prerequisites:
317
566
  * - Ubuntu 20.04+ or Debian 11+ (64-bit)
318
- * - X11 or Wayland display server
567
+ * - X11 or Wayland display server (for GUI applications)
319
568
  * - sudo privileges
320
- *
321
- * NOTE: A system restart (or logout/login) may be required after installing
322
- * Flatpak for the first time before Bambu Studio can be launched.
569
+ * - curl installed
323
570
  *
324
571
  * @returns {Promise<void>}
325
572
  */
326
573
  async function install_ubuntu() {
327
- // Check if already installed via Flatpak (idempotency check)
328
- const alreadyInstalled = await isInstalledViaFlatpak();
329
- if (alreadyInstalled) {
574
+ // Check if already installed via AppImage (idempotency check)
575
+ if (isAppImageInstalled()) {
330
576
  console.log('Bambu Studio is already installed.');
331
577
  return;
332
578
  }
@@ -345,53 +591,29 @@ async function install_ubuntu() {
345
591
  return;
346
592
  }
347
593
 
348
- // Ensure Flatpak is installed (required for Bambu Studio on Linux)
349
- const flatpakReady = await ensureFlatpakInstalled();
350
- if (!flatpakReady) {
351
- console.error('Could not install Flatpak. Please install it manually:');
352
- console.log(' sudo apt-get update && sudo apt-get install -y flatpak');
353
- return;
354
- }
594
+ // Install using AppImage
595
+ console.log('Installing Bambu Studio via AppImage from GitHub...');
596
+ const success = await installAppImage();
355
597
 
356
- // Ensure Flathub repository is configured
357
- const flathubReady = await ensureFlathubConfigured();
358
- if (!flathubReady) {
359
- console.error('Could not configure Flathub repository. Please add it manually:');
360
- console.log(' flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo');
361
- return;
362
- }
363
-
364
- console.log('Installing Bambu Studio via Flatpak...');
365
- console.log('Note: This may take several minutes on first install.');
366
-
367
- // Install Bambu Studio from Flathub
368
- // The -y flag automatically confirms the installation
369
- const installResult = await shell.exec(`flatpak install -y flathub ${FLATPAK_APP_ID}`);
370
-
371
- if (installResult.code !== 0) {
372
- console.error('Failed to install Bambu Studio:', installResult.stderr);
598
+ if (!success) {
599
+ console.error('Failed to install Bambu Studio AppImage.');
373
600
  console.log('');
374
601
  console.log('Troubleshooting:');
375
- console.log(' 1. Try restarting your system and running the install again');
376
- console.log(' 2. Run: flatpak update -y');
377
- console.log(' 3. If Flathub fails, try re-adding it:');
378
- console.log(' flatpak remote-delete flathub');
379
- console.log(' flatpak remote-add flathub https://dl.flathub.org/repo/flathub.flatpakrepo');
602
+ console.log(' 1. Ensure curl is installed: sudo apt-get install -y curl');
603
+ console.log(' 2. Check your internet connection');
604
+ console.log(' 3. Visit https://github.com/bambulab/BambuStudio/releases for manual download');
380
605
  return;
381
606
  }
382
607
 
383
608
  // Verify installation succeeded
384
- const verifyInstalled = await isInstalledViaFlatpak();
385
- if (verifyInstalled) {
386
- console.log('Bambu Studio installed successfully.');
609
+ if (isAppImageInstalled()) {
387
610
  console.log('');
388
- console.log('Launch with: flatpak run com.bambulab.BambuStudio');
611
+ console.log('Bambu Studio installed successfully.');
389
612
  console.log('');
390
- console.log('Note: If this is your first Flatpak installation, you may need to');
391
- console.log('restart your system or log out/in for the app to appear in menus.');
613
+ console.log('Launch with: bambu-studio');
614
+ console.log('Location: /usr/local/bin/bambu-studio');
392
615
  } else {
393
616
  console.error('Installation completed but Bambu Studio was not found.');
394
- console.log('Try running: flatpak list | grep -i bambu');
395
617
  }
396
618
  }
397
619
 
@@ -490,7 +712,7 @@ async function install_raspbian() {
490
712
  }
491
713
 
492
714
  /**
493
- * Install Bambu Studio on Amazon Linux/RHEL using Flatpak.
715
+ * Install Bambu Studio on Amazon Linux/RHEL using AppImage.
494
716
  *
495
717
  * IMPORTANT: Amazon Linux is primarily a server OS without a desktop environment.
496
718
  * Bambu Studio is a GUI application and requires a display. This platform is
@@ -499,15 +721,14 @@ async function install_raspbian() {
499
721
  * Prerequisites:
500
722
  * - Amazon Linux 2023, Amazon Linux 2, RHEL 8+, or Fedora 35+
501
723
  * - Desktop environment with X11/Wayland support
502
- * - Flatpak package manager
503
724
  * - sudo privileges
725
+ * - curl installed
504
726
  *
505
727
  * @returns {Promise<void>}
506
728
  */
507
729
  async function install_amazon_linux() {
508
- // Check if already installed via Flatpak (idempotency check)
509
- const alreadyInstalled = await isInstalledViaFlatpak();
510
- if (alreadyInstalled) {
730
+ // Check if already installed via AppImage (idempotency check)
731
+ if (isAppImageInstalled()) {
511
732
  console.log('Bambu Studio is already installed.');
512
733
  return;
513
734
  }
@@ -530,44 +751,29 @@ async function install_amazon_linux() {
530
751
  return;
531
752
  }
532
753
 
533
- // Ensure Flatpak is installed
534
- const flatpakReady = await ensureFlatpakInstalledRHEL();
535
- if (!flatpakReady) {
536
- console.error('Could not install Flatpak. Please install it manually:');
537
- console.log(' sudo dnf install -y flatpak');
538
- return;
539
- }
540
-
541
- // Ensure Flathub repository is configured
542
- const flathubReady = await ensureFlathubConfigured();
543
- if (!flathubReady) {
544
- console.error('Could not configure Flathub repository. Please add it manually:');
545
- console.log(' flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo');
546
- return;
547
- }
548
-
549
- console.log('Installing Bambu Studio via Flatpak...');
754
+ // Install using AppImage
755
+ console.log('Installing Bambu Studio via AppImage from GitHub...');
756
+ const success = await installAppImage();
550
757
 
551
- // Install Bambu Studio from Flathub
552
- const installResult = await shell.exec(`flatpak install -y flathub ${FLATPAK_APP_ID}`);
553
-
554
- if (installResult.code !== 0) {
555
- console.error('Failed to install Bambu Studio:', installResult.stderr);
758
+ if (!success) {
759
+ console.error('Failed to install Bambu Studio AppImage.');
556
760
  console.log('');
557
761
  console.log('Troubleshooting:');
558
- console.log(' 1. Ensure you have a desktop environment installed:');
762
+ console.log(' 1. Ensure curl is installed: sudo dnf install -y curl');
763
+ console.log(' 2. Check your internet connection');
764
+ console.log(' 3. Ensure you have a desktop environment installed:');
559
765
  console.log(' sudo dnf groupinstall -y "GNOME Desktop Environment"');
560
- console.log(' 2. Install required graphics drivers:');
561
- console.log(' sudo dnf install -y mesa-libGL mesa-libGLU mesa-dri-drivers');
766
+ console.log(' 4. Visit https://github.com/bambulab/BambuStudio/releases for manual download');
562
767
  return;
563
768
  }
564
769
 
565
770
  // Verify installation succeeded
566
- const verifyInstalled = await isInstalledViaFlatpak();
567
- if (verifyInstalled) {
771
+ if (isAppImageInstalled()) {
772
+ console.log('');
568
773
  console.log('Bambu Studio installed successfully.');
569
774
  console.log('');
570
- console.log('Launch with: flatpak run com.bambulab.BambuStudio');
775
+ console.log('Launch with: bambu-studio');
776
+ console.log('Location: /usr/local/bin/bambu-studio');
571
777
  } else {
572
778
  console.error('Installation completed but Bambu Studio was not found.');
573
779
  }
@@ -683,8 +889,8 @@ async function install_ubuntu_wsl() {
683
889
  }
684
890
 
685
891
  // Ensure Flathub repository is configured
686
- const flathubReady = await ensureFlathubConfigured();
687
- if (!flathubReady) {
892
+ const flathubResult = await ensureFlathubConfigured();
893
+ if (!flathubResult.success) {
688
894
  console.error('Could not configure Flathub repository. Please add it manually:');
689
895
  console.log(' flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo');
690
896
  return;
@@ -694,7 +900,9 @@ async function install_ubuntu_wsl() {
694
900
  console.log('Note: This may take several minutes on first install.');
695
901
 
696
902
  // Install Bambu Studio from Flathub
697
- const installResult = await shell.exec(`flatpak install -y flathub ${FLATPAK_APP_ID}`);
903
+ // Use --user flag if we're using user-level Flatpak (no system D-Bus)
904
+ const userFlag = flathubResult.userLevel ? '--user' : '';
905
+ const installResult = await shell.exec(`flatpak install -y ${userFlag} flathub ${FLATPAK_APP_ID}`);
698
906
 
699
907
  if (installResult.code !== 0) {
700
908
  console.error('Failed to install Bambu Studio:', installResult.stderr);
@@ -826,8 +1034,13 @@ async function isInstalled() {
826
1034
  return await isInstalledOnRaspbian();
827
1035
  }
828
1036
 
829
- // Linux platforms (Ubuntu, Debian, WSL, Amazon Linux, Fedora, RHEL): Check Flatpak
1037
+ // Linux platforms (Ubuntu, Debian, WSL, Amazon Linux, Fedora, RHEL): Check AppImage first, then Flatpak
830
1038
  if (['ubuntu', 'debian', 'wsl', 'amazon_linux', 'fedora', 'rhel'].includes(platform.type)) {
1039
+ // Check AppImage installation (preferred)
1040
+ if (isAppImageInstalled()) {
1041
+ return true;
1042
+ }
1043
+ // Fallback to Flatpak check (for legacy installations)
831
1044
  return await isInstalledViaFlatpak();
832
1045
  }
833
1046