现在位置: 首页 > Skills 教程 > 正文

Skills 与工具链集成

Skills 可以通过与外部工具链集成,Skill 可以完成单靠 Claude 无法完成的任务。

本篇介绍如何在 Skill 中调用命令行工具、系统工具及第三方库,并提供一个完整的集成示例。


Skills 可以调用的工具类型

工具类型示例调用方式
系统命令ls、cp、find、wcsubprocess.run()
语言运行时python、node、bashsubprocess.run()
文档处理工具pandoc、pdflatexsubprocess.run()
媒体处理工具ffmpeg、imagemagicksubprocess.run()
Python 库pandas、openpyxl、pypdfimport 后直接调用
Node.js 工具prettier、eslintnpx 调用

调用外部工具前,先确认工具在运行环境中已安装。Claude 沙箱中预装了常用工具(python3、pip、node、npm),但 pandoc、ffmpeg 等需要额外安装。


在脚本中调用外部命令

Python 的 subprocess 模块是调用外部命令的标准方式,推荐统一封装成工具函数复用。

实例

# 文件路径:scripts/tool_integration.py
import subprocess
import sys
import json

def run_command(cmd: list, timeout: int = 60) -> dict:
    """
    运行外部命令并捕获输出

    参数:
        cmd:     命令列表,如 ["pandoc", "--version"]
        timeout: 超时秒数,默认 60

    返回:
        包含 success、stdout、stderr、returncode 的字典
    """

    try:
        result = subprocess.run(
            cmd,
            capture_output=True,   # 同时捕获 stdout 和 stderr
            text=True,             # 以字符串返回,而非字节
            timeout=timeout
        )
        return {
            "success":    result.returncode == 0,
            "returncode": result.returncode,
            "stdout":     result.stdout.strip(),
            "stderr":     result.stderr.strip()
        }
    except FileNotFoundError:
        return {
            "success":    False,
            "returncode": -1,
            "stdout":     "",
            "stderr":     f"命令不存在:{cmd[0]},请确认已安装"
        }
    except subprocess.TimeoutExpired:
        return {
            "success":    False,
            "returncode": -1,
            "stdout":     "",
            "stderr":     f"命令执行超时(超过 {timeout} 秒)"
        }

# 示例:用 pandoc 将 Markdown 转换为 HTML
if __name__ == "__main__":
    result = run_command([
        "pandoc",
        "/mnt/user-data/uploads/readme.md",
        "-o", "/mnt/user-data/outputs/readme.html",
        "--standalone"
    ])
    if result["success"]:
        print("转换成功")
    else:
        print(f"转换失败:{result['stderr']}")
        sys.exit(1)

检查工具是否可用

在 Skill 执行前检查所需工具是否安装,能在任务中途失败前给出清晰提示。

实例

# 文件路径:scripts/check_tools.py
import shutil
import sys

REQUIRED_TOOLS = [
    ("pandoc",  "sudo apt-get install pandoc"),
    ("ffmpeg",  "sudo apt-get install ffmpeg"),
    ("convert", "sudo apt-get install imagemagick"),
]

def check_tools(tools: list) -> bool:
    """检查工具列表,返回 True 表示全部就绪"""
    all_ok = True
    for tool, install_cmd in tools:
        path = shutil.which(tool)   # 在 PATH 中查找工具路径
        if path:
            print(f"  已安装:{tool} → {path}")
        else:
            print(f"  未安装:{tool}  安装命令:{install_cmd}")
            all_ok = False
    return all_ok

if __name__ == "__main__":
    print("检查工具依赖...")
    if not check_tools(REQUIRED_TOOLS):
        print("\n请先安装缺少的工具。")
        sys.exit(1)
    print("\n所有工具已就绪,继续执行。")
检查工具依赖...
  已安装:pandoc → /usr/bin/pandoc
  未安装:ffmpeg  安装命令:sudo apt-get install ffmpeg
  未安装:convert  安装命令:sudo apt-get install imagemagick

请先安装缺少的工具。

在 SKILL.md 中声明工具依赖

用 YAML frontmatter 的 compatibility 字段列出所有外部依赖,让用户安装 Skill 前就知道需要准备什么。

---
name: doc-converter
description: >
  将文档在不同格式间转换,支持 Markdown、HTML、PDF、Word。
  当用户需要格式转换、导出文档时触发。
compatibility:
  tools:
    - pandoc >= 2.14   # 文档格式转换
    - python >= 3.8    # 运行辅助脚本
  python_packages:
    - pypdf >= 3.0     # PDF 处理
    - python-docx >= 1.0
---

集成 Node.js 工具

通过 npx 可以直接调用 npm 包中的 CLI 工具,无需全局安装。

实例

# 文件路径:scripts/use_node_tool.py
import subprocess
import sys

def run_prettier(file_path: str) -> bool:
    """用 prettier 格式化代码文件"""
    result = subprocess.run(
        ["npx", "--yes", "prettier", "--write", file_path],
        capture_output=True,
        text=True
    )
    if result.returncode == 0:
        print(f"格式化成功:{file_path}")
        return True
    print(f"格式化失败:{result.stderr}")
    return False

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("用法:python use_node_tool.py <文件路径>")
        sys.exit(1)
    sys.exit(0 if run_prettier(sys.argv[1]) else 1)

npx --yes 首次运行时会自动下载工具包,需要网络连接到 npm registry。在网络受限的环境中应提前全局安装:npm install -g prettier


工具调用结果的标准化处理

不同工具的输出格式各不相同,建议在 Skill 层统一封装,对外只暴露一致的结构。

处理方式适用场景典型工具
捕获 stdout工具将结果输出到标准输出pandoc、wc、cat
检查返回码工具成功返回 0,失败返回非 0几乎所有 CLI 工具
读取输出文件工具将结果写入指定文件ffmpeg、pandoc -o
解析 JSON 输出工具支持 --json 参数eslint --format json

完整集成示例:Markdown 转 PDF 报告

以下示例将 pandoc 与 Python 脚本结合,实现一个完整的 Markdown → PDF 生成 Skill 脚本。

实例

# 文件路径:scripts/md_to_pdf.py
# 完整工作流:检查工具 → 验证输入 → 调用 pandoc → 确认输出

import subprocess
import shutil
import sys
import os
import json
from datetime import datetime

def check_pandoc() -> bool:
    """检查 pandoc 是否可用"""
    if not shutil.which("pandoc"):
        print("错误:未找到 pandoc,请运行:sudo apt-get install pandoc")
        return False
    return True

def validate_input(md_path: str) -> bool:
    """验证输入的 Markdown 文件"""
    if not os.path.exists(md_path):
        print(f"错误:文件不存在 → {md_path}")
        return False
    if not md_path.lower().endswith(".md"):
        print(f"错误:文件必须是 .md 格式 → {md_path}")
        return False
    return True

def convert_to_pdf(md_path: str, output_dir: str) -> dict:
    """调用 pandoc 将 Markdown 转换为 PDF"""
    os.makedirs(output_dir, exist_ok=True)

    # 生成带时间戳的输出文件名,避免覆盖旧文件
    base_name   = os.path.splitext(os.path.basename(md_path))[0]
    timestamp   = datetime.now().strftime("%Y%m%d_%H%M%S")
    output_path = os.path.join(output_dir, f"{base_name}_{timestamp}.pdf")

    result = subprocess.run(
        [
            "pandoc", md_path,
            "-o", output_path,
            "--pdf-engine=xelatex",      # 支持中文
            "-V", "CJKmainfont=SimSun",  # 中文字体(按环境调整)
            "-V", "geometry:margin=2cm"  # 页边距
        ],
        capture_output=True,
        text=True,
        timeout=120
    )

    if result.returncode == 0 and os.path.exists(output_path):
        size_kb = os.path.getsize(output_path) // 1024
        return {
            "status":  "success",
            "output":  output_path,
            "size_kb": size_kb
        }
    return {
        "status": "error",
        "message": result.stderr or "pandoc 未生成输出文件"
    }

def main():
    if len(sys.argv) < 2:
        print("用法:python md_to_pdf.py <Markdown文件路径>")
        sys.exit(1)

    md_path    = sys.argv[1]
    output_dir = "/mnt/user-data/outputs"

    # 逐步检查,任一步骤失败立即退出
    if not check_pandoc():
        sys.exit(1)
    if not validate_input(md_path):
        sys.exit(1)

    print(f"正在转换:{md_path}")
    result = convert_to_pdf(md_path, output_dir)
    print(json.dumps(result, ensure_ascii=False, indent=2))

    sys.exit(0 if result["status"] == "success" else 1)

if __name__ == "__main__":
    main()
正在转换:/mnt/user-data/uploads/runoob_report.md
{
  "status": "success",
  "output": "/mnt/user-data/outputs/runoob_report_20260518_102305.pdf",
  "size_kb": 248
}

在 SKILL.md 中调用该脚本:

## 执行转换

获取用户上传的 .md 文件路径后,运行:

```bash
python scripts/md_to_pdf.py <文件路径>
```

解析 JSON 输出:
- status 为 "success":调用 present_files 展示 output 路径的文件
- status 为 "error":将 message 内容展示给用户,说明可能原因