Skill Simplifier
写 agent-team 的时候我反复强调过一条纪律:每段提示词只存在于唯一一个地方。重复就是漂移源——上游措辞变了而下游抄了一份旧版本时,下一次 coordination 就出 bug。但这条纪律没法靠”写的时候多注意点”维持,Claude 自己写 skill 和 CLAUDE.md 时倾向于把它觉得重要的事一股脑全写上,分不清这些事是不是已经被系统提示词、Tool Description、其他 skill 或更上层的 CLAUDE.md 提供了。于是我把这条纪律做成了 skill-simplifier:审一个目标文档,列出每一处与上游重复的内容,自动删那些”无论如何都该删”的,剩下”两侧都由用户拥有”的让用户决定
它解决什么问题
Claude 写 SKILL.md 和 CLAUDE.md 有一种 kitchen-sink 倾向:只要觉得”这个规则很重要”就写进去,不管这条规则是不是已经由更上游的知识源提供。最常见的几类冤枉重复:
- SKILL.md 里写”用 Edit 工具不要用 sed”——这是系统提示词里已经有的
- SKILL.md 里详细解释
TeamCreate的参数——这是 tool description 已经返回的 - CLAUDE.md(项目级)写”使用中文回答”——这是用户全局 CLAUDE.md 已经有的
- skill 的
references/foo.md里抄一段superpowers:test-driven-development的 RED/GREEN/REFACTOR 流程——这是另一个 skill 激活后直接提供的
每条单独看都不冒犯,但堆起来就两件坏事:占 context、稀释目标文档真正独特的价值;上游变了之后副本悄悄过时。第二件更要命,因为它是隐式的:你以为 skill 还在按最新规则跑,实际上它依据的是某条 tool description 半年前的措辞
核心判定标准
判定一段内容是不是冗余的方法很朴素:删掉它,Claude 的行为会不会变? 如果不会,那它就是冗余的,因为同样的约束已经在上游某处提供
两个要点:
- 语义而非字面:措辞不同也可能是重复。“使用 Read 而非 cat 读文件”和”避免用 shell 拼接读取文件内容,应当调用专用工具” 是同一条规则的两种说法
- 字面相同也可能不是重复:如果目标补上了上游缺失的”为什么 / 例子 / 取舍”,那它在做独立的工作。例如系统提示词只说”破坏性操作前先确认”,而某个 CLAUDE.md 补一句”过去 force push 删过 main 历史,所以这条规则在我们这特别严”——保留有上下文的那一侧
四类上游知识源
每一处重复都会归到下面四类之一。skill-simplifier 在 Stage 1 按顺序排查,分类要做准,因为 Stage 4 的处理规则按类不同
1. 系统提示词(隐式上游)
这是最容易漏的一类,因为 Claude 没法 Read 系统提示词,它就在 context 里。需要逐项扫的重灾区:
- 用专用 tool 而非
cat/echo/sed - 独立的 tool 调用并行执行
file_path:line_number引用约定- git commit / PR 工作流
- sandbox 与安全规则
- 破坏性操作先确认
只要目标把这些规则之一重新陈述了一遍,就是在重复系统提示词
2. Tool Description
每个 tool 自带一段 description。这里有个反直觉点:
- 内置 tool(Read、Edit、Bash、Skill 等)的 description 在 context 里,直接看
- Deferred tool(
TeamCreate/SendMessage/WebFetch/Monitor等)的 schema 不在 context 里——只在<system-reminder>块里以名字出现。要查它们的 description 必须先用ToolSearch配合select:Name1,Name2,...把 schema 拉进来
agent-team 这个 skill 反复出现 “the descriptions returned are the authoritative reference” 这句话的原因正是为此:与其在 SKILL.md 里抄一份 TeamCreate 参数表(必然过时),不如强制 agent 每次激活时去拉 live schema
3. 其他 Skill
Available Skills 列表在 <system-reminder> 里。扫一遍,挑出名字或一句话描述和目标领域重叠的 skill。读其他 skill 的内容必须用 Skill(name) 调用它,而不是用 Read 去读 SKILL.md 文件——plugin cache 的路径不稳定(带版本号、可能因 plugin 更新而变),靠 Read 拼路径是脆弱的
如果目标重述了一条”另一个 skill 一旦激活就会提供”的指令,就是在重复 Skill
4. 其他 CLAUDE.md
CLAUDE.md 是 cascade 的,上游链按目标类型不同:
- CLAUDE.md 目标:从
~/.claude/CLAUDE.md一路读到目标父目录的每一个 CLAUDE.md - Skill 目标:
~/.claude/CLAUDE.md加上 skill 预期将运行其中的项目根 CLAUDE.md
如果目标重述了一条更上游 CLAUDE.md 已经提供的规则,就是在重复 CLAUDE.md
报告先于改动:Stage 4 闸门
skill-simplifier 最重要的设计是强制在改动前先输出完整报告,等用户对部分条目做决定再执行 Edit。这条约束在 skill 里直接列为红线:“不要在用户给出 Zone B 和 Zone C 决定之前进入 Stage 5”
理由:删除是低成本的操作,但误删(false-positive)是隐性回退——一段被错删的情境化指引不会立刻报错,下一次 Claude 在边界 case 上失去判断依据时才暴露。让用户先看完所有命中条目再做决定,比一次性 batch 删完更安全
报告分两到三区:
Zone A — 自动删
上游是系统提示词或 Tool Description。这两个上游用户没法编辑,唯一可动的杠杆就是目标侧。所以 Zone A 默认全删,列出来只是方便用户做合理性核查、对具体某条提出反对
Zone B — 用户决定
上游是其他 Skill 或其他 CLAUDE.md。两侧都由用户拥有,所以三选一:删目标侧、删上游侧、或两侧都留并加显式的交叉引用
明显成组的条目可以合并成一个决定。但不要把上游来源不同的条目合并成同一条——用户可能想对不同上游做不同选择(比如:愿意删项目 CLAUDE.md 的副本,但全局 CLAUDE.md 的那条保留)
Zone C — 内部分层(仅 Skill 目标)
skill 的 SKILL.md 总是在激活时加载;references/*.md 按需加载。内容在两层都出现就破坏了 progressive disclosure。用 Zone B 同款格式让用户选,因为”哪一层拥有这段内容”是设计决策——是把它放进常驻 context 还是按需加载
几条不能碰的红线
触发内容神圣不可动
Skill 的 description: frontmatter 是它被 trigger 的入口,CLAUDE.md 里的”看到 X 时做 Y”短语是它被应用的入口。即便它们和某条上游措辞重叠,也要保留——删掉就破坏了激活路径,整个文档变成沉默资源
不要把临时 query 结果固化进去
通过 ToolSearch / WebSearch / Read 一次性获取的 schema、版本号、API 字段名等等,绝不能抄进 SKILL.md 或 CLAUDE.md 当”方便的 inline 参考”。上游会变,inline 副本必然过时。让目标在每次调用时重新获取——这正是 deferred tool schema 不进 skill 的同一条原则
保守删除
拿不准时保留目标内容,加一句 “see X” 的指针即可。多一句话的代价很小;丢掉用户依赖的情境化指引的代价大。漏删在下一次审查时能补救;误删则悄悄回退 Claude 的行为
具体胜过泛化
如果一份 skill / CLAUDE.md 重述了系统提示词的泛化规则、但补上了具体例子、取舍或为什么,它是在做真实工作。这种张力出现时保留情境化的那一版,只裁掉冗余的泛化前言
一个工作流上的小细节
skill 在 Stage 2 会激活辅助 skill,但按目标类型分叉:
- 目标是 Skill → 激活
superpowers:writing-skills+skill-creator - 目标是 CLAUDE.md → 激活
claude-md-management:claude-md-improver
这两组辅助 skill 提供”好的 skill / 好的 CLAUDE.md 长什么样”的参考,但它们本身不是 skill-simplifier 的替代品——它们关心结构和清晰度,skill-simplifier 单点关心去重。所以辅助 skill 是激活,不是委派
安装
/plugin marketplace add Fomalhaut647/plugins/plugin install skill-simplifier@fomalhaut647-plugins@ 前的 skill-simplifier 是 plugin name,@ 后的 fomalhaut647-plugins 是 marketplace name
怎么用
最直接的触发短语:“simplify this skill”、“review this CLAUDE.md”、“审查 / 精简 / 去重 / 瘦身 skill”、“是不是有重复”。其实更常见的场景是用户自己写完 skill 后感觉冗长 / 抱怨”这段我好像在别处写过”——这时候哪怕用户没明说 “simplify”,也应该优先调用本 skill。这正是它存在的意义
跑一次完整流程的样子:
- 问用户目标是哪个 skill 目录或 CLAUDE.md 文件
- 枚举四类上游知识源、读完整目标
- 输出两到三区报告(这里停下来)
- 用户对 Zone B / Zone C 给出决定
Edit按决定逐条删除或加交叉引用
每次调用只处理一个目标。如果用户有多个 skill 要审,每个文件各跑一次工作流——上游枚举可能因目标而异,混在一起处理会漏判
后记
skill-simplifier 自己是个反讽:它的 SKILL.md 写得相当瘦,没有重复的”好 skill 长什么样”教学(那是 superpowers:writing-skills 的事)、没有抄 Skill tool description(那是 tool 自带的)、没有解释什么是 cascade(那是 CLAUDE.md 自己的概念)。它只做一件事——审目标里有没有上游已经提供的内容——所以它自己也必须严格遵守这条纪律
仓库:https://github.com/Fomalhaut647/plugins/tree/main/plugins/skill-simplifier,欢迎试用、提 issue
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!