
1. 从一次真实的 No skills found 说起你在~/.claude/skills/下认认真真写好了SKILL.md目录结构看着也没毛病结果在 Claude Code 里敲下/skills屏幕上冷冰冰地回你一句No skills found.。这种「文件明明在工具就是装看不见」的体验比直接报语法错误还让人抓狂因为你连从哪下手都不知道。这个问题的本质是 Claude Code 的 skills 加载机制对目录层级、入口文件名、YAML frontmatter 格式三件事同时有硬性要求任何一项不满足这个 skill 就会被静默跳过——注意是静默它不会告诉你「第 3 个 skill 的 frontmatter 解析失败」只会整体告诉你一个都没找到。所以排查思路必须是「逐项排除」而不是盯着某一个点死磕。这篇内容适合三类人刚接触 Claude Code skills 机制、想给自己搭一套可复用技能库的新手从别人那里拷贝了 skill 目录却加载不出来的开发者以及用插件市场安装 skill 后发现状态异常的团队用户。我会把三个根因拆开讲清楚每个都配上可以直接复制执行的验证命令最后给一份能照着抄的SKILL.mdfrontmatter 模板。在开始之前先明确一个概念Claude Code 的 skill 不是「一个文件」而是「一个目录 一个约定命名的入口文件」。你可以把它类比成 npm 包——package.json决定这个包能不能被识别SKILL.md里的 frontmatter 就扮演类似的角色。理解这一点后面所有排查都会顺很多。2. 三个根因路径、命名、frontmatter 格式2.1 目录层级放错是最常见的原因Claude Code 扫描 skills 时期望的结构是「每个 skill 一个独立子目录」入口文件放在子目录里面~/.claude/skills/ └── my-skill/ └── SKILL.md很多人第一次写会犯的错是直接把SKILL.md丢在skills/根目录下~/.claude/skills/ └── SKILL.md # 错误缺少独立子目录这种情况下扫描器遍历skills/下的子目录时发现根目录下没有符合「目录 SKILL.md」结构的项自然就报No skills found。先用这条命令确认层级ls -la ~/.claude/skills/ find ~/.claude/skills/ -name SKILL.md -maxdepth 2find的输出应该形如~/.claude/skills/my-skill/SKILL.md如果它直接输出~/.claude/skills/SKILL.md那就是层级错了把文件挪进一个子目录即可。2.2 入口文件名大小写不匹配约定文件名是全大写的SKILL.md。在 macOS 默认的大小写不敏感文件系统上skill.md或Skill.md看起来「能用」但 Claude Code 内部做的是精确字符串匹配skill.md不会被识别。Linux 服务器上更直接文件名不一致就是找不到。# 精确列出文件名确认大小写 ls -1 ~/.claude/skills/my-skill/输出必须是SKILL.md不能是skill.md、Skill.MD或SKILL.markdown。改名命令mv ~/.claude/skills/my-skill/skill.md ~/.claude/skills/my-skill/SKILL.md2.3 YAML frontmatter 格式错误会被静默跳过这是最隐蔽的一类。SKILL.md开头必须是一段用---包裹的 YAML frontmatter里面至少要有name和description两个字段。常见错误包括开头少了第一个---、结尾少了第二个---、description里用了未转义的特殊字符、缩进用了 Tab 而不是空格。一个合法的 frontmatter 长这样--- name: my-skill description: 当用户需要处理特定任务时使用说明触发场景和适用边界 ---注意---必须顶格写在文件第一行前面不能有空行、注释或 BOM 字符。如果你是从网页复制的模板很可能带上了不可见的 BOM用下面这条命令检查head -c 3 ~/.claude/skills/my-skill/SKILL.md | xxd正常输出应该是2d 2d 2d即三个-。如果开头是ef bb bf说明有 BOM需要去掉sed -i 1s/^\xEF\xBB\xBF// ~/.claude/skills/my-skill/SKILL.md2.4 用户级与项目级路径混淆Claude Code 支持两个作用域用户级~/.claude/skills/全局生效项目级.claude/skills/只在当前项目生效。如果你期望某个 skill 全局可用却放进了项目目录换个项目就找不到了反过来把项目专属 skill 放进用户级又会在所有项目里冒出来干扰。# 用户级 ls -la ~/.claude/skills/ # 项目级在项目根目录执行 ls -la .claude/skills/两个路径的目录结构约定完全一致区别只在作用范围。团队协作的项目专属 skill 建议放项目级并纳入版本管理个人通用习惯放用户级。3. 可复制的 SKILL.md 模板与配置片段3.1 标准 frontmatter 模板下面这份模板可以直接复制改掉name和description就能用--- name: code-review-helper description: 当用户提交代码需要审查、或询问代码质量改进建议时使用。适用于 Python、TypeScript 和 Go 项目聚焦可读性、边界处理和潜在 bug。 --- # Code Review Helper ## 使用场景 当用户粘贴代码片段并询问改进意见时按以下步骤执行。 ## 执行步骤 1. 先通读代码识别明显的逻辑错误和边界问题 2. 检查命名是否清晰、函数职责是否单一 3. 给出具体修改建议附带修改后的代码片段 ## 输出格式 用 Markdown 列表列出问题每条包含「问题描述 修改建议 示例代码」。description字段很关键它不只是给人看的说明模型会依据这段文字判断「当前对话是否该触发这个 skill」。所以描述要写清楚触发场景而不是泛泛地说「这是一个有用的工具」。3.2 项目级 settings.json 配置片段如果你通过项目配置管理 skill 加载settings.json里可以显式声明。路径是项目根目录下的.claude/settings.json{ skills: { enabled: true, paths: [ .claude/skills, ~/.claude/skills ] } }注意paths里的路径是相对于项目根目录解析的~会被展开为用户主目录。如果你只想要项目级 skill把用户级那条删掉即可。改完配置后需要重启 Claude Code 会话才会重新扫描。3.3 用脚本批量校验所有 skill手动一个个查太慢写个小脚本一次性校验目录结构、文件名和 frontmatter#!/usr/bin/env bash SKILLS_DIR${1:-$HOME/.claude/skills} echo 扫描目录: $SKILLS_DIR for dir in $SKILLS_DIR/*/; do name$(basename $dir) file$dir/SKILL.md if [ ! -f $file ]; then echo [缺失] $name 下没有 SKILL.md continue fi first_line$(head -n 1 $file) if [ $first_line ! --- ]; then echo [格式错误] $name 的 SKILL.md 首行不是 --- continue fi if ! grep -q ^name: $file || ! grep -q ^description: $file; then echo [字段缺失] $name 缺少 name 或 description continue fi echo [通过] $name done保存为check-skills.shchmod x后执行./check-skills.sh它会逐个报告每个 skill 的状态比肉眼扫快得多。4. 验证请求与成功结果4.1 重启会话后重新扫描skill 的扫描通常只在会话启动阶段执行一次中途新增的文件不会自动被索引。所以改完文件后先完全退出再重启# 退出所有 Claude Code 进程后重新启动 claude进入会话后执行/skills如果配置正确你会看到类似下面的输出列出每个已识别的 skill 名称和描述Available skills: - code-review-helper: 当用户提交代码需要审查时使用... - doc-writer: 当用户需要生成技术文档时使用...4.2 用最小 skill 做对照实验如果还是No skills found建议先建一个最小可用的 skill 排除干扰。新建一个只有最简 frontmatter 的 skillmkdir -p ~/.claude/skills/minimal-test cat ~/.claude/skills/minimal-test/SKILL.md EOF --- name: minimal-test description: 最小测试 skill用于验证加载机制是否正常 --- 这是一个测试 skill。 EOF重启后执行/skills如果minimal-test出现了说明加载机制本身没问题问题出在你原来那个 skill 的细节上如果它也没出现那就是路径或全局配置的问题回到第 2 节重新核对。4.3 确认 skill 能被模型触发skill 出现在列表里只代表「被识别」不代表「会被自动调用」。触发是模型自主判断的取决于description写得够不够明确。测试方法是在对话里直接描述一个匹配场景看模型是否引用该 skill帮我审查这段 Python 代码看看有没有边界问题。如果模型没有触发把description改得更具体比如加上「当用户粘贴代码并询问改进建议时使用」而不是「用于代码相关任务」。5. 常见报错逐条排查5.1 报错 No skills found 但目录确实有文件先跑第 3.3 节的校验脚本它会直接告诉你哪个 skill 卡在哪一步。90% 的情况是目录层级或文件名大小写问题。如果脚本全部通过却仍然报错检查是不是有多个 Claude Code 进程在跑旧进程缓存了启动时的扫描结果ps aux | grep claude把所有相关进程杀掉后重新启动。5.2 报错 local proxy failed 或连接异常这类报错和 skill 加载本身无关通常是网络请求链路的问题。如果你在配置里用了自定义的 API 端点确认 Base URL 写对了。以 TaoToken 为例API 端点是https://taotoken.net/api配置时不要多加路径后缀。检查你的环境变量echo $ANTHROPIC_BASE_URL echo $ANTHROPIC_API_KEYBase URL 和 Key 要成对出现缺一个都会导致请求失败。Key 可以在控制台的 API Keys 页面生成https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapikeys5.3 报错 401 Unauthorized401 说明 Key 无效或过期。先确认 Key 没有多余空格echo -n $ANTHROPIC_API_KEY | wc -c如果长度明显不对重新复制一次。生成新 Key 后记得重启会话让环境变量生效。如果你用的是auth.json方式管理凭证Codex 类工具常见确认文件里的字段名和格式正确{ api_key: sk-xxxxxxxx, base_url: https://taotoken.net/api }5.4 报错 reading choices 或响应解析失败这类报错通常出现在流式响应解析阶段原因可能是模型 ID 写错了。确认你配置的 Model ID 和实际可用的模型一致。在 TaoToken 的模型对话页面可以快速验证某个模型 ID 是否可用https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel_chat5.5 OAuth 相关报错如果你用的是 OAuth 登录方式而非 API Key报错通常和 token 刷新有关。先退出登录再重新授权claude logout claude login如果反复失败改用 API Key 方式接入会更稳定配置文档在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc5.6 排查速查清单检查项命令期望结果目录层级find ~/.claude/skills -name SKILL.md -maxdepth 2路径含子目录文件名大小写ls -1 ~/.claude/skills/my-skill/输出SKILL.mdfrontmatter 首行head -n 1 SKILL.md输出---BOM 字符head -c 3 SKILL.md | xxd2d 2d 2d必需字段grep -E ^(name|description): SKILL.md两行都命中进程状态ps aux | grep claude无残留旧进程6. 长期编码场景下的接入建议如果你打算把 Claude Code 当作日常主力编码工具而不是偶尔试试那 skill 库会越攒越多这时候接入方式的稳定性就很重要。我自己的做法是把 API 接入和 skill 管理分开处理接入层用固定的 Base URL Key Model ID 三件套skill 层用项目级目录 版本管理。三件套的配置方式以环境变量为例export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYsk-你的key export ANTHROPIC_MODELclaude-sonnet-4-5三个变量缺一不可Base URL 决定请求发往哪里Key 决定身份Model ID 决定用哪个模型。写进~/.bashrc或~/.zshrc后source一下即可持久生效。如果你需要长期跑 Agent 类任务、或者团队多人共用一套编码环境Coding Plan 会比按量计费更省心具体方案可以看这里https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcodingplan最后回到 skill 本身建议你把每个 skill 的description当成「给模型看的触发说明书」来写而不是「给人看的备注」。写得越具体模型判断触发时越准也就越少出现「skill 明明加载了却从不被调用」的尴尬。项目级的 skill 目录记得纳入 git团队克隆后自动获得一致配置这比每个人手动拷贝靠谱得多。