本文摘要:Skill 放对目录仍不生效是静默失败,常被误判为模型问题。本文复现目录冲突、frontmatter 缺失与 instincts 抢占三种失败,用日志确认加载。
一、问题与结论
从 mattpocock/skills 复制一个 Skill 到项目根目录的 .agents/skills/,敲 /skills,列表是空的;把它挪进 .claude/skills/,列表还是空的;装上 ECC 之后,原本能触发的 code-review Skill 也沉默了。三个现象看起来是三个 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,项目根目录下操作。
bash
mkdir -p .claude/skills
git clone --depth 1 https://github.com/mattpocock/skills /tmp/skills-repo
find /tmp/skills-repo -name SKILL.md
cp -r /tmp/skills-repo/.agents/skills/repo-structure .claude/skills/repo-structure
head -10 .claude/skills/repo-structure/SKILL.md
find 会显示该仓库的 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 为主力的单工具工作流;多代理共存、或依赖某个插件的会话级注入时,目录统一与优先级假设都需要重新评估。