首页 › tutorials › 造注释补全Skill:裸函数秒变自解释

造注释补全Skill:裸函数秒变自解释

一份从零到发布的 Claude Code Skill 实战教程,带完整脚本、渐进式披露设计与可复现案例。

概述

本教程带你从零创建一个名为 comment-doctor 的自定义 Skill:它扫描项目源代码,精确定位缺失文档注释的函数、方法与类,再按目标语言规范(Python docstring、JSDoc、GoDoc、JavaDoc)生成准确的中文注释并写回文件。学完你将掌握 Skill 的目录结构、SKILL.md 元数据写法、渐进式披露(Progressive Disclosure)三层架构,以及如何用挂载脚本把"凭感觉分析"升级为"可量化、可复核"的工程化能力。适用人群:已跑通 Claude Code 并能创建项目的开发者,希望把重复性文档工作沉淀为团队可复用资产的人。

前置条件


第 1 步:理解 Skill 的本质——三层渐进式披露

在动手之前,必须先吃透 Skill 区别于"一段提示词"的核心设计:渐进式披露(Progressive Disclosure)。它的工程动机很朴素——上下文窗口是稀缺资源,不该把所有指令一股脑塞进去。

Skill 把信息分成三个加载层级:

flowchart TD
    A[用户提问/命令] --> B{Tier 1: 仅读 frontmatter description}
    B -->|不相关| C[不加载, 零成本]
    B -->|相关| D[Tier 2: 加载 SKILL.md 正文]
    D --> E[执行任务]
    E -->|需要细规范| F[Tier 3: 按需加载 references/ 脚本]
    F --> E
    style B fill:#fef3c7
    style D fill:#dbeafe
    style F fill:#dcfce7
层级 内容 何时加载 成本
Tier 1 frontmatter 的 description 每次对话都读 极低
Tier 2 SKILL.md 正文指令 仅当 Skill 被判定相关并触发 中
Tier 3 references/、scripts/ 等附属文件 正文指令显式要求时才读 按需

这条铁律直接影响成败:description 写不好,Skill 永远不会被触发;正文写太长,每次触发都浪费上下文。后面每一步都围绕这条铁律展开。

第 2 步:创建 Skill 目录骨架

Claude Code 在两个位置查找 Skill:个人级 ~/.claude/skills/ 与项目级 <repo>/.claude/skills/。本教程选个人级,这样 comment-doctor 在任何项目里都能用。

Skill 的目录名必须与 name 字段一致,且用小写连字符(kebab-case)。一个自包含的 Skill 推荐结构如下:

~/.claude/skills/comment-doctor/
├── SKILL.md                      # 入口:元数据 + 正文指令
├── scripts/
│   └── find_undocumented.py      # Tier 3:静态扫描脚本
└── references/
    └── docstring-styles.md       # Tier 3:各语言注释风格规范

操作命令(在终端执行):

mkdir -p ~/.claude/skills/comment-doctor/scripts
mkdir -p ~/.claude/skills/comment-doctor/references

预期结果:目录创建后,Claude Code 启动时会自动发现该 Skill 并把它的 description 注入可触发列表。你可以在会话里输入 / 或直接问"有没有补全注释的技能"来确认它已被识别。

常见问题:

第 3 步:编写 SKILL.md——元数据是触发开关

SKILL.md 由两部分组成:顶部的 YAML frontmatter 与下方的正文指令。先看 frontmatter 的最小可用版本:

---
name: comment-doctor
description: 扫描项目源代码,定位缺失文档注释的函数、方法与类,按目标语言规范(Python docstring、JSDoc、GoDoc、JavaDoc)生成准确的中文注释并写回文件。当用户要求"补全注释""给函数加文档""生成 docstring""让代码自解释",或代码缺少文档时触发。
---

frontmatter 只有两个必填字段,但每一个都有硬约束:

字段 约束 写法要点
name 最长 64 字符,须与目录名一致 全小写连字符,避免缩写歧义
description 最长 1024 字符 第三人称,先说"做什么",再列"何时触发"的关键短语

description 是整个 Skill 的命脉。Claude 仅凭它判断是否调用本 Skill,因此要"埋"进用户真实会说的高频短语("补全注释""生成 docstring""让代码自解释")。注意要用第三人称("扫描…定位…"),不要写"我可以帮你"这类第一人称表述——那是反模式,会降低匹配准确率。

接着写正文指令。正文应聚焦"做什么 + 用什么工具做 + 边界在哪",避免长篇大论:

# Comment Doctor

## 何时使用
当用户希望为无注释的函数、方法、类补全文档注释时使用。语言涵盖 Python、JavaScript/TypeScript、Go、Java。

## 工作流程(务必按序)
1. **先扫描**:运行 `python3 ~/.claude/skills/comment-doctor/scripts/find_undocumented.py <目标路径>`,得到缺失注释的函数清单(JSON)。
2. **读上下文**:对清单中的每一项,读取该函数及其调用处的代码,理解真实行为,而非按函数名臆测。
3. **查规范**:按目标语言,参考 `references/docstring-styles.md` 中的格式样板生成注释。内容要准确反映实际逻辑(参数含义、返回值、副作用、抛出的异常)。
4. **写回文件**:用 Edit 工具把注释插入到函数定义正下方。每改完一个文件,向用户报告本次新增注释的函数数量。
5. **输出总结**:在会话末尾给出 Markdown 表格,列出已补全注释的文件与函数数。

## 边界(禁止行为)
- 不要修改函数体逻辑,只加注释。
- 不要生成显而易见的废话注释(如 `# 返回 a + b` 给 `def add(a, b): return a+b`)。如果函数确实简单,写一句总结即可,或主动跳过并说明。
- 不要为已经存在注释的函数重复添加。

正文刻意短小——把"各语言具体长什么样"这种细节挪到 Tier 3 的 references/,需要时才加载。

常见问题:

第 4 步:编写挂载脚本——把"凭感觉"升级为"可量化"

Tier 2 正文只能让 Claude 读文件、靠理解来判断"哪些函数缺注释",这在大型项目里既慢又不可靠。挂载脚本(Tier 3)的引入正是为了解决这个痛点:用确定性算法给出精确清单,Claude 据此逐个处理,可复核、可重跑。

创建 ~/.claude/skills/comment-doctor/scripts/find_undocumented.py:

#!/usr/bin/env python3
"""扫描源文件,输出缺失文档注释的函数/类清单(JSON)。
用法: python3 find_undocumented.py <path>
"""
import ast, json, sys, os

# 支持的扩展名 → 解析器(本脚本聚焦 Python;JS/TS 可用 tree-sitter 扩展)
SUPPORTED = {".py": "python"}
SKIP_DIRS = {"node_modules", ".git", "venv", ".venv", "__pycache__", "dist", "build"}

def find_py(path):
    """解析单个 Python 文件,返回缺 docstring 的函数/类。"""
    src = open(path, encoding="utf-8").read()
    tree = ast.parse(src)
    out = []
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)):
            if not ast.get_docstring(node):
                kind = "class" if isinstance(node, ast.ClassDef) else "function"
                out.append({"type": kind, "name": node.name,
                            "line": node.lineno, "file": path})
    return out

def walk(root):
    results = []
    for dp, dn, fn in os.walk(root):
        dn[:] = [d for d in dn if d not in SKIP_DIRS]   # 原地剪枝
        for f in fn:
            p = os.path.join(dp, f)
            if os.path.splitext(f)[1] in SUPPORTED:
                try:
                    results += find_py(p)
                except SyntaxError:
                    pass   # 跳过无法解析的文件
    return results

if __name__ == "__main__":
    root = sys.argv[1] if len(sys.argv) > 1 else "."
    print(json.dumps(walk(root), ensure_ascii=False, indent=2))

运行预期结果(对某个含无注释函数的目录执行):

[
  {"type": "function", "name": "calculate_tax", "line": 12, "file": "./billing/calc.py"},
  {"type": "class", "name": "OrderRepository", "line": 40, "file": "./billing/repo.py"}
]

这段脚本体现了三层设计的精髓:它独立于 Skill 体系,可单独测试、单独改进;Skill 正文只需说"运行它并处理清单",把繁重的静态分析外包出去。

常见问题:

第 5 步:编写风格规范参考文件

创建 ~/.claude/skills/comment-doctor/references/docstring-styles.md,这里集中存放每种语言的样板,正文只在需要时引导加载:

# 文档注释风格规范

## Python(Google 风格 docstring)
"""计算含税金额。

Args:
    price: 不含税单价。
    rate: 税率,0~1 之间的小数。

Returns:
    含税后的总价。

Raises:
    ValueError: rate 超出 [0, 1] 时抛出。
"""

## JavaScript / TypeScript(JSDoc)
/**
 * 计算含税金额。
 * @param {number} price - 不含税单价。
 * @param {number} rate - 税率,0~1。
 * @returns {number} 含税总价。
 */

## Go(GoDoc,注释紧贴声明、以名字开头)
// CalculateTax 计算含税金额。price 为不含税单价,rate 为 0~1 的税率。
func CalculateTax(price float64, rate float64) float64 { ... }

## Java(JavaDoc)
/** 计算含税金额。
 * @param price 不含税单价
 * @param rate 税率,0~1
 * @return 含税总价
 */

把样板放进 Tier 3 而非正文,是因为它只在"生成注释"那一步才需要,提前加载纯属浪费上下文。

第 6 步:端到端测试

准备一个最小测试项目 ~/demo_shop/,内含故意无注释的代码:

# ~/demo_shop/billing.py
def apply_discount(price, pct):
    if pct < 0 or pct > 1:
        raise ValueError("pct 必须在 0~1")
    return price * (1 - pct)

class Cart:
    def add(self, sku, qty=1):
        self.items[sku] = self.items.get(sku, 0) + qty

在 Claude Code 会话里触发 Skill(自然语言即可):

帮我把 ~/demo_shop/billing.py 里没注释的函数都补上文档。

预期结果:Claude 自动调用 comment-doctor,运行脚本得到清单,逐个生成注释并写回。最终 billing.py 变为:

def apply_discount(price, pct):
    """对原价施加折扣。

    Args:
        price: 原价。
        pct: 折扣比例,0~1 之间(0.2 表示打 8 折)。

    Returns:
        折扣后的价格。

    Raises:
        ValueError: pct 不在 [0, 1] 区间时抛出。
    """
    if pct < 0 or pct > 1:
        raise ValueError("pct 必须在 0~1")
    return price * (1 - pct)

class Cart:
    """购物车,维护 SKU 到数量的映射。"""

    def add(self, sku, qty=1):
        """向购物车加入商品,已存在则累加数量。

        Args:
            sku: 商品唯一标识。
            qty: 本次添加数量,默认 1。
        """
        self.items[sku] = self.items.get(sku, 0) + qty

并给出类似总结表:

文件 新增注释函数/类
billing.py apply_discount、Cart、Cart.add

常见问题:


实战案例:给一个真实 Flask 项目批量补注释

把上述六步串成一个完整工作流,目标是一个 30+ 路由、文档缺失严重的 Flask 仓库。

  1. 进入仓库:cd ~/my_flask_app
  2. 触发 Skill:对 Claude 说"用 comment-doctor 扫描 app/ 目录,为所有缺失 docstring 的函数补注释,每改 5 个文件向我汇报一次"。
  3. Skill 自动执行: - 跑 find_undocumented.py app/,假设命中 47 处; - 按文件分批,每批读上下文 → 查 docstring-styles.md → 用 Edit 写回 → 汇报; - 全程不碰业务逻辑,只增注释。
  4. 校验:git diff --stat 查看改动行数;python -m compileall app/ 确认未引入语法错误;对抽样函数人工核对注释与逻辑是否一致。

整个案例的价值在于可复现:同样的脚本、同样的指令,换一个项目再跑一次,结果同样可信。这正是 Skill 相比"一次性提示词"的根本优势。

调优进阶:让 Skill 越用越准

flowchart LR
    U[真实使用] --> T[触发记录]
    T --> M{该触发时触发?}
    M -->|漏触发| D1[在 description 补同义短语]
    M -->|误触发| D2[收窄 description 场景]
    M -->|准| OK[保持]
    D1 --> U
    D2 --> U
    OK --> U

Skill 是"活"的资产,建议建立调优闭环:

延伸阅读

训练营适用性评估

维度 评估
适合的训练营类型 AI 工程化实战营、研发效能提升营、Claude Code 专项训练营
学员基础要求 会用命令行、读过 YAML、写过任意一门后端语言
预计教学时长 讲解 + 跟练 90 分钟,独立完成实战案例另需 60 分钟
可交付成果 每位学员带走一个可运行、可复用的个人 Skill,并能套用到自己项目
进阶衔接 学完后可衔接"造量化基准测试体系""调优 Skill 描述"等专题,深化测试与触发优化

本教程把 Skill 的元数据、目录结构、渐进式披露三层与脚本挂载四个要点,全部压缩进一个能立刻用、能反复跑的真实技能里。掌握 comment-doctor 的搭建路径,你就掌握了造任何自定义 Skill 的通用方法。

参考来源

  1. Skill authoring best practices — Claude Platform Docs — 官方权威,规定 name/description 字段约束与正文写作准则。
  2. Agent Skills — Overview — Skill 在 Agent 与工具体系中的定位与三原语概念。
  3. anthropics/skills — GitHub — 官方 Skill 样例仓库,每个技能自包含于独立文件夹,是目录结构的最佳范式来源。
  4. Claude Code Skills 2026 — Progressive Disclosure — 团队工程化视角下的三层渐进式披露深度解读。
  5. Anatomy of a Skill — Vercel Academy — SKILL.md 解剖与 YAML frontmatter 各字段含义。

[!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学通信知识星球海报-扫码加入