Focus Timer is a compact macOS countdown timer inspired by the Time Timer visual style. It shows the remaining time as a circular disk, supports timers up to one hour, keeps pinned and recent timers, can show a floating read-only timer window, and includes menu bar controls, appearance settings, custom colors, completion sounds, and optional completion notifications.
- macOS 13.0 or later
- Xcode with the macOS SDK installed
The app is a native SwiftUI/AppKit macOS app.
- Circular visual countdown up to one hour
- Editable time text
- Pinned and recent timers
- Floating read-only timer window
- Optional click-through floating timer mode
- Menu bar item with configurable icon style
- Instant start timers from the menu bar
- Sparkle-based update checks and automatic update settings
- System, dark, and white appearance modes
- Built-in and custom completion sounds
- Stop ringing control when a timer completes
- Optional completion notification
- Open
focus-timer.xcodeproj. - Select the
focus-timerscheme. - Select
My Macas the run destination. - Press
Run.
The app product name is Focus Timer.
For a local Debug build:
xcodebuild \
-project focus-timer.xcodeproj \
-scheme focus-timer \
-configuration Debug \
-sdk macosx \
-derivedDataPath .derivedData \
CODE_SIGNING_ALLOWED=NO \
buildSparkle update controls are disabled in local builds unless a public EdDSA key is provided. To test update UI with a configured updater, pass the public key as a build setting:
xcodebuild \
-project focus-timer.xcodeproj \
-scheme focus-timer \
-configuration Debug \
-sdk macosx \
-derivedDataPath .derivedData \
CODE_SIGNING_ALLOWED=NO \
SPARKLE_PUBLIC_ED_KEY="your-public-key" \
buildFor a local Release build:
xcodebuild \
-project focus-timer.xcodeproj \
-scheme focus-timer \
-configuration Release \
-sdk macosx \
-derivedDataPath .derivedData \
CODE_SIGNING_ALLOWED=NO \
buildThe built app is created at:
.derivedData/Build/Products/Release/Focus Timer.app
The GitHub Actions workflow in .github/workflows/release.yml builds the app,
ad-hoc signs it, zips Focus Timer.app, generates a Sparkle appcast.xml, and
uploads both files to a GitHub release. The workflow can run when a release is
published or manually through workflow_dispatch.
The app's Sparkle feed URL is:
https://github.com/minkyu97/focus-timer/releases/latest/download/appcast.xml
Before using Sparkle releases, configure these GitHub repository settings:
- Repository variable
SPARKLE_PUBLIC_ED_KEY: the public EdDSA key generated by Sparkle. - Repository secret
SPARKLE_PRIVATE_KEY: the private EdDSA key used only by the release workflow to sign update archives.
Generate the Sparkle key pair once with Sparkle's generate_keys tool. After
Xcode resolves the Sparkle package, the tools are usually under:
.derivedData/SourcePackages/artifacts/sparkle/Sparkle/bin/
Keep the private key out of git. Sparkle compares releases using
CFBundleVersion, so increment CURRENT_PROJECT_VERSION before publishing an
update. For real public distribution, prefer Developer ID signing and
notarization over ad-hoc signing.
If you download a release artifact from GitHub:
- Unzip the downloaded file.
- Move
Focus Timer.appto/Applications. - Control-click or right-click the app and choose
Open. - Click "Open Anyway" at the bottom section of
System Settings -> Privacy & Security
Focus Timer stores user preferences with UserDefaults, including recent timers,
pinned timers, appearance mode, selected sound, menu bar settings, and floating
timer settings.
Custom completion sounds are copied into:
~/Library/Application Support/Focus Timer/Sounds/
Notification permission is requested by macOS the first time the app needs to show a completion notification.