Repository navigation
Windows: let Coucou tell people a new version is out (and later, install it in one click) #812
Description
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-versioninsrc/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/lateststays the Mac's). So listGET https://api.github.com/repos/Louis-CFM/coucou/releases?per_page=50, keep tags starting withwindows-v(not the rollingwindows-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, andwindows-v0.5.0comes 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-vis 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 withlinux-v*tags and a link (AppImage users have the same problem). Otherwise hide it on Linux. - Code: a small
update.rs, using the existingnet::clientandnet::read_cappedhelpers. No new crates, no keys, no release workflow change. Strings go throught()/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:
- 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 writesHKCU\…\Uninstall\Coucouwith thatInstallLocation(checked on a real install); - running from Program Files →
Coucou-Windows-<v>.msi. Tauri's MSI template isInstallScope="perMachine"underProgramFiles64Folder, with aMajorUpgrade, so a newer MSI replaces the old one in place; - anywhere else (the portable exe) → no Install button, only the link from step A.
- running from
- Download it to a temp folder, following redirects only to
github.com/*.githubusercontent.com(same allowlist asallowedHost). - Check its SHA-256 against the
digestGitHub publishes for every release asset (e.g.sha256:e8234a…). If there's no digest or it doesn't match, install nothing. - Run it and quit Coucou:
- setup.exe with
/P /UPDATE, the same flags Tauri's own updater uses./Pis passive (progress bar only)./UPDATEmakes 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.
- setup.exe with
- 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 newestwindows-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_PREUNINSTALLremovesbin,inboxand the log, and fix(windows): clean up agent hooks on uninstallation #445 adds--uninstall-hooks). For the setup.exe,/UPDATEcovers it. For the MSI, aMajorUpgradedoes remove the old product. fix(windows): clean up agent hooks on uninstallation #445'swix/hooks.wxsalready 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
- Build with the version set to
0.4.0: clicking "Check for updates" shows "0.5.0 is available" and the link openswindows-v0.5.0. - Build as
0.5.0: "You're up to date". - No network, and a blocked
api.github.com(hosts file): a clear message, and the window stays usable. - 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.
Activity
Windows and Linux: new version in the island, one click to install it…