Skip to content

fix(desktop): improve AppImage icons and remote environment#2538

Open
mwolson wants to merge 19 commits intopingdotgg:mainfrom
mwolson:fix/linux-secret-store-backend
Open

fix(desktop): improve AppImage icons and remote environment#2538
mwolson wants to merge 19 commits intopingdotgg:mainfrom
mwolson:fix/linux-secret-store-backend

Conversation

@mwolson
Copy link
Copy Markdown
Contributor

@mwolson mwolson commented May 6, 2026

Summary

  • Generates standard hicolor Linux icon sizes for AppImage builds so AppImageLauncher and desktop shells can resolve the installed app icon.
  • Fixes Linux AppImage/Niri remote environment pairing by configuring Electron's Linux startup options before ready, including --password-store, Wayland/X11 app class, and desktop scheme privileges.
  • Hydrates Linux desktop session environment values, including DBUS_SESSION_BUS_ADDRESS, so GNOME Keyring/libsecret is reachable when launching outside GNOME.
  • Hardens SSH remote environment auth by accepting JSON date strings from remote auth APIs and preserving/rolling back saved environment metadata consistently when bearer-token persistence fails.
  • Fixes saved SSH environment removal so deleting an environment cannot resurrect it on restart. Desktop now removes the saved environment record and embedded encrypted token in one atomic persistence operation before the UI clears local state or starts SSH cleanup.

Closes #2331.
Fixes #2539.

Diagnosis

The icon issue came from Linux AppImage builds staging only a single large icon.png. This PR stages a directory of standard icon sizes (16, 22, 24, 32, 48, 64, 128, 256, and 512) and points electron-builder at that directory. CI installs ImageMagick for Linux release builds so those sizes can be generated reliably.

The credential-store failure came from Electron selecting a non-encrypting Linux safeStorage backend when running under desktop environments it does not recognize, such as Niri. The app was also relying on shell/session environment values that may not be present when launched from an AppImage or desktop entry.

This PR moves the Linux Electron setup into the synchronous process bootstrap path so it happens before Electron emits ready, which is required for --password-store and privileged protocol registration to take effect. It also imports enough login/session environment to reach the user's DBus session bus and falls back to /run/user/$UID/bus when appropriate.

While testing the remote flow, two separate persistence issues showed up:

  • Auth responses returned JSON ISO date strings over the SSH HTTP bridge, while the contract expected already-materialized DateTime.Utc values.
  • Removing a saved SSH environment used two separate persistence writes: one fire-and-forget registry rewrite and one secret removal. Those writes could race, letting secret removal read the old record and write it back, so the environment reappeared after restart.

Scope

This is intentionally focused on Linux desktop/AppImage remote environment reliability. It does not change remote server behavior, and SSH process cleanup after removal remains fire-and-forget so the Settings UI does not hang if disconnect stalls.

Test plan

  • bun fmt
  • bun lint
  • bun typecheck
  • bun run test
  • bun run --filter @t3tools/desktop test -- DesktopEarlyElectronStartup DesktopEnvironment ElectronProtocol DesktopShellEnvironment linuxSecretStorage
  • bun run --filter @t3tools/desktop test -- DesktopSavedEnvironments
  • bun run --filter @t3tools/web test -- localApi service.addSavedEnvironment catalog
  • bun run dist:desktop:linux
  • Extracted AppImages and confirmed hicolor icon entries for 16, 22, 24, 32, 48, 64, 128, 256, and 512.
  • Built a local AppImage and launched it under Niri with T3CODE_HOME isolated.
  • Confirmed packaged logs report passwordStore: gnome-libsecret, backend: gnome_libsecret, and encryptionAvailable: true.
  • Installed with Shelly, added remote-game, and ran a trivial task on it.
  • Deleted remote-game, reinstalled/restarted, and confirmed the saved environment did not come back.

Note

Medium Risk
Medium risk: changes Electron pre-ready bootstrap behavior on Linux (command-line switches/protocol privileges) and alters saved-environment credential persistence/error handling, which could affect startup and environment management flows.

Overview
Improves Linux desktop/AppImage reliability by running required Electron configuration before app.ready (scheme privileges, WM class, DBus address fallback, and --password-store selection based on an early-read linuxPasswordStore setting).

Hardens saved-environment persistence across desktop IPC and the web runtime: adds a dedicated removeSavedEnvironment operation, makes secret persistence failures return descriptive remediation errors (GNOME Keyring/KWallet) instead of a silent false, and refactors web-side rollback/removal so environment records and embedded secrets can’t reappear after deletion.

Build/release updates: Linux artifact builds now stage standard hicolor icon sizes using ImageMagick (and CI installs it), and auth contract schemas switch expiresAt decoding to accept ISO strings (DateTimeUtcFromString) with updated SSH remote API tests.

Reviewed by Cursor Bugbot for commit 0f7c19d. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Improve Linux AppImage icons and remote environment configuration for desktop app

  • Generates multiple sized PNG icons (16–512px) via ImageMagick during Linux build staging, replacing the single icon.png with an icons/ directory; installs ImageMagick in CI if absent.
  • Adds Linux password store preference (linuxPasswordStore) to desktop settings, supporting auto, gnome-libsecret, kwallet, kwallet5, and kwallet6; defaults to auto and applies the correct Electron --password-store switch before app ready.
  • Hydrates DBUS_SESSION_BUS_ADDRESS, DISPLAY, XDG_*, and WAYLAND_DISPLAY from the login shell on POSIX systems; falls back to the default runtime bus socket path on Linux when the variable is unset.
  • Adds a removeSavedEnvironment IPC channel end-to-end (preload → IPC handler → DesktopSavedEnvironments → local API → web service), replacing bearer-token removal with persisted-record deletion during environment removal.
  • Fixes expiresAt decoding in auth contract schemas (AuthBearerBootstrapResult, AuthWebSocketTokenResult, AuthSessionState) from DateTimeUtc to DateTimeUtcFromString so ISO string inputs decode correctly.
  • Risk: setSecret now fails with DesktopSavedEnvironmentSecretUnavailableError instead of returning false when encryption is unavailable on Linux, which is a breaking change for callers that checked the boolean return.

Macroscope summarized 0f7c19d.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bff9fbe2-0029-4ac7-af81-34e977cf3b3c

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels May 6, 2026
@mwolson mwolson changed the title fix(desktop): improve Niri AppImage integration fix(desktop): improve Niri AppImage and remote environment May 6, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 6, 2026

Approvability

Verdict: Needs human review

This PR introduces significant new Linux desktop environment handling (password store detection, DBus session bus resolution), a new IPC method for removing saved environments, and schema changes affecting date serialization. An unresolved review comment questions whether the Electron pre-ready layer restructuring maintains correct initialization ordering.

You can customize Macroscope's approvability policy. Learn more.

@mwolson mwolson force-pushed the fix/linux-secret-store-backend branch from dba46b4 to bfc4a7c Compare May 6, 2026 02:10
@mwolson
Copy link
Copy Markdown
Contributor Author

mwolson commented May 6, 2026

Before (missing icon)

Missing icon (works in shelly, doesn't work when appimage is launched directly, or with AppImageLauncher):

image

Before (secret manager)

Error when trying to add environment:

image

@mwolson
Copy link
Copy Markdown
Contributor Author

mwolson commented May 6, 2026

After (icons fix)

Launched appimage directly after chmod +x on it:

image

After (secrets-manager fix)

Screenshot from 2026-05-06 14-07-50-blur

Comment thread apps/web/src/environments/runtime/service.ts
@juliusmarminge
Copy link
Copy Markdown
Member

can you resolve conflcits here?

mwolson added 2 commits May 8, 2026 15:02
…ore-backend

# Conflicts:
#	apps/desktop/src/desktopSettings.test.ts
#	apps/desktop/src/desktopSettings.ts
#	apps/desktop/src/main.ts
@juliusmarminge
Copy link
Copy Markdown
Member

icon looks like this for me on ubuntu?
IMG_5075

@mwolson mwolson changed the title fix(desktop): improve Niri AppImage and remote environment fix(desktop): improve AppImage icons and remote environment May 9, 2026
@mwolson mwolson changed the title fix(desktop): improve AppImage icons and remote environment fix(desktop): harden Linux remote environments May 9, 2026
@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels May 9, 2026
@mwolson mwolson changed the title fix(desktop): harden Linux remote environments fix(desktop): improve AppImage icons and remote environment May 9, 2026
Comment thread apps/desktop/src/app/DesktopEarlyElectronStartup.ts
Comment thread apps/desktop/src/app/DesktopEarlyElectronStartup.ts Outdated
Copy link
Copy Markdown
Member

@juliusmarminge juliusmarminge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested on ubuntu and it works.

desktop app could use some cleanup to follow effect best practices more. i just cleaned it up a bunch so don't wanna move away directly

Comment thread apps/desktop/src/app/DesktopEnvironment.ts Outdated
registerDesktopSchemePrivilegesSync,
).pipe(Effect.withSpan("desktop.electron.protocol.registerSchemePrivileges"));

export const layerSchemePrivileges = Layer.effectDiscard(registerDesktopSchemePrivileges);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the way the layers were setup this ran before electron setup. not sure if you changed some layer structure so that's no longer the case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that ordering is still preserved. main.ts now calls configureElectronBeforeReady() synchronously at module startup, before building the Effect runtime/layers and before NodeRuntime.runMain.

I kept only the pre-ready Electron requirements there: registerSchemesAsPrivileged plus the Linux command-line switches. The file protocol handler still registers later after whenReady.

@mwolson mwolson requested a review from juliusmarminge May 9, 2026 20:57
@mwolson
Copy link
Copy Markdown
Contributor Author

mwolson commented May 9, 2026

@juliusmarminge fixed the issues you mentioned and re-smoked it on my end. If you don't want the AGENTS.md changes around Effect (or want different content there) let me know.

@juliusmarminge
Copy link
Copy Markdown
Member

I can look at it in a bit, but there's nothing that says that just cause it should run before electron it must run synchronously at module scope? The layer graph before was setup so that the protocol was the first thing that executed before the main effect program? Was there an issue with that? We create the electron app inside the effect program ye?

Comment thread apps/desktop/src/shell/DesktopShellEnvironment.ts
@mwolson
Copy link
Copy Markdown
Contributor Author

mwolson commented May 9, 2026

I can look at it in a bit, but there's nothing that says that just cause it should run before electron it must run synchronously at module scope? The layer graph before was setup so that the protocol was the first thing that executed before the main effect program? Was there an issue with that? We create the electron app inside the effect program ye?

Good points; I moved this back into the Effect startup graph as an explicit first layer with Layer.flatMap, and isolated the synchronous process/fs reads in a small pre-ready platform adapter. That keeps the Electron pre-ready ordering intact without doing the setup at module scope. (Also updated AGENTS.md guidance to match.)

Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6c34906. Configure here.

Comment thread apps/desktop/src/app/DesktopEarlyElectronStartup.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Niri AppImage cannot save remote environment credentials [Bug]: AppImage installed by AppImageLauncher lacks usable Linux desktop icon

2 participants