Feedr v0.8.0 – 一个终端UI的RSS阅读器,现在可以在终端中阅读完整文章

Hacker News Top 工具

摘要

Feedr v0.8.0 是一款基于终端的RSS阅读器,使用Rust编写,具有TUI界面,支持订阅管理、全文提取以及vim风格的导航。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/05/15 18:33

bahdotsh/feedr

源:https://github.com/bahdotsh/feedr

Feedr - 终端 RSS 阅读器 📰

Feedr 是一个功能丰富的终端 RSS 阅读器,采用 Rust 编写。它提供了简洁直观的 TUI 界面,用于管理和阅读 RSS 提要,具有优雅的视觉效果和流畅的键盘导航。

Feedr 终端 RSS 阅读器

演示

Feedr 演示

功能特性

  • 仪表盘视图:查看所有订阅源中按时间排序的最新文章
  • 订阅源管理:订阅和组织多个 RSS/Atom 订阅源
  • 订阅源自动发现:粘贴任何网页 URL,Feedr 将自动检测并提供订阅其 RSS/Atom 订阅源
  • 星标文章:保存文章以供稍后阅读,设有专门的星标视图
  • 分类:将订阅源组织到自定义分类中,支持创建、重命名和删除
  • 树形视图:以分类分组的层级树形结构浏览订阅源
  • 高级过滤:按分类、时间、作者、阅读状态、星标状态和内容长度过滤文章
  • 双主题:使用 t 键在深色赛博朋克主题和浅色禅意主题之间切换
  • 实时搜索:即时搜索所有订阅源标题和文章内容
  • 摘要视图:“最新动态”屏幕显示自上次会话后添加的文章,并附带每个订阅源的统计信息
  • 已读/未读追踪:跨会话持久化阅读状态
  • 全部标记为已读:使用 m 键快速将所有可见项目标记为已读
  • 文章预览:在仪表盘视图中切换内联预览面板
  • 链接提取:使用 l 键提取并浏览文章中的所有链接
  • 全文提取:去除摘要,通过 Mozilla Readability 内联读取实际文章内容——手动按 Shift+F,或在刷新时自动按订阅源配置 fulltext = true
  • 帮助浮层:按 ? 键查看可滚动的快捷键参考浮层
  • OPML 导入:通过 feedr --import <文件> 批量从 OPML 文件导入订阅源
  • 浏览器集成:在默认浏览器中打开文章
  • 鼠标支持:点击选择项目,使用鼠标滚轮滚动
  • 后台刷新:自动更新订阅源,可配置间隔和智能速率限制
  • 速率限制:按域名限制请求频率,防止“请求过多”错误(特别适合 Reddit 订阅源)
  • Vim 风格导航:使用 j/k 以及方向键进行导航
  • 富内容显示:HTML 转文本,文章格式整洁
  • 认证订阅源:支持为每个订阅源设置自定义 HTTP 标头(例如 Authorization: Bearer ...),用于私有/认证 RSS 订阅源
  • 紧凑模式:小终端(≤30 行)自动启用紧凑布局,可在配置中手动覆盖为 always/never
  • CLI 配置管理:从命令行获取、设置和列出配置(feedr config),或使用交互式 TUI 配置编辑器(feedr config --tui
  • 可配置快捷键:通过 config.toml 中的 [keybindings] 节重新映射任何按键动作
  • 外部命令钩子:Newsboat 风格的宏(pipe-toexec)绑定到按键,以及每次新项目时触发的 exec_on_new 通知——均支持无 shell 的参数模板
  • 可配置:通过 TOML 配置自定义超时、主题、UI 行为和默认订阅源
  • XDG 兼容:遵循标准目录规范存储配置和数据

安装

前提条件

  • Rust 和 Cargo(从 https://rustup.rs/ 安装)

使用 Cargo 安装(推荐)

cargo install feedr

Arch Linux(AUR)

Feedr 可通过 AUR 获取(https://aur.archlinux.org/packages/feedr)。使用您偏好的 AUR 助手安装:

paru -S feedr
# 或
yay -S feedr

从源码构建

git clone https://github.com/bahdotsh/feedr.git
cd feedr
cargo build --release

编译后的二进制文件位于 target/release/feedr

使用方法

运行应用:

feedr

OPML 导入

从 OPML 文件导入订阅源:

feedr --import feeds.opml

配置管理

从命令行查看和修改设置:

feedr config list            # 列出所有设置及其当前值
feedr config get ui.theme    # 获取单个值
feedr config set ui.theme light   # 设置值(带验证)
feedr config --tui           # 打开交互式 TUI 配置编辑器

配置键使用点号表示法(例如 general.max_dashboard_itemsnetwork.http_timeoutui.themeui.compact_mode)。运行 feedr config list 可查看所有键。订阅源管理(default_feeds)仅通过 TUI 编辑器可用。

快速上手

  1. 首次打开 Feedr 时,按 a 添加一个订阅源
  2. 输入有效的 RSS 订阅源 URL(例如 https://news.ycombinator.com/rss
  3. 您也可以按 123 快速添加 Hacker News、TechCrunch 或 BBC News
  4. 使用方向键(或 j/k)导航,按 Enter 查看项目
  5. o 在浏览器中打开当前文章
  6. t 在深色和浅色主题之间切换

键盘控制

以下所有快捷键显示其默认值。您可以通过配置文件中的 [keybindings] 节重新映射任何动作——请参阅可配置快捷键

通用导航

按键操作
Tab向前循环切换视图
Shift+Tab向后循环切换视图
q返回(从仪表盘退出)
h / Esc / Backspace返回上一视图
Home返回仪表盘
Ctrl+Q从任意视图退出
r刷新所有订阅源
t切换深色/浅色主题
/搜索模式
?帮助浮层(可滚动的快捷键参考)

仪表盘视图

按键操作
↑/↓k/j导航项目
g / GEnd跳至顶部 / 底部
Enter查看选中的项目
f过滤文章
c循环切换分类过滤
Ctrl+C打开分类管理
a添加新的订阅源
s切换星标
Space切换已读/未读
m将所有项目标记为已读
p切换预览面板
Shift+J / Shift+K向下 / 向上滚动预览
o在浏览器中打开链接
1/2/3快速添加演示订阅源(HN、TechCrunch、BBC)

订阅源列表视图

按键操作
q / h / Esc前往仪表盘
↑/↓k/j导航订阅源
Enter查看订阅源项目
Space展开/折叠分类(树形视图)
a添加新的订阅源
d删除选中的订阅源
c为订阅源分配分类

订阅源项目视图

按键操作
q / h / Esc / Backspace返回订阅源列表
Home前往仪表盘
↑/↓k/j导航项目
g / GEnd跳至顶部 / 底部
Enter查看项目详情
s切换星标
Space切换已读/未读
m将所有项目标记为已读
o在浏览器中打开项目

项目详情视图

按键操作
q / h / Esc / Backspace返回订阅源项目
↑/↓k/j滚动内容
Ctrl+U / Ctrl+D滚动内容(翻页)
Page Up / Page Down滚动内容(翻页)
g跳至顶部
G / End跳至底部
s切换星标
o在浏览器中打开项目
l提取并显示所有链接
Shift+F切换/获取全文(Readability)

星标视图

按键操作
↑/↓k/j导航项目
Enter查看项目详情
s取消星标
o在浏览器中打开项目

分类管理视图

按键操作
n新建分类
e重命名分类
d删除分类
Space展开/折叠分类
Enter选择分类
r刷新
?帮助
h / Esc / q返回

过滤模式(在仪表盘按 f

按键操作
c按分类过滤
t按时间/新旧程度过滤
a按作者过滤
r按阅读状态过滤
s按星标状态过滤
l按内容长度过滤
x清除所有过滤

鼠标支持

操作效果
左键点击选择项目
向上/向下滚动导航项目

配置

Feedr 通过遵循 XDG 基础目录规范的 TOML 配置文件支持自定义。您可以直接编辑文件,使用 feedr config get/set 命令行,或使用 feedr config --tui 交互式编辑器。

配置文件位置

  • Linux/macOS~/.config/feedr/config.toml
  • Windows%APPDATA%\feedr\config.toml

配置文件在首次运行时自动生成默认值(如果不存在)。

可用设置

# Feedr 配置文件

[general]
max_dashboard_items = 100        # 仪表盘上显示的最大项目数
auto_refresh_interval = 0        # 自动刷新间隔(秒,0 表示禁用)
refresh_enabled = false          # 启用自动后台刷新
refresh_rate_limit_delay = 2000  # 对同一域名的请求之间的延迟(毫秒)

[network]
http_timeout = 15                # HTTP 请求超时(秒)
user_agent = "Mozilla/5.0 (compatible; Feedr/1.0; +https://github.com/bahdotsh/feedr)"

[ui]
tick_rate = 100                  # UI 更新速率(毫秒)
error_display_timeout = 3000     # 错误消息显示持续时间(毫秒)
theme = "dark"                   # 主题:"dark"(赛博朋克)或 "light"(禅意)
compact_mode = "auto"            # 紧凑布局:"auto"、"always" 或 "never"

# 可选:定义首次运行时加载的默认订阅源
[[default_feeds]]
url = "https://example.com/feed.xml"
category = "News"

# 带自定义 HTTP 标头的认证订阅源
[[default_feeds]]
url = "https://private.example.com/feed.xml"
[default_feeds.headers]
Authorization = "Bearer your_token_here"

配置选项说明

通用设置

  • max_dashboard_items:控制仪表盘上显示的项目数量(默认:100)
  • auto_refresh_interval:按指定间隔(秒)自动刷新订阅源(0 禁用自动刷新)
  • refresh_enabled:总开关,启用/禁用自动后台刷新(默认:false)
  • refresh_rate_limit_delay:对同一域名的请求之间的延迟(毫秒),以防止“请求过多”错误(默认:2000ms)。对于 Reddit 订阅源和其他有速率限制的服务特别有用。

网络设置

  • http_timeout:获取订阅源时 HTTP 请求的超时时间(适用于慢速连接)
  • user_agent:自定义 HTTP 请求的用户代理字符串

UI 设置

  • tick_rate:UI 更新频率(毫秒),越低响应越快,越高 CPU 占用越低
  • error_display_timeout:错误消息显示持续时间(毫秒)
  • theme:选择 "dark"(赛博朋克美学,霓虹色)或 "light"(禅意极简,自然色)。也可在运行时按 t 切换。
  • compact_mode:控制小终端的紧凑布局。"auto"(默认)在终端高度 ≤30 行时启用紧凑模式,"always" 强制紧凑模式,"never" 禁用。紧凑模式使用单行项目、最小化标题栏和缩略的帮助栏,以最大化屏幕可用空间。

后台刷新示例

要每 5 分钟启用自动刷新并带速率限制:

[general]
refresh_enabled = true
auto_refresh_interval = 300      # 5 分钟
refresh_rate_limit_delay = 2000  # 对同一域名的请求间隔 2 秒

注意:速率限制按域名分组订阅源,并交错请求以防止达到 API 限制。例如,如果您有多个 Reddit 订阅源,它们将以 2 秒的间隔依次请求,避免被屏蔽。

默认订阅源

您可以定义首次运行时自动加载的订阅源:

[[default_feeds]]
url = "https://news.ycombinator.com/rss"
category = "Tech"

[[default_feeds]]
url = "https://example.com/feed.xml"
category = "News"

# 可选的每个订阅源刷新阈值(秒)。当自上次刷新后经过此时间,
# 下一个自动刷新 tick 将被触发——当前所有订阅源一起刷新
# (没有真正的按订阅源选择性刷新)。
# 需要启用 `general.refresh_enabled = true`。
[[default_feeds]]
url = "https://example.com/fast-feed.xml"
refresh_interval = 60

认证订阅源

某些 RSS 订阅源需要认证或自定义 HTTP 标头。您可以配置每个订阅源的标头:

[[default_feeds]]
url = "https://private.example.com/feed.xml"
[default_feeds.headers]
Authorization = "Bearer your_api_token"

[[default_feeds]]
url = "https://another-api.example.com/rss"
[default_feeds.headers]
X-API-Key = "your_api_key"
Cookie = "session=abc123"

标头会随每次对该订阅源的请求发送,包括刷新时。

全文提取

大多数 RSS 订阅源只提供简短摘要。Feedr 可以获取关联的文章 URL,并运行 Mozilla Readability(https://github.com/mozilla/readability)(通过 dom_smoothie crate)提取实际文章正文并内联显示。

  • 手动:在文章详情视图中,按 Shift+F 提取当前聚焦的文章。再次按 Shift+F 切换回原始摘要,或在失败后重试。
  • 刷新时自动:为订阅源设置 fulltext = true,Feedr 会在每次刷新时自动提取新出现的项目(遵循与 exec_on_new 相同的“非洪泛”规则——首次观察到的订阅源静默作为种子)。
[[default_feeds]]
url = "https://example.com/summary-only-feed.xml"
fulltext = true

说明:

  • 提取的内容仅在内存中——不会持久化到磁盘。重启后按需重新提取。
  • 每个订阅源的认证标头不会发送到文章 URL(文章 URL 通常是第三方主机;转发 Authorization 会泄漏凭据)。
  • 提取正文过短的页面(很可能是 JS 渲染或受限页面)会优雅地失败,并回退显示原始摘要。

外部命令钩子

Feedr 支持类似 Newsboat 的外部命令,用于两种工作流程:(按键触发的链式动作,作用于当前聚焦的文章)和 exec_on_new(每次刷新后,每个新出现的项目触发的通知钩子)。

命令不通过 shell 运行。 模板在配置加载时一次性进行标记化,%X 占位符会被替换到各个 argv 标记中——订阅源内容永远不会逸出参数。对于管道、重定向或通配符,请编写一个小型 shell 脚本并调用它。

模板变量

在宏和钩子命令的每个 argv 标记中展开:

变量展开为
%t文章标题
%u文章 URL
%a作者
%d格式化后的发布日期
%f订阅源标题
%F订阅源 URL
%%字面 %

宏将按键绑定到有序的步骤链。按下 <prefix><key> 触发(默认前缀为 ,)。步骤之间用 ; 分隔。可选的尾部 -- "description" 会覆盖帮助浮层中的标签。

[macros]
y = 'open-in-browser ; pipe-to "yt-dlp %u"'
w = 'pipe-to "wallabag-cli add %u" -- "保存到 Wallabag"'
n = 'pipe-to "tee /tmp/out.txt" stdin=metadata'

[macro_options]
prefix = ","                # 宏前缀键
pipe_default_stdin = "body"  # body | title | url | metadata | none

步骤类型:

  • <action> — 调用内置动作。宏中支持的动作:open-in-browsertoggle-startoggle-readmark-all-readrefreshtoggle-themeextract-linksfetch-full-texthelp
  • pipe-to "cmd %u" [stdin=...] — 暂停 TUI,运行命令,并将文章内容通过管道发送到其标准输入。stdin 可以是 body(默认)、titleurlmetadatanone
  • exec "cmd %u" — 分离方式生成命令(无标准输入,不接管终端)。

链在第一个步骤出错时停止。按下前缀后的 Esc 可取消;未绑定的后续步骤会显示“未绑定宏”错误。宏也会在帮助浮层(?)中显示。

exec_on_new 通知

在每次刷新后,对每个新出现的项目执行一次命令。首次成功加载订阅源时,不会触发通知(仅作为种子)。后续刷新中,仅触发先前未见过的项目。

[[default_feeds]]
url = "https://example.com/feed.xml"
exec_on_new = 'notify-send "%t" "%u"'

相似文章

现代 feed 阅读器(2024)

Lobsters Hottest

作者分析了 RSS 源因抓取和干扰而衰退的问题,认为现代 Feed 阅读器必须整合替代的聚合方式才能保持相关性。