.TH TIMER 1 "ttym 3.0" .SH NAME timer \- terminal countdown and stopwatch .SH SYNOPSIS .B timer .RB [ \-qs ] .RB [ \-\-no\-persist ] .RB [ \-\-flash .BR on | off ] .RB [ \-\-bar .IR style ] .RB [ \-\- ] .RI [ duration ] .PP The remaining forms exist only when the corresponding patch is applied; each is annotated .RI [patch: name ] under .BR OPTIONS . .PP .B timer .RB [ \-qs ] .RB [ \-c .IR text ] .RB [ \-\-no\-persist ] .RB [ \-\-flash .BR on | off ] .RB [ \-\-bar .IR style ] .RB [ \-\-dump\-config ] .RB [ \-\- ] .RI [ duration ] .RI [ message .IR ... ] .PP .B timer \-r .RB [ \-n .IR N ] .RB [ \-\-raw ] .PP .B timer \-\-stats .RB [ today | week | month | all ] .SH DESCRIPTION .B 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. .PP The binary is intentionally small and modular. The base build is terminal\-only: countdown, stopwatch, pause/resume, the progress bar and its eight styles, and the alert\-until\-keypress loop with its optional terminal flash. It writes no files and spawns no processes. Every feature that touches the filesystem, runs a subprocess or depends on an external binary is an optional patch under .IR patches/ . Each section below describing a non\-base feature is annotated with .RI [patch: name ]; those options and behaviours are only present if the corresponding patch has been applied at build time. .B timer \-h always reflects the actual build. .SH OPTIONS .SS Base .TP .B \-q Suppress the one\-shot completion bell. With the .B notify patch it also suppresses the completion sound, though not the desktop notification. Persistent alert loops, if enabled by a patch, still ring the bell. .TP .B \-s Silent. No bell, no notification, no alert loop. Equivalent to combining every silencing flag. .TP .B \-h Print usage and exit. Reflects the actual build. .TP .B \-\- End of options. Subsequent arguments are treated as positional even if they begin with .BR \- . .TP .B \-\-no\-persist Skip the alert\-until\-keypress loop. .B timer emits one bell, then exits. .TP .BR \-\-flash \ \fBon\fR | \fBoff\fR Toggle the reverse\-video terminal flash that runs during the persistent alert loop. Accepts .BR on / off / true / false / 1 / 0 / yes / no . Default is .B FLASH in .IR config.h . .TP .BR \-\-bar \ \fIstyle\fR Progress bar style. One of .BR unicode , .BR ascii , .BR hash , .BR dots , .BR line , .BR block , .BR arrow , .BR minimal . Unset (the default) auto\-detects: unicode on a UTF\-8 locale, otherwise ascii. The .B BAR_FILL and .B BAR_EMPTY glyphs in .I config.h are the fallback when no style matches. .SS Optional, added by patches .TP .BR \-c \ \fItext\fR .RI [patch: logging, .RI hooks] Comment associated with this session. With the .B logging patch, it is written as the third TSV field and any .BI + tag tokens within it are picked up by .BR "timer \-\-stats" . With the .B hooks patch, it is passed as the third argument to each hook script. .TP .B \-\-dump\-config .RI [patch: config\-file] Print a commented configuration template on stdout and exit. .B timer never creates the file itself: .PP .RS .nf timer \-\-dump\-config > ~/.config/ttym/config .fi .RE .SH SUBCOMMANDS .SS timer \-r [\-n N] [\-\-raw] .RI [patch: logging] Read the session log. .B \-n N limits output to the last .I N entries. .B \-\-raw prints the underlying TSV instead of the formatted table, suitable for piping through .BR awk (1), .BR grep (1) or .BR sort (1). .SS timer \-\-stats [\fIperiod\fR] .RI [patch: logging] Print aggregate statistics. Period is one of .BR today (default), .BR week , .BR month , .BR all . Entries are summed in total and broken down by .BI + tag tokens extracted from comments. Untagged sessions are reported as .BR (untagged) . .SH DURATION FORMAT A duration is either a colon notation or a unit notation. Examples: .PP .RS .nf 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 .fi .RE .PP Colon notation expects .IR H:M:S or .IR M:S . Unit notation is a concatenation of one or more .IR Nh , .IR Nm , .IR Ns groups in any order. .SH MESSAGE .RI [patch: notify] Any positional arguments after .I duration are joined into the message used for the one\-shot completion notification. The message is expanded into the .B notify_cmd template via the .B {msg} placeholder. .SH KEYS While the timer is running: .TP .B space Pause or resume the countdown or stopwatch. .TP .B q Quit immediately. Logs the partial session if logging is enabled. .TP .B Ctrl+C Same as .BR q . .SH ALERT LOOP When a countdown reaches zero, instead of emitting one bell and exiting, the program rings the bell every \(ti1.5 s and polls for a keypress. Any key acknowledges and exits. .PP The loop runs only when .B timer is in the foreground. Background jobs .RB ( timer .IR ... \ &) get one bell and exit normally, leaving the shell quiet. .PP Each beat of the loop briefly inverts the terminal colours (reverse\-video). The flash can be suppressed without disabling the loop via .BR "\-\-flash off" , or permanently via .B FLASH in .IR config.h . .SH HOOKS .RI [patch: hooks] On state transitions .B timer invokes optional executables under .IR ~/.config/ttym/hooks/ : .TP .B on_start Called when a session begins. .TP .B on_done Called when a countdown completes normally. .TP .B on_quit Called when a session is interrupted with .BR q or .BR Ctrl+C , or when a stopwatch is stopped. .PP A hook is any executable file at that name; there is nothing to enable. A file that is missing or not marked executable is skipped silently. The three are independent: installing only .BR on_quit , for instance, is a complete and normal setup. .SS Arguments Each hook is run with exactly three positional arguments. .TP .B $1 .BR countdown " or " stopwatch . .TP .B $2 Seconds. The meaning depends on the hook: .RS .IP \(bu 2 .BR on_start : the requested duration of a countdown, or .B 0 for a stopwatch. .IP \(bu 2 .BR on_done : the full duration that elapsed. .IP \(bu 2 .BR on_quit : the time actually elapsed, excluding any time spent paused. A countdown abandoned after two seconds reports .BR 2 , not the duration that was asked for. .RE .TP .B $3 The .B \-c text, or an empty string. Always passed, so .B $3 is never unset. .SS Execution Hooks run synchronously: .B timer forks, executes the hook and waits for it. A slow hook delays the timer \(em .B on_start delays the first frame, and .B on_done delays the completion bell and the alert loop. Background anything slow with .BR & . .PP Standard input, output and error are all redirected to .IR /dev/null , so a hook cannot print to the terminal and cannot corrupt the redrawn progress line. Write to a file, to .BR logger (1), or to a notification daemon instead. The exit status is discarded: a failing hook cannot abort the timer. .PP Hooks are executed with .BR execvp (3), so a script needs a .B #! line like any other. .SS Examples Three commented, working examples ship with the source and are installed to .IR PREFIX/share/doc/ttym/hooks/ . They form one coherent set but each works alone. Together they do two things the binary cannot: .IP \(bu 2 Record intent against outcome. The session log behind .B timer \-r stores elapsed seconds only, so a finished 25m and an abandoned 30m that ran 25m look identical in it. The duration you asked for is visible to .B on_start and nowhere else, so the examples write a START/DONE/QUIT record to .I $XDG_STATE_HOME/ttym/sessions.tsv that shows follow\-through. .IP \(bu 2 Focus mode. During a countdown they pause .BR dunst (1) notifications and any .BR playerctl (1) or .BR mpc (1) playback, and restore both when it ends. Every external command is guarded, so the examples are harmless on a machine without them. .PP A commented .BR timew (1) bridge is included but off by default; it turns .B \-c comments into timewarrior tags. .PP Copy the ones you want and edit: .PP .RS .nf mkdir \-p ~/.config/ttym/hooks cp /usr/local/share/doc/ttym/hooks/on_done ~/.config/ttym/hooks/ chmod +x ~/.config/ttym/hooks/on_done .fi .RE .SH EXIT STATUS .TP .B 0 A countdown ran to completion. .TP .B 1 Usage error: an unknown option, or a duration that could not be parsed. .TP .B 130 The session was cut short, either by .B q or by .BR SIGINT , .BR SIGTERM , .BR SIGQUIT or .BR SIGHUP . The terminal is restored in every case. A stopwatch always exits this way \(em it has no natural end. .SH ENVIRONMENT .TP .B XDG_CONFIG_HOME Base directory for the files below. Defaults to .I ~/.config when unset or empty. .SH FILES .TP .I /etc/ttym.conf .RI [patch: config\-file] System\-wide runtime configuration, read before the per\-user file. .TP .I ~/.config/ttym/config .RI [patch: config\-file] Per\-user runtime configuration; .BR key " = " value lines. A .B # begins a comment at the start of a line or after whitespace, and never inside quotes; quote a value to protect surrounding spaces or a leading .BR # . Unknown keys and unparseable values are reported on stderr. Command\-line flags override this file, which overrides .IR /etc/ttym.conf , which overrides the compile\-time defaults in .IR config.h . .B timer never creates this file \(em see .BR \-\-dump\-config . .TP .I ~/.config/ttym/ttym.log .RI [patch: logging] Session log. TSV with three fields per line: .RS .PP .RS .nf YYYY\-MM\-DD HH:MM:SSSECONDSCOMMENT .fi .RE .PP Designed to be processed with .BR awk (1) and .BR grep (1) rather than re\-rendered by the binary. .RE .TP .I ~/.config/ttym/hooks/ .RI [patch: hooks] Directory containing the .BR on_start , .BR on_done , .B on_quit executables described in .BR HOOKS . .TP .I PREFIX/share/doc/ttym/hooks/ Commented example hooks, installed by .BR "make install" . Copy them into the directory above to use them. .SH EXAMPLES A twenty\-five minute work session, tagged for later stats: .PP .RS .nf timer \-c "+work coding" 25m .fi .RE .PP A countdown that pops a notification with custom text: .PP .RS .nf timer 10m Lunch .fi .RE .PP Total hours logged this week: .PP .RS .nf timer \-r \-\-raw | awk \-F'\\t' '{s+=$2} END {printf "%dh\\n", s/3600}' .fi .RE .PP Count .BR +work sessions ever: .PP .RS .nf timer \-r \-\-raw | grep '+work' | wc \-l .fi .RE .PP Stopwatch with no notifications: .PP .RS .nf timer \-s .fi .RE .SH DESIGN The binary does one thing: time intervals and, optionally, log them. Reports .RB ( "timer \-r" , .BR "timer \-\-stats" ) are read\-only views over the same TSV log. For any other view, pipe .B "timer \-r \-\-raw" through .BR awk (1), .BR grep (1) or .BR sort (1). No daemon, no IPC, no plugin system, no embedded TUI. Hooks are git\-style: executables you write yourself. .PP Compile\-time options live in .IR config.h ; runtime overrides (when the .B config\-file patch is applied) live in .IR ~/.config/ttym/config . .SH AUTHORS .B timer is maintained by \(/Lukasz Kasprzak. Distributed under the MIT license; see .B LICENSE in the source tree. .SH SEE ALSO .BR awk (1), .BR grep (1), .BR notify\-send (1), .BR paplay (1), .BR patch (1)