---
title: RSS feed integration (read RSS/Atom feeds in your inbox)
---

# RSS feed integration (read RSS/Atom feeds in your inbox)

## What it is

Omniscio's RSS integration polls a list of RSS/Atom feed URLs you configure and surfaces each new entry as its own row in the unified inbox — alongside Gmail, SMS, Slack, Telegram, and webhooks. Each entry shows the title, source feed name, author, and a sanitized preview; click in to read the full entry's HTML. This is a **read-only** channel — there's no replying or "send" path. The use case is collapsing "things I want to read or react to" into one inbox so you can mark items read, snooze them for later, archive them, or feed them into automations and the daily digest.

On top of the raw entries, the integration produces an **AI-curated daily digest** that compresses the day's feed activity into a single inbox row — handy when you subscribe to enough feeds that the firehose gets noisy.

## Where to find it

### How to use it

1. **Enable RSS.** Settings → **RSS** → toggle `rssEnabled` on.
2. **Add feeds.** In the same panel, paste a feed URL (e.g., `https://news.ycombinator.com/rss`, your favorite blog's `/feed`, a YouTube channel's `/videos.xml`). Omniscio validates the URL — feeds pointing at private IP ranges, localhost, or non-HTTP(S) protocols are refused (SSRF protection).
3. **Triage the inbox.** Each new entry shows up as a row tagged with the feed name. Click to read the entry's content (HTML stripped to plain text in the preview, full HTML in the detail view). Mark it read, archive it, or snooze it like any other inbox row.
4. **(Optional) Enable Daily Digest.** Toggle `rssDigestEnabled` in the same settings panel to get a once-a-day AI briefing. Configure `rssDigestTime` (delivery time, default `07:00`) and `rssDigestInterests` (free-form interest keywords) to steer prioritisation. **Generate Now** produces a digest on-demand; the **Recent Digests** collapsible lists the last 10 with read/unread status.
5. **Pair with automations.** RSS entries flow through the standard Automation engine — keyword-match the title/body to forward via email, summarize in the daily digest, or trigger a Claude session to react.

## How it behaves

### Two inbox sources

The integration registers **two** distinct inbox source ids — both gated behind `rssEnabled`:

- `rss` — one row per raw feed entry. Filterable independently in the inbox source dropdown so you can keep the firehose collapsed.
- `rss-digest` — one row per generated daily digest. Added 2026-05-14 alongside the **Recent Digests** sidebar section in RSS Feeds settings; clicking a digest row opens the dedicated `RssDigestView`.

Both surface through the same registry entry in [/src/shared/integration-registry.ts](/src/shared/integration-registry.ts) (see the `inboxSourceIds: ['rss', 'rss-digest']` declaration); the contract test in [/tests/unit/lint/integration-completeness.test.ts](/tests/unit/lint/integration-completeness.test.ts) enforces both being wired through `INBOX_SOURCE_INTEGRATIONS` and `INBOX_ALLOWED_CHANNELS`. The pattern mirrors how the daily-digest integration owns both `daily-digest` and `weekly-summary` sub-sources under a single feature-flag.

## For agents

### How it works

The fetcher is [/src/main/services/rss-service.ts](/src/main/services/rss-service.ts) — wraps the `rss-parser` npm library with a 15-second timeout per feed, a custom `User-Agent`, and explicit `Accept` headers covering RSS, Atom, and generic XML. SSRF protection lives in `isPrivateOrLocalUrl()`, defined in [/src/main/services/redirect-aware-fetch.ts](/src/main/services/redirect-aware-fetch.ts) and re-exported from `rss-service.ts` (so callers can keep importing from either): blocks localhost variations, RFC 1918 private IPv4 ranges, link-local (169.254/16, including AWS metadata 169.254.169.254), IPv6 loopback/private, and any non-HTTP(S) protocol — all enforced before the HTTP request fires. The redirect-aware fetcher also re-validates every redirect target against the same predicate so a public URL cannot bounce a request into private space. Polling and persistence live in [/src/main/db/queries-rss.ts](/src/main/db/queries-rss.ts) and the channel adapter [/src/main/services/channels/rss-adapter.ts](/src/main/services/channels/rss-adapter.ts), which maps each `RssEntryRow` into a `UnifiedConversation` (one entry = one conversation) with `participants: [{ id: author }]` and `lastMessage` carrying the body preview. The adapter declares `canSend: false` so reply UI is hidden everywhere RSS rows appear. Settings flags: `rssEnabled`, `rssDigestEnabled`, `rssDigestTime`, `rssDigestInterests`, `rssRetentionDays` in [/src/shared/types.ts](/src/shared/types.ts). Digest generation lives in [/src/main/services/rss-digest-service.ts](/src/main/services/rss-digest-service.ts) — runs on the cron set by `rssDigestTime`, calls Claude with the interests prompt, and persists results to `rss_digests`, including the per-call curation + summary spend (`curationCostUsd` / `summaryCostUsd`, priced via the same `calculateAnthropicCostUsd` the central ledger uses) that the digest view surfaces. The real spend is also captured centrally in `api_cost_log`; these two columns are the per-digest display copy. Search integration: RSS entries are indexed alongside other channels — `SearchChannelType` in `types.ts` includes `'rss'`.

## Related

- [INDEX.md](INDEX.md) — full library index
- [webhook-integration.md](webhook-integration.md) — sibling read-only channel for HTTP push events
- [automations-and-auto-replies.md](automations-and-auto-replies.md) — keyword rules that route RSS entries
- [daily-digest.md](daily-digest.md) — separate cross-app briefing (emails + calendar + sessions); the RSS digest is a feed-only sibling
- [global-search.md](global-search.md) — Ctrl+K searches RSS entries alongside every other channel
