Your calendar, work items, reminders, and local notes in one quiet macOS menu.
Website · Download the latest DMG · Release notes
Dayline is a small, native SwiftUI menu bar app built for the information you check throughout the day. It keeps upcoming Google Calendar events, active Linear or GitHub issues, Apple Reminders, and quick local notes together without adding another dashboard or Dock icon.
- Calendar at a glance: see timed events plus optional all-day events today, expand tomorrow, and create Apple Calendar events directly.
- Work without the tab: review assigned Linear or GitHub issues alongside incomplete Apple Reminders.
- Local Markdown notes: write formatted notes on this Mac; the first line becomes the title.
- Keyboard-first actions: hover a work item and use configurable shortcuts for status, priority, due date, and provider-specific fields.
- Super lightweight: native and menu-bar-only, using next to no system resources in the background.
- Quiet by design: menu-bar-only, background refresh, launch at login, and configurable ordering.
- Direct and private: Dayline has no backend, account system, analytics, or tracking.
Dayline shows the rest of today without making you open Calendar. Expand tomorrow when you want a head start.
Assigned issues stay within reach. Hover a row and press C to copy its URL,
S to change status, L to change labels, or A to change the assignee.
Linear issues also support P for priority and D for due date. The shortcuts are configurable.
Click a Linear or GitHub issue to read its details and description. Command-click opens the original issue in your browser. In Settings → Issues → Opening issues, choose the normal-click action and use Command, Option, or Shift for the opposite action. Space still toggles details while hovering.
Apple Reminders can occupy the same section instead of, or alongside, Linear and GitHub. Dayline can show selected reminder lists, create reminders, mark them complete, and change priority or due date without leaving the menu when the reminder and its list permit the action. Mutations require writable reminders and lists, and recurring reminder due dates cannot be changed.
Notes use a native live Markdown editor and stay on this Mac. The first line becomes the menu title, while standard shortcuts such as Command-B and Command-I format the current selection.
More screenshots
Quick status changes |
Quick priority changes |
Create Linear issues |
Focused, native settings |
- macOS 26 or newer
For source builds, install SwiftPM / Swift 5.9 or newer.
Download the notarized DMG from the latest GitHub release, open it, and drag Dayline into Applications.
Install the latest notarized release with Homebrew:
brew install --cask robin-liquidium/tap/daylineTo create and install a local development build instead:
./script/build_and_run.shThis requires an Apple Development signing identity and installs the isolated
/Applications/Dayline Dev.app without replacing production Dayline.
macOS writes native .ips reports when Dayline crashes. Dayline also keeps a
small rotating breadcrumb log with app lifecycle, refresh counts, and actions;
it never records account identifiers, calendar or issue contents, notes, URLs,
or authentication data.
Choose Settings → General → Export Diagnostics… to save a local ZIP with the bounded Dayline log, app/system version information, and up to five recent Dayline crash reports. Nothing is uploaded automatically. Native crash reports can contain system and device identifiers, so review the ZIP before sharing it.
The feedback sheet has a separate, off-by-default Include diagnostics option. When selected, Dayline creates the same ZIP, uploads it with the feedback, and adds a public download link to the GitHub issue for 30 days.
On first launch, connect any integrations you want from the menu:
- Google Calendar: link any number of Google accounts, then choose the readable calendars Dayline should merge into one agenda. Calendars currently visible in Google Calendar are enabled by default.
- Linear: read/write access for assigned issues and issue actions, filtered by user-selected teams.
- GitHub: assigned issues from user-selected repositories, with status, label, and assignee actions.
- Apple Reminders: incomplete reminders from user-selected lists, with create, complete, priority, and due-date actions when the reminder and list are writable. Recurring reminder due dates cannot be changed.
Google and Linear use OAuth 2.0 with PKCE; GitHub uses OAuth's device flow.
GitHub's OAuth repo scope grants Dayline access to every repository the
signed-in user can access; the selected repositories only filter what Dayline
displays and acts on.
Tokens are stored in the macOS
Keychain, and disconnecting a Google account revokes and removes only that
account's token. Shared meeting occurrences are shown once, with their source
calendar names visible in the agenda.
Official builds include the public OAuth client IDs needed for sign-in. Custom
builds can override them with DAYLINE_GOOGLE_CLIENT_ID and
DAYLINE_LINEAR_CLIENT_ID, or DAYLINE_GITHUB_CLIENT_ID.
Run ./script/build_and_run.sh to build the current checkout in release mode,
install it as /Applications/Dayline Dev.app, and launch it. The stable
de.obermaier.dayline.dev identity preserves Apple Calendar and Reminders
permissions across rebuilds without replacing or quitting the production app.
Dayline Dev keeps its preferences, OAuth credentials, notes, and diagnostics
separate from production Dayline. Sparkle updates are disabled in this build.
Google Calendar is deliberately unavailable unless the build receives a
separate iOS OAuth client created for bundle ID de.obermaier.dayline.dev:
DAYLINE_DEV_GOOGLE_CLIENT_ID="<dev-client-id>.apps.googleusercontent.com" ./script/build_and_run.shThe client ID is embedded in the installed app and preserved by later plain
rebuilds. Set DAYLINE_DEV_GOOGLE_CLIENT_ID="" explicitly to clear it. Its
reversed client-ID callback scheme is registered only to Dayline Dev. Linear
continues to use the dedicated dayline-dev://oauth/callback redirect, and
GitHub device flow needs no redirect.
Use ./script/build_and_run.sh --reset-privacy only when intentionally retesting
the first-run Apple Calendar and Reminders permission prompts. Normal updates do
not reset privacy approvals.
Configure different OAuth applications
- Create a Google Cloud project and enable the Google Calendar API.
- Configure and publish the external OAuth consent screen.
- Create an OAuth client of type iOS with bundle ID
build.local.Dayline. - Put the client ID in
Sources/Dayline/Auth/AuthConfig.swiftor provideDAYLINE_GOOGLE_CLIENT_IDat launch.
Google's iOS client redirects through the reversed client ID scheme, which Dayline derives automatically.
- Create an OAuth application in Linear under Settings → API → OAuth Applications.
- Enable refresh tokens and add
dayline://oauth/callbackas a callback URL. - Mark the application public if it should work across other workspaces.
- Put the client ID in
Sources/Dayline/Auth/AuthConfig.swiftor provideDAYLINE_LINEAR_CLIENT_IDat launch.
Dayline requests the read,write scopes.
Dayline Dev builds created by script/build_and_run.sh use the
dayline-dev://oauth/callback scheme, so installed production builds are not
hijacked. Register that callback URL in the same Linear OAuth application, or
override the scheme with DAYLINE_LINEAR_CALLBACK_SCHEME.
- Create a GitHub OAuth app and enable Device Flow.
- Put the client ID in
Sources/Dayline/Auth/AuthConfig.swiftor provideDAYLINE_GITHUB_CLIENT_IDat launch.
Dayline requests repo read:user so it can read and update assigned issues in
public and private repositories. GitHub's classic OAuth scopes do not offer a
read-only private-repository permission.
Dayline talks directly from your Mac to Google Calendar, Linear, and GitHub over HTTPS, and to Apple Reminders through macOS EventKit. There is no Dayline server between them.
- OAuth tokens live in the macOS Keychain.
- Linked account labels, calendar selections, GitHub repository selections, and enabled reminder lists live in local app preferences.
- Notes live in
~/Library/Application Support/Dayline/notes.json. - Calendar, Linear, GitHub, and reminder data is held in memory for display.
- Dayline does not include analytics, tracking, advertising, or an account system.
Dayline is free software licensed under the GNU General Public License v3.0. You may use, study, share, and modify it, and any distributed copies or derivative works must remain open source under the same license with their copyright notices intact.
"Dayline" and the Dayline logo are trademarks of Robin Obermaier. The GPL license covers the code, not the name or logo: modified versions distributed publicly must not be presented as the original Dayline.
Clone the repository, then build and launch the local app bundle:
git clone https://github.com/robin-liquidium/dayline.git
cd dayline
./script/build_and_run.shUseful development modes:
./script/build_and_run.sh --verify
./script/build_and_run.sh --debug
./script/build_and_run.sh --logs
./script/build_and_run.sh --telemetryThe script builds with SwiftPM, atomically updates /Applications/Dayline Dev.app,
and launches it as a menu bar accessory app without touching production Dayline.
Dayline includes an isolated mock app for screenshots, demos, and visual testing:
./script/build_mock_and_run.sh
DAYLINE_APP_NAME="Dayline Mock" ./script/menu_test.sh openDayline Mock.app has its own bundle ID and connected-looking sample Calendar,
Linear, GitHub, Apple Reminders, and Notes data. Refreshes, account actions, work-item updates, and note edits
remain in memory and never use real OAuth tokens, APIs, or the production notes
file.
The Accessibility-driven menu helper can inspect and operate either the real or mock app:
./script/menu_test.sh open
./script/menu_test.sh screenshot /tmp/dayline.png
./script/menu_test.sh tree
./script/menu_test.sh identifiers
./script/menu_test.sh press-id calendar.tomorrow.toggle
./script/menu_test.sh press-id linear.new
./script/menu_test.sh press-id linear.showMore
./script/menu_test.sh press-id notes.new
./script/menu_test.sh scroll downRun the complete smoke test with:
./script/smoke_test.shRun the scripted XCUITest suite with:
./script/ui_test.shThe XCUITests build and launch the isolated Dayline Mock.app, exercise the
menu, Calendar expansion, Linear/GitHub/Reminders switching, work-item actions and creation, pagination, complex Markdown
note rendering and formatting shortcuts, and Settings. Each run saves an isolated evidence directory under
dist/ui-test-results/ containing the .xcresult, structured test summaries,
the complete runner log, privacy-safe app breadcrumbs, and always-kept visual
and element-state checkpoints for successful as well as failed tests. The
checkpoint PNGs and text files are also extracted into a directly browsable
checkpoints/ directory.
The same suite runs on a GitHub-hosted macOS runner for every pull request and
push to main, so it does not use the local mouse or interrupt local work.
Stable accessibility identifiers
dayline.refreshdayline.settingsdayline.quitsetup.checkAgainsetup.googlesetup.google.connectsetup.google.<ACCOUNT-UUID>setup.google.<ACCOUNT-UUID>.reconnectsetup.linearsetup.linear.connectcalendar.tomorrow.togglelinear.newlinear.showMorelinear.showLesslinear.issue.<ISSUE-ID>linear.cancel.<ISSUE-ID>linearEditor.titlelinearEditor.descriptionlinearEditor.createlinearEditor.cancelreminders.newreminders.showMorereminders.showLessreminders.issue.<REMINDER-ID>reminders.preview.<REMINDER-ID>reminders.status.completedreminders.status.incompletereminders.priority.<PRIORITY>reminders.dueDate.calendar.<REMINDER-ID>reminders.dueDate.remove.<REMINDER-ID>reminderEditor.titlereminderEditor.notesreminderEditor.listreminderEditor.priorityreminderEditor.dueDate.addreminderEditor.dueTimeEnabledreminderEditor.createreminderEditor.cancelnotes.newnotes.showMorenotes.showLessnotes.note.<NOTE-ID>notes.delete.<NOTE-ID>noteEditor.textnoteEditor.savenoteEditor.cancelsettings.account.googlesettings.account.google.addsettings.account.google.<ACCOUNT-UUID>settings.account.google.<ACCOUNT-UUID>.reconnectsettings.account.google.<ACCOUNT-UUID>.disconnectsettings.account.google.<ACCOUNT-UUID>.calendar.<CALENDAR-ID>settings.account.reminders.connectsettings.account.reminders.disconnectsettings.account.reminders.list.<LIST-ID>settings.meetingAlertSnoozesettings.account.linearsettings.launchAtLoginsettings.refreshCadencesettings.menuBarEventLeadTimesettings.copyIssueHotkeysettings.statusPickerHotkeysettings.priorityPickerHotkeysettings.linearIssueOrdersettings.defaultNoteCountsettings.localNoteSortOrder
Sources/Dayline/App/ App entry point
Sources/Dayline/Auth/ OAuth sessions, PKCE, and Keychain token storage
Sources/Dayline/Models/ Display and persistence models
Sources/Dayline/Services/ Google Calendar, Linear, and local notes services
Sources/Dayline/Stores/ App state and refresh loop
Sources/Dayline/Support/ Formatters, mock data, and window helpers
Sources/Dayline/Views/ SwiftUI views
script/ Build, release, smoke, and menu test helpers
website/ TanStack Start landing page for Cloudflare Workers
Public releases are built, signed, notarized, stapled, and published by GitHub
Actions when a vX.Y.Z tag is pushed.
Maintainer release instructions
Export the Developer ID Application certificate and private key as a
password-protected .p12, create an App Store Connect API key for notarization,
then run:
./script/configure_release_secrets.shRequired GitHub Actions secrets:
MACOS_CERTIFICATE_P12_BASE64MACOS_CERTIFICATE_PASSWORDAPP_STORE_CONNECT_KEY_P8_BASE64APP_STORE_CONNECT_KEY_IDAPP_STORE_CONNECT_ISSUER_IDDAYLINE_SPARKLE_PRIVATE_KEY
Dayline uses Sparkle 2. The production feed is the signed
website/public/appcast.xml served at
https://dayline.robin.build/appcast.xml; release archives remain immutable,
versioned GitHub Release assets. Never hand-edit the feed after it has been
signed.
The EdDSA private key is stored in the maintainer's macOS Keychain under the
Sparkle account dayline and in the encrypted GitHub Actions secret
DAYLINE_SPARKLE_PRIVATE_KEY. GitHub secrets cannot be exported again, so keep
a separate secure backup of the key. The public key compiled into Dayline is
not secret.
Only an exact stable vX.Y.Z release may enter the production feed. Signed but
unnotarized test builds must remain prereleases and must never be marked latest.
After both the app and DMG pass notarization and validation, the continuation
workflow signs and uploads the appcast, publishes the stable release, then
commits only the updated appcast to main so Cloudflare deploys it. The
scheduled continuation reconciles that final feed commit if publication fails
transiently.
The first Sparkle-enabled release is a manual-download bootstrap because older Dayline versions contain no updater. Later production releases update automatically. Maintainers can exercise the same signed download, replacement, and relaunch path before release with isolated lower/higher local builds and a localhost appcast.
After release changes are merged to a clean, synchronized main branch:
./script/tag_release.sh 0.1.4The script validates the branch, clean tree, remote synchronization, and version uniqueness before pushing the tag. The release workflows then:
- Builds and tests the exact tagged commit.
- Imports the Developer ID certificate.
- Signs with hardened runtime and timestamping.
- Uploads the exact signed app to a private draft release before submitting it to Apple once.
- Exits instead of holding a GitHub-hosted runner open while Apple processes it.
- Checks pending drafts every ten minutes, resuming the saved submission ID.
- Staples the accepted app, builds and submits the DMG once, and saves that ID.
- Staples and validates the accepted DMG and app, runs Gatekeeper checks, then
publishes the versioned DMG, app ZIP, matching dSYM archive, stable
Dayline.dmg, and signedappcast.xmlassets, then deploys the appcast through the website.
The scheduled continuation is idempotent and verifies preserved artifact hashes before contacting Apple. To check one pending release immediately:
gh workflow run notarization-continuation.yml -f tag=v0.1.4Do not rerun the submission workflow while its private draft is pending. The continuation resumes the stored artifact and submission rather than uploading a new copy merely because Apple is slow.
CI also runs swift build and swift test for pull requests and pushes to
main. Regular pushes never publish releases.
Install the DMG layout tool with Homebrew before packaging locally:
brew install create-dmg
./script/package_release.shAlternatively, use the checksum-pinned bootstrap used by CI:
CREATE_DMG_BIN="$(./script/install_create_dmg.sh /tmp/dayline-create-dmg)" \
./script/package_release.shOfficial notarization should run through GitHub Actions so the preserved artifact, submission IDs, and continuation state stay together. The scripts reject dirty, untagged, mismatched, corrupt, or duplicate public releases.







