Repository navigation
Troubleshooting
Every dismissed alert panel stayed alive hidden and kept redrawing, so CPU use grew with each alert until the app was restarted. Fixed in newer releases: upgrade, or quit and reopen MeetAlert to clear it.
Those two releases did nothing when built with the macOS 27 SDK (the menu and Settings were bound to
a different, unstarted store), and touching Settings could reset config.json to defaults. Upgrade to
the latest release, then re-check your ntfyTopic and calendar selection.
Work through these in order:
-
Is the calendar it's on actually enabled? Menu bar icon → Settings… → Calendars
— an unticked calendar is completely invisible to MeetAlert (
calendarIdsexcludes it from the EventKit query, not just from the UI). If you've unticked every calendar, that's respected as deliberate — the menu bar says "no calendars selected" and nothing fires, on purpose. That's different from a stale selection (e.g. after re-adding an account, whose calendar identifiers changed): MeetAlert detects when a saved selection matches zero real calendars and falls back to watching everything with a ⚠︎ warning, rather than going quietly dead — if you're seeing that warning, re-open Settings → Calendars and re-tick what you want. -
Is it within an alert window? Each entry in
alertMinutesBefore(plus atravelLeadMinuteswindow if the meeting has a physical location) opens its own window, from that offset untillateAlertMinutesafter it. A meeting 2 hours out won't alert yet; with the defaultalertMinutesBefore: [3, 0]andlateAlertMinutes: 10, one that started more than 10 minutes ago never will. -
Sync lag. If the event is genuinely new (just accepted an invite, calendar just synced),
macOS's own calendar cache might not have it yet — MeetAlert only sees what EventKit already
has. Open Calendar.app → Settings → General and set "Refresh calendars" to Every
minute.
lateAlertMinutesexists specifically to cushion whatever lag remains after that. -
Keyword filter. Check
ignoreKeywords(Settings → Ignore) — a title containing any of those substrings is silently skipped. -
Already ignored. Check Settings → Ignore — the "Currently ignored" list shows every
ignored occurrence and series with a one-click remove. (Under the hood:
state.json'signoredKeys/ignoredSeriesIds.) -
All-day.
ignoreAllDaydefaults totrue. - Declined. If you (the current user) declined the invite, it's always skipped — there's no setting to change this.
Expected, not a bug: MeetAlert treats you as "away" — idle past awayIdleSeconds (default 120s),
or your screen is locked — and skips the normal high-priority grace window for the first push
when that's the case. If this fires too eagerly, raise awayIdleSeconds in Settings.
Escalation stopped after escalationRepeats pushes / stopped once the meeting was 15 minutes old / never escalated at all
Also expected. Escalation repeats at most escalationRepeats times (3 by default), and never continues past 15 minutes after the
meeting's start time, regardless of escalationSeconds. Both bounds are fixed, not configurable.
If an alert itself first fired later than that 15-minute mark (e.g. a very late offset, or a
missed alert caught up via lateAlertMinutes), there's no escalation window left at all by the
time it fires — you'll get exactly one push and no re-pushes, which is correct, not a bug.
Check your server's cache-duration setting. MeetAlert detects an ACK/snooze by polling the
topic's message history — if your self-hosted server has caching disabled
(cache-duration: 0), there's no history for it to poll, so your reply is invisible to MeetAlert
even though ntfy delivered it to your phone fine. Turn message caching back on (it's the default);
see ntfy Setup. Public ntfy.sh isn't affected — it caches by default.
- Check
agendaTime(Settings → Phone → "Send morning agenda") — it defaults off (null). - It's skipped entirely under
MEETALERT_TEST=1. - The agenda push only fires once its hour has passed for the day (
Calendar.current's local hour) and only once per calendar day — checkstate.json'slastAgendaDay; if it already matches today, it already fired (or there were no meetings left to summarize) and won't again until tomorrow.
Expected. Dismissing/ACKing (or Joining from) any of a meeting's alerts marks that whole
occurrence done — every remaining offset is suppressed and pending snoozes are dropped
(alertedKeys gets a ...@dismissed key). Use Snooze instead of Dismiss if you want the
alert back later.
If the calendar icon isn't showing up at all, a menu-bar-management app (Bartender, Ice, the
built-in "menu bar spacer" in newer macOS, etc.) may be hiding it rather than MeetAlert failing
to launch. Check that tool's hidden-items list, or hold ⌘ and drag in the menu bar area to
reveal hidden icons. If it's not there even after that, check Activity Monitor for a running
MeetAlert process — if there isn't one, relaunch from /Applications or your build folder.
Expected. build.sh re-signs the app ad-hoc on every run, and macOS ties the TCC (privacy)
grant to that signature — a new signature looks like a new app to Gatekeeper/TCC. This only
matters for building from source; a Homebrew install doesn't rebuild locally so it won't churn
the signature.
You have the ntfy app's Settings → Notifications → "Keep alerting for highest priority" turned on. Turn it off — it has to be the global toggle, because a per-topic "Alert only once" does not override the global setting.
ACK is working: it reached MeetAlert, escalation stopped, and the notification was cleared and
marked read. What didn't stop is ntfy's insistent alarm, which is a single looping MediaPlayer
that only the notification's delete intent (a swipe) or opening the topic screen ever stops. An
action button with clear: true cancels the notification programmatically, which never fires that
delete intent — so the ring outlives the notification. Filed upstream as
ntfy-android#189; see
ntfy Setup for the full explanation.
Until you turn it off, the only way out is tap ACK, then swipe the notification away (or open the topic). Swiping alone doesn't ack — ntfy has no dismiss callback, so MeetAlert never hears it and the next re-push restarts the ring.
Once it's off, get the persistence back from MeetAlert instead: set escalationSeconds to 45
and escalationRepeats to 8 (about six minutes of pings, each one silenceable, all of them
ended by a single ACK).
This is almost always an OS-level notification setting, not a MeetAlert problem — MeetAlert only controls the priority header it sends; whether that priority actually breaks through silence is entirely up to the ntfy app and the phone's own settings. See the ntfy Setup page for the exact Android channel setting and the (currently limited) iOS story. Short version: Android needs a per-channel "Override Do Not Disturb" toggle set manually; iOS Focus-mode bypass isn't fully supported by ntfy's iOS app yet, so treat the desktop popup as your real backstop there.
MeetAlert releases are self-signed with a stable identity, so permissions survive updates (not notarized, so first launch still needs Open Anyway) — macOS's Gatekeeper doesn't recognize the signer. Open System Settings → Privacy & Security and click Open Anyway next to MeetAlert (right-click → Open no longer works on macOS 15+), or clear the quarantine flag once:
xattr -dr com.apple.quarantine /Applications/MeetAlert.appIf you built from source yourself, this can recur on every rebuild since the ad-hoc signature
changes each time ./build.sh runs.
MeetAlert · MIT © Roy Padina · More Mac apps · Support on Ko-fi ☕