Emerson · plan · 2026-10-07

Emerson Beta — a Sparkle channel that runs on the Claude CLI

23 of 25 tasks done

Date: 2026-10-07
Status: 0.1.0 published 2026-10-10 (LochLustra e853953); tester checks pending
Goal: Give a remote tester an Emerson build that runs model calls through his own claude login and updates itself through Sparkle, the way Code Raven's beta does. The App Store / TestFlight build stays sandboxed, API-only, and free of Sparkle.

Why the TestFlight build can't do this

Shape of the solution

A second app target, Emerson Beta, built from the same source folder:

Emerson (App Store / TestFlight)Emerson Beta (Sparkle)
Bundle IDcom.lochlustra.Emersoncom.lochlustra.Emerson.beta
Sandboxonoff
Model callsAnthropic APIClaude CLI by default, API selectable
UpdatesApp Store / TestFlightSparkle appcast on lochlustra.com
Data folderApplication Support/Emerson (inside the container)Application Support/Emerson Beta
Distribution signingApp StoreDeveloper ID, notarized DMG

A build configuration cannot do this job. Sparkle arrives as a Swift package, and Xcode links a package into every configuration of the target that depends on it. App Store review rejects self-updating apps, so Sparkle has to live in a target the App Store build never touches.

Compile flags

Target / configurationSWIFT_ACTIVE_COMPILATION_CONDITIONS
Emerson DebugDEBUG CLAUDE_CLI
Emerson Release*(none)*
Emerson Beta DebugDEBUG CLAUDE_CLI EMERSON_BETA
Emerson Beta ReleaseCLAUDE_CLI EMERSON_BETA

Phase 1 — Target and build settings

Phase 2 — Code gates

Phase 3 — Sparkle

Phase 4 — Deploy script

scripts/deploy-beta.sh, adapted from Code Raven's, plus scripts/ExportOptions-Beta.plist (method = developer-id).

StepEmerson Beta specifics
VersionMARKETING_VERSION passed on the xcodebuild command line only. Code Raven's script seds every MARKETING_VERSION in the project, which here would also rewrite the App Store target.
Build numberCURRENT_PROJECT_VERSION = $(date +%Y%m%d%H%M), as Code Raven does. Sparkle compares CFBundleVersion.
Archive / exportScheme Emerson Beta, Release, Developer ID export.
DMGreleases/Emerson-Beta-<version>.dmg, signed with Developer ID Application: Loch Lustra, LLC (X7BPXRX9NA).
NotarizeReuse the CodeRaven-Notarization keychain profile. It is a team-level App Store Connect key.
Appcastgenerate_appcast --account emerson-beta.
UploadVercel Blob, reusing the CodeRaven-Blob token.
Publishappcast.xml and an unlisted download page into ~/Developer/LochLustra/emerson/beta/, served at https://lochlustra.com/emerson/beta/. Reachable only by direct link (see Discoverability).

Discoverability

Decided 2026-10-07: the Emerson and Code Raven beta pages are reachable only by direct link.

Phase 5 — Verification

Tester setup (one time)

  1. Install Claude Code (curl -fsSL https://claude.ai/install.sh | bash), run claude once, and log in.
  2. Download the DMG and drag Emerson Beta to Applications.
  3. Open it. Settings → Model calls should read "Calls run through the local claude CLI."
  4. Keep or delete the TestFlight Emerson. The two apps store data separately and don't see each other's writing.

Decisions (2026-10-08)

  1. Display name: "Emerson Beta".
  2. Shared credentials: reuse Code Raven's CodeRaven-Notarization profile and CodeRaven-Blob token.
  3. Discoverability: direct link only (see Phase 4).
  4. Vercel Authentication (Standard Protection) is on for the lochlustra project, so old deployment URLs require a Vercel login.

Implementation notes (2026-10-09)

Where the build differs from the phases below:

Final review

Pros

Cons

Edge cases the plan does not cover

Adjustments worth considering

Confidence: 80/100. The target split, the separate data folder, and the deploy pipeline follow patterns proven in this repo and in Code Raven. Two steps haven't been done in this project and remain unverified: sharing one synchronized root group between two app targets with per-file exceptions, and a Developer ID export without a provisioning profile once keychain-access-groups is dropped. Either could add an hour of Xcode work, but neither changes the design.