SH | Blog

In the middle of the desert you can say anything you want

12 Nov 2018

Pomodoro timers in i3 statusbar

The Pomodoro Technique

Pomodoro is an awesome productivity technique, one of the few that work for me, consistently, more than five years now. If you have not heard of it, the basic idea is the following:

  1. Decide on the task to be done.
  2. Set the pomodoro timer (traditionally to 25 minutes).
  3. Work on the task.
  4. End work when the timer rings and put a checkmark on a piece of paper.
  5. If you have fewer than four checkmarks, take a short break (3–5 minutes), then go to step 2.
  6. After four pomodoros, take a longer break (15–30 minutes), reset your checkmark count to zero, then go to step 1. 1

Now playing: Iggy Pop – The Passenger

This works, for me usually 15 / 5 minutes, depending on the complexity of the task. For things that are very hard to do or for times when I don’t feel well at all, switching helps immensely. Usually it’s 5 minutes of a task that requires a lot of willpower, 5 minutes of something easier, 5+ minutes of pause. For tasks requiring more uninterrupted contentration, tasks that are easier for me, and when I feel well and productive, I go for 25 minutes / 5 minutes of pause.

This system is also nice because it implements the age-old rule of “rest before you are tired”. (I found that when I feel tired, it’s probably too late to rest, and my productivity is already impaired. I can force myself through it, but it would mean that I’d pay for it the next day.)  So the best metric I found for the exact ratio is the amount of willpower it takes to do something.

To implement this, I always used, and it’s absolutely perfect. You can even drag and drop individual timers and create bookmarks out of them:

i3 / i3status

But since I use it really a lot, I decided to make another keyboard shortcut for a timer, and visualize it in my i3 statusbar, to have a nice overview.

i3 is a(n awesome) tiling windows manager for Linux. Its statusbar is controlled in .i3/config:

bar {
    output eDP
    status_command i3status --config=~/.i3status-small | ~/.i3/
    strip_workspace_numbers yes
    mode hide
    modifier Mod4
    position bottom

This is the config for my smaller screen, which hides the statusbar except Mod4 (=Win) is pressed. It executes status_command, which in turn generates a statusbar with i3status using a certain config file, and then pipes the output through .i3/

My .i3status-small is not too creative. Maybe the only nontrivial thing is a run_watch which tells me if a VPN is running:

run_watch VPN {
        pidfile = "/etc/openvpn/"

It checks if the file /etc/openvpn/ exists, if it does – the VPN in running. The vpn is run via the following aliased command:

alias o=’sudo openvpn –writepid /etc/openvpn/ –config’

The result looks like this (click to enlarge)

i3status wrapper for custom commands

Now playing: Les Miserables 10th anniversary version – The Confrontation

First, I researched possible timers. Found utimer, It’s perfect.

Its output looks like this:

I added the following lines in .i3/config. The first line executes utimer, countdown 15 minutes, pipes the output to a textfile and plays a sound at the end of its execution. Third line kills the player.

# Timers
    bindsym Mod3+n exec "utimer -c 15m > ~/s/sounds/outpomo && mpg123 -q ~/s/sounds/tib.mp3"
    bindsym Mod3+Shift+s exec "utimer -c 5m > ~/s/sounds/outpause && mpg123 -q ~/s/sounds/cl.mp3"
    bindsym Mod3+k exec "killall mpg123"

I needed to prepend the timers to the statusbar, so I cound see how much time is left. For this, I used this excellent wrapper script. It’s built based on i3statusbar’s input protocol, documented here.

I added the following lines, heavily commented:

{% highlight javascript %} j = json.loads(line)

    # Files with the output of utimer:

    def rtime(tfile, color):
        with open(tfile, "r") as f:
            # last line of the file
            except IndexError:
        # Utime seems to add a \n(^M?); at the end 
        # We use it as a way to check that the timer has stopped
        # When it stops, a \n is added.
        if "\n" not in t:
            j.insert(0, {'full_text': '%s' % to, 'color':'%s'%color})


    rtime(tfile, tcolor1)
    rtime(tfile3, tcolor3)
    rtime(tfile2, tcolor2)


{% endhighlight %}

It’s quite a dirty solution, but it works. When there’s text, it gets outputted on screen after being split. If the timer program finishes, it outputs a \n instead of a ^M, and nothing is shown. They are colored so I know which timer is which.

I also added  a  third timer, which I can run from CLI and which both makes a sound and a popup, with optional text. Heavily based on this forum post. Its file also gets read by

tm() {
  local N=$1; shift
  (utimer -c > ~/s/sounds/outbash $N && mpg123 -q ~/s/sounds/tib.mp3  &
      zenity --info --title="Time's Up" --text="${*:-BING}")

The statusbar with all three timers active looks like this:

Sometimes they break, probably because of the hack-y way I use to read the files outputted by the timer. Restarting i3 (which does not close any programs and is not a problem) helps, I have a shortcut for that.

The sounds I use are and



Nel mezzo del deserto posso dire tutto quello che voglio.