Skip to main content
The !timer command creates countdown timers that notify you when time’s up. Perfect for cooking, workouts, study sessions, and any activity where you need a countdown.

Subcommands

!timer <start|list|cancel> [duration/number]

Start a Timer

Create a new countdown timer.
!timer start <duration>

Duration Formats

FormatDescriptionExample
30mMinutes only30 minutes
1hHours only60 minutes
2h30mHours + minutes150 minutes
30Plain number30 minutes (default)
From TimerHandler.ts:5-8, plain numbers are automatically interpreted as minutes:
if (/^\d+$/.test(timeStr)) {
    return parseInt(timeStr);
}

Examples

30-minute timer:
!timer start 30m
Response:
⏰ Timer set for 30 minutes!
Short format:
!timer start 30
Response:
⏰ Timer set for 30 minutes!
1-hour timer:
!timer start 1h
Response:
⏰ Timer set for 60 minutes!
Complex duration:
!timer start 2h30m
Response:
⏰ Timer set for 150 minutes!
Maximum timer duration is 24 hours (1440 minutes). From TimerHandler.ts:65-70:
if (duration > 1440) {
    await socket.sendMessage(chat, {
        text: 'Timer duration cannot exceed 24 hours.'
    });
}

List Active Timers

View all your running timers with remaining time.
!timer list
Response:
⏰ Active Timers:
1. ⏳ 25 minutes remaining
2. ⏳ 45 minutes remaining

No Active Timers

!timer list
Response:
No active timers.
Remaining time is calculated dynamically from the stored end time (TimerHandler.ts:86-88):
const remainingTime = Math.max(0,
    Math.floor((timer.endTime.getTime() - Date.now()) / 60000)
);

Cancel a Timer

Stop and remove an active timer.
!timer cancel <number>
Example:
!timer cancel 1
Response:
⏰ Timer cancelled successfully!
number
integer
required
The timer number from the !timer list output

Complete Workflow

1

Start a timer

Set a timer for your activity
!timer start 25m
Response: ⏰ Timer set for 25 minutes!
2

Check your timers

View all active timers
!timer list
Response:
⏰ Active Timers:
1. ⏳ 23 minutes remaining
3

Get notified

When the timer expires, you receive a WhatsApp notification
4

Cancel if needed

Cancel a timer early if plans change
!timer cancel 1

Common Use Cases

Pomodoro Technique

!timer start 25m    # Work session
# ... work ...
!timer start 5m     # Short break

Cooking

!timer start 45m    # Bake the chicken
!timer start 20m    # Boil pasta
!timer start 10m    # Preheat oven

Workout Intervals

!timer start 30     # 30 seconds high intensity
!timer start 10     # 10 seconds rest

Study Sessions

!timer start 1h30m  # Deep work block

Parameters

start
subcommand
Create a new timer.Required: Duration (minutes, hours, or combination)Example: !timer start 30m
list
subcommand
Display all active timers with remaining time.Arguments: NoneExample: !timer list
cancel
subcommand
Stop and delete a timer.Required: Timer number (from list)Example: !timer cancel 1

Error Handling

No Subcommand

!timer
Response:
Usage: !timer start <duration> | !timer list | !timer cancel <number>

Missing Duration

!timer start
Response:
Please specify a duration (e.g., 30m, 1h, or just 30 for minutes).

Invalid Duration Format

!timer start tomorrow
Response:
Invalid duration format. Examples: 30m, 1h, or just 30 for minutes.

Exceeds Maximum

!timer start 48h
Response:
Timer duration cannot exceed 24 hours.

Invalid Timer Number

!timer cancel 99
Response:
Invalid timer number.

Unknown Subcommand

!timer pause
Response:
Unknown command. Use: start, list, or cancel.

Implementation Details

Time Parsing

From TimerHandler.ts:4-24, the parser handles multiple formats:
function parseTimeString(timeStr: string): number | null {
    // If it's just a number, treat as minutes
    if (/^\d+$/.test(timeStr)) {
        return parseInt(timeStr);
    }

    // Parse time notation (e.g., '30m', '1h')
    const hourMatch = timeStr.match(/(\d+)h/);
    const minuteMatch = timeStr.match(/(\d+)m/);

    let totalMinutes = 0;

    if (hourMatch) {
        totalMinutes += parseInt(hourMatch[1]) * 60;
    }
    if (minuteMatch) {
        totalMinutes += parseInt(minuteMatch[1]);
    }

    return totalMinutes > 0 ? totalMinutes : null;
}

Timer Storage

Timers are stored in the database with:
  • User ID (sender)
  • End time (calculated as current time + duration)
  • ID for reference
From TimerHandler.ts:72:
await TimerService.create(sender, duration);

Remaining Time Calculation

The list command calculates remaining minutes dynamically (TimerHandler.ts:85-90):
const timerList = timers.map((timer, index) => {
    const remainingTime = Math.max(0,
        Math.floor((timer.endTime.getTime() - Date.now()) / 60000)
    );
    return `${index + 1}. ⏳ ${remainingTime} minutes remaining`;
}).join('\n');
Yes! You can have multiple timers running simultaneously. Each timer operates independently, and you can view them all with !timer list.
The TimerService sends you a WhatsApp notification when the timer reaches zero. The timer is then automatically removed from your active timers list.
The current implementation doesn’t support pausing. You can cancel and restart if needed:
!timer cancel 1
!timer start 15m
Yes, timers are associated with your user ID (sender), so they’re private to you. Other users can’t see or modify your timers.
This depends on the TimerService implementation. If timers are stored in a persistent database, they should survive restarts. Check the service implementation for details.
  • !notify - For reminders at specific times rather than countdowns
  • !todo - Track tasks that timers might be associated with

Build docs developers (and LLMs) love