A modern RSS reader that is actually fast and actually small.
An installer under 5 MB that opens in under a second and holds 20,000 articles in a 14 MB core process. Rust core, React shell, built with Tauri 2.
By t21 dev and TriptoAfsin
Download from the latest release.
| Platform | File |
|---|---|
| Windows | _x64-setup.exe or .msi, or _x64_portable.zip to run without installing |
| macOS | _aarch64.dmg for Apple silicon, _x64.dmg for Intel |
| Linux | .AppImage, .deb, .rpm or .flatpak |
Flatpak on Linux. Install the bundle with
flatpak install --user Turbo.Reader_*_x86_64.flatpak. It needs the GNOME 51
runtime from Flathub, which Flatpak fetches for
you. Inside the sandbox, Start at login is not offered, and the agent skill is
saved through Save SKILL.md rather than installed straight into
~/.claude or ~/.codex.
Portable on Windows. Unzip the portable zip anywhere, a USB stick included,
and run Turbo Reader.exe. The portable file beside it keeps your library,
settings and window position in a data folder next to the exe, so the whole
reader moves with the folder. Delete the portable file to use the normal
per-user data folder instead. It needs the Microsoft Edge WebView2 Runtime,
which Windows 10 and 11 already have.
The builds are not code-signed yet, so Windows SmartScreen and macOS Gatekeeper
warn on first run. On Windows, click More info, then Run anyway. On macOS,
right-click the app and choose Open, or run
xattr -cr "/Applications/Turbo Reader.app". Each release lists the SHA-256
checksum of every download in SHA256SUMS.txt, so you can check what you
installed.
| Feed management | The reader |
|---|---|
![]() |
![]() |
| Article actions | Light |
|---|---|
![]() |
![]() |
| Settings | Shortcuts |
|---|---|
![]() |
![]() |
A home page, not a backlog. Most readers open on everything you have not read, which is the same question again rather than an answer. Turbo Reader opens on what happened since you last looked: counts for today, this week and this month, your pinned feeds first, and a section per category.
Ranking that needs no account and no API key. Freshness, what you have read, which feeds you actually open, the feeds you pinned, and two keyword lists you write yourself. It runs locally, makes no network calls, and every card tells you why it is there.
Five layouts, per category. Cards, mosaic, magazine, compact or headlines, chosen per folder or left on auto, which decides from whether that folder's feeds carry images rather than guessing.
It cannot be taken down by an article. Feed HTML is fetched, parsed and run
through an allowlist sanitiser in Rust before the webview ever sees it. Browser
engines terminate the renderer outright on certain malformed markup, and that
is not an exception any try/catch or error boundary can catch, so the only
real defence is never handing it over in the first place.
#[test]
fn geolocation_cannot_survive_sanitising() {
let hostile = r#"<p>a <geolocation> b</p><script>alert(1)</script>"#;
let out = sanitise(hostile, None);
assert!(!out.contains("<geolocation"));
assert!(!out.contains("<script"));
}Home
- The date, a clock, and one optional line: a quote from a file you can edit, or the top story
- Counts for today, this week and this month, each one a filter, with a fourteen-day sparkline
- Search across everything, pinned feeds as a row, and a band per category
- Five layouts per category: cards, mosaic, magazine, compact and headlines, or auto, which decides from whether that category's feeds carry images
- Put the sections in any order, hide the ones you do not use, give categories a home order separate from the sidebar, and choose small, medium or large cards, all from the Customize button on home
- Ranking with no API key and no network: freshness, unread, how often you open a feed, the feeds you pinned, and your own interest and mute lists. A line in slashes is a regular expression, anything else a substring
- Every card says why it is there
Reading
- Two views: a dense three-pane list, or a card grid with cover art
- Unread, starred and all filters, scoped per feed or per group
- Newest-first or oldest-first ordering
- Full-text search across every article, backed by SQLite FTS5, matching as you type
- Search everything from the title bar or
CtrlK: feeds, folders and articles in one box - Load full content for feeds that only publish a teaser
- Reading mode on
z: the article alone, with the sidebar and list out of the way - Copy link, save as Markdown, save as PDF, QR code to a phone
- Hide an article, or mark all as read from 1, 3 or 7 days back
- Keyboard first, with a shortcut sheet on
? - Settings > Storage shows what the library and the webview take on disk, and frees it: compact the database, drop downloaded full articles, delete old read articles (starred and unread stay), or clear the webview cache
- Checks for a new release at launch and shows it in the title bar (can be switched off), plus a manual check in Settings
Appearance
- Light, dark, paper (a warm, low-contrast page for long reading), or follow the system
- Seven accent colours, or any colour you pick
- Comfortable and compact density
- Four interface sizes, on
Ctrl+/-/0 - Six open-source reading fonts, bundled so they work offline: Geist, Libron, Literata, Source Serif 4, Merriweather and Atkinson Hyperlegible Next, plus the system serif and a mono. Other scripts and emoji fall back to the system's own fonts
- Article text size, line width and text direction
- Animations you can switch off
Feeds
- RSS 0.9x, 1.0 and 2.0, Atom, and JSON Feed, detected automatically
- Right-click a feed to rename, move, pin, set retention or delete it, and a folder to rename or delete it
- Automatic refresh on a timer, or manual only
- Sorted as imported or alphabetically
- YouTube feeds show the video, in the browser or inline
- OPML import and export, with folder nesting preserved both ways
- Conditional GET, so an unchanged feed costs one
304and no parsing - Per-feed retention limits
- Duplicate collapsing across feeds, keyed on the destination URL with tracking parameters stripped, so a story syndicated through three feeds shows up once
Background (all off until you switch them on, on the welcome screen or in Settings)
- Keep running in the tray when the window closes, so refreshes carry on: the notification area on Windows, the menu bar on macOS, the system tray on Linux (GNOME needs the AppIndicator extension)
- Start at login, quietly in the tray
- A notification when a background refresh brings new articles, for all feeds or pinned feeds only
Turbo Reader can be a news source for Claude Code, Codex, Claude Desktop, Cursor and any other agent that speaks the Model Context Protocol. Ask "what's new in my feeds today?" or "summarise this week's articles about Kubernetes, with links", and the agent reads your own library.
- Two ways in. A local server inside the app, with API keys, or
turbo-reader --mcp, which an agent starts itself with the app closed. - Off by default, and local to this computer unless you allow your network.
- Read-only unless you say otherwise, per key.
- 14 tools: latest articles, full-text search, full articles as Markdown, digests, feeds and folders, and (with write access) subscribe, star and mark read.
- A skill to go with it. Install the Turbo Reader
SKILL.mdfor Claude Code or Codex in one click, or save it for any other agent. It teaches the agent when to use your feeds and how, and keeps itself up to date through the server.
Turn it on in Settings > AI agents, where the setup for each agent is ready to copy. The full guide, with every tool and real example answers, is in docs/mcp.md.
The feature set is not guesswork. These are the most-upvoted open requests in the desktop RSS community, several of them open for years, and where each one stands here.
| Request | Votes | Status |
|---|---|---|
| #246, #554 Sort oldest to newest | 8, 4 | Shipped |
| #144, #334, #533 Hide duplicate articles | 8, 7, 3 | Shipped |
| #334 Post limit per feed | 7 | Shipped |
| #347, #397 UI scaling, larger fonts | 5, 5 | Shipped as density |
| #335 Theme customisation | 7 | Shipped as accents |
#256 Identify articles by guid |
2 | Shipped |
| #629 FeedBurner returns 403 | 4 | Shipped, browser User-Agent |
| #592 Keyboard shortcuts | 2 | Shipped, with a shortcut sheet |
| #539 Sort groups and feeds alphabetically | 4 | Shipped |
| #316, #100 Tray and background notifications | 21, 16 | Planned |
| #169 Use the site's favicon | 9 | Shipped |
| #190 Nested folders | 4 | Planned |
| #464 HTTP Basic Auth feeds | 7 | Planned |
| #211, #663 YouTube content and previews | 9, 4 | Shipped |
| #69 Podcast feeds | 3 | Planned |
| #4, #23 Feedly and sync services | 87, 39 | Under consideration |
Sync (the Google Reader API, Fever, Miniflux, Nextcloud, Feedly) is the most requested feature by a wide margin and also the largest body of work. It is out of scope rather than half built, because a sync that loses your read state once is worse than none at all.
src-tauri/src/
feed.rs fetch, parse, sanitise. The security boundary.
readable.rs full-content extraction, scored and sanitised
markdown.rs HTML to Markdown for the export
db.rs SQLite schema, FTS5 index, retention
opml.rs OPML import and export, folders preserved
commands.rs the Tauri command surface
src/
lib/api.ts typed client over those commands
lib/theme.tsx light and dark modes, accent tokens
components/ Sidebar, ArticleList, Reader, SettingsPanel
Two choices worth explaining.
SQLite instead of an in-memory store. Articles stay on disk, queries are paged, and search goes through FTS5, so a library of a hundred thousand articles costs the same at startup as a library of ten.
Bounded-concurrency fetching. Refresh polls up to 12 feeds at once on a Tokio semaphore. Unbounded would hammer the connection pool. Serial would be slow.
npm install
npm run app # dev, with hot reload
npm run app:build # production bundle
cd src-tauri && cargo testEnd to end tests drive the real app through WebDriver, with its own data
folder so your feeds are never touched. They need
tauri-driver on your path and
an msedgedriver.exe matching your WebView2 version in e2e/.bin/.
npm run e2e:build # build the test copy of the app
npm run e2e # run the suiteYou need Rust (stable) and the Tauri 2 prerequisites for your platform.
Linux packages without the toolchain. Docker can build the .deb, .rpm
and .AppImage on any machine, Windows and macOS included:
docker build -f docker/linux-build.Dockerfile --output dist-linux .The packages land in dist-linux/. The image builds on Ubuntu 22.04, the same
base as the release builds, so the AppImage runs on the same distributions.
Flatpak. The manifest is in flatpak/ and builds from source, offline, as
Flathub requires. On Linux with flatpak-builder:
git submodule update --init # flatpak/shared-modules, for the tray library
flatpak/generate-sources.sh # npm and cargo sources for the offline build
flatpak-builder --user --install --install-deps-from=flathub --force-clean build-dir flatpak/dev.t21.turbo-reader.yml
flatpak run dev.t21.turbo-readerRun generate-sources.sh again whenever package-lock.json or Cargo.lock
changes. For a release, add a <release> line to
flatpak/dev.t21.turbo-reader.metainfo.xml.
Turbo Reader is an independent implementation. Thanks to Fluent Reader by Haoyuan Liu, whose feature design informed parts of this one.
Built with Tauri, feed-rs, ammonia and rusqlite. Type is Geist. Reading fonts, all under the SIL Open Font License: Libron by Nico Verbruggen, Literata by TypeTogether, Source Serif 4 by Adobe, Merriweather by Sorkin Type, and Atkinson Hyperlegible Next by the Braille Institute.
| Windows installer | 4.7 MB, kept under 5 MB |
| Installed on disk | 11 MB |
| Memory, 500 feeds and 20,000 articles | 14 MB app process, ~270 MB with the system webview |
| Refresh 500 feeds from a local test server | 0.2 s |
| Cold start to usable | under half a second |
Measured, not estimated, on one Windows machine.
Size budget. The Windows installer stays under 5 MB. The reading fonts are cut to Latin characters only for that reason, and anything new that would push the installer past 5 MB has to make room first.
Where the memory goes. The Rust process that holds your library, the database and the fetcher uses about 14 MB, and that number barely moves as the library grows. Most of the rest belongs to WebView2, the system webview that draws the window, which runs its own processes: about half of the total is its GPU process, the hardware-accelerated drawing every Chromium-based window pays for, and the page itself takes about 60 MB. The app's own JavaScript heap is under 5 MB. With nothing loaded the whole app sits around 220 MB; Task Manager's figure is lower, because about half of the GPU process's share is graphics memory rather than RAM.
Two decisions buy most of that. Tauri uses the webview the operating system already ships instead of bundling a second copy of a browser, and articles stay in SQLite with paged queries and an FTS5 index rather than being loaded into the renderer at startup, so memory does not climb with the size of your library.
The AI assistant is specified and not yet built: bring your own key, OpenAI-shaped so Claude, Gemini, Kimi, DeepSeek, Groq, OpenRouter and a local Ollama all work, with summaries, clustering, a connection test and a token ledger.
The home page already ranks without it, on local scoring and your own interest and mute lists. The assistant is meant to make that better, not to be the thing that makes it work.
Turbo Reader keeps your library on your computer and has no account, no analytics and no telemetry. It connects to other systems only for these:
- The feeds and websites you add: to fetch new articles, their icons, and the full article when you ask for it.
- GitHub, once when the app opens, to check for a new release. Turn this off in About.
- AI agents, only if you turn the agent server on. It answers programs on this computer, or on your network if you allow that, and only with a key you made.
The full policy is in PRIVACY.md.
Turbo Reader is free and open source under the MIT licence.
Turbo Reader is by t21 dev and TriptoAfsin. See LICENSE for the full terms.






