Skip to content

feat(macos): the app updates itself from GitHub releases - #4

Merged
brentc22 merged 4 commits into
mainfrom
feat/auto-update
Oct 5, 2026
Merged

brentc22 merged 4 commits into
mainfrom
feat/auto-update

Conversation

@brentc22

@brentc22 brentc22 commented Oct 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • The Mac app checks releases/latest at launch and every 6 hours. A newer release is announced once per version: a notification with an Update button, plus an entry at the top of the tray menu. catchbox → Check for Updates… asks right away.
  • Update and Restart downloads Catchbox-<version>.zip from the release, unpacks it next to the app (same volume, so the swap is a rename), checks bundle id + version + codesign --verify --deep --strict, swaps the bundle in place and relaunches. Skip This Version silences it until the next one.
  • Relaunch: the new copy is started as a second instance with --replacing <pid> and waits for the old one. A helper shell that waits for the exit gets killed along with the app, and NSRunningApplication only learns of the exit from the run loop, so the replaced pid is excluded explicitly.
  • CATCHBOX_UPDATE_FEED points the check at your own release JSON, to test an update without publishing one.

Test plan

  • make -C macos test: version comparison, release decoding, picking the right zip
  • make -C macos bundle: universal release build
  • End to end: a copy at 1.2.0 against a local 1.4.0 feed → dialog → downloaded, verified, replaced, relaunched by itself, inbox server back up
  • Against real GitHub: a 1.2.0 copy found and announced v1.3.0
  • First release with this code (1.4.0): 1.3.0 has no updater, so that one step is manual (brew upgrade / zip)

Note: after a self-update the Homebrew cask still records the old version, which is harmless. brew upgrade reinstalls the same release.

🤖 Generated with Claude Code

brentc22 and others added 4 commits October 5, 2026 10:21
Checks the latest release at launch and every six hours, announces a
newer one once (notification with an Update button, plus an entry at
the top of the tray menu), and on a click downloads the release zip,
verifies bundle id, version and signature, swaps the bundle in place
and relaunches. Check for Updates… in the app menu asks right away.

The relaunch starts the new copy as a second instance with the pid it
replaces: a helper waiting for the old one to exit is killed along with
the app, and NSRunningApplication only sees the exit from the run loop.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- show the update notification even while catchbox is in front, and ask
  for notification permission for it when mail notifications are off
- a skipped version stays out of the tray until a later one
- keep 'installing' set after the swap, so the tray never offers it twice
- one offer at a time; Check for Updates during an install says so
- wait for the replaced copy off the main thread, and never hand over to it
- remove the downloaded zip; only download from this repo's releases
- a pre-release is offered its final release; no checks without a version
- README no longer implies the signature proves who built the app

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@brentc22
brentc22 merged commit 822c009 into main Oct 5, 2026
5 checks passed
@brentc22
brentc22 deleted the feat/auto-update branch October 5, 2026 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant