你是不是每次都在重复输入同样的 Prompt?
“帮我生成 commit message”、“帮我跑一下测试”、“帮我格式化代码”……
这不是在用 AI,这是在当复读机。
Agent Skills 的出现,彻底改变了这个局面。它不是让你”调用”Claude,而是让 Claude 主动发现你封装好的能力,在合适的时机自动使用。
这才是真正的”模块化 AI”。
一、先搞清楚:Skills 和斜杠命令有什么区别?
很多人把 Skills 和斜杠命令搞混了。它们的本质区别在于谁来触发:
| 特性 | 斜杠命令 | Agent Skills |
|---|---|---|
| 触发方式 | 用户手动输入 /xxx | Claude 自动识别并调用 |
| 适用场景 | 快速执行固定任务 | 复杂工作流、专业知识封装 |
| 智能程度 | 被动执行 | 主动发现、自主决策 |
一句话总结:斜杠命令是”你叫它干啥它干啥”,Skills 是”它知道什么时候该干啥”。
二、Skills 的三种存放位置
1. 个人技能:~/.claude/skills/
- 在所有项目中都可用
- 适合个人工作流、实验性功能
- 不会被 git 追踪
2. 项目技能:.claude/skills/
- 通过 git 与团队共享
- 适合团队标准化流程
- 确保所有人用同一套工具
3. 插件技能
- 随插件安装自动可用
- 第三方开发者分发功能的标准方式
三、Skill 的核心:SKILL.md 文件
每个 Skill 都需要一个 SKILL.md 文件,包含 YAML 前置元数据:
---
name: 技能名称
description: 技能描述(决定 Claude 何时激活)
allowed-tools: Read, Grep, Glob # 可选:限制可用工具
---
# 技能说明
具体的指令和工作流程...
描述字段是关键中的关键
描述决定了 Claude 什么时候会激活你的技能。
好的描述:
Extract text and tables from PDF files when the user asks to read or analyze PDF content
差的描述:
Helps with documents
区别在哪?好的描述包含了:
- 技能的功能(提取 PDF 文本和表格)
- 触发时机(用户要求读取或分析 PDF)
- 具体用例(PDF content)
四、实战案例:从简单到复杂
案例 1:PDF 文本提取器
<!-- .claude/skills/pdf-extractor/SKILL.md -->
---
name: PDF Text Extractor
description: Extract text and tables from PDF files when user asks to read or analyze PDF content
allowed-tools: Read, Bash(pdftotext:*)
---
# PDF 文本提取
当用户提供 PDF 文件或要求分析 PDF 内容时:
1. 使用 `pdftotext` 提取文本内容
2. 格式化输出以提高可读性
3. 如果存在表格,尝试保留结构
4. 提供提取内容的摘要
## 前置条件
确保系统已安装 `pdftotext`。
## 使用示例
- "提取 report.pdf 中的文本"
- "这个 PDF 说了什么?"
- "分析 data.pdf 中的表格"
案例 2:只读代码分析器
这个技能的关键在于 allowed-tools 限制——只允许读取,不允许修改:
---
name: Read-Only Analyzer
description: Analyze code structure without making changes
allowed-tools: Read, Grep, Glob, Bash(ls:*)
---
# 只读代码分析器
提供全面的代码分析能力,但不修改任何文件。
## 分析能力
### 代码结构分析
```bash
# 列出目录结构
ls -la src/
# 查找所有 TypeScript 文件
find . -name "*.ts" -type f
# 分析 import 模式
grep -r "import.*from" src/ --include="*.ts"
依赖映射
# 检查 package.json 依赖
cat package.json | jq '.dependencies'
代码质量指标
# 统计代码行数
find src/ -name "*.ts" -exec wc -l {} + | tail -1
# 查找大文件
find . -name "*.ts" -exec du -h {} + | sort -rh | head -10
### 案例 3:Git 工作流助手
```markdown
---
name: Git Workflow Helper
description: Streamline Git operations with conventional commits and branch management
allowed-tools: Read, Write, Bash, Grep
---
# Git 工作流自动化
## Conventional Commit 生成器
```bash
# 分析暂存的更改
git diff --cached --name-only
# 根据更改生成提交消息
git status --porcelain
分支管理
# 创建符合命名规范的功能分支
git checkout -b feature/user-authentication
# 与主分支同步
git fetch origin
git rebase origin/main
提交消息模板
# 格式: type(scope): description
feat(auth): add JWT token validation
fix(api): resolve user creation timeout issue
docs(readme): update installation instructions
### 案例 4:数据库迁移助手
```markdown
---
name: Database Migration Assistant
description: Handle database schema migrations with safety checks and rollback support
allowed-tools: Read, Write, Bash, Grep
---
# 数据库迁移助手
## 迁移模板
```sql
-- migrations/001_create_users_table.sql
BEGIN;
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
COMMIT;
回滚脚本
-- rollbacks/001_create_users_table.sql
BEGIN;
DROP INDEX IF EXISTS idx_users_email;
DROP INDEX IF EXISTS idx_users_username;
DROP TABLE IF EXISTS users;
COMMIT;
迁移执行
# 检查当前迁移状态
npm run migrate:status
# 运行待处理的迁移
npm run migrate:up
# 回滚上一次迁移
npm run migrate:down
# 创建新迁移
npm run migrate:create add_user_roles
### 案例 5:API 测试助手
```markdown
---
name: API Testing Assistant
description: Generate and execute API tests with comprehensive coverage
allowed-tools: Read, Write, Bash, Grep
---
# API 测试框架
## 测试模板
```javascript
// tests/api/users.test.js
const request = require('supertest');
const app = require('../../app');
describe('Users API', () => {
describe('GET /api/users', () => {
it('should return all users', async () => {
const response = await request(app)
.get('/api/users')
.expect(200);
expect(response.body).toHaveProperty('data');
expect(Array.isArray(response.body.data)).toBe(true);
});
it('should handle pagination', async () => {
const response = await request(app)
.get('/api/users?page=1&limit=10')
.expect(200);
expect(response.body.data.length).toBeLessThanOrEqual(10);
});
});
describe('POST /api/users', () => {
it('should create a new user', async () => {
const userData = {
username: 'testuser',
email: 'test@example.com'
};
const response = await request(app)
.post('/api/users')
.send(userData)
.expect(201);
expect(response.body).toMatchObject(userData);
});
it('should validate required fields', async () => {
const response = await request(app)
.post('/api/users')
.send({})
.expect(400);
expect(response.body).toHaveProperty('errors');
});
});
});
测试执行
# 运行所有 API 测试
npm test -- tests/api/
# 运行特定测试文件
npm test -- tests/api/users.test.js
# 带覆盖率运行测试
npm run test:coverage
# 监视模式运行测试
npm run test:watch
### 案例 6:代码生成器
```markdown
---
name: Code Generator Pro
description: Generate boilerplate code with consistent patterns and best practices
allowed-tools: Read, Write, Grep, Glob
---
# 代码生成模板
## React 组件模板
```jsx
// src/components/UserCard/UserCard.jsx
import React from 'react';
import PropTypes from 'prop-types';
import styles from './UserCard.module.css';
const UserCard = ({ user, onEdit, onDelete }) => {
const handleEdit = () => onEdit(user.id);
const handleDelete = () => onDelete(user.id);
return (
<div className={styles.card}>
<div className={styles.header}>
<h3>{user.username}</h3>
<p>{user.email}</p>
</div>
<div className={styles.actions}>
<button onClick={handleEdit} className={styles.editButton}>
Edit
</button>
<button onClick={handleDelete} className={styles.deleteButton}>
Delete
</button>
</div>
</div>
);
};
UserCard.propTypes = {
user: PropTypes.shape({
id: PropTypes.number.isRequired,
username: PropTypes.string.isRequired,
email: PropTypes.string.isRequired,
}).isRequired,
onEdit: PropTypes.func.isRequired,
onDelete: PropTypes.func.isRequired,
};
export default UserCard;
Express 路由模板
// routes/users.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const { validateUser } = require('../middleware/validation');
router.get('/', userController.getAllUsers);
router.get('/:id', userController.getUserById);
router.post('/', validateUser, userController.createUser);
router.put('/:id', validateUser, userController.updateUser);
router.delete('/:id', userController.deleteUser);
module.exports = router;
---
## 五、Skill 设计的三条铁律
### 铁律 1:一个 Skill 只做一件事
**好的设计**:
- PDF 文本提取
- 数据库迁移助手
- Git 提交生成器
**差的设计**:
- 文档助手(太模糊)
- 开发者工具(太宽泛)
### 铁律 2:描述要具体到触发条件
不要写"帮助处理 Git",要写"当用户要求提交代码时,生成符合 Conventional Commits 规范的提交消息"。
**对比**:
| 差的描述 | 好的描述 |
|----------|----------|
| Create conventional git commits | Generate conventional git commit messages with emojis when user asks to commit changes |
| Works with types | Generate TypeScript types from JSON schemas, activated when user wants to create types from JSON or OpenAPI specs |
### 铁律 3:用 allowed-tools 限制权限
如果你的 Skill 只需要读取文件,就不要给它写入权限:
```yaml
allowed-tools: Read, Grep, Glob
这不是多此一举,而是防止 AI 在不该动手的时候动手。
六、Skill 的目录结构
一个完整的 Skill 可以包含多个文件:
.claude/skills/my-skill/
├── SKILL.md # 必需:技能定义
├── docs/ # 可选:参考文档
│ └── api-spec.md
├── examples/ # 可选:示例文件
│ └── sample.json
├── scripts/ # 可选:辅助脚本
│ └── helper.sh
└── templates/ # 可选:模板文件
└── component.tsx
Claude 会渐进式加载这些文件,高效管理上下文。
七、总结:从”复读机”到”乐高大师”
Agent Skills 的本质是知识封装。
以前,你的经验在脑子里,每次都要重新输入。
现在,你的经验在 SKILL.md 里,Claude 自动调用。
以前,团队协作靠口口相传。
现在,团队协作靠 git push。
这才是 AI 时代的正确打开方式:不是让 AI 替你干活,而是让 AI 学会你的方法论。
去创建你的第一个 Skill 吧。