Files
cs-note/hzh/AI/怎么创建一个自己的 SKILL.md
2026-05-24 11:42:38 +08:00

24 KiB
Raw Permalink Blame History

tags, create time
tags create time
Skill
Agent
自动化
2026-05-03 15:30

怎么创建一个自己的 CLAUDE CODE SKILL

概述

本文系统梳理 Claude Code(原 Claude Desktop / Anthropic SDK)的 Agent Skill 概念、定义语法、开发工作流和最佳实践,并通过多个实战场景案例帮助读者从零创建属于自己的可复用 AI 助手技能。

[!QUESTION] 💡 思考 你是否有过这样的场景——反复向 AI 助手解释同样的上下文、规则或约束,才能让它按你的预期完成工作?Skill 机制正是为了解决这个问题而生的:将"重复教育"变成一键加载的「能力插件」。

什么是 Agent Skill

核心概念

Agent Skill 是 Anthropic 提供的一种 结构化指令注入机制。它允许开发者/用户通过 YAML 格式的 skill definition,在不修改模型权重的前提下,向 Claude 注入特定的行为规则、知识框架和工具调用策略。

flowchart TD
    U["用户提示词\nFix the auth bug"] --> S{"Claude 模型"}
    
    subgraph Context ["Skill Context 注入层"]
        direction TB
        T["Trigger: trigger(auth)"]
        R["Rules: System Prompt"]
        C["Constraints: Tool Limits"]
    end
    
    S --> Context
    Context --> S
    
    S --> O["专精行为输出\nSecurity Review / Config Update / etc."]
    
    classDef normal fill:#e3f2fd,stroke:#1565c0
    classDef highlight fill:#fff3e0,stroke:#ef6c00
    class U,O normal
    class T,R,C highlight

Skill vs 普通 Prompt vs Project Instructions

维度 普通 Prompt CLAUDE.md (Project Instructions) Agent Skill
粒度 单次对话级别 整个 workspace 级别 特定任务域级别
触发方式 必须明确提及 始终生效 自动检测触发 / 手动 @ 调用
作用范围 不持久化 全局覆盖 按需挂载,不影响其他任务
复杂度 简单 中等 高(含系统级指令注入)
典型用例 快速提问 编码规范、语言偏好 安全审计、配置管理、代码审查

[!NOTE] 🔑 关键区别

  • CLAUDE.md 是你的"项目宪法",适用于所有对话
  • Skill 是你的"专业技能包",在特定场景下挂载到对话上,提供更深层的行为控制
  • 两者可以共存 —— Skill 中的指令仅在 skill 激活时生效,优先级高于 CLAUDE.md

内置 Skill 一览

Claude Code SDK 自带一组开箱即用的 Skill,理解它们是学习自定义 Skill 的最佳起点:

Skill 功能 触发条件
update-config 修改 settings.json、管理权限和环境变量 涉及配置文件、hook、权限变更
keybindings-help 定制键盘快捷键 用户询问快捷键相关
simplify 审查并重用冗余代码 代码审查场景
fewer-permission-prompts 扫描代码,生成 .claude/settings.json 的 allowlist 请求减少权限提示时
loop 运行定时/循环任务(如 /loop 5m /foo) 用户要求周期性任务
claude-api 构建和优化 Claude API 应用(含缓存策略) 导入 anthropic SDK、问 API/模型相关问题
init 初始化新的 CLAUDE.md 新项目初始化
review 审查 Pull Request PR 审查请求
security-review 安全审查当前分支变更 安全审查请求

Skill 定义语法详解

YAML Frontmatter 结构

每个 Skill 通过 YAML frontmatter 定义其元数据和触发逻辑:

---
name: security-review
description: Complete a security review of the pending changes on the current branch
---

一个完整的核心字段表:

字段 必填 说明
name ✅ Skill 的唯一标识符(kebab-case)
description ✅ 简短描述,用于匹配用户意图
trigger ❌ 何时自动激活(正则表达式)
skip ❌ 什么情况下跳过该 Skill
tools ❌ Skill 可用的工具白名单
systemPrompt ❌ 注入的系统级指令(核心内容区)

Trigger 模式匹配

Trigger 决定了 Skill 在什么情况下被自动激活。支持以下模式:

trigger: "code imports .anthropic. or @anthropic-ai/sdk."
trigger: 'filename like \*-openai.py/.*-generic\.py'
trigger: "/loop"

常见的触发方式:

方式 示例 适用场景
关键词匹配 trigger: "send email" 功能明确的任务
文件路径匹配 trigger: "\.secrets\."" 特定文件或目录变更时
命令前缀 trigger: "/deploy" Slash Command 触发
正则表达式 trigger: "imports .anthropic." 复杂模式匹配
手动 @ 引用 @my-skill 用户主动调用

[!TIP] ⚡ 最佳实践 Trigger 要尽可能精确。过于宽泛会导致错误的 Skill 被激活,干扰正常对话。遵循 "最小充分原则":用最少的匹配条件覆盖目标场景。

Skill 开发工作流

Step 1: 确定需求边界

[!QUESTION] 🧭 先问自己

  1. 这个 Skill 解决的是 一次性问题 还是 反复出现的需求?

    • 一次性 → 直接写 prompt
    • 反复出现 → 考虑做成 Skill
  2. 这个 Skill 的规则能否用 明确的 trigger + system prompt 表达?

    • 能 → 适合做成 Skill
    • 不能 → 可能需要更复杂的 Agent 类型
  3. 这个 Skill 会和其他 Skill 冲突吗?

    • 检查已有 Skill 的 trigger,避免重叠

Step 2: 编写 Skill Definition

一个典型的 Skill 定义放在项目的 .claude/skills/<skill-name>/SKILL.md 文件中:

---
name: my-cool-skill
description: Help with X when Y happens
trigger: "X scenario appears"
---

# My Cool Skill

When this skill is active, follow these rules:

## Rules
1. Rule one...
2. Rule two...

## Workflow
Step-by-step instructions for Claude to follow.

## Examples
Concrete examples showing expected behavior.

Step 3: 测试与迭代

阶段 操作 目的
单元测试 针对单个触发场景验证 确认 trigger 正确匹配
集成测试 模拟真实用户输入 观察 Skill 是否正确激活
负样本测试 用不应触发的输入测试 防止误触发
冲突检查 同时存在多 Skill 时测试 确保无歧义匹配

最佳实践

✅ Do's

[!SUCCESS] 推荐做法

1. 职责单一原则(Single Responsibility)

每个 Skill 只负责一个明确的领域。不要试图在一个 Skill 里塞入所有邮件发送逻辑。拆分为独立的 Skill:

graph LR
    Root["skills/"] --> A["send-email-report/\n发送邮件报告"]
    Root --> B["generate-changelog/\n生成 Changelog"]
    Root --> C["notify-team/\n团队通知"]
    
    classDef folder fill:#e8f5e9,stroke:#2e7d32
    classDef item fill:#fff3e0,stroke:#ef6c00
    class Root folder
    class A,B,C item

2. System Prompt 要明确且封闭

# good — 明确的正面指令 + 负面约束
## Rules
- ALWAYS use the smtp.send() helper from utils/email.py
- NEVER hardcode credentials; always use os.getenv()
- After sending, log the message ID to the database
- If SMTP fails, queue the email and retry in 5 minutes

# bad — 模糊、开放式的描述
## Notes
You can send emails however you think is best, just make sure it works.

3. Trigger 要精确且有排他性

# good — 具体的文件名 + 动作组合
trigger: "user asks to review .migrations/ or changes to schema files"

# bad — 太宽泛
trigger: "database"

4. 包含错误处理路径

优秀的 Skill 不是只在理想情况下工作,还要定义失败时的行为:

## Error Handling
- If the required config file is missing: create a template and ask the user to fill it in
- If the API returns 429: implement exponential backoff (initial: 1s, max: 30s)
- If the recipient list is empty: abort with an informative error message

❌ Don'ts

[!WARNING] ⚠️ 常见陷阱

1. 过度依赖 Skill 解决简单问题

如果只是一个简单的 git commit 封装,不需要写成 Skill。Skill 适合 复杂、多步骤、有严格规则 的场景。

2. Trigger 相互冲突

两个 Skill 的 trigger 匹配同一个输入时,行为不可预测:

flowchart LR
    Input["用户说: fix auth bug"] --> SkillA["Skill A\ntrigger: fix the bug in auth"]
    Input --> SkillB["Skill B\ntrigger: fix authentication bug"]
    
    classDef input fill:#e3f2fd,stroke:#1565c0
    classDef conflict fill:#f9d0c4,stroke:#d84315
    class Input input
    class SkillA,SkillB conflict

3. 在 Skill 中硬编码敏感信息

绝对不要在 system prompt 中写入密码、API Key、URL 等。使用环境变量或配置文件引用:

❌ BAD:
Always use password = "mySuperSecret123!" at host smtp.example.com

✅ GOOD:
Use credentials from ENV vars EMAIL_USER and EMAIL_PASS

4. 忽略性能影响

过长的 system prompt 会增加 token 消耗和响应延迟。保持精简,只注入必要的上下文。

实战场景案例集

下面通过四个不同难度级别的实战场景,展示如何从需求到完整的 Skill 定义。

场景一:中间件集成的最佳编码实践(入门级)

需求: 当检测到项目中引入 Redis/MQ 等中间件时,自动注入最佳实践指导。

[!QUESTION] 🤔 为什么需要这个 Skill? 每次引入新中间件,你都需要告诉 AI:"记得连接池、超时设置、重试策略..." —— 这正是 Skill 的用武之地。

Skill 定义

---
name: redis-best-practices
description: Guide proper Redis integration patterns when Redis-related code is detected
trigger: "redis OR redigo OR go-redis OR ioredis OR Lettuce"
---

# Redis Integration Best Practices

## Overview
This skill activates when Redis-related imports or configuration appear in the codebase.
It ensures the assistant guides the developer through production-ready patterns.

## Core Principles

> [!INFO] 三大基石
> 1. **资源管理**: 连接必须复用,禁止每次请求新建连接
> 2. **容错设计**: 网络异常必须有降级方案,Redis 不可用时服务不能完全崩溃
> 3. **数据安全**: 敏感数据不能明文存储,大 value 要考虑内存水位

## Checklist

When reviewing or writing Redis code, verify:

- [ ] Connection pool configured with MinIdle/MaxActive ratios
- [ ] Read/write timeouts explicitly set (> 0)
- [ ] Retry logic implemented with bounded attempts (max 3)
- [ ] Hot key detection strategy in place
- [ ] Cache penetration/breakdown/avalanche handled
- [ ] Distributed lock has auto-expiry + reentrant design
- [ ] Pipeline used for batch operations (> 3 commands)
- [ ] Keys have TTL set (except explicit no-expiry cases)

## Common Patterns

### Pattern 1: Safe Cache-Aside

```go
func GetProductCacheable(ctx context.Context, id string) (*Product, error) {
    // 1. Try cache first
    data, err := rdb.Get(ctx, productKey(id)).Result()
    if err == nil {
        // deserialized...
        return parse(data)
    }

    // 2. Cache miss -> query DB with double-check pattern
    mu.Lock()
    defer mu.Unlock()
    
    // Double-check after acquiring lock
    data, err = rdb.Get(ctx, productKey(id)).Result()
    if err == nil {
        return parse(data)
    }

    result, err := db.QueryProduct(ctx, id)
    if err != nil {
        // Write cache with short TTL to prevent penetration
        rdb.Set(ctx, productKey(id), "", 30*time.Second)
        return nil, fmt.Errorf("product not found: %w", err)
    }

    rdb.Set(ctx, productKey(id), marshal(result), 15*time.Minute)
    return result, nil
}

[!SUMMARY] 这段代码的关键点

  • 使用了 Cache-Aside 模式(缓存旁路),而非 Write-Through
  • 实现了 Double-Check 加锁机制,防止缓存击穿下的并发穿透
  • 穿透保护用了 30 秒短 TTL(空值缓存),常规数据用 15 分钟
  • 注意这里用 marshal/unmarshal 抽象了序列化,实际应统一使用 msgpack 或 protobuf

Pattern 2: Distributed Lock (Redisson-style)

func WithDistributedLock(ctx context.Context, key string, ttl time.Duration, fn func() error) error {
    lockKey := "lock:" + key
    locked, err := rdb.SetNX(ctx, lockKey, uuid.New().String(), ttl).Result()
    if err != nil {
        return fmt.Errorf("acquire lock failed: %w", err)
    }
    if !locked {
        return ErrLockAcquireFailed
    }

    // Auto-release on exit
    defer rdb.Del(ctx, lockKey)
    
    return fn()
}

Anti-patterns to Avoid

[!FAILURE] ❌ 反模式

  • 全量导出: KEYS * 在生产环境禁用,改用 SCAN
  • 阻塞操作: BLPOP 无超时时间可能导致 goroutine 泄漏
  • 主从切换丢失: 同步写后立即读可能命中 slave 导致不一致,需用 READONLY 或 WAIT
  • Large Key: Value > 10KB 的 hash/string 需特别注意内存和网络开销
graph LR
    A["客户端请求"] --> B{"缓存命中?"}
    B -- "Yes" --> C["返回缓存值"]
    B -- "No" --> D["获取分布式锁"]
    D --> E{"获取成功?"}
    E -- "No" --> F["等待后重试"]
    F --> D
    E -- "Yes" --> G["查询数据库"]
    G --> H["写入缓存 + 设置 TTL"]
    H --> C2["返回数据"]
flowchart TD
    A["客户端"] --> B["Sentinel / Cluster"]
    B --> C[Master Node]
    C -- "异步复制" --> D[Slave 1]
    C -- "异步复制" --> E[Slave N]
    
    subgraph Problem ["主从切换期间的风险"]
        W1["写入 Master"] -.->|"可能未复制到 Slave"| W2["Master 故障"]
        W2 --> W3["Slave 晋升为新 Master"]
        W3 --> W4["新写入丢失"]
    end
    
    classDef warn fill:#f9d0c4,stroke:#d84315
    class W1,W2,W3,W4 warn

关联笔记


---

### 场景二:自动化邮件报告(进阶级)

**需求**: 创建 Skill 让 AI 能够自动生成周报、月报并通过邮件发送。

> [!SUCCESS] 这个 Skill 的优势在于 —— 它不仅是一个模板,还包含了完整的错误处理和幂等保证。

#### Skill 定义

```markdown
---
name: email-report
description: Generate and send automated reports (weekly/monthly) via email
trigger: "generate report AND email OR send weekly OR monthly report OR 生成报告"
---

# Automated Email Report Skill

## Overview
Guides the creation of structured reports and their delivery via email,
handling template rendering, attachment generation, and notification delivery.

## Pre-flight Checks

Before sending any report, verify these environment variables are set:

| Variable | Required | Description |
|----------|----------|-------------|
| `SMTP_HOST` | Yes | SMTP server address |
| `SMTP_PORT` | Yes | SMTP port (587 for TLS) |
| `EMAIL_USER` | Yes | Sender address |
| `EMAIL_PASS` | Yes | App-specific password or API token |
| `REPORT_RECIPIENTS` | No | Comma-separated recipient list |

> [!IMPORTANT] 安全提醒
> All credentials must come from ENV or secrets manager. NEVER hardcode.

## Workflow

```mermaid
sequenceDiagram
    participant U as User
    participant S as Email Report Skill
    participant T as Template Engine
    participant A as Attachment Generator
    participant M as SMTP Client
    participant R as Recipients

    U->>S: "Generate weekly report"
    S->>S: Parse scope & date range
    S->>T: Render HTML template
    T-->>S: Generated HTML
    S->>A: Generate PDF attachment
    A-->>S: PDF bytes
    S->>M: Send email with attachments
    M-->>R: Deliver to all recipients
    S->>S: Log delivery status
    S-->>U: Report sent successfully

Step 1: Report Template Structure

All reports follow this standard structure:

<h1>{{report_type}} Report — {{period}}</h1>

<section>
  <h2>Summary</h2>
  <p>{{summary}}</p>
</section>

<section>
  <h2>Key Metrics</h2>
  <table>
    <!-- rendered metrics table -->
  </table>
</section>

<section>
  <h2>Action Items</h2>
  <ul>
    <!-- rendered action items -->
  </ul>
</section>

<footer>Sent by automated reporting system</footer>

Step 2: Sending Implementation

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os

def send_report(subject: str, html_body: str, 
                attachments: list[str] | None = None,
                recipients: list[str] | None = None):
    """Send report email with optional attachments."""
    
    msg = MIMEMultipart("mixed")
    msg["From"] = os.getenv("EMAIL_USER")
    msg["To"] = ", ".join(recipients or [])
    msg["Subject"] = subject
    
    # HTML body
    msg.attach(MIMEText(html_body, "html"))
    
    # Attachments (PDFs, charts, etc.)
    for filepath in attachments or []:
        with open(filepath, "rb") as f:
            part = MIMEBase("application", "octet-stream")
            part.set_payload(f.read())
            encoders.encode_base64(part)
            part.add_header("Content-Disposition", "attachment", filename=os.path.basename(filepath))
            msg.attach(part)
    
    # Send with TLS and timeout protection
    with smtplib.SMTP(os.getenv("SMTP_HOST"), int(os.getenv("SMTP_PORT"))) as server:
        server.starttls()
        server.login(msg["From"], os.getenv("EMAIL_PASS"))
        server.send_message(msg, to_addrs=recipients)

Step 3: Retry Strategy

import tenacity

@tenacity.retry(
    stop=tenacity.stop_after_attempt(3),
    wait=tenacity.wait_exponential(multiplier=1, min=2, max=30),
    retry=tenacity.retry_if_exception_type(smtplib.SMTPException),
    before_sleep=lambda retry_state: print(f"Retrying email delivery... ({retry_state.attempt_number}/3)")
)
def send_with_retry(email_fn, *args, **kwargs):
    """Email sending with exponential backoff retry."""
    return email_fn(*args, **kwargs)

Error Handling Matrix

Scenario Action Logging Level
Missing env vars Abort early, output help text ERROR
SMTP connection refused Queue job for retry WARN
Authentication failed Notify admin via web hook CRITICAL
Attachment too large (> 25MB) Split into multiple emails WARN
Empty recipient list Skip sending, log info INFO

Cron Integration (Optional)

If scheduling is needed, recommend platform-native schedulers over custom cron scripts:

Platform Recommendation Example
Linux systemd timer or crontab 0 9 * * 1 /usr/bin/python report.py
Docker entrypoint wrapper script Health-checked container
Cloud EventBridge / Cloud Scheduler Configured via IaC

关联笔记


---

### 场景三:PR Review Checklist(实用级)

**需求**: 每当用户请求审查某个 PR 或 diff 时,自动以预设的检查清单来审视代码变更。

#### 快速定义

```markdown
---
name: pr-review-checklist
description: Run a structured code review checklist on PR diffs
trigger: "review PR OR review diff OR review pull request"
---

# PR Review Checklist

## Quick Reference

Review each change against these categories:

### 1. Correctness
- [ ] Logic matches requirements?
- [ ] Edge cases handled (empty input, null, zero)?
- [ ] Error propagation correct (not swallowed)?

### 2. Performance
- [ ] No O(n²) loops where O(n) suffices?
- [ ] Database queries not N+1?
- [ ] Large data streaming instead of loading entirely into memory?

### 3. Security
- [ ] Input sanitization present?
- [ ] AuthN/AuthZ verified before sensitive operations?
- [ ] Secrets never logged or committed?

### 4. Maintainability
- [ ] Function size reasonable (< 50 lines)?
- [ ] Meaningful variable/function names?
- [ ] Comments explain WHY not WHAT?

### 5. Testing
- [ ] Unit tests cover happy path + edge cases?
- [ ] Test isolation maintained (no shared mutable state)?
- [ ] Integration tests if external dependency involved?

场景四:数据库迁移脚本生成器(高级)

需求: 基于当前的数据库 schema 和用户提出的变更需求,自动生成带版本控制和回滚能力的迁移脚本。

[!FAILURE] ⚠️ 这个场景比较危险 —— 涉及数据库变更的操作,必须在 Skill 中加入强制确认步骤。

---
name: db-migration-generator
description: Generate safe database migration scripts with rollback support
trigger: "migration OR alter table OR add column AND database"
---

# Database Migration Generator

> [!CRITICAL] 安全协议
> This skill operates on real databases. Every generated migration MUST include:
> 1. A rollback script
> 2. Data safety analysis
> 3. Explicit confirmation requirement before execution

## Safe Migration Rules

### Zero-Downtime Pattern for Schema Changes

```mermaid
flowchart LR
    A["Step 1: Add nullable column"] --> B["Step 2: Backfill existing data"]
    B --> C["Step 3: Deploy app with dual-write"]
    C --> D["Step 4: Validate new data correctness"]
    D --> E["Step 5: Switch reads to new column"]
    E --> F["Step 6: Remove old column (next release)"]
    classDef step fill:#e8f5e9,stroke:#2e7d32
    class A,B,C,D,E,F step

Never Do This on Large Tables

[!FAILURE] 高危操作 —— 以下操作在 > 100K 行的表上执行会导致锁表:

操作 风险等级 推荐替代方案
ALTER TABLE ADD NOT NULL 🔴 致命 分步添加 + backfill
ALTER TABLE DROP COLUMN 🔴 致命 标记废弃 + 下周期清理
ALTER TABLE MODIFY TYPE 🟠 危险 新建列 + 数据迁移 + 切换
ADD UNIQUE INDEX CONCURRENTLY 🟢 安全 PostgreSQL 原生支持

Generated Script Template

-- Migration: 0042_add_user_email_verified
-- Date: YYYY-MM-DD
-- Risk: LOW (additive change only)

BEGIN;

-- Step 1: Add new nullable column
ALTER TABLE users 
  ADD COLUMN email_verified_at TIMESTAMP WITH TIME ZONE DEFAULT NULL;

-- Step 2: Create index (non-blocking where possible)
CREATE INDEX CONCURRENTLY idx_users_email_verified 
  ON users(email_verified_at) WHERE email_verified_at IS NOT NULL;

COMMIT;

-- ============================
-- ROLLBACK SCRIPT
-- ============================
-- BEGIN;
-- DROP INDEX CONCURRENTLY IF EXISTS idx_users_email_verified;
-- ALTER TABLE users DROP COLUMN IF EXISTS email_verified_at;
-- COMMIT;

Confirmation Steps

Before generating any migration, ask the user:

  1. What is the target database and version? (PostgreSQL 15, MySQL 8.x, etc.)
  2. Is the table large (> 1M rows)? If yes, enforce zero-downtime pattern.
  3. Can rolling deploy be supported? If no, plan full downtime window.
  4. Has the migration been reviewed by a second person?

关联笔记


## 总结与进阶方向

### Skill 成熟度模型

```mermaid
graph BT
    P1["Level 1: Prompt 库"]
    P2["Level 2: CLAUDE.md snippets"]
    P3["Level 3: Custom Skill"]
    P4["Level 4: Custom Agent Type"]
    P5["Level 5: MCP Server Integration"]
    
    P1 --> P2 --> P3 --> P4 --> P5
    
    classDef low fill:#fff3e0,stroke:#ef6c00
    classDef mid fill:#e3f2fd,stroke:#1565c0
    classDef high fill:#e8f5e9,stroke:#2e7d32
    
    class P1,P2 low
    class P3,P4 mid
    class P5 high

下一步学习路线

阶段 重点 推荐资源
Phase 1 理解现有内置 Skill 的触发逻辑 阅读本 Skill 的定义源码
Phase 2 创建第一个极简 Skill(3 条 rule) 参考 PR Review Checklist 案例
Phase 3 加入 workflow 图表 + 错误处理 参考 Email Report 案例
Phase 4 探索自定义 Agent Type(超越 Skill 的能力边界) Study Explore / Plan agent 的实现
Phase 5 构建 MCP Server 实现跨工具链联动 Anthropic MCP Protocol 文档

一句话总结

好的 Skill 不是"教 AI 怎么做",而是"给 AI 一套它做这件事时一定会遵守的思维框架"。 就像给高级工程师一份技术规范——细节他可以自己决定,但红线和标准你必须写好。