A tiny macOS menu bar app for staying on task: a Pomodoro-style timer, a day planner whose blocks auto-start the timer for you, and a "parking lot" to dump stray ideas so they stop rattling around in your head while you work.
No Dock icon, no bloat, no build step — it's one HTML file for all the product logic, wrapped in a small native Swift shell that gives it a menu bar icon, speech, and a place to live. The core timer/planner works fully offline; the optional AI chat and weather chip are the only things that talk to the network.
- Timer — the scheduled timer, shown live in the menu bar. It's deliberately rigid (no pause, no fiddling) — that's the schedule talking. An Ad hoc tab has a normal lenient timer for off-plan work.
- Planner — schedule blocks for your day (once, daily, weekdays, weekends, or custom days), with optional color-coded categories. When a block starts, it auto-loads the task and starts the timer for you. If you're already mid-session, it just nudges instead of interrupting.
- Chopped blocks — mark a long block as e.g. 25/5 and it subdivides into Pomodoro sprints and breaks while it runs, with a per-sprint "stayed focused?" check-in.
- Parking lot — a scratch space for ideas/todos that pop into your head while you're focused on something else.
- Real interrupts — when a plan fires, you get an actual sound + spoken reminder + the popover forced open, not a notification that's easy to ignore.
- Log — every check-in is recorded, rolled up into on-time % (did you show up when planned?) and focused % (did you stay on task?), with a per-category breakdown.
- AI chat — an assistant that can read and edit your plan ("push everything after lunch back an hour") behind a confirm-before-apply proposal card. Talk to it by voice: on-device dictation in, spoken replies out, with a voice/speed picker and a hands-free mode. Bring your own OpenAI API key — it's stored in the macOS Keychain, not on disk.
- Weather chip — today's weather at a glance, using your coarse location if you allow it (IP-based fallback if not).
- macOS
- Xcode Command Line Tools (for
swiftc— no full Xcode project needed) - An OpenAI API key, only if you want the AI chat — everything else works without it
git clone https://github.com/chris-jk/focus-app-mac.git
cd focus-app-mac
bash install.shThis builds the app, ad-hoc signs it, installs it to /Applications/Focus.app,
and registers a login LaunchAgent so it starts automatically. Re-run it any
time you change focus.html or app/main.swift to rebuild and reload.
On first launch macOS will ask for microphone, speech recognition, and location permissions — those power the dictation, spoken replies, and weather chip. All of them are optional; deny anything you don't want and the rest of the app is unaffected.
- Left-click the menu bar icon — opens the app.
- Right-click — quit.
- It runs quietly in the background and starts at login.
All the actual app logic — UI, timer, scheduler, storage — lives in
focus.html. It's vanilla JS, no build step, no dependencies. Open it
directly in a browser to poke at it without touching your real app data
(the browser and the app's WKWebView have separate localStorage).
The shipped default routine (SEED_PLANS in focus.html) is a generic
placeholder. My actual routine lives in a gitignored seed-plans.local.js
that install.sh bundles in automatically if it exists — it's just a
SEED_PLANS_LOCAL array in the same shape, dropped in the repo root. Make
your own if you want a personal default seeded in on first launch, or just
skip it and add plans by hand from the app.
launchctl unload ~/Library/LaunchAgents/app.cannappy.focusapp.plist
rm ~/Library/LaunchAgents/app.cannappy.focusapp.plist
rm -rf /Applications/Focus.appIt's a one-file app, so PRs are easy to review. Fork it, poke around, send a pull request — happy to look at anything reasonable.
If this ends up useful to you, a shoutout / link back / mention somewhere would genuinely make my day. Not required, just appreciated.
And if you want to buy me a coffee for it: https://buymeacoffee.com/amgmproy ☕
MIT — see LICENSE. Do what you want with it, just don't sue me.