全文搜索依赖 Meilisearch,AI 功能需自备 Anthropic/Gemini/OpenAI 的 API Key;生产 compose 默认带 cloudflared 边车走 Cloudflare Tunnel,不用隧道需自行调整;CSS 选择器订阅和反爬需额外部署 RSS Bridge 与 FlareSolverr 容器

docker compose -f compose.yaml -f compose.prod.yaml up --build -dREADME 未说明具体硬件要求;架构上需本地磁盘存 SQLite,且需常驻进程跑定时抓取,因此不支持 serverless/edge 运行时
AI 原生 RSS 阅读器,自动抓取每篇文章全文并本地存储,让摘要、翻译和搜索都基于完整内容
一款 AI 原生的自托管 RSS 阅读器,用大模型帮你筛选和总结订阅内容,解决信息过载、看不过来的问题。
核心能力
- 用 Readability 加 500 条去噪规则自动提取全文并转 Markdown
- 调用 Anthropic、Gemini 或 OpenAI 做流式摘要与翻译
- 基于 Meilisearch 对全部文章做全文搜索
- 支持多轮 AI 对话,通过 MCP 工具检索文章和统计
- 按 feed 自适应调度抓取,带 ETag 条件请求与内容去重
容易踩的坑
- v0.5.0最新正式版2026-06-08 · 2026-06-08 04:58 UTC
What's Changed
New Features
- feat: add support for vLLM LLM provider by @pju-hoge in https://github.com/babarot/oksskolten/pull/56
Bug fixes
- Update feed items with excerpt by @asonas in https://github.com/babarot/oksskolten/pull/51
- fix: add type="button" to cancel button in FolderStep by @tenajima in https://github.com/babarot/oksskolten/pull/66
- Fix article lists not refreshing after bookmark/like toggle by @babarot in https://github.com/babarot/oksskolten/pull/76
- fix(fetcher): relax worker memory limit and clean up timeout aborts by @babarot in https://github.com/babarot/oksskolten/pull/81
Improvements
- Add fallback mechanism for RSS description as article content by @asonas in https://github.com/babarot/oksskolten/pull/46
- feat(chat): increase tool round limit and add batch tools by @pju-hoge in https://github.com/babarot/oksskolten/pull/61
- Replace skip checkbox with two-phase choice flow for feed scope by @babarot in https://github.com/babarot/oksskolten/pull/54
- feat: implement zap keyboard navigation in article view and fix settings sync race condition by @pju-hoge in https://github.com/babarot/oksskolten/pull/68
- fix: address production memory instability — tsx→node, worker idleTimeout, SQLite soft_heap_limit by @pju-hoge in https://github.com/babarot/oksskolten/pull/78
Others
- Refresh cloud LLM model list to latest releases by @babarot in https://github.com/babarot/oksskolten/pull/77
- Add new font option with "System Serif" by @pellaeon in https://github.com/babarot/oksskolten/pull/65
- refine(fonts): use curated stack for System Serif by @babarot in https://github.com/babarot/oksskolten/pull/80
- fix(search): raise Meilisearch waitTask timeout to 5 minutes by @babarot in https://github.com/babarot/oksskolten/pull/82
New Contributors
- @pju-hoge made their first contribution in https://github.com/babarot/oksskolten/pull/56
- @tenajima made their first contribution in https://github.com/babarot/oksskolten/pull/66
- @pellaeon made their first contribution in https://github.com/babarot/oksskolten/pull/65
Full Changelog: https://github.com/babarot/oksskolten/compare/v0.4.2...v0.5.0
- v0.4.22026-03-26 · 2026-03-26 05:48 UTC
查看更新说明
What's Changed
Improvements
- Add support for custom key bindings in settings by @asonas in https://github.com/babarot/oksskolten/pull/37
- Refactor
safeFetchto exclude certain HTTP status codes as redirects by @asonas in https://github.com/babarot/oksskolten/pull/42 - Update keyboard navigation to include prefetching on near-end items by @asonas in https://github.com/babarot/oksskolten/pull/43
- Expose article original URL as data-original-url attribute on all car… by @asonas in https://github.com/babarot/oksskolten/pull/44
Full Changelog: https://github.com/babarot/oksskolten/compare/v0.4.1...v0.4.2
- v0.4.12026-03-23 · 2026-03-23 23:23 UTC
查看更新说明
What's Changed
Bug fixes
- Fix multibyte URL lookup returning 404 by @babarot in https://github.com/babarot/oksskolten/pull/31
Full Changelog: https://github.com/babarot/oksskolten/compare/v0.4.0...v0.4.1
- v0.4.02026-03-20 · 2026-03-20 14:41 UTC
查看更新说明
What's Changed
New Features
- Add Ollama as a self-hosted LLM provider by @asonas in https://github.com/babarot/oksskolten/pull/25
- Add retention policy with configurable article cleanup by @babarot in https://github.com/babarot/oksskolten/pull/24
Bug fixes
- Fix mojibake on non-UTF-8 articles and feeds by @Just2enough in https://github.com/babarot/oksskolten/pull/23
Improvements
- Perf/score recalc daily batch by @asonas in https://github.com/babarot/oksskolten/pull/19
- Update article excerpt generation to strip Markdown syntax by @asonas in https://github.com/babarot/oksskolten/pull/21
- Improve decodeResponse portability and test coverage by @babarot in https://github.com/babarot/oksskolten/pull/26
New Contributors
- @Just2enough made their first contribution in https://github.com/babarot/oksskolten/pull/23
Full Changelog: https://github.com/babarot/oksskolten/compare/v0.3.0...v0.4.0
- v0.3.02026-03-19 · 2026-03-19 12:12 UTC
查看更新说明
What's Changed
New Features
- Feature/keyboard navigation by @asonas in https://github.com/babarot/oksskolten/pull/12
Bug fixes
- Feature/retry backoff by @asonas in https://github.com/babarot/oksskolten/pull/18
Others
- Reject http:// URLs in feed and clip endpoints by @babarot in https://github.com/babarot/oksskolten/pull/15
- Add mocks for unused components and hooks in
article-list.test.tsxby @asonas in https://github.com/babarot/oksskolten/pull/16
Full Changelog: https://github.com/babarot/oksskolten/compare/v0.2.0...v0.3.0
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Why Oksskolten?
Most RSS readers show what the feed gives you — a title and maybe a summary. Some (like Miniflux and FreshRSS) can fetch full article text, but it's opt-in per feed and requires configuration. Oksskolten does it for every article automatically: it fetches the original article, extracts the full text using Mozilla's Readability + 500 noise-removal patterns, converts it to clean Markdown, and stores it locally. No per-feed toggles, no manual CSS selectors — it just works.
Because Oksskolten always has the complete text, AI summarization and translation produce meaningful results, full-text search actually covers everything, and you never need to leave the app to read an article.
See it in action
🕺 Live Demo → demo.oksskolten.com
Features
- Full-Text Extraction — Every article is fetched from its source and processed through Readability + 500 noise-removal patterns. You read complete articles inside Oksskolten, never needing to click through to the original site
- AI Summarization & Translation — On-demand article processing via Anthropic, Gemini, or OpenAI with SSE streaming. Works on full article text, not RSS excerpts
- Interactive Chat — Multi-turn AI conversations with MCP tooling; search articles, get stats, and ask questions about your feeds
- Full-Text Search — Meilisearch-powered search across your entire article archive
- Smart Fetching — Adaptive per-feed scheduling, conditional HTTP requests (ETag/Last-Modified), content-hash deduplication, exponential backoff, and tracking parameter removal
- PWA — Offline reading, background sync, and add-to-home-screen support
- Multi-Auth — Password, Passkey (WebAuthn), and GitHub OAuth — each independently configurable
- Smart Feed Management — Auto-discovery, CSS selector-based feeds (via RSS Bridge), bot bypass (FlareSolverr), and automatic disabling of dead feeds
- Article Clipping — Save any URL as an article, with full content extraction
- Theming — 14 built-in color themes + custom theme import via JSON, 9 article fonts, 8 code highlighting styles
- Single Container — API, SPA, and cron scheduler all run in one Docker container
Tech Stack
| Layer | Technology |
|---|---|
| Backend | Node.js 22 + Fastify |
| Frontend | React 19 + Vite + Tailwind CSS + shadcn/ui |
| Database | SQLite via libsql (WAL mode) |
| AI | Anthropic / Gemini / OpenAI |
| Search | Meilisearch |
| Auth | JWT + Passkey / WebAuthn + GitHub OAuth |
| Deployment | Docker Compose + Cloudflare Tunnel |
Architecture
graph TD
subgraph host["Docker Host"]
subgraph app["oksskolten (Node.js 22, port 3000)"]
fastify["Fastify API<br/>/api/*"]
spa["SPA static serving<br/>(Vite build)"]
sqlite["SQLite<br/>(WAL mode)"]
cron["node-cron<br/>Feed fetch every 5 min"]
fetcher["Fetcher Pipeline<br/>RSS parse → Readability<br/>→ HTML cleaner → Markdown"]
ai["AI Provider<br/>Anthropic / Gemini / OpenAI"]
chat["Chat Service<br/>MCP Server + 4 Adapters"]
fastify --> sqlite
fastify --- spa
fastify --> fetcher
fastify --> ai
fastify --> chat
cron --> fetcher
fetcher --> sqlite
chat --> sqlite
chat --> ai
end
bridge["RSS Bridge<br/>(Docker, port 80)"]
flare["FlareSolverr<br/>(Docker, port 8191)"]
tunnel["cloudflared<br/>(Cloudflare Tunnel)"]
end
user(("User")) -- "HTTPS" --> tunnel
tunnel --> fastify
cron -- "HTTP fetch" --> rss(("RSS Feeds"))
fetcher --> bridge
fetcher --> flare
ai -- "API" --> llm_api(("Anthropic / Gemini<br/>/ OpenAI API"))
Everything runs in a single long-lived process — SQLite needs local disk, and node-cron needs a process that stays alive. This rules out serverless/edge runtimes but keeps the stack simple: one container, no external queues or coordination. For cloud deployment, a small VM or Fly.io + Turso works well.
Oksskolten also exposes an MCP server, so Claude Code or any MCP client can search, summarize, and query your article archive without opening the app.
What's in a name? Oksskolten is the highest peak in northern Norway — a mountain of knowledge for your feeds.
Content Pipeline
Unlike traditional RSS readers that rely on feed-provided summaries, Oksskolten fetches every article directly from its source URL and extracts the full text. This means the reader is self-contained — no need to leave the app to read an article.
- Fetch RSS — Adaptive per-feed scheduling with conditional requests (ETag/Last-Modified/content hash)
- Parse — RSS/Atom/RDF parsed via feedsmith + fast-xml-parser, tracking parameters stripped
- Fetch Article — Original article URL fetched directly (with FlareSolverr fallback for bot-protected sites)
- Extract — Full article content extracted with Readability in isolated Worker Threads
- Clean — ~500 noise-removal patterns strip ads, nav, sidebars, and tracking elements
- Convert — HTML converted to Markdown with GFM support
- Enrich — Language detection, OGP image extraction, excerpt generation
- Index — Articles indexed in Meilisearch for full-text search
Smart Fetching
The feed fetcher minimizes bandwidth and adapts to each feed's behavior, inspired by best practices from FreshRSS, Miniflux, and CommaFeed:
- 3-layer change detection — HTTP 304 (ETag/Last-Modified) → content hash (SHA-256) → full parse. Unchanged feeds are caught early without parsing XML
- Adaptive scheduling — Each feed gets its own check interval (15min–4h) based on three signals: HTTP
Cache-Control, RSS<ttl>, and actual article frequency. Active blogs are checked often; dormant ones back off automatically - Resilient error handling — Exponential backoff on errors (1h–4h cap), but feeds are never disabled. Rate limits (429/503) respect
Retry-Afterheaders without counting as errors - URL deduplication — 60+ tracking parameters (utm_*, fbclid, gclid, etc.) are stripped before duplicate checking, preventing the same article from being inserted twice
Comparison
| Oksskolten | Miniflux | FreshRSS | Feedly | |
|---|---|---|---|---|
| Full-text extraction | Every article, by default | Opt-in per feed | Opt-in per feed | Auto (best-effort) |
| Extraction engine | Readability.js + 500 patterns | Go Readability (~390 lines, ~60 rules) | Manual CSS selectors | Proprietary |
| JS-rendered sites | FlareSolverr | — | — | Enterprise only |
| Sites without RSS | Auto-discovery → RSS Bridge → LLM inference | — | — | Pro+ (25) / Enterprise (100) |
| AI summarization | Built-in (Anthropic/Gemini/OpenAI) | — | — | Pro+ only (Leo) |
| AI translation | Built-in (+ Google Translate, DeepL) | — | — | Enterprise only |
| AI chat | MCP-powered, searches archive | — | — | — |
| Search | Meilisearch (typo-tolerant) | PostgreSQL full-text | SQL LIKE | Pro+ (Power Search) |
| Database | SQLite (embedded, WAL) | PostgreSQL (external) | MySQL/PG/SQLite | SaaS |
| Deployment | Single container | Binary + PostgreSQL | PHP + web server + DB | SaaS |
| Offline reading | PWA with background sync | — | — | Mobile apps only |
| Auth | Password + Passkey/WebAuthn + GitHub OAuth | Password + API key | Password + API key | Google/Apple/social + SAML (Enterprise) |
| Themes | 14 + custom JSON import | Light/Dark | ~10 themes | — |
| Language | Node.js (TypeScript) | Go | PHP | — |
| Price | Free / OSS (AGPL-3.0) | Free / OSS (Apache-2.0) | Free / OSS (AGPL-3.0) | $12.99/mo (Pro+) |
Miniflux and FreshRSS are excellent, mature projects. Oksskolten's focus is different: full-text extraction and AI as first-class defaults, not optional add-ons.
Development
docker compose up --build # HMR enabled
# Frontend: http://localhost:5173
# Backend: http://localhost:3000
npm test # Run all tests
npm run build # Production build
On first startup with an empty database, sample feeds and articles are automatically loaded from the demo seed data (src/lib/demo/seed/*.json). This gives you a populated UI to work with immediately. The seed is idempotent — it only runs when no RSS feeds exist in the database. To start with an empty database instead, set NO_SEED=1.
See .env.example for available environment variables. AI provider keys are configured through the Settings UI.
Deployment
Runs anywhere Docker runs — a home NAS, a Raspberry Pi, or a cloud VM.
Using pre-built images
Pre-built multi-architecture Docker images (amd64/arm64) are published to GHCR on every release:
docker pull ghcr.io/babarot/oksskolten:latest
To use the pre-built image instead of building locally, edit compose.prod.yaml and swap the build directive for the commented-out image line, then:
docker compose -f compose.yaml -f compose.prod.yaml up -d
Building locally
# Production with Cloudflare Tunnel
docker compose -f compose.yaml -f compose.prod.yaml up --build -d
The production compose file includes a cloudflared sidecar that exposes the app via Cloudflare Tunnel — no port forwarding or static IP required.