每台设备都拥有完整的阅读库。
云端可以提供帮助,但不会成为唯一的数据源。阅读、收藏、搜索与知识记录都先从设备本地开始。
同步操作与字段时钟
设备交换持久意图与用户状态,不复制 SQLite 文件、文章正文、索引或模型缓存。
沿着合并路径往下看 ↓Connector 先声明自己需要什么
带版本的 descriptor、统一内容模型与受约束网络上下文,把来源适配和本地存储分开。
查看契约细节 ↓一套界面,可替换的数据 Adapter
React 依赖平台能力与 Reader Repository,不直接判断操作系统,也不绑定某一种数据库 transport。
查看 Adapter 层次 ↓桌面与 Web 当前仍以本地 Node API 为完整生产路径。移动 SQLite Adapter 已能编译,但完整阅读路径切换与真实设备验证尚未完成。
当前源码中存在,并通过已有构建或测试验证。
可选默认关闭,或只在用户主动配置后使用。
早期基础今天已经有用,但范围刻意小于未来的完整系统。
尚未发布共享实现已经存在,打包、签名、商店或设备验证仍未完成。
文章开始以后,阅读器安静退后。
已经实现Rinwa 围绕阅读,而不是提醒压力来组织订阅。未读通过字重与颜色表达;操作只在需要时出现,不用红点把每篇文章变成任务。
保留原文结构
标题、段落、列表、引文、代码、表格、图片和媒体按原来的顺序呈现。全文抽取异步进行;刷新失败时,缓存或 Feed 内容仍然可以阅读。
今天、未读、收藏与单订阅
智能视图与分组、单订阅阅读并列存在。订阅可以不进入聚合首页,但不会因此被删除;未读数量保留在本机。
健康状态、历史与偏好
可查看最近尝试与成功时间、HTTP 状态、连续失败、文章总数与新增数,并设置分组、目标语言和自动 AI 偏好。
OPML 导入与导出
导入包含预览、选择、重复处理与分组保留;导出仍是普通 OPML,让其他阅读器可以理解。
站点图标与安静回退
能够取得时显示站点 favicon;加载失败时使用简洁的来源首字,不留下破损图片。
用键盘完成导航与操作
打开智能视图、分组、订阅与保存搜索;添加或管理订阅;切换已读和收藏;打开原文;或把当前列表全部标记已读。搜索词同时包含中英文别名。
RSS、Atom、JSON Feed 与内置 Connector 都进入统一内容模型。
先保存 Feed 副本;全文抽取可以改进它,但不会删除上一份成功正文。
智能视图与来源视图共用同一套阅读器、键盘、触控和触控板交互。
原文不等待译文。
可选 · 需要同意文章先显示原文。译文异步出现在对应段落下方,保留原文作为证据,而不是把页面替换成另一种语言。
结构、媒体、链接与可执行代码仍属于作者原文。
对齐在原文下方;失败不会遮住原文。
跳过规则
中文、代码与预格式化区块、只有 URL 的内容、日期、数字、纯标点和没有自然语言价值的文本不会送去翻译。
每个订阅独立语言
每个订阅保存自己的目标语言。自动翻译按订阅单独开启,并在全文缓存完成后运行。
Provider 可选择
可以使用环境配置、DeepL、OpenAI-compatible 翻译或自定义端点。Provider 与模型设置不会侵入阅读表面。
没有翻译服务时,Rinwa 仍是完整的本地阅读器。开发环境中的确定式回退不会被包装成高质量人工翻译。
全文确定性,加上语义召回。
向量索引需主动开启SQLite 全文检索始终可用。本地向量启用并准备好以后,语义通道会并行运行;最后用 Reciprocal Rank Fusion 合并两边排序,不让向量模型成为搜索的单点故障。
ONNX Runtime 可以从本地 buffer 或 URL 加载模型,也支持执行 Provider 的降级解析。Rinwa 当前使用 Transformers.js 带来的 Node 侧运行时,并没有宣称所有客户端都已走 WebGPU。
先组织证据,再调用 Provider。
BYOK · 需要同意AI 辅助首先在本地构造有限上下文。短文章可以使用全文,长文章与全库问题则先检索段落;文章坐标和知识记录会先变成引用 ID,再交给用户选择的服务。
摘要、文章、文章+知识或全库
范围由用户明确选择。短文章可以完整进入上下文;长文章与全库问题在固定输入预算内检索相关段落。
段落、划线与全库引用
文章段落使用 [P],保存划线使用 [H],其他文章使用 [S]。没有出现在本次上下文中的引用 ID 会在展示前移除。
近期原文+有界滚动记忆
最近消息在单条预算内保留原文;更早的用户问题压缩成简短提醒,旧的助手回答不会被当作证据。
简洁、平衡或深入
可以选择回答语言、风格、上下文范围、引用、temperature、token 上限,以及 Provider 支持的 reasoning effort。
OpenAI、OpenRouter、Ollama 或自定义
Rinwa 通过 OpenAI-compatible /models 发现模型,并传递受支持的 reasoning effort,不把界面绑定到单一厂商。
本地阅读仍然可用
非 AI 路径与开发环境保留确定式本地回退。没有配置服务,只意味着没有外部回答,不会让内容库失效。
每个订阅的自动翻译与自动摘要默认关闭,需要当前版本的数据共享同意,并显示后台 token 成本提示。AI 可以建议笔记内容,但不能未经确认直接修改。
一个问题,可以变成长期更新的阅读流。
已经实现保存搜索把结构化本地查询变成持续更新的虚拟订阅。它出现在智能视图旁边,拥有自己的未读数量,并使用普通文章列表与阅读器。
可解释的筛选
V1 使用 AND 条件,不用不透明的 AI 规则:关键词、订阅、分组、作者、域名、已读状态、收藏、24 小时 / 7 天 / 30 天与标签。
设备之间可迁移
查询保存订阅的稳定 global ID,而不是某台设备的数据库行号,因此可以通过 operation log 同步。
共享查询基础
服务端使用同一个 resolver,让侧栏、未读数、全部标记已读、备份、同步和未来自动化保持同一套含义。
宁可暂时无法定位,也不画错位置。
已经实现Rinwa 保存选中文字与有限的前后文。当全文抽取改变 HTML 时,会跨区块与行内元素保守地重新定位完全匹配的规范化文本。
分段行内标记
一处划线可以跨多个文本节点或行内元素。Rinwa 把它渲染成一个可访问的逻辑划线,不会把文章结构压平。
前后文消歧
重复句子会根据保存的 prefix 与 suffix 评分。证据太弱或为空时保持未定位,不会直接选择最早出现的位置。
跳转到原文
选择保存划线后,知识面板先关闭,再把对应原文标记滚动到阅读区中央,并遵守减少动态效果偏好。
只读弹出层
激活标记后显示保存的附注,或者安静的“无附注”状态。V1 不在这里提供编辑或单条划线删除。
阅读结果可以离开应用。
已经实现收藏文章可以带有可编辑摘要、个人笔记、标签、划线、译文摘录与外部引用。这些是用户数据,不是可以随时清理的 AI 输出。
Obsidian 双向往返
Rinwa 只写入清楚标记的受控区块,保留周围的用户 Markdown;Vault 中的修改可以通过本地同步 worker 回到 Rinwa。
安全移除
移除知识条目会取消收藏并删除对应受控记录。导出的 Vault 文件默认保留,只有用户明确勾选时才一起删除。
stdio 本地 MCP
独立本地进程向 AI agent 提供订阅、文章、搜索、知识、标签、统计、健康状态与 OPML。安全写入需要本地 token;破坏性操作和 Rinwa 的外部 AI 调用不会暴露。
MCP 通过 Rinwa 本地 HTTP API 工作,不直接打开 SQLite。它面向桌面与本地开发环境,不作为移动端进程运行。
插件边界,先从更少权限开始。
P0/P1 基础SourceConnector 把特定来源的发现和拉取,与 Rinwa 数据库分开。RSS 与公开 YouTube 通过同一个 registry factory 注册,也实现未来 Connector 会使用的同一套接口:probe、discover、resolveSubscription 与 pullEntries。
fetch();没有数据库或文件系统句柄
Capability 描述行为
V1 契约识别发现、URL 解析、增量拉取、认证、内嵌正文与媒体资源。未知能力会让 descriptor 校验失败,不会悄悄扩大权限。
网络与节奏显式声明
Descriptor 包含允许访问的 host、最小请求间隔、最大并发与可选分页大小。当前 Host 创建 fetch context 时会使用声明的网络 host。
SDK 不依赖应用实现
Descriptor、订阅意图、内容条目、媒体资源、请求响应与 JSON 消息 ABI 都位于 packages/connector-sdk,存储仍由 Host 负责。
这些层级目前是权限词汇,不代表正文接口已经开放。两个内置 Connector 都只声明 query 与 source-id;当前 ConnectorContext 根本没有提供 article body API。
每一跳都重新检查
Redirect 由 Host 手动跟随。下一次请求前会再次检查协议、声明的 host 策略与公网地址,不能只验证起点。
拒绝私有网络
Loopback、私网、link-local、运营商级 NAT、云 metadata 以及对应 IPv6 范围都会被拒绝,避免 Connector 成为访问用户局域网的通道。
限制响应边界
Direct context 最多跟随 5 次跳转,正文上限 8 MiB,请求超时 15 秒。跨 origin 跳转时会移除敏感 header。
规范化以后再存储
Connector 输出进入 RSS 也使用的 ingestion service,让稳定 ID、内容哈希、媒体、抽取策略与后续索引保持同一含义。
RSS 与 YouTube 证明这套接口确实在用,不只是计划。但 Connector 仍内置在 API 进程中:还没有第三方包加载器,也没有针对任意代码的安全沙箱。DNS rebinding 也仍有已记录的 TOCTOU 限制,要等到解析地址能固定到实际 socket 才能消除。
既能带走,也能带回来。
已经实现备份与同步彼此独立。可以只保存易读的订阅配置,也可以创建包含用户阅读与知识数据的完整加密快照。
可读导出
订阅、分组、聚合设置、目标语言与自动 AI 偏好以明文文件导出。
AES-256-GCM
口令经过 scrypt 加强,再使用随机 salt、nonce 与带认证的加密保护完整备份。
合并或替换
合并会在适当位置保留本地记录;替换在事务中执行,避免留下只完成一半的破坏性状态。
桌面本地文件夹
可以每天或每周写入用户选择的文件夹,保留指定数量,并把口令放在操作系统安全存储中。
Web 开发模式提供手动下载与上传。当前备份实现不包含移动端后台定时。
同步操作,不复制数据库文件。
可选服务器每台设备都能独立使用。本地修改在上传前先记录成 operation,包含稳定 ID、实体、动作、JSON payload、设备序列、时间与 HLC 排序键。服务器中继日志;每台客户端再把它合并进自己的 SQLite。
记录
deviceId:sequence、实体、动作、payload、时间和 HLC 先写入本机。
中继
服务器验证有界批次;重复 operation ID 只会成为无害的 CouchDB conflict。
按字段合并
sync_field_clocks 为每个实体字段保存一枚 HLC;shouldApplyField 只推进更晚到达的那个字段。
记住删除
deleted 字段时钟在数据行消失后仍保留。旧 upsert 不能复活它,真正更新的重新添加可以。
当前协议实体
connector_subscriptionfeedhighlight
item_stateitem_summaryknowledge
preferencesread_later_capturereading_position
rulesaved_search
createHlc() 生成的排序键
epochMillis:sequence:deviceId
13 位 epoch 毫秒提供大致时间顺序。
每设备 sequence 让同一毫秒内产生的多次操作也能有序。
device ID 让时间与序列都相同时,在所有客户端得到相同比较结果。
只用墙上时钟会产生相同时间戳,不同设备也可能对当前时间意见不一。Rinwa 当前的 HLC 形态键保证确定式字符串排序,但不会消除时钟漂移:设备时间严重错误时,仍可能影响同一字段哪次写入被认为更新。
isRead = true推进 isRead 时钟isStarred = true推进 isStarred 时钟朴素的整行 last-writer-wins 会覆盖整条 item state,让其中一次修改丢失。Rinwa 分字段比较;只有两台设备修改同一字段时,才由更新的 HLC 决定结果。
传订阅与 URL,不传抓取正文
Connector 订阅携带来源身份与设置;稍后读携带 URL 与 capture 时间。接收设备各自在本地抓取和保存结果,减少私密正文复制与带宽消耗。
必须一致的值共用一枚时钟
阅读位置用一个 anchor 时钟覆盖文章 ID 与排序键;稍后读用一个 capture 时钟覆盖 URL 与 capture 时间,避免把两次写入拼成一组。
日志记录意图,Service 完成工作
新导入订阅会在本机安排抓取;稍后读的网络抓取离开 apply loop 排队执行,不让 operation 应用变成破坏性或阻塞步骤。
Tombstone 决定删除还是重新添加
Feed、知识、Connector、保存搜索、阅读位置、规则、划线与稍后读的删除路径都会推进 deleted,阻止旧快照把记录复活。
Feed 与 Connector 意图 · 文章状态与摘要 · 知识与划线 · 阅读偏好与位置 · 规则 · 保存搜索 · 稍后读 capture
文章正文 · 抽取 HTML · 媒体 · 翻译 · 模型文件 · 向量 · 全文与向量索引
Rinwa 由 kappain 以开源阅读器的方式开发;托管 Rinwa Sync 是计划中的商业服务。本地阅读不依赖它,自托管能力也继续留在协议边界内。
服务器可以创建 Qdrant Collection,但协议仍明确返回 semanticSearch: false。当前语义检索发生在本地,远端集合存在不等于功能已经上线。
应用版本与内容版本彼此独立。
核心约束每台设备以 SQLite 作为主要存储。修改界面、增加设置或修复手势不会清空文章;正文抽取、翻译、生成摘要和向量分别拥有自己的兼容版本。
翻译、摘要与问答在当前数据共享版本被接受前不会发送内容;用户可以撤回同意。
打包桌面客户端使用操作系统安全存储保存 Provider Key 与同步 token。旧明文字段只用于迁移,不是继续复制的设计。
文章正文、prompt、API Key、同步 token 与 Vault 内容都不应记录。
已有数据库原地升级;开发过程不会删除或重建用户内容库。
笔记、标签、划线、引用与手工编辑摘要不会被当作可丢弃的生成缓存。
OPML、Obsidian 与备份提供真正可用的离开路径。
一套界面,两处可替换边界。
移动端尚未发布React 与 Vite 提供共享阅读表面,Tauri 2 将它交付到桌面与移动端。存储 transport 隐藏在 ReaderRepository 后面;运行时能力隐藏在 PlatformAdapter 后面。组件应该询问“能做什么”,而不是判断操作系统名字。
listFeeds · getItems · 写操作tauri-plugin-sqlRepository 在运行时选择
getReaderRepository() 只在壳报告 native API transport 且存在本地 SQL 能力时选择 SQLite;其他环境都得到 HTTP 实现。
接口刻意保持窄小
当前阅读核心覆盖订阅列表、文章查询、已读/收藏、订阅设置与删除。AI、知识、OPML 和同步仍是接口之外的远端操作。
切换尚未完成
主要订阅读取与订阅设置写入已经通过 Repository;分散的文章状态调用、iOS/Android 真机验证,以及移动数据库填充路径仍未完成。
浏览器 Adapter 在合适位置返回 false 或 null,安全存储与应用内浏览不可用时抛出 PlatformCapabilityError。原生壳可以覆盖 capability map,不需要假装每个平台都已完成。
共享界面与桌面壳已经存在,包括原生窗口、目录选择、SQLite Bridge、安全存储基础和原生网页窗口;目前仍没有签名、notarized 的正式安装包。
共享界面可以打包,但本地 SQLite 完整切换、Keystore、后台刷新、真实设备验证、签名与商店发布仍未完成。
它们复用同一套 React/Tauri 架构;原生构建、数据库填充、签名、设备验证与分发流程仍未完成。
实现细节直接由产品仓库文档生成。
构建校验下面的页面来自 feedsuite 中选定的 Markdown 文档。官网构建会自动重新生成页面、检查站内链接并打包产物,不再需要在两个仓库里手工复制。
当前页面继续负责清晰解释产品;参考页承载更细的实现信息,并链接到 GitHub 中的源文档。
已经实现,不等于已经发布。
阅读与订阅管理、OPML、原文优先翻译、多 Provider AI、本地混合检索、保存搜索、稳定划线锚点、知识与 Obsidian、本地 MCP、P0/P1 Connector 与 YouTube、加密备份、operation log 同步、命令面板和共享响应式 UI。
本地向量需主动开启;AI 与同步需要配置;Connector 是 P0/P1 内置基础,不是市场;Android 是开发预览。
移动端原生后台刷新、完整 Android Keystore 验证、移动 SQLite 全面切换与填充、签名/notarized macOS 安装包、iOS 与 Windows 正式包、商店提交,以及第三方 Connector 市场。
需要实现级别的细节?
在 GitHub 阅读源码 ↗