
这是什么
一个原生桌面应用,把一台机器上各家编码 agent 的会话收进一处。它只读地打开这些 agent 本来就在写的私有目录,从不写回去,把它们变成一座可以按 agent 或项目浏览、可以搜索、并且能在原项目目录里用终端恢复的库。支持表里有 22 行,合起来覆盖了 JSONL 目录树、按日期分层的 rollout 目录加一份 SQLite 状态库、同一款产品跨两个库文件的三种表结构、一个键值库、文件名里带着格式代号的 zstd 压缩日志,以及一个把正文加密、因此只能按元信息列出的 agent。搜索是建在三元组索引上的 SQLite FTS5,所以中文短语和 useEffect( 这样的代码子串走的是同一条路,命中之后直接跳到正文里那条消息。同一个索引还通过随应用打包的只读 MCP 服务(五个工具)和一条输出逐字节相同的命令行交回给 agent 自己。周围还有 Insights 统计页、用 SSH 镜像回来的远程主机、只读的记忆页,以及一个把会话文件移进系统回收站、并留下标记让它们不会复活的清理页。Rust + GPUI,MIT,macOS 优先,Linux 与 Windows 是实验性构建。
谁做的一位独立开发者,按他自己的记录,主力工具是 Claude Code 与 Codex,工作语言以中文为主。仓库 200 次提交里 181 次是他写的;其余来自一个名为 claude 的 GitHub 账号(10 次)、YTwsy(3 次),以及另外五位各一次。129 条共同作者尾注里有 125 条署名某个 Claude 模型——Fable 5.1 占 63 条,Fable 5 占 36 条,Opus 5 占 16 条,Opus 5.5 占九条。
它是怎么搭起来的
组成 · 6这个仓库是双 crate 的工作区,中间留着一道刻意的接缝。wake-core 是完全没有 UI 依赖的数据层——adapter、扫描器与文件监听、SQLite 索引、远程主机镜像、MCP 服务、命令行,以及按平台分开的服务——wake 是它上面的 GPUI 应用。几乎其余所有决定都是「接缝放在这里」的后果。因为唯一的真相是别家工具的文件、且只读打开,索引就是一份可以扔掉重建的派生缓存,收藏与置顶另放一张表,所以重建也带得走;因为各家专属的东西都在一个 trait 后面,新增一个数据源是新增一个模块,而不是改接口;又因为同一批查询工具同时供 MCP 与命令行使用,命令行的输出可以和接入的 agent 所见逐字节对齐断言,于是要写文档的格式只有一份而不是两份。远程主机是同一道接缝的第二种用法:remote.rs 把 adapter 套在一份镜像缓存上,接缝以上的部分除了徽章之外,分辨不出远程会话与本地会话。
- crates/wake-core/src/adapters/
- 二十六个文件:22 个 agent 模块挂在
AgentAdaptertrait 后面,另有 61,238 字节的mod.rs、41,391 字节的parse_utils.rs、负责 SSH 镜像的remote.rs,以及只读访问数据库的sqlite_ro.rs。单个最大的 adapter 是 59,164 字节的 Codex 与 46,943 字节的 Cursor。 - crates/wake-core/src/{scanner,watcher,db}.rs
- 一次扫描同时收元信息与全文行,之后按 mtime 增量;基于 notify 的文件监听做逐文件更新;rusqlite 索引跑在 WAL 模式,表有 sessions、messages、messages_fts、user_data、tombstones,另加 location、remote_hosts 与 schema meta。
db.rs有 146,506 字节,scanner.rs有 53,568 字节。 - crates/wake-core/src/{mcp,cli} 与 bin/
- 一个走 stdio 的只读 MCP 服务,JSON-RPC 手写,带五个工具;一条命令行把 argv 翻成同一批调用。随包出三个二进制:做数据层冒烟测试的
scan、wake-cli与wake-mcp。 - crates/wake-core/src/services/
- 按平台分别实现的终端恢复——macOS 走 AppleScript、POSIX 走 argv、Windows 走原生参数接口,共六个文件——外加导出、agent 上下文辅助、文件系统辅助,以及一个 88,525 字节的清理模块:它找出可移除的会话,移动任何文件之前先取内容摘要,回收站用各平台自己的那一个。
- crates/wake/
- GPUI 应用本体。
workbench.rs有 388,590 字节,是全仓最大的文件;settings.rs79,160 字节,main_window.rs12,803 字节。theme.rs与ui.rs是唯一允许存放颜色、字号与间距常量的地方。简体中文译文 24,547 字节,旁边那份en.json只有 25 字节——因为英文是源语言,不是译文。 - DESIGN.md、PRODUCT.md、docs/ 与 scripts/
- 三份承载项目书面记忆的文档——26,541 个字符的界面规格、一份记平台与约束并逐 adapter 记出处的产品记录,以及三份参考(21,972 字节的
cli.md、20,502 字节的mcp.md、7,888 字节的session-cleanup-design.md)——旁边是给应用包、Linux 包与 Windows zip 用的打包脚本,和一个 34,869 字节、用来生成所有公开截图的合成家目录的脚本。
取舍,以及它替代了什么
数据层独立成 crate,不带 UI 依赖 替代 把解析与索引写在应用里面
README 的架构块把
wake-core标为「纯数据层,没有 UI 依赖」,而正是这一点让同一批 adapter 可以被应用、被wake-mcp、被wake-cli分别驱动,也让测试成为数据层测试:持续集成在三个平台上跑cargo test -p wake-core,而 GPUI 窗口层只要求编译通过。每个方向都只读 替代 回写别家 agent 自己的存储
README 的隐私一节写明:agent 数据目录只读打开,
auth.json这类凭证文件从不读取,全部写入只落在 Wake 自己的索引与三个小偏好文件上。PRODUCT.md把同一条当成对 Codex 那个 SQLite 的硬约束记下;它同样管到远程主机:OpenClaw 的数据库因为同时存着凭证而不进镜像,只复制它的旧版 JSONL。索引可丢弃,而命令只许建不存在的索引 替代 把数据库当成记录本身,或让工具重建一份正在使用的索引
README 说索引随时可以从头重建,收藏与置顶放在另一张表里、重建也活得下来。
wake-cli index刻意比这更窄:它扫进真库旁边的一份临时库,扫完才原子占位,所以中途被杀可以重试;而应用已经拿着索引时它退让——界面与两条写命令共用一把锁,关窗即放。在文件边界上判定 Codex 的内部线程,同时保留派出去的子代理 替代 解析之后再过滤,或者把这一族整体排除
维护者对 issue #42 的回答是:guardian auto-review、
/review、compaction 与 memory consolidation 继续排除,而spawn_agent子线程回来,挂在派它的会话下面,被复制进来的父会话历史折成一条不计入索引的替身。README 还写明了认不出来时倒向哪边:宁可让它继续可见,也不冒藏掉一段真实对话的风险。宁可不报 Qoder 的 token 数,也不拿 Credits 去填 替代 把唯一非零的用量字段换算成 token
#35 把这个当作粗代理提了出来,维护者在回复里拒掉并写明理由:那会把不同单位混进同一个统计里。最后落到文档与回归测试上的是一条能力限制,而这些会话仍出现在 Insights 中不依赖 token 的那几个视图里。
所有截图与演示都用一份合成家目录 替代 直接拍作者自己的真实会话库
PRODUCT.md记下了 2026-08-19 的这个决定与理由:真实项目名是私密的。一个脚本生成假家目录——22 个合成会话、五个编出来的项目、七家 agent 全亮——所有对外截图都用它。测试套件遵循同一条规则,只解析合成夹具,README 对此有明确说明,连那个走假ssh与系统rsync、对着合成家目录跑的远程主机测试也一样。
依据crates/wake-core/src/adapters/ 与带体积的 235 个文件树、README 的架构与隐私两节、PRODUCT.md(7,614 字符)、DESIGN.md(26,541 字符)、docs/session-cleanup-design.md、.github/workflows/release.yml 与 .github/workflows/ci.yml。adapter 数量与逐个文件体积取自仓库自己的目录清单;trait 名、crate 划分与索引各表引自 README 的架构块。
制作过程
6 个阶段- 01
四十一天里四十二个版本,以及一条绕开代理的发布线路
仓库建于 2026-08-18,当天就发布了带七个 agent 的
0.1.0。到 2026-09-27 的0.8.5,中间隔了四十一天,变更日志多了 42 个版本段落;200 次提交里八月 76 次、九月 124 次。最忙的一天是 2026-08-25,发了五个版本;2026-09-03 四个,2026-09-01 与 2026-09-25 各三个。侦察报告里那份 API 列表停在二十条,从v0.4.2到v0.8.5——那只是一页;变更日志一直写到第一个版本。旁边是 1,387 个星、88 个 fork、2 个 watcher、6 个开着的 issue,以及 MIT 许可。八个账号提交过代码:作者本人 181 次,一个名为claude的账号 10 次,YTwsy 三次,另外五位各一次。发布工作流本身值得一读。推一个v*tag 会创建 GitHub Release,说明文字从变更日志里切出来——脚本取## [X.Y.Z]与下一个版本标题之间的整段——随后三个 job 并行给 macOS、两个 Linux runner 和 Windows 打包。它们都跑在原生机器上,因为按作者写在文件顶部的注释,GPUI 的 shader 无法交叉编译。已存在的同名资产一律跳过、绝不覆盖,所以先传上去的那份(包括维护者本机打的)就是发布物。同一段注释还记着一个绕法:tag 推送与手动派发都被开发环境所经代理回了 403,于是推一个名为release/vX.Y.Z的分支同样触发工作流,tag 名从分支名里剥出来。 - 02
一个 trait、二十六个 adapter 文件,以及各家自己发明出来的存储格式
数据层是
wake-core,各家之间的差异全被关在一个AgentAdaptertrait 后面。README 用一句注释写明回报——「add an adapter, get the whole UI for free」——并补充说remote.rs把任意 adapter 套在一份同步过来的缓存上,于是远程主机复用同一套代码,而不是另起一份实现。crates/wake-core/src/adapters/下是 26 个文件:22 个 agent 模块,加上 61 KB 的mod.rs与 41 KB 的parse_utils.rs。它们要吞下的格式几乎没有共同点。Claude Code 在按项目分的目录下每个会话写一个 JSONL。Codex 把rollout-*.jsonl写进按日期分层的目录,旁边另有一份state_5.sqlite。Cursor 留着两个永不相交的存储:~/.cursor/projects下的 CLI 转录,以及 IDE 的 Chat/Composer 历史所在的state.vscdb——一个键值库,一个键给顺序、逐消息的键给正文;同时有完整转录的对话留在转录那一侧,好归到正确的项目下。OpenCode 为同一款产品带着三种表结构、两个库文件,两个都会扫。DeepSeek Harness 写的是session[.vN].jsonl[.zstd]:文件名里带着格式代号,日志在读取时解压——这正是 issue #45 出问题的形状:adapter 还在找旧名字,于是磁盘上 112 份日志一个都没进索引。Devin 是一个明文双表库,可见的转录是从main_chain_id沿parent_node_id往回走出来的森林,并写明了一条「走不通就按写入顺序列全部节点」的兜底。Cursor 的目录 slug 是最小也最刁的那个:一个-同时表示路径分隔符、连字符和空格,于是My Project一直被解析成My/Project,直到 issue #38。 - 03
文件边界上留下什么、藏起什么,以及刻意留在明面上的东西
Codex 会把后台线程写进与真实对话同一个
sessions目录,而最初的 Wake 把它们也索引了:issue #30 报告 guardian auto-review 线程以Untitled出现在列表里,有的点开空白,有的显示一段审批结果 JSON。两种形状都在第一行自报家门——一条带thread_source与结构化source对象的session_meta记录——而这个判断被放在文件边界上,而不是解析之后,于是 watcher 与增量路径得到和全量扫描同样的结论。v0.6.6 把这一族整体排除。接着 issue #42 来问spawn_agent子代理能否回来,并指出codex.rs里本来就留着一句注释:这些转录暂不展示,日后可走parent_links挂回父会话。v0.8.0 回答了这个问题:派出去的子线程重新进索引,挂在派它的会话下面、以任务名为标题;Codex 复制进每个子线程的父会话历史折成一条不计入索引的替身,而 guardian、/review、compaction 与 memory consolidation 仍然留在外面。对认不出来的东西,README 写明倾向哪一边:宁可让它继续可见,也不冒藏掉一段真实对话的风险。同一种直觉也出现在 Craft Agents 上:它跑的是别人的引擎,每段对话都会在 Claude Code 的历史里留下一份副本;Wake 列出 Craft 的会话,并且只在原件还在时藏掉那份引擎副本,Craft 里删掉会话,副本就会重新出现。 - 04
跨所有 agent 的搜索,以及两份把会话 id 变成命令行开关的报告
搜索是一张建在三元组索引上的 SQLite FTS5 表,这也是中文短语与
useEffect(这类查询走同一条路的原因;不足三个码点时降级为LIKE扫描,而 0.8.0 修掉了一个崩溃:一两个字符的搜索词碰上一条在命中之前含 Ω 或 İ 这类字符的消息就会挂。命中会直接跳到正文里那条消息,而不是转录开头,走的是索引与阅读器都遵守的seq契约;0.6.5 补上了标题命中,并让最近活跃的会话在同样好的一击里略占先。同一次发布还得拦住一件事:agent 自己用wake_*做的查询,不该在它自己的会话里变成搜索命中。最锋利的报告落在恢复这条路上。issue #50 指出会话 id 未经任何形状校验就拼进 agent 的命令行,而取引号的那个快速路径把-当作安全字符,于是一个名为--dangerously-skip-permissions.jsonl的会话文件真的成了那条命令行上的开关。issue #49 走的是反方向:Windows 下「命令提示符」这条路把 id 用双引号包起来却不做任何内层转义,且只过滤%;而好几个 adapter 的 id 取自数据库而不是文件名,代码所依赖的那个前提并不总成立。0.8.4 用同一种办法修掉两份报告:打开终端、打开桌面应用、或复制 SSH 命令之前,先校验 id。 - 05
GPUI:没有符号图标、没有缩放、藏不进 Dock,而窗口层 CI 只保证能编译
应用是 GPUI 0.2 加 gpui-component 0.5,几条小限制由此而来,并且都被写了下来。GPUI 没有 SF Symbols,所以所有界面图标都是随包自带的 Lucide SVG,所有 agent 身份都是随包自带的品牌 PNG,按原色渲染、永不着色,选中行里也不变。没有页面缩放,因为没有 web view:issue #51 要一个能看清正文的办法,并列出不存在的东西——设置里没有字号项,
Cmd +没有反应,Window 菜单里的 Zoom 只是最大化窗口——唯一给出的绕法是 macOS 的辅助功能缩放,而它会放大整个屏幕。issue #43 撞上第二扇关着的门:作者试过在应用包里写LSUIElement把 Wake 从 Dock 里拿掉,毫无作用,因为 GPUI 在启动时自己设置激活策略。另外两条限制被写成守则而不是 bug。指针回调里不得同步派发键盘事件,因为从 AppKit 的mouseUp路径打开搜索面板会重入 GPUI 的事件分发;Root 必须在面板打开前先保存当前焦点,否则面板一关⌘K就失效。主题还关掉了组件库的聚焦环,因为那个环是元素框外两像素的绝对定位子节点,会被弹窗内容层和滚动列表裁掉——聚焦状态改用染边框表达,不占空间,也不会被切掉一半。持续集成在 macOS、Linux、Windows 上都构建这个应用,但窗口层在那里只保证编译通过;记忆页、清理页与整个工作台都不带启动窗口的测试。 - 06
一份用数字写成的设计文档,和一份作者自己列出的「验不了」清单
DESIGN.md是 26,541 个字符的规格而不是指导:颜色只许在theme.rs里改,图标必须登记到assets.rs(漏掉后缀就是一块静默空白),每个可交互元素先设.id()再绑行为,每个窗口根节点必须在内容之后按固定顺序挂上浮层——文档把这个顺序称作契约。其中一部分读起来像实测笔记。侧栏中轴是 macOS 红绿灯红灯的中心,x = 26.75,其余一切由它派生,一直到 7.75 像素的行首内边距;标题那个 9 是从字母 W 的字形宽度反推出来的,文档同时警告:字号或字重一改,它立即失效。有一处间隔在 2026-09-22 被统一成 6 像素,并且故意不在四像素网格上,因为品牌 PNG 没有留白,而 Lucide 线条图标自带约 1.5 像素。第三条笔记写着 2x 屏的光栅化步长是 0.5 像素,小数点后不要再动:头部内边距原本取 12.125,落位 −0.125,改到 12.25 反而跳到 +0.375——两者落进不同的物理像素。同一份文档在 2026-08-24 完成迁移后彻底禁用基于 rem 的间距,因为 rem 被钉在 14 像素,它替换掉的那些工具类实渲出来是 10.5 或 12.25 这类数字。在这些之下,PRODUCT.md记的是另一类东西:哪些 adapter 是在作者本机的真实会话上验过的,哪些只是从源码推断出来的;OpenClaw、CodeBuddy 与 Reasonix 本机一份会话都没有,无从核对;Qoder 的 token 计数全是零,而它的 Credits 是另一种单位,不会被换算;以及从 2026-08-19 起,所有对外截图与演示都用一份由 34 KB 脚本生成的合成家目录,因为真实项目名是私密的。
相关档案
全部档案 →第 113 号
Chat On Steroids
一个给 ChatGPT 装上本地工具的桌面工作台。它用 MCP 提供文件、shell、终端和整个桌面,再用一个 Chrome 扩展通过隧道驱动用户自己那一个 ChatGPT 对话页面:模型因此能改真实项目,而 app 记录每一次工具调用,并在旧对话装不下时把会话搬进一个新对话。
第 108 号
agy-staff
它把 Google 的 Antigravity CLI 雇成一名员工。宿主 agent——Claude Code、Codex 或 Pi——留住决策权,把调研、评审和范围明确的改动交给一个跑在后台的 Gemini 3.8 Flash 员工,用一个 job id 来回传话。
第 109 号
Whiteboard
一个桌面应用,让 agent 和人共用同一块画布。agent 把审查画出来——时序图、实体关系图、钉在某次提交上的代码引用——而画布上的每个形状都能跳回它被画出来时所指的那段代码。