Elfeed is an extensible web feed reader for Emacs, supporting both Atom and RSS. It requires Emacs 24.3 and is available for download from MELPA or el-get. Elfeed was inspired by notmuch.
For a longer overview,
The database format is stable, but there may still be an update someday that requires migration.
Elfeed is broken into a multiple source files, so if you manually
install it you will need to add the Elfeed package directory to your
load-path
. If installed via package.el or el-get, this will be done
automatically.
It is recommended that you make a global binding for elfeed
.
(global-set-key (kbd "C-x w") 'elfeed)
Running the interactive function elfeed
will pop up the
*elfeed-search*
buffer, which will display feed items.
- g: refresh view of the feed listing
- G: fetch feed updates from the servers
- s: update the search filter (see tags)
This buffer will be empty until you add your feeds to the
elfeed-feeds
list and initiate an update with M-x elfeed-update
(or G in the Elfeed buffer). This will populate the Elfeed
database with entries.
;; Somewhere in your .emacs file
(setq elfeed-feeds
'("http://nullprogram.com/feed/"
"http://www.terminally-incoherent.com/blog/feed/"))
Another option for providing a feel list is with an OPML file. Running
M-x elfeed-load-opml
will fill elfeed-feeds
with feeds listed in
an OPML file. When elfeed-load-opml
is called interactively, it will
automatically save the feedlist to your customization file, so you
will only need to do this once.
If there are a lot of feeds, the initial update will take noticeably
longer than normal operation because of the large amount of
information being written the database. Future updates will only need
to write new or changed data. If updating feeds slows down Emacs too
much for you, reduce the value of url-queue-parallel-processes
(the
number of feeds to process at one time).
Elfeed uses Emacs' url-queue package to manage feed fetching.
Unfortunately it has a very short default value, so if you're getting
any "Queue timeout exceeded" errors, increase url-queue-timeout
.
(setf url-queue-timeout 30)
From the search buffer there are a number of ways to interact with entries. Entries are selected by placing the point over an entry. Multiple entries are selected at once by using an active region.
- RET: view selected entry in a buffer
- b: open selected entries in your browser (
browse-url
) - y: copy selected entries URL to the clipboard
- r: mark selected entries as read
- u: mark selected entries as unread
- +: add a specific tag to selected entries
- -: remove a specific tag from selected entries
Elfeed maintains a list of arbitrary tags -- symbols attached to an
entry. The tag unread
is treated specially by default, with unread
entries appearing in bold.
Tags can automatically be applied to entries discovered in specific
feeds through extra syntax in elfeed-feeds
. Normally this is a list
of strings, but an item can also be a list, providing set of
"autotags" for a feed's entries.
(setq elfeed-feeds
'(("http://nullprogram.com/feed/" blog emacs)
"http://www.50ply.com/atom.xml" ; no autotagging
("http://nedroid.com/feed/" webcomic)))
To make tags useful, the Elfeed entry listing buffer can be filtered
by tags. Use elfeed-search-set-filter
(or s) to update
the filter.
Any component of the search string beginning with a +
or
a -
is treated like a tag. +
means the tag is required, -
means
the tag must not be present.
A component beginning with a @
indicates an age. Entries older than
this age are filtered out. The age description accepts plain English,
but cannot have spaces, so use dashes. For example, "@2-years-old"
or "@3-days-ago"
. The database is date-oriented, so filters that
include an age restriction are significantly more efficient.
A component beginning with a !
is treated as an "inverse" regular
expression. This means that any entry matching this regular expression
will be filtered out. The regular expression begins after the !
character. You can read this as "entry not matching foo
".
A component beginning with a #
limits the total number of entries
displayed to the number immediately following the symbol. For example,
to limit the display to 20 entries: #20
.
All other components are treated as a regular expression, which means only entries matching this will be shown.
Here are some example filters.
@6-months-ago +unread
Only show unread entries of the last six months. This is the default filter.
linu[xs] @1-year-old
Only show entries about Linux or Linus from the last year.
-unread +youtube #10
Only show the most recent 10 previously-read entries tagged as
youtube
.
+unread !x?emacs
Only show unread entries not having emacs
or xemacs
in the title
or link.
You can set your default search filter by changing the default value
of elfeed-search-filter
. It only changes buffer-locally when you're
adjusting the filter within Elfeed. For example, some users prefer to
have a space on the end for easier quick searching.
(setq-default elfeed-search-filter "@1-week-ago +unread ")
The last example assumes you've tagged posts with youtube
. You
probably want to do this sort of thing automatically, either through
the "autotags" feature mentioned above, or with the
elfeed-new-entry-hook
. Functions in this hook are called with new
entries, allowing them to be manipulated, such as adding tags.
;; Mark all YouTube entries
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :feed-url "youtube\\.com"
:add '(video youtube)))
Avoiding tagging old entries as unread
:
;; Entries older than 2 weeks are marked as read
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :before "2 weeks ago"
:remove 'unread))
Or building your own subset feeds:
(add-hook 'elfeed-new-entry-hook
(elfeed-make-tagger :feed-url "example\\.com"
:entry-title '(not "something interesting")
:add 'junk
:remove 'unread))
Elfeed includes a demonstration/toy web interface for remote network
access. It's a single-page web application that follows the database
live as new entries arrive. It's packaged separately as elfeed-web
.
To fire it up, run M-x elfeed-web-start
and visit
http://localhost:8080/elfeed/ (check your httpd-port
) with a
browser. See the elfeed-web.el
header for endpoint documentation if
you'd like to access the Elfeed database through the web API.
It's rough and unfinished -- no keyboard shortcuts, read-only, no authentication, and a narrow entry viewer. This is basically Elfeed's "mobile" interface. Patches welcome.
I personally only use Elfeed on Linux, but it's occasionally tested on Windows. Unfortunately the Windows port of Emacs is a bit too unstable for parallel feed downloads, not to mention the tiny, hard-coded, 512 open descriptor limitation, so it limits itself to one feed at a time on this platform.
The GNU-provided W32 build of Emacs doesn't include any of the libraries needed to actually view entries within Emacs, but you can still see the entry listing and visit entries in your browser. For full support, you'll either have to track down and install the missing DLLs, or use a build that includes it.
The database should keep itself under control without any manual
intervention, but steps can be taken to minimize the database size if
desired. The simplest option is to run the elfeed-db-compact
command, which will pack the loose-file content database into a single
compressed file. This function works well in kill-emacs-hook
.
Going further, a function could be added to elfeed-new-entry-hook
to
strip unwanted/unneeded content from select entries before being
stored in the database. For example, for YouTube videos only the entry
link is of interest and the regularly-changing entry content could be
tossed to save time and storage.
Elfeed is to the point where it can serve 100% of my own web feed needs. My personal selection of about 150 feeds has been acting as my test case as I optimize and add features.
Some things I still might want to add:
- Database synchronization between computers
- Parallel feed fetching via separate Emacs subprocesses
- SQLite-backed database via EmacSQL
- Support for xml:base in Atom feeds
- Smaller database footprint
As far as I know, outside of Elfeed there does not exist an extensible, text-file configured, power-user web feed client that can handle a reasonable number of feeds. The existing clients I've tried are missing some important capability that limits its usefulness to me.