mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-07-06 17:13:24 -05:00
The Electron app sets its application ID to 'ai.opencode.desktop' via app.setAppUserModelId(), but the nixpkgs desktop file used name='opencode-desktop' with StartupWMClass='OpenCode'. This mismatch caused desktop environments (especially ChromeOS Crostini/sommelier-rs) to fail associating the running window with the launcher icon. Fix both values to match the app_id set by the upstream Electron app, aligning with the electron-builder config which already generates the desktop file as 'ai.opencode.desktop.desktop' with the correct StartupWMClass. Assisted-by: opencode <model-gateway/opencode/deepseek-v4-flash-free>
186 lines
5.9 KiB
Nix
186 lines
5.9 KiB
Nix
{
|
|
autoPatchelfHook,
|
|
bun,
|
|
copyDesktopItems,
|
|
electron_41,
|
|
lib,
|
|
makeBinaryWrapper,
|
|
makeDesktopItem,
|
|
models-dev,
|
|
nodejs,
|
|
opencode,
|
|
stdenv,
|
|
stdenvNoCC,
|
|
writableTmpDirAsHomeHook,
|
|
|
|
commandLineArgs ? "",
|
|
}:
|
|
|
|
let
|
|
electron = electron_41;
|
|
in
|
|
stdenvNoCC.mkDerivation (finalAttrs: {
|
|
pname = "opencode-desktop";
|
|
inherit (opencode)
|
|
version
|
|
src
|
|
node_modules
|
|
patches
|
|
;
|
|
|
|
nativeBuildInputs = [
|
|
bun
|
|
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 = {
|
|
ELECTRON_SKIP_BINARY_DOWNLOAD = "1";
|
|
OPENCODE_CHANNEL = "prod";
|
|
MODELS_DEV_API_JSON = "${models-dev}/dist/_api.json";
|
|
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'
|
|
|
|
# Relax Bun version check to be a warning instead of an error
|
|
substituteInPlace packages/script/src/index.ts \
|
|
--replace-fail 'throw new Error(`This script requires bun@''${expectedBunVersionRange}' \
|
|
'console.warn(`Warning: This script requires bun@''${expectedBunVersionRange}'
|
|
'';
|
|
|
|
configurePhase = ''
|
|
runHook preConfigure
|
|
|
|
cp -R ${finalAttrs.node_modules}/. .
|
|
patchShebangs node_modules
|
|
patchShebangs packages/*/node_modules
|
|
|
|
runHook postConfigure
|
|
'';
|
|
|
|
preBuild = lib.optionalString stdenvNoCC.hostPlatform.isDarwin ''
|
|
# Patch electron-builder to skip code signing on macOS.
|
|
# The nix sandbox on public Darwin builders cannot spawn
|
|
# `security find-identity` — trying gives spawn EPERM.
|
|
# We patch the compiled JS to make getValidIdentities a no-op.
|
|
for f in $(find node_modules -path "*/app-builder-lib/out/codeSign/macCodeSign.js" -type f 2>/dev/null); do
|
|
substituteInPlace "$f" \
|
|
--replace-fail "async function getValidIdentities" \
|
|
"async function getValidIdentities() { return []; }; async function getValidIdentities_DISABLED"
|
|
done
|
|
'';
|
|
|
|
buildPhase = ''
|
|
runHook preBuild
|
|
|
|
# Build the opencode node bundle (needed by the desktop sidecar)
|
|
cd packages/opencode
|
|
bun --bun ./script/build-node.ts --skip-install
|
|
cd ../..
|
|
|
|
# Prepare desktop app
|
|
cd packages/desktop
|
|
|
|
# Copy prod icons
|
|
cp -R icons/prod resources/icons
|
|
|
|
# Build with electron-vite
|
|
node_modules/.bin/electron-vite build
|
|
|
|
# Package with electron-builder (unpacked directory mode)
|
|
cp -r "${electron.dist}" $HOME/.electron-dist
|
|
chmod -R u+w $HOME/.electron-dist
|
|
|
|
node_modules/.bin/electron-builder --dir \
|
|
--config=electron-builder.config.ts \
|
|
--config.electronDist="$HOME/.electron-dist" \
|
|
--config.electronVersion=${electron.version} \
|
|
--config.asarUnpack='**/*.node' \
|
|
${lib.optionalString stdenvNoCC.hostPlatform.isDarwin "--config.mac.identity=null"}
|
|
|
|
cd ../..
|
|
|
|
runHook postBuild
|
|
'';
|
|
|
|
desktopItems = lib.optional stdenvNoCC.hostPlatform.isLinux (makeDesktopItem {
|
|
name = "ai.opencode.desktop";
|
|
desktopName = "OpenCode";
|
|
exec = "opencode-desktop %U";
|
|
icon = "opencode-desktop";
|
|
startupWMClass = "ai.opencode.desktop";
|
|
categories = [ "Development" ];
|
|
mimeTypes = [ "x-scheme-handler/opencode" ];
|
|
});
|
|
|
|
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/
|
|
|
|
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 = if stdenvNoCC.hostPlatform.isDarwin then "OpenCode" else "opencode-desktop";
|
|
maintainers = with lib.maintainers; [ xiaoxiangmoe ];
|
|
};
|
|
})
|