Itsy Calendar
Itsy Calendar is an Omarchy clock replacement with a local-vdir calendar store, a short-lived Rust calendar engine, and a pinnable calendar panel. It creates a writable Personal calendar on first startup. CalDAV accounts and provider credentials remain outside the plugin.
Prerequisites
- Omarchy 4 with the Omarchy shell and Hyprland running.
jq,sha256sum, andcurlfor engine downloads, update checks, and URL calendar subscriptions.- A supported
x86_64oraarch64Linux machine. The engine is a static musl release; Cargo and Python are not runtime prerequisites. vdirsynceris recommended for CalDAV sync;khalis useful for inspecting the resulting vdirs. Itsy Calendar does not install or configure either.
For example, after configuring vdirsyncer yourself:
vdirsyncer discover
vdirsyncer sync
khal list
The panel can create more writable local calendars and add read-only HTTPS or
webcal subscriptions. URL calendars refresh at startup, every 15 minutes, and
when Sync Now is selected. The source URL is stored with mode 0600 inside
Itsy Calendar's XDG data directory. Sync failures never hide records already
present locally.
For a read-only subscription, add an empty .itsy-calendar-read-only marker
to its calendar directory. The sync tool can still update the directory, while
Itsy Calendar hides mutation actions and rejects writes to that calendar.
Install and review
Omarchy plugins run unsandboxed inside the long-lived omarchy-shell process.
Review the repository, especially manifest.json, QML entry points,
setup, and scripts/, before enabling it:
omarchy plugin add https://github.com/ajanraj/itsy-calendar.git
less ~/.config/omarchy/plugins/io.github.ajanraj.itsy-calendar/README.md
~/.config/omarchy/plugins/io.github.ajanraj.itsy-calendar/setup doctor
~/.config/omarchy/plugins/io.github.ajanraj.itsy-calendar/setup install
omarchy plugin add validates the manifest but does not run setup. The
explicit setup step downloads the architecture-specific engine only after the
user asks for installation and enables the reviewed plugin as the final step.
It verifies the digest pinned in
scripts/engine-checksums.json before placing the executable at:
${XDG_DATA_HOME:-$HOME/.local/share}/itsy-calendar/bin/itsy-calendar-engine
The released checksum map is deliberately fail-closed. A source checkout can
contain UNRELEASED entries until the two-phase release process has committed
the real digests. For local development, use the explicit, network-free
override (never with an unreviewed binary):
./setup install --engine-path /absolute/path/to/itsy-calendar-engine
This hashes and atomically copies that file but is not a release trust path.
Release provenance
Engine releases use a tag-only workflow with every action pinned to a full
commit SHA, fixed Rust and cross versions, and digest-pinned build images.
Before tagging, the release candidate and a second CI build must match
byte-for-byte; the matching digests are then committed. The workflow checks
that the tag, source commit, package version, and those committed engine
digests agree before it publishes anything. It also creates build-provenance
attestations for both engine binaries. Before tagging, the release maintainer
must verify that repository release immutability is enabled; after publication,
the workflow verifies the resulting signed immutable release. From v0.2.1
onward, GitHub locks the tag and assets after that publication.
To verify the release and an engine binary:
gh release verify v0.2.1 --repo ajanraj/itsy-calendar
gh release download v0.2.1 --repo ajanraj/itsy-calendar \
--pattern 'itsy-calendar-engine-x86_64-unknown-linux-musl'
gh attestation verify ./itsy-calendar-engine-x86_64-unknown-linux-musl \
--repo ajanraj/itsy-calendar \
--signer-workflow ajanraj/itsy-calendar/.github/workflows/release.yml \
--source-ref refs/tags/v0.2.1
What setup changes
./setup install performs a narrow transaction:
- verifies and atomically installs the pinned engine;
- changes exactly one
omarchy.clockbar entry'sidtoio.github.ajanraj.itsy-calendar, preserving its section, index, and every other property; - changes
bar.centerAnchoronly when it wasomarchy.clock; - adds a uniquely marked
hypr.itsy-calendarfragment and a marked include inhypr/bindings.lua, overriding the existingSuper+Ctrl+Alt+Dbinding; - reloads the Omarchy shell and Hyprland when their commands are available.
The original bytes, modes, and hashes are journaled outside the checkout at
${XDG_STATE_HOME:-$HOME/.local/state}/itsy-calendar/setup.json. Temporary
files are created beside their target and renamed atomically. Setup never
evaluates a user-provided command string; executable-plus-argument-array
settings belong to the runtime, not this installer.
The URI handler is opt-in:
./setup install --register-uri
This registers itsycal:// through the fixed xdg-mime argv interface and
records the previous handler. Uninstall restores that handler only while it
still points to Itsy Calendar. No URI association is changed by a normal
install. The handler accepts only itsycal://date/now and strict Gregorian
itsycal://date/YYYY-MM-DD links; malformed links are ignored, and valid links
are dispatched directly to the running Calendar service.
Capabilities
The Calendar Engine speaks protocol 1 and reads one JSON request, writes one JSON response, logs only to stderr, and exits nonzero for errors. It supports:
doctor: discover local vdir calendars and report capabilities/diagnostics;snapshot: inclusive-start, exclusive-end occurrence snapshots;apply: create an item or delete one occurrence / all future occurrences;manage: ensure the Personal calendar, create local calendars, and add or refresh URL subscriptions.
The engine preserves date-only, floating, named-timezone, recurrence,
detached-override, unknown-property, and malformed-item boundaries. It does not
authenticate to providers, run vdirsyncer/khal, invoke a shell, or provide an
event-edit UI. URL downloads execute curl with a fixed argument list and an
HTTPS-only redirect policy. Creation requires the explicitly selected writable
Creation Calendar.
The resident Omarchy service owns snapshots, polling, alerts, hourly sound, and IPC once the plugin is enabled. The bar remains presentation-only, so a multi-monitor shell does not duplicate engine work or notifications.
In Advanced settings, optional My calendar emails identify which ICS
attendee is you. This enables accurate declined filtering and pending/tentative
styling; when left empty, Itsy Calendar does not guess. The panel follows the
global Omarchy theme. Its source-derived row shortcuts are Ctrl+Shift+J to
add a row and Ctrl+K to remove one; Ctrl+J remains Join because macOS's
separate Command-J and Control-J both map to Ctrl on Linux.
Setup commands
./setup install [--register-uri] [--engine-path PATH]
./setup install-engine [--engine-path PATH]
./setup check-update
./setup doctor
./setup shortcut 'SUPER + CTRL + ALT + D'
./setup disable
./setup uninstall
check-update is non-mutating and prints exactly one protocol-1 JSON envelope,
for example:
{"protocol":1,"ok":true,"data":{"current":"0.2.1","latest":"0.2.1","available":false}}
The UI checks every four days and on demand. An update is reviewed through
Omarchy's plugin-update flow; the engine is never silently replaced. The UI
must obtain confirmation before calling install-engine.
disable restores the stock clock and binding while retaining inline plugin
settings, the Calendar Store, runtime alert history, and the engine. A later
install restores the saved plugin entry, including settings changed while it
was enabled or disabled. uninstall removes only unchanged setup-owned
integration and the unchanged setup-owned engine; it does not delete Calendar
Store data or runtime.json. For a shell file with normal user edits, setup
replaces only the uniquely identified plugin/stock clock entry and preserves
its current settings, section/index, and unrelated bar edits. Use disable
when you want to keep those plugin settings for a future reinstall.
After explicit review/confirmation, shortcut rewrites only the managed Hypr
fragment. It accepts one normalized chord with one or more of SUPER, CTRL,
ALT, and SHIFT, plus one letter, digit, or F1–F12 key, then reloads
Hyprland and checks for configuration errors. Rejected or failed changes leave
the prior fragment and journal ownership intact.
Recovery and ownership safety
Shell layout ownership is structural: disable/uninstall require exactly one known plugin entry and no stock clock while enabled, or exactly one stock clock and no plugin while disabled. Normal plugin setting edits, entry moves, and unrelated bar edits are preserved. Duplicate, missing, or mixed clock entries are ambiguous and refuse the operation. Hypr include/fragment files, the opt-in URI desktop entry, and the engine use whole-file compare-and-swap ownership; setup refuses to restore those paths after edits rather than clobbering them. It also refuses symlinks, incomplete markers, and foreign or malformed journals.
Start with:
./setup doctor
If it reports edited or ambiguous state, preserve the diagnostic and review the
specific file and journal backup before making a manual choice. Do not delete
the journal or backup directory to force an uninstall. A transaction failure
attempts a compare-and-swap rollback; if rollback itself encounters an edit,
the journal is left for manual recovery and doctor remains non-mutating.