Skip to content

Instantly share code, notes, and snippets.

@bashbunni
Created January 4, 2023 16:28
Show Gist options
  • Save bashbunni/3880e4194e3f800c4c494de286ebc1d7 to your computer and use it in GitHub Desktop.
Save bashbunni/3880e4194e3f800c4c494de286ebc1d7 to your computer and use it in GitHub Desktop.
CLI Pomodoro for Linux
# study stream aliases
# Requires https://github.com/caarlos0/timer to be installed. spd-say should ship with your distro
declare -A pomo_options
pomo_options["work"]="45"
pomo_options["break"]="10"
pomodoro () {
if [ -n "$1" -a -n "${pomo_options["$1"]}" ]; then
val=$1
echo $val | lolcat
timer ${pomo_options["$val"]}m
spd-say "'$val' session done"
fi
}
alias wo="pomodoro 'work'"
alias br="pomodoro 'break'"
@brianbert
Copy link

Thank you. Yes, this is what I did, I copied the code at the bottom of it, saved it and closed it. But if I wanted to run 'work' or 'break' I got the error message: command not found.

did you try running it with wo and br ?

@bbazsi41
Copy link

bbazsi41 commented Jan 28, 2023

Yes, but unfortunately I got the same errors:
zsh: command not found: wo
zsh: command not found: br

@brianbert
Copy link

Yes, but unfortunately I got the same errors: zsh: command not found: wo zsh: command not found: br

Things you can try:

  1. Close your terminal and open it again, as the changes may not take effect until the terminal is restarted.
  2. Ensure that you have installed all necessary dependencies, such as timer, lolcat, and spd-say.
  3. Verify that the code you pasted is complete.
  4. Restart your system to see if that resolves the issue.
  5. Reinstall zsh and paste the code again.
  6. Realize that you were using Windows all along.
  7. Fall into despair and cry in the shower.
  8. Someone in the future will help you by posting the solution here. (happy ending)

@bbazsi41
Copy link

Except the last 3 points I did everyhing and now it is working with 'wo' and 'br'.
Thank you for your help!

@AIMadeScripts
Copy link

AIMadeScripts commented Jan 29, 2023

Use with:
./timer.sh work 10
./timer.sh break 10
Will be set in minutes.

Quick install instructions for debian:

sudo apt-get install lolcat
echo 'deb [trusted=yes] https://repo.caarlos0.dev/apt/ /' | sudo tee /etc/apt/sources.list.d/caarlos0.list
sudo apt update
sudo apt install timer

#!/bin/bash

clear

declare -A pomo_options
pomo_options["work"]="45"
pomo_options["break"]="10"

pomodoro () {
  if [ -n "$1" -a -n "${pomo_options["$1"]}" ]; then
    val=$1
    if [ -z "$2" ]; then
      minutes=${pomo_options["$val"]}
    else
      minutes=$2
    fi
    echo $val | lolcat
    timer $minutes"m"
    spd-say "'$val' session done"
  else
    echo "Usage: pomodoro <work|break> [minutes]"
  fi
}

if [ "$1" == "work" ]; then
  pomodoro "work" "$2"
elif [ "$1" == "break" ]; then
  pomodoro "break" "$2"
else
  echo "Usage: ./timer.sh <work|break> [minutes]"
fi

#Make sure to install https://github.com/caarlos0/timer
#And make sure to have lolcat installed```

@cornuel
Copy link

cornuel commented Jan 31, 2023

So simple yet very useful, thank you! πŸ’ͺ🏻

@hglbrg
Copy link

hglbrg commented Feb 14, 2023

I added some artificial intelligense neural network framework library laser surgery hack scripting hackerman logic to this:

# study stream aliases
# Requires https://github.com/caarlos0/timer to be installed. spd-say should ship with your distro

declare -A pomo_options
pomo_options["work"]="45"
pomo_options["break"]="10"

pomodoro () {
  if [ -n "$1" -a -n "${pomo_options["$1"]}" ]; then
  val=$1
  clear
  echo $val | lolcat
  timer ${pomo_options["$val"]}m
  spd-say "'$val' session done"
  fi
}

alias wo="pomodoro 'work'"
alias br="pomodoro 'break'"

which improves it by 405.33 (repeating of course) %

@paolojulian
Copy link

This is quite good.

Also, a suggestion of mine is that it would be nice if we can add like a "TODO" list along with it.

@Fonseca004
Copy link

How can i add this to my timer, i.e. where should i place this file?

@rosscondie
Copy link

I modified the script a bit just to adjust the duration and added a custom .wav that you could replace with whatever you wanted.

repo is here

Not sure if this was the best way to go about it all so if I have done anything in a long winded way I would love some feedback.

@OpenSourceLasagna
Copy link

OpenSourceLasagna commented Jun 8, 2025

I made an adjusted version, so you do not have to restart the timer manually and after 4 iterations a longer break is set - and you get notifications :)

pomodoro() {
  typeset -A pomo_options

  pomo_options["work"]=${1:-25}
  pomo_options["break"]=${2:-5}
  pomo_options["long_break"]=${3:-15}

  local current_phase="work"
  if [[ "$1" == "break" ]]; then
    current_phase="break"
  fi

  local pomodoro_count=0

  trap - INT

  while true; do
    local duration_key
    local notification_title
    local notification_text
    local notification_speaker

    if [[ "$current_phase" == "work" ]]; then
      pomodoro_count=$((pomodoro_count + 1))
      duration_key="work"
      notification_title="πŸ… Session done"
      notification_text="It is now time to take a <b>BREAK</b>!"
      notification_speaker="Break time"
    else
      if (( (pomodoro_count % 4) == 0 && pomodoro_count > 0 )); then
        echo "Taking a LONG BREAK!" | lolcat
        duration_key="long_break"
      else
        duration_key="break"
      fi
      notification_title="🧘 Break over"
      notification_text="Time to get back to <b>WORK</b>"
      notification_speaker="Work time"
    fi

    echo "$current_phase" | lolcat
    timer ${pomo_options["$duration_key"]}m
    local timer_exit_status=$?

    if [[ "$timer_exit_status" -ne 0 ]]; then
      echo "Pomodoro stopped."
      break
    fi

    notify-send -u normal -t 3000 -i alarm "$notification_title" "$notification_text"
    spd-say -t male3 -r -10 -p -100 "$notification_speaker"

    if [[ "$current_phase" == "work" ]]; then
      current_phase="break"
    else
      current_phase="work"
    fi
  done
  exit
}

alias pomo="pomodoro"
alias wo="pomodoro"
alias br="pomodoro break"

@junaid10144
Copy link

junaid10144 commented Jul 26, 2025

To use your .zshrc and the pomodoro function on WSL with Ubuntu 24.04, follow these steps:


βœ… 1. Install Required Tools

Before using your aliases and functions, install the required tools in your WSL environment:

sudo apt update
sudo apt install zsh lolcat espeak  # spd-say comes from speech-dispatcher or use espeak as fallback

Then install timer from GitHub (by caarlos0):

# Install Go (required for building the timer)
sudo apt install golang-go

# Clone and install the timer tool
git clone https://github.com/caarlos0/timer.git
cd timer
go build -o timer
sudo mv timer /usr/local/bin/

Now timer should be available system-wide.


βœ… 2. Ensure You're Using zsh in WSL

If you're not already using Zsh as your shell in WSL, switch to it:

sudo apt install zsh
chsh -s $(which zsh)

Then restart WSL or run zsh.


βœ… 3. Configure .zshrc

Put your function and aliases in the .zshrc file:

nano ~/.zshrc

Paste this:

# study stream aliases
# Requires https://github.com/caarlos0/timer to be installed. spd-say should ship with your distro

declare -A pomo_options
pomo_options["work"]="45"
pomo_options["break"]="10"

pomodoro () {
  if [ -n "$1" -a -n "${pomo_options["$1"]}" ]; then
  val=$1
  echo $val | lolcat
  timer ${pomo_options["$val"]}m
  spd-say "'$val' session done"
  fi
}

alias wo="pomodoro 'work'"
alias br="pomodoro 'break'"

Then reload it:

source ~/.zshrc

βœ… 4. Run the Commands

Now you can simply run:

wo   # starts a 45-minute "work" timer
br   # starts a 10-minute "break" timer

⚠️ Note on spd-say in WSL

spd-say may not produce audio output in WSL directly unless you have audio forwarding set up (via PulseAudio or similar). If it doesn't work, consider replacing spd-say with something like espeak or even just a notify-send (if running a Linux GUI).

Example:

espeak "'$val' session done"

or remove it if sound isn’t essential.


βœ… How to Send Windows Notifications from WSL

The only way to get native Windows notifications from WSL is to explicitly call Windows tools from WSL, like PowerShell.

βœ”οΈ Step-by-Step: Add Windows Toast Notification

πŸ”§ 1. Install the BurntToast module (Windows side)

In a Windows PowerShell terminal (not WSL), run:

Install-Module -Name BurntToast -Force -SkipPublisherCheck

You only need to do this once. BurntToast is a PowerShell module for sending toast notifications.


✏️ 2. Modify Your pomodoro Function

Update your function to use PowerShell from WSL to send a toast:

pomodoro () {
  if [ -n "$1" ] && [ -n "${pomo_options["$1"]}" ]; then
    val=$1
    echo $val | lolcat
    timer ${pomo_options["$val"]}m
    espeak "'$val' session done"
    powershell.exe -Command "New-BurntToastNotification -Text 'Pomodoro Timer', '$val session done'" > /dev/null 2>&1
  fi
}

This line:

powershell.exe -Command "New-BurntToastNotification -Text 'Pomodoro Timer', '$val session done'"

runs PowerShell on Windows from WSL, and sends the notification natively.


πŸ§ͺ 3. Test It

After timer finishes, you should:

  • βœ… Hear audio (espeak)
  • βœ… See a Windows toast notification pop up

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment