首页 › tutorials › 造技术债扫描Skill:TODO注释秒出债清单

概述

本教程带你从零打造一个技术债扫描 Skill:它能扫描代码库里所有 TODO / FIXME / HACK / XXX 注释,结合 git blame 算出每条债的作者和债龄(沉淀了多少天),并按"严重度 + 陈旧度"排序,自动产出一份技术债体检报告。适合已经装好 Claude Code、想学会自定义 Skill 这项核心扩展能力的开发者。学完后你将掌握 Skill 的目录结构、frontmatter 字段、动态上下文注入(!command``)、支撑脚本、参数替换与触发调优——这套方法论可直接套用到任何重复性工作流上。


一、前置条件

项目 要求
Claude Code 已安装,版本建议 v2.1.145+(本教程用到 ! 动态注入与 ${CLAUDE_SKILL_DIR} 替换)
终端环境 macOS / Linux,或开启了 CLAUDE_CODE_USE_POWERSHELL_TOOL 的 Windows
工具链 grep、git、awk、date(系统自带)
测试仓库 任意一个 git 仓库,有几个 TODO 注释最佳

核心认知(一句话):Skill 就是一个带 SKILL.md 的文件夹。SKILL.md 顶部是 YAML frontmatter(告诉 Claude "我是什么、何时启用我"),下面是 Markdown 正文(Claude 执行时要遵循的指令)。文件夹名就是你敲的命令名。


二、先理解 Skill 的"渐进式披露"机制

很多人误以为 Skill 是把一大段提示词塞进每次对话——恰恰相反。Skill 的精髓是按需加载:

flowchart LR
    A[会话启动] --> B[只加载各 Skill 的<br/>description 摘要<br/>≈ 极低成本]
    B --> C{是否被触发?}
    C -- 用户敲 /命令 --> D[加载完整 SKILL.md 正文]
    C -- Claude 判断描述匹配 --> D
    C -- 不匹配 --> E[正文永不加载<br/>零成本]
    D --> F[执行动态注入 !命令]
    F --> G[把脚本输出 + 指令<br/>一起交给 Claude]
    G --> H[Claude 产出最终结果]

关键推论:description 是常驻的"目录索引",正文是触发后才花的钱。所以 description 要写好(决定能否被正确触发),正文要写精(一旦加载就持续占 token)。这与 CLAUDE.md 的"事实常驻"形成互补——当一个 CLAUDE.md 段落长成了"操作流程",就该抽成 Skill。


三、第 1 步:创建 Skill 目录结构

个人级 Skill 放在 ~/.claude/skills/ 下(所有项目可用),项目级放 .claude/skills/(仅当前项目)。我们做一个个人级的:

mkdir -p ~/.claude/skills/tech-debt-scan
cd ~/.claude/skills/tech-debt-scan

最终目录长这样:

~/.claude/skills/tech-debt-scan/
├── SKILL.md              # 必需:frontmatter + 指令
└── scan_tech_debt.sh     # 可选:支撑脚本(干脏活的)

文件夹名 tech-debt-scan 决定了命令名是 /tech-debt-scan。frontmatter 里的 name 字段只是显示标签,不改命令名。


四、第 2 步:写支撑脚本 scan_tech_debt.sh(干脏活)

Skill 的设计哲学:让脚本做机械、确定的事(grep + blame),让 Claude 做需要判断的事(排序、归类、给建议)。两者分工,既稳又省 token。

把下面内容存为 ~/.claude/skills/tech-debt-scan/scan_tech_debt.sh:

#!/usr/bin/env bash
# scan_tech_debt.sh — 扫描技术债标记,附加 git blame 的作者与债龄
set -euo pipefail

ROOT="${1:-.}"          # $1 为空时默认扫当前目录
cd "$ROOT"

# 1) grep 出所有 TODO/FIXME/HACK/XXX,过滤常见无关目录与二进制后缀
grep -rnIE '\b(TODO|FIXME|HACK|XXX)\b[: ]' \
  --include='*.py' --include='*.js' --include='*.ts' --include='*.tsx' \
  --include='*.java' --include='*.go' --include='*.rs' \
  --exclude-dir=node_modules --exclude-dir=.git \
  --exclude-dir=dist --exclude-dir=build --exclude-dir=.next \
  . 2>/dev/null || true \
| while IFS=: read -r file lineno content; do
    [ -f "$file" ] || continue

    # 2) git blame 该行,取作者与提交时间戳
    blame=$(git blame --line-porcelain "$file" -L "$lineno,$lineno" 2>/dev/null || true)
    author=$(awk '/^author /{print $2" "$3; exit}' <<<"$blame")
    ts=$(awk '/^author-time /{print $2; exit}' <<<"$blame")

    # 3) 把时间戳换算成"债龄天数"
    days="-"
    if [[ "$ts" =~ ^[0-9]+$ ]]; then
      days=$(( ( $(date +%s) - ts ) / 86400 ))
    fi

    # 4) 严重度初判:FIXME/HACK = 高,其余 = 低(留给 Claude 再细化)
    sev="低"
    if grep -qE '\bFIXME\b|\bHACK\b' <<<"$content"; then sev="高"; fi

    content=$(printf '%s' "$content" | sed 's/^[[:space:]]*//; s/|/\\|/g')
    # 输出:严重度 | 文件:行号 | 债龄 | 作者 | 内容
    printf '%s|%s:%s|%s天|%s|%s\n' "$sev" "$file" "$lineno" "$days" "$author" "$content"
  done

赋可执行权限:

chmod +x ~/.claude/skills/tech-debt-scan/scan_tech_debt.sh

预期结果:在任一 git 仓库里手工跑 ~/.claude/skills/tech-debt-scan/scan_tech_debt.sh,会吐出形如 高|src/auth.py:42|128天|张三|FIXME 密码明文比对应换 bcrypt 的管道分隔行。脚本能独立跑通,是 Skill 稳定的前提。

常见问题: - 报 grep: ... No such file → 去掉某个 --include 即可,或确认目录有对应后缀文件。 - days 全是 - → 该目录不是 git 仓库,git blame 失败;先 git init 或换到仓库根。 - 作者显示乱码 → 部分系统 awk 取 $2 $3 不够,可改用 git log 的 %an,但对大多数场景足够。


五、第 3 步:写 SKILL.md(frontmatter + 指令 + 动态注入)

这是核心文件。把下面内容存为 ~/.claude/skills/tech-debt-scan/SKILL.md:

---
name: 技术债扫描
description: 扫描代码库的 TODO/FIXME/HACK/XXX 注释,结合 git blame 算出债龄与作者,输出按严重度和陈旧度排序的技术债清单。在用户问"技术债""还有多少 TODO""哪些 FIXME 该先还""清理技术债"时使用。
argument-hint: [扫描根目录,默认当前目录]
allowed-tools: Bash Read
---

## 待分析的原始债清单

扫描脚本输出(格式:严重度 | 文件:行号 | 债龄 | 作者 | 内容):

\`\`\`
!`${CLAUDE_SKILL_DIR}/scan_tech_debt.sh "$ARGUMENTS"`
\`\`\`

## 你的任务

把上面的原始清单整理成一份**技术债体检报告**:

1. **总览**:报总数,并按标记类型(TODO/FIXME/HACK/XXX)与严重度分桶统计。
2. **明细表**:输出 Markdown 表格,列 `严重度 | 债龄 | 文件:行号 | 作者 | 内容摘要`,**按"严重度降序、债龄降序"排序**——FIXME/HACK 且超过 90 天的排最前。
3. **Top 3 必还债**:逐条说明为什么危险(FIXME=已知缺陷,HACK=脆弱实现,XXX=待定危险区),并给处理方向(删除 / 重写 / 补测试 / 转工单)。
4. **空结果**:若脚本输出为空,明确回复"未发现技术债标记,工作树干净"。

`$ARGUMENTS` 是用户传入的扫描根目录;为空时脚本默认扫当前目录。

逐段拆解

Frontmatter 字段(全部可选,仅 description 强烈推荐):

字段 作用
name 列表里的显示名(不影响命令名)
description 最关键。Claude 用它判断何时自动触发。description + when_to_use 合计在列表里被截断到 1536 字符,所以关键用例放最前
argument-hint 敲命令时自动补全里显示的参数提示,如 [扫描根目录]
allowed-tools 该 Skill 激活期间,Claude 用这些工具免确认。这里放 Bash Read,因为要跑脚本、可能读文件

动态上下文注入(最该掌握的特性):

!`命令`        # 行内注入:Claude Code 先执行命令,再用输出替换这一行
```!            # 代码围栏注入:整块执行并替换

我们的脚本通过 ${CLAUDE_SKILL_DIR} 引用——这是 Claude Code 内置替换变量,永远指向 SKILL.md 所在目录,跟当前工作目录无关,保证脚本路径不会因你在哪个项目里而失效。

参数替换:$ARGUMENTS 代表用户敲命令时传的全部参数。例如敲 /tech-debt-scan ./apps/web,$ARGUMENTS 就是 ./apps/web。还有 $0/$1(按位置取)、$name(命名参数,需配合 arguments 字段)等。


六、第 4 步:测试两种调用方式

进入任意 git 仓库(先故意留几个 TODO),启动 claude,然后:

方式 A——显式调用(最可靠):

/tech-debt-scan

或带参数扫子目录:

/tech-debt-scan ./src

方式 B——自然语言触发(靠 description 匹配):

帮我看看项目里欠了多少技术债,哪些 FIXME 最该先还?

Claude 会自动匹配到这个 Skill 并执行。两种方式都应输出类似下面的报告:

## 技术债体检报告

共发现 7 处技术债标记:TODO×4、FIXME×2、HACK×1;高严重度 3 条。

| 严重度 | 债龄 | 文件:行号 | 作者 | 内容摘要 |
|--------|------|-----------|------|----------|
| 高 | 128天 | src/auth.py:42 | 张三 | FIXME 密码明文比对应换 bcrypt |
| 高 | 96天  | utils/cache.ts:11 | 李四 | HACK 临时绕过空指针,上线前必须修 |
| 低 | 30天  | api/order.go:8 | 王五 | TODO 加幂等校验 |
| ... | | | | |

### Top 3 必还债
1. **auth.py:42 密码明文比对**(FIXME / 128天)——已知安全缺陷且超期 4 个月,建议本周改用 bcrypt,并补一组对照测试。
2. **cache.ts:11 临时绕过**(HACK / 96天)——脆弱实现,建议定位空指针根因后删除该分支。
3. ... 

Claude Code 有热加载:你改了 SKILL.md 或脚本,无需重启,下一条消息即生效。


七、第 5 步:调优 description,避免"不触发"或"乱触发"

这是新手最容易踩的坑。官方给出三条排障口诀:

  1. Skill 不触发 → description 没覆盖用户真实说法。补上用户会怎么问的原话("还有多少 TODO""清理技术债"),就像我们已经做的那样。
  2. Skill 触发太频繁 → 描述太宽泛(例如只写"分析代码")。收紧到具体动作 + 触发场景。
  3. 描述被截断 → 关键用例必须放最前,别铺垫背景。1536 字符是硬上限。

如果你希望这个 Skill 只手动调用、绝不自动触发(比如它是个会改文件的重型流程),加一行:

disable-model-invocation: true

反之,若想隐藏某个"背景知识型" Skill、不让它出现在 / 菜单,用 user-invocable: false。两者组合能精细控制"谁能触发它"。


八、实战案例:5 分钟跑通完整流程

新建一个最小演示仓库:

mkdir ~/debt-demo && cd ~/debt-demo
git init -q && git config user.email "[email protected]" && git config user.name "demo"

cat > auth.py <<'EOF'
def login(pwd):
    # FIXME 明文比对密码,存在时序攻击风险,换 bcrypt
    return pwd == "admin"
    # TODO 记录失败次数,连续 5 次锁定账号
EOF

cat > cache.ts <<'EOF'
// HACK 这里直接吞掉了空值,先让 demo 跑起来,上线前必须修
export function get(k){ return store[k] ?? null }
// XXX 缓存过期策略待定
EOF

git add -A && git commit -qm "init demo with debt"

然后:

claude
# 进入交互后输入:
/tech-debt-scan

预期:报告会准确识别 4 条债(2 高 2 低),并指出 auth.py 的 FIXME 因为是已知缺陷应优先处理。注意:因为是当天提交,债龄 会显示 0天——这验证了 git blame 链路打通;真实老仓库里你会看到几十上百天的沉淀债。


九、进阶:让大型仓库扫描更稳、更省 token

代码库很大时,有三个增强方向:

1. 跑在子代理里(隔离上下文)。把扫描的大量原始输出关进独立上下文,只把报告回传主会话:

context: fork
agent: Explore

context: fork 让 Skill 在 fork 出的子代理中运行;agent: Explore 用只读探索型子代理,安全且不污染主对话历史。

2. 用 paths 限定生效范围。只在编辑特定文件时才让 Claude 自动加载它:

paths: "**/*.{py,ts,tsx,go,java,rs}"

3. 拆支撑文件。若脚本膨胀,可拆成 scan_tech_debt.sh + format_report.py,在 SKILL.md 里注明每个文件做什么、何时加载,正文保持精简。

记住一个成本铁律:Skill 正文一旦加载,跨多轮都留在上下文里。所以正文要"说要做什么",而非"讲为什么、讲历史",每多一行都是反复支出的 token。


十、整套工作流程总览

flowchart TD
    U[用户: 帮我看看技术债] --> M{Claude 匹配 description?}
    M -->|匹配| L[加载 SKILL.md 正文]
    M -->|用户敲 /tech-debt-scan| L
    L --> S[替换变量: ${CLAUDE_SKILL_DIR}, $ARGUMENTS]
    S --> I[动态注入: 运行 scan_tech_debt.sh]
    I --> R[拿到原始管道分隔清单]
    R --> C[Claude 排序/归类/点名 Top3]
    C --> O[输出技术债体检报告]
    I -.失败.-> DBG[排查: chmod? git 仓库? 后缀?]

延伸阅读


训练营适用性评估

维度 评估
适合的训练营类型 AI 工程提效 / 研发效能 / 命令行工具开发类训练营;也适合"AI + DevOps"主题作为实操单元
学员基础 会基本命令行(grep/git)+ 用过 Claude Code 即可;无需编程语言专精
教学时长 约 90–120 分钟:30 分钟讲机制 + 45 分钟动手造 + 30 分钟调优与排障
难度定位 ⭐⭐⭐(中偏低)——核心是"配置 + 脚本",不涉及复杂编程,但 frontmatter 调优需反复试错
可拓展练习 ① 改成扫描 console.log/print 遗留;② 加 paths 做多语言仓库;③ 接 gh issue create 把 Top 债直接转成 GitHub 工单
评估产出 学员能独立交付一个"扫描+归因+排序+建议"的可用 Skill,并演示自然语言触发

参考来源

  1. Extend Claude with skills — Claude Code 官方文档 — Skill 目录结构、frontmatter 全字段、动态上下文注入与字符串替换变量的权威定义。
  2. Claude Code Skill Frontmatter: Every YAML Option Explained — 逐字段图解 15 个 frontmatter 选项,含触发控制的取舍建议。
  3. Chapter 2: Custom Skills — Claude Code Handbook — 从机制到实践的系统性进阶讲解,覆盖支撑文件与子代理执行。
  4. How to create a Claude Code skill (and the best practices nobody put in) — 社区总结的 description 撰写与触发调优实战经验。
  5. Creating custom skills — Claude.ai Documentation — 自定义 Skill 的官方 how-to 指南,含从零创建到分享的完整流程。

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