本文摘要:Skill 放对目录仍不生效是静默失败,常被误判为模型问题。本文复现目录冲突、frontmatter 缺失与 instincts 抢占三种失败,用日志确认加载。
一、问题与结论
从mattpocock/skills复制一个 Skill 到项目根目录的.agents/skills/,敲/skills,列表是空的;把它挪进.claude/skills/,列表还是空的;装上 ECC 之后,原本能触发的code-reviewSkill 也沉默了。三个现象看起来是三个 bug,其实只有三类根因。
结论先给:第一,Claude Code 只原生扫描.claude/skills/,.agents/是社区多工具共用约定,不在扫描范围内;第二,SKILL.md的 frontmatter 缺description,或name与目录名不一致,文件即使在正确路径也不会进索引;第三,ECC 的 instincts 在会话开始时先于 Skills 的描述匹配注入,抢占了触发优先级。另外还有一条容易被忽略的:已启动的会话不会重新扫描 Skills 目录,改动后必须重启会话,否则/skills给你的是缓存里的旧结果——这也是"我明明改了怎么还没生效"的直接来源。
二、排查与选择依据
按代价从低到高走三步,每步都能独立证伪一个假设:
- 确认路径:
find . -name SKILL.md看文件到底落在哪个目录;只有.claude/skills/下的会被扫描。 - 确认 frontmatter:
head -10打开文件,检查name、description是否齐全且name与目录名一致。 - 确认优先级:禁用 ECC 后重启会话,重复同一个请求;若 Skill 恢复触发,根因就是 instincts 抢占而非 Skill 配置错误。
排查到第 3 步时,通常已经要动配置了,先看取舍。
替代方案与取舍
| 替代方案 | 选择条件 | 代价与边界 |
|---|---|---|
以.claude/skills/为唯一真源,ln -s到.agents/skills | Claude Code 是主力,其他工具需要共读同一份 Skill | 一次软链接即可;不支持符号链接的 CI 或 Windows 环境需改为复制脚本 |
在CLAUDE.md中声明.agents/下存在 Skills | 团队坚持.agents/目录约定 | 依赖上下文注入时机,Skill 仍可能不进/skills索引,效果需实测 |
把 ECC 的 instincts 逐条改写成SKILL.md | 想保留 ECC 功能又消除优先级冲突 | 需要读 ECC 源码并人工转化,成本中等 |
只细化 Skill 的description以提高触发优先级 | 不愿改目录结构、也不想动插件 | 改 frontmatter 即可,但匹配逻辑在 Claude Code 内部,效果未验证 |
不该用本文方案的情况:项目里 Claude Code 只是多个代理之一,且各代理都坚持自己的扫描路径时,强行统一到.claude/skills/会让其他工具失明——这时按工具分目录、用脚本同步比软链接更可控。
三、关键原理
Skills 的生效链路有四个环节,任一环断裂都是静默失败:扫描路径 → frontmatter 索引 → 会话级缓存 → 触发优先级。官方anthropics/skills仓库把标准路径定在.claude/skills/<skill-name>/SKILL.md,frontmatter 的name与description共同构成身份与触发条件;缺description时文件存在但不入索引。ECC 同时提供 Skills、instincts、memory 三类注入源,其中 instincts 是会话级行为指令,注入时机早于 Skills 的描述匹配——这就是"插件启用顺序"问题:instincts 先到,泛化指令吃掉了本该落到具体 Skill 的请求。
四、可运行示例
环境:Claude Code 2.x、macOS 或 Linux、已安装 Git,项目根目录下操作。
mkdir-p.claude/skillsgitclone--depth1https://github.com/mattpocock/skills /tmp/skills-repofind/tmp/skills-repo-nameSKILL.mdcp-r/tmp/skills-repo/.agents/skills/repo-structure .claude/skills/repo-structurehead-10.claude/skills/repo-structure/SKILL.mdfind会显示该仓库的 Skill 全部位于.agents/之下;复制后用head -10检查 frontmatter。随后重启 Claude Code 会话(旧会话带着缓存,不重启这一步等于白做),执行/skills。
预期输出:/skills列出repo-structure,说明路径与 frontmatter 都通过。
实际输出(未在本环境实测,按上述失败条件推演):repo-structure不在列表中——若文件确在.claude/skills/下,则是 frontmatter 缺description;若仍在.agents/skills/下,则是路径未被扫描。
常见失败与修复:frontmatter 不完整或name与目录名不一致 → 在SKILL.md顶部补齐name、description并使两者与目录名相同;改完仍不出现 → 退出并重启会话以丢弃扫描缓存;重启后出现但调用时被泛化回答替代 → 禁用 ECC 对照,确认 instincts 抢占。
五、验证结果与边界
可以确认的部分:.agents/不在 Claude Code 原生扫描范围内,.claude/skills/是官方仓库定义的路径,frontmatter 字段缺失会导致不入索引。未验证的部分:ECC instincts 与 Skills 的优先级关系是依据其"Skills, instincts, memory"功能描述的推断,具体版本行为需实测;调试日志能否直接打印扫描到的 Skill 清单,也未在 2.x 上验证。本文方案适合 Claude Code 为主力的单工具工作流;多代理共存、或依赖某个插件的会话级注入时,目录统一与优先级假设都需要重新评估。
参考资料
- anthropics/skills
- mattpocock/skills
- affaan-m/ECC