Inspired by this System Crafters post I am using org-timer-set-timer for my pomodoro timing needs.

Of course one then would like to see the remaining time in the macOS menubar.

Further inspired by this blog post by Xiang who used bitbar for this purpose, I upgraded the solution to use the new xbar (successor to bitbar), and the built-in org-timer instead of org-pomodoro.

After installing xbar (which I did with a cheeky brew install xbar), create a file named org-timer.30s.sh in the directory $HOME/Library/Application Support/xbar/plugins with the following contents:

#!/usr/bin/env zsh
 
# needed both additions for it to find emacsclient and sed
export PATH='/opt/homebrew/bin:/usr/bin:$PATH'
# substring strips of extraneous whitespace at end of "h:mm:ss "
# split-spring by :
# cdr gets us ("mm", "ss")
# mapconcat puts it back together as mm:ss
# final sed removes the literal "s we get from emacsclient
emacsclient --eval "(if (not org-timer-countdown-timer) \"🤗\" (mapconcat 'identity (cdr (split-string (substring (org-timer-value-string) 0 -1) \":\")) \":\"))" | sed 's/"//g'

Remember to chmod +x and then refresh your xbar.

See also fix emacs sound on macos which might be relevant to you.

Bonus: Show countdown immediately when timer starts

Due to the 30s refresh interval, it can take up to that long before you see the countdown update in the menubar.

If you start your pomodoro with the elisp below, it will immediately show the countdown update thanks to the xbar:// refresh call.

(defun cpb/pomodoro-start ()
  (interactive)
  (org-timer-set-timer 25)
  (start-process "update xbar" nil "/usr/bin/open" "-g" "xbar://app.xbarapp.com/refreshPlugin?path=org-timer.30s.sh"))

P.S. now I am tempted to add timer start / pause via xbar plugin menu items. Please stahp!

Double Bonus: macOS do-not-disturb during pomodoro

Create two (2) shortcuts named respectively Focus DND on and Focus DND off. The former looks like this:

The latter is left as an exercise for the reader.

With the following code, you will automatically be DnD, by default across all your Apple devices, during every pomodoro!

(defun cpb--update-xbar-org-timer()
  (start-process "update xbar" nil "/usr/bin/open" "-g" "xbar://app.xbarapp.com/refreshPlugin?path=org-timer.30s.sh"))
 
(defun cpb--hook-pomodoro-done ()
  (interactive)
  ;; you have to create two shortcuts named "Focus DND off" and "Focus DND on"
  (start-process "disable DND" nil "/usr/bin/shortcuts" "run" "Focus DND off")
  (cpb--update-xbar-org-timer))
 
;; due to focus mode DnD only being disabled in done hook AFTER end of pomodoro notification,
;; you'll hear the gong sound but not see the notification.
;; hack: In org-timer.el, move (run-hooks 'org-timer-done-hook) to just above (org-notify msg sound)
(add-hook 'org-timer-done-hook 'cpb--hook-pomodoro-done)
 
(defun cpb/pomodoro-start ()
  (interactive)
  ;; start timer, this will also set org-timer-countdown-timer-title based on emacs context; we use to seed description
  (org-timer-set-timer 25)
  ;; activate DnD focus mode
  (start-process "disable DND" nil "/usr/bin/shortcuts" "run" "Focus DND on")
  ;; immediately show the countdown timer
  (cpb--update-xbar-org-timer))

Do this on Linux using waybar

This post possibly helped to nerd-snipe my friend Stéfan, who then went and made a much nicer version of this for Linux!

Changelog

  • 2025-01-08: Publish only the shell script part
  • 2025-01-09: Add xbar refresh at startup, inspired by Stéfan’s post
  • 2025-02-14: Add automatic Apple DnD focus during pomodoro