乐于分享
好东西不私藏

我用纯 Swift 写了一个 AI 技术雷达,增加 AI读屏助手,一键将内容生成一张漂亮的结构化卡片,你老板的下巴都惊掉了

我用纯 Swift 写了一个 AI 技术雷达,增加 AI读屏助手,一键将内容生成一张漂亮的结构化卡片,你老板的下巴都惊掉了

聚合 Hacker News、GitHub Trending、arXiv、Product Hunt 四大技术社区,用 AI 生成趋势报告;

生成趋势报告

为了方便分享给同事查看,我加了复制为图片的功能,这样就可以直接吧这个趋势分享给同事和领导了,方便的一比。

可以分享的趋势报告
深度解读的能力
单篇文章深度解读
解读后的效果

为了便于分享给同事,朋友,领导,对技术感兴趣的妹子,我也做了复制为图片

复制后之后的效果
为了追求不太好调节的美观,我做了自定义主题

这两天重点就是在打磨一个快捷键截屏,把屏幕上的任何信息变成结构化认知卡片

可以对你截图进行分析

这个分析是自动识别你截图的内容的,OCR 直接使用OS 的

import ScreenCaptureKitimport Visionimport CoreGraphics

所以,这块完全就无依赖。

这是分析之后的效果,结构化,清晰好理解

这是这两天 Tech Brain 进化的故事,且听我娓娓道来,搬好板凳。

还是先说说,我为什么要做这个工具

作为一个技术人,我每天的信息焦虑来自两个方向:

第一,技术趋势追不过来。 Hacker News 要刷,GitHub Trending 要看,arXiv 上的 AI 论文要跟,Product Hunt 上的新产品要关注。四个站点,四种信息格式,每天花 30 分钟都嫌不够。

第二,屏幕上的信息用不起来。 群里一段讨论,看完就忘了谁说了什么结论;领导发了一段话,到底是要我干什么;一个报错截图,每次都要自己逐行分析;开完会截了个屏,会议纪要还是要手动整理。

我需要的不是又一个 RSS 阅读器,也不是又一个 OCR 工具。我需要的是:AI 帮我把信息变成判断,把截图变成行动。

于是我用 Swift 写了 Tech Brain ,一个跑在 macOS 上的 AI 技术雷达 + 读屏助手。

我还有好多的 TODO ,比如,我需要管理的粘贴版,我需要…,算了,兑现了再说

我们这个 swift 版本的技术雷达,它能做什么

Tech Brain 有两条核心能力线:

能力一:AI 技术趋势雷达

同时聚合四大技术社区的实时内容:

数据源
获取方式
内容
Hacker News
Firebase REST API
Top 30 热门文章
GitHub Trending
HTML 页面解析
每日趋势仓库
arXiv
Atom XML API
AI/ML/NLP 最新论文
Product Hunt
GraphQL API + RSS 降级
最新产品

四个源的数据汇入统一的 Feed 列表,支持按来源筛选、全局搜索、已读/未读状态管理。

当然,我这里是可以扩展的,我后面想把他做成配置,自己定义更多的源上来。

然后在此基础上,AI 提供三种分析模式:

  1. 1. 每日趋势报告 —— 把当天所有 Feed 喂给大模型,生成热点解读、趋势分析、技术预测和开发者行动建议。SSE 流式输出,边生成边看。
  2. 2. 单条深度解读 —— 对任意一条 Feed 右键,AI 给出”它是什么 → 为什么值得关注 → 对开发者的影响 → 要不要跟进”的四维分析。
  3. 3. 技术热度雷达 —— AI 对 10 个技术方向(AI/LLM、Web、移动端、云原生、Rust/系统、数据库、安全、开源工具、Web3、量子计算)打分 0-100,标注上升/稳定/下降趋势,生成可视化雷达图。

你还可以配置定时任务,每天自动抓取 + 生成报告 + 推送到飞书群,团队里的人早上打开群就能看到今天的技术趋势摘要。

能力二:AI 读屏助手

这是我最喜欢的功能。一句话概括:

按下快捷键 → 框选屏幕区域 → AI 自动识别内容 → 生成一张漂亮的结构化卡片。

完整流程是这样的:

⌥ + Space 触发(可以自定义快捷键)   → 全屏半透明遮罩,鼠标拖拽选区   → 本地 OCR 识别文字(Apple Vision,不上传图片)   → AI 判断内容场景   → 用户确认或切换场景   → AI 按场景生成 HTML 卡片 + Markdown   → 复制为图片 / 复制 Markdown / 保存文件

内置 8 个分析场景,每个场景有专属的 Prompt 模板和卡片结构:

场景
识别内容
生成卡片
代码报错
IDE/终端/CI 报错
错误定位 + 原因分析 + 修复方案
聊天讨论
微信/飞书/钉钉对话
核心结论 + 待办 + 回复建议
技术评审
架构图/方案文档
方案要点 + 风险 + 评审建议
会议纪要
会议记录/讨论截图
议题 + 共识 + 争议 + 行动项
周报素材
看板/任务/进展
本周进展 + 风险 + 下周计划
领导消息
上级指示/问询
关注点 + 必须响应 + 交付物 + 回复建议
需求拆解
PRD/用户故事
用户故事 + 边界条件 + 验收标准
待办提取
任务清单/TODO
结构化待办 + 优先级 + 责任人

卡片输出为精美的个性化的卡片,支持 8 种场景主色、明暗主题切换。同时生成 Markdown 版本,方便粘贴到飞书文档、Notion 或任何笔记工具。

使用场景:它解决了哪些真实痛点

可以对你截图进行分析

场景一:早上 5 分钟了解技术圈发生了什么

打开 Tech Brain,点一下”生成趋势报告”,AI 把四个社区的信息浓缩成一篇结构化分析。哪些项目在 GitHub 上火了,HN 上在讨论什么,arXiv 有什么新论文,Product Hunt 上线了什么新产品——一次性看完。

配合飞书推送,这个报告可以自动发到团队群里,省掉”今天技术圈有什么新闻”的群聊问答。

场景二:群里一段讨论,秒变会议纪要

群聊截图 → ⌥ + Space → 框选 → AI 自动整理成”讨论主题 / 主要观点 / 已达成共识 / 争议点 / 行动项”。直接复制成图片发回群里,或者粘贴 Markdown 到文档。

场景三:领导发了一段话,拆解出行动项

领导消息往往需要”读懂”。截图一段领导的话,AI 帮你分析:他真正关心什么、哪些要马上响应、哪些可以后续补充、应该产出什么材料、怎么回复比较稳妥。

场景四:一个报错截图,直接给修复方案

不管是 Xcode 编译失败、终端命令报错还是 CI/CD 构建失败,截图扔给 AI,拿回来的是:错误类型 → 可能原因 → 定位步骤 → 建议命令 → 最小修复方案。

场景五:需求文档截图,自动拆成 SPEC

产品经理发来一段需求描述,截图后 AI 直接生成:用户故事 → 输入输出 → 边界条件 → 验收标准 → 前后端改动点 → 测试要点。

技术实现,这部分也许是你最关心的

零第三方依赖

整个项目没有引入任何第三方库。没有 Alamofire,没有 SwiftyJSON,没有 Kingfisher。纯 Apple 框架:

  • • 网络请求:URLSession
  • • UI:SwiftUI
  • • 数据持久化:SwiftData
  • • 截屏:ScreenCaptureKit
  • • OCR:Apple Vision
  • • 密钥存储:Keychain
  • • 卡片渲染:WKWebView
  • • 并发:Swift Concurrency

安装包大小不到 3MB。在这个动辄几十 MB 的 Electron 应用时代,这是一个纯原生 App 该有的样子。

全 Actor 并发模型

所有的网络服务(HackerNewsService、GitHubTrendingService、ArxivService、ProductHuntService、OpenAIService、ScreenCaptureService、VisionOCRService、CardAnalysisService)全部声明为 actor

actor CardAnalysisService {    private let openAI = OpenAIService()    func suggestScene(ocrText: String, ...) async -> SceneType { ... }    func analyze(ocrText: String, scene: SceneType, ...) async throws -> CardDocument { ... }}

不需要手动加锁,不需要 DispatchQueue,编译器帮你保证线程安全。9 个 Service 类,零数据竞争。

搭配 TaskGroup 实现四个数据源的并发拉取:

await withTaskGroup(of: [FeedItem].self) { group in    group.addTask { await self.hackerNewsService.fetch() }    group.addTask { await self.gitHubService.fetch() }    group.addTask { await self.arxivService.fetch() }    group.addTask { await self.productHuntService.fetch() }    // ...}

状态机驱动的截屏流程

截屏 + OCR + AI 分析是一条复杂的异步链路,我们用一个显式的状态机来管理:

enum Stage: Equatable {    case landing           // 待机    case capturing         // 截图区域选择中    case recognizing       // OCR 识别中    case scenePicking      // 等用户选场景    case analyzing         // AI 分析中    case showingResult     // 展示结果    case failed            // 失败}

每个 Stage 对应一个视图面板,状态转换清晰可追踪。快捷键可以在任意非 capturing 阶段打断重来,不会产生竞态问题。

HTML + Markdown 双段输出协议

让 LLM 直接输出结构化 JSON 的痛点大家都体会过:格式校验失败、重试循环、schema 约束越加越复杂。

我们换了一个思路:让 LLM 输出 HTML + Markdown 双段文本,用分隔符切分。

<<<HTML>>><div class="container">  <div class="scene-banner">...</div>  <div class="card">...</div></div><<<MARKDOWN>>># 标题## 摘要...

HTML 天然是松散语义的,没有 JSON 那种”少一个逗号全盘报废”的脆弱性。我们预定义好 CSS 组件类(.card.scene-banner.badge.steps.todo.alert 等),LLM 只需要往里”填内容”,端侧用完整的 CSS 设计系统渲染。

解析器有 5 级容错策略,覆盖双 marker 存在、单 marker 存在、无 marker 但有 <div> 标签、纯文本等所有情况:

enum HTMLResponseParser {    static func parse(_ raw: String) -> Parsed {        // 1. 双分隔符都在 → 完美切两段        // 2. 只有 <<<HTML>>> → 剩余归 Markdown        // 3. 只有 <<<MARKDOWN>>> → 分隔符前归 HTML        // 4. 都没有但有 <div> → 整段当 HTML        // 5. 都没有也没 div → 当 Markdown,HTML 用 fallback 包裹    }}

这个设计的结果是:解析失败率趋近于零。 不再需要 JSON 重试 / sanitize / 校正循环。

18KB 手写 CSS 设计系统

卡片的视觉质量决定了用户愿不愿意分享。我们为 8 个场景手写了一套完整的 CSS 设计系统:

  • • Tailwind 风格的 utility class:间距、字号、颜色、圆角等原子类
  • • 语义化组件 class.card.scene-banner.badge.kvp(键值对)、.steps(步骤条)、.code-block(代码块)等
  • • 场景主色切换:通过 body[data-scene="codeError"] 切换 CSS 变量 --scene,8 个场景 8 种主色,LLM 写 .bg-scene 就能拿到当前配色
  • • 明暗主题body[data-theme="dark"] 一键切换
  • • CSP 安全策略default-src 'none',禁止加载任何外部资源,杜绝 XSS

LLM 不需要关心配色和样式,只需要用对 CSS class,端侧保证视觉一致性。

WKWebView 截图渲染管线

用户要的最终产物往往是一张图片——发到群里、贴到文档里。我们用 WKWebView 做了一条完整的截图渲染管线:

  1. 1. 创建一个离屏的NSWindow(用户看不到),挂载 WKWebView
  2. 2. 加载 HTML 内容,通过 JavaScript ResizeObserver 上报实际内容高度
  3. 3. 动态调整 WebView 尺寸,等内容渲染稳定(防抖 + 8 秒超时守护)
  4. 4. 调用 WKWebView 的 takeSnapshot,乘以 backingScaleFactor 实现 Retina 2x 高清输出
  5. 5. 写入 NSPasteboard 或通过 NSSavePanel 保存文件

优雅降级策略

健壮性体现在边界情况的处理上:

  • • Product Hunt 的 GraphQL API 需要 Token,拿不到自动降级为 RSS 解析
  • • SwiftData 的数据库 schema 如果不兼容(比如升级后字段变了),自动降级为内存数据库,不 crash
  • • 场景推荐失败时返回 .auto,让用户自己选,永不抛错
  • • AI 返回格式异常时,5 级容错保证总能解析出可用内容

全局快捷键 + 窗口协调

全局快捷键用 NSEvent.addGlobalMonitorForEvents 实现,需要用户授权辅助功能权限。按下快捷键后的窗口协调逻辑:

  1. 1. 隐藏所有 Tech Brain 的窗口(orderOut),避免遮挡用户屏幕
  2. 2. 弹出全屏透明遮罩,用户拖拽选区
  3. 3. 选区完成后,恢复窗口,切换到截屏分析 Tab
  4. 4. 如果用户按 Esc 取消,恢复窗口但不抢焦点

键盘布局适配使用 UCKeyTranslate + ANSI 键名 fallback,非拉丁键盘也能正确显示快捷键名称。

多模型兼容

多模型选择

通过 OpenAI-compatible API 协议,一套代码适配 7 种模型服务:

  • • DeepSeek(默认)
  • • OpenAI(GPT-4o、o1-mini、o3-mini)
  • • Kimi / Moonshot
  • • 通义千问
  • • 智谱 GLM
  • • Ollama(本地模型)
  • • 自定义端点(任何兼容 OpenAI 格式的服务)

API Key 存 Keychain,不存 UserDefaults,不写配置文件。

SSE 流式输出

AI 分析结果通过 SSE(Server-Sent Events)流式返回,使用 URLSession.bytes 的原生 AsyncSequence 逐行解析:

for try await line in urlSession.bytes(for: request).lines {    guard line.hasPrefix("data: ") else { continue }    // 解析 JSON,提取 delta content,拼接到结果中    // 同时通过 streamMarkdown() 实时提取可显示内容}

用户看到的是打字机效果的实时输出,而不是等待 30 秒后一次性显示。

我的架构总览

┌─────────────────────────────────────────────┐│                  SwiftUI Views              ││  MainTabView / FeedListView / TrendReport   ││  ScreenshotCardView / WebCardView / Settings│├─────────────────────────────────────────────┤│              @Observable ViewModels         ││  FeedViewModel / AIViewModel /              ││  ScreenshotCardViewModel                    │├─────────────────────────────────────────────┤│               Actor Services                ││  HackerNews / GitHub / arXiv / ProductHunt  ││  OpenAI / ScreenCapture / VisionOCR /       ││  CardAnalysis / Scheduler / Feishu          │├─────────────────────────────────────────────┤│              Apple Frameworks               ││  URLSession / ScreenCaptureKit / Vision     ││  SwiftData / Keychain / WKWebView           │└─────────────────────────────────────────────┘

每一层只依赖下一层,View 不直接调用 Service,ViewModel 持有 Service 引用并协调业务逻辑。

一些设计决策的思考

为什么用 HTML 而不是 JSON 作为 LLM 输出格式?

我们最初也是用 JSON Schema 约束 LLM 输出。但实际使用中发现三个问题:一是不同模型对 JSON 格式的遵守程度参差不齐,需要大量的后处理和重试;二是 JSON 的卡片类型体系越做越复杂,新增场景意味着新增 schema;三是视觉表现力有限,很难做到”一张图发到群里就能看”的效果。

切换到 HTML 后,LLM 的输出自由度大幅提升,容错性也好得多。我们只需要维护一套 CSS 组件库,LLM 用组件”搭积木”,端侧保证渲染质量。这其实是一种 “约束在 CSS 层,自由在内容层” 的设计哲学。

为什么不用 Electron?

因为这是一个需要频繁截屏、OCR、调系统 API 的工具。ScreenCaptureKit、Apple Vision、Keychain、全局快捷键——这些能力在 Electron 里要么不可用,要么需要 native 插件绕一大圈。而且 Electron 打出来的包动辄 100MB+,一个工具类应用,不应该比用户的项目还大。

为什么选 Actor 而不是传统的 GCD?

Swift Concurrency 的 Actor 模型给了我们编译期的线程安全保证。9 个 Service 类,如果用 GCD 手动管理,光是 DispatchQueue 的创建、同步、回调嵌套就够折腾了。而 actor 关键字一加,编译器帮你干完所有事。代码更短,bug 更少。

隐私设计

这类工具天然涉及敏感信息(截屏内容、聊天记录、代码)。我们的原则是 本地优先

  • • 截图图片不上传,只在本地处理
  • • OCR 由 Apple Vision 本地完成,不走网络
  • • 只有 OCR 识别出的文字会发送给 AI 模型,原始图片不会上传
  • • API Key 存 Keychain,不存配置文件
  • • CSP 策略禁止 HTML 卡片加载任何外部资源,防止被外部埋雷

写在最后

Tech Brain 目前是 v2.2.0,两条核心链路已经跑通:

  • • 技术趋势:四源聚合 → AI 趋势报告 → 飞书推送
  • • 读屏助手:快捷键截屏 → 本地 OCR → 场景识别 → AI 卡片 → 复制分享

整个项目零第三方依赖,纯 Swift + Apple 框架,安装包不到 3MB。

如果你也是一个每天在信息洪流里挣扎的技术人,或者你想体验”截图即分析”的工作流,欢迎到我的小群(公众号菜单-联系我-加群)试用。

开源地址:https://github.com/coder-brzhang/tect-brain-swift

注意,本项目仅在小张的400 多个人的小群(公众号菜单-联系我-加群)中分享。

这个工具的核心理念始终是一句话:

你负责看到信息,它负责把信息变成判断、行动和结构化表达。

Tech Brain 是一个 macOS 原生应用,需要 macOS 14 (Sonoma) 及以上版本。