Chapter 6: Skills — 构建你自己的斜杠命令
附录链接:A01 提示工程 讲解了如何编写高效的 skill 指令以产出一致、高质量的输出。编写 skill Markdown 文件时可以运用那些技巧。
你将构建什么
三个从顶级仓库中提取的生产级 Skill:
/deep-research— 多源调研,带引用和结构化报告(来自 ECC)/review— 基于置信度的代码审查,带严重程度评级和 file:line 引用(来自 gstack)/investigate— 根因调试,读取日志、追踪代码路径、定位 bug
这些使用的是 Everything Claude Code 和 gstack 在生产团队中部署的同一模式。
Skill 工作原理
Skill 是 .claude/skills/ 中的一个 Markdown 文件,会变成斜杠命令。当你在 Claude Code 中输入 /review 时,它加载对应文件,替换你的参数,Claude 按照指令执行。
你输入: /review src/auth/login.ts
|
v
Claude 加载 .claude/skills/review.md
|
v
读取 YAML frontmatter(name、tools、context 模式)
|
v
将 $ARGUMENTS 替换为 "src/auth/login.ts"
|
v
执行 !`backtick` 命令注入动态上下文
|
v
Claude 按照 skill 指令执行Skill vs CLAUDE.md
| CLAUDE.md | Skill | |
|---|---|---|
| 加载时机 | 每次会话自动加载 | 按需加载,输入 /命令 时 |
| 用途 | 项目规则、编码规范 | 特定任务的特定工作流 |
| 作用域 | 始终活跃 | 仅在执行期间活跃 |
| 类比 | 团队手册 | 需要时拿出来的电动工具 |
经验法则:如果规则适用于每次交互,放进 CLAUDE.md。如果是手动触发的特定工作流,做成 skill。
SKILL.md 格式
---
name: review
description: "Confidence-based code review with severity ratings"
user-invocable: true
context: fork
allowed-tools:
- Read
- Glob
- Grep
- Bash
---
你的 skill 指令在这里。
用户的参数: $ARGUMENTSFrontmatter 字段
| 字段 | 类型 | 作用 |
|---|---|---|
name | string | 斜杠命令名(review 变成 /review) |
description | string | 在 / 自动补全菜单中显示 |
user-invocable | boolean | true = 出现在菜单中,false = 仅 agent 可调用 |
allowed-tools | list | 该 skill 可使用的工具白名单 |
context | string | fork 在子 agent 中运行(保持主上下文干净) |
disable-model-invocation | boolean | true = 纯模板,不调用模型 |
动态上下文注入
使用 !`command` 在 skill 加载时运行命令并注入输出:
当前分支: !`git branch --show-current`
最近 5 次提交: !`git log --oneline -5`Claude 看到的是实际输出,而不是命令本身。这样可以节省工具调用次数。
context: fork — 保持上下文干净
重度 skill(大量文件读取、长输出)应使用 context: fork。Skill 在子 agent 中运行,有自己的上下文窗口。只有最终结果返回主会话。
主会话(保持干净)
|
+--> 分叉的子 agent
| 读取 50 个文件
| 分析模式
| 生成报告
|
<-- 只有报告返回(~500 tokens)不使用 fork 的话,所有 50 次文件读取都会消耗你的主上下文,导致更快的压缩和质量下降。
Skill 文件位置
.claude/skills/ <-- 项目级 skill(提交到 Git,团队共享)
~/.claude/skills/ <-- 个人 skill(不提交,仅个人使用)同名时项目级 skill 覆盖个人级 skill。
Demo 15: /deep-research Skill
灵感来自 ECC 的
/deep-researchskill -- 多源调研,结构化输出带引用。
问题
你需要了解一项技术、评估一个库或研究一个架构模式。你可以花 30 分钟读博客和文档,或者让 Claude 在 2 分钟内完成系统化调研并提供引用。
构建
1. 准备
mkdir -p ~/claude-demos/demo-15 && cd ~/claude-demos/demo-15
git init && git branch -M main
mkdir -p .claude/skills src
cat > CLAUDE.md << 'EOF'
# Research Demo Project
- When researching, cite specific sources
- Present findings in structured format
- Be honest about confidence levels
EOF
cat > package.json << 'EOF'
{
"name": "research-demo",
"version": "1.0.0",
"type": "module"
}
EOF
git add -A && git commit -m "feat: initial setup"2. 创建 Skill
cat > .claude/skills/deep-research.md << 'SKILLEOF'
---
name: deep-research
description: "Multi-source research with citations and structured analysis"
user-invocable: true
context: fork
allowed-tools:
- Bash
- Read
- Glob
- Grep
---
# Deep Research
You are a senior engineer conducting thorough research. Your job is to produce a well-sourced, structured analysis that someone could use to make a real decision.
## Research Topic
$ARGUMENTS
## Process
### Phase 1: Gather Sources
Search for information using multiple approaches:
1. Check if there are relevant files in the current project (grep for mentions, check package.json dependencies)
2. Use `bash` to query package registries: `npm info <package>`, `pip show <package>`, etc.
3. Check GitHub stats if relevant: `gh api repos/<owner>/<repo> --jq '.stargazers_count, .open_issues_count, .pushed_at'`
4. Look at the project's own code for existing usage patterns
### Phase 2: Analyze
For each source of information, evaluate:
- **Recency**: When was this information last updated?
- **Reliability**: Official docs vs blog post vs Stack Overflow answer
- **Relevance**: Does this directly address the research question?
### Phase 3: Report
Output a structured report in this exact format:
```markdown
# Research: [Topic]
## Summary
[2-3 sentence executive summary]
## Key Findings
### Finding 1: [Title]
- **Source**: [Where this came from]
- **Confidence**: High/Medium/Low
- **Details**: [What you found]
### Finding 2: [Title]
...
## Comparison Table (if applicable)
| Criterion | Option A | Option B |
|-----------|----------|----------|
| ... | ... | ... |
## Recommendation
[What you would actually recommend and why]
## Caveats
- [What you're not sure about]
- [What needs more investigation]
## Sources
1. [Source with specific location/URL]
2. ...Rules
- Never make up information. If you can't find something, say so.
- Confidence levels matter: High = verified from official sources, Medium = from reliable community sources, Low = inferred or from a single source.
- Include version numbers and dates wherever possible.
- If you find conflicting information, present both sides. SKILLEOF
git add .claude/skills/deep-research.md git commit -m "feat: add /deep-research skill"
#### 3. 测试
```bash
claude/deep-research Compare Vitest vs Jest for a TypeScript monorepo — performance, DX, migration path> /deep-research Compare Vitest vs Jest for a TypeScript monorepo — performance, DX, migration path
⏳ Forking subagent for deep-research...
● Bash: npm info vitest version
→ 3.2.1
● Bash: npm info jest version
→ 30.0.2
● Bash: gh api repos/vitest-dev/vitest --jq '.stargazers_count'
→ 14832
● Read: package.json
→ Checking current test dependencies...
● Bash: npm info vitest time --json | jq 'to_entries | last'
→ {"key":"3.2.1","value":"2025-05-12T..."}
✔ Subagent complete. Result:
# Research: Vitest vs Jest for TypeScript Monorepo
## Summary
Vitest offers significantly faster execution for TypeScript projects
due to native ESM and Vite-based transforms. Jest 30 closed the gap
with its new ESM support, but migration cost is low if you are
already using Vite.
## Key Findings
...再试一个:
/deep-research What are the security implications of using JWT tokens stored in localStorage vs httpOnly cookies?刚才发生了什么?
要点:
- Skill 在分叉的子 agent 中运行,保持主上下文干净
- Claude 从多个来源(npm 注册表、GitHub API、本地文件)收集数据后才形成结论
- 报告中的每个发现都包含置信度等级和来源归属
context: fork设置意味着只有最终报告返回到你的会话
为什么这个模式有效
ECC 中这个 skill 是使用率最高的之一。关键设计决策:
context: fork-- 调研产生大量上下文(文件读取、命令输出)。Fork 保持主会话干净。- 结构化输出 -- 报告格式是刻意严格的。它迫使 Claude 组织发现而不是写一堆文字。
- 置信度等级 -- 这是有用的调研和臆想的调研之间的区别。Claude 必须为每个发现标注置信度。
- 多源交叉验证 -- Skill 指导 Claude 交叉参考,而不是只抓第一个答案。
Demo 16: /review Skill
灵感来自 gstack 的
/reviewskill -- 基于置信度的代码审查,带具体 file:line 引用。
问题
代码审查是最常见的 AI 辅助任务,但大多数人只是说"审查这段代码",得到模糊的反馈。gstack 的方法不同:每个发现都有置信度分数、严重程度评级和具体 file:line 引用。置信度低于 80% 的发现被过滤掉。
构建
1. 创建待审查代码
cd ~/claude-demos/demo-15
# Create code with real issues at specific lines
mkdir -p src/api
cat > src/api/users.js << 'EOF'
import { db } from '../db.js';
import { hash } from '../utils/crypto.js';
export async function createUser(req, res) {
const { username, email, password } = req.body;
// Line 7: No input validation at all
const hashedPassword = await hash(password);
// Line 10: SQL injection via string interpolation
const existing = await db.query(
`SELECT id FROM users WHERE email = '${email}'`
);
if (existing.rows.length > 0) {
return res.status(409).json({ error: 'Email taken' });
}
// Line 18: Another SQL injection
const result = await db.query(
`INSERT INTO users (username, email, password)
VALUES ('${username}', '${email}', '${hashedPassword}')`
);
// Line 23: Returning the hashed password in the response
return res.status(201).json({
id: result.rows[0].id,
username,
email,
password: hashedPassword
});
}
export async function deleteUser(req, res) {
// Line 31: No auth check — any user can delete any other user
const { id } = req.params;
await db.query(`DELETE FROM users WHERE id = ${id}`);
return res.json({ success: true });
}
export async function listUsers(req, res) {
// Line 38: No pagination — will OOM on large tables
const result = await db.query('SELECT * FROM users');
// Line 40: Returning all fields including password hashes
return res.json(result.rows);
}
EOF
git add -A && git commit -m "feat: add user API endpoints"2. 创建 Skill
cat > .claude/skills/review.md << 'SKILLEOF'
---
name: review
description: "Confidence-based code review with severity ratings and file:line references"
user-invocable: true
context: fork
allowed-tools:
- Read
- Glob
- Grep
- Bash
---
# Code Review
You are a senior engineer performing a thorough code review. This isn't a surface-level scan — you're looking for real issues that would block a PR or cause incidents in production.
## Target
Review: $ARGUMENTS
If no specific files are provided, review the changes on the current branch:
!`git diff main --name-only 2>/dev/null | head -20`
## Review Process
### Step 1: Read the Code
Read every file in scope. Don't skim — read line by line.
### Step 2: Analyze Each Finding
For every issue you find, assign:
- **Severity**: P0 (security/data loss), P1 (bug), P2 (code quality), P3 (style/nit)
- **Confidence**: 0-100%. Only report findings with confidence >= 80%.
- **File:Line**: Exact location, e.g., `src/api/users.js:10`
### Step 3: Generate Report
Use this exact format for each finding:[P0] SQL Injection in user query File: src/api/users.js:10 Confidence: 95% Problem: User input is interpolated directly into SQL string. The email parameter from req.body is inserted without parameterization, allowing arbitrary SQL execution. Fix: Use parameterized queries. const existing = await db.query( 'SELECT id FROM users WHERE email = $1', [email] );
### Output FormatCode Review: [files reviewed]
Summary
- Files reviewed: N
- Findings: N (X critical, Y bugs, Z quality)
- Overall: APPROVE / REQUEST CHANGES / BLOCK
Critical (P0)
[findings...]
Bugs (P1)
[findings...]
Code Quality (P2)
[findings...]
Style (P3)
[findings...]
What's Good
[1-2 things the code does well — always include this]
### Rules
- **Be specific**: "auth.ts:47" not "the authentication module"
- **Confidence threshold**: Drop anything below 80%. False positives waste everyone's time.
- **Actionable fixes**: Every finding must include a concrete fix, not just "consider improving this"
- **No AI vocabulary**: Don't say "I'd suggest considering" — say "Change X to Y"
- P0 findings automatically mean REQUEST CHANGES or BLOCK
SKILLEOF
git add .claude/skills/review.md
git commit -m "feat: add /review skill"3. 测试
claude/review src/api/users.js> /review src/api/users.js
⏳ Forking subagent for review...
● Read: src/api/users.js
→ 42 lines read
● Grep: 'db.query' in src/
→ 5 matches across 1 file
● Grep: 'parameterized\|prepared\|\$[0-9]' in src/
→ 0 matches — no parameterized queries found
✔ Subagent complete. Result:
# Code Review: src/api/users.js
## Summary
- Files reviewed: 1
- Findings: 6 (3 critical, 1 bug, 2 quality)
- Overall: BLOCK
## Critical (P0)
[P0] SQL Injection in email lookup
File: src/api/users.js:11
Confidence: 98%
Problem: Email is interpolated directly into SQL via template literal.
Fix: Use parameterized query: db.query('SELECT id FROM users WHERE email = $1', [email])
[P0] SQL Injection in INSERT
File: src/api/users.js:19
Confidence: 98%
...
[P0] Missing authorization on deleteUser
File: src/api/users.js:31
Confidence: 95%
...刚才发生了什么?
要点:
- 80% 置信度门槛过滤掉了不确定的发现,保持报告聚焦
- 每个发现都有具体的 file:line 引用,而非模糊描述
- Skill 使用 Grep 交叉验证模式,不只是用 Read 扫描文件
- P0 发现自动触发 BLOCK 结论
"auth.ts:47" 而不是 "认证模块" 这条规则直接来自 gstack 的语言风格指南。它迫使 Claude 精确表达而不是含糊其辞。
Demo 17: /investigate Skill
一个根因调试 skill,像资深工程师一样追踪代码。
问题
有人报告了一个 bug。你可以问 Claude "这为什么坏了?"得到一个猜测,或者使用结构化的调查 skill,它会读取日志、追踪代码路径、定位根因,并给出带置信度的修复方案。
构建
1. 创建包含真实 Bug 的代码库
cd ~/claude-demos/demo-15
mkdir -p src/services src/utils
cat > src/services/order.js << 'EOF'
import { db } from '../db.js';
import { calculateTotal } from '../utils/pricing.js';
import { sendNotification } from '../utils/notify.js';
export async function placeOrder(userId, items) {
// Fetch product details
const products = [];
for (const item of items) {
const product = await db.query(
'SELECT * FROM products WHERE id = $1',
[item.productId]
);
products.push({ ...product.rows[0], quantity: item.quantity });
}
// Calculate total
const total = calculateTotal(products);
// Create order
const order = await db.query(
'INSERT INTO orders (user_id, total, status) VALUES ($1, $2, $3) RETURNING id',
[userId, total, 'confirmed']
);
// BUG: sendNotification is called with order.id but
// order is a query result object, not the order itself
await sendNotification(userId, order.id, total);
return { orderId: order.rows[0].id, total };
}
EOF
cat > src/utils/pricing.js << 'EOF'
export function calculateTotal(products) {
let total = 0;
for (const p of products) {
// BUG: floating point arithmetic without rounding
// 19.99 * 3 = 59.970000000000006
total += p.price * p.quantity;
}
// Missing: Math.round(total * 100) / 100
return total;
}
export function applyDiscount(total, discountPercent) {
// BUG: no validation — negative discount increases price
return total * (1 - discountPercent / 100);
}
EOF
cat > src/utils/notify.js << 'EOF'
export async function sendNotification(userId, orderId, total) {
// This will fail silently if orderId is undefined
// because order.id doesn't exist on the query result
console.log(`Order ${orderId}: $${total} for user ${userId}`);
// In production this would call an email/SMS service
// The silent failure means users never get confirmation
}
EOF
git add -A && git commit -m "feat: add order system with pricing and notifications"2. 创建 Skill
cat > .claude/skills/investigate.md << 'SKILLEOF'
---
name: investigate
description: "Root-cause debugging — trace code paths, identify the bug, propose fix"
user-invocable: true
context: fork
allowed-tools:
- Read
- Glob
- Grep
- Bash
---
# Bug Investigation
You are a senior engineer doing root-cause analysis. Don't guess — trace through the code systematically.
## Bug Report
$ARGUMENTS
## Investigation Process
### Phase 1: Reproduce
1. Read the reported symptoms carefully
2. Find the entry point in the code
3. Trace the execution path step by step
### Phase 2: Evidence Gathering
1. Read every file in the execution path
2. Check for error handling (or lack thereof)
3. Look at data transformations — where do values change?
4. Search for related issues: `grep -rn` for the function names, variable names
5. Check git history for recent changes: `git log --oneline -10 -- <file>`
### Phase 3: Root Cause Analysis
For each potential root cause:
- **Evidence**: What specific code points to this being the issue?
- **Confidence**: High/Medium/Low
- **Impact**: What's the blast radius?
### Phase 4: Report
```markdown
# Investigation: [Bug Title]
## Symptom
[What the user reported]
## Root Cause
[What's actually broken and why]
## Evidence Trail
1. [Entry point] -> [Function A at file:line]
2. [Function A] -> [Function B at file:line]
3. [Function B]: HERE IS THE BUG
- Expected: [what should happen]
- Actual: [what happens instead]
- Code: [the specific line]
## Contributing Factors
- [Other issues that make this worse]
## Fix
### Immediate Fix (do this now)
[Specific code change with before/after]
### Proper Fix (do this soon)
[More thorough solution]
## Prevention
- [How to prevent this class of bug in the future]Rules
- Follow the data. Read the actual code, don't guess based on function names.
- Every claim needs a file:line reference.
- If you find multiple bugs during investigation, report all of them, but clearly mark which one causes the reported symptom.
- "I don't know" is better than a wrong diagnosis. SKILLEOF
git add .claude/skills/investigate.md git commit -m "feat: add /investigate skill"
#### 3. 测试
```bash
claude/investigate Users report that order confirmation notifications are never received, and some order totals show values like $59.970000000000006 instead of $59.97> /investigate Users report that order confirmation notifications are never received, and some order totals show values like $59.970000000000006 instead of $59.97
⏳ Forking subagent for investigate...
● Grep: 'sendNotification' in src/
→ 2 matches: order.js:27, notify.js:1
● Read: src/services/order.js
→ 32 lines read
● Read: src/utils/notify.js
→ 8 lines read
● Read: src/utils/pricing.js
→ 14 lines read
● Bash: git log --oneline -10 -- src/services/order.js
→ 1 commit: "feat: add order system..."
✔ Subagent complete. Result:
# Investigation: Missing Order Notifications + Broken Totals
## Root Cause
Two separate bugs:
1. **Notifications (Primary)**: order.js:27 calls
sendNotification(userId, order.id, total) but `order` is a
pg query result object — it has `rows`, `rowCount`, `command`,
but no `.id` property. The correct access is
`order.rows[0].id`. The notification receives `undefined`
as the orderId.
2. **Totals**: pricing.js:5 accumulates floating point products
without rounding. 19.99 * 3 = 59.970000000000006.
## Evidence Trail
1. placeOrder (order.js:5) -> calculateTotal (pricing.js:1)
2. pricing.js:5: total += p.price * p.quantity ← no rounding
3. placeOrder (order.js:27): order.id ← WRONG, should be
order.rows[0].id
4. notify.js:4: silently logs "Order undefined: $59.97..."
...刚才发生了什么?
要点:
- Claude 追踪的是数据流,而非猜测 -- 从症状回溯到根因
- 两个 bug 都被识别并清晰区分:哪个导致了报告的症状,哪个是加重因素
- 每个结论都有 file:line 引用,有实际的代码读取支撑
- Git 历史检查确认了 bug 是原始的,不是回归
常见问题排查
Skill 找不到
你输入 /deep-research 但什么都没发生:
> /deep-research Compare React vs Vue
⚠ Unknown command: /deep-research
Available commands: /help, /clear, /compact, /review ...常见原因:
目录不对 -- Skill 从项目的
.claude/skills/目录加载。如果你在不同的目录启动 Claude,它找不到 skill。bash# 错误:在 home 目录启动 Claude cd ~ && claude # /deep-research 找不到,因为 ~/claude-demos/demo-15/.claude/skills/ 不在这里 # 正确:在项目目录启动 Claude cd ~/claude-demos/demo-15 && claudename字段拼写错误 -- Frontmatter 中的name必须和你输入的一致。如果文件是deep-research.md但 frontmatter 写的是name: deepresearch(没有连字符),/deep-research命令就无法解析。缺少
user-invocable: true-- 没有这个字段,skill 存在但不会出现在自动补全菜单中,用户也无法触发。
Skill 文件语法错误
如果 YAML frontmatter 格式错误,skill 将无法加载:
> /review src/api/users.js
⚠ Error loading skill: review
YAML parse error at line 3: bad indentation of a mapping entry常见 YAML 错误:
- 用 Tab 缩进而不是空格(YAML 要求用空格)
- 包含冒号的 description 没有加引号
allowed-tools列表缩进不正确
# 错误 — 未引用字符串中的冒号会破坏 YAML
description: Confidence-based review: with ratings
# 正确 — 引用字符串
description: "Confidence-based review with ratings"Skill 名称冲突
如果 .claude/skills/review.md(项目级)和 ~/.claude/skills/review.md(个人级)同时存在,项目级 skill 优先。如果你期望的是个人版本,这可能会造成困惑。
# 检查加载了哪些 skill
ls .claude/skills/ # 项目级 skill(更高优先级)
ls ~/.claude/skills/ # 个人级 skill(更低优先级)如果你想在特定项目中使用个人版本,要么移除项目级 skill,要么重命名其中一个。
Skill 设计模式
模式:守门员(来自 gstack 的 /ship)
---
name: ship
allowed-tools:
- Bash
- Read
---
Before deploying, verify ALL of these pass:
1. `git status` shows clean working tree
2. `npm test` passes with no failures
3. `npm run lint` passes with no errors
4. `npm run build` completes successfully
5. No P0/P1 issues in the last review
If ANY check fails, stop and report what failed. Do not proceed.模式:多角色管线(来自 gstack 的 /autoplan)
---
name: autoplan
context: fork
---
Evaluate this feature request from three perspectives:
**Product (CEO review)**: Is this worth building? Impact vs effort?
**Design (Design review)**: How should the UX flow work?
**Engineering (Eng review)**: What's the technical approach? What are the risks?
For each perspective, rate 1-10 and explain.
Conclude with: BUILD / DEFER / REJECT and next steps.模式:评估驱动(来自 ECC 的 /eval-harness)
---
name: eval
context: fork
---
Run the evaluation harness for: $1
1. Run the test suite 3 times: `npm test -- --reporter=json`
2. Calculate pass@1 (first run) and pass@3 (any of 3 runs)
3. Compare against the baseline in `.claude/eval-baseline.json`
4. Report regressions and improvements练习:构建 /changelog Skill
创建一个 /changelog skill,读取 git 历史并生成发布说明:
- 读取最近 N 次提交(默认 20,可通过
$1配置) - 按 Conventional Commit 类型分组(Features / Fixes / Other)
- 生成适合 GitHub Release 的 markdown
- 包含日期范围和贡献者列表
附加挑战:自动检测带 ! 的 commit 类型中的破坏性变更(如 feat!: remove legacy API)。
成功标准
- [ ] Skill 文件在
.claude/skills/changelog.md - [ ] 使用
context: fork(它会读取大量 git 历史) - [ ] 支持
$1参数控制提交数 - [ ] 使用
!`git log --oneline -5`注入动态上下文 - [ ] 按类型分组
- [ ] 输出可直接粘贴到 GitHub Releases
知识检测
总结
Skill 把重复性工作流变成一条命令的操作。本章的三个模式 -- 调研、审查、调查 -- 是生产环境中 Claude Code 最常用的 skill 类型。
要点:
context: fork对读取大量文件的 skill 至关重要 -- 保护主上下文- 置信度门槛(来自 gstack 的 80% 规则)防止误报
- 结构化输出格式迫使 Claude 组织而不是散漫
allowed-tools限制影响范围 -- 审查 skill 不应该能 Write 文件!`backtick`注入通过预加载上下文节省工具调用
深入了解:参见 A01 提示工程 了解如何编写产出一致、高质量输出的 skill 指令。让好的系统提示发挥作用的原则同样适用于 skill 文件。
下一章:Chapter 7: MCP 服务器集成 -- 通过 Model Context Protocol 将 Claude 连接到 GitHub、文档服务器和浏览器自动化。