desktop_updater

Flutter desktop updater plugin for macOS, Windows, and Linux.

2.x uses one small update index, one release descriptor, and one verified zip:

app-archive.json -> release.json -> app.zip

No public folder listing is required. Clients fetch exact URLs and verify the zip length and SHA-256 before installation.

flutter_desktop_updater

Quick Start

Add the package:

dependencies:
  desktop_updater: ^2.2.0

Point your app at the hosted archive:

final controller = DesktopUpdaterController(
  appArchiveUrl: Uri.parse("https://updates.example.com/app-archive.json"),
);

Add desktop_updater.yaml at your app repository root, next to pubspec.yaml:

updates:
  baseUrl: https://updates.example.com

Publish one platform:

dart run desktop_updater:release publish --platform macos

Before your first production release, run:

dart run desktop_updater:release doctor --platform macos

With only updates.baseUrl, publish creates an upload-ready package under dist/desktop_updater and prints the manual upload and validate instructions. With an upload provider configured, it uploads versioned files first, validates them, uploads app-archive.json last, then validates hosted update selection.

EL10

Think of your update host as a shelf on the internet:

  1. The app reads app-archive.json.
  2. The archive says which release.json is newest for this platform/channel.
  3. release.json points to one zip and records its size and hash.
  4. The app downloads the zip only after the metadata says it is a valid update.
  5. The app verifies the zip before staging or installing it.

Publish does the reverse: create the zip, create release.json, update app-archive.json, upload the versioned files first, then expose the new archive last.

Ready-Made UI

Use the stock inline card:

DesktopUpdateWidget(
  controller: controller,
  child: const YourHomePage(),
)

Other built-in surfaces:

  • DesktopUpdateDirectCard
  • DesktopUpdateSliver
  • UpdateDialogListener

See Ready-made UI widgets for screenshots, placement guidance, and when to choose each surface.

For custom UI, switch on controller.state.

Diagnostics And Recovery

2.2.0 adds opt-in diagnostics and recovery for support flows. The default stays quiet: no package-owned files, uploads, telemetry, or storage.

Use in-memory problem reports for normal support, add an app-owned diagnostics sink for durable Dart lifecycle logs, and add diagnosticsLogPath plus an app-owned UpdateRecoveryStore only when support needs post-exit native helper evidence.

Details live in Diagnostics and recovery, Ready-made UI widgets, and Publishing desktop updates.

Production Trust

desktop_updater handles update mechanics. Your app still owns platform trust:

  • macOS production updates should be Developer ID signed, hardened-runtime enabled, notarized, stapled, and Gatekeeper accepted before packaging.
  • Windows production updates should use Authenticode when publisher trust is required.
  • Linux direct zip distribution should add descriptor signing or another publisher-authenticity policy when production trust matters.

Documentation

Advanced Commands

Most apps should start with release publish. Use low-level commands only when your pipeline needs to own each step:

dart run desktop_updater:package --help
dart run desktop_updater:app_archive --help
dart run desktop_updater:verify --help