feat: add Linux desktop installation support - #19
Closed
eltonacosta wants to merge 4 commits into
Closed
eltonacosta wants to merge 4 commits into
eltonacosta wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved installation, platform handling, test portability, and Linux CI issues remain.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds Linux AppDir installation and launch support for ZCode Desktop Extensions while preserving Windows behavior.
Changes:
- Adds platform-specific paths, executables, process detection, and launch handling.
- Adds Linux desktop-entry integration and installation-path persistence.
- Updates native resource preservation, builds, updater behavior, and cross-platform tests.
File summaries
| File | Reviewed change |
|---|---|
tests/task-service.test.ts |
Uses portable workspace paths. |
tests/installer.test.ts |
Covers platform layouts and unpacked resources. |
tests/host-updater.test.ts |
Adds portable updater fixtures. |
tests/host-update-apply.test.ts |
Tests platform-specific launch paths. |
tests/extension-updater.test.ts |
Updates portable archive handling. |
src/shared/schemas.ts |
Stores optional desktop-entry state. |
src/shared/constants.ts |
Centralizes platform paths and executables. |
src/host/host-updater.ts |
Handles platform-aware host updates. |
src/host/bootstrap.ts |
Launches the platform-specific guardian. |
src/cli/shortcut.ts |
Adds Linux desktop-entry integration. |
src/cli/launcher.ts |
Launches the platform-specific helper. |
src/cli/installer.ts |
Adds Linux installation and resource preservation. |
src/cli/index.ts |
Persists installation paths and forwards arguments. |
src/cli/host-update-apply.ts |
Applies platform-aware update launches. |
src/cli/guardian.ts |
Performs platform-aware process checks. |
scripts/build.ts |
Builds platform-specific executables. |
Review details
Suppressed comments (5)
scripts/build.ts:58
- The new Linux-specific build path is not exercised by CI:
.github/workflows/ci.ymlstill runs only onwindows-latest. That leaves the ELF build, Linux process detection, desktop-entry integration, and--no-sandboxlaunch path without automated regression coverage; add a Linux job or matrix entry for the check suite.
"build", path.join(root, "src", "cli", "index.ts"), "--compile", "--minify", "--sourcemap", "--outfile", path.join(bin, ZDP_EXECUTABLE),
]);
const launcherArgs = ["build", path.join(root, "src", "cli", "launcher.ts"), "--compile", "--minify"];
if (process.platform === "win32") launcherArgs.push("--windows-hide-console");
launcherArgs.push("--outfile", path.join(bin, ZDP_LAUNCHER_EXECUTABLE));
await runBunBuild(launcherArgs);
if (process.platform !== "win32") await Promise.all([
chmod(path.join(bin, ZDP_EXECUTABLE), 0o755),
chmod(path.join(bin, ZDP_LAUNCHER_EXECUTABLE), 0o755),
src/cli/index.ts:10
--zcodeis persisted and reused exactly as supplied, so a relative value such as--zcode ./ZCodeis stored relative to the install command's working directory. The launcher later startszdpwith the ZDP root as its cwd, making the same value resolve to a different directory (andlaunchcan try to execute<root>/ZCode/zcodefrom<root>/ZCode). Normalize the ZCode path to an absolute path before storing and using it.
const zcodeRoot = valueAfter("--zcode") ?? installed?.zcodeRoot ?? DEFAULT_ZCODE_ROOT;
src/cli/shortcut.ts:16
- If
XDG_DATA_HOMEis set to an empty string, nullish coalescing selects""and this produces the relative pathapplications/zcode.desktopinstead of the XDG fallback. Empty is treated like unset for this variable, so use a truthy/trimmed check before falling back to~/.local/share.
if (process.platform !== "win32") return path.join(process.env.XDG_DATA_HOME ?? path.join(os.homedir(), ".local", "share"), "applications", "zcode.desktop");
src/host/host-updater.ts:85
- This deliberately makes Linux host updates non-installable, but the renderer uses
installable === falseto display that the installation is a development checkout. A packaged writable Linux AppDir will therefore show a false explanation for every available host update; expose a platform-specific reason/status or update the UI copy for Linux.
const installable = process.platform === "win32" && await this.#installedManifest().then(() => true).catch(() => false);
src/shared/constants.ts:16
- These conditionals treat every non-Windows platform as Linux. On macOS or another unsupported platform this selects
zdp/zcode, the Linux install directory, and--no-sandbox, whileisZCodeRunningexplicitly returns false there, so commands can silently attempt an invalid Linux installation instead of rejecting the platform. Use an explicit Linux branch and fail fast for unsupported platforms.
export const ZDP_EXECUTABLE = process.platform === "win32" ? "zdp.exe" : "zdp";
export const ZDP_LAUNCHER_EXECUTABLE = process.platform === "win32" ? "zdp-launcher.exe" : "zdp-launcher";
export const DEFAULT_ZCODE_ROOT = process.platform === "win32"
? path.join(process.env.LOCALAPPDATA ?? "C:\\Users\\me\\AppData\\Local", "Programs", "ZCode")
: path.join(os.homedir(), ".local", "opt", "ZCode");
export function getZCodeLayout(root: string) {
const electronExecutable = path.join(root, process.platform === "win32" ? "ZCode.exe" : "zcode");
- Files reviewed: 16/16 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const child = Bun.spawn(["powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", command], { | ||
| const command = process.platform === "win32" | ||
| ? ["powershell.exe", "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", `Compress-Archive -LiteralPath ${quote(source)} -DestinationPath ${quote(destination)} -CompressionLevel Optimal -Force`] | ||
| : ["bsdtar", "-a", "-cf", destination, path.basename(source)]; |
Comment on lines
+55
to
+59
| const existing = await readFile(shortcutPath, "utf8").catch(() => "[Desktop Entry]\nName=ZCode\nType=Application\nTerminal=false\nCategories=Development;\nMimeType=x-scheme-handler/zcode;\n"); | ||
| const exec = `Exec=${quoteDesktopValue(launcher)} %U`; | ||
| const tryExec = `TryExec=${launcher}`; | ||
| let contents = /^Exec=.*$/m.test(existing) ? existing.replace(/^Exec=.*$/m, exec) : `${existing.trimEnd()}\n${exec}\n`; | ||
| contents = /^TryExec=.*$/m.test(contents) ? contents.replace(/^TryExec=.*$/m, tryExec) : `${contents.trimEnd()}\n${tryExec}\n`; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds Linux support to the ZCode Desktop Extensions host while preserving the existing Windows installation and update behavior.
The implementation supports ZCode running from a writable AppDir extracted from the official AppImage. Platform-specific paths and executable names are centralized so Windows continues to use the existing
.exebinaries, Start Menu shortcut integration, and process detection.Changes
zdpandzdp-launcheras executable ELF binaries on Linux.zdp.exe,zdp-launcher.exe, andZCode.exebehavior on Windows./proc..desktopintegration while preserving the original desktop entry for uninstall.app.asar.unpackedtogether withapp.asar.Windows Compatibility
Windows behavior remains unchanged:
%LOCALAPPDATA%\Programs\ZCode.ZCode.exe,zdp.exe, andzdp-launcher.exe..lnkintegration continues to use PowerShell andWScript.Shell.tasklist.exe.--windows-hide-consoleremains enabled for the Windows launcher build.Linux Installation Model
AppImages are mounted read-only and cannot be patched in place. Linux installation therefore targets a writable AppDir extracted from the official ZCode AppImage.
The default Linux paths are:
~/.local/opt/ZCode$XDG_DATA_HOME/applications/zcode.desktop, falling back to~/.local/share/applications/zcode.desktopThe original AppImage can remain installed as an unmodified recovery source.
Host self-update is intentionally marked non-installable on Linux until platform-specific release artifacts and feeds are available. Extension updates remain unaffected.
Validation
Tested on Linux x86-64 with ZCode 3.11.2 extracted from the official AppImage.