文章目录前言一、那个让我怀疑AI成精的自动commit事件二、静态注入Claude偷偷给模型塞的小纸条三、Skill工具模型自己给自己发指令的自导自演四、动态注入Skill集合变了怎么办五、语义匹配注入当Skill多到烧不起token的时候六、设计取舍每一个决策背后都是血泪史七、写在最后P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。前言我搞AI22年了最近被Claude Code整出了心理阴影。上周我让它帮我在format.ts里加个日期格式化函数我刚敲完回车它啪一下就给我提交了commit信息还写得比我标准十倍feat(utils): add date format function。我当时手里的咖啡都洒键盘上了我寻思我没让你提交啊我还没检查有没有bug呢我赶紧翻git log好家伙连git add都给我执行了一气呵成比我自己写代码还利索。我当时第一反应是完了Claude成精了它要接管我的代码库了。我赶紧去翻项目目录看看是不是被黑客入侵了结果发现我三天前随手写了个auto-commit的SKILL.md还在AGENTS.md里写了一句“改完代码后自动commit”。我当时就想抽自己两嘴巴我这不是给自己找了个比老板还严格的监工吗我改完代码它比我还积极直接就提交了连给我反悔的机会都没有。后来我跟几个程序员兄弟唠嗑发现大家都遇到过这种事。有人说他让AI改个bug结果AI自动跑了lint还把他写的所有注释都删了有人说他让AI加个接口结果AI自动生成了单元测试还给他提了个PR。大家都以为是AI抽风了结果翻源码才发现这根本不是bug是Claude Code的Skill动态发现机制在搞鬼。今天我就把这个机制扒得底裤都不剩让大家看看你的AI到底是怎么背着你偷偷干活的。一、那个让我怀疑AI成精的自动commit事件先给大家还原一下案发现场。我的项目根目录长这样my-project/ ├── src/ │ └── utils/ │ └── format.ts ├── .claude/ │ └── skills/ │ └── auto-commit/ │ └── SKILL.md └── AGENTS.mdSKILL.md里我就写了三行--- description: 按 conventional commit 规范提交代码当完成代码修改或新增文件后调用 --- 当用户完成代码修改后执行 git commit。使用 conventional commit 格式type(scope): description。AGENTS.md里我就写了一句话改完代码后自动commit。然后我跟Claude说帮我在src/utils/format.ts里加一个格式化日期的函数。接下来发生的事情我至今记忆犹新Claude打开了format.ts文件它写了一个完美的日期格式化函数连边界情况都考虑到了它自动执行了git add src/utils/format.ts它自动执行了git commit -m “feat(utils): add date format function”它告诉我代码已写入并已提交commit hash是a3f8b2c整个过程不到三秒钟我连“等一下”都没来得及说。我当时就懵了我寻思我没让你提交啊我只是让你加个函数啊你怎么自作主张就提交了你经过我同意了吗后来我才知道这整个过程没有任何硬编码规则也没有任何预先注入的指令。Claude是自己判断出“我改完代码了应该调用auto-commit这个Skill”的。这就像你雇了个保姆你跟她说“做完饭把碗洗了”然后你让她炒个西红柿炒鸡蛋她炒完之后不用你说自己就把碗洗了还把灶台擦了。你说这保姆好不好好是好就是有时候会让你觉得有点瘆得慌。二、静态注入Claude偷偷给模型塞的小纸条很多人以为Claude知道有哪些Skill可用是因为这些Skill写在了system prompt里。大错特错。Claude Code有个特别鸡贼的设计它不在system prompt里预置任何Skill列表而是通过一个叫attachment的东西偷偷给模型塞小纸条。这个attachment是什么呢就是系统在每轮对话中自动附加到消息列表里的额外内容片段以system-reminder的形式注入。这个东西对用户界面是完全隐藏的只有模型能看到。就像你考试的时候老师偷偷给学霸递了一张小抄上面写着所有的考点你在旁边干瞪眼啥也不知道。每次你给Claude发消息系统在调用模型之前都会先执行一个叫getAttachments()的函数。这个函数会收集各种附加信息其中就包括skill_listing。skill_listing是什么呢就是当前所有可用Skill的列表。它长这样system-reminder The following skills are available for use with the Skill tool: # skills: 用户/项目 .claude/skills/ - auto-commit: 按 conventional commit 规范提交代码当完成代码修改或新增文件后调用 # bundled: Claude Code 内置 - some-builtin-skill: ... # mcp: MCP 服务器提供 - some-mcp-skill: ... # plugin: 插件提供 - some-plugin-skill: ... /system-reminder你看它把所有来源的Skill都列出来了每个Skill后面跟着它的描述。这个描述就是从SKILL.md的frontmatter里的description字段来的。而且它还特别聪明不会每次都把完整的列表塞给模型。它有个去重机制第一次用户输入的时候会把所有Skill都注入进去之后每轮都会检查只有当有新的Skill的时候才会把新的Skill塞进去。不然的话每轮都塞一遍完整的列表token早就烧没了。我见过有人项目里有50多个Skill全量注入一次就要烧2000多个token这谁顶得住啊我之前一直以为Claude是天生就知道这些Skill的结果翻了源码才发现原来它也是靠小抄啊。我当时就笑了合着搞了半天AI也得靠作弊才能考好啊。三、Skill工具模型自己给自己发指令的自导自演这里有个特别容易混淆的地方很多人以为每个Skill都是一个独立的工具模型可以直接调用。根本不是。模型眼里只有一个工具叫SkillTool。这个工具的参数就两个skill和args。它的schema长这样{name:Skill,description:Execute a skill within the main conversation,input_schema:{type:object,properties:{skill:{type:string,description:The skill name},args:{type:string,description:Optional arguments}}}}看到了吗模型根本不知道每个Skill具体是干什么的它只知道有个叫Skill的工具给它传个名字和参数它就能执行。这就像你去饭店吃饭你不用管后厨有多少个厨师每个厨师擅长做什么菜。你只要跟服务员说“我要一份宫保鸡丁”服务员自己会去找对应的厨师做。这个SkillTool就是那个服务员。那SkillTool拿到名字之后干什么呢它会去一个叫Command表的地方查找对应的Command。哦对了我忘了说了Skill和Command本质上是同一个东西。SKILL.md文件被createSkillCommand()函数解析之后会直接返回一个Command对象。所以你在源码里看到的findCommand()、getSkillToolCommands()这些函数其实都是在找Skill。SkillTool找到对应的Command之后会把SKILL.md里的内容作为用户消息注入到对话中。划重点SKILL.md的内容不是工具返回的文本而是作为用户消息注入对话。也就是说模型调用完SkillTool之后会收到一条“新用户消息”内容就是SKILL.md里的指令。它会以为是你让它去执行git commit的根本不知道是自己触发的。我当时看到这里的时候笑了整整五分钟。合着模型自己给自己发指令自己执行还以为是用户让它干的。这不是典型的自导自演吗那模型是怎么决定什么时候调用哪个Skill的呢它靠三个信息的组合AGENTS.md中的行为指令比如“改完代码后自动commit”SkillTool的工具提示“发现匹配的Skill就必须调用不要跳过”skill_listing中的短描述比如“auto-commit: 按conventional commit规范提交代码当完成代码修改或新增文件后调用”这三个信息凑到一起模型就会想哦我刚改完代码AGENTS.md说改完代码要自动commitskill_listing里有个auto-commit的Skill正好是干这个的那我就调用它吧。你看整个过程没有任何硬编码规则全靠模型自己推理。这就是为什么Claude Code这么灵活也是为什么它有时候会干出一些让你意想不到的事情。四、动态注入Skill集合变了怎么办有人可能会问那我中途加了一个Skill模型能知道吗我删了一个Skill模型还会记得吗答案是能知道但不是立刻知道会记得但调用会失败。Claude Code的Skill集合不是静态的你可以随时创建、修改、删除SKILL.md文件系统会自动感知这些变化。它是怎么感知的呢首先Agent Loop每轮工具执行完毕后都会再次调用getAttachments()函数检查有没有新的附加信息需要注入。也就是说每次模型执行完一个工具系统都会再检查一遍有没有新的Skill。如果有就把新的Skill塞给模型。其次系统会监听文件系统当SKILL.md文件被添加、修改或删除时会触发防抖重载重置去重记录。下一次检查的时候就会把新的Skill列表塞给模型。但是这里有个坑已经注入到历史上下文里的旧skill_listing不会被“反向删除”。也就是说如果你删了一个Skill模型可能还会记得那个Skill的存在然后尝试调用它。这时候SkillTool会在当前Command表里查找失败返回“Unknown skill”的错误。这就像你把一个员工开除了但是老板的通讯录里还留着他的电话有事还会给他打电话结果发现打不通。老板还会纳闷哎这个人怎么不接电话了还有一个更坑的地方系统不会在启动时扫描整个项目树的Skill。它只会加载根目录下.claude/skills/里的Skill。子目录下的Skill只有当模型操作到那个子目录下的文件时才会被发现。比如你的项目长这样my-project/ ├── .claude/skills/auto-commit/SKILL.md ← 启动时已加载 └── packages/ └── core/ └── .claude/skills/core-lint/SKILL.md ← 启动时不知道这个目录存在当模型读取packages/core/src/index.ts文件时系统才会沿路径向上搜索发现packages/core/.claude/skills/目录加载core-lint这个Skill。这个设计其实挺聪明的它让项目不同模块可以自带独立的Skill模型只在触碰到相关文件时才会发现它们不会浪费token加载无关的Skill。但是如果你想让模型一开始就知道所有的Skill你就得把它们都放在根目录下的.claude/skills/里。不然的话模型可能永远都不会发现它们。五、语义匹配注入当Skill多到烧不起token的时候前面说的全量注入在Skill数量少的时候没问题。但是当你的项目里有200多个Skill的时候全量注入一次就要烧几千个token这谁顶得住啊就像你去超市买东西本来只想买瓶水结果超市把所有商品的清单都给你念一遍念完你都渴死了。所以Claude Code搞了个实验性功能叫skill_discovery。这个功能用Haiku模型做语义匹配只注入与当前任务相关的Skill。打开这个功能之后原来的skill_listing会被裁剪只保留bundled和MCP两类Skill。user/project/plugin的Skill会由skill_discovery按需匹配注入。skill_discovery有两条触发路径用户消息触发用户发送消息时在首次API调用前同步执行把用户输入、对话历史和上下文喂给HaikuHaiku返回匹配到的Skill列表。Agent Loop触发Agent Loop每轮循环开始时尝试启动异步预取。但只有当本轮有工具真正写入了文件时才会执行Haiku调用否则直接跳过。为什么只有写入文件时才触发因为prod数据显示早期实现每轮都调用Haiku结果97%的调用什么都匹配不到。改成只在文件变更时触发大幅减少了无意义的调用。我当时看到这个数据的时候笑了半天。合着97%的情况下模型根本不需要任何额外的Skill全量注入纯属浪费token。打开skill_discovery之后模型在同一轮对话中可能同时看到两条system-reminder# skill_listing 发的始终存在只是内容变少了 The following skills are available for use with the Skill tool: - graphify: any input to knowledge graph... - sensight: 实时查询各平台热榜... # skill_discovery 发的按需出现 Skills relevant to your task: - article-publish-review: 对技术文章做发布前审查 These skills encode project-specific conventions. Invoke via Skill(name) for complete instructions.如果skill_discovery没有匹配到任何Skill整个attachment就会被过滤不注入任何内容。这个功能我亲测过开了之后token消耗直接降了一半而且模型调用Skill的准确率还提高了。以前模型经常会调用一些不相关的Skill现在只会调用跟当前任务相关的。当然模型也不是完全依赖自动注入。它还可以主动调用DiscoverSkillsTool来触发发现。比如当任务转向、遇到非常规工作流的时候模型可以自己搜索系统可能遗漏的Skill。六、设计取舍每一个决策背后都是血泪史最后跟大家聊聊Claude Code的设计取舍。每一个看起来很奇怪的决策背后都是无数次踩坑踩出来的。我给大家列几个最有意思的为什么首次用户输入时就注入skill_listing因为要确保模型从第一轮就知道有哪些Skill可用。不然的话模型可能会自己想办法解决问题而不是调用现成的Skill。就像你雇了个保姆你不告诉她家里有洗衣机她可能会用手洗所有的衣服。为什么skill_listing要去重发送废话不然每轮都重复通知token早就烧没了。我见过有人因为没做去重一天烧了1000美元的API账单直接原地心梗。为什么压缩后不重置skill_listing因为重新注入一次要4K token而且那些几十轮都没用到的Skill大概率跟当前任务没关系重新注入纯属浪费。就像你搬家的时候不会把十年都没穿过的衣服也带走一样。为什么信任模型的长上下文注意力因为如果每轮都重新注入token消耗会爆炸。这就是一个设计赌注赌模型能记住第一轮注入的Skill列表。当然这个赌注有时候会输比如到了第50轮模型可能就忘了还有某个Skill存在。这时候你只能手动用斜杠命令调用它。为什么只在文件写入时触发skill发现因为prod数据显示97%的Haiku调用无结果。工具没有写文件的时候模型大概率不需要任何新的Skill。这就像你去饭店吃饭只有当你坐下点菜的时候服务员才会给你菜单不会你一进门就把菜单塞给你。你看这些设计取舍没有一个是完美的。每一个都有它的优点和缺点。但是综合来看这已经是目前最好的解决方案了。七、写在最后今天我把Claude Code的Skill动态发现机制扒了个底朝天。从静态注入到Skill工具从动态注入到语义匹配注入每一个环节我都给大家讲清楚了。现在你应该知道为什么你的AI会自动执行代码了。它不是成精了也不是抽风了是Skill动态发现机制在搞鬼。其实这个机制设计得真的挺巧妙的。它没有用任何硬编码规则全靠模型的推理能力来决定什么时候调用哪个Skill。这让Claude Code变得非常灵活可以适应各种不同的项目和工作流。当然它也不是完美的。有时候它会调用不相关的Skill有时候它会忘记某个Skill的存在有时候它会干出一些让你意想不到的事情。但是总的来说它已经比市面上所有的AI编程助手都要好用了。我搞AI22年了见过太多的技术来来去去。但是我觉得Skill动态发现机制可能是AI编程助手未来的发展方向。它让AI不再是一个简单的代码生成器而是一个真正的编程助手可以帮你完成整个开发流程。最后希望这篇文章能帮到大家。如果你也遇到过AI自动执行代码的情况欢迎在评论区留言分享你的经历。P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。
Claude Code Skill动态发现机制全解析:为什么你的AI会自动执行代码
发布时间:2026/5/26 0:00:17
文章目录前言一、那个让我怀疑AI成精的自动commit事件二、静态注入Claude偷偷给模型塞的小纸条三、Skill工具模型自己给自己发指令的自导自演四、动态注入Skill集合变了怎么办五、语义匹配注入当Skill多到烧不起token的时候六、设计取舍每一个决策背后都是血泪史七、写在最后P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。前言我搞AI22年了最近被Claude Code整出了心理阴影。上周我让它帮我在format.ts里加个日期格式化函数我刚敲完回车它啪一下就给我提交了commit信息还写得比我标准十倍feat(utils): add date format function。我当时手里的咖啡都洒键盘上了我寻思我没让你提交啊我还没检查有没有bug呢我赶紧翻git log好家伙连git add都给我执行了一气呵成比我自己写代码还利索。我当时第一反应是完了Claude成精了它要接管我的代码库了。我赶紧去翻项目目录看看是不是被黑客入侵了结果发现我三天前随手写了个auto-commit的SKILL.md还在AGENTS.md里写了一句“改完代码后自动commit”。我当时就想抽自己两嘴巴我这不是给自己找了个比老板还严格的监工吗我改完代码它比我还积极直接就提交了连给我反悔的机会都没有。后来我跟几个程序员兄弟唠嗑发现大家都遇到过这种事。有人说他让AI改个bug结果AI自动跑了lint还把他写的所有注释都删了有人说他让AI加个接口结果AI自动生成了单元测试还给他提了个PR。大家都以为是AI抽风了结果翻源码才发现这根本不是bug是Claude Code的Skill动态发现机制在搞鬼。今天我就把这个机制扒得底裤都不剩让大家看看你的AI到底是怎么背着你偷偷干活的。一、那个让我怀疑AI成精的自动commit事件先给大家还原一下案发现场。我的项目根目录长这样my-project/ ├── src/ │ └── utils/ │ └── format.ts ├── .claude/ │ └── skills/ │ └── auto-commit/ │ └── SKILL.md └── AGENTS.mdSKILL.md里我就写了三行--- description: 按 conventional commit 规范提交代码当完成代码修改或新增文件后调用 --- 当用户完成代码修改后执行 git commit。使用 conventional commit 格式type(scope): description。AGENTS.md里我就写了一句话改完代码后自动commit。然后我跟Claude说帮我在src/utils/format.ts里加一个格式化日期的函数。接下来发生的事情我至今记忆犹新Claude打开了format.ts文件它写了一个完美的日期格式化函数连边界情况都考虑到了它自动执行了git add src/utils/format.ts它自动执行了git commit -m “feat(utils): add date format function”它告诉我代码已写入并已提交commit hash是a3f8b2c整个过程不到三秒钟我连“等一下”都没来得及说。我当时就懵了我寻思我没让你提交啊我只是让你加个函数啊你怎么自作主张就提交了你经过我同意了吗后来我才知道这整个过程没有任何硬编码规则也没有任何预先注入的指令。Claude是自己判断出“我改完代码了应该调用auto-commit这个Skill”的。这就像你雇了个保姆你跟她说“做完饭把碗洗了”然后你让她炒个西红柿炒鸡蛋她炒完之后不用你说自己就把碗洗了还把灶台擦了。你说这保姆好不好好是好就是有时候会让你觉得有点瘆得慌。二、静态注入Claude偷偷给模型塞的小纸条很多人以为Claude知道有哪些Skill可用是因为这些Skill写在了system prompt里。大错特错。Claude Code有个特别鸡贼的设计它不在system prompt里预置任何Skill列表而是通过一个叫attachment的东西偷偷给模型塞小纸条。这个attachment是什么呢就是系统在每轮对话中自动附加到消息列表里的额外内容片段以system-reminder的形式注入。这个东西对用户界面是完全隐藏的只有模型能看到。就像你考试的时候老师偷偷给学霸递了一张小抄上面写着所有的考点你在旁边干瞪眼啥也不知道。每次你给Claude发消息系统在调用模型之前都会先执行一个叫getAttachments()的函数。这个函数会收集各种附加信息其中就包括skill_listing。skill_listing是什么呢就是当前所有可用Skill的列表。它长这样system-reminder The following skills are available for use with the Skill tool: # skills: 用户/项目 .claude/skills/ - auto-commit: 按 conventional commit 规范提交代码当完成代码修改或新增文件后调用 # bundled: Claude Code 内置 - some-builtin-skill: ... # mcp: MCP 服务器提供 - some-mcp-skill: ... # plugin: 插件提供 - some-plugin-skill: ... /system-reminder你看它把所有来源的Skill都列出来了每个Skill后面跟着它的描述。这个描述就是从SKILL.md的frontmatter里的description字段来的。而且它还特别聪明不会每次都把完整的列表塞给模型。它有个去重机制第一次用户输入的时候会把所有Skill都注入进去之后每轮都会检查只有当有新的Skill的时候才会把新的Skill塞进去。不然的话每轮都塞一遍完整的列表token早就烧没了。我见过有人项目里有50多个Skill全量注入一次就要烧2000多个token这谁顶得住啊我之前一直以为Claude是天生就知道这些Skill的结果翻了源码才发现原来它也是靠小抄啊。我当时就笑了合着搞了半天AI也得靠作弊才能考好啊。三、Skill工具模型自己给自己发指令的自导自演这里有个特别容易混淆的地方很多人以为每个Skill都是一个独立的工具模型可以直接调用。根本不是。模型眼里只有一个工具叫SkillTool。这个工具的参数就两个skill和args。它的schema长这样{name:Skill,description:Execute a skill within the main conversation,input_schema:{type:object,properties:{skill:{type:string,description:The skill name},args:{type:string,description:Optional arguments}}}}看到了吗模型根本不知道每个Skill具体是干什么的它只知道有个叫Skill的工具给它传个名字和参数它就能执行。这就像你去饭店吃饭你不用管后厨有多少个厨师每个厨师擅长做什么菜。你只要跟服务员说“我要一份宫保鸡丁”服务员自己会去找对应的厨师做。这个SkillTool就是那个服务员。那SkillTool拿到名字之后干什么呢它会去一个叫Command表的地方查找对应的Command。哦对了我忘了说了Skill和Command本质上是同一个东西。SKILL.md文件被createSkillCommand()函数解析之后会直接返回一个Command对象。所以你在源码里看到的findCommand()、getSkillToolCommands()这些函数其实都是在找Skill。SkillTool找到对应的Command之后会把SKILL.md里的内容作为用户消息注入到对话中。划重点SKILL.md的内容不是工具返回的文本而是作为用户消息注入对话。也就是说模型调用完SkillTool之后会收到一条“新用户消息”内容就是SKILL.md里的指令。它会以为是你让它去执行git commit的根本不知道是自己触发的。我当时看到这里的时候笑了整整五分钟。合着模型自己给自己发指令自己执行还以为是用户让它干的。这不是典型的自导自演吗那模型是怎么决定什么时候调用哪个Skill的呢它靠三个信息的组合AGENTS.md中的行为指令比如“改完代码后自动commit”SkillTool的工具提示“发现匹配的Skill就必须调用不要跳过”skill_listing中的短描述比如“auto-commit: 按conventional commit规范提交代码当完成代码修改或新增文件后调用”这三个信息凑到一起模型就会想哦我刚改完代码AGENTS.md说改完代码要自动commitskill_listing里有个auto-commit的Skill正好是干这个的那我就调用它吧。你看整个过程没有任何硬编码规则全靠模型自己推理。这就是为什么Claude Code这么灵活也是为什么它有时候会干出一些让你意想不到的事情。四、动态注入Skill集合变了怎么办有人可能会问那我中途加了一个Skill模型能知道吗我删了一个Skill模型还会记得吗答案是能知道但不是立刻知道会记得但调用会失败。Claude Code的Skill集合不是静态的你可以随时创建、修改、删除SKILL.md文件系统会自动感知这些变化。它是怎么感知的呢首先Agent Loop每轮工具执行完毕后都会再次调用getAttachments()函数检查有没有新的附加信息需要注入。也就是说每次模型执行完一个工具系统都会再检查一遍有没有新的Skill。如果有就把新的Skill塞给模型。其次系统会监听文件系统当SKILL.md文件被添加、修改或删除时会触发防抖重载重置去重记录。下一次检查的时候就会把新的Skill列表塞给模型。但是这里有个坑已经注入到历史上下文里的旧skill_listing不会被“反向删除”。也就是说如果你删了一个Skill模型可能还会记得那个Skill的存在然后尝试调用它。这时候SkillTool会在当前Command表里查找失败返回“Unknown skill”的错误。这就像你把一个员工开除了但是老板的通讯录里还留着他的电话有事还会给他打电话结果发现打不通。老板还会纳闷哎这个人怎么不接电话了还有一个更坑的地方系统不会在启动时扫描整个项目树的Skill。它只会加载根目录下.claude/skills/里的Skill。子目录下的Skill只有当模型操作到那个子目录下的文件时才会被发现。比如你的项目长这样my-project/ ├── .claude/skills/auto-commit/SKILL.md ← 启动时已加载 └── packages/ └── core/ └── .claude/skills/core-lint/SKILL.md ← 启动时不知道这个目录存在当模型读取packages/core/src/index.ts文件时系统才会沿路径向上搜索发现packages/core/.claude/skills/目录加载core-lint这个Skill。这个设计其实挺聪明的它让项目不同模块可以自带独立的Skill模型只在触碰到相关文件时才会发现它们不会浪费token加载无关的Skill。但是如果你想让模型一开始就知道所有的Skill你就得把它们都放在根目录下的.claude/skills/里。不然的话模型可能永远都不会发现它们。五、语义匹配注入当Skill多到烧不起token的时候前面说的全量注入在Skill数量少的时候没问题。但是当你的项目里有200多个Skill的时候全量注入一次就要烧几千个token这谁顶得住啊就像你去超市买东西本来只想买瓶水结果超市把所有商品的清单都给你念一遍念完你都渴死了。所以Claude Code搞了个实验性功能叫skill_discovery。这个功能用Haiku模型做语义匹配只注入与当前任务相关的Skill。打开这个功能之后原来的skill_listing会被裁剪只保留bundled和MCP两类Skill。user/project/plugin的Skill会由skill_discovery按需匹配注入。skill_discovery有两条触发路径用户消息触发用户发送消息时在首次API调用前同步执行把用户输入、对话历史和上下文喂给HaikuHaiku返回匹配到的Skill列表。Agent Loop触发Agent Loop每轮循环开始时尝试启动异步预取。但只有当本轮有工具真正写入了文件时才会执行Haiku调用否则直接跳过。为什么只有写入文件时才触发因为prod数据显示早期实现每轮都调用Haiku结果97%的调用什么都匹配不到。改成只在文件变更时触发大幅减少了无意义的调用。我当时看到这个数据的时候笑了半天。合着97%的情况下模型根本不需要任何额外的Skill全量注入纯属浪费token。打开skill_discovery之后模型在同一轮对话中可能同时看到两条system-reminder# skill_listing 发的始终存在只是内容变少了 The following skills are available for use with the Skill tool: - graphify: any input to knowledge graph... - sensight: 实时查询各平台热榜... # skill_discovery 发的按需出现 Skills relevant to your task: - article-publish-review: 对技术文章做发布前审查 These skills encode project-specific conventions. Invoke via Skill(name) for complete instructions.如果skill_discovery没有匹配到任何Skill整个attachment就会被过滤不注入任何内容。这个功能我亲测过开了之后token消耗直接降了一半而且模型调用Skill的准确率还提高了。以前模型经常会调用一些不相关的Skill现在只会调用跟当前任务相关的。当然模型也不是完全依赖自动注入。它还可以主动调用DiscoverSkillsTool来触发发现。比如当任务转向、遇到非常规工作流的时候模型可以自己搜索系统可能遗漏的Skill。六、设计取舍每一个决策背后都是血泪史最后跟大家聊聊Claude Code的设计取舍。每一个看起来很奇怪的决策背后都是无数次踩坑踩出来的。我给大家列几个最有意思的为什么首次用户输入时就注入skill_listing因为要确保模型从第一轮就知道有哪些Skill可用。不然的话模型可能会自己想办法解决问题而不是调用现成的Skill。就像你雇了个保姆你不告诉她家里有洗衣机她可能会用手洗所有的衣服。为什么skill_listing要去重发送废话不然每轮都重复通知token早就烧没了。我见过有人因为没做去重一天烧了1000美元的API账单直接原地心梗。为什么压缩后不重置skill_listing因为重新注入一次要4K token而且那些几十轮都没用到的Skill大概率跟当前任务没关系重新注入纯属浪费。就像你搬家的时候不会把十年都没穿过的衣服也带走一样。为什么信任模型的长上下文注意力因为如果每轮都重新注入token消耗会爆炸。这就是一个设计赌注赌模型能记住第一轮注入的Skill列表。当然这个赌注有时候会输比如到了第50轮模型可能就忘了还有某个Skill存在。这时候你只能手动用斜杠命令调用它。为什么只在文件写入时触发skill发现因为prod数据显示97%的Haiku调用无结果。工具没有写文件的时候模型大概率不需要任何新的Skill。这就像你去饭店吃饭只有当你坐下点菜的时候服务员才会给你菜单不会你一进门就把菜单塞给你。你看这些设计取舍没有一个是完美的。每一个都有它的优点和缺点。但是综合来看这已经是目前最好的解决方案了。七、写在最后今天我把Claude Code的Skill动态发现机制扒了个底朝天。从静态注入到Skill工具从动态注入到语义匹配注入每一个环节我都给大家讲清楚了。现在你应该知道为什么你的AI会自动执行代码了。它不是成精了也不是抽风了是Skill动态发现机制在搞鬼。其实这个机制设计得真的挺巧妙的。它没有用任何硬编码规则全靠模型的推理能力来决定什么时候调用哪个Skill。这让Claude Code变得非常灵活可以适应各种不同的项目和工作流。当然它也不是完美的。有时候它会调用不相关的Skill有时候它会忘记某个Skill的存在有时候它会干出一些让你意想不到的事情。但是总的来说它已经比市面上所有的AI编程助手都要好用了。我搞AI22年了见过太多的技术来来去去。但是我觉得Skill动态发现机制可能是AI编程助手未来的发展方向。它让AI不再是一个简单的代码生成器而是一个真正的编程助手可以帮你完成整个开发流程。最后希望这篇文章能帮到大家。如果你也遇到过AI自动执行代码的情况欢迎在评论区留言分享你的经历。P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。