Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction Tomat logo

Welcome to the documentation for Tomat 2.8.1, a customizable and lightweight Pomodoro timer designed for seamless integration with waybar and other status bars.

To get started, have a look at Getting Started for a quick guide to install and setup Tomat.

Contents

This documentation includes the following sections:

Additional Resources

Support

Contributing

Contributions are welcome! Please see the Contributing Guide for details on how to get involved.

Getting Started

Tomat (“tomato” in Swedish 🇸🇪) is a Pomodoro timer designed for seamless integration with Waybar and other status bars. It consists of a background service (daemon) that manages the timer state and a command-line client to control the timer and query its status.

If you are new to the Pomodoro technique, it is a time management method that breaks work into intervals (typically 25 minutes) separated by short breaks. This approach helps improve focus and productivity by encouraging regular breaks to rest and recharge.

graph TD
    A[25 min work] -->|Sessions 1-4| B[5 min break]
    B --> A
    A -->|Session 5| C[15 min long break]
    C --> A
An illustration of the Pomodoro technique.

Installation

The easiest way to install Tomat is to download a pre-built binary from the releases page, or use your package manager if available:

# Download pre-built binary (x86_64)
curl -L https://github.com/jolars/tomat/releases/latest/download/tomat-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv tomat /usr/local/bin/

# Or install via Cargo
cargo install tomat

# Or on Arch Linux (AUR)
paru -S tomat-bin

See the installation guide for more options including DEB/RPM packages, NixOS, and building from source.

Basic Usage

The next step is to start the daemon:

tomat daemon start

After that, you can start a Pomodoro session by calling

tomat start

You can check the current status of the timer with:

tomat status

Which by default returns a JSON object suitable for Waybar integration:

{
  "text": "🍅 25:00 ⏸",
  "tooltip": "Work (2/4) - 25.0min (Paused)",
  "class": "work-paused",
  "percentage": 0.0
}

See the CLI Reference for a full list of commands and options.

Systemd Service Setup

Most users will want to run the Tomat daemon as a systemd user service so that it starts automatically on login. Tomat provides a convenience command to install the service:

tomat daemon install

After that, you can enable and start the service with:

systemctl --user enable tomat.service --now

Status Bar Integration

The last step is to integrate Tomat with your status bar. To for instance set up Waybar, simply add the following module to your Waybar configuration:

{
  "modules-right": ["custom/tomat"],
  "custom/tomat": {
    "exec": "tomat status",
    "interval": 1,
    "return-type": "json",
    "format": "{text}",
    "tooltip": true,
    "on-click": "tomat toggle",
    "on-click-right": "tomat skip"
  }
}

The documentation features integration guides for several popular status bars, including Waybar, Polybar, and others.

Configuration

Tomat can be configured via a configuration file located at $XDG_CONFIG_HOME/tomat/config.toml (usually ~/.config/tomat/config.toml). Here is a basic example to get you started:

[timer]
work = 25.0
break = 5.0
long_break = 15.0
sessions = 4
auto_advance = "none"

See the Configuration Guide for a detailed explanation of all available configuration options

Architecture

Tomat uses as a client–server architecture consisting of a daemon that runs in the background and a command-line client that sends commands to the daemon via a Unix socket located at $XDG_RUNTIME_DIR/tomat.sock.

graph TD
    A[Client] -->|Commands| B(Server)
    B -->|Status| A
    B -->|Notifications| C[Notification System]
    B -->|Sound| D[Sound System]
Overview of Tomat's architecture.

The purpose of this is to avoid having the timer be tied to the lifetime of the calling process, which allows several different clients to interact with the same timer instance and also prevents the need to save and restore states on status bar restarts.

The daemon is also responsible for sending desktop notification, sound alerts, and calling hooks.

Installation Instructions

This section provides instructions on how to install Tomat, a customizable Pomodoro timer.

Pre-built Binaries

The easiest way to install Tomat is to download a pre-built binary from the releases page. Binaries are available for multiple architectures and distributions:

  • Generic Linux (x86_64, aarch64): .tar.gz archives
  • Debian/Ubuntu: .deb packages
  • Fedora/RHEL/openSUSE: .rpm packages

Generic Binary

# Download and install (x86_64)
curl -L https://github.com/jolars/tomat/releases/latest/download/tomat-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv tomat /usr/local/bin/

# Or for ARM64
curl -L https://github.com/jolars/tomat/releases/latest/download/tomat-aarch64-unknown-linux-gnu.tar.gz | tar xz
sudo mv tomat /usr/local/bin/

Debian/Ubuntu Package

curl -LO https://github.com/jolars/tomat/releases/latest/download/tomat_amd64.deb
sudo dpkg -i tomat_amd64.deb

The DEB package includes the systemd service and shell completions.

RPM Package (Fedora/RHEL/openSUSE)

curl -LO https://github.com/jolars/tomat/releases/latest/download/tomat-x86_64.rpm
sudo rpm -i tomat-x86_64.rpm

The RPM package includes the systemd service and shell completions.

Package Managers

Arch Linux (AUR)

Tomat is available in the AUR as tomat-bin:

# Using your favorite AUR helper
paru -S tomat-bin
# or
yay -S tomat-bin

NixOS

If you are using NixOS, Tomat is available in the official packages:

{
  environment.systemPackages = [
    pkgs.tomat
  ];
}

You still need to set up the systemd service for automatic startup.

Home Manager

But if you’re using home manager, you’re in luck! Tomat is supported as a module:

{
  services.tomat = {
    enable = true;

    settings = {
      timer = {
        work = 25;
        break = 5;
      };
    };
  };
}

Install from Crates.io

You can also install Tomat via Cargo from crates.io. If you don’t have Rust and Cargo installed, follow the instructions at https://www.rust-lang.org/tools/install first to set up your Rust environment.

cargo install tomat

Building from Source

Anoter way to install Tomat is to build it from source. First, clone the repository:

git clone https://github.com/jolars/tomat.git
cd tomat

Prerequisites

On Linux systems, audio notifications require ALSA development libraries:

# Ubuntu/Debian
sudo apt-get install libasound2-dev

# Fedora/RHEL
sudo dnf install alsa-lib-devel

# Arch Linux
sudo pacman -S alsa-lib

Build and Install

Then, build and install Tomat using Cargo:

cargo install --path .

Note

Audio will be automatically disabled if ALSA is not available. The timer will still work normally, but with desktop notifications only.

Systemd Service Setup

Most users will want to run the Tomat daemon as a systemd user service so that it starts automatically on login. Tomat provides a convenience command to install the service:

tomat daemon install

After that, you can enable and start the service with:

systemctl --user enable tomat.service --now

Alternative Manual Setup

If you prefer to set up the systemd service manually, you can copy the service file from the examples directory:

# Manual systemd setup (if you prefer)
mkdir -p ~/.config/systemd/user
curl -o ~/.config/systemd/user/tomat.service https://raw.githubusercontent.com/jolars/tomat/main/assets/tomat.service
systemctl --user daemon-reload
systemctl --user enable tomat.service --now

Configuration Guide

Tomat supports comprehensive configuration via a TOML file located at $XDG_CONFIG_HOME/tomat/config.toml (typically ~/.config/tomat/config.toml). This allows you to set default values for timer durations and behaviors without specifying them on every command.

The configuration file is organized into five main sections, which are documented in detail in the configuration reference.

Example

Here’s a minimal example of the [timer] section, showing the default values:

[timer]
work = 25.0
break = 5.0
long_break = 15.0
sessions = 4

Tip

Ready-to-use configuration files are available in the examples/ directory. Copy the complete example config to get started quickly.

mkdir -p $XDG_CONFIG_HOME/tomat  # or: mkdir -p ~/.config/tomat
cp examples/config.toml $XDG_CONFIG_HOME/tomat/config.toml
# Then edit the config file as needed

Configuration Priority

Settings are applied in the following order, with later sources overriding earlier ones:

  1. Built-in defaults

    Standard Pomodoro timings (25min work, 5min break, 15min long break, 4 sessions).

  2. Config file

    Values from $XDG_CONFIG_HOME/tomat/config.toml.

  3. CLI arguments

    Flags passed to tomat start command.

This means you can set your preferred defaults in the config file and still override them on a per-session basis using command-line flags.

Complete Configuration Example

Here’s a complete configuration file with all available options:

# $XDG_CONFIG_HOME/tomat/config.toml

# Timer durations and behavior
[timer]
work = 25.0           # Work session duration in minutes
break = 5.0           # Break duration in minutes
long_break = 15.0     # Long break duration in minutes
sessions = 4          # Number of work sessions before long break
auto_advance = "none" # Auto-advance mode: "none", "all", "to-break", "to-work"

# Sound notifications
[sound]
enabled = true        # Enable sound notifications
system_beep = false   # Use system beep instead of sound files
use_embedded = true   # Use embedded sound files
volume = 0.5          # Volume level (0.0 to 1.0)
# Optional: Custom sound files (will override embedded sounds)
# work_to_break = "/path/to/custom/work-to-break.wav"
# break_to_work = "/path/to/custom/break-to-work.wav"
# work_to_long_break = "/path/to/custom/work-to-long-break.wav"

# Desktop notifications
[notification]
enabled = true        # Enable desktop notifications
icon = "auto"         # Icon mode: "auto" (embedded), "theme" (system), or "/path/to/icon.png"
timeout = 5000        # Notification timeout in milliseconds
urgency = "normal"    # Urgency level: "low", "normal", "critical"
# Optional: Custom notification messages
# work_message = "Break time! Take a short rest ☕"
# break_message = "Back to work! Let's focus 🍅"
# long_break_message = "Long break time! Take a well-deserved rest 🏖️"

# Display formatting
[display]
text_format = "{icon} {time} {state}"  # Text display template

Integration Guide

Tomat can be integrated with various status bars, notification systems, and service managers to enhance your productivity experience. This guide provides step-by-step instructions for setting up these integrations.

Status Bar Integration Guide

Tomat can be integrated with various status bars to display timer information in real-time. In this section, we provide configuration examples for popular status bars.

Waybar

Tomat is designed specifically for Waybar integration with rich JSON output and CSS styling support.

Basic Configuration

Add this to your waybar config (~/.config/waybar/config):

{
  "modules-right": ["custom/tomat"],
  "custom/tomat": {
    "exec": "tomat status",
    "interval": 1,
    "return-type": "json",
    "format": "{text}",
    "tooltip": true,
    "on-click": "tomat toggle",
    "on-click-right": "tomat skip"
  }
}

Styling

Add CSS styling (~/.config/waybar/style.css):

#custom-tomat {
  padding: 0 10px;
  margin: 0 5px;
  border-radius: 5px;
}

#custom-tomat.work {
  background-color: #ff6b6b;
  color: #ffffff;
}

#custom-tomat.work-paused {
  background-color: #ff9999;
  color: #ffffff;
}

#custom-tomat.break {
  background-color: #4ecdc4;
  color: #ffffff;
}

#custom-tomat.break-paused {
  background-color: #7dd3db;
  color: #ffffff;
}

#custom-tomat.long-break {
  background-color: #45b7d1;
  color: #ffffff;
}

#custom-tomat.long-break-paused {
  background-color: #74c0db;
  color: #ffffff;
}

JSON Output Format

Tomat provides waybar-optimized JSON output:

{
  "text": "🍅 24:30 ▶",
  "tooltip": "Work (1/4) - 25.0min",
  "class": "work",
  "percentage": 2.0
}

Fields:

  • text: Display text with icon and status symbols
  • tooltip: Detailed information for hover
  • class: CSS class for styling
  • percentage: Progress percentage (0-100)

CSS Classes:

  • work / work-paused - Work session running/paused
  • break / break-paused - Break session running/paused
  • long-break / long-break-paused - Long break running/paused

Visual Indicators:

  • Icons: 🍅 (work), ☕ (break), 🏖️ (long break)
  • State: ▶ (running), ⏸ (paused)

Polybar

Polybar

To integrate Tomat with Polybar, you can create a custom module that executes the tomat status command to display the current timer status. Below is an example configuration snippet that you can add to your Polybar configuration file (usually located at ~/.config/polybar/config).

[module/tomat]
type = custom/script
exec = tomat status --output plain
interval = 1
click-left = tomat toggle
click-right = tomat skip
format-prefix = " "
format-foreground = #ffffff

i3status-rust

Tomat provides native support for i3status-rust with a dedicated output format:

[[block]]
block = "custom"
command = "tomat status --output i3status-rs"
interval = 1
json = true

[[block.click]]
button = "left"
cmd = "tomat toggle"

[[block.click]]
button = "right"
cmd = "tomat skip"

The i3status-rs format provides:

text
Display text with timer and status icons
short_text
Same as text (for abbreviated display)
state
Timer state mapping (Critical=work, Good=break, Info=paused)

i3status

For i3status compatible bars like i3bar, you can use a helper script. First, add this to your i3status config:

order += "read_file tomat"

read_file tomat {
    path = "/tmp/tomat-status"
    format = "%content"
}

Helper script:

#!/bin/bash
while true; do
    tomat status --output plain > /tmp/tomat-status
    sleep 1
done

i3blocks

i3blocks works perfectly with Tomat’s plain text output mode.

Simple Integration

[tomat]
command=tomat status --output plain
interval=1

With Click Support

[tomat]
command=tomat status --output plain
interval=1
signal=10

Add click handling with environment variables:

#!/bin/bash
# ~/.config/i3blocks/scripts/tomat-click
case $BLOCK_BUTTON in
    1) tomat toggle ;;     # Left click: toggle
    3) tomat skip ;;       # Right click: skip
esac
pkill -RTMIN+10 i3blocks   # Refresh the block

Then set as the command: command=~/.config/i3blocks/scripts/tomat-click

Notification Systems

Tomat uses the notify-rust crate to send desktop notifications, which supports a variety of notification daemons on Linux systems. Below are instructions for integrating Tomat with popular notification systems.

Mako (Wayland)

Tomat works perfectly with mako out of the box using the embedded icon system:

# Default configuration works automatically
# Icon will be cached to ~/.cache/tomat/icon.png

For custom mako styling, add to ~/.config/mako/config:

[app-name="Tomat"]
background-color=#2d3748
text-color=#ffffff
border-color=#4a5568
default-timeout=5000

Dunst (X11)

For dunst notification daemon:

# Works with default configuration
# Uses embedded icon or theme icon as fallback

Custom dunst rules (~/.config/dunst/dunstrc):

[tomat]
appname = "Tomat"
background = "#2d3748"
foreground = "#ffffff"
timeout = 5000

Custom Notification Icons

To use a custom notification icon:

# ~/.config/tomat/config.toml
[notification]
icon = "/path/to/your/custom-icon.png"

Service Management

Tomat uses a daemon (server) to manager its timers in the background. Most users will want to set up tomat to start automatically when they log in. This is typically done using systemd user services on Linux systems.

Systemd

Setup

Install the service file and enable auto-start:

# Copy service file
curl -o ~/.config/systemd/user/tomat.service https://raw.githubusercontent.com/jolars/tomat/main/assets/tomat.service

# Enable auto-start
systemctl --user enable tomat.service
systemctl --user start tomat.service

If you prefer to create the service file manually (~/.config/systemd/user/tomat.service):

[Unit]
Description=Tomat Pomodoro Timer Daemon
After=graphical-session.target

[Service]
Type=simple
ExecStart=%h/.cargo/bin/tomat daemon run
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

Management

The service is managed using standard systemctl commands:

# Check status
systemctl --user status tomat.service

# View logs
journalctl --user -u tomat.service -f

# Restart service
systemctl --user restart tomat.service

# Disable auto-start
systemctl --user disable tomat.service

Troubleshooting Guide

This guide covers common issues and their solutions when using tomat.

Getting Help

If you’re still experiencing issues, check existing issues on GitHub and the discussion board for similar problems and solutions.

If you cannot find a solution, please open a new issue or discussion.

Installation Issues

ALSA Library Missing

Problem

Audio notifications don’t work, or you get ALSA-related errors.

Solution

# Ubuntu/Debian
sudo apt-get install libasound2-dev

# Fedora/RHEL
sudo dnf install alsa-lib-devel

# Arch Linux
sudo pacman -S alsa-lib

Note: Audio will be automatically disabled if ALSA is not available. The timer will still work normally with desktop notifications only.

Cargo Install Fails

Problem

cargo install tomat fails with compilation errors.

Solution

Try the following steps:

  1. Update Rust: rustup update stable
  2. Check toolchain: Ensure you’re using Rust stable
  3. Install ALSA: See ALSA section above
  4. Clear cache: cargo clean if building from source

Configuration Issues

Config File Not Loading

Problem

Configuration file is not being loaded or recognized.

Solution

Check that your config file is at the correct location: $XDG_CONFIG_HOME/tomat/config.toml (typically ~/.config/tomat/config.toml).

Verify the path exists:

ls -l $XDG_CONFIG_HOME/tomat/config.toml
# Or: ls -l ~/.config/tomat/config.toml

Syntax Errors

Problem

Configuration file has TOML syntax errors.

Solution

TOML is whitespace-sensitive and requires proper quoting. Use a TOML validator or check that brackets, quotes, and equal signs are balanced.

Test your config:

# Using tomat to validate
tomat status
# Will show errors if config is invalid

Permission Denied

Problem

Cannot read configuration file due to permission errors.

Solution

Ensure the config file is readable by your user:

chmod 644 $XDG_CONFIG_HOME/tomat/config.toml
# Or: chmod 644 ~/.config/tomat/config.toml

Status Bar Integration Troubleshooting

General Issues

No Status Showing

Problem

The status bar does not display any tomat status.

Solution

  1. Ensure daemon is running:

    tomat daemon status
    # Should show "Daemon is running"
    
  2. Check that the PATH includes the directory where tomat is installed. See https://github.com/jolars/tomat/issues/21 for instance.

Waybar Integration Issues

Status Not Updating

Problem

Waybar shows outdated or no tomat status.

Solution

  1. Check daemon status:

    tomat daemon status
    # Should show "Daemon is running"
    
  2. Test status command directly:

    tomat status
    # Should return JSON with current status
    
  3. Check waybar configuration:

    {
      "custom/tomat": {
        "exec": "tomat status",
        "interval": 1, // Update every second
        "return-type": "json" // Required for proper parsing
      }
    }
    
  4. Restart waybar:

    killall waybar && waybar &
    

JSON Parsing Errors

Problem

Waybar shows parsing errors for tomat output.

Solution

  1. Verify JSON output:

    tomat status | jq .
    # Should show properly formatted JSON
    
  2. Check for daemon errors:

    tomat daemon stop
    tomat daemon run  # Run in foreground to see errors
    
  3. Update waybar config:

    {
      "custom/tomat": {
        "exec": "tomat status 2>/dev/null || echo '{\"text\":\"🍅 Error\"}'",
        "return-type": "json"
      }
    }
    

Styling Not Applied

Problem

Waybar shows tomat status but CSS styling doesn’t work.

Solution

  1. Check CSS class names:

    tomat status | jq .class
    # Should return: "work", "work-paused", "break", etc.
    
  2. Verify CSS selectors in waybar style:

    #custom-tomat.work {
      background-color: #ff6b6b;
    }
    
    #custom-tomat.work-paused {
      background-color: #ff9999;
    }
    
  3. Test with simple styling:

    #custom-tomat {
      background-color: red; /* Should always apply */
    }
    

Hook Issues

Hook Not Executing

Problem

Configured hook command does not run when expected.

Solution

Verify the command exists and is executable:

which playerctl
ls -l /home/user/scripts/my-script.sh

Use absolute paths in your hook configuration:

[hooks.on_work_start]
cmd = "/usr/bin/playerctl"

Permission Denied

Problem

Hook fails with permission denied error.

Solution

Check that the command has execute permissions:

chmod +x /home/user/scripts/my-script.sh

Hook Timing Out

Problem

Hook command is killed before completing.

Solution

If your command takes longer than the default 5 seconds, increase the timeout:

[hooks.on_work_start]
cmd = "/home/user/scripts/slow-script.sh"
timeout = 10

Check if the command hangs when run manually. Ensure it doesn’t require interactive input.

No Error Output

Problem

Hook fails silently with no error messages.

Solution

Enable output capture to see error messages:

[hooks.on_work_start]
cmd = "/usr/bin/my-command"
capture_output = true

Working Directory Errors

Problem

Hook fails because working directory is invalid or inaccessible.

Solution

Verify the working directory exists and has correct permissions:

ls -ld /path/to/working/directory

Use absolute paths for both commands and working directories:

[hooks.on_work_start]
cmd = "/usr/bin/my-command"
cwd = "/home/user/project"

Hook Not Triggered

Problem

Hook is configured but never fires on the expected event.

Solution

Check that the hook name is spelled correctly (e.g., on_work_start, not on_start_work). After changing your config, restart the daemon:

tomat daemon stop
tomat daemon start

Environment Variables Not Working

Problem

Hook command cannot access TOMAT_* environment variables.

Solution

Test your hook manually with environment variables:

TOMAT_EVENT=work_start TOMAT_PHASE=work /path/to/command

Verify your script or command is reading the correct variable names.

Notification Issues

No Desktop Notifications

Problem

Timer works but no notifications appear.

Solution

  1. Check notification daemon:

    # For mako (Wayland)
    ps aux | grep mako
    
    # For dunst (X11)
    ps aux | grep dunst
    
    # Test notifications
    notify-send "Test" "Notification test"
    
  2. Check tomat notification config:

    [notification]
    enabled = true  # Must be true
    
  3. Try different icon modes:

    [notification]
    icon = "theme"  # Try system theme icon
    

Icon Not Showing in Notifications

Problem

Notifications appear but without icons.

Solution

Different solutions for different notification daemons:

  1. Mako: Use auto mode (default)

    [notification]
    icon = "auto"  # Uses cached embedded icon
    
  2. Dunst: Try theme mode

    [notification]
    icon = "theme"  # Uses system "timer" icon
    
  3. Custom icon:

    [notification]
    icon = "/usr/share/icons/hicolor/48x48/apps/timer.png"
    
  4. Check icon cache location:

    ls -la $XDG_CACHE_HOME/tomat/icon.png
    # Should exist if using "auto" mode
    

Audio Issues

No Sound Notifications

Problem

Timer works but no audio plays during transitions.

Solution

  1. Check audio configuration:

    # $XDG_CONFIG_HOME/tomat/config.toml
    [sound]
    mode = "embedded"  # Must not be "none"
    
  2. Test system audio:

    # Test if ALSA works
    aplay /usr/share/sounds/alsa/Front_Left.wav
    
    # Or try speaker-test
    speaker-test -t sine -f 1000 -l 1
    
  3. Check volume levels:

    • System volume (alsamixer, pavucontrol)
    • Tomat volume in config (0.0-1.0)
  4. Try different audio modes:

    [sound]
    mode = "system-beep"  # Use system beep instead
    

Wrong Audio Device

Problem

Audio plays on wrong device or not audible.

Solution

  1. Check default ALSA device:

    aplay -l  # List audio devices
    cat ~/.asoundrc  # Check ALSA configuration
    
  2. Use system beep as fallback:

    [sound]
    mode = "system-beep"
    

Custom Sound Files Not Working

Problem

Custom sound files don’t play.

Solution

  1. Check file paths and existence:

    ls -la /path/to/your/sound.ogg
    
  2. Verify file format (must be supported audio format):

    file /path/to/your/sound.ogg
    # Common formats: WAV, OGG, FLAC, MP3
    
  3. Test file with system player:

    aplay /path/to/your/sound.wav
    
  4. Use absolute paths:

    [sound]
    mode = "embedded"
    work_to_break = "/home/user/sounds/work-done.ogg"  # Absolute path
    

Service Management Troubleshooting

Service Fails to Start

Problem

systemctl --user start tomat.service fails.

Solution

  1. Check service file location:

    ls -la $XDG_CONFIG_HOME/systemd/user/tomat.service
    
  2. Verify service file content:

    cat $XDG_CONFIG_HOME/systemd/user/tomat.service
    # Should contain: ExecStart=%h/.cargo/bin/tomat daemon run
    
  3. Check service status:

    systemctl --user status tomat.service
    journalctl --user -u tomat.service -f
    
  4. Reload systemd configuration:

    systemctl --user daemon-reload
    systemctl --user restart tomat.service
    

Service Starts But Daemon Not Accessible

Problem

Service is running but tomat status fails.

Solution

  1. Check if daemon is actually running:

    ps aux | grep tomat
    
  2. Verify socket creation:

    ls -la $XDG_RUNTIME_DIR/tomat.sock
    
  3. Check service logs:

    journalctl --user -u tomat.service --no-pager
    

Enable Debug Output

Problem

Need to see detailed daemon output for debugging.

Solution

Run daemon in foreground to see all output:

tomat daemon stop
tomat daemon run  # Shows all debug output

Daemon Issues

Daemon Won’t Start

Problem

tomat daemon start fails or daemon exits immediately.

Solution

  1. Check if already running:

    tomat daemon status
    # If running, stop first: tomat daemon stop
    
  2. Check socket permissions:

    ls -la $XDG_RUNTIME_DIR/tomat*
    # Should show socket and PID files with your user ownership
    
  3. Run daemon in foreground to see errors:

    tomat daemon run
    # This shows all output directly
    
  4. Check runtime directory:

    echo $XDG_RUNTIME_DIR
    # Should output something like /run/user/1000
    # If empty, daemon will fail to start
    

Daemon Stops Unexpectedly

Problem

Daemon process dies or becomes unresponsive.

Solution

  1. Check system logs:

    journalctl --user -u tomat.service -f  # If using systemd
    
  2. Check for multiple instances:

    ps aux | grep tomat
    # Kill any duplicate processes
    
  3. Clean up stale files:

    rm -f $XDG_RUNTIME_DIR/tomat.sock $XDG_RUNTIME_DIR/tomat.pid
    tomat daemon start
    

Permission Errors

Problem

“Permission denied” when accessing socket or PID files.

Solution

  1. Check file ownership:

    ls -la $XDG_RUNTIME_DIR/tomat*
    # Files should be owned by your user
    
  2. Ensure runtime directory exists:

    mkdir -p $XDG_RUNTIME_DIR
    chmod 700 $XDG_RUNTIME_DIR
    
  3. Restart daemon:

    tomat daemon stop
    tomat daemon start
    

Command-Line Help for tomat

This document contains the help content for the tomat command-line program.

Command Overview:

tomat

Tomat is a Pomodoro timer with a daemon-based architecture, designed for seamless integration with waybar and other status bars. It uses a Unix socket for client-server communication, ensuring your timer state persists across waybar restarts and system suspend/resume.

Usage: tomat <COMMAND>

EXAMPLES:

# Start daemon and begin a session
tomat daemon start
tomat start

# Custom session durations
tomat start --work 45 --break 15

# Check status (outputs JSON for waybar)
tomat status

# Toggle pause/resume
tomat toggle

For more information, visit: https://github.com/jolars/tomat

Subcommands:
  • daemon — Manage the background daemon
  • start — Start a new Pomodoro session
  • stop — Stop the current session
  • status — Get current timer status
  • watch — Continuously output status updates
  • skip — Skip to the next phase
  • pause — Pause the current timer
  • resume — Resume a paused timer
  • toggle — Toggle timer pause/resume

tomat daemon

Manage the tomat daemon, which runs in the background and maintains timer state. The daemon must be running for timer commands to work.

Usage: tomat daemon <COMMAND>

Subcommands:
  • start — Start the daemon in the background
  • stop — Stop the running daemon
  • status — Check daemon status
  • install — Install systemd user service
  • uninstall — Uninstall systemd user service

tomat daemon start

Start the tomat daemon as a background process. The daemon manages timer state and handles client requests via a Unix socket at $XDG_RUNTIME_DIR/tomat.sock. Only one daemon instance can run at a time.

Usage: tomat daemon start

tomat daemon stop

Stop the running tomat daemon gracefully. This will terminate any active timer session. The daemon will clean up its socket and PID files.

Usage: tomat daemon stop

tomat daemon status

Check if the tomat daemon is currently running and report its process ID.

Usage: tomat daemon status

tomat daemon install

Install and enable the tomat systemd user service. This allows the daemon to start automatically on login and restart if it crashes. The service file is installed to ~/.config/systemd/user/tomat.service.

Usage: tomat daemon install

After installation, manage the service with systemctl: systemctl –user start tomat.service systemctl –user status tomat.service systemctl –user stop tomat.service

tomat daemon uninstall

Stop and remove the tomat systemd user service. This removes the service file and disables automatic startup.

Usage: tomat daemon uninstall

tomat start

Start a new Pomodoro timer session with the specified durations. If no options are provided, uses defaults from ~/.config/tomat/config.toml or built-in defaults (25min work, 5min break, 15min long break, 4 sessions). Custom durations only apply to the current session.

Usage: tomat start [OPTIONS]

EXAMPLES:

# Start with defaults
tomat start

# Custom work/break durations
tomat start --work 45 --break 15

# Auto-advance between phases
tomat start --auto-advance
Options:
  • -w, --work <WORK> — Duration of work sessions in minutes. If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of 25 minutes.

  • -b, --break <BREAK_TIME> — Duration of short breaks in minutes. If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of 5 minutes.

  • -l, --long-break <LONG_BREAK> — Duration of long breaks in minutes. Long breaks occur after completing the configured number of work sessions. If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of 15 minutes.

  • -s, --sessions <SESSIONS> — Number of work/break cycles before taking a long break. If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of 4 sessions.

  • -a, --auto-advance <AUTO_ADVANCE> — Control automatic phase transitions: all - Auto-advance through all phases none - Never auto-advance (pause at transitions) to-break - Auto-advance from work to break only to-work - Auto-advance from break to work only

    If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of ‘none’.

  • --sound-mode <SOUND_MODE> — Control sound notifications: embedded - Use built-in audio files (default) system-beep - Use system beep (terminal bell) none - No sound notifications

    If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of ‘embedded’.

  • --volume <VOLUME> — Set the audio volume for sound notifications, from 0.0 (silent) to 1.0 (maximum). Values outside this range will be clamped. If not specified, uses the value from ~/.config/tomat/config.toml or the built-in default of 0.5.

tomat stop

Stop the current Pomodoro session and return the timer to idle state.

Usage: tomat stop

tomat status

Display the current timer status. Output format can be customized for different status bars (waybar, i3status-rs) or plain text. Text appearance can be customized using format templates.

Usage: tomat status [OPTIONS]

OUTPUT FORMATS:

waybar
JSON output for waybar (default)
i3status-rs
JSON output for i3status-rs
plain
Plain text output

FORMAT PLACEHOLDERS:

{icon}
Phase icon (🍅 work, ☕ break, 🏖️ long break)
{time}
Remaining time (MM:SS)
{state}
Play/pause symbol (▶/⏸)
{phase}
Phase name (Work/Break/Long Break)
{session}
Session progress (e.g. 1/4)

EXAMPLES:

tomat status
tomat status --output plain
tomat status --format "{time}"
tomat status --format "{phase}: {time} {state}"
Options:
  • -o, --output <OUTPUT> — Output format: waybar, i3status-rs, or plain

    Default value: waybar

    Possible values: waybar, i3status-rs, plain

  • -f, --format <FORMAT> — Customize the text display using placeholders: {icon} - Phase icon {time} - Remaining time (MM:SS) {state} - Play/pause symbol {phase} - Phase name {session} - Session progress

tomat watch

Continuously watch and output timer status updates. This maintains a single connection to the daemon and updates at the specified interval. Automatically exits when the daemon stops. More efficient than polling with ‘status’ command.

Usage: tomat watch [OPTIONS]

EXAMPLES:

# Watch with default interval (0.25 seconds)
tomat watch

# Watch with 5-second updates
tomat watch --interval 5

# Watch with plain text output
tomat watch --output plain
Options:
  • -o, --output <OUTPUT> — Output format: waybar, i3status-rs, or plain

    Default value: waybar

    Possible values: waybar, i3status-rs, plain

  • -f, --format <FORMAT> — Custom text format (e.g. “{icon} {time}”)

  • -i, --interval <INTERVAL> — Update interval in seconds

    Default value: 0.25

tomat skip

Skip the current phase and immediately transition to the next phase (work → break → work → … → long break). The timer will start in the new phase if auto-advance is enabled, otherwise it will be paused.

Usage: tomat skip

tomat pause

Pause the currently running timer. Use ‘resume’ or ‘toggle’ to continue.

Usage: tomat pause

tomat resume

Resume a paused timer from where it left off.

Usage: tomat resume

tomat toggle

Toggle the timer state: pause if running, resume if paused. This is useful for waybar click handlers.

Usage: tomat toggle


This document was generated automatically by clap-markdown.

Configuration Guide

Tomat supports comprehensive configuration via a TOML file located at $XDG_CONFIG_HOME/tomat/config.toml (typically ~/.config/tomat/config.toml). This allows you to set default values for timer durations and behaviors without specifying them on every command.

The configuration file is organized into five main sections:

[timer]
timer durations and behavior
[sound]
for audio notification settings
[notification]
for desktop notification settings [display] for output
[display]
for output formatting
[hooks]
for custom commands triggered by timer events

Timer Settings

The [timer] section controls timer durations and phase transition behavior.

[timer]
work = 25.0
break = 5.0
long_break = 15.0
sessions = 4
auto_advance = "none"

Options

work

Duration of work phase in minutes (default: 25.0)

break

Duration of short break phase in minutes (default: 5.0)

long_break

Duration of long break phase in minutes (default: 15.0)

sessions

Number of work sessions before a long break (default: 4)

auto_advance

Controls how the timer transitions between phases.

"none" (default)
Pause after every phase transition (requires manual resume)
"all"
Automatically continue through all phases without pausing
"to-break"
Auto-advance only from work to break/long-break
"to-work"
Auto-advance only from break/long-break to work

Note

Boolean values true and false are deprecated and will be automatically converted to "all" and "none" respectively.

Examples

To set a 30-minute work session, 10-minute break, 20-minute long break, with 3 sessions before a long break, and auto-advance from work to break, use the following configuration.

[timer]
work = 30.0
break = 10.0
long_break = 20.0
sessions = 3
auto_advance = "to-break"

Sound Settings

The [sound] section controls audio notifications when transitioning between work/break phases. By default, tomat plays high-quality WAV files built into the application. On Linux, this requires ALSA (Advanced Linux Sound Architecture). If the audio system is unavailable, it will automatically fall back to the system beep or disable audio.

[sound]
mode = "embedded"
volume = 0.5

Options

mode

Sound notification mode. Controls how phase transitions are announced.

"embedded" (default)
Use built-in audio files
"system-beep"
Use system beep (terminal bell)
"none"
No sound notifications
volume

Audio volume level for embedded and custom sounds (0.0-1.0). Default: 0.5

work_to_break

Path to custom sound file for work→break transitions. Overrides embedded sound. Optional.

break_to_work

Path to custom sound file for break→work transitions. Overrides embedded sound. Optional.

work_to_long_break

Path to custom sound file for work→long break transitions. Overrides embedded sound. Optional.

"enabled"

Enable sound notifications.

Warning

Deprecated option. Use mode = "embedded" instead.

"system_beep"

Use system beep.

Warning

Deprecated option. Use mode = "system-beep" instead.

"use_embedded"

Use embedded sounds.

Warning

Deprecated option. Use mode = "embedded" instead.

Examples

To use your own sound files, keep mode = "embedded" and specify paths to your audio files. Custom sounds override the built-in ones:

[sound]
mode = "embedded"
work_to_break = "/home/user/sounds/work-done.ogg"
break_to_work = "/home/user/sounds/break-over.ogg"
work_to_long_break = "/home/user/sounds/long-break.ogg"
volume = 0.7

To disable all audio:

[sound]
mode = "none"

To use system beep only:

[sound]
mode = "system-beep"

Notification Settings

The [notification] section controls desktop notifications shown during phase transitions. Notifications are displayed by your system’s notification daemon (such as dunst or mako).

[notification]
enabled = true
icon = "auto"
timeout = 5000
urgency = "normal"

Options

enabled

Whether to show desktop notifications.

icon

Controls notification icon.

"auto" (default)
Uses embedded icon, cached to $XDG_CACHE_HOME/tomat/icon.png (mako-compatible)
"theme"
Uses system theme icon ("timer")
<path>
Specify a file path (e.g., "/home/user/my-icon.png")
timeout

Default: 5000

urgency

Controls notification priority level.

"normal" (default)
Standard notification priority
"low"
Minimal interruption, typically shown without sound
"critical"
High priority, may bypass do-not-disturb settings
work_message

The message shown when transitioning from work to break.

Default
"Break time! Take a short rest ☕"
break_message

The message sown when transitioning from break to work.

Default
"Back to work! Let's focus 🍅"
long_break_message

The message shown when transitioning to a long break.

Default
"Long break time! Take a well-deserved rest 🏖️"

Examples

To disable notifications:

[notification]
enabled = false

To use a custom icon:

[notification]
icon = "/path/to/custom/icon.png"

To customize notification messages:

[notification]
work_message = "Break time! Step away from the screen."
break_message = "Back to work! Let's get things done."
long_break_message = "Long break! You've earned it."

Display Settings

The [display] section controls how timer status is formatted in the output.

[display]
text_format = "{icon} {time} {state}"

Options

text_format

Template string for formatting timer display. The field supports the following placeholders enclosed in curly braces {}:

{icon}
Phase icon (🍅 🏖️)
{time}
Remaining time (e.g., 25:00)
{state}
Play/pause symbol ( )
{phase}
Phase name (Work, Break, Long Break)
{session}
Session progress (e.g., 1/4; empty for breaks)
Default
"{icon} {time} {state}"
Example
"{phase}: {time} {state}"

Examples

Minimal format (time only):

[display]
text_format = "{time}"

With session counter:

[display]
text_format = "[{session}] {icon} {time}"

Verbose format:

[display]
text_format = "{phase}: {time} {state}"

Hooks

Hooks allow you to execute custom commands when timer events occur. This enables integration with external tools, automation workflows, and custom notifications.

[hooks.on_work_start]
cmd = "playerctl"
args = ["pause"]

[hooks.on_break_start]
cmd = "playerctl"
args = ["play"]

Available Hooks

on_work_start
A work session starts
on_break_start
A break starts
on_long_break_start
A long break starts
on_pause
Timer is paused
on_resume
Timer is resumed
on_stop
Timer is stopped manually
on_complete
A phase completes naturally (auto or manual transition)
on_skip
User skips to next phase

Options

cmd

Command to execute

Example
"/usr/bin/notify-send"
args

Command arguments (list of strings)

Default
[] (no arguments)
Example
["-u", "critical"]
timeout

Timeout in seconds (0 = no timeout)

Default
5 seconds
cwd

Working directory

Default
User’s home directory ($HOME)
Example
"/home/user/scripts"
capture_output

Capture stdout/stderr for debugging

Default
false

Environment Variables

All hooks receive these environment variables:

TOMAT_EVENT
Event name (e.g., "work_start", "pause")
TOMAT_PHASE
Current phase ("work", "break", "long_break")
TOMAT_REMAINING_SECONDS
Seconds remaining in current phase
TOMAT_SESSION_COUNT
Current session number (1, 2, 3, …)
TOMAT_AUTO_ADVANCE
Auto-advance mode ("none", "all", "to-break", "to-work")

These can be used in scripts to customize behavior based on the timer state.

Examples

Pause music during work sessions:

[hooks.on_work_start]
cmd = "playerctl"
args = ["pause"]
timeout = 2

[hooks.on_break_start]
cmd = "playerctl"
args = ["play"]

Adjust screen brightness:

[hooks.on_pause]
cmd = "brightnessctl"
args = ["set", "30%"]

[hooks.on_resume]
cmd = "brightnessctl"
args = ["set", "100%"]

Log completed sessions:

[hooks.on_complete]
cmd = "sh"
args = ["-c", "echo \"$(date): $TOMAT_PHASE completed\" >> ~/tomat.log"]
capture_output = true

Custom notifications:

[hooks.on_work_start]
cmd = "notify-send"
args = ["🍅 Focus Time", "Let's get things done!", "-u", "critical"]
timeout = 3

[hooks.on_long_break_start]
cmd = "notify-send"
args = ["🏖️ Long Break", "You've earned it! Take 15 minutes."]

Execute custom scripts:

[hooks.on_work_start]
cmd = "/home/user/scripts/start-focus-mode.sh"
cwd = "/home/user/scripts"
timeout = 10

[hooks.on_stop]
cmd = "/home/user/scripts/end-focus-mode.sh"
cwd = "/home/user/scripts"

Security Considerations

Hooks execute with the daemon’s user privileges. Follow these security best practices:

  • Only configure trusted commands: Hooks can execute any command your user can run.
  • Use absolute paths: Prefer /usr/bin/notify-send over notify-send to avoid PATH manipulation.
  • Never run the daemon as root: Always use the --user systemd service.
  • Verify config file ownership: Ensure your config file is owned by your user.
  • No shell injection: Commands are executed directly without a shell, preventing injection attacks.
  • Timeout protection: Hooks are automatically killed after the timeout to prevent hanging processes.

Note: If an attacker controls your $XDG_CONFIG_HOME directory, they already have code execution via shell rc files. Hooks don’t introduce new attack vectors beyond standard Unix permissions.

Contributing

We welcome contributions to tomat! Here’s a guide to help you get started.

Quick Contribution Checklist

Before submitting any changes:

  • Formatting: cargo fmt -- --check (MUST exit with code 0)
  • Linting: cargo clippy --all-targets --all-features -- -D warnings (MUST exit with code 0, no warnings allowed)
  • Compilation: cargo check (MUST pass)
  • Tests: cargo test (all integration tests must pass)

Getting Started

  1. Fork the repository.

  2. Clone your fork:

    git clone <your-fork-url>
    
  3. Install prerequisites:

    # Rust toolchain (specified in rust-toolchain.toml)
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    
    # ALSA development libraries (for audio)
    sudo apt-get install libasound2-dev  # Ubuntu/Debian
    sudo dnf install alsa-lib-devel      # Fedora/RHEL
    sudo pacman -S alsa-lib              # Arch Linux
    
  4. You might also want to install task for easier task management. The following task commands assume you have it installed.

Development Workflow

Essential Build Commands

Always run commands from the repository root.

# Quick development check (recommended)
task dev

# Individual commands
cargo check                    # Check compilation without building
cargo test                     # Run all tests (19 integration tests)
cargo clippy --all-targets --all-features -- -D warnings  # Lint
cargo fmt                      # Format code
cargo fmt -- --check          # Check formatting

# Build commands
cargo build                    # Development build
cargo build --release          # Release build

Testing Your Changes

# Build and start daemon for testing
cargo build
./target/debug/tomat daemon start

# Test with short durations for fast feedback
./target/debug/tomat start --work 0.1 --break 0.05  # 6s work, 3s break
./target/debug/tomat status
./target/debug/tomat toggle

# Stop daemon when done
./target/debug/tomat daemon stop

Code Quality Standards

Mandatory Requirements

All code changes MUST pass these checks before commit:

  1. Zero clippy warnings: cargo clippy --all-targets --all-features -- -D warnings
  2. Proper formatting: cargo fmt -- --check
  3. All tests pass: cargo test
  4. Compilation success: cargo check

Code Style

  • Error handling: Uses Box<dyn std::error::Error> for simplicity
  • Comments: Only add comments when they match existing style or explain complex logic
  • Dependencies: Use existing libraries when possible, avoid adding new dependencies unless absolutely necessary
  • Commit style: Use Conventional Commits (feat:, fix:, docs:, test:, refactor:)

Architecture Overview

Tomat is designed as a small, focused Rust project with a client-server architecture.

Module Structure

  • src/main.rs Main entry point, command parsing, high-level flow
  • src/cli.rs CLI argument parsing with clap
  • src/config.rs Configuration system with timer, sound, and notification settings
  • src/server.rs Unix socket server, daemon lifecycle, client request handling, PID file management
  • src/timer.rs Timer state machine, phase transitions, status output formatting, desktop notifications
  • src/audio.rs Audio playback utilities
  • tests/ integration tests

Communication Flow

Client CLI Commands
       ↓
Unix Socket ($XDG_RUNTIME_DIR/tomat.sock)
       ↓
Daemon Process (background)
       ↓
TimerState (Work/Break/LongBreak phases)
       ↓
JSON Status Output (optimized for waybar)

Key Design Decisions

Client-Server Architecture:

  • Single binary with subcommands
  • Daemon listens on Unix socket at $XDG_RUNTIME_DIR/tomat.sock
  • PID file tracking at $XDG_RUNTIME_DIR/tomat.pid with exclusive file locking
  • Line-delimited JSON protocol for communication

Timer State Machine:

  • Phases: Work → Break → Work → … → LongBreak (after N sessions)
  • Two modes controlled by --auto-advance flag:
    • false (default): Timer transitions to next phase but pauses, requiring manual resume
    • true: Timer automatically continues through all phases
  • Timer starts in paused work state

Testing Infrastructure

Integration Test Pattern

All tests use the TestDaemon helper struct for isolated testing:

#![allow(unused)]
fn main() {
// Start isolated test daemon with temporary socket
let daemon = TestDaemon::start()?;

// Send commands
daemon.send_command(&["start", "--work", "0.05", "--break", "0.05"])?;

// Get status
let status = daemon.get_status()?;
assert_eq!(status["class"], "work");

// Wait for timer completion
daemon.wait_for_completion(10)?;
}

Key testing features:

  • Isolated environments: Each test uses tempfile::tempdir() with custom XDG_RUNTIME_DIR
  • Fast execution: Fractional minutes (0.05 = 3 seconds) for rapid testing
  • Notification suppression: TOMAT_TESTING=1 env var disables desktop notifications
  • Automatic cleanup: TestDaemon Drop impl kills daemon process

Test Categories

  1. Auto-advance behavior: Verify auto_advance=false pauses after transitions, auto_advance=true continues automatically
  2. Timer control: Toggle pause/resume, stop/start
  3. Daemon lifecycle: Start, stop, status, duplicate detection
  4. Edge cases: Manual skip, fractional minutes
  5. Configuration: Timer, sound, and notification configuration parsing
  6. Icon management: Embedded icon caching and different icon modes

Adding New Features

Adding a New Command

  1. Add enum variant to Commands in src/main.rs
  2. Add command handling in handle_client() in src/server.rs
  3. Add match arm in main() in src/main.rs
  4. Write integration tests in tests/ using TestDaemon

Modifying Timer Behavior

  1. Update TimerState struct in src/timer.rs if new fields needed
  2. Modify state machine logic in next_phase(), start_work(), etc.
  3. Update status output in get_status_output()
  4. Test both auto_advance=true and auto_advance=false modes

Adding Configuration Options

  1. Update appropriate config struct in src/config.rs
  2. Add default value functions
  3. Update Default implementation
  4. Add comprehensive tests for new configuration options
  5. Update documentation and examples

Technical Implementation Details

Process Management

  • Daemon lifecycle: SIGTERM with 5-second timeout, then SIGKILL
  • PID file locking: Uses fs2::FileExt::try_lock_exclusive() to prevent race conditions
  • Socket cleanup: Automatic cleanup of socket and PID files on graceful shutdown

Notification System

  • Desktop notifications: Via notify-rust with embedded icon system
  • Icon caching: Embedded icon automatically cached to ~/.cache/tomat/icon.png
  • Mako compatibility: Default “auto” icon mode works with mako out of the box

Configuration System

  • TOML-based: Configuration loaded from ~/.config/tomat/config.toml
  • Hierarchical: Built-in defaults → config file → CLI arguments

Debugging Tips

# Run daemon in foreground (see output directly)
cargo build && ./target/debug/tomat daemon run

# Test output (see println! statements)
cargo test -- --nocapture

# Check socket status
ss -lx | grep tomat

# Inspect PID file
cat $XDG_RUNTIME_DIR/tomat.pid && ps -p <PID>

# Check logs (if using systemd)
journalctl --user -u tomat.service -f

Backward Compatibility

When contributing, ensure:

  • No breaking changes: Existing waybar configurations must continue to work
  • CLI stability: Existing command-line interfaces are preserved
  • Configuration compatibility: Existing config files remain valid
  • API consistency: JSON output format remains stable for waybar integration

Release Process

The project uses automated semantic versioning:

  1. Conventional Commits: Commit messages determine version bumps
  2. Automated CI: GitHub Actions handle testing and releases
  3. Semantic Versioning: feat: → minor, fix: → patch, BREAKING CHANGE: → major

Changelog

2.8.1 (2026-01-19)

Bug Fixes

  • man pages, service unit, and completions in releases (598f024)
  • open audio stream on demand (11bfd92)

2.8.0 (2026-01-15)

Features

  • add sound.mode option (66b537a)
  • add hooks for end of states (494c8be)
  • make 0 timeout for hooks mean no timeout (9c4514a)

Bug Fixes

  • await resume for hooks if auto advancing (15ba349)
  • execute skip hooks before phase transition (9ffc487)
  • remove dead on_complete hook code (ae61f6e)
  • track cli reference and exclude from cargo build (4addeaa)

2.7.0 (2026-01-13)

Features

  • add granular options for auto advancing (80d7f31)
  • add support for customizing notification urgency (337ebd1)
  • allow customization of notification messages (feb3b13)

Performance Improvements

  • reduce size of sound alerts (755b791)

2.6.0 (2026-01-09)

Features

  • add a system for calling hooks upon state changes (0573d57)
  • reduce default tomat watch interval to 0.25s (5735a89)

Bug Fixes

  • execute hook on work start (bf0b375)

2.5.0 (2025-11-29)

Features

Bug Fixes

  • work around race conditions for spawning servers (c5b9113)

Performance Improvements

  • reduce startup delay in server verification (0e02b9d)

2.4.0 (2025-11-04)

Features

Bug Fixes

  • correctly get status output when paused (6006947)

2.3.0 (2025-10-31)

Features

  • add tomat daemon install/uninstall (f414020)

Bug Fixes

2.2.0 (2025-10-31)

Features

  • add --output option (8ccda87)
  • add i3status-rs to output formats (0515bd9)
  • change default timer duration to 5 seconds (5d96283)

Bug Fixes

2.1.0 (2025-10-30)

Features

  • add icon and enable it in notifications (70c047a)
  • change summary field in notification to “Tomato” (e9e7c70)
  • config: add configuration section for notifications (ff7f8ce)
  • update logo (ee3559d)

2.0.0 (2025-10-29)

⚠ BREAKING CHANGES

  • change break-time to break in cli and config

Features

  • change break-time to break in cli and config (ef325fc)
  • enable sound notifications (bd28eb0)
  • implement pause and resume commands (f63662b)
  • improve timer precision (4cd6c16)

Bug Fixes

  • avoid socket race condition (eefe788)
  • don’t play audio notifications during testing (253df25)
  • make timer persist after restarts (b0706c4)
  • preserve timer progress across pause/resume cycles (333b03d)
  • remove unused arguments from tomat toggle (53c3065)

1.0.0 (2025-10-29)

Features

  • add daemon, service file, and binary (baea76c)
  • add notifications via notify-rust (435e8dc)
  • add support for configuration through a TOML file (a3cb56d)
  • add toggle subcommand (17f03c8)
  • allow floats in durations (b61372f)
  • enable full daemon control (68df527)
  • setup basic package infrastructure (20401a8)
  • support long breaks (91d544b)

Bug Fixes