SFEEDRC(5)

πŸ“¦
version 2.4 Β· 4 versions
, in alpine 3.24, nixos 26.05, nixpkgs unstable, ubuntu resolute, ubuntu stonking

πŸ’– 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 concurrent feed() jobs run at once. default is 16. 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 the iconv(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-save and --etag-compare) can be used to store and send the previous ETag header value. curl version 7.73+ is recommended for it to work properly.
  • the curl -z option can be used to send the modification date of a local file as a HTTP If-Modified-Since request header. the server can then respond if the data is modified or not, or respond with only the incremental data.
  • the curl --compressed option 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