opencode-desktop: fix empty window and missing desktop entry
- Patch prebuilt .node files (node-pty, @parcel/watcher) with
autoPatchelfHook so they can dlopen libstdc++. Without this, the
sidecar exits on startup because glibc does not consult electron's
DT_RUNPATH transitively for dlopened libraries, and the renderer
shows an empty window with no backend.
- Ignore unresolved libc.musl-* SONAMEs in the prebuilt .node files
so autoPatchelfHook accepts them on glibc systems. The musl-targeting
bindings are dead code at runtime on the host's libc anyway.
- Pass --config.asarUnpack='**/*.node' to electron-builder so every
prebuilt native binding lands on the filesystem (not embedded in
app.asar where dlopen cannot find them).
- Disable the auto-updater at source via postPatch. With the package
now correctly identifying as packaged, the updater would otherwise
try to download and run upstream binaries that aren't patched for
Nix.
- Generate a .desktop entry via makeDesktopItem. electron-builder
--dir skips the deb/AppImage/rpm stages that normally produce one,
so copyDesktopItems on its own was a no-op.
- Install icons into share/icons/hicolor/{30,32,44,64,71,89,107,128,
142,150,284,310}x*/apps/ mirroring upstream's deb layout, so desktop
environments find them. Previously a single bare PNG at
share/icons/opencode-desktop.png (not part of any icon theme path).
- Set ELECTRON_FORCE_IS_PACKAGED=1 in the wrapper. With
--inherit-argv0, Electron's app.isPackaged heuristic returns false,
which routes the app to the dev XDG dir and breaks the WM-class
match with StartupWMClass=OpenCode.
- On darwin, symlink Contents/MacOS/OpenCode into $out/bin and set
mainProgram accordingly so lib.getExe works on both platforms.
- Drop the unused opencode-cli sidecar copy; the bundled chunk hosts
its own server and never spawns the CLI.
Assisted-by: OpenCode:claude-opus-4-7
Co-authored-by: typedrat <alexis@typedr.at>
This commit is contained in:
committed by
superherointj
parent
99b5236774
commit
f6fc501041
@@ -1,12 +1,15 @@
|
||||
{
|
||||
autoPatchelfHook,
|
||||
bun,
|
||||
copyDesktopItems,
|
||||
electron_41,
|
||||
lib,
|
||||
makeBinaryWrapper,
|
||||
makeDesktopItem,
|
||||
models-dev,
|
||||
nodejs,
|
||||
opencode,
|
||||
stdenv,
|
||||
stdenvNoCC,
|
||||
writableTmpDirAsHomeHook,
|
||||
|
||||
@@ -30,9 +33,20 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
nodejs # for patchShebangs node_modules
|
||||
makeBinaryWrapper
|
||||
writableTmpDirAsHomeHook
|
||||
]
|
||||
++ lib.optionals stdenvNoCC.hostPlatform.isLinux [
|
||||
autoPatchelfHook
|
||||
copyDesktopItems
|
||||
];
|
||||
|
||||
buildInputs = lib.optionals stdenvNoCC.hostPlatform.isLinux [
|
||||
(lib.getLib stdenv.cc.cc)
|
||||
];
|
||||
|
||||
# The musl prebuilts ship libc.musl-*.so.1 SONAMEs that autoPatchelfHook can't
|
||||
# resolve on glibc systems. They aren't loaded at runtime on the host libc anyway.
|
||||
autoPatchelfIgnoreMissingDeps = [ "libc.musl-*.so.*" ];
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
env = {
|
||||
@@ -42,6 +56,13 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
OPENCODE_DISABLE_MODELS_FETCH = true;
|
||||
};
|
||||
|
||||
postPatch = ''
|
||||
# The auto-updater would try to download and run an upstream binary that
|
||||
# isn't patched for Nix. Disable it at source.
|
||||
substituteInPlace packages/desktop/src/main/constants.ts \
|
||||
--replace-fail 'app.isPackaged && CHANNEL !== "dev"' 'false'
|
||||
'';
|
||||
|
||||
configurePhase = ''
|
||||
runHook preConfigure
|
||||
|
||||
@@ -69,10 +90,6 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
# Build with electron-vite
|
||||
node_modules/.bin/electron-vite build
|
||||
|
||||
# Copy opencode CLI as sidecar
|
||||
sidecar_name="opencode-cli"
|
||||
install -D ${lib.getExe opencode} "resources/$sidecar_name"
|
||||
|
||||
# Package with electron-builder (unpacked directory mode)
|
||||
cp -r "${electron.dist}" $HOME/.electron-dist
|
||||
chmod -R u+w $HOME/.electron-dist
|
||||
@@ -80,53 +97,72 @@ stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
node_modules/.bin/electron-builder --dir \
|
||||
--config=electron-builder.config.ts \
|
||||
--config.electronDist="$HOME/.electron-dist" \
|
||||
--config.electronVersion=${electron.version}
|
||||
--config.electronVersion=${electron.version} \
|
||||
--config.asarUnpack='**/*.node'
|
||||
|
||||
cd ../..
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
''
|
||||
+ lib.optionalString stdenvNoCC.hostPlatform.isDarwin ''
|
||||
mkdir -p $out/Applications
|
||||
mv packages/desktop/dist/mac-*/OpenCode.app "$out/Applications/OpenCode.app"
|
||||
''
|
||||
+ lib.optionalString stdenvNoCC.hostPlatform.isLinux ''
|
||||
mkdir -p $out/opt/opencode-desktop
|
||||
${
|
||||
if stdenvNoCC.hostPlatform.isAarch64 then
|
||||
''
|
||||
appDir="packages/desktop/dist/linux-arm64-unpacked"
|
||||
''
|
||||
else
|
||||
''
|
||||
appDir="packages/desktop/dist/linux-unpacked"
|
||||
''
|
||||
}
|
||||
[ -d "$appDir" ] || { echo "no electron-builder output dir found: $appDir"; exit 1; }
|
||||
cp -r "$appDir/resources" $out/opt/opencode-desktop/
|
||||
desktopItems = lib.optional stdenvNoCC.hostPlatform.isLinux (makeDesktopItem {
|
||||
name = "opencode-desktop";
|
||||
desktopName = "OpenCode";
|
||||
exec = "opencode-desktop %U";
|
||||
icon = "opencode-desktop";
|
||||
startupWMClass = "OpenCode";
|
||||
categories = [ "Development" ];
|
||||
mimeTypes = [ "x-scheme-handler/opencode" ];
|
||||
});
|
||||
|
||||
install -Dm644 packages/desktop/resources/icons/icon.png $out/share/icons/opencode-desktop.png
|
||||
installPhase =
|
||||
let
|
||||
appDir = if stdenvNoCC.hostPlatform.isAarch64 then "linux-arm64-unpacked" else "linux-unpacked";
|
||||
in
|
||||
lib.concatLines [
|
||||
''
|
||||
runHook preInstall
|
||||
''
|
||||
(lib.optionalString stdenvNoCC.hostPlatform.isDarwin ''
|
||||
mkdir -p $out/Applications $out/bin
|
||||
mv packages/desktop/dist/mac-*/OpenCode.app "$out/Applications/OpenCode.app"
|
||||
ln -s "$out/Applications/OpenCode.app/Contents/MacOS/OpenCode" $out/bin/OpenCode
|
||||
'')
|
||||
(lib.optionalString stdenvNoCC.hostPlatform.isLinux ''
|
||||
mkdir -p $out/opt/opencode-desktop
|
||||
appDir="packages/desktop/dist/${appDir}"
|
||||
[ -d "$appDir" ] || { echo "no electron-builder output dir found: $appDir"; exit 1; }
|
||||
cp -r "$appDir/resources" $out/opt/opencode-desktop/
|
||||
|
||||
makeWrapper ${lib.getExe electron} $out/bin/opencode-desktop \
|
||||
--inherit-argv0 \
|
||||
--add-flags $out/opt/opencode-desktop/resources/app.asar \
|
||||
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true --wayland-text-input-version=3}}" \
|
||||
--add-flags ${lib.escapeShellArg commandLineArgs}
|
||||
''
|
||||
+ ''
|
||||
runHook postInstall
|
||||
'';
|
||||
for size in 32 64 128; do
|
||||
install -Dm644 \
|
||||
packages/desktop/resources/icons/''${size}x''${size}.png \
|
||||
$out/share/icons/hicolor/''${size}x''${size}/apps/opencode-desktop.png
|
||||
done
|
||||
for size in 30 44 71 89 107 142 150 284 310; do
|
||||
install -Dm644 \
|
||||
packages/desktop/resources/icons/Square''${size}x''${size}Logo.png \
|
||||
$out/share/icons/hicolor/''${size}x''${size}/apps/opencode-desktop.png
|
||||
done
|
||||
|
||||
makeWrapper ${lib.getExe electron} $out/bin/opencode-desktop \
|
||||
--inherit-argv0 \
|
||||
--set ELECTRON_FORCE_IS_PACKAGED 1 \
|
||||
--add-flags $out/opt/opencode-desktop/resources/app.asar \
|
||||
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true --wayland-text-input-version=3}}" \
|
||||
--add-flags ${lib.escapeShellArg commandLineArgs}
|
||||
'')
|
||||
''
|
||||
runHook postInstall
|
||||
''
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "AI coding agent desktop client";
|
||||
homepage = "https://opencode.ai";
|
||||
inherit (opencode.meta) platforms;
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = "OpenCode";
|
||||
mainProgram = if stdenvNoCC.hostPlatform.isDarwin then "OpenCode" else "opencode-desktop";
|
||||
maintainers = with lib.maintainers; [ xiaoxiangmoe ];
|
||||
};
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user