<!-- title: Skills脚本封装术：从Shell到智能Skill -->

# Skills脚本封装术：从Shell到智能Skill

**学习目标**：掌握将现有Shell/Python脚本封装为Claude Code Skill的完整方法，理解`scripts/`目录机制、`allowed-tools`权限配置、参数传递模式，并能独立完成从脚本到可复用Skill的转换。

**适用人群**：已有Shell或Python自动化脚本的工程师，希望将现有工具链整合进Claude Code工作流。

---

## 为什么要封装现有脚本

大多数开发者的日常工具不是从零开始的——你已经有部署脚本、监控巡检、数据库迁移、日志分析等一批Shell脚本。这些脚本是经过实战验证的可靠工具，问题是它们缺乏上下文感知能力：不知道当前项目的目录结构，不理解代码变更的意图，无法与AI辅助编程流程无缝衔接。

Claude Code Skills提供了一种封装机制，将你的脚本升级为"AI可理解的工具"。封装后的Skill不仅保留了脚本的原始能力，还获得了自然语言触发、上下文感知、错误自修复三个新维度。

```
传统脚本调用：  ./deploy.sh --env staging --skip-tests
Skill调用：     /deploy 到staging环境，跳过测试
```

区别在于：Skill能根据当前对话上下文推断参数，能读取项目配置文件获取环境变量，能在执行失败时自主分析日志并调整策略。

---

## 前置条件

- Claude Code ≥ 1.0.25（Skills功能稳定版本）
- 至少一个你熟悉的Shell脚本或Python CLI工具
- 基本了解SKILL.md的frontmatter格式（本文会涵盖关键部分）
- 本地开发环境具备Bash和/或Python运行时

---

## Skill文件结构与脚本嵌入原理

一个包含脚本的Skill目录结构如下：

```
my-deploy-skill/
├── SKILL.md              # 指令入口（必需）
├── scripts/
│   ├── deploy.sh         # 部署脚本
│   ├── rollback.sh       # 回滚脚本
│   └── health-check.py   # 健康检查脚本
└── templates/
    └── config.yaml       # 配置模板（可选）
```

关键机制：`SKILL.md`中通过指令告诉Claude何时以及如何调用`scripts/`目录下的脚本。Claude Code会读取SKILL.md的frontmatter获取元数据，然后根据正文指令执行具体操作。脚本文件作为Skill的一部分被一起打包和分发。

**与普通Skill的区别**：纯指令型Skill只在SKILL.md中写入文本指令，Claude通过内置工具（Read/Edit/Bash）执行。脚本封装型Skill则预置了可执行文件，Claude通过`bash scripts/xxx.sh`方式调用，获得更精确的控制力。

---

## 封装六步法

### 第一步：分析脚本的输入输出边界

拿到一个现有脚本，先回答三个问题：

| 分析维度 | 问题 | 示例 |
|---------|------|------|
| 输入 | 脚本需要哪些参数/环境变量？ | `--env`, `--version`, `DB_HOST` |
| 输出 | 成功/失败的标志是什么？ | exit code 0=成功, stdout含URL |
| 副作用 | 会修改什么外部状态？ | 创建EC2实例、写入数据库 |

以一个典型的部署脚本为例：

```bash
#!/bin/bash
# deploy.sh - 原始脚本
set -euo pipefail

ENV=${1:-staging}
VERSION=${2:-latest}
SKIP_TESTS=${SKIP_TESTS:-false}

echo "Deploying version $VERSION to $ENV..."

# 构建Docker镜像
docker build -t myapp:$VERSION .
docker tag myapp:$VERSION registry.example.com/myapp:$VERSION
docker push registry.example.com/myapp:$VERSION

# 部署到K8s
kubectl set image deployment/myapp \
  myapp=registry.example.com/myapp:$VERSION \
  -n $ENV

# 等待滚动更新完成
kubectl rollout status deployment/myapp -n $ENV --timeout=300s

echo "Deployment complete: $ENV/$VERSION"
```

**边界分析结果**：
- 输入：`ENV`（环境名）、`VERSION`（版本号）、`SKIP_TESTS`（是否跳过测试）
- 输出：stdout中的"Deployment complete"标志成功，非零exit code标志失败
- 副作用：推送Docker镜像、更新K8s Deployment

### 第二步：创建Skill目录并放入脚本

```bash
mkdir -p ~/.claude/skills/deploy-tool/scripts
mkdir -p ~/.claude/skills/deploy-tool/templates
```

将原始脚本复制到`scripts/`目录，并做两处关键调整：

**调整1：添加结构化输出**。原始脚本的echo输出是给人读的，封装后需要给Claude读。在关键节点添加结构化标记：

```bash
#!/bin/bash
# scripts/deploy.sh - 封装版
set -euo pipefail

ENV=${1:-staging}
VERSION=${2:-latest}
SKIP_TESTS=${3:-false}

# ===SKILL_OUTPUT_START===
echo "::deploy::phase=build"
docker build -t myapp:$VERSION . 2>&1 | tail -1
echo "::deploy::phase=push"
docker push registry.example.com/myapp:$VERSION 2>&1 | tail -1
echo "::deploy::phase=rollout"
kubectl set image deployment/myapp \
  myapp=registry.example.com/myapp:$VERSION \
  -n $ENV
kubectl rollout status deployment/myapp -n $ENV --timeout=300s
# ===SKILL_OUTPUT_END===

echo "DEPLOY_SUCCESS env=$ENV version=$VERSION"
```

**调整2：增强错误输出**。在`set -e`的基础上添加trap，让Claude能获取失败原因：

```bash
on_error() {
  echo "DEPLOY_FAILED phase=$PHASE message='$BASH_COMMAND'"
  exit 1
}
trap on_error ERR
```

### 第三步：编写SKILL.md的Frontmatter

Frontmatter定义Skill的元数据和权限声明：

```yaml
---
name: deploy-tool
description: |
  部署工具：将应用部署到指定K8s环境。
  当用户提到部署、deploy、发布、上线、滚动更新时使用此Skill。
  支持staging/production环境，可指定版本号。
allowed-tools: Bash(bash:docker), Bash(bash:kubectl), Bash(bash:scripts/*), Read, Glob
---
```

**`allowed-tools`配置要点**：

| 配置值 | 含义 |
|--------|------|
| `Bash(bash:docker)` | 仅允许执行`docker`开头的Bash命令 |
| `Bash(bash:kubectl)` | 仅允许执行`kubectl`开头的Bash命令 |
| `Bash(bash:scripts/*)` | 允许执行scripts目录下的脚本 |
| `Read, Glob` | 允许读取文件和搜索文件 |

这种细粒度配置避免了每次调用时弹出权限确认框，同时限制Skill只能在声明的范围内操作。如果Skill尝试执行`rm -rf`这样的危险命令，会被Claude Code的权限系统拦截。

### 第四步：编写核心指令

SKILL.md的正文部分是给Claude的执行指令。这是封装的灵魂——它将自然语言意图映射到具体的脚本调用：

```markdown
# 部署工具 Skill

## 触发条件

当用户要求执行以下操作时激活此Skill：
- 部署应用 / deploy
- 发布新版本 / release
- 滚动更新 / rollout
- 回滚 / rollback

## 执行流程

### 1. 预检

在执行部署前，必须完成以下检查：

1. 读取项目根目录的`docker-compose.yml`或`Dockerfile`，确认构建配置存在
2. 检查当前git分支和状态：运行`git status`确认没有未提交的变更
3. 如果用户未指定版本号，从`package.json`或`Cargo.toml`获取当前版本

### 2. 参数解析

从用户消息中提取以下参数：

| 参数 | 来源 | 默认值 | 校验规则 |
|------|------|--------|----------|
| ENV | 用户指定或"环境" | staging | 必须是staging/production之一 |
| VERSION | 用户指定或"版本" | package.json中的版本 | 符合semver格式 |
| SKIP_TESTS | 用户说"跳过测试"时为true | false | 布尔值 |

### 3. 执行部署

运行部署脚本：

\`\`\`bash
bash ~/.claude/skills/deploy-tool/scripts/deploy.sh "$ENV" "$VERSION" "$SKIP_TESTS"
\`\`\`

### 4. 结果解析

根据脚本输出判断结果：
- 看到`DEPLOY_SUCCESS`：向用户确认部署成功，报告环境和版本
- 看到`DEPLOY_FAILED`：分析失败阶段和原因，提供修复建议
- 看到超时：建议检查集群状态或增加超时时间

### 5. 回滚（条件触发）

如果部署失败且用户要求回滚：

\`\`\`bash
bash ~/.claude/skills/deploy-tool/scripts/rollback.sh "$ENV"
\`\`\`

## 约束

- 永远不要在没有用户确认的情况下部署到production环境
- 部署前必须通过预检步骤
- 如果Docker构建失败，不要重试，而是分析错误日志给出修复建议
```

注意指令的写法特点：**具体到命令级别**。不是"部署应用"这样的模糊描述，而是精确到运行哪个脚本、传什么参数、如何解析输出。这正是封装的关键——将脚本的操作细节固化为Claude可重复执行的流程。

### 第五步：添加辅助脚本

部署脚本通常不是孤立的，添加辅助工具增强Skill的能力：

```python
#!/usr/bin/env python3
"""scripts/health-check.py - 部署后健康检查"""
import sys
import subprocess
import json
import time

def check_deployment(env, timeout=120):
    """等待Deployment就绪并检查健康状态"""
    start = time.time()
    while time.time() - start < timeout:
        result = subprocess.run(
            ["kubectl", "get", "pods", "-n", env,
             "-l", "app=myapp", "-o", "json"],
            capture_output=True, text=True
        )
        pods = json.loads(result.stdout)
        all_ready = all(
            p["status"]["phase"] == "Running"
            and any(
                c["ready"]
                for c in p["status"].get("containerStatuses", [])
            )
            for p in pods.get("items", [])
        )
        if all_ready and pods.get("items"):
            print(f"HEALTH_CHECK_PASSED pods={len(pods['items'])} env={env}")
            return 0
        time.sleep(5)

    print(f"HEALTH_CHECK_FAILED env={env} timeout={timeout}s")
    return 1

if __name__ == "__main__":
    env = sys.argv[1] if len(sys.argv) > 1 else "staging"
    sys.exit(check_deployment(env))
```

在SKILL.md的指令中添加健康检查步骤：

```markdown
### 4.1 部署后健康检查

部署成功后自动执行：

\`\`\`bash
python3 ~/.claude/skills/deploy-tool/scripts/health-check.py "$ENV"
\`\`\`

如果健康检查失败，自动建议回滚。
```

### 第六步：测试与迭代

**手动测试**：在Claude Code中输入触发命令：

```
/deploy 到staging环境
```

观察Claude的行为是否符合预期：
1. 是否执行了预检步骤？
2. 参数是否正确传递？
3. 输出解析是否准确？

**自动化测试**：创建测试用的SKILL.md指令片段：

```markdown
## 测试模式

当用户说"测试deploy skill"时：

1. 使用`staging`环境和`test-0.0.1`版本号
2. 设置`SKIP_TESTS=true`加速测试
3. 验证脚本能正常运行到完成
4. 不执行实际的docker push和kubectl操作
```

一个实用技巧：在脚本中添加`DRY_RUN`模式：

```bash
DRY_RUN=${DRY_RUN:-false}

if [[ "$DRY_RUN" == "true" ]]; then
  echo "[DRY RUN] Would deploy version $VERSION to $ENV"
  echo "DEPLOY_SUCCESS env=$ENV version=$VERSION (dry-run)"
  exit 0
fi
```

---

## 三种典型封装模式

通过六步法的实践，可以归纳出三种常见的封装模式，覆盖大多数场景：

### 模式一：纯封装型——脚本直接调用

```
用户意图 → Claude解析参数 → 直接执行脚本 → 解析输出
```

适用于：已有成熟脚本，只需加一层自然语言接口。部署、备份、数据迁移等场景。

```yaml
# SKILL.md frontmatter 示例
---
name: db-backup
description: 数据库备份工具。当用户提到备份数据库时使用。
allowed-tools: Bash(bash:scripts/*), Bash(bash:pg_dump), Bash(bash:aws), Read
---
```

指令核心就一句话：`运行 bash scripts/backup.sh "$DB_NAME" "$TARGET"`。Claude负责从上下文中提取`DB_NAME`和`TARGET`。

### 模式二：编排型——多脚本串联

```
用户意图 → Claude拆解为多步骤 → 逐步执行脚本1,2,3... → 汇总结果
```

适用于：需要多步骤编排的复杂操作。CI/CD流水线、环境初始化、批量运维。

```markdown
## 执行流程

1. 预检：`bash scripts/pre-check.sh`
2. 准备：`bash scripts/prepare.sh "$ENV"`
3. 执行：`bash scripts/deploy.sh "$ENV" "$VERSION"`
4. 验证：`python3 scripts/health-check.py "$ENV"`
5. 通知：`bash scripts/notify.sh "$RESULT"`

如果任何步骤失败，执行回滚：`bash scripts/rollback.sh "$ENV"`
```

编排型的价值在于Claude能根据每一步的输出动态决定下一步——脚本1失败时可能走修复路径而非直接回滚。

### 模式三：增强型——Claude与脚本协作

```
用户意图 → Claude分析代码 → 生成脚本参数 → 执行脚本 → Claude分析结果 → 自主决策
```

适用于：需要代码理解能力的操作。代码质量检查、自动化重构、智能监控。

```markdown
## 执行流程

1. 使用Read工具读取项目的`go.mod`或`package.json`，识别项目类型
2. 使用Glob工具查找所有源代码文件
3. 根据项目类型选择对应的检查脚本：
   - Go项目：`bash scripts/go-lint.sh "$PROJECT_DIR"`
   - Node项目：`bash scripts/node-lint.sh "$PROJECT_DIR"`
   - Python项目：`bash scripts/python-lint.sh "$PROJECT_DIR"`
4. 分析脚本输出，按严重程度分类（error/warning/info）
5. 对于error级别问题，直接使用Edit工具修复
6. 对于warning级别问题，列出清单由用户决定
```

这种模式下，Claude不是简单的脚本调用者，而是参与决策的协作者——它理解代码、选择工具、处理结果。

---

## 参数传递机制详解

脚本封装中最容易出错的环节是参数传递。Claude Code Skill与脚本之间有三层参数通道：

```
┌─────────────────────────────────────────────┐
│  用户消息                                     │
│  "部署v2.1到staging，跳过测试"                 │
└──────────────┬──────────────────────────────┘
               │ Claude解析
               ▼
┌─────────────────────────────────────────────┐
│  SKILL.md 指令层                              │
│  参数映射规则：                                │
│  v2.1 → VERSION                               │
│  staging → ENV                                │
│  跳过测试 → SKIP_TESTS=true                   │
└──────────────┬──────────────────────────────┘
               │ 命令行参数
               ▼
┌─────────────────────────────────────────────┐
│  scripts/deploy.sh "$ENV" "$VERSION" ...     │
└──────────────┬──────────────────────────────┘
               │ 环境变量
               ▼
┌─────────────────────────────────────────────┐
│  脚本内部通过 $ENV/$VERSION/$SKIP_TESTS 访问   │
└─────────────────────────────────────────────┘
```

**通道一：命令行参数**

最直接的传递方式。在SKILL.md指令中明确告诉Claude如何构造命令：

```markdown
运行以下命令，替换参数值：
bash scripts/deploy.sh "<ENV>" "<VERSION>"
```

**通道二：环境变量**

适合传递敏感信息或全局配置。SKILL.md中声明环境变量需求：

```markdown
## 环境要求

此脚本需要以下环境变量：
- `REGISTRY_URL`：Docker Registry地址
- `KUBECONFIG`：K8s配置文件路径
- `SLACK_WEBHOOK`：通知Webhook（可选）

如果用户未提供，从项目根目录的`.env.deploy`文件读取。
如果文件不存在，提示用户创建。
```

**通道三：配置文件**

适合复杂参数集。在`templates/`目录预置配置模板：

```yaml
# templates/deploy-config.yaml
env: staging
version: ""  # 从package.json填充
registry: registry.example.com
namespace: default
replicas: 3
resources:
  limits:
    cpu: "1"
    memory: "512Mi"
```

在SKILL.md中指示Claude先生成配置文件再执行脚本：

```markdown
1. 复制`templates/deploy-config.yaml`到项目根目录
2. 根据用户要求修改配置值
3. 运行`bash scripts/deploy.sh --config deploy-config.yaml`
```

---

## 安全配置与权限控制

脚本封装型Skill的安全风险高于纯指令型，因为它直接执行外部命令。`allowed-tools`是你的第一道防线。

### 最小权限原则

```yaml
# 好的做法：精确声明需要的命令
allowed-tools: Bash(bash:docker build*), Bash(bash:docker push*), Bash(bash:kubectl apply*), Bash(bash:kubectl rollout*), Read

# 危险的做法：给予所有Bash权限
allowed-tools: Bash

# 更危险的做法：给予所有Bash权限且绕过确认
allowed-tools: Bash, Edit, Write
```

### 沙箱隔离

对于有副作用的操作（部署、删除、修改生产数据），推荐使用`disable-mcp: true`和独立子代理执行：

```yaml
---
name: production-deploy
description: 生产环境部署工具
allowed-tools: Bash(bash:scripts/*), Read
disable-mcp: true
---
```

`disable-mcp: true`确保Skill执行时不会调用MCP服务器，减少攻击面。

### 危险命令拦截

在脚本内部添加防护：

```bash
#!/bin/bash
# scripts/deploy.sh 中的安全检查

if [[ "$ENV" == "production" ]]; then
  # 生产环境需要二次确认
  echo "::CONFIRM_REQUIRED:: 正在部署到PRODUCTION环境，版本=$VERSION"
  echo "请在Claude Code中确认此操作。"
fi

# 防止误删
if [[ "$ACTION" == "delete" && -z "$CONFIRM_DELETE" ]]; then
  echo "ERROR: 删除操作需要设置CONFIRM_DELETE=true"
  exit 1
fi
```

---

## 实战案例：日志分析Skill

将一个现有的日志分析脚本封装为Skill，展示完整的端到端流程。

### 原始脚本

```bash
#!/bin/bash
# analyze-logs.sh - 分析Nginx访问日志
LOG_FILE=${1:-/var/log/nginx/access.log}
TOP_N=${2:-10}

echo "=== 日志分析报告 ==="
echo "文件: $LOG_FILE"
echo ""

echo "--- Top ${TOP_N} 访问IP ---"
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -"$TOP_N"

echo ""
echo "--- Top ${TOP_N} 访问路径 ---"
awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -"$TOP_N"

echo ""
echo "--- 状态码分布 ---"
awk '{print $9}' "$LOG_FILE" | sort | uniq -c | sort -rn

echo ""
echo "--- 错误请求 (4xx/5xx) ---"
awk '$9 >= 400 {print $9, $7, $1}' "$LOG_FILE" | head -20
```

### 封装后的目录结构

```
log-analyzer/
├── SKILL.md
├── scripts/
│   ├── analyze-logs.sh
│   ├── analyze-errors.py
│   └── generate-report.py
└── templates/
    └── report-template.md
```

### 完整SKILL.md

```yaml
---
name: log-analyzer
description: |
  Nginx日志分析工具。当用户提到分析日志、查看访问统计、
  排查错误请求、日志报告时使用。
  支持访问IP统计、路径分析、状态码分布、错误请求筛选。
allowed-tools: Bash(bash:scripts/*), Bash(bash:awk), Bash(bash:sort), Bash(bash:head), Read, Glob
---
```

```markdown
# 日志分析工具

## 触发条件

- "分析日志" / "分析访问日志" / "log analysis"
- "查看访问统计" / "哪些IP访问最多"
- "排查错误请求" / "4xx/5xx错误"
- "生成日志报告"

## 参数提取

| 参数 | 来源 | 默认值 |
|------|------|--------|
| LOG_FILE | 用户指定路径，或搜索项目中的`*.log`文件 | 自动发现 |
| TOP_N | 用户指定"前N个" | 10 |
| FOCUS | "错误"→errors, "IP"→ips, "路径"→paths, 空→all | all |

## 执行步骤

### 1. 定位日志文件

如果用户未指定日志文件路径：

1. 在项目目录中使用Glob搜索`**/*.log`
2. 搜索`/var/log/nginx/access.log`
3. 如果找不到，提示用户指定路径

### 2. 运行分析

根据FOCUS参数选择性执行：

**全量分析**（默认）：

\`\`\`bash
bash scripts/analyze-logs.sh "$LOG_FILE" "$TOP_N"
\`\`\`

**仅错误分析**：

\`\`\`bash
python3 scripts/analyze-errors.py "$LOG_FILE" --top "$TOP_N"
\`\`\`

### 3. 生成报告

如果用户要求"生成报告"：

\`\`\`bash
python3 scripts/generate-report.py "$LOG_FILE" --output log-report.md
\`\`\`

## 输出格式化

将脚本输出格式化为易读的分析报告：
- 使用表格展示Top N数据
- 高亮4xx/5xx错误
- 如果错误率超过5%，主动建议排查方向
```

### 增强脚本：错误分析

```python
#!/usr/bin/env python3
"""scripts/analyze-errors.py - 深度错误分析"""
import sys
import re
from collections import Counter, defaultdict

def analyze_errors(log_file, top_n=10):
    error_patterns = defaultdict(list)
    status_counter = Counter()
    error_ips = Counter()

    pattern = re.compile(
        r'(?P<ip>\S+) \S+ \S+ \[(?P<time>[^\]]+)\] '
        r'"(?P<method>\S+) (?P<path>\S+) \S+" '
        r'(?P<status>\d+) (?P<size>\S+)'
    )

    with open(log_file) as f:
        for line in f:
            m = pattern.match(line)
            if not m:
                continue
            status = int(m.group('status'))
            if status >= 400:
                status_counter[status] += 1
                error_ips[m.group('ip')] += 1
                error_patterns[m.group('path')].append({
                    'status': status,
                    'ip': m.group('ip'),
                    'time': m.group('time')
                })

    print(f"ERROR_SUMMARY total_errors={sum(status_counter.values())}")
    print(f"ERROR_RATE={sum(status_counter.values())} errors")

    print("\n## 状态码分布")
    for status, count in status_counter.most_common(top_n):
        print(f"  {status}: {count}次")

    print(f"\n## 高频错误IP (Top {top_n})")
    for ip, count in error_ips.most_common(top_n):
        print(f"  {ip}: {count}次错误")

    print(f"\n## 高频错误路径")
    for path, errors in sorted(
        error_patterns.items(),
        key=lambda x: len(x[1]),
        reverse=True
    )[:top_n]:
        print(f"  {path}: {len(errors)}次错误")

if __name__ == "__main__":
    log_file = sys.argv[1] if len(sys.argv) > 1 else "/var/log/nginx/access.log"
    top_n = int(sys.argv[3]) if len(sys.argv) > 3 else 10
    analyze_errors(log_file, top_n)
```

### 使用效果

在Claude Code中：

```
> 分析项目日志中的错误请求

[Claude执行步骤]
1. 搜索日志文件 → 发现 logs/access.log
2. 运行 python3 scripts/analyze-errors.py logs/access.log --top 10
3. 解析输出并格式化报告

┌──────────────────────────────────────┐
│ 日志错误分析报告                        │
├──────────────────────────────────────┤
│ 总错误数: 347                         │
│ 错误率: 2.3%                          │
│                                      │
│ 状态码分布:                           │
│   404: 198次 (57%)                   │
│   500: 89次 (26%)                    │
│   403: 60次 (17%)                    │
│                                      │
│ ⚠️ 500错误占比偏高，建议检查:          │
│   /api/users (32次)                   │
│   /api/orders (28次)                  │
└──────────────────────────────────────┘

建议：/api/users 的500错误集中在下午2-4点，
可能是数据库连接池耗尽。建议检查该时段的DB指标。
```

---

## 团队分发策略

封装好的Skill需要分发给团队。有三种主流方案：

### 方案一：Git Submodule（推荐中小团队）

```bash
# 创建Skill仓库
git init my-team-skills
# 将Skills放入仓库
cp -r deploy-tool my-team-skills/
cp -r log-analyzer my-team-skills/

# 在项目中引用
cd my-project
git submodule add git@github.com:team/my-team-skills.git .claude/skills/team
```

每次`git submodule update`即可同步最新Skill。

### 方案二：安装脚本（适合快速分发）

```bash
# install-team-skills.sh
SKILLS_REPO="git@github.com:team/my-team-skills.git"
INSTALL_DIR="$HOME/.claude/skills"

git clone --depth 1 "$SKILLS_REPO" /tmp/team-skills
cp -r /tmp/team-skills/* "$INSTALL_DIR/"
rm -rf /tmp/team-skills

echo "已安装以下Skills:"
ls "$INSTALL_DIR"
```

### 方案三：Claude Code Skill Registry

对于有版本管理需求的大型团队，可以使用社区Registry方案（如csreg.nexus），或搭建私有Registry。将Skills发布到Registry后，团队成员通过简单的安装命令获取：

```bash
# 从Registry安装（示例）
claude skill install @team/deploy-tool@^1.0
```

---

## 常见陷阱与排障

### 陷阱一：脚本路径硬编码

```markdown
❌ 错误：bash /Users/john/.claude/skills/deploy/scripts/deploy.sh
✅ 正确：bash scripts/deploy.sh（相对于Skill目录）
```

Claude Code执行脚本时的工作目录是项目根目录。在SKILL.md中使用相对于Skill安装路径的引用。

### 陷阱二：缺少错误边界

脚本如果输出不符合预期格式，Claude会困惑。始终在脚本中添加明确的成功/失败标记：

```bash
# 每个关键步骤都标记
echo "::STEP::build"
docker build . || { echo "STEP_FAILED step=build"; exit 1; }
echo "::STEP::push"
docker push myapp:latest || { echo "STEP_FAILED step=push"; exit 1; }
echo "ALL_STEPS_PASSED"
```

### 陷阱三：allowed-tools过于宽泛

```yaml
# 这等于给了Skill无限制的Shell权限
allowed-tools: Bash

# 应该精确到具体命令
allowed-tools: Bash(bash:docker*), Bash(bash:kubectl*), Bash(bash:scripts/*)
```

### 陷阱四：忽略跨平台兼容性

团队成员可能使用macOS和Linux。脚本中避免使用平台特有命令：

```bash
# macOS的date和Linux的date参数不同
# 统一使用Python处理日期
DATE=$(python3 -c "from datetime import datetime; print(datetime.now().strftime('%Y%m%d'))")
```

---

## 工作流程全景

```mermaid
flowchart TD
    A[现有脚本/工具] --> B{分析输入输出边界}
    B --> C[创建Skill目录结构]
    C --> D[放入scripts/目录]
    D --> E[编写SKILL.md frontmatter]
    E --> F[配置allowed-tools权限]
    F --> G[编写核心指令]
    G --> H[添加参数传递规则]
    H --> I[本地测试]
    I --> J{测试通过?}
    J -- 否 --> K[分析Claude执行日志]
    K --> L[调整指令/脚本]
    L --> I
    J -- 是 --> M{团队分发?}
    M -- 否 --> N[个人使用]
    M -- 是 --> O[推送到Git仓库]
    O --> P[Git Submodule / 安装脚本 / Registry]
    P --> Q[团队安装使用]

    style A fill:#e1f5fe
    style G fill:#fff3e0
    style I fill:#e8f5e9
    style Q fill:#fce4ec
```

```mermaid
flowchart LR
    subgraph 封装模式
        direction TB
        M1[纯封装型<br/>直接调用脚本]
        M2[编排型<br/>多脚本串联]
        M3[增强型<br/>Claude+脚本协作]
    end

    subgraph 参数通道
        direction TB
        C1[命令行参数<br/>最直接]
        C2[环境变量<br/>敏感信息]
        C3[配置文件<br/>复杂参数集]
    end

    M1 --> C1
    M2 --> C1
    M2 --> C2
    M3 --> C1
    M3 --> C3
```

---

## 延伸阅读

- [Extend Claude with skills - 官方文档](https://code.claude.com/docs/en/skills) — Anthropic官方Skills文档，涵盖创建、安装和分发全流程
- [Build Better Tools in Claude Skills with Scripts - egghead.io](https://egghead.io/lessons/build-better-tools-in-claude-skills-with-scripts~0oa34) — 深入讲解Skill中嵌入TypeScript/Bun脚本的技术细节
- [Claude Code Skill Frontmatter: Every YAML Option Explained](https://allahabadi.dev/blogs/ai/claude-code-skills-frontmatter-complete-guide/) — frontmatter所有YAML字段的完整参考
- [Configuring allowed-tools in Skill Frontmatter](https://instagit.com/shanraisshan/claude-code-best-practice/configuring-allowed-tools-in-skill-frontmatter/) — allowed-tools权限配置最佳实践
- [Distributing Claude Code skills across a team - LinkedIn](https://www.linkedin.com/pulse/distributing-claude-code-skills-across-team-will-jackson-1gx6e) — 企业团队Skill分发实战经验

---

## 训练营适用性评估

| 维度 | 评估 |
|------|------|
| **适合训练营类型** | DevOps训练营、自动化工程训练营、团队效能训练营 |
| **教学时长** | 3-4小时（含动手实验） |
| **前置知识要求** | Shell脚本基础、Claude Code基本操作、YAML格式 |
| **实验环境需求** | 每人一个带Claude Code的终端、Docker环境（可选） |
| **难度等级** | 中级——需要理解脚本和Claude Code两套体系并做桥接 |
| **建议分组** | 2-3人一组，每组选择一个真实脚本进行封装 |
| **交付物** | 一个可运行的脚本封装Skill + 简短的SKILL.md设计文档 |

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
