How Modly Auto-Updater Manages Updates for Packaged Applications Across Operating Systems

Modly's auto-updater uses Electron Updater (electron-updater) from the main process with platform-specific logic that enables automatic patches on Windows and Linux while disabling updates entirely on macOS due to unsigned builds.

Modly, an open-source desktop application built with Electron, implements a sophisticated cross-platform update mechanism that balances automation with user control. The system handles patch updates silently while requiring manual intervention for major and minor releases, with special handling for macOS limitations. All auto-updater logic lives in electron/main/updater.ts and integrates with the UI through src/shared/stores/appStore.ts.

Platform-Specific Update Behavior

Modly's update support varies dramatically by operating system due to code signing requirements.

Windows and Linux: Full Auto-Updater Support

On Windows and Linux, electron-updater operates normally. The updater validates bundle signatures against signed builds, enabling seamless automatic updates. Users receive patch updates without interruption while major and minor releases trigger UI notifications.

macOS: Updates Explicitly Disabled

macOS builds are unsigned—the project lacks an Apple Developer ID. Since electron-updater validates code signatures before applying any update, the updater would fail repeatedly on macOS. The code explicitly disables updates through the updatesSupported constant:

// In electron/main/updater.ts
const updatesSupported = process.platform !== 'darwin';

This platform gate ensures macOS users manually download installers from GitHub Releases rather than experiencing broken auto-update attempts.

Initializing the Auto-Updater

The initAutoUpdater(getWindow) function bootstraps the update system from electron/main/index.ts. It receives a callback returning the current BrowserWindow to enable renderer communication.

Configuration applied when updatesSupported is true:

Setting Value Purpose
autoDownload false Prevents automatic downloads; app controls when to fetch updates
autoInstallOnAppQuit true Silent installation when user quits the application
disableWebInstaller true Forces updates from GitHub release assets only
// From electron/main/index.ts
import { initAutoUpdater } from './updater';
import { createWindow } from './window';

const mainWindow = createWindow();
initAutoUpdater(() => mainWindow);

Update Detection and Scheduling

Modly checks for updates immediately on application startup, then polls every 2 hours using setInterval. The autoUpdater.checkForUpdates() method queries the configured update source (GitHub Releases) for new versions.

Distinguishing Patch vs. Major/Minor Updates

When electron-updater emits the 'update-available' event, Modly implements version parsing logic to categorize the update type:

Patch updates (same major.minor, different patch):

  • Automatically downloaded via autoUpdater.downloadUpdate()
  • Applied silently on next quit

Major/minor updates (different major or minor version):

  • Renderer notified via updater:major-minor-available IPC channel
  • UI prompts user to download new installer from GitHub

This separation prevents disruptive automatic updates that might require manual migration or new dependencies.

// Simplified version comparison logic from updater.ts
const [currentMajor, currentMinor] = currentVersion.split('.').map(Number);
const [newMajor, newMinor] = newVersion.split('.').map(Number);

if (currentMajor === newMajor && currentMinor === newMinor) {
  // Patch: auto-download
  autoUpdater.downloadUpdate();
} else {
  // Major/minor: notify renderer
  mainWindow.webContents.send('updater:major-minor-available', { version: newVersion });
}

Applying Downloaded Updates

Once a patch finishes downloading, the 'update-downloaded' event triggers the installation sequence:

  1. Main process sends updater:applying to renderer
  2. Renderer sets patchUpdateReady = true in useAppStore
  3. Short delay allows UI to render "Applying update..." screen
  4. autoUpdater.quitAndInstall(true, true) executes with:
    • First true: quit silently
    • Second true: run installer after quit

State Management and UI Integration

The shared store in src/shared/stores/appStore.ts exposes update state to the React renderer. Components subscribe to patchUpdateReady to display appropriate UI feedback.

Renderer Event Listener Hook

import { useEffect } from 'react';
import { useAppStore } from '../../shared/stores/appStore';

export function useUpdateListener() {
  const setPatchUpdateReady = useAppStore(state => state.setPatchUpdateReady);
  const showToast = useAppStore(state => state.showToast);

  useEffect(() => {
    const onMajorMinor = (_event, { version }) => {
      showToast(`New version ${version} available – download from GitHub`);
    };
    const onApplying = (_event, { version }) => {
      setPatchUpdateReady(true);
      showToast(`Applying patch ${version}…`);
    };

    window.electron.ipcRenderer.on('updater:major-minor-available', onMajorMinor);
    window.electron.ipcRenderer.on('updater:applying', onApplying);

    return () => {
      window.electron.ipcRenderer.removeListener('updater:major-minor-available', onMajorMinor);
      window.electron.ipcRenderer.removeListener('updater:applying', onApplying);
    };
  }, [setPatchUpdateReady, showToast]);
}

React UI Component

import { useAppStore } from '../../shared/stores/appStore';

export function PatchUpdateBanner() {
  const patchReady = useAppStore(state => state.patchUpdateReady);
  if (!patchReady) return null;
  return <div className="banner">Applying update… Please wait.</div>;
}

Error Handling and Logging

All updater errors route through Modly's shared logger. The IPC channel in electron/main/ipc-handlers.ts registers the autoUpdater instance for renderer communication, ensuring consistent error propagation across processes.

Summary

  • Modly's auto-updater is disabled on macOS (process.platform !== 'darwin') due to unsigned builds that would fail signature validation
  • Windows and Linux support automatic patch updates with autoDownload: false and autoInstallOnAppQuit: true
  • Patch updates download and install silently; major/minor releases require manual GitHub download
  • Update logic resides in electron/main/updater.ts with state shared via src/shared/stores/appStore.ts
  • The renderer receives notifications through IPC channels updater:major-minor-available and updater:applying

Frequently Asked Questions

Why doesn't Modly's auto-updater work on macOS?

The macOS builds are unsigned because the project lacks an Apple Developer ID. Since electron-updater validates code signatures before applying updates, it would fail repeatedly on macOS. The updater is explicitly disabled on darwin platforms to prevent broken user experiences, forcing manual downloads from GitHub Releases instead.

How does Modly decide between automatic patches and manual major updates?

The updater parses version strings into major, minor, and patch components when an 'update-available' event fires. If the major and minor numbers match the current installation, it's classified as a patch and downloads automatically. Different major or minor numbers trigger a renderer notification, prompting the user to download a new installer from GitHub.

Can I disable automatic updates in Modly?

Automatic updates require updatesSupported to be true (non-macOS platforms) and depend on autoDownload: false requiring explicit download calls. There is no user-facing toggle to fully disable the update check, though the 2-hour polling interval and manual download gate provide user control over when updates apply.

Where does Modly download updates from?

The disableWebInstaller: true setting forces electron-updater to source updates exclusively from GitHub release assets. Modly does not use web installers or third-party update servers—all binaries must be present in the repository's Releases section with proper version tags.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →