Skip to content

Replay 0.9.9

Choose a tag to compare

@github-actions github-actions released this 31 Jul 12:02
· 17 commits to main since this release

Install

Homebrew is the recommended way, and the only one with nothing to click
through — the tap clears the quarantine flag on install and on every upgrade:

brew trust --tap nurkamol/tap
brew install --cask nurkamol/tap/replay-app

brew trust is required by Homebrew 6 before it will load any third-party tap.
Skipping it looks like a broken tap rather than a consent prompt.

Also in the tap: nurkamol/tap/replay (the command-line reader) and
nurkamol/tap/replay-app-source, which compiles on your Mac and needs a full Xcode.

Or the zip

Replay-0.9.9.zip — unzip it and drag Replay.app to Applications.

macOS will refuse to open this one the first time. Replay has no Apple Developer
ID yet, so a downloaded copy shows "Apple could not verify Replay is free of
malware"
, offering only Move to Trash or Cancel. That message is about a
missing certificate, not about anything found in the app.

To open it:

  1. Try to open Replay once and dismiss the warning.
  2. Go to System Settings ▸ Privacy & Security, scroll down, click Open Anyway.
  3. Confirm. It opens normally from then on.

Or one line in a terminal, which does the same thing:

xattr -dr com.apple.quarantine /Applications/Replay.app

Right-click ▸ Open does not work. That bypass existed for years and Apple
removed it in macOS 15. It is still the advice in most projects' READMEs.

A signed, notarised disk image — no warnings on any route — appears here the day
there is a certificate. The workflow that builds it is already written.


Fixed

  • brew upgrade no longer swaps the bundle out from under a running Replay. The cask had
    no uninstall quit:, so an upgrade replaced the application directory while the process was
    still in it — holding an open SQLite handle it writes to every few seconds. A launcher
    survives that; a recorder can lose the tail of the day, and the record is the product, with
    no cloud copy to restore from. Homebrew now quits Replay first and reopens it afterwards.

  • The in-app updater no longer overwrites a Homebrew-managed copy. It recognised a
    formula build by its /Cellar/ path, but a cask moves the app into /Applications,
    where it is indistinguishable from a copy dragged there by hand. So from the day 0.9.8
    shipped a cask, the updater would replace it — leaving brew describing a version it no
    longer had, and the next brew upgrade putting the older one back. It now checks
    Homebrew's own receipt under both prefixes.

Changed

  • Every build carries the same signature, so an update stops asking again. Replay was
    signed ad-hoc, and an ad-hoc signature has no identity: its designated requirement is the
    code hash, so it changed with every build. Homebrew 6 compares that requirement across an
    upgrade and carries a reader's Gatekeeper approval forward only when it matches — otherwise
    printing "the signer changed so macOS will prompt at next launch". That branch was taken
    every time, so each update meant another trip through System Settings, forever rather
    than once. A stable self-signed certificate fixes it, and fixes the same churn in the
    in-app updater. It is not a Developer ID and does not make the first launch any quieter.
    docs/SIGNING.md has the whole argument and the commands.

  • The tap clears the quarantine flag, and says so. Installing the cask no longer ends at
    a dialog offering only Move to Trash. What that trades is stated in the cask's caveats, in
    the README and on the site rather than buried: macOS did not check the app, Homebrew checked
    the download against the cask's SHA-256 instead, and that is a check published by the same
    project that publishes the app. The source build remains the route for anyone who would
    rather Apple's check applied.

  • brew trust --tap nurkamol/tap is now the first line of every install instruction.
    Homebrew 6 refuses to load a third-party tap until it is trusted, and the refusal reads like
    a broken tap rather than a consent prompt — which is what several confusing install errors
    turned out to be.

  • The cask's version and checksum are bumped by the release workflow, from the artefact it
    just built. They used to be copied between two repositories by hand, and 0.9.8 duly shipped
    for a while carrying 0.9.7's checksum against a 0.9.8 URL: every install failed, and failed
    in a way that reads as a corrupted download rather than a mistake in the tap.

Added

  • Memories reads in your language. The surface that exists to be read was the one still in
    English: its frame translated and every card inside it said "Your longest focus", "A late
    night"
    , "Where it began". All seven now follow the chosen language, along with the
    on-this-day names, the heatmap's months and weekday initials, and the dates throughout.

    • Word order moves with it. In Uzbek the application's name leads — "Firefox ilovasida 2h
      13m…"
      — which is what positional arguments are for and what glueing clauses together
      could never produce.
    • The English is untouched: it is the reference's own wording, and a facts payload on each
      moment is what lets the sentence be assembled a second time rather than replaced.
  • Update messages are translated too. The eleven sentences that appear when a check or an
    install fails were English in every language — which is the worst moment to meet a language
    you did not choose.

  • A day you reopen reads in your language. Six English strings were sitting on that
    surface — the time-of-day word in the story, the headline date, the toolbar subtitle, the
    reflection prompt, and both Export menus — and nobody had ever seen them, because the
    screenshot harness drove 21 surfaces and a past day was not one of them. It drives 25 now:
    a reopened day, the welcome screen's two pages, and What's New.

    • One of the six was self-inflicted, and is the useful half. The day parts are looked up
      through a variable, which the key scanner cannot see, so their translations looked
      orphaned and a tidy-up deleted them. docs/TRANSLATING.md now carries the rule: never
      sweep orphans in bulk.
  • Every SF Symbol is checked against the oldest macOS this app supports. A symbol newer
    than the deployment target draws nothing — no crash, no warning, a gap where an icon
    should be, on a Mac the developer does not own. tools/symbol-audit.mjs reads Apple's own
    availability manifest and fails the build instead. All 52 in use are safe on macOS 14; that
    was true by luck until now.