本教程面向已能在 Claude Code 里完成基本对话、但从未写过自定义 Skill 的开发者。学完后你将独立交付一个可在真实仓库里运行的
tech-debt-scannerSkill:扫描 TODO/FIXME/HACK 等技术债标记、按严重度归类、产出一份可追踪的技术债登记表,并掌握 Skill 的解剖结构、热加载调试、自动触发调优与多层级分发。
allowed-tools、paths、context: fork 等字段在新版本稳定可用)。git、bash、python3 的 macOS / Linux / WSL 终端;Windows 用户建议在 Git Bash 或 WSL 下操作。TODO / FIXME 注释的 Git 仓库(没有的话,文章末尾的实战案例会教你临时造一个)。很多人写 Skill 的第一反应是"往 SKILL.md 里堆提示词"。这是错的起点。Skill 是一个目录而不是一个文件,它的真正力量来自三层渐进式披露(progressive disclosure)——上下文按需加载,而不是一次性灌满。
官方定义的目录骨架如下:
tech-debt-scanner/
├── SKILL.md # 必需:入口指令
├── references/ # 可选:按需加载的参考资料
│ └── severity.md # 严重度分级标准
├── scripts/ # 可选:被"执行"而非"阅读"的脚本
│ └── scan.sh
└── assets/ # 可选:模板、图标等输出素材
└── report-template.md
关键认知:Claude 在每个会话里只常驻所有 Skill 的 name + description(约占 100 tokens/个),这是"第一层";当某个 Skill 被触发时,SKILL.md 正文进入上下文,这是"第二层"(官方建议 < 500 行);scripts/ 与 references/ 是"第三层",只有在 Claude 主动读取或执行时才消耗 token,脚本的输出可以无限长而不挤占正文预算。
flowchart TB
subgraph L1["第一层:元数据 始终常驻 ~100 tokens"]
A["name: tech-debt-scanner"]
B["description: 扫描技术债标记…"]
end
subgraph L2["第二层:触发后加载 < 500 行"]
C["SKILL.md 正文<br/>指令 + 动态注入"]
end
subgraph L3["第三层:按需访问 无上限"]
D["scripts/scan.sh 执行"]
E["references/severity.md 阅读"]
F["assets/report-template.md 引用"]
end
A --> C
B --> C
C --> D
C --> E
C --> F
style L1 fill:#e8f5e9
style L2 fill:#fff8e1
style L3 fill:#fce4ec
把这个三层模型刻进脑子里,后面所有的设计取舍(为什么 description 要短、为什么大段参考要外置、为什么确定性逻辑要写成脚本)都源于它。
Claude Code 有四类 Skill 存放位置,位置决定了谁能用:
| 层级 | 路径 | 生效范围 |
|---|---|---|
| 个人级 | ~/.claude/skills/tech-debt-scanner/SKILL.md |
你的所有项目 |
| 项目级 | .claude/skills/tech-debt-scanner/SKILL.md |
仅当前项目(随仓库提交给团队) |
| 插件级 | <plugin>/skills/tech-debt-scanner/SKILL.md |
启用该插件的环境 |
| 企业级 | 通过 managed settings 下发 | 全组织 |
同名时优先级为:企业 > 个人 > 项目 > 内置。技术债扫描这类"强项目相关、需要随仓库走"的工具,我们放到项目级,这样团队成员 clone 仓库后即用。如果你只是想自己全项目复用,放个人级即可。
创建骨架(项目级):
mkdir -p .claude/skills/tech-debt-scanner/{scripts,references,assets}
SKILL.md 顶部是 YAML frontmatter,夹在两行 --- 之间。其中 description 字段是决定 Claude 是否调用该 Skill 的主要机制,所有"何时使用"的信息都必须放在这里,而不是正文。
技术债扫描 Skill 的初版 frontmatter:
---
name: tech-debt-scanner
description: 扫描代码库中的技术债标记(TODO/FIXME/HACK/XXX/@deprecated),按严重度归类并生成可追踪的技术债登记表。当用户想了解项目欠了多少技术债、盘点 TODO、排查遗留问题、做技术债清理规划,或提到"扫一下 TODO""有哪些 FIXME"时使用。
allowed-tools: Bash(bash *) Bash(grep *) Bash(git *)
paths:
- "**/*.py"
- "**/*.ts"
- "**/*.tsx"
- "**/*.js"
- "**/*.go"
- "**/*.java"
---
写 description 时有三个务必遵守的原则:
description + when_to_use 合并后在 Skill 列表里被截断到 1536 字符,且整个列表还要受"预算"约束(默认约为模型上下文窗口的 1%),越靠前的内容越容易被保留。paths 字段是一个常被忽略的利器:设置后,Claude 只有在编辑或讨论匹配这些 glob 的文件时才会自动加载该 Skill。对技术债扫描来说,它只关心源码文件,所以列出常见源码后缀,能避免在改文档、改配置时被无谓触发。
SKILL.md 正文是 Skill 被触发后进入上下文的"第二层"。技术债扫描的正文不需要长,核心是用 ! 反引号语法做动态上下文注入——在 Claude 读到 Skill 之前,先由 Claude Code 跑命令、把输出原地替换进提示词:
# 技术债扫描
## 当前仓库实况
下列数据在 Skill 触发时由 Claude Code 自动采集并内联,请基于真实数据而非猜测工作:
- 当前分支:!`git rev-parse --abbrev-ref HEAD`
- 待扫描源码文件数:!`git ls-files '*.py' '*.ts' '*.tsx' '*.js' '*.go' '*.java' | wc -l`
## 任务
1. 执行扫描脚本(无需重新发明扫描逻辑):
```bash
bash ${CLAUDE_SKILL_DIR}/scripts/scan.sh
```
2. 读取 `references/severity.md`,把脚本输出的每一类标记按 P0–P3 分级。
3. 用 `assets/report-template.md` 作为模板,生成 `TECH_DEBT.md`,写到仓库根目录。
4. 在报告开头用两三句话给出总体评估:债务规模、最该优先处理的 3 项、近期新增趋势。
这里有三个要点:
! 反引号是预处理,不是 Claude 自己执行的命令。Claude 只看到替换后的结果。多行命令要用 ```! 围栏而非内联形式。${CLAUDE_SKILL_DIR} 是官方字符串替换变量,会被替换成 Skill 自身目录的绝对路径,让你无论从哪个工作目录调用都能找到随包的脚本。其他常用变量还有 $ARGUMENTS、$0/$1(位置参数)、${CLAUDE_SESSION_ID}、${CLAUDE_EFFORT}。! 注入有安全隐患(在团队仓库里跑别人提交的 Skill),可以在 settings 里设 "disableSkillShellExecution": true,此时注入命令会被替换成一行策略提示而不执行。bundled 与 managed Skill 不受此设置影响。正文里反复出现的、可机械化的步骤,应当写成 scripts/ 下的脚本——这是 skill-creator 总结的核心规律:"如果几个测试用例都在独立地写类似的辅助脚本,那就把它固化进 scripts/,省得每次调用都重新发明轮子。"
scripts/scan.sh(扫描并按标记聚类):
#!/usr/bin/env bash
# 扫描技术债标记,输出 TSV:行号前缀\t标记类型\t内容
set -euo pipefail
ROOT="${1:-.}"
PATTERN='TODO|FIXME|HACK|XXX|@deprecated'
echo -e "file\tline\tmarker\ttext"
# 只扫 Git 跟踪的文件,避开 node_modules、构建产物
git -C "$ROOT" ls-files -z \
| grep -zE '\.(py|ts|tsx|js|go|java|rb|rs|c|cpp|h)$' \
| xargs -0 grep -rnIE "$PATTERN" "$ROOT" 2>/dev/null \
| sed -E 's/^([^:]+):([0-9]+):[^:]*('"$PATTERN"')[[:space:]:]*[[:space:]]*(.*)/\1\t\2\t\3\t\4/' \
| sort
references/severity.md(按需加载的分级标准,第三层):
# 技术债严重度分级
- **P0 阻断**:FIXME 涉及安全、数据丢失、生产崩溃;HACK 绕过鉴权或事务。
- **P1 高**:FIXME 涉及核心逻辑正确性;TODO 标注的未实现关键功能。
- **P2 中**:XXX 性能/可维护性隐患;@deprecated 仍在被新代码调用。
- **P3 低**:普通 TODO(文档、小重构、命名优化)。
判定优先看"影响面"再看"发生频率",单点高频标记可升一级。
assets/report-template.md(输出模板):
# 技术债登记表 · {{date}}
> 总体评估:{{summary}}
| 优先级 | 数量 | 代表文件 |
| --- | --- | --- |
| P0 | {{p0}} | {{p0_files}} |
| P1 | {{p1}} | {{p1_files}} |
| P2 | {{p2}} | {{p2_files}} |
| P3 | {{p3}} | {{p3_files}} |
## 建议优先处理
1. ...
为什么把分级标准外置到 references/?因为它是"长尾参考",每次只在生成报告时读一次,外置后不占 SKILL.md 正文预算,也方便团队单独维护这一份标准。
Claude Code 会监听 Skill 目录的文件变化,新增、编辑、删除都无需重启即在当前会话生效(仅限 SKILL.md 文本;若同时是插件目录,hooks/、agents/ 等变更需要 /reload-plugins)。这意味着你可以边改边测。
测试有两种路径,都要验证:
路径 A:直接斜杠调用
/tech-debt-scanner
这条最稳,能确认 Skill 本身能跑通。
路径 B:自然语言自动触发
我们这个项目欠了多少技术债?最近 TODO 多不多,列一下最该先还的
如果这条触发了你的 Skill,说明 description 写到位了。如果没触发,先问一句 当前有哪些可用的 Skill? 确认它出现在列表里;若出现却不触发,多半是 description 关键词没覆盖到你的措辞,或者问题太"轻"——Claude 只在它判断"靠自己处理不好"时才咨询 Skill,简单的一步式提问往往不触发。
预期结果:仓库根目录生成 TECH_DEBT.md,终端打印一段两三句话的总评 + P0–P3 分布表。
写完能跑,只是及格。Skill 的工程价值在于触发既不漏也不过激。三组工具按场景选用:
1. 控制谁能调用
| frontmatter | 你能调用 | Claude 自动调用 |
|---|---|---|
| 默认 | ✅ | ✅ |
disable-model-invocation: true |
✅ | ❌(仅手动) |
user-invocable: false |
❌(隐藏菜单) | ✅ |
技术债扫描希望 Claude 在合适时主动用,也允许你 /tech-debt-scanner 手动跑,所以保持默认即可。对比之下,/deploy、/commit 这类有副作用的,就该加 disable-model-invocation: true,免得 Claude 看"代码差不多了"就自作主张部署。
2. 收紧工具与执行范围
allowed-tools: Bash(grep *) Bash(git *):在该 Skill 激活期间,这些工具免二次确认。注意它是"授权"而非"限制",其他工具仍可调用。disallowed-tools:把不想让该 Skill 碰的工具整个移出可用池(下次发消息后清除)。无人值守循环里常用它屏蔽 AskUserQuestion。paths:前面用过的 glob 限定,只在编辑匹配文件时自动激活。3. 让它跑在子代理里
如果仓库很大、扫描耗时长,加 context: fork 让 Skill 在隔离的子代理里跑,不污染主对话上下文:
context: fork
agent: Explore
agent 可选内置的 Explore(只读、上下文最小)、Plan 或自定义 agent。注意 context: fork 只适合"有明确任务"的 Skill;纯约定参考型 Skill(如"API 命名规范")在子代理里拿不到可执行任务,会空手返回。
4. 描述级优化(进阶)
官方 skill-creator 提供一条 description 自动优化链路:生成 20 条"应触发/不应触发"的真实查询(应触发的要多变措辞、含文件路径等细节;不应触发的要用"近义但不该命中"的棘手负例),再用 run_loop.py 做 60% 训练 / 40% 留出的 5 轮迭代,按测试集得分(而非训练集)选出 best_description 回填 frontmatter。如果你的 Skill 要分发给很多人,这步值得做。
~/.claude/skills/。.claude/skills/ 到仓库,同事 clone 后首次接受"工作区信任"对话框即可用。务必在 README 里提醒:项目级 Skill 的 allowed-tools 在信任后才生效,review 别人仓库的 Skill 时要当心——一个 Skill 可以给自己授予很宽的工具权限。.claude-plugin/plugin.json,它就变成一个能捆绑 agent、hooks、MCP 的插件,用 plugin-name:skill-name 命名空间加载,不会与各层同名 Skill 冲突。排错速查:
/doctor 看描述是否被预算截断;太简单的提问本来就不会触发,把问题改"重"一点再试。disable-model-invocation: true 改纯手动。skillListingBudgetFraction(如 0.02)或环境变量 SLASH_COMMAND_TOOL_CHAR_BUDGET;或在 skillOverrides 里把低优先 Skill 设为 "name-only" 腾出预算。准备一个最小复现仓库:
mkdir demo-debt && cd demo-debt && git init -q
cat > app.py <<'EOF'
def login(user, pwd):
# FIXME 明文比对密码,上线前必须换成 bcrypt
return user.pwd == pwd
def cache_get(key):
# TODO 命中率统计还没接,先返回 None
return None
# HACK 跳过鉴权方便联调,记得删
def dev_bypass(): ...
EOF
git add -A && git commit -qm "demo with debt"
把前面八步的 tech-debt-scanner/ 目录建到 .claude/skills/ 下,给 scripts/scan.sh 加可执行权限:
chmod +x .claude/skills/tech-debt-scanner/scripts/scan.sh
启动 claude,输入:
这个项目技术债情况怎么样?帮我扫一遍并出个登记表
预期 TECH_DEBT.md 里 P0 命中那条 FIXME 明文密码、P0/P1 命中 HACK 鉴权绕过、P3 命中 TODO 命中率。这个闭环跑通,你就掌握了 Skill 从"零"到"可分发"的完整链路。
flowchart LR
M["1 明确意图<br/>扫描+归类+登记"] --> S["2 建目录骨架<br/>skills/scanner/{scripts,references,assets}"]
S --> F["3 写 frontmatter<br/>name+description+paths"]
F --> B["4 写正文+动态注入<br/>!`git ls-files`"]
B --> C["5 下沉脚本/参考<br/>scan.sh / severity.md"]
C --> T["6 热加载测试<br/>/slash 与自然语言双验"]
T --> O{"触发准确?"}
O -- "漏触发" --> F
O -- "过触发" --> F
O -- "准确" --> D["7 调优<br/>invocation/tools/fork"]
D --> SH["8 分发<br/>personal/project/plugin"]
style O fill:#fff8e1
Q1:! 反引号里的命令没执行,原样出现在回复里。
多半是 ! 紧跟在别的字符后面(如 KEY=!cmd)。内联形式只在!出现在行首或紧跟空白时才被识别。多行命令改用 ``! 围栏。
Q2:${CLAUDE_SKILL_DIR} 没被替换。
确认你写的是 ${CLAUDE_SKILL_DIR}(带 ${}),它指向 SKILL.md 所在目录;插件 Skill 指向插件内该 Skill 子目录而非插件根。
Q3:Skill 跑一次后后面就不"听话"了。
Skill 内容作为单条消息进入对话后会常驻,Claude Code 不会每轮重读文件。若开了自动压缩,会按"最近优先 + 每 Skill 前 5000 tokens、合计 25000 tokens 预算"重新挂载,老的可能被丢。压缩后若发现失效,重新 /tech-debt-scanner 一次即可恢复全文。
Q4:脚本在 macOS 上 grep 报错。
BSD grep 不支持 GNU 的 -z/-P。脚本里用了 POSIX 友好的写法,若仍遇问题,可 brew install grep 后用 ggrep,或在团队里统一用 Docker 跑扫描。
skill-creator 源 Skill:https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md —— 官方"造 Skill 的 Skill",含描述优化链路与评测方法。references/severity.md 换成团队自己的代码规范,本教程即变成"用 Skill 沉淀团队规范"的范式教学。[!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 等场景全覆盖。
