我最近在同一个代码仓库里同时接入了Codex和Claude Code两个AI编码工具,来回切换的时候发现一个很折磨人的问题:修一个具体的bug,两个工具表现都不赖;但一旦问"这个项目整体架构是怎么组织的",它们就开始顾左右而言他,要么丢给我一堆文件夹路径,要么把README复述一遍。后来社区里越来越多人在聊架构分析Skill,我才意识到问题不在工具本身,而在于我们缺了一层"全局视角"的注入机制。这篇文章就围绕Codex和Claude Code的Skill架构,结合我接入Birdview的实际配置过程,把"怎么让AI Coding工具真正看懂项目全貌"这件事讲清楚。如果你也在用这类AI编码助手,或者正准备给团队搭一套可复用的架构分析流程,这篇值得看完再动手。
1. 架构分析为什么成了AI Coding的短板
1.1 局部检索模式的局限
先说一个我反复遇到的场景。问一个Spring Boot项目里某个接口的调用链,Claude Code会自己去翻Controller、Service、Mapper,最后给我一个相对准确的回答,这个环节体验其实不差。问题出在更粗粒度的请求上:当我说"帮我看下这套系统按领域划分应该怎么改",它突然就变成了一个"文件夹播报员",把根目录下的每个目录挨个念一遍,然后给几句正确的废话。Codex的情况也没好到哪去,甚至因为默认的检索习惯更偏向单文件,面对跨模块依赖时更容易陷入"局部最优"。
这类AI编码工具底层的运作方式是相似的:它们不会像人一样先"通读一遍代码库"再回答问题,而是在对话过程中不断做关键词检索、文件读取、符号定位,把命中的片段塞进上下文。这种局部检索模式天然适合单点问题,却不适合全局分析——因为模型的判断完全取决于它手头已经读到的那些片段,没读到的模块,对它来说就等于不存在。所以我一度以为是模型能力不够,后来才意识到,问题出在我们没有给工具设计"全局观察"的入口。
1.2 AGENTS.md和CLAUDE.md为什么补不上这块
很多人会说,你可以在仓库里写AGENTS.md(Codex的项目指令文件)或CLAUDE.md(Claude Code的项目记忆文件)啊,把架构写在里面让模型去读不就行了。这个方法能用,但作用非常有限。项目说明文件的核心职责是"约定":它告诉模型这个仓库的规范、命令、目录约定,让模型在行动前先了解约束。你可以在里面写下"本项目采用分层架构,Controller层注意……",但写不了"当前实际代码里ServiceA依赖了ServiceB,而B又反向依赖A"这种只有扫描代码才能得出的动态事实。
换句话说,架构信息的时效性决定了这类静态说明文件永远只能描述"应该长什么样",无法描述"现在长什么样"。项目结构跟着需求在变,说明文件却常常滞后。真想让AI拿到准确的架构全貌,唯一可靠的办法是让它在每次分析时重新扫描、重新归纳,而不是依赖某个可能已经过期的文档。这正是我转向Skill方案的根本原因。
1.3 Skill的出现,本质是把"分析流程"显性化
Skill在这两个工具里,说白了就是一份用Markdown写成的"操作手册+触发条件",存放在约定的目录下。当用户提问命中触发词时,agent会把这份手册读入上下文,然后按照手册里写的步骤去执行。架构分析类Skill的意义在于,它把"如何做一次全局代码分析"从模型临场发挥,变成了可复用、可调整、可沉淀的固定流程。
我观察到社区里比较流行的做法,是把架构分析Skill定位成"项目鸟瞰图生成器"。用户只需要说一声"birdview"或者"帮我从全局视角分析",agent就会按既定顺序执行:先扫根目录,再读入口文件和模块配置文件,然后识别模块边界,最后输出分层结构、依赖关系和风险点。整个过程像是一台不会遗漏步骤的流水线,而不是每次都要靠模型猜一遍"用户到底想要什么样的架构分析"。
2. Codex与Claude Code的Skill机制,到底差在哪里
2.1 Claude Code的Skills目录与延迟加载
先看Claude Code这边的机制。它把Skills定义在.claude/skills/<skill-name>/SKILL.md,支持用户级和项目级两种存放位置。用户级目录对所有项目生效,适合放一些通用技能;项目级目录则放在仓库里,跟着代码库走,适合放与业务强相关的分析规则。
这一套设计里最关键的点是"延迟加载"。SKILL.md不是每次对话都全量读入上下文,而是由模型判断当前用户请求是否匹配某个Skill的触发条件,匹配了才去加载对应文件。我给Birdview写过很长的SKILL.md,里面包含完整的输出模板和依赖表格式,如果每次对话都占用上下文,那token开销受不了;托延迟加载的福,平时不触发就完全不占位,触发时才把那几K内容注入。
用Claude Code直接管理Skill的体验也不错,它内置了/skills命令可以列出当前可用的技能清单,也可以指定文件夹让工具自动扫描。我在接入Birdview的过程中,基本不需要额外装插件,就是创建目录、放入文件、重新加载,三件事而已。
2.2 Codex的AGENTS.md与扩展指令
Codex这边没有一个叫"skills"的标准机制,它依赖的核心是AGENTS.md,也就是项目级别的指令文件。初次接触的人容易觉得不方便,但实际上思路是通的:在AGENTS.md里可以声明外部指令文件的位置与触发规则,再配合目录约定,就能模拟出一套类似Skill的加载逻辑。
我的做法是给仓库单独建一个codex/skills/目录,每个技能一个子目录,里面同样放一份Markdown描述文件。然后在AGENTS.md里加一条显式约定,例如:"当用户请求架构分析、全局视角、birdview、overview时,你应该读取 codex/skills/birdview/SKILL.md 并严格按其步骤执行"。这样Codex在对话中判断命中关键词后,就会主动去读取对应的操作手册。本质上就是把Claude Code的"规则匹配触发"改成"模型按AGENTS.md指示自行触发",精细度略低,但多试几次就能调到顺手。
2.3 一套Skill内容两端复用的前提
既然两边都是"Markdown指令文件+触发条件",那么把同一份Birdview技能同时接入两个工具,需要的额外工作就不多了。关键前提有两个:第一,SKILL.md内容本身不能绑定某个工具特有的命令或文件路径,尽量只写通用步骤和输出格式;第二,触发词设计要考虑两个工具的匹配习惯,不能只在Claude Code的YAML头里写触发词,而完全不管Codex那边只能靠AGENTS.md文本约定来触发。
在我实际配置的过程中,两端唯一有差异的地方在文件头。Claude Code会识别SKILL.md开头的YAML frontmatter(name、description),用来做技能描述与触发匹配;Codex不会解析这个,它只读取正文里的逻辑步骤。所以我会把同一份技能说明复制到两个位置,只在Claude Code版本里保留YAML头,Codex版本则把触发说明并进正文第一段。这样维护成本并没有翻倍,因为核心的分析步骤和输出模板始终是同一份。
提示:如果团队里同时用多个AI编码工具,建议把"技能内容"和"工具适配层"分开管理。核心分析步骤放在共享目录,两份适配文件只做薄薄的包装,这样后续给Codex加规则或给Claude Code加触发条件,都不会影响分析逻辑本身。
3. Birdview Skill的核心设计:让"代码地图"可复现
3.1 SKILL.md的四段式结构
我参考社区里Birdview相关Skill的做法,结合自己的项目习惯,把SKILL.md整理成了四个段落。第一段是角色声明,明确告诉agent"你是一个专门负责项目结构分析的职能助手",避免它在分析过程中突然跑偏去改代码。第二段是触发场景,写清楚"什么时候调用这个技能",包括用户直接说birdview/overview/架构分析,也包括在代码审查、功能开发前需要先了解全局的情况。
第三段是执行步骤,这一段是整份文件的核心。我要求agent严格按顺序做四件事:先扫描仓库根目录和顶层目录结构,判断项目类型;再读取README、启动配置、构建脚本等入口文件,确认技术栈和模块边界;接着分析模块之间的实际依赖关系,最好能追溯到具体文件引用;最后汇总成一份结构化的架构报告。第四段是输出模板,后面专门讲。
这个四段式的好处在于它把"隐性能力"变成了"显性流程"。模型本身当然具备代码分析能力,但如果没有步骤约束,它会凭感觉选择分析深度。有了执行步骤,它每次都会先看入口再展开模块,不会一上来就钻进某个细节文件里出不来。
3.2 输出报告的格式规范:从目录树到架构图
这是Birdview和其他"扫描目录"类Skill最大的分水岭。很多失败案例里,agent确实扫描了目录,但输出就是一份树状结构,看完了依然不知道模块之间什么关系。为了让报告真正可用,我在输出模板里定了五层结构:
- 第一层:技术栈与运行入口(构建工具、启动类、主要依赖)
- 第二层:顶层模块划分(按目录或包名归纳,标注业务职责)
- 第三层:模块依赖表(用表格列出依赖方向、依赖强度、引用文件)
- 第四层:核心数据流或事件流(描述数据从入口到落库/展示的路径)
- 第五层:风险点扫描(循环依赖、过度耦合、异常分支)
第三层的依赖表是整个报告的精华。我要求agent用表格呈现,每一行是一对依赖关系,列名包括"上游模块""下游模块""触发方式""关键引用文件"。看到这张表,基本就能判断一个系统的健康程度。我在一个40多个后端工程的仓库里运行Birdview后,它直接指出了两个服务之间的双向依赖,那是之前靠人肉翻代码翻了大半天的结论。
3.3 与代码审查、测试生成类Skill的协作顺序
只引入一个Birdview还不够,实际工作流里它是可以和其他Skill串联的。我的使用习惯是:新接手一个项目,先触发Birdview生成架构地图,把"全局视图"固定在上下文里;之后再让代码审查类Skill去扫描具体改动,因为审查时它已经有了一份全局判断,知道哪些模块无关紧要、哪些模块牵一发动全身;最后再让测试生成类Skill去补充用例,它会优先为高风险模块生成测试。
顺序很重要。如果反过来,先做细粒度审查或测试,agent很容易盯着局部代码反复挑刺,而忽略改动对整体架构的影响。Birdview在这个协作链条里的角色,相当于给后续所有技能提供一张"地图",让它们知道自己的工作落在哪个位置、影响的半径有多大。这也是我为什么坚持把Skill分成多个、而不是写一个万能大指令的原因:每个技能只做一件事,协作时的边界才清晰。
4. 接入实操:一套配置跑通两个工具
4.1 准备工作与环境确认
动手之前先确认两件事:一是工具有没有启用Skills/外部指令读取能力。Claude Code只要版本不太旧就默认支持;Codex则需要确保项目里已经存在AGENTS.md并且被正确加载。二是仓库里如果有node_modules、target、build这类生成目录,最好在后续Skill里明确忽略,否则架构扫描会被大量无关文件干扰,输出噪音非常大。
这里有一点值得说明:Skill的加载机制跟模型后端是解耦的,不管Codex或Claude Code实际连着官方API还是本地模型、第三方兼容接口,技能文件都是走同样的读取路径,所以下面这套配置不会因为你换了模型后端就失效。
我建议先准备一个结构简单的测试仓库,不用多大,几个模块就行,用来快速验证Skill链路是否通。等两端都跑通了,再把正式的大型仓库加进来。直接拿大仓库做首次接入不是不行,只是出了问题很难判断是Skill没触发,还是模型执行中途跑偏。
4.2 Claude Code端:新建skills目录
在Claude Code上接入,我喜欢用项目级目录,因为它跟着仓库走,团队其他人clone下来也能直接用。目录结构如下:
your-project/ ├── .claude/ │ └── skills/ │ └── birdview/ │ └── SKILL.md ├── AGENTS.md └── src/然后在.claude/skills/birdview/SKILL.md里放内容。文件头必须有YAML frontmatter,description写清楚触发场景,比如"Birdview分析:当用户要求架构概览、项目结构、birdview、overview时使用"。我那个SKILL.md中段大致是这样的:
--- name: birdview description: 生成项目架构鸟瞰报告,适用于用户要求架构分析、全局视角、项目结构概览、birdview、overview等场景 --- # Birdview 架构分析 ## 执行步骤 1. 扫描仓库根目录,列出顶层目录与主要文件,判断项目类型与技术栈。 2. 读取README、构建配置、入口文件,归纳模块边界与业务职责。 3. 分析模块间的实际依赖关系,追溯到具体文件引用与调用方式。 4. 按输出模板生成架构报告,未确认的信息明确标注为"推测"。 ## 忽略范围 node_modules、dist、build、target、.git 等生成目录不参与分析。 ## 输出模板 按输出模板章节所述的五层结构输出,依赖关系必须使用表格。写完保存后,在Claude Code会话里执行/skills,如果列表里能看到birdview,说明已被正确扫描。这里有个容易忽略的细节:修改SKILL.md之后,正在进行的会话可能不会自动加载最新版,稳妥的做法是执行/skills或者新开一个会话再测试。
4.3 Codex端:通过AGENTS.md注册
Codex这边我用的目录约定是:
your-project/ ├── codex/ │ └── skills/ │ └── birdview/ │ └── SKILL.md ├── AGENTS.md └── src/然后在AGENTS.md里显式声明技能入口,例如:
## 技能目录 当用户请求架构分析、全局视角、项目结构概览、birdview、overview 时,请读取 codex/skills/birdview/SKILL.md,并严格按照其中的步骤与输出模板执行。 所有技能描述文件均位于 codex/skills/ 下,按需加载,不要在同一轮对话中读取全部技能。把这一段放在AGENTS.md靠前的位置,Codex在初始化项目上下文时读到,就等于给后续对话注册了一个"按需调用"的入口。注意这里不要写成"每次对话都读取SKILL.md内容",否则会导致上下文膨胀,也和Skill按需加载的设计初衷相违背。
Codex版本的SKILL.md和Claude Code版内容基本一致,只是不加YAML frontmatter,把触发说明直接写进正文第一段。我第一次接入时直接把带frontmatter的文件复制过去,结果Codex把整个YAML块当成正文读了一遍,虽然不影响分析结果,但明显多浪费不少token,后来就学乖了。
4.4 验证技能是否生效
配置好之后,用三种典型说法分别测试两个工具:
- 说"birdview":看是否能命中触发词并进入分析流程
- 说"帮我分析一下这个项目的架构":看模型是否按SKILL.md的步骤执行,而不是自由发挥
- 说"基于当前项目结构评估这次改动的影响范围":看它是否先做全局扫描再回答细节
判断生效的标志是输出结构稳定。同一个项目连续问三次,如果每次都能按第二层到第五层的模板输出,说明技能已经稳定命中;如果三次输出风格飘忽不定,就要检查触发词或SKILL.md步骤是否写得太模糊。我自己的经验是,触发词宁可多写几个同义词,也不要只写一个生僻英文词,中文环境里"架构""全局""结构"都是高频表达,必须覆盖到。
5. 实测效果与翻车记录
5.1 两个工程的对照:接入前后的差异
我在一个Spring Boot加Vue的前后端分离项目上做了对照测试。后端大概40个业务模块,接口文件、配置、工具类混在一起,属于典型的"能跑但结构不清晰"的老项目。接入前直接问Claude Code"分析项目架构",它输出的是文件夹列表加高度概括的结论;接入Birdview后,它能主动给出模块依赖表,还指出了两个模块间存在反向依赖。
同样的测试在Codex上重复了一遍,结论一致但有个差别:Claude Code更擅长按模板输出,报告格式稳定;Codex更倾向按照自己的分析惯性组织语言,输出模板有时候会变形。解决办法是在Codex版本的SKILL.md里把输出模板的约束语句加强,明确写"必须按以下五个小节逐项输出,不得合并、省略"。改完之后,Codex的格式稳定性明显上来了。
这个对照让我意识到,Skill的内容可以两端复用,但"模板执行力"在不同模型上有差异,适配层的职责不只是把文件放对位置,还需要针对模型特性调整措辞强度。
5.2 最常见的三个翻车原因
第一次接入的人,翻车通常集中在三件事上。第一是触发词写太窄。只写了"birdview"一个词,结果用户用中文说"架构分析"完全触发不了,agent就按照默认方式回答了。我后来把所有可能的说法都列在触发场景里,包括英文缩写、中文短语、使用场景描述,覆盖面一下子宽很多。
第二是把SKILL.md写成万金油。有人喜欢把架构分析、代码规范、测试要求全塞进一个文件里,觉得"反正都是项目经验"。实测下来这种做法效果很差,因为模型会把注意力分散到各个指令上,执行步骤反而模糊了。Skill的设计应该是单一职责,Birdview就只管架构分析,不要顺手在里面写"同时检查代码风格"之类的额外要求。
第三是忽略上下文长度。SKILL.md写得再长,模型也未必会完整执行,尤其是步骤超过6步之后,执行率明显下降。我曾经试图把输出模板写得很细,结果模型只输出了前两段就停住了。后来把步骤精简到4步,模板保留框架性的五层结构,执行完整度就好了很多。
5.3 针对性调参经验
聊几个经过调整后效果明显的参数和写法。一是显式声明"忽略目录",这在大型仓库里几乎是必须的,否则agent会在 node_modules 这种目录里浪费大量扫描次数。二是给输出加上"未确认信息标注为推测"的约束,防止模型把猜测当成事实写进架构报告,这一点在依赖关系分析里尤其重要。
三是超大仓库的分层处理。如果项目超过100个模块,让agent一次性生成完整依赖表,报告会膨胀到没有可读性。我的做法是给SKILL.md加一条规则:如果模块超过50个,先输出模块粒度清单,让用户指定重点模块后再深入展开。这样第一次扫描的成本可控,追问时的精确性也不受影响。
四是定期更新SKILL.md。项目结构会演化,输出模板和分析步骤也要跟着调。我大概每两三个迭代周期会把社区里新的Birdview变体和自己的实际使用记录对照一次,把"实测有效"的做法吸收进来,把"写了好听但模型不执行"的段落删掉。Skill这个东西最忌讳写完就不管,它本质上是持续维护的工作流资产。
最后聊一点个人体会。把Birdview接入Codex和Claude Code之后,我最大的感受不是"工具变聪明了",而是"工作流终于有了固定的第一站"。以前接手一个陌生仓库,我自己的第一反应是打开目录树硬看,现在直接让AI先生成架构报告,再基于报告决定往哪个方向深挖,整个人的阅读路径都变了。如果你也想在团队里推广这套做法,我的建议是从一个通用Birdview开始,跑通流程后再让每个人往自己的SKILL.md里加团队特定的模块命名习惯或风险检验项。Skill的价值不在于某个文件本身写得多好,而在于它能不能被持续使用、持续修正,最终长成团队自己的分析标准。