Malo RSS 订阅助手 —— 一款轻量级信息聚合工具,帮你管理和阅读来自任意网站的信息流。 提供 Chrome 浏览器扩展 和 macOS 桌面应用(Electron) 两种形态,共享同一套 UI 和业务逻辑。 支持标准 RSS/Atom 源,也能抓取无 RSS 输出的普通博客和 JS 渲染页面。
Malo RSS 订阅助手是一个 100% AI Coding 项目 —— 从架构设计、功能实现、UI 样式到 Bug 修复,所有代码均由 AI 编程助手(CatPaw / Cursor)生成,未手写任何一行代码。人工仅负责提出需求、验收效果和测试反馈,全程以自然语言驱动开发。
| 文章列表 | 订阅源管理 |
|---|---|
![]() |
![]() |
| 发现页面 | AI 设置 |
|---|---|
![]() |
![]() |
| 分类 | 功能 |
|---|---|
| 📥 订阅管理 | 添加 / 删除 RSS 源,支持直接粘贴 RSS 地址或普通博客网址 |
| 🔍 智能检测 | 自动识别源类型(RSS / 静态网页 / JS 渲染页面)并缓存 |
| 🔄 后台抓取 | 定时自动抓取(默认 15 分钟),并发上限 3 |
| 🗂️ 三栏 UI | 文章、订阅源、AI 设置 —— 信息一目了然 |
| 🔎 筛选搜索 | 按来源筛选、关键词搜索、收藏过滤 |
| ⭐ 文章收藏 | 星标收藏文章,"只看收藏"模式不受列表数量限制 |
| 🤖 AI 文章解读 | 集成 OpenAI 兼容 API,一键 AI 总结与深度解读文章内容 |
| 💬 AI 问答对话 | 解读完成后可基于文章内容继续提问,支持多轮对话、快捷提问 |
| 📝 总结当前网页 | 一键总结当前打开的网页,自动提取正文并通过 AI 生成摘要(仅 Chrome 扩展) |
| ⚙️ 自定义 Prompt | 支持自定义 AI 系统提示词,灵活控制解读风格 |
| 🌐 发现页面 | 自动检测当前页面中的 RSS/Atom 源与网页文章,一键订阅(仅 Chrome 扩展) |
| 🔔 未读角标 | 扩展图标 / Dock 图标实时显示未读条目数 |
| 🖥️ 桌面应用 | macOS 原生应用体验,系统托盘、菜单栏、窗口管理 |
| 🌗 深色模式 | 深色 / 浅色主题切换,偏好自动保存 |
- Node.js >= 18
- npm >= 9
git clone git@github.com:MrKiven/malo.git
cd malo
npm installnpm run build:extension构建完成后,dist/ 目录即为完整的 Chrome 扩展(已自动包含 manifest.json 和 assets/)。
- 打开
chrome://extensions/ - 右上角开启 「开发者模式」
- 点击 「加载已解压的扩展程序」
- 选择项目下的
dist/目录
npm run dev启动 Vite watch 模式,修改源码后自动重新编译。编译完成后到 chrome://extensions/ 点击扩展的 🔄 刷新按钮即可生效。
npm run pack:extension会在 release/ 目录生成 rss-chrome-extension-<版本号>-<时间戳>.zip,可直接上传到 Chrome Web Store。
npm run build:app构建完成后,dist/ 为渲染进程资源,dist-electron/ 为主进程代码。
npm run app注意:如果在 Cursor / VS Code 等 Electron 应用的终端中运行,环境变量
ELECTRON_RUN_AS_NODE=1会导致 Electron 以纯 Node.js 模式启动。app脚本已自动处理此问题。如需手动运行,请先执行unset ELECTRON_RUN_AS_NODE。
npm run pack:app在 release/ 目录生成 .dmg 和 .zip 安装包。
npm run dev:app启动 Vite dev server + Electron,支持热重载。
项目在 feeds/ 目录下内置了精选订阅源文件(rss-feeds-<日期>.json),涵盖 Cursor、Claude、Windsurf、Cline、Zed、JetBrains 等 AI 编程工具的官方博客,开箱即用:
- 安装并打开扩展或桌面应用,切换到 订阅源 标签页
- 点击 导入 按钮,选择
feeds/目录下日期最新的 JSON 文件 - 导入完成后会自动开始抓取,稍等片刻即可在 文章 标签页浏览最新内容
💡 建议始终导入日期最新的文件以获取最完整的订阅源列表。你也可以在订阅源标签页点击 导出 按钮,随时备份自己的订阅列表。
| 标签页 | 说明 |
|---|---|
| 文章 | 浏览最新条目;按来源 / 关键词筛选;点击星标收藏;"只看收藏"模式展示全部收藏文章 |
| 订阅源 | 输入 RSS 或博客网址点击"添加";管理已订阅列表,支持按类型排序、删除(二次确认) |
| 发现 | 自动检测当前页面中的 RSS 源和网页文章内容,均可一键订阅(仅 Chrome 扩展) |
| AI 设置 | 配置 AI API 地址、Key、模型和自定义 Prompt;支持连接测试 |
💡 小提示:筛选某个来源时会显示该源的全部条目(不受列表数量限制)。文章条目整行可点击跳转原文。
- 在 AI 设置 标签页中配置 API 地址、API Key 和模型
- 配置完成后,文章列表中每篇文章会出现 AI 总结 按钮
- 点击按钮会打开独立窗口进行 AI 解读(不受插件弹窗关闭影响)
- 支持流式输出、停止生成、重新生成、复制内容
- 可自定义 Prompt 控制解读风格,留空则使用默认的「核心摘要 + 关键要点 + 值得注意」结构
- AI 解读完成后,底部自动出现对话输入框和快捷提问按钮
- 内置常用快捷提问:
核心观点、通俗解释、质疑与不足、延伸阅读,一键发送 - 也可以手动输入任意问题,按 Enter 发送(Shift+Enter 换行)
- AI 会基于文章内容和之前的解读进行流式回答,支持多轮连续对话
- 对话过程中可随时停止生成;历史自动保留最近 10 轮对话
- 配置好 AI 后,工具栏右上角会出现 AI 总结 按钮
- 在任意网页上点击此按钮,即可自动提取页面正文并由 AI 生成摘要
- 通过注入脚本提取内容,优先识别
<article>、<main>等语义区域,过滤导航、广告等无关元素 - 若注入失败(如 chrome:// 页面),会自动回退到 fetch 抓取方式
支持任何 OpenAI 兼容的 API 接口(OpenAI、DeepSeek、Moonshot、Qwen 等),API Key 仅保存在本地。
| 类型 | 说明 | 适用场景 |
|---|---|---|
rss |
标准 RSS/Atom XML 解析 | 提供 RSS 输出的站点 |
page |
正则抓取静态 HTML 中的文章链接 | 无 RSS 的博客 / 新闻站 |
page-js |
后台标签页注入脚本,抓取 JS 渲染内容(仅 Chrome 扩展) | SPA、动态加载页面 |
首次添加源时自动检测类型并缓存,后续按已知类型直接抓取。
malo/
├── manifest.json # Chrome 扩展 MV3 配置
├── package.json # 依赖与脚本(dev / build / pack)
├── tsconfig.json # TypeScript 严格模式与路径别名
├── vite.config.ts # 扩展构建(Vite)
├── vite.electron.config.ts # 桌面版构建(Vite + Electron)
├── electron-builder.json5 # 桌面应用打包(macOS DMG/ZIP)
├── build.sh # 扩展打包脚本(产出 zip)
├── _gen_icons.py # 图标生成(扩展 + 桌面 + 托盘)
├── STORAGE.md # 存储结构说明(可选阅读)
├── feeds/ # 预置订阅源(rss-feeds-<日期>.json,导入最新即可)
├── assets/
│ ├── icons/
│ │ ├── extension/ # 扩展图标 16 / 48 / 128
│ │ ├── app/ # 桌面图标 icns、托盘 template
│ │ └── *.svg # 界面用矢量图标
│ └── screenshots/ # README 截图
├── electron/ # 桌面版主进程
│ ├── main.ts # 入口、窗口、生命周期
│ ├── preload.ts # 预加载(contextBridge 暴露 IPC)
│ ├── ipc-handlers.ts # IPC:storage / fetch / window
│ ├── storage.ts # electron-store(sync + local)
│ ├── fetcher.ts # 定时抓取(Node fetch)
│ └── tray.ts # 菜单栏托盘与右键菜单
├── dist/ # 构建产物:扩展包 / 桌面版渲染资源
├── dist-electron/ # 构建产物:桌面版主进程
└── src/
├── platform/index.ts # 平台抽象(Chrome / Electron 自动切换)
├── types.ts # 共享类型
├── constants.ts # 常量
├── utils/ # 工具函数
│ ├── format.ts # 日期等格式化
│ └── html.ts # HTML 处理
├── popup/ # 主界面(四栏:文章 / 订阅源 / 发现 / 配置)
│ ├── index.html
│ ├── index.ts # 入口与模块协调
│ ├── theme.ts # 深色 / 浅色主题
│ ├── tabs.ts
│ ├── feeds.ts # 订阅源列表
│ ├── feeds-io.ts # 导入 / 导出
│ ├── feeds-dnd.ts # 拖拽排序
│ ├── articles.ts # 文章列表、筛选、收藏、已读
│ ├── articles-render.ts # 列表 DOM 渲染
│ ├── articles-ai.ts # 打开 AI 解读
│ ├── detect.ts # 发现页(RSS 检测、网页订阅)
│ ├── ai-settings.ts # AI 配置面板
│ ├── sync.ts # 插件 / 桌面数据同步
│ └── shared.ts # Toast、Loading、状态文案
├── ai-panel/ # AI 解读独立窗口
│ ├── index.html
│ ├── index.ts # 总结流程与 UI 控制
│ ├── summarize.ts # 内容提取 + 流式调用
│ ├── markdown.ts # Markdown 渲染
│ ├── chat.ts # 多轮问答
│ └── ui.ts # 解读窗口 UI 组件
├── background/ # Chrome Service Worker
│ ├── index.ts # 定时抓取、类型检测、标签页注入
│ ├── fetcher.ts # 扩展侧抓取逻辑
│ └── utils.ts
├── detector/ # Content Script(注入到网页)
│ └── index.ts # RSS 源与文章内容检测
├── services/ # 业务逻辑(无 DOM)
│ ├── storage/ # 存储封装与迁移
│ │ ├── index.ts
│ │ ├── feeds.ts
│ │ ├── items.ts
│ │ ├── favorites.ts
│ │ └── helpers.ts
│ ├── ai.ts # AI 请求与 SSE 解析
│ ├── content.ts # 正文提取(HTML / PDF)
│ ├── parser.ts # RSS/Atom 解析
│ ├── scraper.ts # 静态 HTML 文章链接抓取
│ └── page-scraper.ts # 单页抓取(含 JS 渲染)
└── styles/ # 模块化 CSS
├── variables.css # 主题变量
├── base.css # 全局与桌面适配
├── components.css # 按钮、卡片、输入框等
├── header.css
├── tabs.css
├── feeds.css
├── articles.css
├── discover.css
├── ai-panel.css
└── ai-settings.css
项目通过 src/platform/index.ts 实现了一套平台抽象层,统一封装了 storage、runtime、tabs、scripting、windows 等 API。运行时根据 window.electronAPI 是否存在自动选择 Chrome 或 Electron 实现,UI 层代码完全无需感知运行平台。
┌─────────────────────────────────┐
│ UI 层 (popup/) │
│ articles / feeds / ai-settings │
└──────────────┬──────────────────┘
│ platform.*
┌──────────────┴──────────────────┐
│ 平台抽象层 (platform/) │
├─────────────┬───────────────────┤
│ Chrome 实现 │ Electron 实现 │
│ chrome.* │ electronAPI.* │
└─────────────┴───────────────────┘
- Popup(渲染层)→
chrome.runtime.sendMessage→ Service Worker(后台抓取、标签注入) - Content Script 注入到目标页面检测 RSS 源
- Renderer(渲染层)→ IPC(
contextBridge)→ Main Process(后台抓取、窗口管理、系统托盘) - 数据通过
electron-store持久化到本地文件 - 后台抓取使用 Node.js
fetch,无需浏览器标签页 page-js抓取模式和「发现」功能在桌面版中不可用
| 技术 | 说明 |
|---|---|
| TypeScript | 全量类型标注,strict 模式 |
| Vite | 多入口构建,自动处理 HTML/CSS/TS |
| Chrome Extension MV3 | Service Worker、Content Script、chrome.storage API |
| Electron 40 | macOS 桌面应用,主进程 + 渲染进程架构 |
| electron-store | Electron 本地持久化存储 |
| electron-builder | 桌面应用打包(DMG / ZIP) |
| 纯 DOM 操作 | 无前端框架依赖,轻量快速 |
| 存储类型 | 内容 | 说明 |
|---|---|---|
chrome.storage.sync |
订阅源列表、源类型、收藏、主题偏好、AI 配置 | 登录同一 Google 账号即可跨浏览器同步 |
chrome.storage.local |
文章缓存 | 数据量大,可重新抓取恢复 |
| 存储类型 | 内容 | 说明 |
|---|---|---|
electron-store (sync-data) |
订阅源列表、源类型、收藏、主题偏好、AI 配置 | JSON 文件,存于 ~/Library/Application Support/malo-rss/ |
electron-store (local-data) |
文章缓存、已读状态 | 同上 |
数据限制:
- 每个订阅源最多保留 50 条条目
- 合并视图(全部来源)默认显示 50 条;按来源筛选或只看收藏时展示全部
- Chrome 扩展:Sync 单 key 上限 8 KB,收藏文章摘要会自动截断;若超限自动回退到 local
- 某些站点可能存在 CORS / UA / 防爬限制,抓取失败属正常现象
page-js模式抓取时会在后台短暂创建标签页并自动关闭(仅 Chrome 扩展)- Chrome 扩展需要 Chrome 110+ 版本(Manifest V3)
- Electron 桌面版不支持「发现」功能和
page-js抓取模式(无浏览器标签页环境)
| 权限 | 用途 |
|---|---|
storage |
存储订阅源、文章缓存、用户偏好 |
alarms |
定时后台抓取 |
activeTab |
检测当前页面内容 |
scripting |
注入脚本抓取 JS 渲染页面 |
tabs |
后台标签页管理(page-js 模式) |
notifications |
新文章通知(预留) |
<all_urls> |
允许抓取任意站点的 RSS / 网页内容 |
| 脚本 | 说明 |
|---|---|
npm run dev |
Chrome 扩展开发模式(Vite watch) |
npm run dev:app |
Electron 开发模式(Vite dev server + Electron) |
npm run app |
启动 Electron 桌面应用 |
npm run build |
一键构建 Chrome 扩展 + Electron 应用 |
npm run build:extension |
Chrome 扩展生产构建 |
npm run build:app |
Electron 生产构建 |
npm run pack |
一键打包全部(Chrome .zip + macOS DMG/ZIP) |
npm run pack:extension |
Chrome 扩展打包为 .zip |
npm run pack:app |
Electron 打包为 macOS DMG/ZIP |
npm run clean |
清理所有构建产物 |



