Notifications & “normal for me”
Anomalous notifies sparingly, only for confirmed high-confidence anomalies, and learns when you say “this is normal for me” so it stops telling you twice.
Notification discipline
Anomalous notifies you rarely, and only when it has something worth your attention. A notification means one thing: a confirmed, high-confidence anomaly that your Mac decided you should know about now. Lower-confidence quiet findings never notify. They are still recorded and visible in the app, but they do not interrupt you. Silence is the point of this product, so a banner from Anomalous carries weight.
The app also never asks for notification permission at launch. It asks the first time it actually has an anomaly worth surfacing, so the permission prompt arrives with a reason attached rather than as a cold request during setup.
Under the hood
Medium and low quiet findings are filtered out before the notification path is ever reached (NotificationManager.swift:10-12). Only surfaced high-confidence anomalies call into NotificationManager, which requests authorization lazily at the first real anomaly (NotificationManager.swift:53-112). Bursts and restarts from one program collapse into a single thread, keyed by process lineage (bundle ID or executable name) rather than pid, so a repeatedly-restarting runaway coalesces into one summary instead of stacking dozens of banners (NotificationManager.swift:70-72).
Time-sensitive alerts
When Anomalous does notify, it does so as a time-sensitive alert with no sound. Time-sensitive means the notification can reach you through a Focus mode, because a confirmed anomaly is the kind of thing you would want to see even while you are heads-down. No sound means it never makes noise to do it. It is presence, not a chime.
Every notification carries the same actions as the in-app card: Investigate, Snooze 1 hour, and Normal for me. You can act on it without opening the app. The same controls are also available from a widget tile and from Siri and Shortcuts.
Under the hood
Interruption level is set to .timeSensitive with sound = nil (NotificationManager.swift:53-112). Piercing Focus depends on the com.apple.developer.usernotifications.time-sensitive entitlement on the app; without it, alerts fall back to the normal interruption level rather than reaching through Focus (NotificationManager.swift:12-13). The notification action buttons call the same acknowledgment paths as the card buttons, so behavior is identical wherever you tap (AppState.swift:454-460).
“Normal for me” — teaching the baseline
When a flagged behavior is fine by you — a video encoder that pins the CPU, a backup tool that hammers the disk — you tap Normal for me. This does not silence the program forever. It teaches Anomalous your baseline for that one behavior: it records roughly how intense the behavior was at that moment and sets an acceptance envelope around it. As long as the program stays inside that envelope, Anomalous stays quiet and keeps the observation on file. The nagging stops because you taught it what normal looks like for you, not because you muted it.
This is scoped to one thing: this program, this kind of anomaly, this driving metric. A brand-new kind of misbehavior from the same program is a different condition, so it surfaces normally rather than hiding under your earlier answer.
Under the hood
Acknowledging stores an envelope of acknowledged magnitude × multiplier with no expiry (AcknowledgmentStore.swift:181-196). The slack depends on an intent heuristic: a foreground, user-installed (non-Apple, non-root) app gets 2.0× its acknowledged level; a background or root process gets 1.5×, because a user-launched app working hard is categorically different from a silent daemon doing the same (AcknowledgmentStore.swift:90-108). Identity is the condition key — process lineage plus anomaly kind plus driving-metric dimension, never the pid — so a new kind of problem is a new key (AcknowledgmentStore.swift:156). Everything persists to a local JSON file (Application Support/Anomalous/acknowledgments.json); nothing about your acknowledgments is sent off-device.
Snooze vs acknowledge
There are three ways to push back, and they mean different things.
- Normal for me sets a lasting envelope for one behavior. Use it when a flagged behavior is genuinely fine.
- Snooze (Snooze 1 hour, or until end of day) defers one specific anomaly briefly. It re-surfaces when the snooze expires if the behavior is still active, or immediately if it gets materially worse in the meantime.
- Snooze Alerts is global. It stops notifications for a while, but detection keeps running — cards still appear in the app. Snoozing alerts silences the banners, it does not stop watching.
Under the hood
A snooze is the same envelope as an acknowledgment but with a snoozeUntil date; it re-surfaces on expiry or on materially-worse escalation (AcknowledgmentStore.swift:200). Global snooze sets alertsSnoozedUntil, which suppresses the notification path while detection continues (AppState.swift:1428-1440). The re-alert markers shown to you are plain strings, e.g. Returned, worse than acknowledged and Returned after snooze (AppState.swift:1347-1353).
The anti-mute safeguard
None of these controls is a permanent mute, and that is a deliberate design promise Anomalous calls the anti-mute guarantee. Whatever you accept, Anomalous will come back and tell you why if the situation changes. An acknowledged behavior returns when any of four things happen: it gets materially worse than what you accepted, the program quits and restarts as a fresh instance, a timed snooze runs out while the problem is still happening, or the program does a new kind of misbehavior. When it returns, the alert says the reason up front, such as “Returned, worse than acknowledged.”
Once a re-alert fires, that acknowledgment is spent. A dismissed “it’s back and worse” card can never bounce straight back into silence — the exact mute the design forbids.
Under the hood
The re-alert decision is a pure function returning realert when magnitude exceeds acknowledged × multiplier, when the process restarted (a different startAbsTime, so a restart is caught structurally rather than by pid reuse), or when the snooze expired; otherwise suppress; and notAcknowledged when there is no record (AcknowledgmentStore.swift:239-257). decide() deletes the record whenever it re-alerts, so a fired re-alert cannot suppress again (AcknowledgmentStore.swift:262-279).
The same discipline extends to the widget and Shortcuts. Because the widget runs in a separate sandboxed process, its buttons drop signed command messages into a shared container that the app reads and applies. Commands carry an HMAC-SHA256 MAC over a canonical field list plus a per-command nonce; the app verifies the MAC, rejects replayed nonces, and clamps any snooze to 86400 seconds (one day) before executing (AppState.swift:1485-1520, AcknowledgmentStore.swift:510-565). The shared key is a per-install secret in a team-scoped Keychain access group readable only by co-signed Anomalous processes (AcknowledgmentStore.swift:613-663). On an unsigned or improperly-entitled build the key read fails and the app fails closed, dropping all widget commands. This means malware on the same machine cannot forge a command to disable monitoring or mute alerts for a century.
Optional passive resolution notes (“Filed in the journal”) are off by default. If you want to see how these behaviors are inspected once you tap Investigate, see Judgment. The sensor is open source at anomalous-mac, and the public data corpus at anomalous-corpus welcomes PRs.