A macOS menubar application for Todoist with optional Linear and GitHub integrations.
Built with Rust (core logic) + Swift (native UI) via UniFFI.
- 🔴 Shows count of overdue tasks in the menubar
- 📋 Click to see today's tasks sorted chronologically
⚠️ Overdue tasks appear at the top- ✅ Click a task to mark it as complete
- ⏱️ Todoist submenu actions: Resolve + configurable Snooze durations
- 🟦 Optional Linear integration for assigned in-progress issues
- 🐙 Optional GitHub notifications with multiple accounts
- 📅 Optional calendar events from iCal feeds (Google Calendar and others), with multiple feeds
- 🔔 Notifications for newly overdue tasks
- 🔄 Auto-refreshes every 5 minutes
- Rust 1.70+ (install via rustup)
- Xcode 15+ with Xcode Command Line Tools
- xcodegen (
brew install xcodegen) - just (
brew install just)
Go to Todoist Integrations Settings and copy your API token.
just setup-config
# Then edit the config file with your token:
open -e ~/Library/Application\ Support/todo-tray/config.tomlOr manually:
mkdir -p ~/Library/Application\ Support/todo-tray
cat > ~/Library/Application\ Support/todo-tray/config.toml << 'EOF'
todoist_api_token = "YOUR_API_TOKEN_HERE"
# Optional: Linear in-progress issues
# linear_api_token = "lin_api_..."
# Optional: GitHub notifications (repeat block for multiple accounts)
# [[github_accounts]]
# name = "work"
# token = "ghp_..."
# Optional: iCal feeds (repeat block for multiple calendars/providers)
# [[calendar_feeds]]
# name = "Work Calendar"
# ical_url = "https://calendar.google.com/calendar/ical/.../basic.ics"
#
# Alias also supported:
# url = "https://calendar.google.com/calendar/ical/.../basic.ics"
# Optional: Snooze durations (default: 30m, 1d)
# snooze_durations = ["30m", "1d"]
# Optional: show upcoming meetings in the tray before they start (default: 10)
# meeting_focus_lead_time_minutes = 10
EOFjust runjust build-core # Build Rust library only
just build-app # Build complete app
just rebuild # Clean + full rebuild (use when Rust code changed)
just run # Build and open app
just fresh # Rebuild and run
just lint # Run clippy
just fmt # Format codeConfig file location: ~/Library/Application Support/todo-tray/config.toml
todoist_api_token = "your_todoist_api_token"
# Optional: include Linear issues assigned to you that are In Progress
linear_api_token = "your_linear_api_key"
# Optional: GitHub notifications grouped by account
[[github_accounts]]
name = "work"
token = "ghp_..."
[[github_accounts]]
name = "personal"
token = "ghp_..."
# Optional: calendar events grouped by feed/account
[[calendar_feeds]]
name = "Work Calendar"
ical_url = "https://calendar.google.com/calendar/ical/.../basic.ics"
[[calendar_feeds]]
name = "Personal Calendar"
ical_url = "https://calendar.google.com/calendar/ical/.../basic.ics"
# Optional: todoist snooze options
snooze_durations = ["30m", "1d"]
# Optional: switch the tray title to the active/next meeting before start
meeting_focus_lead_time_minutes = 10
# Optional: auto-launch at login
autostart = true- Rust Core (
src/): Business logic, API clients, state management - Swift UI (
SwiftApp/TodoTray/Sources/): Native AppKit menubar app - UniFFI: Generates Swift bindings from Rust types
MIT