packages/desktop/docs/plans/2026-06-08-desktop-auto-update-design.md
Enable stable-channel desktop auto-updates for packaged OpenWork and Qwen Code desktop builds using public GitHub Releases and electron-updater.
The first version supports stable releases only. Draft releases, prereleases, nightly builds, staged rollouts, and forced updates are intentionally out of scope.
Before this change, the desktop app already had most of the runtime surface:
apps/electron/src/main/auto-update.ts wraps electron-updater, broadcasts update state, and checks on launch when a packaged build has a brand update source.apps/electron/src/main/handlers/system.ts exposes update RPC handlers.apps/electron/src/transport/channel-map.ts exposes renderer API methods for update RPC and events.apps/electron/src/renderer/hooks/useUpdateChecker.ts returned a disabled stub.apps/electron/electron-builder.yml had no publish configuration, so release builds did not produce update feed metadata.Update source configuration belongs in packages/shared/src/branding.ts with the rest of desktop brand metadata. Each brand owns its release location:
openwork uses modelstudioai/openwork.qwen-code uses QwenLM/qwen-code.The brand config exposes a GitHub update source with provider, owner, repo, and releasePageUrl. scripts/electron-builder-config.ts reads it and emits the publish block in apps/electron/electron-builder.generated.yml. Runtime code reads the same brand update source for logs and fallback release-page actions.
The existing desktop release workflow remains responsible for uploading assets to GitHub Releases. electron-builder should generate updater metadata, but the workflow continues to publish assets itself.
Expected assets include platform installers and feed files:
latest-mac.ymllatest.ymlOnly non-draft, non-prerelease GitHub Releases are expected to reach stable-channel users.
Packaged desktop builds enable auto-update. Development builds stay disabled to avoid replacing local development apps.
On launch, the app checks for updates and auto-downloads available stable updates. It does not force an immediate restart. Once a download is ready, the renderer can prompt the user to restart; if the user quits normally after a download is ready, electron-updater may apply the update on quit using its default behavior. Manual checks in Settings use the same update API and can show dismissed versions.
The first UI lives in Settings > App as an Updates section:
Global interruption is deliberately minimal. Startup checks stay silent unless an update is ready.
Use focused local checks first:
openwork and qwen-code, verifying each brand emits the right publish config.CI dry runs validate asset and metadata generation. A true update test requires installing an older packaged release, publishing a newer non-draft stable release, and confirming the old app downloads and installs the new version.