App Lifecycle & Upgrades
Relevant source files
The following files were used as context for generating this wiki page:
Crisp manages a structured application lifecycle that encompasses first-run onboarding, automated background updates, and sophisticated safeguards to prevent data corruption during terminal phases. The system is designed around a multi-channel distribution model (Stable, Nightly, and Dev), each with distinct update behaviors and versioning strategies.
The lifecycle is rooted in the @main entry point which orchestrates service initialization, log rotation, and update checks upon launch. Upgrades are handled via a custom GitHub-integrated Updater service that performs binary swapping and application relaunching.
Sources: CLAUDE.md, apps/desktop/Sources/Crisp/App/CrispApp.swift
Application Launch & Initialization
Upon launch, the CrispApp struct initializes core services and triggers a sequence of asynchronous tasks to ensure the environment is ready for video processing.
Initialization Sequence
- Log Rotation: The application calls
FileLog.shared.pruneOldLogs()to remove logs older than 30 days and records a launch marker with the current version and channel info. - Update Verification: An automatic check is performed shortly after launch for Stable and Nightly channels.
- Service Reconciliation: The
WatchAgentControlleris synced with user preferences to ensure the background folder-watching agent is correctly registered or unregistered. - State Refresh: The application refreshes the
ModelStore(speech models) andLicenseStoreto determine the current operational capabilities.
Sources: apps/desktop/Sources/Crisp/App/CrispApp.swift:31-62, CLAUDE.md
Distribution Channels & Versioning
Crisp utilizes three distinct channels that can be installed side-by-side. These channels are defined by the CrispChannel key in the Info.plist.
| Channel | Identity | Update Logic | Icon |
|---|---|---|---|
| Stable | com.syntaxlabtechnology.crisp | Tracks latest GitHub Release | Blue |
| Nightly | ...crisp.nightly | Tracks newest pre-release (by build number) | Amber |
| Dev | ...crisp.dev | Updates disabled | Purple |
Versioning Strategy
- Stable: Computed as
0.<total_commit_count>. - Nightly: Includes a cosmetic
-nightlysuffix and utilizes a monotonicCrispBuildNumber(CI run number) to determine if a release is newer. - Metadata: Nightly and Dev builds include
CrispBuildInfo(branch@sha) for debugging.
Sources: apps/desktop/build.sh:10-44, apps/desktop/build.sh:82-100, CLAUDE.md
Automated Update System
The Updater service manages the transition from the current running version to a newer release by interacting with the GitHub API.
Update Workflow
- Check: Queries
api.github.com/repos/rafay99-epic/Crisp/releases. For private repositories, it attempts to retrieve a token using thegh(GitHub CLI) auth utility. - Comparison: Stable checks if the tag version is numerically higher. Nightly compares the
build <n>string parsed from the release name. - Download: Fetches the
.dmgasset into a temporary directory. - Install:
- Mounts the DMG using
/usr/bin/hdiutil. - Uses
/usr/bin/dittoto swap the new.appbundle into the current installation path. - Detaches the DMG and deletes the temporary file.
- Mounts the DMG using
- Relaunch: Executes a shell command to sleep for 1 second and then reopen the app using
/usr/bin/open, followed by an immediateNSApp.terminate.
Sources: apps/desktop/Sources/Crisp/Services/Updates/Updater.swift:54-100, apps/desktop/Sources/Crisp/Services/Updates/Updater.swift:188-212
Post-Upgrade Experience
After a successful update, the WhatsNewController determines whether to present a "What's New" sheet.
- Trigger: It compares the
releaseIDof the current build against alastWhatsNewReleasekey stored inUserDefaults. - Content: Highlights are parsed from the GitHub release notes. The parser looks for a
## Highlightssection or falls back to deduped titles from specific user-facing areas (e.g., "desktop", "backend"). - Onboarding Suppression: The sheet is suppressed if the onboarding tour is currently active or if the user is brand new, as the tour already covers the features.
Sources: apps/desktop/Sources/Crisp/Services/WhatsNewController.swift:45-75, apps/desktop/Sources/Crisp/Services/WhatsNewController.swift:85-115
Termination Guardrails
To prevent the creation of corrupt video files, Crisp implements a ProcessingGuard (referenced as QuitGuard in logic) that monitors the state of the CleanModel.
- Mechanism: The
CrispAppdefines aProcessingGuard.shared.isBusyProbe. This closure returnstrueif either the mainCleanModelis running or a "Quick Clean" (menu bar drop) is in progress. - Veto: The
AppDelegateuses this probe to veto application termination or window closing if a render is currently in flight. - User Feedback: A notification or notice is displayed to the user when a quit is blocked due to active processing.
Sources: apps/desktop/Sources/Crisp/App/CrispApp.swift:65-71, CLAUDE.md
Summary
The Crisp lifecycle ensures a seamless transition between versions while prioritizing data integrity. By utilizing channel-specific bundles and a robust GitHub-based update mechanism, the app maintains the "Never lose the user's footage" philosophy even during the upgrade process. The combination of first-run onboarding and post-update release highlights ensures users are always aware of the system's capabilities and latest improvements.