TIMER(1)

NAME
timer - terminal countdown and stopwatch

SYNOPSIS
timer [-qs] [-c text] [--no-persist] [--flash on|off] [--bar style] [--] [duration] [message ...]

timer -r [-n N] [--raw]

timer --stats [today|week|month|all]

DESCRIPTION
timer is a small terminal countdown timer and stopwatch inspired by suckless philosophy. A single argument is parsed as a duration and the program counts down. With no duration argument it runs as a stopwatch. The progress bar, current elapsed time and time remaining are redrawn on the same line ten times per second.

The binary is intentionally small and modular. Beyond the base build (countdown, stopwatch, ASCII progress bar, pause/resume, one-shot terminal bell on completion) every feature is an optional patch under patches/. Each section below describing a non-base feature is annotated with [patch:name]; those options and behaviours are only present if the corresponding patch has been applied at build time. timer -h always reflects the actual build.

OPTIONS

  Base

-q  Suppress the one-shot completion bell. Persistent alert loops, if enabled by a patch, still ring the bell.

-s  Silent. No bell, no notification, no alert loop. Equivalent to combining every silencing flag.

-h  Print usage and exit. Reflects the actual build.

--  End of options. Subsequent arguments are treated as positional even if they begin with -.

  Optional, added by patches

-c text
    [patch:logging, hooks] Comment associated with this session. With the logging patch, it is written as the third TSV field and any +tag tokens within it are picked up by timer --stats. With the hooks patch, it is passed as the fourth argument to each hook script.

--no-persist
    [patch:persist-alert] Skip the alert-until-keypress loop. timer emits one bell and one notification, then exits.

--flash on|off
    [patch:flash] Toggle the reverse-video terminal flash that runs during the persistent alert loop. Accepts on/off/true/false/1/0/yes/no. Default is build-dependent.

--bar style
    [patch:bar-styles] Progress bar style. One of unicode, ascii, hash, dots, line, block, arrow, minimal. With no patch applied the bar uses the compile-time BAR_FILL and BAR_EMPTY glyphs from config.h.

SUBCOMMANDS

  timer -r [-n N] [--raw]
[patch:logging] Read the session log. -n N limits output to the last N entries. --raw prints the underlying TSV instead of the formatted table, suitable for piping through awk(1), grep(1) or sort(1).

  timer --stats [period]
[patch:logging] Print aggregate statistics. Period is one of today (default), week, month, all. Entries are summed in total and broken down by +tag tokens extracted from comments. Untagged sessions are reported as (untagged).

DURATION FORMAT
A duration is either a colon notation or a unit notation. Examples:

    25m         twenty-five minutes
    90s         ninety seconds
    2h          two hours
    1h30m       one and a half hours
    01:30:00    one and a half hours
    25:00       twenty-five minutes

Colon notation expects H:M:S or M:S. Unit notation is a concatenation of one or more Nh, Nm, Ns groups in any order.

MESSAGE
[patch:notify] Any positional arguments after duration are joined into the message used for the one-shot completion notification. The message is expanded into the notify_cmd template via the {msg} placeholder.

KEYS
While the timer is running:

space
    Pause or resume the countdown or stopwatch.

q   Quit immediately. Logs the partial session if logging is enabled.

Ctrl+C
    Same as q.

ALERT LOOP
[patch:persist-alert] When a countdown reaches zero, instead of emitting one bell and exiting, the program rings the bell every ~1.5 s and polls for a keypress. Any key acknowledges and exits.

The loop runs only when timer is in the foreground. Background jobs (timer ... &) get one bell and exit normally, leaving the shell quiet.

If the flash patch is also applied, each beat of the loop briefly inverts the terminal colours (reverse-video). The flash can be suppressed without disabling the loop via --flash off.

HOOKS
[patch:hooks] On state transitions timer invokes optional executables under ~/.config/ttym/hooks/:

on_start
    Called when a session begins.

on_done
    Called when a countdown completes normally.

on_quit
    Called when a session is interrupted with q or Ctrl+C, or when a stopwatch is stopped.

Each hook is executed synchronously with three arguments: mode, duration_seconds, comment. The first is countdown or stopwatch; the others come from the running session. Hooks must be marked executable. Standard streams are redirected to /dev/null.

FILES

~/.config/ttym/config
    [patch:config-file] Runtime configuration. Auto-generated on first run with all keys commented out.

~/.config/ttym/ttym.log
    [patch:logging] Session log. TSV with three fields per line:

        YYYY-MM-DD HH:MM:SS<TAB>SECONDS<TAB>COMMENT

    Designed to be processed with awk(1) and grep(1) rather than re-rendered by the binary.

~/.config/ttym/hooks/
    [patch:hooks] Directory containing the on_start, on_done, on_quit executables described in HOOKS.

EXAMPLES
A twenty-five minute work session, tagged for later stats:

    timer -c "+work coding" 25m

A countdown that pops a notification with custom text:

    timer 10m Lunch

Total hours logged this week:

    timer -r --raw | awk -F'\t' '{s+=$2} END {printf "%dh\n", s/3600}'

Count +work sessions ever:

    timer -r --raw | grep '+work' | wc -l

Stopwatch with no notifications:

    timer -s

DESIGN
The binary does one thing: time intervals and, optionally, log them. Reports (timer -r, timer --stats) are read-only views over the same TSV log. For any other view, pipe timer -r --raw through awk(1), grep(1) or sort(1). No daemon, no IPC, no plugin system, no embedded TUI. Hooks are git-style: executables you write yourself.

Compile-time options live in config.h; runtime overrides (when the config-file patch is applied) live in ~/.config/ttym/config.

AUTHORS
timer is maintained by Łukasz Kasprzak. Distributed under the MIT license; see LICENSE in the source tree.

SEE ALSO
awk(1), grep(1), notify-send(1), paplay(1), patch(1)