SFEEDRC(5)
π SFEEDRC(5) π
okay bestie, sit down, hydrate, because today we're learning about sfeedrc β the File Formats Manual entry that makes sfeed_update(1) do its little thing. it's a config file, it's a shellscript, it's giving main character energy, and honestly? iconic.
β¨ NAME β¨
sfeedrc β the configuration file for sfeed_update(1). yes girl, that's the whole name, slay.
πΈ DESCRIPTION πΈ
so sfeedrc is literally the config file for sfeed_update(1), and here's the tea: it gets evaluated as a shellscript. not parsed, not interpreted by some cute custom parser β straight up evaluated as a shellscript. so like, respect it, it has powers. π«Ά
π VARIABLES π
these are the little knobs you can turn, bestie:
sfeedpathβ set this to the directory where your TAB-separated feed files get stored. the default is$HOME/.sfeed/feeds. set it and forget it. β¨maxjobsβ this one changes how many concurrentfeed()jobs run at once. default is16. so like, sixteen little feeds doing their thing simultaneously. multitasking queen behavior. π
π¦ FUNCTIONS π¦
feeds()
this is the required "main" entry-point function that sfeed_update(1) calls. no feeds(), no feeds. periodt. it's required, not optional, don't try it.
feed(name, feedurl, basesiteurl, encoding)
inside that feeds() function, you define your actual feeds by calling feed(). here's what each argument is doing:
nameβ the name of the feed. this is ALSO the filename used for the TAB-separated feed file, so it's doing double duty (iconic of it). it cannot contain the/character because that's the path separator β those get replaced with_. and each name should be unique, okay? no twinsies.feedurlβ the URL where the RSS/Atom data gets fetched from. usually an HTTP or HTTPS URL. (usually. not always.)[basesiteurl]β base URL of the feed links. this is the little fixer-upper that lets you repair relative item links. per the RSS and Atom spec, feeds should always have absolute URLs, but in practice? bestie, no. not always the case. so this exists. π[encoding]β feeds get converted from this encoding to UTF-8. it should be a usable character-set name for theiconv(1)tool.
π₯ OVERRIDE FUNCTIONS π₯
because sfeed_update(1) is a shellscript, every single function can be overridden to change how it behaves. you're the boss. the notable ones are:
fetch(name, url, feedfile)
fetches the feed from the URL and writes the data to stdout. arguments:
nameβ feed name.urlβ URL to fetch.feedfileβ the used feedfile (useful for comparing modification times, lowkey handy).
by default, the tool curl(1) is used.
convertencoding(name, from, to)
converts data from stdin from one text-encoding to another and writes it to stdout. arguments:
nameβ feed name.fromβ from text-encoding.toβ to text-encoding.
by default, the tool iconv(1) is used.
parse(name, feedurl, basesiteurl)
reads RSS/Atom XML data from stdin, converts it, and writes it as sfeed(5) data to stdout. arguments:
nameβ feed name.feedurlβ URL of the feed.basesiteurlβ base URL of the feed links. this argument allows fixing relative item links.
filter(name, url)
filters sfeed(5) data from stdin and writes it to stdout. arguments:
nameβ feed name.urlβ URL of the feed.
merge(name, oldfile, newfile)
merges sfeed(5) data of oldfile with newfile and writes it to stdout. arguments:
nameβ feed name.oldfileβ old file.newfileβ new file.
order(name, url)
sorts sfeed(5) data from stdin and writes it to stdout. arguments:
nameβ feed name.urlβ URL of the feed.
π EXAMPLES π
an example configuration file is included, named sfeedrc.example, and it's also shown right here because we're generous like that:
#sfeedpath="$HOME/.sfeed/feeds"
# list of feeds to fetch:
feeds() {
# feed <name> <feedurl> [basesiteurl] [encoding]
feed "codemadness" "https://www.codemadness.org/atom_content.xml"
feed "explosm" "http://feeds.feedburner.com/Explosm"
feed "golang github releases" "https://github.com/golang/go/releases.atom"
feed "linux kernel" "https://www.kernel.org/feeds/kdist.xml" "https://www.kernel.org"
feed "reddit openbsd" "https://old.reddit.com/r/openbsd/.rss"
feed "slashdot" "http://rss.slashdot.org/Slashdot/slashdot" "http://slashdot.org"
feed "tweakers" "http://feeds.feedburner.com/tweakers/mixed" "http://tweakers.net" "iso-8859-1"
# get youtube Atom feed: curl -s -L 'https://www.youtube.com/user/gocoding/videos' | sfeed_web | cut -f 1
feed "youtube golang" "https://www.youtube.com/feeds/videos.xml?channel_id=UCO3LEtymiLrgvpb59cNsb8A"
feed "xkcd" "https://xkcd.com/atom.xml" "https://xkcd.com"
}
now, to change the default curl(1) options for fetching the data, you can override the fetch() function and stick it at the top of your sfeedrc file. like this, bestie:
# fetch(name, url, feedfile)
fetch() {
# allow for 1 redirect, set User-Agent, timeout is 15 seconds.
curl -L --max-redirs 1 -H "User-Agent: 007" -f -s -m 15 \
"$2" 2>/dev/null
}
πΎ Caching, incremental data updates and bandwidth saving
for HTTP servers that support it, you can save some bandwidth by changing some of the default curl options. but heads up β these options can come at a cost of some privacy, because they expose additional metadata from the previous request. so like, know what you're signing up for. π
- the curl ETag options (
--etag-saveand--etag-compare) can be used to store and send the previous ETag header value. curl version7.73+is recommended for it to work properly. - the curl
-zoption can be used to send the modification date of a local file as a HTTPIf-Modified-Sincerequest header. the server can then respond if the data is modified or not, or respond with only the incremental data. - the curl
--compressedoption can be used to indicate the client supports decompression. because RSS/Atom feeds are textual XML data, this generally compresses very well. - the example below also sets the User-Agent to
sfeed, because some CDNs block HTTP clients based on the User-Agent request header.
example:
mkdir -p "$HOME/.sfeed/etags" "$HOME/.sfeed/lastmod"
# fetch(name, url, feedfile)
fetch() {
basename="$(basename "$3")"
etag="$HOME/.sfeed/etags/${basename}"
lastmod="$HOME/.sfeed/lastmod/${basename}"
output="${sfeedtmpdir}/feeds/${basename}.xml"
curl \
-f -s -m 15 \
-L --max-redirs 0 \
-H "User-Agent: sfeed" \
--compressed \
--etag-save "${etag}" --etag-compare "${etag}" \
-R -o "${output}" \
-z "${lastmod}" \
"$2" 2>/dev/null || return 1
# succesful, but no file written: assume it is OK and Not Modified.
[ -e "${output}" ] || return 0
# use server timestamp from curl -R to set Last-Modified.
touch -r "${output}" "${lastmod}" 2>/dev/null
cat "${output}" 2>/dev/null
# use write output status, other errors are ignored here.
fetchstatus="$?"
rm -f "${output}" 2>/dev/null
return "${fetchstatus}"
}
the README file has more examples. go read it, i believe in you. πβ¨
π SEE ALSO π
curl(1), iconv(1), sfeed_update(1), sh(1)
π AUTHORS π
Hiltjo Posthuma <hiltjo@codemadness.org>
and that's the whole thing, bestie!! π this page came to you from Debian, dated August 8, 2025, and yes, it really is SFEEDRC(5). now go write your sfeedrc and absolutely eat. π
β¨ no cap. π¦
π¦ where this page comes from
- alpine 3.24: sfeed-doc 2.4-r0 Β· ISC
- nixos 26.05: sfeed 2.4
- nixpkgs unstable: sfeed 2.4
- ubuntu resolute: sfeed 2.3-1 Β· ISC
- ubuntu stonking: sfeed 2.3-1 Β· ISC
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms