Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ai.opencode.opencode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ modules:
- mv usr/share/applications usr/share/icons /app/share
- desktop-file-edit --set-key Exec --set-value "run.sh %U" /app/share/applications/ai.opencode.desktop.desktop
- patch-electron-desktop-filename /app/main/resources/app.asar
- python3 patch-opencode-asar.py /app/main/resources/app.asar
- install -Dm644 usr/share/metainfo/ai.opencode.desktop.metainfo.xml /app/share/metainfo/ai.opencode.opencode.metainfo.xml
- install -Dm755 -t /app/bin run.sh
sources:
Expand Down Expand Up @@ -86,3 +87,5 @@ modules:
- zypak-wrapper.sh /app/main/ai.opencode.desktop "$@"
- type: file
path: metainfo.patch
- type: file
path: patch-opencode-asar.py
54 changes: 54 additions & 0 deletions patch-opencode-asar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
"""
Disable the OpenCode Electron app's self-updater inside a Flatpak, in place.

Sets UPDATER_ENABLED = false in out/main/index.js inside app.asar. This is a
same-length text replacement, so the asar binary is patched directly without
extract/repack (which would drop the app.asar.unpacked native-module
metadata). The asar header, all offsets, and the unpacked entries are
preserved byte-for-byte.

Flatpak provides updates via the OS updater (GNOME Software / KDE Discover /
flatpak update); the electron-updater self-updater can't install into the
read-only /app anyway, so it must be disabled. Upstream issue:
https://github.com/anomalyco/opencode/issues/39670

Usage: patch-opencode-asar.py <path/to/app.asar>
"""
import os
import sys


def main() -> None:
if len(sys.argv) != 2:
print(f"usage: {sys.argv[0]} <path/to/app.asar>", file=sys.stderr)
sys.exit(2)

asar_path = sys.argv[1]
if not os.environ.get("FLATPAK_ID"):
print("FLATPAK_ID is not set; expected to be run inside flatpak-builder", file=sys.stderr)
sys.exit(1)

with open(asar_path, "rb") as f:
data = f.read()

# out/main/index.js: `const UPDATER_ENABLED = app.isPackaged && CHANNEL !== "dev";`
# Replace the RHS with `false` plus a comment, padded to the same byte
# length so the asar layout (offsets, unpacked entries) is unchanged.
old = b'app.isPackaged && CHANNEL !== "dev"'
new = b'false/*packed&&CHANNEL!=="dev"*/'.ljust(len(old), b" ")
if len(old) != len(new):
raise SystemExit(f"length mismatch: {len(old)} vs {len(new)}")
count = data.count(old)
if count != 1:
raise SystemExit(f"expected exactly 1 occurrence of UPDATER_ENABLED, found {count}")
data = data.replace(old, new, 1)

with open(asar_path, "wb") as f:
f.write(data)

print(f"patched {asar_path}: UPDATER_ENABLED = false")


if __name__ == "__main__":
main()