Skip to content

Windows: let Coucou tell people a new version is out (and later, install it in one click) #812

Closed

Description

@afpruivo

The problem

Coucou for Windows can't tell you that a new version exists. To get a fix, people have to notice a release on GitHub themselves, download the installer and run it again. Most won't, so they stay on old builds and may keep reporting bugs that are already fixed.

About this proposal: I'm not opening a PR. The way updates reach users is the maintainer's call, so this is a plan to use, change or ignore. It follows the patterns already in the repo, and I'm happy to test builds on Windows 11.

Recommendation: two small steps, following the app's existing patterns

Step A: "Check for updates" (notify only)

A Check for updates action, only on click. Three places fit what's already in the app (the maintainer picks one or two):

  • right under the version at the bottom of the hub's sidebar ("Coucou 0.5.0", hub-version in src/hub/shell.ts), where people already look for the version. The existing line stays exactly as it is;
  • a row in Notch → General, next to "Launch at startup" and "Language", the app-wide options;
  • a "Check for updates…" item in the tray menu (src-tauri/src/tray.rs, next to "Settings…"), where many Windows apps put it.

On click, Coucou asks GitHub for the newest Windows release and shows either "You're up to date" or "0.6.0 is available" with a link to its release page. The user installs it as they do today.

  • Which release: Windows releases are published with --latest=false (so /releases/latest stays the Mac's). So list GET https://api.github.com/repos/Louis-CFM/coucou/releases?per_page=50, keep tags starting with windows-v (not the rolling windows-latest) that aren't drafts or prereleases, and take the highest SemVer. Compare it with the running version (app.package_info().version). I checked this from Windows: today the list mixes Mac (v*), Linux, Android and Windows releases, and windows-v0.5.0 comes back with both assets and their SHA-256 digests. 20 releases are about 120 KB, well under the existing 8 MB cap.
  • Why not just the tags: git/matching-refs/tags/windows-v is smaller (2 KB), but tags exist that never got a release (windows-v0.1.0/0.1.1), and a new tag exists for the 10–20 minutes before its build is published. Reading published releases avoids pointing anyone at a 404.
  • Network: a single request, only when the user clicks. That fits "network calls only to services the user configured": the user asked for it. Unauthenticated, GitHub allows 60 requests an hour per IP, which is plenty for a button. Add one line to the README's network list.
  • Linux for free (optional): windows/ also builds Linux, and the sidebar is shared. The same check works there with linux-v* tags and a link (AppImage users have the same problem). Otherwise hide it on Linux.
  • Code: a small update.rs, using the existing net::client and net::read_capped helpers. No new crates, no keys, no release workflow change. Strings go through t() / i18n/extra.json.
  • Works for every install: MSI, setup.exe and the portable exe alike, since it only shows a link.

Step B (later): "Install and restart"

The same flow as the Mac app's one-click Install WhatsApp (WAGOWARelease in NotchBuddy/Sources/App/WhatsAppGateway.swift), which already downloads from GitHub releases safely:

  1. Pick the asset that matches how this copy was installed:
    • running from %LOCALAPPDATA%\Coucou\ → Coucou-Windows-<v>-setup.exe. The setup.exe is per-user and writes HKCU\…\Uninstall\Coucou with that InstallLocation (checked on a real install);
    • running from Program Files → Coucou-Windows-<v>.msi. Tauri's MSI template is InstallScope="perMachine" under ProgramFiles64Folder, with a MajorUpgrade, so a newer MSI replaces the old one in place;
    • anywhere else (the portable exe) → no Install button, only the link from step A.
  2. Download it to a temp folder, following redirects only to github.com / *.githubusercontent.com (same allowlist as allowedHost).
  3. Check its SHA-256 against the digest GitHub publishes for every release asset (e.g. sha256:e8234a…). If there's no digest or it doesn't match, install nothing.
  4. Run it and quit Coucou:
    • setup.exe with /P /UPDATE, the same flags Tauri's own updater uses. /P is passive (progress bar only). /UPDATE makes Tauri's NSIS script skip the "reinstall or uninstall?" step and never run the old uninstaller. Without it, a passive install over an older version takes a path whose outcome isn't spelled out in the script;
    • the MSI with msiexec /i <file> /passive. Being per-machine, it shows a UAC prompt, as a manual MSI install does today.
  5. Coming back: check whether the passive setup starts Coucou again by itself (Tauri's updater adds a separate restart flag for that). If it doesn't, relaunch from a tiny step after install, or say "start Coucou again from the Start menu".

Still no new crates, no signing key and no workflow change. Like step A, nothing happens without a click.

What the checksum does and doesn't prove: it proves the file is exactly the one on the GitHub release, so a corrupted or swapped download is refused. It doesn't prove who uploaded it. That's the same trust people place in a manual download from the release page today. If signed updates are wanted later, see option C below.

Things to get right (both steps)

  • Never interrupt work: no automatic check in this version and no popup. An install shows "Coucou will restart". If Claude Code fires a hook while Coucou is restarting, the relay finds no app and exits 0, which is the existing "never block Claude Code" rule, so nothing breaks.
  • Errors in plain words: no network, GitHub rate limit, no Windows release found, checksum mismatch, and Defender blocking the download. Defender's ML model has flagged new unsigned builds before, so say "Windows blocked the download; get it from the release page" with the link.
  • Don't trust what comes back: cap the response size (read_capped), ignore assets whose names don't match the exact expected pattern, and never run anything that isn't the verified file.
  • Pure, testable pieces, as in WAGOWARelease: parse the releases list, pick the newest windows-v*, compare versions, pick the asset for an install type, read the expected SHA-256, and check the host. Unit tests for each, with a saved API response as the fixture.
  • Uninstall hooks: an update must not trigger the uninstall steps (NSIS_HOOK_PREUNINSTALL removes bin, inbox and the log, and fix(windows): clean up agent hooks on uninstallation #445 adds --uninstall-hooks). For the setup.exe, /UPDATE covers it. For the MSI, a MajorUpgrade does remove the old product. fix(windows): clean up agent hooks on uninstallation #445's wix/hooks.wxs already handles this (… AND NOT UPGRADINGPRODUCTCODE), so the agent hooks survive. Keep that condition if the action changes.

Alternatives considered

Option Why not now
C. Tauri's updater plugin (tauri-plugin-updater) The standard Tauri way, with signatures that don't depend on GitHub. But it adds two plugins and a signing key the maintainer must never lose (lose it and installed copies can't update), changes the release workflow, and needs separate -nsis/-msi entries to cover both installers. It's heavier than the app's own GOWA pattern for the same result. It's a good upgrade path if signed updates become a goal.
D. winget Nice for power users (winget upgrade), and it can be automated in the workflow. But people have to know about it, so it doesn't fix "people don't notice new versions". A good extra, not the answer.
E. Microsoft Store Automatic updates and code signing done by Microsoft, which would mirror the Mac App Store plan. But it's a separate, much bigger project (MSIX, Store account, review).
Automatic check at startup Convenient, but it's a network call the user didn't ask for, which goes against "no telemetry / only configured services". It could be an opt-in switch later.

Test plan

Step A

  1. Build with the version set to 0.4.0: clicking "Check for updates" shows "0.5.0 is available" and the link opens windows-v0.5.0.
  2. Build as 0.5.0: "You're up to date".
  3. No network, and a blocked api.github.com (hosts file): a clear message, and the window stays usable.
  4. The unit tests pass with a saved releases response (including a Mac v* release and a draft, which must be ignored).

Step B
5. A setup.exe install at 0.4.0 → Install → it comes back on 0.5.0. Settings, inbox and Claude Code hooks are untouched, with no admin prompt.
6. The same with an MSI install. Check that there's only one Coucou in Apps afterwards.
7. The portable exe: link only, no Install button.
8. Tamper with the expected digest in a test build: the download is refused.
9. A Claude Code session running during the update: after the restart, the next hook event reaches the island.
10. linux.yml still builds, and on Linux the check is either hidden or points at linux-v*.
11. MSI update with Coucou's agent hooks installed: the hooks are still there afterwards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions