
这是什么
一个给团队共用编码 agent 的工作台,用的还是他们本来就在用的那些 agent。一台机器通过在命令行里启动一个守护进程加入工作区,这条命令会给出一个登录链接,之后这台机器就一直可用;在主人把它共享给工作区之前,它保持私密。活是从桌面端、手机、网页或终端派下来的一个会话,每个会话通过 Agent Client Protocol 把对话交给某个 agent,于是 Claude Code、Codex、Kimi、OpenCode 或其他兼容 agent 沿用自己已经配置好的订阅、登录、模型与权限模式。会话可以分到自己的 git worktree 并行干活,也可以分叉成另一个会话,连同文件、终端和预览一起开在标签页里,并用逐轮或整段会话的 diff、行级评论和一手旁边的 pull request 状态来查看改动。agent 还会拿到一组工具,可以去创建、读取、给别的会话发消息或取消它们,于是一个会话能同时当好几个会话的协调者;跑起来的网页应用可以直接开在会话里,把元素级的标注发回给 agent,而权限请求能在手机通知里直接批准。
谁做的这个仓库属于 LodyAI 这个组织而不是某个人,提交记录看起来也像一支队伍,而且排在最前面的是自动化账号:1,201 次提交里 296 次记在 lodystage[bot] 名下,274 次是 zxch3n,262 次是 Leeeon233,223 次是 wibus-wee,后面还跟着 40 个账号,贡献者名单一共 44 位。仓库的规范文件把这三个账号单独点出来,说明按它们算「Lody 团队」,其余都算社区。
它是怎么搭起来的
组成 · 6一张共享工作台、多个入口,而活本身留在团队自己拥有的机器上。一个会话通过 Agent Client Protocol 去跑一个编码 agent,所以这个产品不实现 agent,而是监管它们:每台机器上的守护进程让它们保持已知可达,会话层给每个会话一份 git worktree 和一份持久历史,而桌面端、手机、网页和终端只是同一份会话状态的几个视图,不是四个应用。真正有意思的是状态:协作状态用 CRDT 表示,经 Loro 这套栈同步,README 也把方向与尚未抵达讲得很明白——同一套地基还要从对话延伸到文档。两条边界对代码的塑造不亚于架构本身:公开的只有两个应用及其包,托管后端、运营配置、私有记录以及网页端与移动端源码都被划在外面;而开源桌面端是纯本地的,在它里面发起需要鉴权的产品云请求是被禁止的。隔离也是按会话而不是按人:worktree 让并行的 agent 不互相搅合改动,这正是命令行这一侧有那么多 git 管道和进程监管代码的原因。
- apps/cli/
- 736 个文件、11.2 MB:守护进程、会话层、agent 层、工具面,以及 git 管道。重量集中在少数几个文件上——会话执行服务 267,883 字节、agent 客户端 113,265 字节、会话派发监视器 110,836 字节、会话管理器 95,959 字节、worktree 管理器 61,447 字节、受管运行时解析器 55,841 字节、鉴权模块 47,025 字节——旁边是给内置适配器用的八份运行时清单和一份 12,071 字节的开发构建脚本。
- apps/electron/
- 226 个文件、8.7 MB 的桌面应用:主进程、预加载与渲染进程,一个带自己测试文件的开发者工具条,一份 6,942 字节的打包脚本加一个 12,469 字节的打包后钩子,四套图标与两份 macOS 授权文件,以及一套把命令行工具拷进应用里、而不是要求用户另外安装的构建。
- packages/
- 两个应用背后有十三个工作区包。最大的是
components,2,565 个文件、33.7 MB——路由、provider 层、story、基准测试和会话滚动引擎;ui是 110 个文件的基础组件与 StyleX 设计令牌,光它的规则文档就有 52,835 字节;shared放 schema、协议与会话数据;code-review-helper与code-review-viewer是 diff 与评审界面;loro-streams-rpc是传输层;cloud-api里只有可选托管组合用的协议名与类型。八个acp-extension-*目录是各自带仓库的 git 子模块,其中两个完全不在根工作区图里,而是以单独构建、带校验和的产物形式被消费。 - specs/ 与 .agents/
- 写下来的那套系统:162 份规格文件、595 KB,配中文孪生;846 份笔记、4.2 MB,按生命周期阶段与类别组织;外加 28 份说明文档。每个作用域——根目录、每个应用、每个包、站点与脚本——都有一份压到八千字节以内的规范文件,而每一份旁边都有一个九字节的
CLAUDE.md软链接,一套规则就这样同时服务两种不同的 agent 工具。 - e2e/ 与 .github/
- 108 个浏览器驱动验收的源文件:二十个特性文件配上对应的步骤定义与页面对象,用脚本化的协议夹具代替真实 agent,一份 52,485 字节的旅程注册表,一个分析失败原因的 scout,一个负载跑手,以及一套产物约定。周围是十四个工作流和 23 个政策脚本,最大的那个按 22,053 字节挑选持续集成范围,另一个用 18,174 字节自动撰写测试旅程。
- site-docs/
- 官网、文档、博客与更新日志,预渲染成静态文件,配自己的后处理和一个 23,059 字节的浏览器验证脚本,另有站点地图、订阅源、文档搜索索引的生成器,以及放在公开资源目录里的机器可读摘要文件。246 个内容文件、两棵语言树,
public/下还有约 39 MB 图片。
取舍,以及它替代了什么
用一套协议去监管 agent,而不是逐个自己做集成 替代 为每一种助手各写一套自家实现
README 在开篇第一段就把这个问题答了:连上任意一台机器,把任意编码 agent 通过 Agent Client Protocol 带进来。这个选择的后果对贡献者也是写明的——适配器包是各自带仓库的公开子模块,适配器的行为要先去那些包的源码里修,而不是在消费它的应用里修。
只公开两个应用及其包,其余不公开 替代 把整个产品开源出去
仓库规范把边界写得明确:公开源码是两个应用及其包,而托管后端、运营与计费配置、私有密钥与记录,以及网页端和移动端的应用源码都在外面。抓取到的用户或 agent 对话记录绝不允许提交,夹具必须是合成的;开源桌面端是纯本地的,在它里面发起需要鉴权的产品云请求是被禁止的。
协作状态建立在 CRDT 上,朝本地优先走 替代 让服务端独占文档、客户端只负责渲染
README 把意图和没做完的部分写在同一节里:项目希望整个工作台——而不只是对话——都变成本地优先,它用 Loro 这套栈(含 Loro 与 Flock)来表示和同步协作状态,并且直说它仍在朝完整的本地优先推进。也正因如此,传输层是一个独立的小包,而不是服务端里一个藏起来的细节。
让 DeepSeek Harness 刻意不进受管运行时那一档 替代 也给它「内置适配器加受管原生运行时」的待遇
命令行总览先把 Claude、Codex、Grok 列为带受管原生运行时的内置适配器、把 Kimi 列为受管 Node 包,然后专门把 DeepSeek Harness 分出来:它从自己的子模块里取一份钉住的 profile,通过隔离的包缓存启动,并加载一个内置适配器,于是扩展负责模型、推理强度和权限这几个选择器,而 Harness 继续掌握模型执行、沙箱约束和一次性批准。
选 Electron 43,而不是最新的那个大版本 替代 趁这次升级直接跳到 Electron 44
那条 pull request 把两边理由都写全了:43 保住了仍在支持的最老 macOS 版本和同步剪贴板调用,而 44 砍掉了那个版本、需要一个项目只写了规格的原子剪贴板迁移,还带着一个未修的启动崩溃。之所以要升级,是因为旧的那条线已经不在支持范围内,而且它强制给每个进程带了一个特性开关。
依据apps/cli/scripts/dev-build.mjs、.agents/docs/cli-overview.md、.agents/docs/ 下那 28 份文档、根目录的 AGENTS.md、specs/ 及其中文孪生、.agents/notes/implemented/process/*、编号 1154、1155、1156、1157、1168、1171、1176、1177 的 pull request 正文、README.md(8,701 字符),以及完整的 6,135 个文件树及其体积和两级目录汇总。
制作过程
6 个阶段- 01
一段从「播种式提交」开始的公开历史
仓库建于 2026-08-07,而它最老的一次提交——时间是同一天 02:29 UTC,比建库晚二十分钟——是
chore: prepare public source history [risk:high]:公开的源码历史是准备出来的,不是累积出来的。此后它跑了不到八周、1,201 次提交,八月 437 次,九月 764 次,最后停在 2026-09-30 把桌面运行时搬到 Electron 43 的那一条。许可是 Apache-2.0,体积 115,592 KB;报告抓取时它有 1,158 个星、133 个 fork、4 个 watcher 和 146 个未关的 issue。与这个体量相对的是一片极薄的发版面:四个标签——v0.88.0、v0.93.3、v0.100.0、v0.102.0——而 GitHub release 只有三个,最后一个在 2026-09-30。填补这段落差的是 changelog:apps/cli/CHANGELOG.md有 392,802 字节,桌面端那份 115,024 字节。README 用一段话把机制和边界一起写清楚:推送一个稳定的标签会生成一条草稿 pull request,把各个应用的版本号同步一遍,随后是一次带自动生成说明的 release;它不构建也不上传任何安装包或自动更新文件,而原来那个标签永远不会被移动。记录目录里有一份笔记就叫changelog-only-releases。 - 02
谁在提交,以及那条写明模型的尾注
最大的单一提交者是一个机器人——1,201 次里 lodystage[bot] 占 296 次——三位挂名的维护者以 274、262、223 次跟在后面,再往后还有 40 个账号。真正值得读的是共同作者尾注:一共 470 条,其中有 136 条写的是某个 Claude 模型。最大的一群是
Claude Opus 5.5 (1M context)的 50 条,然后是Claude Opus 5 (1M context)39 条、Claude Opus 516 条、Claude Opus 5.514 条、Claude Fable 510 条、Claude Fable 5.15 条,Claude Sonnet 5.5与单写Claude各一条。历史里的第二个 agent 身份是 Cursor,十二次,两种写法——九条Cursor、三条Cursor Agent。再往后是 Devin 10 条、Amp 5 条、copilot-swe-agent[bot]3 条。剩下的是人:Zixuan Chen 106 条、Leeeon233 56 条、Leon Zhao 50 条、一个叫Lody Dev的账号 35 条,还有一位Test User22 条。尾注不是唯一的约定:仓库规范要求人工智能提交以一行Model: <runtime-model-id>结尾,而准备 0.103.0 更新日志的那条 pull request 里,就有三次提交写着Model: gpt-6。 - 03
三种文档,以及把它们分开的那条规矩
项目先划了一条线,然后照着它做:规格表达意图,文档解释实现,笔记记录决定,三种各占一棵目录。
specs/有 162 个文件、595 KB,几乎每一份都有一个中文孪生兄弟——session-files.md28,420 字节配 25,131 字节,ui-primitives.md30,289 字节,session-sharing.md15,365 字节,session-history-writes.md15,051 字节。.agents/notes/更大,846 个文件、4.2 MB,而且它更像一台状态机而不是档案堆:implemented/下面分成架构、缺陷修复、功能、流程、简化和测试,旁边是proposed/与rejected/,再下面是一个按日期归档的archived/,文件名本身就带日期——2026-09-27-conversation-scroll-engine.md有 58,940 字节,译文 53,958 字节。.agents/docs/里另放着 28 份说明文档,.claude/skills/下有一个目录,装着一份 9,988 字节、讲同步栈的文档。真正执行起来的规矩只有一句:非琐碎的改动必须在同一条 pull request 里新增或更新它所属的笔记,只有机械性或局部编辑可以免掉。双语这件事本身也是一条写下来的决定——2026-09-12 的一份流程笔记名字就叫agent-authored-notes-ship-both-languages——而每个作用域的规范文件都被压在八千字节以内,旁边各放一个九字节的CLAUDE.md:那是软链接,不是副本。 - 04
一条社区 pull request 要长成什么样
这套贡献政策的执行者一半是脚本而不是评审者:
check-pr-body.mjs11,783 字节,pr-policy.mjs18,897 字节,pull request 模板 4,366 字节,而持续集成的范围选择脚本有 22,053 字节。模板里那段话对分叉和体量毫不含糊:来自 fork 的贡献必须关联一个 issue,所有政策层面的发现共用同一个七天的整改期,改动超过 1,000 行的社区 pull request 需要在关联 issue 上有一位维护者接手,而没有事先开 issue、改动又超过 200 行的,会再加一条它所谓的体量专项发现。同仓库分支则完全不需要为收件单开 issue,好几条 pull request 都原话这么写。样本里的 issue 展示了这场交换的另一半:2026-09-30 那天,账号 Jackey-Z 一个下午提了六条——1170 到 1174 以及 1178——每条都带着安装方式、版本、操作系统、内核、agent 运行时和一个主分支上的提交号。Dante-dan 对其中两条给出的不是承诺而是机理:1171 的回复点出了那条「把一切已知中止都当已处理」的供应商调用前中止路径、promptStarted这个字段,以及为什么普通用户轮次保留失败回执、而启动之后的投递永远不该获得重放许可,然后附上一个修好的对比分支。评审也有一部分交给了自动化——仓库里接了一个 Codex 评审器,评审说明要求它只报最高两档、安全优先,这个机器人在几条发版 pull request 下留了带表格的摘要。最小的一串对话来自 Gabyran:他希望@在不用空格分词的语言里也能在句子中间唤出提及菜单,并在 pull request 里写道,这只是他个人的一个习惯之举,斗胆提了上来。 - 05
一套把目录布局当作承重结构的构建
一份面向开发者的文档解释了命令行这套构建为什么长这样,而它给出的理由大多是已经付过代价的失败。开发时用 esbuild 打包,大约三秒,产物落到一个开发目录里,然后运行编译出来的 JavaScript;没有按需的 TypeScript 加载器兜底,所以开发启动不能直接跑源码。产物布局必须和生产完全一致,因为工作线程池、diff 存储的工作线程和工作区监视器,都是按文件名在导入它的模块旁边找自己的孩子进程;从源码目录跑就只剩 TypeScript 后缀的兄弟文件,线程池会退回主线程,并把原因记成
worker_missing。因此构建脚本在每次打包后都会断言:没有任何负责解析工作线程的模块被提升进共享分块目录,因为那会把同一种看不见的退回重新引进来。另外两个选择被标为承重:依赖按绝对路径保持外部化,因为一旦把工作区包的源码打进来,它自己的传递依赖在这个严格的包布局下就没有条目;代码分割保持开启,好让动态导入仍是真正的懒边界,否则一个被静态导入的生成清单会让连版本号都跑不起来。版本号本身也来自构建时别名,因为用相对路径去导入包清单曾经把一个旧版本号烤进了发布产物,文档把证据直接写了出来:某个已发布的lody@0.82.1打印的是0.76.0。 - 06
用数字说话:桌面端、轮询器和帧预算
有好几条 pull request 带的是数字而不是形容词。把桌面运行时从 Electron 39.5.1 搬到 43.7.6 时,理由被整段写了出来:39 已经不在支持范围内,而且它强制给每个进程带上一个关掉系统窗口遮挡追踪的特性开关;44 被否掉,是因为它砍掉了仍在支持的最老 macOS 版本、需要一个项目只写了规格的原子剪贴板迁移,还带着一个未修的启动崩溃——于是选了 43,它同时保住了那个 macOS 底线和同步剪贴板接口。紧接着的那条 pull request,正文本身就是一次性能测量:窗口可见但没有焦点时,四个「工作中」标记加两个转圈,让合成器每个垂直同步都画一帧——那块屏是 120 Hz——渲染进程 11.4%、图形进程 20.4%、窗口服务器 46%;而把全部动画暂停后是 2.2%、0.8%、8.0%。失焦即暂停被直接否掉,因为这个应用常常待在第二块屏上,那样看起来会像卡死;于是改成装一个帧预算,失焦时把所有无限动画量化到每秒 30 帧。同一种把算式写下来的习惯也出现在守护进程那一侧:这个 pull request 状态对账器是一套补偿路径,用来兜住已经坏掉的托管 webhook,快车道 20 秒一轮、慢车道 5 分钟一轮,每 20 分钟发现一次未关联的 pull request,完全没有轮次结束钩子,查询按工作区与仓库在同一份凭据范围内批量发出,单个仓库冷却 15 分钟到 2 小时,调度状态写在用户主目录下的一个文件里,并且可以用一个环境变量整体关掉。
相关档案
全部档案 →第 073 号
Zeron
一个 Rust 桌面程序,把你在用的编码 agent——Claude Code、Codex、Cursor、Devin、Grok、Hermes、Pi、Antigravity——装进同一个控制台,默认只在本机跑、不需要账号;只有你主动登录,它才会把这些会话同步到你其它的设备上。
第 074 号
agentacct
读你那些编码 agent 本来就会写下的会话文件,把 agent 通过 MCP 和钩子自报的活儿记下来,用一份公开价目表给 token 估价,然后全放进一个不出本机的本地面板里——而且始终把「agent 说自己做完了」和「有检查证明它做完了」当成两件事。
第 070 号
OpenChatCut
一个本地优先的视频剪辑器,剪辑方式是跟它说话:内置 agent 与外部 Codex、Claude Code 会话调用的是界面自己在用的同一套剪辑工具,于是每一处改动都落在一条真实的多轨时间线上——是片段、转场、字幕、特效或音频,仍然能拖、能撤销、能导出。工程与素材留在本机,预览与最终渲染都出自 Remotion。