All posts feeds

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 typeWhere it runsCost
Date bounds @the indexsingle-digit ms
Tag clauses +/-the indexsingle-digit ms
Result cap #Nthe indexproportional to N
Regex / feedin-appproportional 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.