Until is a small, local-first iPhone countdown for dates that may be seconds or decades away. Version 0.2 supports a library of countdowns, entered/calendar/ total display modes, progress, pause and resume, milestone notifications, widgets, themes, privacy-aware sharing, and an exportable action history.
- Create and pin multiple countdowns using a duration or target date.
- Switch between entered-unit, calendar, and total-time breakdowns.
- Add time, reset, pause, resume, edit, delete, pin, and undo with an append-only history entry for every change.
- Add an optional reason to changes and export the full record as JSON or CSV.
- Schedule local milestone notifications from one year through the target date.
- Show the pinned countdown in small, medium, large, and Lock Screen widgets.
- Apply themes and icons, hide private event names outside the app, and share a rendered countdown card through the system share sheet.
Requires macOS with Xcode 27 and XcodeGen.
xcodegen generate
xcodebuild -project UntilApple.xcodeproj -scheme UntilTests -sdk macosx -destination 'platform=macOS' CODE_SIGNING_ALLOWED=NO clean test
xcodebuild -project UntilApple.xcodeproj -scheme Until -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO clean buildSee docs/development.md for the complete cross-machine handoff and widget build command.
The bundle identifier is pw.kian.until. Change it in project.yml before
configuring distribution signing if a different identifier is required.
Until stores the target date instead of decrementing a counter in the background. While the app is visible, it derives years, months, weeks, days, hours, minutes, and seconds from the current time once per second. A duration keeps the largest unit the user entered, so an eight-week timer remains week-based instead of being converted into calendar months. Date-based timers use the complete calendar breakdown. Years and months preserve their real-world calendar lengths.
State and history are stored as JSON in the app's Application Support folder. Version 0.2 migrates existing state into the private App Group shared with the widget extension. Nothing leaves the device unless the user explicitly exports or shares it.
The widget displays the pinned countdown and opens that countdown in the app. Widget refresh timing is controlled by WidgetKit; dynamic timer text continues to count down between timeline refreshes. Milestones use local notifications and require notification permission. See docs/widgets-and-notifications.md.
Signed archives are produced by the private release runner so certificates, profiles, and App Store Connect credentials never enter this public repository. See docs/testflight.md for the release flow and current Apple identifiers.