Avatar
OsingaOn my interests

On Pomodoro

How to create a minimal Pomodoro menu bar app with Keyboard Maestro.

Modified

This week Keyboard Maestro released v10.0. That update inspired me to hurry up and get my post on desktop productivity out, which covers a lot of my Keyboard Maestro setup.

Since then I've been playing around with some of their new features, and there are two in particular I found interesting: the ability to create subroutines and the ability to show macro groups in the menu bar. I decided to build out a minimal Pomodoro app around these features—partially for the learning experience, and partially at the request of my partner.

The complete macro group can be downloaded from the conclusion.

Background

The Pomodoro technique is a time management method that has you alternate between periods of focus and short breaks. Typically it's 25 minutes of work followed by 5 minutes of break, to be repeated however many times.

There are plenty of dedicated apps for this, but I want to do it with just Keyboard Maestro. On the one hand for the reasons mentioned in the introduction, and on the other hand for the deep integration it provides me with my other macros.

Behavior

The way it works is as follows:

  1. At rest, there's a menu bar item to start a Pomodoro.

    Screenshot of 'Keyboard Maestro → Pomodoro → Start'

  2. Clicking that allows configuring the next Pomodoro: the duration of each interval and the number of loops. This defaults to 4 loops of 25 minutes, for a total duration of 2 hours.

    Screenshot of "Keyboard Maestro → Pomodoro → Prompt"

  3. Starting a Pomodoro shows the remaining time.

    Screenshot of "Keyboard Maestro → Pomodoro → Stop"

  4. The break state is shown when relevant.

    Screenshot of "Keyboard Maestro → Pomodoro → Break"

  5. After the break, steps 3–4 are repeated, until there are no more loops remaining.

Since this is all done with Keyboard Maestro I can easily hook into any of my other macros. For example, when a Pomodoro starts it turns on Do Not Disturb and turns my desk light red, and at the end of a Pomodoro it resets both. This part is really up to you, but having it together with all other macros offers a lot of flexibility.

Macros

The macro group contains four individual macros, and is set to display in the menu bar with a title from the variable POMODORO_TITLE. It has no icon, since I prefer to set that through text to have it display in the same color as the text.

note: For custom icons you can download Apple's SF Symbols for free. This is the same set as is available within Keyboard Maestro itself.

Start

This macro contains two groups called "Logic" with some actions in between. Those macros in between are up to you, and aren't strictly necessary—they just allow for initiating anything else when starting a Pomodoro. The reason of grouping actions together in those "Logic" groups is purely to make it easier to indicate what's actually necessary for the functionality and where to add in custom actions.

In the first "Logic" group it first prompts for input, allowing configuration of the number of loops and the duration of each Pomodoro. I deliberately placed the Local Loops input first, since it seemed more likely to be customized than the duration. While the prompt is open, Enter will start the Pomodoro and Escape will close the prompt and cancel the macro.

In the second "Logic" group I use the configured duration to set the time remaining. This is used to keep track of the Pomodoro progress. I then enable the stop macro and disable this macro, which ensures that only one of them will ever be visible in the menu bar menu: "Start" when no Pomodoro is running, and "Stop" otherwise (see also my approach to starting and stopping modes). Finally, I execute the update macro.

Screenshot of "Keyboard Maestro → Pomodoro → Start"

Update

The first action saves the ID of the macro instance. This is later used to cancel that specific instance, which is needed in case a Pomodoro is stopped mid run.

The POMODORO_REMAINING number is then used to repeat a group of actions n times. First it sets the title, and then it pauses for 1 minute. I initially had this macro set up with the "Periodic Trigger", but since that executes every minute on the minute it didn't ensure an accurate timing.

Once the minute has passed, I decrease the POMODORO_REMAINING by 1. If the result is 0 the stop macro is triggered, and otherwise it goes back to the beginning of the repeating group.

Screenshot of "Keyboard Maestro → Pomodoro → Update"

Stop

Similarly to the start macro, this contains a "Logic" group and a few actions outside of it. These actions outside are again to allow for customization.

In the "Logic" group, first the earlier saved macro instance is canceled. As described, this is in case the Pomodoro is stopped prematurely through the menu bar item. Important to note here is that this is also the reason the "Execute Macro" action in the update macro was called asynchronously; if not, "Stop" would be seen as a child of the "Update" instance, having it cancel itself.

Next, the POMODORO_LOOPS variable is decreased by 1 to indicate that a run has passed. The following "If" check looks if this value is now 0 (meaning all loops have completed) or if the %TriggerValue% variable is not CONTINUE. That last one needs more explaining.

The stop macro is normally executed by the update macro, but it can also be triggered by clicking the "Stop Pomodoro" menu item that shows when opening up the menu bar menu. In that case, the %TriggerValue% would be empty, so to differentiate that from an automatic execution from the "Update" macro a parameter is passed along. With that, the stop macro knows to cancel the Pomodoro completely when stopped from the menu bar mid run.

If it's stopped completely, it will enable the start macro again and disable this macro, and it will delete all the global variables that were used earlier. That isn't strictly necessary, but I like to keep things nice and tidy.

If, instead, there are still more loops to run, it will set the title, pause for 5 minutes, and then execute the start macro again. This is done asynchronously for the same reason as described earlier.

Screenshot of "Keyboard Maestro → Pomodoro → Stop"

Set Title

This macro is set up as a subroutine. It accepts a parameter Local State, and then uses a switch action to update the POMODORO_TITLE variable in one of three ways:

Screenshot of "Keyboard Maestro → Pomodoro → Set Title"

Conclusion

This has been a fun exercise where I played around with the new subroutines and menu bar macro groups, and I'm happy with how it turned out. I'm not quite sure yet what else I'll use the menu bar feature for, but it's an interesting feature with lots of possibilities.

One improvement I'll probably make is to only enable this macro group when sitting at my desk. As with my Dock, I prefer to keep my menu bar tidy, and at my desk is also where it makes the most sense to use for me.

To download the complete macro group, click here: Pomodoro.