Omahub
← All plugins
A

Clock, Zones & Calendar

by Angel Ventura

Date/time label with a calendar popup, a time-zone converter, and read-only calendar sync from any iCal feed

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
8d4a2a8
Scanned
3 weeks ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

None
AI risk level
None
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
8d4a2a8
Reviewed
3 weeks ago

The plugin is a clock/calendar widget with optional iCal sync. The code is transparent, uses safe file handling, and only makes network requests to user-configured feeds. No malicious behavior or hidden danger detected.

How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/angel-ventura/omarchy-clock-zones-calendar --enable
Widgets #bar #quickshell

Clock, Zones & Calendar

An Omarchy bar widget: the clock, with a time-zone converter and optional read-only calendar sync folded into the calendar popup. Installs as angelv.clock — the plugin id is unchanged, only the repository was renamed.

Based on Omarchy's built-in omarchy.clock widget — see Attribution.

<p align="center"> <img src="preview.png" alt="The calendar popup: a month grid with event dots, calendar filter chips, a day agenda with Meet and Zoom join buttons, and the zones section open below showing five cities with day/night rails and the scrubber" width="420"> </p>

What it does differently

  • A zones section under the calendar, collapsed by default. Each row gets a sun/moon glyph, a 24-hour day/night rail, and a magnetic scrubber, so a time quoted in someone else's zone lands in yours at a glance.
  • The home row is detected from timedatectl, so it is always this machine's real zone. You never list it yourself.
  • A settings window. Feeds, zones and every option have a gear in the popup rather than a JSON file to edit. See Configure.
  • Calendar sync, read-only and off by default. Point it at any .ics or webcal:// link — Google, Apple, Outlook, Proton, Nextcloud, Fastmail, or a file on disk — and the month grid gets event dots, with an agenda for the day you click and optional reminders before a meeting. Several at once, each with its own colour. See Calendar sync.

Everything themes with Omarchy: there is no hardcoded colour in the plugin, every value goes through Color.*, Style.*, or bar.foreground.

Install

omarchy plugin add https://github.com/angel-ventura/omarchy-clock-zones-calendar.git --enable

Pick center when it asks for a section. Then remove the stock clock, since you now have two:

omarchy plugin disable omarchy.clock
omarchy restart shell

Remove

omarchy plugin remove angelv.clock
omarchy restart shell

Removal moves the folder to a hidden timestamped backup beside it rather than deleting it, and puts Omarchy's own omarchy.clock back in the bar in its place. To keep it installed but switch it off instead:

omarchy plugin disable angelv.clock

Requirements

Omarchy 4 (omarchy-shell). Nothing to install — every command this uses already ships with Omarchy:

Command Used for
date, timedatectl Zone offsets, and detecting your home zone
python3 Fetching and parsing calendar feeds. Standard library only — no pip packages
notify-send, xdg-open Reminders, and opening a meeting or calendar link

python3 is guaranteed: Omarchy depends on uwsm, which depends on Python.

Calendar sync is the only part that touches the network, and only to GET the feed URLs you configure.

Configure

Click the gear in the top right of the popup. It opens a settings window covering everything below — calendar feeds, zones, and the clock's own options — so none of it needs a text editor.

It opens as its own panel over the desktop rather than inside the popup: the popup is capped to the width of the month grid, which is nowhere to put a searchable zone picker or a pasted iCal URL. Every control writes as you change it; the popup picks the change up the next time you open it.

Tab
Calendars Add, rename, recolour, disable or remove a feed. A swatch beside each colour code shows the colour as you type it. Below the list: sync interval, reminders, and where links open
Zones Your home row's label and clock format, the zones you have added, and a searchable picker for adding more
Clock Agenda times and which day the week starts on

Reset sits beside the tabs and clears the tab you are looking at, after a confirmation naming what goes. On the Calendars tab it resets the sync options and keeps your feeds — a feed URL is a credential that exists nowhere else, so nothing in here deletes one in bulk. Remove feeds one at a time instead.

It sizes itself to the screen it opens on, so it fits a laptop and does not sprawl on a 4K panel, and on two monitors it opens on the focused one.

Feed URLs are masked, with a Show button per row. A Google iCal address is a bearer credential — anyone holding it can read that calendar indefinitely, without signing in — so it should not be sitting in plain text on a screen you might share or screenshot.

Escape closes it, and so does a click outside it. There is nothing to configure to make it appear centred: it is drawn over the desktop the way the rest of Omarchy's settings surfaces are, not opened as an application window that your tiling layout would have to be told about.

The trade is that it is not a window, so a close-window keybind acts on whatever real window is behind it. Nothing in here suggests otherwise — Escape and clicking outside are what it offers, and what the footer names.

The files below are still the source of truth, and hand-editing them works exactly as it always did.

The zones are configuration, not code. Edit this widget's entry in ~/.config/omarchy/shell.json:

{
  "id": "angelv.clock",
  "format": "dddd h:mm AP",
  "formatAlt": "d MMMM 'W'ww yyyy",
  "verticalFormat": "h\n—\nmm\nAP",
  "homeName": "Atlanta",
  "homeHour12": true,
  "zones": [
    "America/Los_Angeles",
    "Europe/London",
    "Asia/Tokyo"
  ]
}
Key What it does
format / formatAlt The bar label, and what it shows when clicked through
verticalFormat The label when the bar is on a vertical edge
homeName The label for the home row only — the zone itself is detected
homeHour12 12-hour clock for the home row
zones IANA zone names to show as extra rows
calendarSync Rarely needed — sync follows whether a feed is configured. Set false to stay inert next to a calendars.json another tool owns
syncIntervalMinutes Minutes between background pulls. 0 is manual only. Default 15, floor 5
notifyUpcomingEvents false silences reminders. On by default when sync is on
notifyMinutesBefore "staged" (10m, 5m, 1m) or a single number of minutes
hour12 Agenda times as 12-hour with AM/PM, or 24-hour. Unset follows your locale
weekStartDay "monday" or "sunday". Unset follows your locale, which is what the stock clock does too
meetingHandler "webapp" (default) opens Zoom and Meet in their own window; "browser" always uses xdg-open

Notes:

  • Never put your home zone in zones — it is added automatically.
  • Rows sort by UTC offset, west to east, whatever order you write them in.
  • Changes apply the next time you open the panel, not while it is open.

Calendar sync

Off until you ask for it. Once on, the popup grows a dot under every day that has something on it and an agenda for the day you click; days are only clickable once sync is on, so the grid stays the plain read-out it was designed as when it is off.

Setting it up

Click the gear in the popup, go to Calendars, and paste your link. The window creates ~/.config/omarchy/calendars.json for you the first time it opens, so there is no file to make and no restart to do. Sync switches itself on once a feed has a URL, and stays off while none does.

If you would rather write the file yourself, it is a plain array and still works exactly as before:

[
  {
    "name": "Personal",
    "url": "paste your link here",
    "color": "#4A90E2",
    "enabled": true
  }
]

Edits made by hand are picked up immediately, with no restart.

Where the link comes from:

Google Settings and sharing → Integrate calendar → Secret address in iCal format. Shown as dots — use the copy button
Apple iCloud Share icon → turn on Public Calendar → copy the webcal:// link. This genuinely publishes the calendar; iCloud has no private option
Outlook / 365 Settings → Calendar → Shared calendars → Publish a calendar. Often disabled by company admins
Anything else Any .ics or webcal:// link — Proton, Nextcloud, Fastmail, or a local file path

Treat these links like passwords: anyone holding one can read that calendar. The file is created readable only by you.

The feed list

Feeds live in ~/.config/omarchy/calendars.json, not in shell.json — a private iCal URL is a bearer credential in disguise, and shell.json is the file people paste into forum posts. The file is written 0600 and re-read whenever it changes, so no restart is needed after an edit.

[
  {
    "name": "Personal",
    "url": "https://calendar.google.com/calendar/ical/you%40gmail.com/private-xxxxxxxx/basic.ics",
    "color": "#4A90E2",
    "enabled": true
  },
  {
    "name": "Family",
    "url": "webcal://p00-caldav.icloud.com/published/2/xxxxxxxx",
    "color": "#e5c07b",
    "enabled": true
  }
]

Add as many as you like — each gets its own colour, a filter chip in the agenda header, and can be switched off with "enabled": false without deleting it.

This is deliberately read-only: both of those are one-way feeds, so events cannot be created or edited from the panel. Two things follow from that, and neither is a bug in this plugin:

  • Google caches its own iCal feed, so an edit made on the web can take a while to show up here. A sync interval under five minutes buys nothing, which is why five is the floor.
  • Apple's link requires the calendar to be published, which means anyone who has the URL can read it. Treat it accordingly.

If you need writable calendars, OAuth against a restricted Google calendar, or JMAP/Fastmail, use sync-calendar-omarchy, which this borrows its iCalendar reader from and which does all of that. Note that it is also a clock widget, so the two replace each other rather than stacking — run one or the other.

In the panel
Click a day Show that day's agenda
Click the big date at the top Back to today: the current month, and the agenda back on today. Live only when there is something to undo
Calendar chips Filter by calendar
Refresh button Sync now. Its tooltip shows when it last synced
Plus button Start a new event on the shown day in Google Calendar. Only appears if a Google feed is configured
Click an event Open it in Google Calendar, where you can edit or delete it
Camera button on an event Join a detected Meet / Zoom / Teams / Webex / Jitsi link. The tooltip names the host it will open

The buttons sit in the agenda header and on each event row; hover any of them for a tooltip. (They are drawn with Nerd Font icons, which is why they are described in words here rather than shown.)

Clicking an event is read-only on this side: it opens Google Calendar and leaves the editing to Google, so the widget still stores no credential and still never writes to a calendar. A Google feed carries no link back to its events, so the link is built from the event id in the feed and the calendar address in the feed URL; where an id is not one Google issued, the click falls back to that day's view. Feeds that are not Google's have no address to build from, and their rows are not clickable.

The plus button opens Google's own new-event form with the day filled in, as an all-day event you can give a time in the form. It lands in whichever calendar is the default for the account you are signed in as — a feed can be one you only subscribe to, so the button does not try to aim at the calendar the agenda came from. Nothing is created until you save it there.

Sign in to Google in Chromium first. By default the event opens as an Omarchy web app, and those run in Chromium — a separate browser profile from your daily one, signed out until you sign in there once. See Where a click lands.

Reminders

A desktop notification before a meeting starts, whether or not the popup is open. "staged" (the default) nudges at 10, 5 and 1 minutes; a number fires once at that mark. All-day events never notify, and each nudge fires once — never twice for the same event and stage.

Set "notifyUpcomingEvents": false to silence them.

Where a click lands

By default ("meetingHandler": "webapp") a call opens in its own window rather than a browser tab. Camera and microphone permission is per-origin and sticks, and a real window can carry a Hyprland rule — a browser tab cannot. Clicking an event to open it in Google Calendar follows the same setting.

Click Opens
Zoom zoommtg://, which Omarchy's own handler turns into the web client. A natively installed Zoom claims that scheme first, which is better still
Google Meet Its own window, via omarchy-launch-webapp
An event, or the plus button Google Calendar in its own window, same way
Teams, Webex, Jitsi, anything else Your default browser

You do not need to install a web app for any of this. omarchy-launch-webapp is chromium --app=<url> and takes the address directly, so Meet and Google Calendar get their own window whether or not an entry exists. Creating one only adds it to the launcher with a name and an icon, which is worth doing for the ones you open by hand:

Super + Alt + Space → Install → Web App, then a name and an address — say Google Calendar and https://calendar.google.com/. It will ask for an icon; any image URL or an installed icon name works.

What these windows do need is a signed-in Chromium: it is a separate browser profile, so sign in to Google there once. Set "meetingHandler": "browser" to send everything to your default browser instead.

Hacking on it

Zone offsets are read by shelling out to date. Qt's JS engine accepts the timeZone option on Intl/toLocaleString and then silently ignores it, so IANA zones cannot be resolved in QML directly.

After editing Panel.qml, reload with omarchy restart shell — a rescanPlugins is not enough for panel changes.

If you are developing against this rather than using it, prefer omarchy plugin disable angelv.clock over omarchy plugin remove — remove moves your working copy to a hidden .bak folder and restores the stock clock.

Attribution

This work is based on Omarchy. It began as a byte-for-byte clone of the Omarchy shell's first-party clock widget, made with omarchy plugin clone omarchy.clock, and BarWidget.qml, Model.js and Panel.qml still contain substantial portions of that original code.

  • Upstream: basecamp/omarchy
  • Upstream author: David Heinemeier Hansson / Basecamp
  • Upstream license: MIT

The calendar sync is derived from sync-calendar-omarchy by promaaa, also MIT. fetch-events.py keeps that project's iCalendar reader and its RRULE expanders; the Google API, OAuth, JMAP and event-writing paths were removed, since none of them are needed for a read-only .ics feed.

Unofficial and independent — not endorsed by or affiliated with the Omarchy project or Basecamp. See NOTICE for the full derivation record.

License

MIT, retaining the upstream copyright notice. See LICENSE.