Skip to content

Clock App

P3DROVFX edited this page Oct 12, 2026 · 1 revision

Clock App

A full clock application that lives inside the shell: alarms, a world clock, timers, a stopwatch, a Pomodoro, a Bedtime coach and a Reminders tab, all in one floating window (ii Clock). It follows the same design as the Notes app — a rail on the left, the current tab in the middle, a side sheet on the right for anything that used to be a dialog — and it is the part of the shell that makes alarms reliable: they ring after a suspend, after a crash, and even wake a sleeping computer.

Alarms, timers and the Pomodoro belong to services, not to the window. Closing the app never stops anything — the bar, the Dynamic Island, the Sidebar Dashboard and the lock screen keep showing and ringing them.

Quick start

  1. Super + Alt + T opens the app (it is a toggle — press it again to close).
  2. Pick a tab in the rail. The big button at the top of the rail does the main action of the tab: New alarm, Add city, New timer or New reminder. Stopwatch and Pomodoro drive everything from their own controls.
  3. The gear at the foot of the rail opens the app's own settings page; every clock option lives there.

From a terminal or a script:

qs -c ii ipc call clock toggle
qs -c ii ipc call clock open
qs -c ii ipc call clock openTab bedtime   # alarms | worldClock | timer | stopwatch | pomodoro | bedtime | reminders

There is also a launcher entry in Settings → Overlays & OSD → Clock App (a master switch, Config.options.clockApp.enable, plus an Open button).


The window

  • Rail — collapsed (icons) or expanded (icons and labels); it collapses by itself on a narrow window and the choice is remembered. Each tab carries a small badge: how many alarms are on, how many cities, how many timers are running, a dot for a running stopwatch or Pomodoro, a dot while Bedtime is winding down, how many reminders are active.
  • Side sheet — editing never leaves the page. Creating or editing an alarm, a timer, a city or a reminder slides a sheet in from the right; the grid you are editing stays in view and slides narrower instead of re-flowing.
  • Compact layouts — on a narrow window the rail falls back to a bottom navigation bar (the active tab wears a pill) and the sheet takes the whole window width.
  • Lazy by design — only the visible tab exists. A hidden tab holds no delegate, binding or timer. The window itself is built asynchronously when the keybind is pressed, kept hidden for 30 seconds so a quick reopen is instant, then destroyed entirely. The app's own once-per-second clock runs only while the window is visible.
  • Window rules — it is a normal Hyprland toplevel titled ii Clock; hyprland/rules.lua floats and centres it. Its size matches the Usage and Modes apps (and the EasyEffects app), so moving between them never resizes the thing you look at.

Alarms

The Alarms tab is a dense grid of tiles. The next alarm leads it as a wide hero tile; every alarm follows as a tile (five across on a wide window, one on a narrow one). A tile has an on/off switch, the time, the label, the repeat days, the time left, and a menu with Edit, Duplicate, Skip next and Delete.

The editor sheet has the time, an optional label, the repeat (Once, Every day, Weekdays, Weekends or individual days) and Next occurrence preview. A one-off alarm can be set for a specific date. Skip next alarm keeps a repeating alarm but silences its coming occurrence only — the tile says Next one skipped.

Tied to your tasks and calendar

  • From the timetable. With khal available, the bottom of the Alarms tab offers From your timetable: the upcoming events as one-click alarms a few minutes before (Ring before the event, default 15). The alarm keeps the event's UID, so it appears as an Alarm row in the event's details in the Cheat Sheet timetable, and changing the lead time replaces the alarm instead of duplicating it. See Calendar and Timetable.
  • From a task. The To Do sheet can set an alarm for a task (setAlarmForTask); the editor shows a Linked task, and the alarm goes away when the task is completed or deleted in the local provider.

How an alarm rings

  • Window-based firing. The service does not compare "now" with a time; it asks which occurrences of each alarm fall in the interval since the last check. The last check is persisted once a minute and whenever an alarm is handled (Persistent.states.alarmState.lastCheck), so a crash or a restart can repeat at most one minute and never rings an alarm twice.
  • Catch-up and missed alarms. An alarm that is late by up to time.alarms.catchUpMinutes (10) still rings. Anything older is recorded as missed — a notification and a strip on the Alarms tab with Dismiss; a missed one-off alarm is turned off.
  • A queue. Alarms in the same minute, or that fall due while another one rings, wait in a queue and ring one after another when you stop or snooze the current one.
  • Ringing surface. By default the alarm shows as a notification (or in the Dynamic Island, which takes the alarm over when its alarm activity is enabled). Full-screen ringing (time.alarms.useFullscreenPopup) puts up a centred overlay card with exclusive keyboard focus.
  • Snooze and auto-silence. Snooze length (default 9 min) and Silence after (default 5 min; 0 rings until dismissed).
  • Gentle wake. sounds.alarmFadeIn fades the alarm in over sounds.alarmFadeInSeconds (30) instead of starting at full volume. The alarm sound rings even when system sounds are off, and can be replaced under Settings → Sound & Alerts (sounds.custom.alarm).

Wake from suspend

When Wake from suspend is on (time.alarms.wakeFromSuspend, default on), the service programs a transient systemd user timer named ii-alarm-wake with WakeSystem=true, time.alarms.wakeLeadSeconds (90) before the next alarm. It needs no root: the user manager of systemd holds CAP_WAKE_ALARM on Fedora and most current distributions. The timer only wakes the machine; the window-based check above is what actually rings, and it catches the alarm up the moment the shell runs again.

The phone's alarm

With the phone connected, the shell mirrors the phone's next alarm read-only over ADB (dumpsys alarm, filtered on the device) every clockApp.phoneAlarm.pollMinutes (10). It appears as a Phone 07:30 chip, warns when it differs from the PC's next alarm within 12 hours, and ringing is inferred when the mirrored time passes and the next one changes. Packages that borrow the alarm API for automations (Samsung Routines by default) are ignored via phoneAlarm.ignorePackages.


World clock

A grid of city cards: local time, date, the offset from your own zone (Same time, +5 h, tomorrow), a day/night indication, and an optional analog dial that shows every city at once (clockApp.analogWorldClock). The Add city sheet searches the whole IANA zone catalog. Cities can be renamed, reordered with Move up / Move down, and removed.

The list is stored in time.worldClocks, and WorldClockService is the single source for the bar's clock popup and the app. UTC offsets come from one Python process (scripts/clock/timezones.py) instead of a date call per city; they refresh when the list changes, when a surface opens and finds them stale (30 minutes), and on the hour while a surface holds the service, because DST moves offsets on the hour. Nothing ticks inside the service — the faces are drawn from the shared DateTime clock.


Timer, Stopwatch and Pomodoro

  • Timer — any number of countdowns at the same time. Create one with the keypad (h / m / s) or a preset (time.timer.presets, default 1, 5, 10, 15, 30 and 60 minutes; Save as preset on the keypad adds one, and a preset is removed in the app's settings). Each card has a progress ring, Pause, Reset, Add a minute, Rename and Delete; a finished timer says Time's up and Clear finished sweeps them. A finished timer notifies when time.timer.notify is on.
  • Stopwatch — start/pause, Lap and Reset, with a list of laps on a pane of their own; the fastest lap is tinted with the accent colour and the slowest with the error colour.
  • Pomodoro — focus, short break and long break (time.pomodoro.focus 1500 s, breakTime 300 s, longBreak 900 s) and Cycles before a long break (4). Skip to next phase jumps ahead; each phase can notify (time.pomodoro.notify).

All three are the same state the rest of the shell uses. TimerService keeps the countdowns as absolute end dates in Persistent.states.timer, so they survive restarts and reloads; one shared countdownTick replaces a Timer per card. The same timers appear as the Timer bar widget (several styles, including Expressive), the Dynamic Island's timer notch and the Dashboard's Timer page, which also takes keyboard shortcuts (Pomodoro: Space/S start or pause, R reset, E set the time; Stopwatch: Space/S, L lap, R reset when stopped).


Bedtime

A target time to stop using the computer, reminders around it, and a record of when each night you actually did. Enable it on the Bedtime tab (clockApp.bedtime.enable, off by default).

  • Target (23:30 by default) and which nights it applies to.
  • Wind-down reminder a number of minutes before (30), a notification at bedtime, then a nudge every N minutes while you are still up (remindEveryMinutes, 15; 0 turns the nudges off).
  • Tracking. A "night" is named after its evening and ends at nightEndsHour (5) the next morning, so 01:10 still belongs to yesterday's night. While the screen is unlocked and there has been input in the last two minutes you count as up; the last such moment is the night's stop time, and every minute up past the target adds to minutes late. The tab shows the last nights as bars, the average against the target and the streak of nights on time. Nights the shell missed are estimated from the Usage app's hourly screen time and drawn faded.
  • Modes & Routines. A bedtime trigger (windDown, bedtime or either) lets a routine dim, mute or lock the machine.
qs -c ii ipc call bedtime status          # on|off | phase | target
qs -c ii ipc call bedtime setTime 23:00
qs -c ii ipc call bedtime enable|disable
qs -c ii ipc call bedtime forget 2026-10-03

Reminders

A Samsung-Reminder-style tab for things that need a time, not a place on a to-do list. They are stored in their own file ($XDG_STATE_HOME/quickshell/user/reminders.json) because they carry a time, an alert level, a checklist and attachments that the To Do providers would drop. RemindersService is that file's only writer.

  • Lists and views — Today, Next 7 days, Overdue, No alert, Completed, Recycle bin and your own categories (each with a colour); card or list view, sort by alert time, modified, created, name or category, search across titles, notes, checklists and links, multi-select, Move to category, Duplicate. Typing a title in the quick-add row and pressing Enter makes one; Ctrl + N opens the full editor; there is a dictation button.
  • The editor — title, date and time (or All day, which alerts at allDayTime, default 09:00), an Early alert (for example a day or a week before), a repeat rule (every N minutes/hours/days/weeks/months/years, on chosen weekdays, ending never, after N times or on a date; a monthly reminder on the 31st falls on the last day of shorter months), notes, a checklist, links, images and files, an Important star.
  • Alert levels — light is a notification with Complete and Snooze; medium takes the screen with a full-screen alert and one chime; strong does the same and keeps ringing until you answer or it goes quiet (autoSilenceMinutes, then it becomes a notification). The alert's background can be a colour or a picture. Keys on the alert: Enter completes, S snoozes, Esc dismisses (the reminder stays open with a notification left behind). While the Dynamic Island owns reminders, it takes over the alert.
  • Reliability — one timer aimed at the next due alert, capped at a minute so a resume from suspend is noticed; each fired occurrence is remembered on the reminder, so a restart never rings twice; one found late (more than catchUpMinutes) arrives as a quiet "missed" notification. wakeFromSuspend wakes the machine for Medium and Strong reminders.
  • Housekeeping — completed reminders can be deleted after N days (autoDeleteCompletedDays); the recycle bin keeps items trashDays (30) days.
  • Microsoft To Do sync — two-way, through the Outlook sign-in (it reuses the Microsoft application's client ID, needs the To Do permission, and the phone side is Samsung Reminder's own Sync with Microsoft To Do). It runs on start, a few seconds after each local edit and every todoSync.intervalMinutes (15); an edit made while a sync is in flight keeps its local version.
  • Timetable — reminders can be shown in the Cheat Sheet timetable (showInTimetable).
qs -c ii ipc call reminders add "Call the bank"
qs -c ii ipc call reminders addAt "Take out the bins" "2026-10-14 19:00" strong
qs -c ii ipc call reminders list | next | ringing
qs -c ii ipc call reminders complete <id>

Settings page

The gear in the rail opens a page that slides over the tab area. It is built only while open. It groups the options by tab — Clock format (24h / 12h with AM/PM / 12h am/pm — used everywhere in the shell, time.format), Start week on Monday, Seconds in the app, the tab the app Opens on (Last used or a fixed one), alarm behaviour (snooze, silence, full-screen ringing, ring late alarms, wake from suspend, show the next alarm and how far ahead, gentle wake and its fade-in length, Alarm sound with Preview), timer and Pomodoro sounds and notifications, world-clock options, timetable suggestions, phone alarm mirroring, Bedtime and Reminders (alert defaults, sync).

Configuration

Key Default Meaning
clockApp.enable true Master switch for the app
clockApp.startTab "last" last, alarms, worldClock, timer, stopwatch, pomodoro, bedtime or reminders
clockApp.showTimetableEvents / timetableLeadMinutes / timetableLookaheadDays true / 15 / 2 Timetable suggestions on the Alarms tab
clockApp.analogWorldClock, showSecondsInApp true, true World-clock dial; seconds in the app
clockApp.bedtime.* see above enable, time, days[7], windDownMinutes, remindEveryMinutes, nightEndsHour
clockApp.phoneAlarm.* enabled, 10 min enable, pollMinutes, clockApps, ignorePackages
clockApp.reminders.* see above defaultAlert, allDayTime, snoozeMinutes, autoSilenceMinutes, catchUpMinutes, wakeFromSuspend, alertBackgroundColor/Image, alertSound, trashDays, sortBy, view, todoSync.* …
time.alarms.* see above useFullscreenPopup, snoozeMinutes 9, autoSilenceMinutes 5, catchUpMinutes 10, wakeFromSuspend, wakeLeadSeconds 90, upcomingMinutes 60, showUpcoming
time.timer.*, time.pomodoro.*, time.worldClocks see above Presets, durations, cities
sounds.alarm, sounds.timer, sounds.pomodoro, sounds.alarmFadeIn, sounds.alarmFadeInSeconds, sounds.custom.* see above Sounds

Where the clock shows up

  • Bar — the Clock widget's popup (with the world clocks), the Timer widget (countdowns, Pomodoro, stopwatch and the next alarm chip within upcomingMinutes), and the Dashboard button's alarm and countdown icons (bar.dashboardButton.showAlarms, showCountdowns).
  • Dynamic Island — a timer notch and a ringing alarm / reminder takeover.
  • Lock screen — an alarm indicator (lock.showAlarm).
  • Modes & Routines — triggers alarm (ringing, dismissed, snoozed, missed), alarmSoon, bedtime, timerDone, phoneAlarm; actions that pause alarms (with revert) or skip the next one, and start a timer.
  • AI — the assistant can read the next alarm and start the Pomodoro or stopwatch; see AI Integration.

Under the hood

Piece Role
modules/ii/clock/ The app: ClockApp.qml (lifecycle, keybind, IPC), ClockAppWindow.qml, ClockAppContent.qml, tabs/, reminders/, components/ (Clock* design tokens and pieces, shared by Usage, Modes and EasyEffects)
services/AlarmService.qml Alarm list, window-based firing, queue, snooze, missed alarms, wake timer; IPC target alarmService (trigger, add, stop, snooze, remove, next, ringing, wake, replaySince, clearMissed)
services/TimerService.qml Countdowns, Pomodoro, stopwatch
services/WorldClockService.qml, scripts/clock/timezones.py Cities and UTC offsets
services/BedtimeService.qml Bedtime phases and nightly records
services/PhoneAlarmService.qml Read-only mirror of the phone's next alarm (IPC phoneAlarm)
services/RemindersService.qml, services/RemindersSync.qml, scripts/outlook/todo_sync.py The reminders store, alerts and Microsoft To Do sync
modules/ii/alarmRingingPopup/, modules/ii/reminderAlertPopup/ The full-screen ringing surfaces

AlarmService, BedtimeService and PhoneAlarmService are touched at startup by shell.qml (loadDeferredServices); otherwise, after a reload, alarms would only resume being checked once something referenced the singleton. Persistent state lives in states.json: alarms, alarmState (last check, missed), timer, bedtime.nights, clockApp.


Related pages

← Back to Home

Clone this wiki locally