前几天一个后端朋友在群里吐槽:他们团队三个月前开始全面用编码代理,提交频率直接翻了几番,一个中型服务从三万多行涨到近三十万行。代码多起来本来是好事,但架构图停在了三年前的版本。项目经理要求补一张,他对着代码画了两天也没敢提交,因为根本不知道哪根箭头还能代表线上系统的真实情况。
这个场景我太熟了。AI 编码代理时代,最不值钱的东西是“能跑的代码”,最值钱的反而是那些机器不生成、人也不爱维护的文档资产。这就是我为什么盯上了 Archify。它让编码代理直出可校验架构图,听起来只是把“画图”交给了 AI,但真正狠的地方在“可校验”三个字。这个项目过去七周用户涨了七倍多,社区里讨论“archify 怎么用”“archify skill”的声音也越来越多。这篇文章就聊聊它的核心思路、完整接入过程,以及我在实际项目中踩过的坑。
1. AI 写代码越来越快,架构图却在集体失守
1.1 编码代理不会替你维护架构,它只负责让代码膨胀得更快
先放下 Archify 本身,说说这个工具出现的背景。
用过编码代理(coding agent)的人都有体会:以前写一个模块怎么也得半小时起步,现在直接说需求,代理“唰唰”就把骨架搭好了。效率确实上来了,但代价是代码库的膨胀速度远超预期。一个周末的密集开发,可能就多出几百个文件。人的阅读速度没变,review 的速度没变,架构层面的失控感却成倍放大。
更麻烦的是,编码代理天然没有“维护架构图”的动机。它只知道按你的指令补代码、跑测试、修错误,不会主动去判断“这个模块是不是开始反向依赖底层了”“这两块业务是不是已经耦合得不像话了”。你把架构维护写进它的指令里,它也只是在你提醒的时候才想起来看一眼。代码增长越快,架构腐化越隐蔽,最后演变成开发团队的日常恐惧:改了 A 模块,不知道会把哪些 B、C、D 拉下水。
我见过不少团队尝试靠人来解决。让某个后端同学兼任“架构守护者”,每次 MR 都手动审一遍依赖边界。这种岗位本质上是个苦力活,干不了几周就放弃了,因为人工审查几千行 diff 里的依赖关系,本身就是一个不可能完成的任务。
1.2 三种我已经听腻的“架构图没救论”
跟开发聊架构图,通常能收到三种论调。第一种,“图画完就过期,没人维护的东西别画”。第二种,“画图成本太高,不如把时间省下来写代码”。第三种,“反正也能用工具自动生成,生成的图一样没人看”。
这三种说法都有道理,但都遗漏了一个关键判断:团队真正需要的是那张“图”吗?
不是。团队需要的是架构约束重新变得可执行。图画在那里,它可以骗人,也可以过期,但你没法执行它。可一旦把架构表达变成代码库里的结构化数据,它就能被扫描、被比较、被校验。这样一来,“这张图还准不准”就不再依赖某个人手动维护,而是每次代码变更后由工具自动给出答案。Archify 的思路本质上就是把架构图从一个“给人看的文档”变成一个“能给机器审的状态”。
我喜欢的类比是单元测试。单测本身不是给用户看的,它存在的意义是让重构变得安全。没有单测的时候,你改代码靠的是胆量和对全局的模糊记忆;有了单测,机器会替你挡掉那些肉眼看不到的回归。架构图也一样。当它可校验之后,编码代理每次改动代码,架构层的边界就自动被检查一遍,这比任何“每周手动review架构”的制度都靠谱。
2. “可校验”三个字到底意味着什么
2.1 别把架构图当成图片,它是结构化事实的投影
很多人第一次听到 Archify,第一反应是“又一个自动生成 Mermaid 图的工具”。我以前也用那些一键生成架构图的开源库,说实话,生成的图挺漂亮,但也就是看看。因为它们只是把代码里的 import 关系可视化了一下,本质上是把混乱原样放大了给你看,中间没有任何“筛选”和“判断”。
Archify 的处理方式不太一样。它会先把代码库解析成一份机器可读的架构定义,记录模块清单、依赖关系、分层边界、外部系统调用这些结构化事实;然后再基于这份定义去渲染人看的图。图谱只是投影,定义才是它关注的真相。所以它不会一次性把所有 import 全扔进图里,而是会按照模块和边界的粒度去组织。
这里体现了可校验的第一个基础:只有当架构信息被保存成有 schema 的数据时,下游才能对它做比对、做断言。你没有办法对一张 PNG 做 diff,但你可以对一份 YAML 做 diff。Archify 真正管理的是那份 YAML/JSON,渲染出的图只是其中一个产物。
2.2 可校验的三层结构:扫描器、基线、断言
在我实际使用的过程中,把 Archify 拆开看,大概有三层结构在工作。
第一层是扫描器。它会进入仓库,分析模块之间的引用关系,可能还会结合构建配置和导入语句,生成一份“当前代码真实长什么样”的中间表示。这一层解决的是“从源码到架构事实”的自动映射问题。
第二层是基线。第一次扫描出来的结果需要经过人工确认,修正掉那些明显是误报的依赖、补充上扫描器看不见的隐式边,然后保存成一个快照。这个快照就是未来所有校验的参照物。我理解 Archify 并不希望这个基线永远不变,而是希望它跟随代码演进,每次变化都有人审。
第三层是断言。当你设定了规则,比如“web 模块不能直接依赖 repository 模块的实现类”“所有对外 HTTP 调用必须经由 client 模块”,那么后续的每次代码改动都会拿新的扫描结果去跑这些断言。违规会以 diff 或错误的形式反馈出来。
这个结构其实很像测试框架。扫描器抓取当前状态,基线是历史状态,断言是业务规则。因此“可校验”不是某一个功能点,而是一整套工程闭环。这也是它和普通架构图工具拉出代差的地方:别的工具在“描述”,它在“检测”。
2.3 一条最小可校验基线长什么样
为了讲清楚,我基于通用思路补一个最小示例。实际 Archify 的格式可能随版本调整,但你大致会看到类似结构:
schema_version: "1.0" modules: - name: web path: services/web - name: application path: services/application - name: repository path: services/repository - name: external-client path: libs/external-client dependencies: - from: web to: application allowed: true - from: application to: repository allowed: true - from: web to: repository allowed: false boundaries: - layer: interfaces includes: ["web"] - layer: application-core includes: ["application"] - layer: infrastructure includes: ["repository", "external-client"]这串定义里,dependencies字段决定了哪条依赖可以存在,哪条不可以。Archify 扫描出新的 import 关系时,会拿着这份定义做匹配,如果出现一条web -> repository的新边,而声明里写着allowed: false,那就立刻暴露成问题。
真正重要的是,这份文件是可以提交进 git 的。它的变更历史就是架构演进史。如果某个 MR 被合并后,这文件里出现了一条新边,就说明代码库的依赖结构变了。你是主动加的边界,还是不小心绕过了分层?如果是后者,CI 就应该拦住这次变更。
2.4 校验背后最难的部分:如何对齐“代码真值”
结构看起来简单,实现的时候难啃的地方在于扫描器怎么理解代码。静态分析再准,也经常会遇到几类问题:动态语言里的依赖是运行时通过字符串拼出来的;某些框架用反射或依赖注入容器在启动时装配对象;还有大量的条件导入,让依赖关系只在特定环境下成立。如果你让扫描器把这一类全当成显式依赖,基线文件里就会塞满噪音,最后没人看。
Archify 这类工具的处理思路一般是:默认只信任静态层面能确认的直接依赖,对动态依赖可以留手工标注口子。对于扫描器识别不了的地方,你可以在架构定义里显式声明“该模块存在隐式依赖 X,原因是什么”,而不是让扫描器去猜。
打个比方,这就像装修验收。工长可以把所有管线走向画出来,但墙里有些隐蔽线路只有当初布线的人知道,那部分只能靠业主在图纸上手工补一笔。工具的价值是把能自动检测的部分全部自动化,把剩余需要人肉确认的部分压缩到最小。
3. 完整接入过程:从首次扫描到编码代理自动维护
3.1 在本地先跑通最简链路
不管团队用 Cursor、Claude Code 还是别的编码代理,我建议第一件事都是先在本地目录里把 Archify 跑起来。装好后进入项目根目录,先做初始化:
archify init这个命令一般会生成一个配置目录,用来管理项目路径、忽略规则和输出目录。接着执行首次扫描:
archify scan --output docs/archify如果一切顺利,docs/archify下会出现两份核心文件:一份是机器可读的架构定义,一份是给人看的架构文档。目录结构大概长这样:
docs/archify/ ├── architecture.yaml └── architecture.mdarchitecture.yaml就是之前说的基线素材,architecture.md是渲染后的架构说明,编码代理之后可以直接读它来理解系统结构。不用急着调整什么策略,先跑出初始结果再说。
3.2 第一次 review:把生成结果变成团队共识
第一次扫描的产物大概率是不完美的。依赖关系可能过多、模块划分粒度可能不对,有些应当被归为基础设施的代码被扫成了业务模块。这一步千万不要偷懒直接设为基线。
把architecture.md从头到尾读一遍,挨个检查那些依赖边。你会发现,很多“依赖”其实是代码里早已存在的坏味道,只是以前没人把它摊开来看。我当时的做法是:把明显是误报的边标出来,把模块之间真正需要保留的边界核对一遍,然后在配置文件里把统一的分层规则写好。
等到这份定义能大致反映团队认可的架构了,执行基线确认:
archify baseline create --from current之后每当代码变化,你就可以跑校验:
archify check它会拿当前代码状态和基线做比对,输出一份类似“新增了哪些依赖、哪些边界仍然守住了”的报告。这一步是后续所有自动化工作流的基础。
3.3 把它注册成编码代理的 skill,让“直出”真正成立
很多人在命令行里手动跑archify check也会觉得别扭,因为这还是没有闭环:你想起来才跑一次,想不起来它就是个摆设。Archify 之所以能和编码代理配合得这么好,是因为它可以被打包成一个 skill,让代理在合适的开发节点自动决定什么时候扫描、什么时候更新架构图。
这里解释一下“skill”的概念。以 Claude Code 的机制为例,skill 是一个带说明文档的专用能力包,里面描述了触发的时机、执行的步骤、使用的工具。放对了位置,编码代理端会在用户说“帮我加一个登录模块”之后,不仅在代码层面动手,还会在涉及模块关系变更时主动调用架构工具,跑一次核对或者更新架构文档。
一个最小可用的 skill 结构大概是这样的:
.claude/skills/archify/ ├── SKILL.md └── scripts/ └── check.shSKILL.md里描述触发条件和操作方式:
--- name: archify description: 在涉及模块依赖变更、新增服务、重构分层时,使用 Archify 扫描代码结构,输出架构变更检查,并保持架构文档同步。 --- ## 工作流程 1. 如果当前分支改动涉及模块间依赖,先运行 `archify check` 2. 读取 docs/archify/architecture.yaml,确认受影响的依赖是否符合边界 3. 对不符合边界的改动给出修改建议 4. 如果架构变更合理,运行 `archify update` 更新架构定义 5. 更新 docs/archify/architecture.md 供后续开发参考把这个目录放进项目的.claude/skills/下,编码代理下次处理相关任务时就能感知到 Archify 的存在。Cursor 那类编辑器也有类似的自定义指令机制,思路是一样的:不是每次都要你手动去敲命令,而是让代理自己判断“这一步会不会改变架构”。
3.4 一次完整的任务演示:从改代码到架构图同步
文字说多了容易飘,走一遍流程你就有感觉了。假设我在一个项目里对编码代理下令:“在 user-service 里新增一个 Kafka 事件通知,把用户注册成功的事件发出去。”
代理的执行过程大致分几步:先读取相关模块的代码,发现 user-service 要向 kafka-client 发消息,于是引用了kafka-client的事件类。写到这里,它的 skill 机制触发,自动运行了一次archify check,终端里出现类似这样的输出:
> archify check INFO loaded baseline from docs/archify/architecture.yaml CHECK module user-service -> module kafka-client new dependency detected baseline: kafka-client is not in allowed dependency list of user-service status: ⚠ WARNING boundary check completed: - kept boundaries: 12 - new dependency: 1 - boundary breaches: 0输出提示:新依赖不在允许列表里,但因为配置文件中把这种情况下判定为 WARNING 而非 ERROR,所以不阻断任务。代理会自己判断一下——这个依赖是否应该被允许?如果架构意图上确实需要 user-service 跟 kafka-client 通信,它应该去更新架构定义,而不是直接忽略这个警告。
于是代理继续修改architecture.yaml,把user-service -> kafka-client加进 allowed 列表,然后执行archify update并提交。最终 MR 里除了业务代码,还带着一份更新过的架构定义和相应的文档片段。代码结构变了,架构图也同步变了,并且这个变化是显示在 diff 里可以供人 review 的。
这就是“编码代理直出可校验架构图”的实际观感。你不再需要画图,也不再需要每次改完代码手动去补文档。代理在完成业务功能的同时,顺带把架构层的账本更新了。
4. 我实际踩过的坑,以及对应的排查思路
4.1 第一次扫描超大型仓库,直接把本地跑崩
我第一次接的时候,往一个中大型 monorepo 里跑archify scan,里面的前端、后端、脚本工具、测试夹具全在一个仓里。扫描到一半内存就开始告警,最后进程被系统干掉。后来才意识到:这类工具默认可能是按整仓解析的,但大型仓库里真正需要关注架构的往往只是核心业务目录。
解决方案很直接:在配置里把扫描范围收窄,忽略掉那些不需要纳入架构管理的目录。
ignore_paths: - tests/ - scripts/ - docs/ - vendor/ - legacy-payments/这是第一次配置时最该做的动作。与其追求全仓覆盖,不如先扫描真正热点的核心模块。否则第一阶段就是大量噪音,浪费调参时间,根本推不到上线那一步。
4.2 解析器给出的依赖关系不等于“事实”
当时项目里有一段通过反射机制加载插件实现的代码,运行时才确定调用链。静态扫描表示“这里没有依赖”,代码跑起来又从配置中心加载了实现类。如果我只信扫描结果,这段隐式依赖就会从架构定义里缺失,后续重构拆模块的时候就会踩空。
这种情况不能靠扫描器解决。最后我在架构定义中加了手工提示,明确该模块与另一个模块存在运行期隐式依赖,要求任何拆分动作都必须先看这个注释。工具能自动化一部分,剩下的是人的领域知识。难点不是要不要手工补,而是怎么让工具给你留出稳定的口子来补充,而不是把所有手写部分都覆盖掉。
4.3 托管区冲突:AI 改图,我也改图,改到一起去就乱了
Archify 生成的架构文档里有相当一部分是自动生成的。但如果人工也在这份文档里补充说明,编码代理的自动更新就会把你写的段落整个覆盖掉,或者和你的新增内容交错在一起,形成一份充满冲突的 diff。
这其实是“生成内容进 git 仓库”这类方案的共同问题。我的经验是把管理和人工标注分开:Archify 生成的内容全部放在architecture.yaml,这是受管文件,交给工具和代理更新;架构设计决策和规避说明放在另一个单独的architecture-decisions.md,由人维护。让工具只更新自己的地盘,不要让代理去“AI 润色”一份机器生成的文件。团队里如果没这个概念,很快会陷入“我改一段你覆盖一段”的死循环。
4.4 回归噪音:架构图越精确,告警越让人麻木
把 Archify 接进 CI 以后,我遇到过告警疲劳。因为每次编码代理改完依赖,扫描结果都会产出好几条提醒,开发看多了就形成条件反射:“哦,那个校验又报了,忽略就行了。”一旦大家开始忽略校验,这套系统就和没有一样,甚至更糟。
后来我把规则分成了 ERROR、WARNING、INFO 三级。破坏明确的架构边界是 ERROR,直接阻断 PR 合并。新模块在边界内出现了依赖膨胀是 WARNING,提醒人工留意,不阻断。模块内部的普通依赖变化记进 INFO 流水,什么都不打扰。阈值设好以后,真正关乎架构健康的问题才不会被淹没在数据流里。
4.5 别把全仓库覆盖当成第一目标
一开始我总是盯着“覆盖率”这个指标,觉得某个系统没纳入 Archify 就等于没防护。后来实践中发现,一个团队如果把所有模块都拿来建架构基线,调研和维护成本会迅速超过收益。更务实的路线是先挑三个最重要的核心模块,把架构边界固化下来,确保任何编码代理对它们的改动都必须通过校验;外围的一次性工具和服务,先不上这么重的流程。随着团队对工具的信任建立,再逐步把范围扩大。
5. 七周七倍背后:为什么一个画图工具能跑出这种曲线
5.1 Archify 踩中的不是画图需求,而是 AI 时代的护栏需求
从市场反馈来看,Archify 的爆发有必然性。编码代理每多写一行代码,传统业务里“人肉审计架构”的能力就在相对削弱。代码生成能力越强,就越需要机器去审机器。Archify 本质上是在编码代理旁边加了一个架构层的安全网,并把这个安全网的输出做得可以直接被 CI 消费。
用单元测试来类比再合适不过。没有单测时,你不敢大规模重构。编码代理普及以后,开发者面临的已经不只是“要不要重构”,而是“让它自己重构的话,我怎么判断它有没有把架构搞坏”。Archify 解决的就是这个问题,它把架构规则从口口相传变成了可自动执行的校验,编码代理改完代码马上能知道“架构这层账本还平不平”。
5.2 七倍增长里藏着的产品取向
能七周涨七倍多,靠的不只是口号。Archify 的设计有几个鲜明的取向:轻量、开发者优先、能进入现有工作流。
对一个新工具来说,最重要的是降低接入门槛。Archify 不需要从零搭建一套架构中心,它直接扫描你现有的代码库,输出到本地文件夹。开发者不需要改变开发方式,它更像是给编码代理加了一个“架构感知”的扩展插槽。注册成 skill 后,代理在任务中会自动判断是否需要校验或更新架构,这正好补上了编码代理缺乏架构意识的短板。
这种传播速度也说明,市场上憋着同样痛点的开发者数量远比想象中多。大家不是不需要架构管理,而是原来的手工方案根本跟不上 AI 开发的速度。
5.3 也不是所有代码库都适合立刻接 Archify
最后说一点不同的话。Archify 不是银弹,以下场景我劝你先别折腾。
小 demo、一次性脚本、纯前端静态页面这类体量的项目,直接跑代码就行,上架构校验纯属给自己找事。以试验性质存在、三周后大概率会被删除的快速原型,同样不适合。团队如果连基本的测试文化都没有,指望架构工具提高代码质量也不太现实,因为它不会替代人的 review 动力。另外,某些动态语言结合大量运行时反射的仓库,首次接入的调参成本会明显偏高,要有心理准备。
我的建议是,从小范围开始:选一个你自己最熟悉、还在积极开发的服务,让 Archify 生成基线,把核心边界规则设好。跑两周,把它接进编码代理的 skill 里,感受一下“代码改完架构图自动同步”的工作流顺不顺,再决定要不要推广给团队。一旦它跑起来了,你可能会和我一样,回不到“改代码不查架构影响”的日子了。