- Go 47.1%
- QML 31.2%
- JavaScript 21.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The bar clock hover tooltip took calendarStore.upcomingEvents.slice(0, 3), but that property is the raw events array from the state file — source order, unfiltered, spanning the binary's whole [now-lookbehind, now+lookahead) window. So the tooltip showed the first three rows as written (a past birthday and two Heartgard reminders), never the actual soonest events. Add Model.upcomingEvents(events, todayKey, limit): keep events on today or a later day, sort by start instant, take the limit. Day-granularity filter (not a now-instant cutoff) so today's all-day events survive. The agenda panel already did this via agendaDayKeys; the tooltip was the one surface that skipped it. |
||
| cmd/calagenda | ||
| docs/superpowers/plans | ||
| internal | ||
| packaging | ||
| test | ||
| testdata | ||
| .gitignore | ||
| Agenda.qml | ||
| BarWidget.qml | ||
| CalendarStore.qml | ||
| EventRow.qml | ||
| go.mod | ||
| go.sum | ||
| manifest.json | ||
| Model.js | ||
| Panel.qml | ||
| README.md | ||
| WorldClocks.qml | ||
calagenda
An Omarchy bar widget with a real calendar agenda — plus the small CLI that
feeds it, in one repo. The calagenda binary fetches events from
ICS/CalDAV/file sources, expands recurrences, and writes them as JSON; the
Omarchy plugin (a fork of the stock omarchy.clock) renders the agenda, day
dots, day selection, meeting-join buttons, and world clocks in the bar.
They talk over a stable seam: the plugin shells out to calagenda
(calagenda paths --state, calagenda sync) and watches the JSON state file.
The plugin runs without the binary too — month grid, rails, and world clocks
still work; only the agenda shows an install hint.
The binary
go install git.straub.dev/erik/calagenda/cmd/calagenda@latest
Under mise, register it as a tool so it survives Go upgrades:
mise use -g "go:git.straub.dev/erik/calagenda/cmd/calagenda@latest"
Configure
~/.config/calagenda/config.toml (create it mode 0600):
lookbehindDays = 1
lookaheadDays = 30
[[sources]]
name = "Proton"
type = "ics"
url = "https://calendar.proton.me/api/calendar/v1/url/<token>/calendar.ics"
color = "#8a5cf6"
[[sources]]
name = "Work"
type = "ics"
url = "https://outlook.office365.com/owa/calendar/<token>/reachcalendar.ics"
color = "#e5484d"
timezone = "America/New_York" # optional; see below
Getting a feed URL:
- Proton Calendar — Settings → Calendars → Share → "Share with anyone."
- Outlook/M365 — Settings → Calendar → Shared calendars → "Publish a calendar," ICS format.
- Google — Calendar settings → "Secret address in iCal format."
- CalDAV (iCloud, Fastmail, Nextcloud) — use
type = "caldav"withusername/passwordCommand.
Per-source timezone (optional): omit it to respect what the feed declares
(the default). Set it to an IANA zone (e.g. America/New_York) to force every
timed event in that source into that zone, ignoring the TZID/Z the feed
carries — the fix for feeds that stamp local wall-clock times as UTC. All-day
events are unaffected.
Secrets never need to sit in the file: use passwordCommand = "secret-tool lookup service calagenda account work".
Run
calagenda doctor # validate config, probe every source
calagenda sync # fetch, expand, write ~/.local/state/calagenda/events.json
calagenda sync --stdout # same, printed to stdout, no write
calagenda paths state # print the state file path
calagenda paths # print both the config and state paths
calagenda --help # full command and flag reference
Every command accepts --config and --state to override the XDG-derived
paths — useful for testing a feed without touching your real config. The
plugin triggers calagenda sync on its own (throttled) while it's on the bar,
so a background timer isn't required; run calagenda sync by hand or from your
own systemd timer if you want refreshes without the widget loaded.
The Omarchy plugin
omarchy plugin add https://git.straub.dev/erik/calagenda.git
omarchy plugin enable erik.calagenda center
Then set up the binary above so the agenda has data.
Settings
Set via omarchy bar set erik.calagenda <key> <value> [--json], or by
hand-editing this plugin's entry in ~/.config/omarchy/shell.json:
| Key | Default | Meaning |
|---|---|---|
format / formatAlt |
inherited from the clock | bar label format; right-click cycles through built-ins plus {next}, {nextTime}, {nextIn}, {count} |
agendaDays |
7 |
how many upcoming days the agenda covers |
maxAgendaEvents |
12 |
cap on total agenda rows before the list truncates |
showDayDots |
true |
small colored dots on grid days with events |
showJoinButtons |
true |
one-click join for detected Meet/Zoom/Teams/Webex/Jitsi/Whereby links |
worldClocks |
[] |
e.g. [{"label":"Work","tz":"America/New_York"}] |
Local development
The shell's plugin watcher may not follow a symlinked plugin directory for
hot-reload — if edits don't show up live, run omarchy-shell shell rescanPlugins
after saving. rescanPlugins alone is not reliable for verifying changes to an
already-open popup's QML content — for that, restart the shell with
omarchy-restart-shell.
Run the plugin's JS unit tests with node --test test/model.test.js; the
binary's tests with go test ./....