# pomo is a terminal Pomodoro timer that keeps statistics in a local SQLite file

> pomo is a Go terminal Pomodoro timer built with Bubble Tea, with configurable work and break durations, task chaining, a live progress bar, ASCII art timer fonts, desktop notifications, custom commands on completion and a pomo stats subcommand that draws a weekly bar chart and a four-month heatmap. It is MIT licensed, installable through Homebrew, Winget, Go or Nix, and configurable from a YAML file.

**Bahaaio/pomo** — Customizable TUI Pomodoro timer with ASCII art, progress bar, desktop notifications, and productivity statistics.

- Repository: https://github.com/Bahaaio/pomo
- Stars: 529 · Forks: 28
- Language: Go
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/bahaaio-pomo

## What it does on a normal day

pomo is a simple, customizable Pomodoro timer for your terminal, built with Bubble Tea.

The command line is the whole interface for starting a session:

```bash
pomo                    # work session
pomo 30m                # 30m work session
pomo 45m 15m            # 45m work with 15m break
pomo -t "write report"  # work session with custom title (or --title)
```

And breaks are a separate subcommand rather than a flag:

```bash
pomo break              # break session
pomo break 10m          # 10m break session
```

The distinction is small but it is the right one. A break started on its own is not a break that follows a work session, and treating them as different commands keeps the session count clean for the statistics.

The feature list covers more than the timer itself. There are work and break sessions, and Pomodoro cycles with a long break. There is task chaining with user confirmation prompts, so a work session can be followed by another without you having to notice the break ended. There is a real-time progress bar visualisation, keyboard shortcuts to adjust time mid-session, pause and resume, and skip to next session.

Then the parts that take it beyond a stopwatch. Cross-platform desktop notifications, so the timer can live in another terminal. Custom commands when timers complete, which is how you get a sound. And a clean, minimal terminal UI with ASCII art timer fonts.

The keyboard shortcuts are worth spelling out because they are what you actually touch while working. The up arrow or k increases the time by one minute, the left arrow or h resets to the initial duration, Space pauses and resumes, s skips to the next session, and q or Ctrl+C quits. Skip bypasses any prompts, which matters when you are chaining tasks.

The primary language is Go, the licence is MIT, and the last push was on 2026-06-06, with the most recent release v1.2.1 from 2026-03-13.

## The timer display, and the fonts

The ASCII art timer is the part of pomo that makes it recognisable in a screenshot, and there are four font choices.

The font options are mono12, rebel, ansi and ansiShadow, with mono12 as the default, and the configuration example sets a different one to show how it is chosen. Alongside the font there is a color setting that takes either a hex color or none, and the example uses #5A56E0, so the timer can be tinted to match your terminal theme.

The four fonts differ in how they are drawn rather than in what they show. mono12 is a wide block font, rebel is a different block style, ansi is a plain single-width rendering, and ansiShadow adds a shadow effect to the ansi form. The configuration reference notes that the asciiArt option can be disabled altogether, which is the setting to reach for on a terminal that cannot render the block characters cleanly.

That setting matters more than it looks. Block-drawing characters occupy the same cell as ordinary text but are drawn from a different range of the character set, and a terminal with a limited font or an unusual configuration renders them as replacement characters. The default is the widest font, so if pomo looks like a row of boxes rather than digits, turning asciiArt off is the fix.

The four images in the readme are laid out as a table, one per font, which is a reasonably efficient way to show what each looks like without four separate paragraphs of description.

Everything the timer renders is drawn with lipgloss, the styling library from the same Charm ecosystem as Bubble Tea, which is what allows the color and the ASCII art to be controlled from configuration rather than hard-coded.

## Configuration, and where the file is looked for

pomo looks for its config file in a defined order, and the order matters when you are debugging why a setting is not taking effect.

The current directory wins first, with pomo.yaml at the highest priority. Then the system config directory, which is ~/.config/pomo/pomo.yaml on Linux and macOS and %APPDATA%\pomo\pomo.yaml on Windows. And if no config file is found at all, the built-in defaults apply.

Putting pomo.yaml in the current directory first is a deliberate choice for a tool you might run from a project directory, and it means a per-project configuration overrides a global one without any flag. The risk is the inverse: a stray pomo.yaml in whatever directory you happen to be in silently changes the behaviour of the timer, and since the file is named the same everywhere you cannot tell from the command line which one was used.

The example configuration shows the shape of the file. onSessionEnd takes 'ask', 'start' or 'quit', and it defaults to ask, which means that when a session completes the timer stops and asks you what to do rather than rolling straight into the next one. That is the right default for a focus timer, because the automatic transition is what breaks the technique: a break that starts while you are still working is not a break.

The work section has a duration, a title, and a notification block with enabled, urgent, title, message and icon settings. The urgent flag means a persistent notification with an alert sound, and the documentation notes it is platform-dependent. The break section has its own duration and a then list of commands to run when the session ends.

The longBreak section is where the Pomodoro cycle lives. It is enabled, it triggers after a number of work sessions, four in the example, and it has its own duration of 15m.

A full example with every option is kept in the repository as pomo.yaml, which is the file to copy as a starting point rather than writing the whole thing from the readme excerpt.

## Commands, sounds and the five second timeout

The then lists are how pomo does anything outside its own UI, and the sound notification is the most common use.

```yaml
work:
  then:
    - [paplay, ~/sounds/work-done.mp3] # Linux
    # - [afplay, ~/sounds/work-done.mp3] # macOS
    # - [powershell, start, work-done.mp3] # Windows
```

Each entry is a command and its arguments as a YAML sequence, so paplay on Linux, afplay on macOS and powershell on Windows are three ways to play the same file. The commented-out lines in the example are there to be uncommented rather than to be invented.

The rule that governs all of these is short and worth knowing: commands run with a 5 second timeout and are automatically cancelled when starting the next session.

Both halves of that sentence matter. The timeout stops a command that hangs from blocking the timer, which would otherwise leave the session stuck. The automatic cancellation on starting the next session means a long-running command does not keep running in the background after you have moved on, which is what you want when the command is a sound that should stop when the next work session begins.

The desktop notification is a separate mechanism from the then commands. pomo sends native desktop notifications when sessions complete, with the readme showing Linux GNOME and Windows examples and a note that the actual appearance varies by operating system and desktop environment.

The Go dependencies explain how the notifications are done. beeep at 0.11.1 is the cross-platform notification library, and it in turn pulls in a Windows toast library, an OSC 52 terminal library and a Linux notification daemon client, which is the standard approach for reaching three quite different notification systems from one call.

## The statistics view and where the data lives

The statistics subcommand is the part of pomo that makes it more than a timer.

```bash
pomo stats              # View your productivity stats
```

It reports a duration ratio, which is total work time against total break time. It draws a weekly bar chart of daily work hours for the past seven days. And it renders a four-month heatmap, described as a GitHub-style activity visualisation.

The heatmap has a dependency worth naming: heatmap icons require a Nerd Font. That is the patched font family that adds a large set of extra glyphs, and without it the cells in the heatmap render as boxes or blanks. It is the same caveat that applies to any terminal status line that draws an activity graph.

The data is local. The repository layout shows a db/ directory and the go.mod includes both sqlx for SQL access and modernc.org/sqlite for the driver, along with testify for the tests. So the session history is a SQLite file on your machine, which means the statistics are private by construction and need no account, and also that they are lost if you delete the file or run the timer from a different home directory.

The four-month window is a reasonable default for a heatmap, since a year of daily cells is unreadable in a terminal at a normal font size, and the weekly bar chart covers the recent period where the resolution is still useful.

The statistics are only as good as the record, and the record is whatever the timer observed. That is the same limitation as any self-reported tracker, and it is why the ratio of work to break time is the more informative number than the total hours: a day with four hours of work and no breaks is not the same as four hours of work with breaks taken.

## Installing it, and the four routes

There are four ways to install pomo and they cover the usual cases.

Homebrew on macOS:

```bash
brew install --cask bahaaio/pomo/pomo
```

Winget on Windows:

```powershell
winget install Bahaaio.pomo
```

Go, if you have the toolchain:

```bash
go install github.com/Bahaaio/pomo@latest
```

And pre-built binaries from the releases page, which is the route for anyone who wants none of the above.

There is also a Nix flake, with two options. The first is to add it to your flake inputs and then to your system packages:

```nix
pomo = {
  url = "github:Bahaaio/pomo";
  inputs.nixpkgs.follows = "nixpkgs";
};
```

and then add the package:

```nix
environment.systemPackages = with pkgs; [
  inputs.pomo.packages.${pkgs.stdenv.hostPlatform.system}.default
];
```

The second Nix option is to run it directly without adding it to your configuration:

```bash
nix run github:Bahaaio/pomo
```

The repository has flake.nix and flake.lock at the root, so the flake is a first-class part of the project rather than an afterthought.

Building from source is the last option and takes three commands:

```bash
git clone https://github.com/Bahaaio/pomo
cd pomo
go build .
```

The module is github.com/Bahaaio/pomo and it requires Go 1.25.0. The command line is built with cobra, configuration is read with viper, the terminal UI is Bubble Tea with bubbles for the components and lipgloss for the styling, and the repository has a cmd/ directory for the subcommands, a config/ directory, a ui/ directory, a db/ directory, and a .goreleaser.yaml for the release builds.

## Conclusion

pomo suits someone who wants a focus timer that lives in the terminal and keeps a record of how the time was actually spent, since the statistics are local SQLite and the work to break ratio is the number most people want to see. It is the wrong tool if you need team visibility or time tracking that someone else can audit, because the database is a local file on your machine, and it is the wrong tool if you want a web or mobile timer. Before you start, write a pomo.yaml, because the default onSessionEnd of ask means the timer will stop and prompt you at the end of every session, and set the then commands for your platform since the sound notification examples differ between Linux, macOS and Windows.

## FAQ

### What is pomo?

It is a simple, customizable Pomodoro timer for your terminal, written in Go and built with Bubble Tea. It offers work and break sessions, cycles with a long break, task chaining with confirmation prompts, a real-time progress bar, mid-session keyboard adjustments, pause and resume, skip, desktop notifications, custom commands on completion and ASCII art timer fonts.

### How do I start a pomo session?

Run pomo for a default work session, pomo 30m for a 30 minute work session, pomo 45m 15m for 45 minutes of work with a 15 minute break, and pomo -t "write report" to set a title. Break sessions use the break subcommand, as in pomo break or pomo break 10m.

### Where does pomo look for its configuration file?

In order of priority: pomo.yaml in the current directory, then the system config directory, which is ~/.config/pomo/pomo.yaml on Linux and macOS and %APPDATA%\pomo\pomo.yaml on Windows, and finally the built-in defaults if no file is found. The repository ships a full pomo.yaml with every option as a starting point.

### How do I get a sound when a session ends?

Add a command to the then list of the work or break section, using a YAML sequence of the command and its arguments, such as [paplay, ~/sounds/work-done.mp3] on Linux, with afplay and powershell shown for macOS and Windows. Commands run with a 5 second timeout and are cancelled automatically when the next session starts.

### What does pomo stats show?

A duration ratio of total work against total break time, a weekly bar chart of daily work hours for the past seven days, and a four-month heatmap in the style of a GitHub activity graph. The heatmap icons require a Nerd Font. The session data is kept in a local SQLite database.

### How do I install pomo?

With brew install --cask bahaaio/pomo/pomo on macOS, winget install Bahaaio.pomo on Windows, go install github.com/Bahaaio/pomo@latest if you have Go, or by downloading a pre-built binary from the releases page. There is also a Nix flake that can be added to your system packages or run directly with nix run github:Bahaaio/pomo, and building from source takes a clone and go build .

## Sources

- [Bahaaio/pomo on GitHub](https://github.com/Bahaaio/pomo)
- [Issues](https://github.com/Bahaaio/pomo/issues)
- [License: MIT](https://github.com/Bahaaio/pomo/blob/main/LICENSE)
- [README](https://github.com/Bahaaio/pomo/blob/main/README.md)
- [Releases](https://github.com/Bahaaio/pomo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bahaaio-pomo
