调试 Skill:定位失败的系统化方法
Skill 的失败通常发生在以下四个层次:文件加载失败、参数解析错误、工具调用失败、输出质量问题。每个层次有不同的诊断方法。
快速诊断:失败在哪一层?
graph TD
A["Skill 执行异常"] --> B{"命令能识别吗?"}
B -->|不能识别| C["文件加载问题\n→ 检查文件路径和格式"]
B -->|能识别| D{"参数解析正确吗?"}
D -->|错误| E["参数问题\n→ 检查参数说明和验证逻辑"]
D -->|正确| F{"工具调用成功吗?"}
F -->|有工具失败| G["工具调用问题\n→ 检查命令、路径、权限"]
F -->|工具都成功| H{"输出符合预期吗?"}
H -->|格式错误| I["提示词质量问题\n→ 改进执行步骤描述"]
H -->|内容错误| J["逻辑/上下文问题\n→ 加强上下文说明"]
style C fill:#ffebee,stroke:#c62828
style E fill:#ffebee,stroke:#c62828
style G fill:#fff3e0,stroke:#ef6c00
style I fill:#e3f2fd,stroke:#1565c0
style J fill:#e3f2fd,stroke:#1565c0
层次一:文件加载问题
症状:运行 /skill-name 时提示"未知命令"
诊断清单:
# 1. 确认文件存在
ls .claude/skills/
# 2. 确认文件名与命令名一致(kebab-case)
# /review-pr → 文件名应该是 review-pr.md(不是 reviewPr.md)
# 3. 确认当前工作目录包含 .claude/
ls -la .claude/
# 4. 确认 frontmatter 格式正确(YAML)
# 检查是否有语法错误:--- 必须是第一行,且匹配关闭的 ---
常见的 frontmatter 格式错误:
# ❌ 错误:--- 前有空行
---
description: 这里有问题
---
# ❌ 错误:缩进不一致
---
description: ok
allowed-tools: Bash
---
# ✅ 正确格式
---
description: 描述文本
allowed-tools: Bash, Read
---
层次二:参数解析问题
症状:Skill 能运行,但忽略了传入的参数,或参数值解析不正确
诊断方法:
- 在 Skill 文件的执行步骤开头添加调试步骤:
## 执行步骤
0. **[调试步骤,测试完成后删除]** 输出以下信息:
- 收到的原始参数:$ARGUMENTS
- 解析的各参数值:[逐个列出]
然后继续正常执行。
- 用非常简单的参数测试,排除参数解析问题:
/review-pr --branch main --focus security
^以上是 $ARGUMENTS 的完整内容^
常见参数解析问题:
| 问题 | 表现 | 修复方法 |
|---|---|---|
| Claude 把参数当成上下文,不用于分支逻辑 | 传入 --focus security 但 Skill 仍做全面检查 | 在步骤中明确说明"根据 $ARGUMENTS 中的 --focus 值" |
| 参数名解析混淆 | --env staging 被误解为 --service staging | 在参数说明中明确参数名和对应含义 |
| 默认值未生效 | 缺少参数时 Skill 不使用默认值 | 在步骤中明确"如果 $ARGUMENTS 中没有 --xxx,使用默认值 yyy" |
层次三:工具调用问题
症状:Skill 在工具调用处停止,或工具返回了错误
诊断方法:
Claude Code 会显示工具调用的详情,观察:
# 工具调用日志示例
Bash 工具:git diff main...feature/auth --name-only
返回:fatal: ambiguous argument 'main...feature/auth'
→ 诊断:分支名可能不正确,或分支不存在
→ 修复:在 Skill 中添加分支存在性验证步骤
常见工具调用失败原因:
Bash 工具失败
# 问题:命令路径不正确
❌ Bash 命令:./node_modules/.bin/eslint src/
✅ 修复:npx eslint src/(更健壮,不依赖相对路径)
# 问题:命令输出到 stderr,被忽略
❌ npm audit(错误信息在 stderr)
✅ 修复:npm audit 2>&1(将 stderr 合并到 stdout)
# 问题:管道命令在 Claude 的工具中可能不稳定
❌ cat file.log | grep ERROR | wc -l
✅ 修复:grep -c ERROR file.log(使用单个命令)
Read 工具失败
# 问题:相对路径 vs 绝对路径
❌ Read 工具:~/project/src/api.ts(~ 在 Read 工具中可能无效)
✅ 修复:在 Skill 中先用 Bash 获取绝对路径,再用 Read
# 问题:文件不存在时没有优雅处理
✅ 修复:在 Skill 步骤中明确"如果 Read 失败,说明文件不存在,输出提示并跳过"
Write 工具失败
# 问题:Write 工具被 settings.json 的 deny 规则阻止
→ 检查 settings.json,确认目标路径被 allow
→ 或者修改 Skill 不需要写入文件
# 问题:目标目录不存在
✅ 修复:在写入前用 Bash 创建目录 mkdir -p .claude/reports/
层次四:输出质量问题
症状:Skill 能运行,但输出内容不正确、不完整、格式混乱
最常见的原因和修复:
原因 1:上下文不足
# ❌ 原因:执行步骤描述太抽象
## 执行步骤
1. 分析代码质量
2. 输出报告
# ✅ 修复:详细描述每个步骤的具体操作
## 执行步骤
1. 使用 Glob 工具找到所有 .ts 文件(模式:src/**/*.ts)
2. 对每个文件:
a. 使用 Read 工具读取内容
b. 检查以下具体模式:[列出模式]
3. 按文件汇总问题,生成报告
原因 2:输出格式描述不精确
# ❌ 不精确
## 输出格式
生成一个包含问题列表的报告。
# ✅ 精确,包含示例
## 输出格式
严格按以下格式输出,不要有额外的段落:
---
## 代码质量报告
**扫描文件数**:N
### 问题列表
| 文件 | 行号 | 问题 | 严重性 |
|------|------|------|--------|
| src/api.ts | 45 | console.log in production | 🟡 中 |
### 总结
[一句话总结]
---
原因 3:Claude 的创造性影响了结构稳定性
如果 Skill 每次输出的结构都不一样(有时有表格,有时是列表),需要更强的格式约束:
## 输出格式
⚠️ 重要:以下格式是必须遵守的,不要根据内容多少随意改变结构。
即使没有问题,也要保留"问题列表"这一节(内容写"无")。
即使只有一个问题,也要使用表格格式(不要改成纯文字)。
[格式模板]
调试检查清单
遇到 Skill 问题时,按顺序排查:
□ 1. 确认命令能被识别(/help 中有显示?)
□ 2. 检查 frontmatter YAML 格式是否正确
□ 3. 添加临时调试步骤输出 $ARGUMENTS 原始值
□ 4. 观察 Claude Code 的工具调用日志
□ 5. 单独运行工具中的 Bash 命令(在终端直接运行,排除 Skill 本身的问题)
□ 6. 对比实际输出 vs 期望输出,找到第一个差异点
□ 7. 修改对应的步骤描述,让指令更明确
□ 8. 重新运行,验证修复是否有效
下一节:Skill 的回归测试与质量基线——如何防止修改 Skill 后引入新的问题?如何建立 Skill 质量的长期基线?