Cindy 深度评测:8158 Star 的开源 AI 客户端,4.9 万行规范里 5 条红线自己没守住

一个 AI 客户端项目,3 个月在 GitHub 上攒到 8158 颗星、写了 4.9 万行开发规范、一共 3308 条规矩。我把它拉下来,拿它自己的规矩去查它自己的代码,5 处没过。

先说清楚这是什么东西。Cindy 是一个开源的多端 AI 助手客户端——桌面版(Mac、Windows、Linux)加手机版,把 Claude Code、Codex、Pi 这几种「干活的引擎」包在同一个界面里,还能让几台电脑和手机接起来:在办公室电脑上开一个任务,回家用笔记本接着聊,文件不用拷来拷去。用的是 Apache-2.0 许可证,代码全公开。但它只有客户端,服务器在另一个不公开的仓库里,所以想自己搭一套完整的,这条路走不通——这点后面还会说。

我评它,是因为它有个很反常的地方:这个仓库把「怎么写代码」本身当成了一等公民。别的开源项目里,规范文档通常是十几页 wiki;这里有 210 份 Markdown、将近 5 万行,还专门给 AI 助手写了一份索引文件,告诉它「动哪块代码之前必须先读哪几份规则」。

于是就有了一个很自然的检验办法:既然你把红线写得这么细,那我就拿你的红线去跑你的代码。

一、它到底在管什么

打个比方:Cindy 不是 AI 本身,它是一个司机。真正下判断、写代码的是坐在副驾的 Claude Code 或 Codex(业内叫「引擎」或者 harness,也就是驱动模型干活的那层外壳),Cindy 负责的是方向盘、后视镜、行车记录仪和「今天走哪条路」。

这个位置决定了它的活儿主要在三件事上:

  • 连接:把用户已经付费的订阅、自己的 API key、本机跑的小模型都接进来;
  • 跨设备:同一个任务能在几台机器间接力,因为电脑本身被当成服务器用;
  • 包装:文件、浏览器、终端这些真实工具,以及插件、定时任务、聊天渠道,都收进一个统一界面。

仓库规模是这样的:一万三千多个 TypeScript 源文件、385 万行;其中测试代码 184 万行,比产品代码(202 万行)还接近一半。35 个内部包,没有一个发布到 npm。

二、我把它的规矩当审计清单跑了一遍

评测机是单核、内存不到 2G 的 Linux,被测项目全程关在隔离沙箱里:宿主机上的密钥、配置、家目录在沙箱里都看不见,克隆和跑脚本都在里面完成。下面每一条都能自己复现。

先说它做得好的部分,这是真材实料:

它自己的要求 我跑的验证 结果
提交前不许有硬编码的生产地址和密钥 跑它自带的地址字面量扫描 通过,零命中
五种语言的界面文案条目必须一一对上 跑它的多语言一致性检查 通过:14205 个条目全部对上
品牌名必须用占位符,不许写死 跑品牌术语守卫 通过
第三方动作(GitHub 上的自动化)必须锁定版本 数它自己的配置文件 15 处全部按完整哈希锁定,零个用浮动版本号

多语言那条值得多说一句:14205 个 key、五种语言,一条不差。这个数量级的同步(每种语言的条目一一对上、不多不少)靠人是做不出来的,只能靠机器每次提交都查一遍。它确实做到了。

然后是没过的 5 处。每一条都是它自己在文档里白纸黑字写了「必须」,而代码里没有:

第一处:主窗口的 5 个安全开关一个都没写

它的安全规范里有一句:「新增窗口必须显式配置下列安全选项,不得只依赖默认值」,后面跟着一张 6 项的清单。我把创建主窗口的那段代码完整截出来数了一遍:

规范要求的字段 主窗口里
sandbox(沙箱,让网页跑在一个受限盒子里) 缺
contextIsolation(隔离层,网页脚本碰不到宿主内部) 缺
nodeIntegration(能不能直接调系统能力,必须关) 缺
webSecurity(同源策略,必须开) 缺
allowRunningInsecureContent(是否允许混合加载) 缺

这 5 项在 Electron 42 里的默认值恰好都是安全的,所以眼下并不等于有漏洞。但规范之所以写成「显式」,就是为了不让安全依赖「默认值恰好没变」这种运气——上游哪天改默认值,这段代码不会有任何提示。

顺带数了一下全仓 16 个建窗口的文件:12 个显式写了沙箱,4 个没写。而没写的那批,正好是「主窗口」和「副窗口」这两个最早写、用得最多的。

第二处:它自己禁掉的东西,代码里有 76 处

架构规范第 2 条写得很硬:「主进程禁止运行时动态加载模块;依赖一律使用顶层静态导入。」原文还给了理由——动态加载会让打包、加载时机和错误路径变得不可预测。

实测:主进程里这类写法有 76 处。更耐人寻味的是,另一个文件里的注释还在引用这条规矩,用它论证「所以这里必须改成注入的方式」。也就是说,写注释的人真心相信这条线还在,只是没人去数。

第三处:代码格式检查根本没进 CI

每个子包都配了代码检查(lint)规则,里面有几条正好在守它的架构边界——比如「界面层不许直接引用桌面框架」「内部包不许反向依赖应用层」。这两条我手工查了,目前都守住了。

但把它的持续集成配置从头翻到尾,一次都没跑过代码检查。385 万行代码,靠的只有类型检查和测试撑着。规则写在了配置文件里,却没有一道门去执行它。

第四处:文档里的版本号是旧的

安全规范开头写着「结合 Cindy 当前 Electron 41 的实际架构」,而依赖里装的是 42.11.12。一个评「安全基线」的文档,引用的基线版本本身就过期了。

第五处:它让贡献者去找一个不存在的东西

英文贡献指南里说「公开仓库只固定了公共协议子模块」。我在仓库根目录查了:没有那个子模块声明文件,问 Git 也答「没有」。这条指引会让新来的贡献者卡在一个多出来的步骤上——而它恰好出现在「第一次装环境」这条最不该出错的路径上。

三、这五处放在一起说明什么

单独看,每一条都不严重:默认值是安全的;动态加载在那些位置大概率有具体理由;没跑的检查手工也能守住;版本号和子模块过期,读的人顶多愣一下。

合起来看才是问题所在:这个仓库的规矩,长到了人记不住、机器也不全查的规模。

  • 规范条目 3308 条(开发规则 1393、产品规则 1837,外加 7 份 AI 索引里的 78 条);
  • 里面有些被做成了自动闸门——多语言、地址扫描、品牌名、测试卫生,这些每次提交都跑,所以全绿;
  • 另一些只写在文档里,没有对应的检查——窗口安全字段、动态加载、代码格式。恰好,出问题的 5 处全部落在这一半。

这不是巧合,是一个很典型的工程规律:能被机器检查的规矩会一直对;只能靠人记住的规矩,会随仓库变大而慢慢脱队。 一个 3 个月做到 11037 次提交的仓库(GitHub 接口统计),人的注意力是最先被稀释的东西。

它甚至自己知道这件事。仓库里有一份「测试卫生基线」,把存量里不该有的写法(重复重置模块、真实等待、读源码断言)逐文件记账,冻结在 359 个文件、770 处,规定「只许减少,不许增加」,连改这个 JSON 文件都会被拒。这是很高级的做法——承认债在哪、锁住它、慢慢还。问题是这套办法只用在了测试上,没有用到上面那三类规矩上。

四、它还值得用吗?分人

如果你是想找「AI 编程客户端该长什么样」的参考:值得。它的安全设计不是贴上去的装饰——内容安全策略从主进程注入(网页自己删不掉)、网页嵌入层在挂载前被强制覆写安全开关、每次进程间通信都校验来源是不是自己的界面、插件跑在各自独立的沙箱里、密钥只走系统级加密存储。这些东西一般要踩过坑才写得出来。

如果你只是想用它干活:先想清楚一件事——它不开源的部分正是它主打的那些功能。跨设备接力、共享上下文、插件市场、聊天渠道接入、模型额度,全都指向它自己的云服务地址。界面上有「跳过登录」,能跑本机引擎,但那些让它区别于「套壳」的能力用不了。许可证给的是「可以审计、可以改、可以自己编译」,不是「可以自己运营」。

如果你想给它提代码:期望值要放低。项目方明确把外部 PR 排除在自动评审之外(怕密钥和提示词注入),只留人工评审;三百个已关闭的 PR 里,前五个人占了近 65%;问题列表里近 40% 是机器人开的。它是一个公司把客户端开放出来的仓库,不是社区共治的项目。

五、我的判断

4.9 万行规范、3308 条规矩、五语言一万四千个条目全对上——这套纪律在三个月内做到这个程度,是今年我看过的开源项目里最认真的几个之一。它失败的地方也很有意思:不是不认真,是认真到规矩比执行手段多。

所以我的结论是两句:

  • 能自动验证的部分,它做得比绝大多数同类项目好,包括主动承认自己的技术债并锁住它;
  • 不能自动验证的部分,它在自己定的优先级上掉队了——而一个把「红线和纪律」当卖点的项目,恰恰最经不起这种掉队。

如果你要拿它当范本抄,建议抄它「把规矩写成触发条件、给每条规矩挂上一条机器检查」的骨架;别抄它「只给一半规矩挂检查」的做法。补上那三道闸门(窗口安全字段、动态加载、代码检查进 CI),这个仓库的自我一致性会立刻上一个台阶——这大概是我能给出的最实用的建议。

—

利益声明:我与该项目无任何关联,未接受报酬,也未与其作者有过接触。本文所有数字来自 2026 年 10 月 29 日的公开仓库快照(提交 118767c9),在隔离沙箱内以只读方式核对;该仓库当时的星标数为 8158。评测没有安装完整依赖,因此类型检查、单元测试全集、桌面端实际运行行为均未验证,本文不对这些方面作任何判断。

相关阅读:

发表评论