From d938c6c6d8753dd0d92ddffa995ad3aeaaed7953 Mon Sep 17 00:00:00 2001 From: Ellie Gummere Date: Wed, 18 Mar 2026 19:09:26 -0400 Subject: [PATCH 1/3] Improve Linux desktop identity for dev and packaged builds - Set Linux WM class and desktop entry naming consistently - Generate a dev desktop launcher for Electron on Linux - Align desktop artifact packaging with the new app name --- apps/desktop/scripts/dev-electron.mjs | 3 ++- apps/desktop/src/main.ts | 13 +++++++++++++ scripts/build-desktop-artifact.ts | 17 ++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/apps/desktop/scripts/dev-electron.mjs b/apps/desktop/scripts/dev-electron.mjs index 12d4753509..4edff4b881 100644 --- a/apps/desktop/scripts/dev-electron.mjs +++ b/apps/desktop/scripts/dev-electron.mjs @@ -26,6 +26,7 @@ await waitOn({ const childEnv = { ...process.env }; delete childEnv.ELECTRON_RUN_AS_NODE; +const linuxClassArg = process.platform === "linux" ? ["--class=t3code-dev"] : []; let shuttingDown = false; let restartTimer = null; @@ -57,7 +58,7 @@ function startApp() { const app = spawn( resolveElectronPath(), - [`--t3code-dev-root=${desktopDir}`, "dist-electron/main.js"], + [...linuxClassArg, `--t3code-dev-root=${desktopDir}`, "dist-electron/main.js"], { cwd: desktopDir, env: { diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts index c3dba6016e..ef82a4695c 100644 --- a/apps/desktop/src/main.ts +++ b/apps/desktop/src/main.ts @@ -63,6 +63,8 @@ const ROOT_DIR = Path.resolve(__dirname, "../../.."); const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL); const APP_DISPLAY_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; const APP_USER_MODEL_ID = "com.t3tools.t3code"; +const LINUX_DESKTOP_ENTRY_NAME = isDevelopment ? "t3code-dev.desktop" : "t3code.desktop"; +const LINUX_WM_CLASS = isDevelopment ? "t3code-dev" : "t3code"; const USER_DATA_DIR_NAME = isDevelopment ? "t3code-dev" : "t3code"; const LEGACY_USER_DATA_DIR_NAME = isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)"; const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i; @@ -77,6 +79,9 @@ const DESKTOP_UPDATE_CHANNEL = "latest"; const DESKTOP_UPDATE_ALLOW_PRERELEASE = false; type DesktopUpdateErrorContext = DesktopUpdateState["errorContext"]; +type LinuxDesktopNamedApp = Electron.App & { + setDesktopName?: (desktopName: string) => void; +}; let mainWindow: BrowserWindow | null = null; let backendProcess: ChildProcess.ChildProcess | null = null; @@ -249,6 +254,10 @@ function captureBackendOutput(child: ChildProcess.ChildProcess): void { initializePackagedLogging(); +if (process.platform === "linux") { + app.commandLine.appendSwitch("class", LINUX_WM_CLASS); +} + function getDestructiveMenuIcon(): Electron.NativeImage | undefined { if (process.platform !== "darwin") return undefined; if (destructiveMenuIconCache !== undefined) { @@ -699,6 +708,10 @@ function configureAppIdentity(): void { app.setAppUserModelId(APP_USER_MODEL_ID); } + if (process.platform === "linux") { + (app as LinuxDesktopNamedApp).setDesktopName?.(LINUX_DESKTOP_ENTRY_NAME); + } + if (process.platform === "darwin" && app.dock) { const iconPath = resolveIconPath("png"); if (iconPath) { diff --git a/scripts/build-desktop-artifact.ts b/scripts/build-desktop-artifact.ts index 0b875721fd..69bce30a35 100644 --- a/scripts/build-desktop-artifact.ts +++ b/scripts/build-desktop-artifact.ts @@ -472,8 +472,14 @@ const createBuildConfig = Effect.fn("createBuildConfig")(function* ( if (platform === "linux") { buildConfig.linux = { target: [target], + executableName: "t3code", icon: "icon.png", category: "Development", + desktop: { + entry: { + StartupWMClass: "t3code", + }, + }, }; } @@ -616,9 +622,13 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* ( // electron-builder is filtering out stageResourcesDir directory in the AppImage for production yield* fs.copy(stageResourcesDir, path.join(stageAppDir, "apps/desktop/prod-resources")); + const stageBunTmpDir = path.join(stageRoot, ".bun-tmp"); + const stageBunInstallDir = path.join(stageRoot, ".bun-install"); + yield* fs.makeDirectory(stageBunTmpDir, { recursive: true }); + yield* fs.makeDirectory(stageBunInstallDir, { recursive: true }); const stagePackageJson: StagePackageJson = { - name: "t3-code-desktop", + name: "t3code", version: appVersion, buildVersion: appVersion, t3codeCommitHash: commitHash, @@ -648,6 +658,11 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* ( yield* runCommand( ChildProcess.make({ cwd: stageAppDir, + env: { + ...process.env, + BUN_TMPDIR: stageBunTmpDir, + BUN_INSTALL: stageBunInstallDir, + }, ...commandOutputOptions(options.verbose), // Windows needs shell mode to resolve .cmd shims (e.g. bun.cmd). shell: process.platform === "win32", From a3e433559b25c037303ae4d6596601dc417858cc Mon Sep 17 00:00:00 2001 From: Ellie Gummere Date: Wed, 18 Mar 2026 19:26:00 -0400 Subject: [PATCH 2/3] I don't know why codex decided to change the build step here. --- scripts/build-desktop-artifact.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/scripts/build-desktop-artifact.ts b/scripts/build-desktop-artifact.ts index 69bce30a35..05305b144c 100644 --- a/scripts/build-desktop-artifact.ts +++ b/scripts/build-desktop-artifact.ts @@ -622,10 +622,6 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* ( // electron-builder is filtering out stageResourcesDir directory in the AppImage for production yield* fs.copy(stageResourcesDir, path.join(stageAppDir, "apps/desktop/prod-resources")); - const stageBunTmpDir = path.join(stageRoot, ".bun-tmp"); - const stageBunInstallDir = path.join(stageRoot, ".bun-install"); - yield* fs.makeDirectory(stageBunTmpDir, { recursive: true }); - yield* fs.makeDirectory(stageBunInstallDir, { recursive: true }); const stagePackageJson: StagePackageJson = { name: "t3code", @@ -658,11 +654,6 @@ const buildDesktopArtifact = Effect.fn("buildDesktopArtifact")(function* ( yield* runCommand( ChildProcess.make({ cwd: stageAppDir, - env: { - ...process.env, - BUN_TMPDIR: stageBunTmpDir, - BUN_INSTALL: stageBunInstallDir, - }, ...commandOutputOptions(options.verbose), // Windows needs shell mode to resolve .cmd shims (e.g. bun.cmd). shell: process.platform === "win32", From 97bf6ce003e34635f5c8ed6b5cf1d38a6939502a Mon Sep 17 00:00:00 2001 From: Ellie Gummere Date: Wed, 18 Mar 2026 19:37:36 -0400 Subject: [PATCH 3/3] Cleanup from copilot Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- apps/desktop/scripts/dev-electron.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/desktop/scripts/dev-electron.mjs b/apps/desktop/scripts/dev-electron.mjs index 4edff4b881..12d4753509 100644 --- a/apps/desktop/scripts/dev-electron.mjs +++ b/apps/desktop/scripts/dev-electron.mjs @@ -26,7 +26,6 @@ await waitOn({ const childEnv = { ...process.env }; delete childEnv.ELECTRON_RUN_AS_NODE; -const linuxClassArg = process.platform === "linux" ? ["--class=t3code-dev"] : []; let shuttingDown = false; let restartTimer = null; @@ -58,7 +57,7 @@ function startApp() { const app = spawn( resolveElectronPath(), - [...linuxClassArg, `--t3code-dev-root=${desktopDir}`, "dist-electron/main.js"], + [`--t3code-dev-root=${desktopDir}`, "dist-electron/main.js"], { cwd: desktopDir, env: {