A Simple Pomodoro CLI
Tags: cli, bash, linux, pomodoro
Published: 2023-03-03 00:34:42


I've long been a fan of the Pomodoro Technique and recently I was looking to restart using it to focus my work. However, I ran into some problems finding the right tool for me. Below you'll see how I solved this problem and maybe this walk through will help someone.

Although the name of the Technique comes from seemingly ubiquitous kitchen timer that looks like a tomato (pomodoro in Italian), I do not have such a device. I was also looking for a solution that was all digital and that easily moved with me where ever I'm traveling and across computers so that I could better create the habit of using this time management technique.

---

## Existing Solutions

**Tomato Timer**
I admittedly did not do a super exhaustive look into the space. I have also used the Tomato-Timer site for many years. I like it. Check it out.
However, I realized I wanted to play with different durations of working periods. Tomato-Timer follows the Pomodoro Technique strictly so you'll get a 25 minute working period and either a 5 or 10 minute break period.

**Pomo**
Pomo is another CLI (command line interface) solution. It looks very mature and full featured. I haven't used it personally but it looks good if you're looking for graphics related to status of your poms and it looks like it integrates into your projects to allow for time tracking. It does allow you to adjust durations of poms so this checked that box for me. [If you've used it let me know if my understanding is inaccurate and I'll update.]

However, I'm looking for something dead simple. I don't need graphics, a UI, integrated workflows, a server running, or an underlying datastore. Eventually maybe I'll have a need for such things but right now let's start with something more simple.

---

##Something More Simple
So where to turn next? Why not just make a (very) little shell script that does exactly what I need.
What do I need exactly?
I want to kick off a pom for a variable number of minutes (default 25), have it run in the background, and play a sound when it's complete (I'm not going to watch it - I'm going to be working).


```
$ pom 5
Waiting 5 minutes
Timer is done // Note: sound plays
```

No big deal right? I think this can be done in a few minutes.

## Shell Script

The above requirement is relatively easily done with just a few lines of shell script. I did this on MacOS but I'm sure with Linux and now Windows it would be trivial to make a similar version if this doesn't directly work there.
This plays to one of my favorite architectural guides - The Unix Philosophy - which emphasizes simplicity and modularity. Which also is the foundation for all of the sweet command line goodies you already use.

## Playing Sound
I thought this might be difficult but it turns out to be very easy to make sounds with Mac and I assume the same on any OS. I went with the text to speech solution of "say"

```
$ say Done
```

Bonus points: Entertain the kids…

```
$ say its time for bed
```

## Waiting
Sleep is a pretty standard command and with it we can build a very small version of the end goal: A script that will just sleep a bit of time and then use 'say' to tell you the wait is done.

```
sleep 60
say "Done"
```

## Doing the Math

Notice that 'sleep' works in seconds and I wanted to give input in minutes so let's do some math. This actually was the trickiest part of the whole script, I guess because I just hadn't done much math in shell scripts before.
I just had to use 'let' and the script was finicky about spaces, but the incantation looks like this:

```
let seconds=1*60
sleep $seconds
say "Done"
```

## Taking Input

A primary requirement of the solution is giving the user the ability to chose their own duration of the pom. I would take in a number of minutes and default it to the standard 25 from the official Technique.

I'm going to have to use the built-in $1 variable which is the standard 1st position parameter into the script, this will tell me the value of what's passed in. But we also want to allow for a default of nothing passed in so we'll need to check the input.

```
if [ -z "$1" ]; then
 let min=25
else
 let min=$1
fi
echo "Waiting ${min} minutes"
```

Putting this into an executable file named "iftest" for now:

```
$ ./iftest
Waiting 25 minutes

$ ./iftest 5
Waiting 5 minutes
```

##Putting It All Together

Now just a few echos to tell the user that things are happening as expected and voila!

```
if [ -z "$1" ]; then
 let min=25
else
 let min=$1
fi
let seconds=$min*60
echo "Waiting ${min} minutes"
sleep $seconds

msg="Timer is done"
say $msg
echo $msg
```

## Final result

Pull down the working pom command [here](https://github.com/byronsalty/pom).