---
title: AI spend alerts (cost cards + the opt-in daily spend digest)
---

# AI spend alerts (cost cards + the opt-in daily spend digest)

## What it is

Omniscio watches your AI spend and surfaces it as **inbox cards** (not a top-of-window banner —
that's gone). There are two kinds:

1. **Always-on cost warnings** — cards that fire only when something looks off:
   - **"AI spend today is unusually high"** — your total spend for the day (across every AI
     feature) crossed a ceiling, OR is far above your own recent daily average. It shows a
     breakdown of **where the money went**, by feature (coding sessions, Inbox Pilot, Plain
     Speak, …) and by model (Opus / Sonnet / …). A genuine **runaway** (well above the
     ceiling) always breaks through, even if you've turned these alerts off — and on a runaway it
     ALSO fires a **desktop notification**, so you catch it even with the app minimized and no phone.
   - **"<Vendor> spend today is unusually high"** — your spend on a single metered
     vendor (Kimi/Moonshot, DeepSeek, GLM, MiniMax, Meta, and proxy-backed CrofAI) crossed a ceiling, OR is far above
     that vendor's own recent daily average. These vendors bill your **own** per-token key and
     aren't tied to an Omniscio account, so the "AI spend today" card can't see them — this is the one
     signal that a runaway on one vendor (the kind of fan-out that once ran up ~$220 of Kimi
     spend unnoticed) is happening. A genuine **runaway** always breaks through, even with alerts
     off. The card carries the daily-limit field itself, so you can set (or clear) that cap right
     there without leaving the inbox; its button still opens **Session settings → Spending limits**
     for the per-account and per-session caps it doesn't cover.
   - **"Voice transcription spend today is unusually high"** — your total paid speech-to-text
     spend for the day (voice dictation + meeting transcription, across Deepgram / ElevenLabs /
     Groq) crossed a budget ceiling ($10/day by default). STT spend is recorded under its own
     internal cost accounts that the "AI spend today" card never rolls up, so this is the one
     company-side signal that voice-transcription cost — which bills the shared built-in key
     when you haven't added your own — is running hot. It deep-links to **Voice settings** so
     you can add your own key.
   - **"Paying for AI suggestions you're not using"** — you've spent on AI reply-suggestions
     over a week but accepted none.
   - **"AI suggestions are costing more than usual"** — each accepted suggestion is averaging
     over ~$1.
   - **"Your automations are spending more than usual today"** — everything your **automations**
     spent on AI today (the actions plus the "should this rule fire?" checks) added up to more than
     **$8**. It's an early heads-up, not a stop: usually it means one automation is matching far more
     messages than you intended. This card appears **once** a day.
   - **"Automation spend is running away"** — the same total crossed **$32** (four times the warning
     line). Unlike the $8 card, this one comes **back** for each further $32 you spend that day, so a
     burn that keeps getting worse can't go quiet just because you dismissed the first card.
   - **"Omniscio has no price on file for a model"** — an AI model you used isn't in the price list,
     so its cost is being **estimated**. Your dashboard can drift from the real bill from that vendor
     until the model is added.
   - **"A spend record couldn't be saved"** — a cost entry failed to write to the local ledger.
     Nothing broke and nothing was double-charged, but your totals (and any spending cap that reads
     them) are **under-counting** until it clears.
   - **"You rarely use AI suggestions"** — over the past week AI reply-suggestions were shown to
     you plenty of times but you picked almost none (fewer than 1 in 20 of at least 40 shown), so
     — **regardless of how little they cost** — the card offers to turn them off. Unlike the two
     cost cards above, this one fires on the **pick-rate alone**. The "shown" count comes from
     suggestions actually **displayed on screen**, never the background prefetch (which warms
     sessions you may never open), so a busy fleet of sessions can't wrongly trigger it.

2. **The opt-in daily spend summary** (OFF by default) — once each morning, a card summarizing
   **yesterday's** AI spend: split into **real API spend (billed)** — from your own API key —
   versus **plan-included usage** (covered by a subscription login, shown as an estimated
   equivalent, not a real charge), then broken down **by provider** (Anthropic, Codex, and metered
   vendor models like Kimi/GLM/DeepSeek). It's silent on a $0 day and costs nothing to produce (a
   plain database rollup, no AI).

Every card carries the universal **Start session** + **Archive**, plus its own actions: the
warnings get **Open settings** and **Turn off these alerts**; the daily summary gets **View
spend dashboard** (jumps to Statistics → Usage → Spend).

## Where to find it

### How to use it

1. **See a card.** It appears in your **Inbox** like any other alert. Open it to read the
   breakdown.
2. **Turn the warnings off.** Click **Turn off these alerts** on any cost card, or use
   **Settings → Notifications → AI cost alerts**. That switch silences **every** tier,
   runaway included — it is the same control the card offers you, and a card that came back
   after you used it would be a broken button. A runaway still breaks through the
   once-a-day limit, so you get that one the moment it happens rather than the next day.
   - **"Allow agents to raise inbox alerts" does not silence them.** That switch only refuses
     cards that agents and plugins post from outside the app; these cards are the app's own.
3. **Opt into the daily summary.** **Settings → Notifications → Daily spend summary** (off by
   default). Turn it on to get the morning rollup.
4. **Dig deeper.** The daily card's **View spend dashboard** button (and the "where's my money
   going" view) live under **Statistics → Usage / Spend**.

## How it behaves

The cards arrive in your **Inbox** like any other alert, and each one can be opened to read its
breakdown. The always-on warnings are capped at once a day, but a genuine **runaway** breaks
through that cap and also fires a desktop notification, so real trouble reaches you immediately.
Both switches — **AI cost alerts** and the master **agent-alerts** switch — silence the
runaway too; turning the cards off is honored, never worked around. The opt-in daily summary is
silent on a $0 day.

## For agents

### Under the hood (for agents)

- **Producer:** the spend monitor (`src/main/services/suggestion-cost-monitor.ts`) ticks every
  30 min. It raises the five threshold cards via `createAlert` (through
  `services/notification/spend-alert-bodies.ts`), and — when the daily digest is enabled —
  raises the daily card once per local day after ~8am, summarizing yesterday. The STT card is
  `evaluateSttDailySpend()` — it sums today's `stt-*` cost sources (`STT_PAID_COST_SOURCES` in
  `voice/stt-cost.ts`, shared with the per-user `sttDailyCapUSD` cap) and fires above
  `AMC_STT_DAILY_SPEND_ALERT_USD` (default $10).
- **Metered-vendor card:** `evaluateMeteredVendorDailySpend()` iterates the **metered-vendor** set
  (`METERED_VENDOR_PROVIDER_IDS` — the anthropic-compat vendors **plus** proxy-backed CrofAI). That
  constant is MATERIALIZED from the registry predicate `isMeteredVendorKey`, never hand-listed, so a
  new metered vendor is picked up automatically — do not substitute `ANTHROPIC_COMPAT_PROVIDER_IDS`,
  which is a narrower set and would silently drop CrofAI. It reads each vendor's today + trailing-baseline
  session spend (`getTodayProviderSessionCost` / `getTrailingDailyAvgProviderSessionCost`, keyed on
  `sessions.provider` — these vendors carry `account_id = null`, so the account card can't see
  them). It raises a per-provider card + the same `account_spend_anomaly` metric across three tiers
  (runaway → bypasses the 24h cap / flat-ceiling / baseline-anomaly), INDEPENDENT of
  the opt-in `dailyMeteredCompatCapUSD`. The bar itself is yours to set — `meteredVendorSpendAlertUSD`
  (Settings → Session → Spending limits, or the field on the card), default $25 with the runaway tier
  at 4× it. Operator overrides: `AMC_METERED_VENDOR_DAILY_SPEND_ALERT_USD` / `_RUNAWAY_USD`, plus
  `AMC_SPEND_USUAL_ALERT_FACTOR` / `AMC_SPEND_USUAL_RUNAWAY_FACTOR`. See
  [api-key-spend-cap-contract.md](../../.claude/memory/contracts/api-key-spend-cap-contract.md)
  `a-metered-vendor-runaway-raises-an-alert`.
- **"Usual" is MEASURED, never assumed (2026-09-28).** The flat tiers are absolute dollars, so a
  user whose normal day already sits above one would be told "well above your usual" every single
  day — measured on the owner's box at 22 DeepSeek cards in 28 days, every one of them BELOW his
  real ~$186/day trailing average. So a FLAT tier (`flat-ceiling`, `runaway`, on BOTH the
  metered-vendor and the account ladder) must now also clear the user's own trailing daily average
  by `SPEND_USUAL_ALERT_FACTOR` (2) / `SPEND_USUAL_RUNAWAY_FACTOR` (4) — the guard is `aboveUsual`
  in `suggestion-cost-evaluators.ts`. With `usual <= 0` — no usable history, e.g. a vendor never
  used before — the guard passes and the flat ceiling is the whole net, so the ~$220 Kimi runaway is
  still caught exactly as before. The `baseline-anomaly` tier is the measured one and is unchanged.
  This is why a card can only ever claim a comparison the producer actually made.
- **Gating:** `shouldRaiseSpendAlert` (`src/shared/alert-features/spend-alert.ts`) folds the
  per-type `costAlertsEnabled` off-switch and a **once-per-day cap**
  (read back via `findLatestCreatedAtByDedupKey`) into one decision. A runaway passes
  `bypassGates` — it skips the **cap** only. An explicit `costAlertsEnabled: false` returns
  BEFORE the bypass, so the card's own "Turn off these alerts" button always works; the setting
  defaults ON, so the runaway net is intact for anyone who never touched it.
- **Runaway desktop notification (F016):** the account-wide and metered-vendor cards ALSO fire a
  desktop OS notification, but **only on the RUNAWAY tier** (via
  `notificationService.fireSystemNotification('spend-runaway', …)` in `spend-alert-bodies.ts`) and
  **only on first create** — matching the budget-cap / Kimi precedent so a minimized app with no
  paired phone still gets a desktop-level interrupt on the case that matters most, without a re-ticked
  monitor spamming toasts. Non-runaway tiers and the STT card (no runaway tier) stay inbox-row +
  mobile-push only. e2e/sandbox never fires (both `surface()` and `fireSystemNotification` gate
  `AMC_INSTANCE_ID`).
- **Breakdown data:** `getTodayAccountSpendBreakdown` (per-account, by feature + model) and
  `getDailySpendDigest` (billed vs plan-included via each account's `type: 'login'|'apikey'`,
  by provider) in `src/main/db/queries-spend-breakdown.ts` — fail-open money reads over
  `api_cost_log`. **F040:** the digest ALSO folds in metered-vendor session
  spend (kimi/glm/deepseek/minimax/meta + crofai) — those record only to `sessions.cost_usd`
  (account_id=null) and are NOT dual-written to `api_cost_log`, so a Kimi/Moonshot-heavy day used to
  show `$0`. The extra read is SCOPED by the registry predicate `isMeteredVendorKey` — the same
  derived set the detector uses, never a hand-listed one (so codex/pi dual-writers are
  never double-counted, central-ai-spend `no-double-count-engine-sources-excluded`) — and folds into `byProvider` + `total` via the
  un-attributable `other` bucket.
- **Low-usage-RATE card:** Rule 3 in `checkSuggestionCostEfficiency` fires **regardless of cost**
  when suggestions are shown enough but rarely picked — `offeredCount >= AMC_SUGGESTION_LOW_USAGE_MIN_OFFERED`
  (default 40) AND `acceptedCount / offeredCount < AMC_SUGGESTION_LOW_USAGE_RATE` (default 0.05).
  It runs AFTER the two spend-gated suggestion rules (so a money card wins the tick), catching the
  cheap-but-ignored case they miss. Crucially, `offeredCount` is a **genuinely-displayed** count:
  `getSuggestionCostEfficiency` counts `feature_events` rows with `action = 'shown'` (fired on-device
  by the composer chip bar in `AiSuggestionChips.tsx`, deduped per session+batch), NOT `api_cost_log`
  — whose suggestion rows the background prefetcher inflates with sessions the user never opens, which
  would make a busy fleet's pick-rate read as near-zero and wrongly nag.
- **dedupKeys + predicates:** `src/shared/alert-features/spend-alert.ts` (`account-daily-spend-high`,
  `stt-daily-spend-high`, `suggestion-zero-usage`, `suggestion-high-cost-per-use`,
  `suggestion-low-usage-rate`, `metered-vendor-spend:<provider>`, `daily-spend-digest:<date>`).
  `isSpendAlertDedupKey` matches the metered-vendor key by prefix, so the shared mute covers it too.
- **Card actions:** `src/shared/alert-primary-actions.ts` — the six warnings deep-link to
  Settings (the STT card to Voice settings, the metered-vendor card to Session settings, the three
  suggestion cards to suggestion settings, the account card to Accounts); the daily card uses the
  in-app-nav `spend-dashboard` action
  kind (like `records`). The "Turn off these alerts" mute is a hand-wired button in
  `AlertInboxViewer.tsx` keyed on `isSpendAlertDedupKey`.
- **Settings:** `costAlertsEnabled` (default on) + `dailySpendDigestEnabled` (default off) in
  `src/shared/types/settings/notifications-settings.ts`.
- Contract: [inbox-alert-contract.md](../../.claude/memory/contracts/inbox-alert-contract.md) +
  [api-key-spend-cap-contract.md](../../.claude/memory/contracts/api-key-spend-cap-contract.md)
  (V1 — the metered-vendor anomaly detector).

## Related

Broader cost controls live in [cost-control.md](cost-control.md), and
[daily-spend-report.md](daily-spend-report.md) is the scheduled spend report rather than an inbox
card. The figures behind every card come from the same ledger that [stats.md](stats.md) renders, and
[usage-forecast.md](usage-forecast.md) projects where that usage is heading. For tuning which alert
cards reach you at all, see [inbox-alerts.md](inbox-alerts.md), and
[kimi-balance-monitor.md](kimi-balance-monitor.md) watches one of the metered vendors named above.
