A small macOS menu bar timer. One activity runs at a time; the dropdown shows today's activities ranked longest-first with each one's share of the day and a running cumulative percentage, so the 80/20 split is visible at a glance. Plan the day as a queue of tasks with a time each; a task from the queue runs as a countdown with a circle that empties as the time runs out.
One line in Terminal downloads the latest release, installs it to
/Applications, and launches it:
curl -fsSL https://github.com/rsee301/pareto-timer/releases/latest/download/ParetoTimer.zip -o /tmp/ParetoTimer.zip \
&& ditto -x -k /tmp/ParetoTimer.zip /Applications && open /Applications/ParetoTimer.appOr download ParetoTimer.zip from the
latest release, unzip it, and
drag ParetoTimer.app to /Applications.
The app is ad-hoc signed, not notarized. A browser download is quarantined, so macOS blocks the first launch. Fix it one of two ways:
- System Settings > Privacy & Security, scroll down, click Open Anyway.
- Or in Terminal:
xattr -dr com.apple.quarantine /Applications/ParetoTimer.app
The curl line above does not trigger this.
The build is universal (Apple silicon and Intel), macOS 11 or later.
bash build.shThat compiles the app, bundles it, installs it to /Applications, and launches
it. Look for the timer icon in the menu bar.
If swiftc is missing, run xcode-select --install once and try again. No
other dependencies: no Homebrew, no Python, nothing to keep updated.
- Install somewhere else:
bash build.sh ~/Applications - Build only, no install:
bash build.sh --no-install
CI (.github/workflows/build.yml) builds the app on every push and pull
request and keeps the zip as a workflow artifact. To publish a download:
- From the browser: Actions tab > build > Run workflow, enter a
version like
1.1.0, click Run workflow. - From git:
git tag v1.1.0 && git push origin v1.1.0
Either way CI builds that version, creates the v1.1.0 tag, and attaches
ParetoTimer.zip to a GitHub release. The install line above always gets the
newest one.
The menu bar shows the current activity and its elapsed time, or today's total when nothing is running.
- Start new activity… (⌘N): type a name, or pick one you've used before from the dropdown. Add minutes for a countdown, or leave them blank to count up. Starting a new activity stops the current one.
- Click any row in the ranked list to switch straight back to that activity.
- Stop timer (⌘S): stops the clock without starting anything else.
- Add to queue… (⌘A): a task name and a time (
25,1:30,1h30; blank is 25 minutes). Add Another keeps the dialog open to plan the whole day in one go. - Start next (⌘↩) starts the top task. Each queue row has a submenu: Start now, Move to top, Remove. A task leaves the queue when it starts. The queue stays until you clear it, so unfinished tasks carry over to tomorrow.
- While a countdown runs, the menu bar icon is a circle that empties and the title shows the time left. The dropdown shows a large ring at the top.
- At zero you hear a sound and get a choice: start the next queued task, 5 More Minutes, Keep Going (overtime counts up in red), or Stop.
- Add 5 minutes in the menu extends a running countdown.
- Tracked time goes into the ranked list the same as before, countdown or not.
- Reset today…: clears today's log only; earlier days are kept.
- Open at login: toggles autostart (macOS 13+).
ACTIVITY TIME SHARE CUM
1. Propulsion review 1:52:10 41% 41%
2. Email 55:30 20% 61%
3. Standups 48:00 18% 79%
4. Slack 31:12 11% 90%
── 80% line ── 4 of 9 activities ──
5. Expense report 14:05 5% 95%
...
SHARE is that activity's percentage of the day. CUM is the running total. The 80% line marks where the cumulative share crosses 80%: everything above it is the vital few, everything below is the trivial many.
Totals cover today only and roll over at midnight on their own.
~/Library/Application Support/ParetoTimer/entries.json: plain JSON, one
record per tracked stretch (activity, start, end, and planned seconds
for a countdown). The queue is queue.json in the same folder. Show data file in
Finder in the menu opens it. History is never deleted, so past days remain
available if you want to chart them later. Reinstalling or updating the app
does not touch this file.
- It runs as a menu bar accessory, so it has no Dock icon and no window.
- A stretch shorter than one second is discarded, so mis-clicks don't show up.
- If the app crashes, the running activity is closed out at its last recorded second (the file is flushed every 30 seconds).
Everything is in ParetoTimer.swift (~840 lines, AppKit only). Re-run
bash build.sh after any edit. Some likely tweaks:
totals(on:now:)inStore: change the window from today to this week.menuNeedsUpdate: the row format string and thecum >= 80cut-off.refreshTitle: what the menu bar itself displays.drawPieandRingView: the countdown circle in the menu bar and the dropdown.timeUp: what happens when a countdown reaches zero.