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!

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