The filter line is the star
How one space-separated string replaces every menu, checkbox and saved search in the Feeds reader.
Most RSS readers bury filtering behind menus: a dropdown for feeds, checkboxes for tags, a date picker, a separate search box. Feeds throws all of that away for a single idea borrowed from Emacs elfeed: one filter line that does everything.
The language
A filter is a space-separated string. Each token narrows the results:
+TAG must have tag -TAG must not have tag
@TIME newer than TIME @OLD--NEW date window [now-OLD, now-NEW]
=REGEX feed url/title matches ~REGEX feed url/title must not match
REGEX title/link matches !REGEX title/link must not match
#N cap results at N
TIME is a relative duration (2-weeks, 3 days, 1y) or an absolute
YYYY-MM-DD. Regexes are smart-case: type them lowercase and they match
case-insensitively.
So “unread kernel news from the last two weeks on LWN, no comment threads, top 50” becomes:
@2-weeks +unread =lwn kernel !comments #50
That’s the whole query. No dialog, no saved-search management — the line is the saved search, and you can edit it in place.
Why it’s fast
The filter isn’t just ergonomic, it’s quick. On a 50,000-entry database:
| Clause type | Where it runs | Cost |
|---|---|---|
Date bounds @ | the index | single-digit ms |
Tag clauses +/- | the index | single-digit ms |
Result cap #N | the index | proportional to N |
| Regex / feed | in-app | proportional to matches |
The trick is pushing everything that can be an index predicate — dates, tags, the cap —
down to the query, and only running regex in-app over the rows that survive. Keep a date
bound in your filter (the default @2-weeks +unread does) and results are effectively
instant.
Same line, everywhere
Because the filter language lives in the shared core, the exact same string works in the terminal, the desktop app, and on mobile. Learn it once; use it everywhere.