Adds an Electron install check that repairs incomplete or wrong-architecture binaries
Runs the check during root postinstall and before electron dev startup
Adds tests and docs for the new ensure:electron workflow
The SQLite write into OpenCode's database was the only consumer of
better-sqlite3 in the repository. Everything that existed to ship its native
binary went with it:
- the dependency in @openchamber/web and @openchamber/electron
- the afterPack hook staging better_sqlite3.node into app.asar.unpacked
- a dedicated @electron/rebuild pass (onlyModules) and its binary assertion,
so desktop packaging now runs one native rebuild instead of two
- the bundler external entry and the AppImage required-native-module check
Desktop packaging, the AppImage verification tests, and the extension bundle
were re-validated after a clean reinstall, so no stale module could satisfy a
missed import.
AppImage exports ARGV0 into the process environment. zsh treats that as
argv[0] for every external command, which broke Python venv detection in
the integrated terminal and managed OpenCode sessions.
Clear ARGV0 in Electron before login-shell probing, refuse to re-apply it
from shell snapshots, and strip it from terminal PTY and managed OpenCode
launch environments.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* perf: optimize session loading and startup
* fix(chat): stabilize history prepend virtualization
* perf: unblock first session open from startup network contention
Opening the first session after app start waited seconds for its message
fetch. Three independent contributors, each measured via CDP network
capture and Chromium net-log against the packaged desktop app:
- The active-session watchdog fired an uncapped per-directory status poll
and child-session discovery burst at startup, and other subsystems
(git checks, global session pages, command/skill discovery) fanned out
alongside it, saturating the browser's ~6 HTTP/1.1 sockets per origin.
Add a shared background-network gate (concurrency 3) and route the
watchdog, poll-shaped git reads (also priority: low), global session
pages, command/skill loads, and the background update check through it.
- The packaged renderer is cross-origin to the loopback backend, so every
API call needs a CORS preflight; a few slow OpenCode-proxied requests
held the whole pool while preflights and interactive traffic queued
behind them. Lift Chromium's per-host connection cap for loopback via
ignore-connections-limit in the Electron shell.
- OpenCode initializes each directory lazily on its first request, so the
first click paid that cost interactively. Warm the last-used directory
and the three most recently opened projects right after OpenCode
readiness, sequentially and best-effort, overlapping UI startup.
Validation: new background-network tests, lifecycle warmup test, focused
store/sync tests, UI type-check and lint, dead-code report, node --check
plus electron type-check/lint, and CDP first-open measurements on the
packaged app (message fetch socket queue 5.4s -> 0.03s).
* fix(ui): keep interactive git reads out of background queue
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
* feat: add Windows ARM64 support with x64-baseline CLI workaround
Windows ARM64 native opencode.exe fails with a Bun FFI/TinyCC dlopen
error (anomalyco/opencode#19130). As a temporary workaround:
- Bundle x64-baseline OpenCode CLI on ARM64 instead of native ARM64
(prepare-opencode-cli.mjs, env-runtime.js)
- Disable OpenCode self-upgrade on ARM64 in server, VS Code, and UI
(upgrade-capability.js, opencode-upgrade-runtime.ts, useUIStore.ts,
OpenCodeCliSettings.tsx, search.ts, SettingsView.tsx, platform.ts)
- Add ARM64 Windows cross-compile builds to release and smoke workflows
(release.yml, release-desktop-smoke.yml)
- Refactor Windows latest.yml to use combine-electron-manifests pattern
matching macOS, since two arches now produce per-arch manifests
The CI ARM64 build itself is permanent; only the x64-baseline CLI
bundling and upgrade disablement are temporary and should be reverted
when the upstream issue is resolved.
* fix(desktop): select Windows updater by architecture
---------
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
Fix remote Desktop runtime bootstrapping across context-panel session chats, additional windows, and host switches.\n\n- Bootstrap embedded session-chat frames through a same-origin parent handshake that supplies the active endpoint, bearer token, runtime headers, local origin, and a credential-free relay descriptor.\n- Keep relay pairing grants out of iframe state and explicitly rebind the SDK after embedded bootstrap or relay restoration.\n- Preserve each additional and Mini Chat window's own init script instead of overwriting it when the main window's host configuration changes.\n- Replace direct iframe global calls with same-origin postMessage synchronization for theme, chat settings, and visibility.\n\nHarden Desktop host authentication and probing.\n\n- Bind password, passkey, session-status, and token-persistence completions to the runtime identity that started them, so a late result cannot alter a newly selected host.\n- Cancel active passkey operations and reset transient auth UI state on endpoint changes.\n- Verify stored client authentication via /auth/session for direct and relay host probes, distinguishing reachable hosts from hosts that require re-authentication.\n- Bound every relay probe request with an aborting timeout so a stalled auth request cannot hang refresh or host switching.\n\nAdd regression coverage for the embedded bootstrap handshake, credential-free relay descriptor exposure, runtime configuration, stale password completion after an A-to-B switch, and SDK errors that carry a zero response status.\n\nAlso preserve SDK response status on session-message loader errors so callers can distinguish transport and server failures.
Resize Linux tray icons so StatusNotifier hosts show them, add Show/Hide/Close
context-menu actions, and resolve FreeDesktop theme icons for Open-in apps
(including the default file manager) instead of skipping Linux icon fetch.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
Rebuilds better-sqlite3 separately for Electron before packaging
Copies the native binary into the packaged app resources
Updates packaging docs to explain the afterPack workaround
* feat(electron): add Linux AppImage releases
* ci: cache Linux OpenCode CLI artifacts
* fix(ci): await Linux release inventory check
* fix(electron): add frameless window controls on Linux desktop
Linux AppImages were created without native WM decorations and without
in-app controls, leaving users unable to close the window with a mouse.
Treat Linux like Windows: frameless BrowserWindow plus the existing
WindowsWindowControls header buttons and app-menu entry. macOS keeps
hidden title bar with traffic lights unchanged.
Shared usesFramelessElectronChrome() helper drives main window, mini
chat, header insets, and titlebar controls.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* Linux desktop feature parity: Open in, background start, tray, multi-window (#2392)
* feat(electron): Linux parity for Open in, background start, and tray
Enable Linux desktop feature parity with macOS/Windows: open projects in
the default file manager and discovered apps, XDG autostart with
--background launches, system tray (including minimize-to-tray), and
tray sync from the renderer.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* fix(electron): allow packaged UI protocol navigations on Linux
Prevent openchamber-ui:// navigations from being handed to
shell.openExternal, which fails on Linux and blocked desktop UI flows.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* fix(ui): surface Linux tray settings in settings search
Include isLinux in settings search runtime context so minimize-to-tray
is discoverable on Linux desktop, matching Windows search behavior.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* fix(electron): stop Linux AppImage Waiting-for-OpenCode flicker
Sync updated boot-outcome init scripts to all BrowserWindows after
desktop_hosts_set, and prefer state.initScript on dom-ready so chooser
reloads inject local/ok instead of a stale not-configured outcome.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* fix(desktop): restore Linux AppImage updater feed and error UX (#2396)
Treat missing latest-linux*.yml (404) as no update available instead of a
hard failure, and stop swallowing updater capability/download errors in the
desktop bridge so About/sidebar can show actionable messages.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* docs: credit Linux AppImage contributors in changelog
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
---------
Co-authored-by: jibanez-staticduo <staticduo@gmail.com>
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
Reads OPENCHAMBER_SKIP_LOCAL_SERVER after inheriting the user shell environment
Applies the flag consistently during startup and initial URL resolution
Updates Electron docs to explain where the setting comes from
Adds a General settings switch to show or hide the macOS menu bar item.
Persists the new desktopMacMenuBarEnabled setting and passes tray state into Electron.
Disables tray sync and native tray setup when the menu bar is turned off.
Allow Desktop to skip its in-process OpenChamber server with OPENCHAMBER_SKIP_LOCAL_SERVER=1 while continuing to load the packaged UI shell.
Carry local runtime availability through the boot contract so unavailable or unconfigured remotes enter a remote-only chooser instead of offering broken local recovery actions. The chooser can select saved instances, add a server by URL, or redeem an OpenChamber pairing link over direct or E2EE relay transports.
Keep additional windows, Mini Chat, background startup, and unreachable-host recovery functional without a local origin. Render boot and recovery surfaces with the active theme background rather than exposing the native vibrancy backing.
Document the environment variable and cover serverless boot routing plus malformed pairing imports with focused tests.
Improve OpenChamber responsiveness under large session workloads while fixing
cache, synchronization, and persistence correctness across runtimes, projects,
directories, and worktrees.
- prioritize selected and visible sessions during bootstrap and defer
non-critical enrichment work
- reduce redundant message loading, event processing, store publication, and
hidden sidebar work
- prevent stale session and message requests from overwriting newer
authoritative state
- preserve existing data when authoritative fetches fail instead of treating
failures as successful empty responses
- scope session materialization, messages, drafts, queues, todos, pins,
permissions, folders, tabs, Git state, and pull request data by runtime and
directory identity
- harden runtime switching, reconnect, cleanup, mutation reconciliation, and
persisted-state ordering
- preserve live subagent Task linkage when metadata arrives after an older
message request or while streaming parts are suspended
- coalesce overlapping tail refreshes without losing newer refresh demand
- improve cold-session loading by moving deferrable work out of the critical
bootstrap path
- isolate URL authentication, mobile credentials, native secrets, and other
runtime-owned state across endpoint changes
- bound long-lived caches and remove avoidable allocations from event and
rendering hot paths
- limit virtualization to archive collections where it improves rendering
without disrupting active sidebar layout
- stabilize session folders, pin ordering, expanded state, and persisted
sidebar behavior
- open skill files through the same secure editor and outside-workspace grant
flow used by file navigation, including worktree sessions
- expand regression coverage for stale completions, runtime collisions,
reconnect behavior, persistence races, authoritative empty results, and
subagent refresh ordering
- document the updated synchronization, cache ownership, performance, and
runtime-isolation invariants
Adds a new `hmr-react-scan` web dev option in `oc-dev`
Turns on React Scan via `VITE_ENABLE_REACT_SCAN` for that mode
Documents Electron workspace trust so fresh installs fetch the runtime automatically
* feat(electron): add Linux AppImage releases
* ci: cache Linux OpenCode CLI artifacts
* fix(ci): await Linux release inventory check
* fix(electron): add frameless window controls on Linux desktop
Linux AppImages were created without native WM decorations and without
in-app controls, leaving users unable to close the window with a mouse.
Treat Linux like Windows: frameless BrowserWindow plus the existing
WindowsWindowControls header buttons and app-menu entry. macOS keeps
hidden title bar with traffic lights unchanged.
Shared usesFramelessElectronChrome() helper drives main window, mini
chat, header insets, and titlebar controls.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* feat(desktop): add configurable window controls position by OS
Add desktopWindowControlsPosition setting (auto/left/right) with OS-aware
defaults: Linux left, Windows right. Wire frameless chrome controls in
Header, TitlebarLeftControls, and MiniChatLayout, plus a Sessions settings
control for Windows and Linux desktop shells.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
* fix(desktop): address Linux AppImage release review findings
Propagate updater capability errors to the UI, treat missing
latest-linux.yml feeds as no-update, stop installed-apps IPC spam on
Linux, document FUSE/AppImage limits, add CHANGELOG entry, migrate
remaining btriapitsyn URLs, and run Electron Linux unit tests on PRs.
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
---------
Co-authored-by: jibanez-staticduo <staticduo@gmail.com>
Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
Bundle the official OpenCode CLI into Electron desktop builds instead of relying on whichever opencode executable happens to be first on PATH. Pin @opencode-ai/sdk to an exact version and use that version as the source of truth for the downloaded CLI artifact.
Add an Electron prepare script that maps the current platform/arch to the official OpenCode release artifact, downloads it from GitHub releases, caches the archive under packages/electron/.cache, stages the binary under resources/opencode-cli, verifies opencode --version, and skips work when the staged binary already matches.
Prefer explicit OpenCode binary overrides first, then the bundled Electron CLI, then PATH/system installs. Keep rejecting the Windows OpenCode desktop app executable as a CLI candidate and add resolver tests for bundled priority, explicit override priority, resourcesPath lookup, and desktop-app rejection.
Suppress OpenCode CLI update prompts when the active CLI source is bundled. The server now reports upgrade-status as unavailable for bundled CLI while still returning the current OpenCode version for About, and rejects direct upgrade attempts with a 409 instead of trying to mutate the bundled binary.
Update desktop release, smoke, and manual macOS DMG workflows to prepare and verify the bundled CLI before packaging, verify the packaged app contains the expected CLI, cache downloads by OS/arch/OpenCode version, and align the Windows smoke runner with production windows-2022.
Document desktop bundling behavior, ignore generated CLI/cache files, add oc-dev helpers, and keep Web/VS Code behavior dependent on installed OpenCode CLI rather than desktop bundled resources.