A unified macOS menu bar application combining three essential functionalities:
- Next Meeting β Shows upcoming calendar events with countdown, one-click join, and notifications
- Notification Badges β Surfaces dock icon badges for selected apps as menu bar icons
- NoSleep β Prevents the computer from sleeping with configurable duration and modes
- π Shows next upcoming calendar event with live countdown
- π One-click join for 50+ meeting services (Zoom, Meet, Teams, etc.)
- π Customizable notifications with snooze support
- π EventKit (macOS Calendar) and Google Calendar support
- π΄ Displays dock notification badges in the menu bar
- π Click badge icons to open/focus the app
- β¨ Auto-appear when badges appear, auto-disappear when cleared
- π― User-selectable apps to monitor
- βοΈ Prevents system sleep with configurable duration
- βοΈ Two modes: system-only or system+display
- β±οΈ Duration options: 15min, 30min, 1h, 2h, 5h, or indefinite
- π‘ Optional activity simulation to prevent "Away" status
- macOS 14.0 (Sonoma) or later
- Xcode 15.0 or later for building
git clone https://github.com/yourusername/businessbar.git
cd businessbar
# Set up Google Calendar credentials (required for Google Calendar support)
cp BusinessBar/Resources/credentials.local.json.example \
BusinessBar/Resources/credentials.local.json
# Edit credentials.local.json with your Google OAuth values (see below)
# Build and run
swift runOr build a standalone .app bundle:
./bundle_app.sh # snapshot build β BusinessBar.app
./bundle_app.sh 1.2.0 42 # versioned release build (CI)
./bundle_app.sh dmg # snapshot build + DMGBusinessBar supports Google Calendar via OAuth 2.0. The credentials are never hardcoded in source β they're loaded at runtime from JSON files and injected at build time by CI.
- Go to the Google Cloud Console and create a new project (or select an existing one)
- Enable the Google Calendar API:
- Navigate to APIs & Services β Library
- Search for "Google Calendar API" and click Enable
- Configure the OAuth consent screen:
- Navigate to APIs & Services β OAuth consent screen
- Choose External (unless you have a Google Workspace account and want Internal)
- Fill in the required fields (App name, User support email, Developer contact email)
- Under Scopes, add:
email.../auth/calendar.calendarlist.readonly.../auth/calendar.events.readonly
- Add your email as a Test User (required while the app stays in "Testing" mode)
- Create OAuth 2.0 credentials:
- Navigate to APIs & Services β Credentials
- Click Create Credentials β OAuth client ID
- Application type: Desktop app
- Name it (e.g. "BusinessBar")
- Click Create β you'll see your Client ID and Client Secret
- Extract the values BusinessBar needs:
google_client_numberβ the numeric prefix of the Client ID before.apps.googleusercontent.com. For example, if the Client ID is12345678.apps.googleusercontent.com, the client number is12345678google_client_secretβ the Client Secret value shown on the credentials page (e.g.GOCSPX-XXXXXXXXX)
Copy the example file and fill in your credentials:
cp BusinessBar/Resources/credentials.local.json.example \
BusinessBar/Resources/credentials.local.jsonEdit BusinessBar/Resources/credentials.local.json:
{
"google_client_number": "12345678",
"google_client_secret": "GOCSPX-XXXXXXXXX",
"sparkle_appcast_url": "",
"sparkle_public_ed_key": ""
}The sparkle_appcast_url and sparkle_public_ed_key fields are optional β leave them empty for local development. They're only needed when building a distributable .app with Sparkle auto-updates enabled.
This file is gitignored and takes precedence over the placeholder credentials.json at runtime. When you run swift run or ./bundle_app.sh, the app loads credentials from credentials.local.json first.
Note: The
Info.plistURL scheme (com.googleusercontent.apps.YOUR_GOOGLE_CLIENT_NUMBER) is also patched automatically bybundle_app.shat build time. Forswift run, the redirect is handled by the app's URL event handler regardless.
For CI builds, configure these repository secrets and variables:
Secrets (sensitive values, never shown in logs):
| Secret | Description |
|---|---|
GOOGLE_CLIENT_NUMBER |
The Google OAuth client number (e.g. 12345678) |
GOOGLE_CLIENT_SECRET |
The Google OAuth client secret (e.g. GOCSPX-XXXXXXXXX) |
SPARKLE_PUBLIC_ED_KEY |
The Sparkle EdDSA public key for update verification (e.g. abcdef123456...) |
Variables (non-sensitive values, visible in logs):
| Variable | Description |
|---|---|
SPARKLE_APPCAST_URL |
The URL to your Sparkle appcast XML file (e.g. https://your-host.example.com/businessbar/appcast.xml) |
To configure:
- Go to your repository on GitHub
- Navigate to Settings β Secrets and variables β Actions
- Under Secrets, click New repository secret for each secret above
- Under Variables, click New repository variable for each variable above
The Build and Release workflows inject Google credentials into credentials.json and patch the Info.plist URL scheme at build time. If the Sparkle variables are set, they also patch SUFeedURL and SUPublicEDKey in Info.plist. Any .local.json is removed from the .app bundle.
BusinessBar uses Sparkle 2 for in-app updates. To set up auto-updates:
-
Generate an EdDSA key pair:
# Install Sparkle's generate_keys tool (bundled with Sparkle.framework) .build/release/Sparkle.framework/Versions/B/XPCServices/Updater.app/Contents/Frameworks/SparkleCore.framework/Versions/A/generate_keysOr download the
generate_keysutility from the Sparkle releases. This saves the private key to your Keychain and prints the public key β setSPARKLE_PUBLIC_ED_KEYto that value. -
Host an appcast XML file at a public URL. The appcast lists available versions with download URLs and EdDSA signatures. Set
SPARKLE_APPCAST_URLto this URL. -
Sign updates locally using Sparkle's
sign_updatetool:sign_update BusinessBar-1.2.0.dmg # Outputs the EdDSA signature and length to add to your appcast entry
For full documentation, see the Sparkle guide.
At runtime, CredentialLoader resolves credentials in this order:
credentials.local.jsonβ local dev override (gitignored, never shipped)credentials.jsonβ bundled default (placeholder in source, real values injected by CI orbundle_app.sh)- Fallback β
YOUR_GOOGLE_CLIENT_NUMBER/YOUR_GOOGLE_CLIENT_SECRET(detected as unconfigured)
When the values start with YOUR_, GoogleAuthConfig.isConfigured returns false and the Google Calendar option is hidden from the UI.
BusinessBar requires the following permissions:
- Calendar Access β To read your calendar events
- Notifications β To send meeting reminders
- Accessibility (optional) β To read dock badges and simulate activity
- Launch BusinessBar
- Grant Calendar and Notification permissions during onboarding
- Select which calendars to monitor in Preferences
- (Optional) Add apps to monitor for notification badges
- (Optional) Grant Accessibility permission for badge monitoring
BusinessBar is built with:
- Swift 6 with strict concurrency
- AppKit for menu bar integration (NSStatusItem)
- SwiftUI for preferences and onboarding UI
- Combine for reactive data flow
- EventKit for calendar access
- IOKit for power assertions
- Accessibility API for dock badge reading
- AppAuth for Google OAuth 2.0 authentication
- CredentialLoader β JSON-based credential system (
.local.jsonoverride β.jsondefault β placeholder fallback) - AppLogger β structured logging via OSLog + rotating file logs (
~/Library/Logs/BusinessBar/) - Sparkle for in-app auto-updates
- Gitleaks via pre-commit for secret detection on push
MIT NON-AI License - See LICENSE file for details
To prevent secrets from being pushed, set up Gitleaks via pre-commit:
# macOS
brew install pre-commit
# or pip
pip install pre-commitrepos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.24.3 # or run: pre-commit autoupdate
hooks:
- id: gitleaks
stages: [pre-push] # runs on push, not commitpre-commit install --hook-type pre-pushGitleaks will now scan for secrets on every git push.
Inspired by:
Third-party libraries:
- Defaults β Copyright Β© Sindre Sorhus (MIT)
- KeyboardShortcuts β Copyright Β© Sindre Sorhus (MIT)
- LaunchAtLogin-Modern β Copyright Β© Sindre Sorhus (MIT)
- AppAuth-iOS β Copyright Β© OpenID contributors (Apache 2.0)
- Sparkle β Copyright Β© Andy Matuschak, Elgato Systems GmbH, Kornel LesiΕski, Mayur Pawashe, C.W. Betts, Petroules Corporation, Big Nerd Ranch (MIT)