安装方式
命令行安装
在项目根目录执行以下命令,完成 Skill 安装。
npx bzskills add anthropics/skills --skill skill-creator 创建新技能,修改和改进现有技能,并衡量技能表现。当用户希望从头创建技能、编辑或优化现有技能、运行评估来测试技能、通过方差分析对技能表现进行基准测试,或优化技能描述以提高触发准确性时使用。
192.7k
下载量
命令行安装
在项目根目录执行以下命令,完成 Skill 安装。
npx bzskills add anthropics/skills --skill skill-creator name: skill-creator
description: 创建新技能,修改和改进现有技能,并衡量技能表现。当用户希望从头创建技能、编辑或优化现有技能、运行评估来测试技能、通过方差分析对技能表现进行基准测试,或优化技能描述以提高触发准确性时使用。一个用于创建新技能并对其进行迭代改进的技能。
从宏观角度来看,创建技能的过程如下:
eval-viewer/generate_review.py 脚本向用户展示结果供其查看,并让他们查看定量指标使用此技能时,你的工作是确定用户处于该流程的哪个阶段,然后介入并帮助他们推进这些阶段。例如,用户可能会说“我想为 X 创建一个技能”。你可以帮助缩小他们的意图,编写草案,编写测试用例,确定他们想要如何评估,运行所有提示,然后重复。
另一方面,用户可能已经有了技能草案。在这种情况下,你可以直接进入循环的评估/迭代部分。
当然,你应该始终灵活处理,如果用户说“我不需要运行一堆评估,就跟我一起感受一下”,你也可以这样做。
技能完成后(但顺序同样灵活),你还可以运行技能描述改进器(我们为此有单独的脚本),以优化技能的触发。
明白了吗?很好。
技能创建者很可能会被代码术语熟悉程度各异的人群使用。如果你还没听说过(但怎么可能呢,这最近才开始流行起来),现在有一个趋势,Claude 的强大功能正在激励水管工打开他们的终端,父母和祖父母谷歌搜索“如何安装 npm”。另一方面,大多数用户可能对计算机相当熟悉。
因此,请关注上下文线索,以了解如何措辞!在默认情况下,给你一些参考:
如果不确定,可以简短解释术语;如果不确定用户是否理解,可以随意用简短定义澄清术语。
---
首先了解用户的意图。当前对话可能已经包含用户想要捕获的工作流(例如,他们说“把它变成一项技能”)。如果是这样,首先从对话历史中提取答案——使用的工具、步骤顺序、用户所做的更正、观察到的输入/输出格式。用户可能需要填补空白,并且应在继续下一步之前确认。
主动询问有关边缘情况、输入/输出格式、示例文件、成功标准和依赖项的问题。等到这一部分确定后再编写测试提示。
检查可用的 MCP——如果对研究有用(搜索文档、查找类似技能、查找最佳实践),则通过子代理(如果可用)并行研究,否则内联进行。带着上下文做好准备,以减少用户的负担。
根据用户访谈,填写以下组件:
#### 技能的构成
skill-name/
├── SKILL.md (必需)
│ ├── YAML 前置元数据(name、description 必需)
│ └── Markdown 指令
└── 捆绑资源(可选)
├── scripts/ - 用于确定性/重复性任务的可执行代码
├── references/ - 根据需要加载到上下文中的文档
└── assets/ - 输出中使用的文件(模板、图标、字体)
#### 渐进式披露
技能使用三级加载系统:
这些字数是近似值,如果需要,可以随意写得更长。
关键模式:
领域组织:当技能支持多个领域/框架时,按变体组织:
cloud-deploy/
├── SKILL.md(工作流 + 选择)
└── references/
├── aws.md
├── gcp.md
└── azure.md
Claude 只读取相关的参考文件。
#### 无意外原则
这不言而喻,但技能不得包含恶意软件、利用代码或任何可能危及系统安全的内容。如果描述了意图,技能的内容不应让用户感到意外。不要配合创建误导性技能或旨在促进未经授权访问、数据泄露或其他恶意活动的技能。像“角色扮演 XYZ”之类的是可以的。
#### 编写模式
在指令中优先使用祈使句。
定义输出格式 - 可以这样做:
## 报告结构
始终使用此确切模板:
# [标题]
## 执行摘要
## 主要发现
## 建议
示例模式 - 包含示例很有用。可以像这样格式化(但如果示例中有“输入”和“输出”,你可能希望稍微偏离):
## 提交消息格式
**示例 1:**
输入:添加了使用 JWT 令牌的用户认证
输出:feat(auth):实现基于 JWT 的认证
尝试向模型解释为什么事情很重要,而不是使用强硬苛刻的“必须”。使用心智理论,并尝试使技能具有通用性,而不是过于狭窄地针对特定示例。首先编写草稿,然后以全新的眼光审视它并改进它。
编写技能草稿后,提出 2-3 个真实的测试提示——真正的用户会实际说的那种。与用户分享:[你不必使用完全相同的语言]“这里有几个我想尝试的测试用例。它们看起来对吗,还是你想添加更多?”然后运行它们。
将测试用例保存到 evals/evals.json。还不要编写断言——只写提示。在运行进行的过程中,你将在下一步中草拟断言。
{
"skill_name": "example-skill",
"evals": [
{
"id": 1,
"prompt": "用户的任务提示",
"expected_output": "预期结果的描述",
"files": []
}
]
}
有关完整模式(包括 assertions 字段,你将在稍后添加),请参阅 references/schemas.md。
本节是一个连续的序列——不要中途停止。不要使用 /skill-test 或任何其他测试技能。
将结果放在与技能目录同级的 <skill-name>-workspace/ 中。在工作区内,按迭代组织结果(iteration-1/、iteration-2/ 等),在每个迭代中,每个测试用例都有一个目录(eval-0/、eval-1/ 等)。不要预先创建所有这些——只需在过程中创建目录即可。
对于每个测试用例,在同一个回合中生成两个子代理——一个带技能,一个不带。这很重要:不要先生成带技能的运行,然后再回来做基线。一次性启动所有事情,以便它们大致在同一时间完成。
带技能运行:
执行此任务:
- 技能路径:<path-to-skill>
- 任务:<eval prompt>
- 输入文件:<eval files if any, or "none">
- 将输出保存到:<workspace>/iteration-<N>/eval-<ID>/with_skill/outputs/
- 要保存的输出:<用户关心的内容——例如,“.docx 文件”、“最终的 CSV”>
基线运行(相同的提示,但基线取决于上下文):
without_skill/outputs/。cp -r <skill-path> <workspace>/skill-snapshot/),然后将基线子代理指向快照。保存到 old_skill/outputs/。为每个测试用例编写一个 eval_metadata.json(断言现在可以为空)。根据测试内容为每个评估提供一个描述性名称——不仅仅是“eval-0”。目录也使用此名称。如果此迭代使用新的或修改过的评估提示,请为每个新的评估目录创建这些文件——不要假设它们从前面的迭代继承过来。
{
"eval_id": 0,
"eval_name": "descriptive-name-here",
"prompt": "用户的任务提示",
"assertions": []
}
不要只是等待运行完成——你可以有效地利用这段时间。为每个测试用例草拟定量的断言并向用户解释。如果断言已存在于 evals/evals.json 中,则审查它们并解释它们检查什么。
好的断言是客观上可验证的,并且具有描述性名称——它们应该在基准查看器中清晰可读,以便浏览结果的人能立即理解每个断言检查的内容。主观技能(写作风格、设计质量)更适合定性评估——不要将断言强加给需要人类判断的事情。
草拟后,更新 eval_metadata.json 文件和 evals/evals.json 中的断言。同时向用户解释他们将在查看器中看到什么——包括定性的输出和定量的基准。
当每个子代理任务完成时,你会收到一个包含 total_tokens 和 duration_ms 的通知。立即将此数据保存到运行目录中的 timing.json 中:
{
"total_tokens": 84852,
"duration_ms": 23332,
"total_duration_seconds": 23.3
}
这是捕获此数据的唯一机会——它通过任务通知传来,不会在其他地方持久化。在收到通知时逐个处理,而不是尝试批量处理。
一旦所有运行完成:
agents/grader.md,并根据输出评估每个断言。将结果保存到每个运行目录的 grading.json 中。grading.json 的 expectations 数组必须使用字段 text、passed 和 evidence(而不是 name/met/details 或其他变体)——查看器依赖这些确切的字段名。对于可以通过编程方式检查的断言,请编写并运行脚本,而不是目测——脚本更快、更可靠,并且可以在多次迭代中重复使用。 python -m scripts.aggregate_benchmark <workspace>/iteration-N --skill-name <name>
这会生成 benchmark.json 和 benchmark.md,其中包含每次配置的通过率、时间和令牌数,以及平均值 ± 标准差和差值。将每个带技能的版本放在其基线对应项之前。
agents/analyzer.md(“分析基准结果”部分)——比如无论技能如何总是通过的断言(无区分度)、高方差的评估(可能不稳定)以及时间/令牌权衡。 nohup python <skill-creator-path>/eval-viewer/generate_review.py \
<workspace>/iteration-N \
--skill-name "my-skill" \
--benchmark <workspace>/iteration-N/benchmark.json \
> /dev/null 2>&1 &
VIEWER_PID=$!
对于第 2 次及以后的迭代,还要传递 --previous-workspace <workspace>/iteration-<N-1>。
Cowork / 无头环境: 如果 webbrowser.open() 不可用或环境没有显示器,请使用 --static <output_path> 写入独立的 HTML 文件,而不是启动服务器。当用户点击“提交所有评论”时,反馈将作为 feedback.json 文件下载。下载后,将 feedback.json 复制到工作区目录中,供下一次迭代使用。
注意:请使用 generate_review.py 创建查看器;无需编写自定义 HTML。
“输出”标签一次显示一个测试用例:
“基准”标签显示统计摘要:每次配置的通过率、计时和令牌使用情况,以及每个评估的细分和分析师观察。
导航通过上一个/下一个按钮或箭头键完成。完成后,他们点击“提交所有评论”,将所有反馈保存到 feedback.json。
当用户告诉您他们完成后,读取 feedback.json:
{
"reviews": [
{"run_id": "eval-0-with_skill", "feedback": "图表缺少轴标签", "timestamp": "..."},
{"run_id": "eval-1-with_skill", "feedback": "", "timestamp": "..."},
{"run_id": "eval-2-with_skill", "feedback": "完美,喜欢这个", "timestamp": "..."}
],
"status": "complete"
}
空反馈意味着用户认为没问题。将你的改进重点放在用户有具体投诉的测试用例上。
完成后终止查看器服务器:
kill $VIEWER_PID 2>/dev/null
---
这是循环的核心。你已经运行了测试用例,用户已经审查了结果,现在你需要根据他们的反馈来改进技能。
create_docx.py 或 build_chart.py,这是一个强烈的信号,表明技能应该捆绑该脚本。编写一次,放入 scripts/,并告诉技能使用它。这可以节省每次未来调用的重复发明轮子的时间。这个任务非常重要(我们正试图创造每年数十亿美元的经济价值!),你的思考时间不是瓶颈;慢慢来,认真思考。我建议写一个修订草案,然后重新审视并进行改进。真正尽最大努力进入用户的头脑,理解他们想要和需要什么。
改进技能后:
iteration-<N+1>/ 目录中,包括基线运行。如果你在创建新技能,基线始终是 without_skill(无技能)——这在各次迭代中保持不变。如果你在改进现有技能,请根据你的判断决定什么作为基线:用户最初带来的原始版本,还是前一次迭代。--previous-workspace 指向之前的迭代来启动查看器持续进行直到:
---
对于需要更严格比较两个技能版本的情况(例如,用户问“新版本真的更好吗?”),有一个盲比较系统。有关详细信息,请阅读 agents/comparator.md 和 agents/analyzer.md。基本思路是:将两个输出交给一个独立的代理,不告诉它哪个是哪个,让它判断质量。然后分析赢家获胜的原因。
这是可选的,需要子代理,大多数用户不需要。人类审查循环通常就足够了。
---
SKILL.md 前置元数据中的描述字段是决定 Claude 是否调用技能的主要机制。在创建或改进技能后,主动提供优化描述以提高触发准确性。
创建 20 个评估查询——混合应触发和不应触发的。保存为 JSON:
[
{"query": "用户提示", "should_trigger": true},
{"query": "另一个提示", "should_trigger": false}
]
查询必须真实,并且是 Claude Code 或 Claude.ai 用户会实际输入的内容。不是抽象的请求,而是具体、详细且有足够信息量的请求。例如,文件路径、关于用户工作或情况的个人背景、列名和值、公司名称、URL。一点背景故事。有些可能是小写或包含缩写、拼写错误或口语化表达。使用不同长度的混合,并专注于边缘情况而不是让它们界限分明(用户将有机会签署它们)。
差的:"格式化这些数据"、"从 PDF 中提取文本"、"创建一个图表"
好的:"ok 我老板刚给我发了这个 xlsx 文件(在我的下载文件夹里,文件名大概是 'Q4 sales final FINAL v2.xlsx'),她想让我添加一列显示毛利率百分比。我认为收入在 C 列,成本在 D 列"
对于应触发的查询(8-10 个),考虑覆盖范围。你需要同一意图的不同措辞——一些正式,一些随意。包括用户没有明确命名技能或文件类型但明显需要它的情况。加入一些不常见的用例以及此技能与另一技能竞争但应胜出的情况。
对于不应触发的查询(8-10 个),最有价值的是那些接近命中但未命中的——与技能共享关键词或概念但实际上需要不同内容的查询。考虑相邻领域、模糊措辞(在这种情况下朴素的关键词匹配会触发但实际上不应触发),以及查询涉及技能所做的某事但在另一个工具更合适的上下文中的情况。
要避免的关键点:不要使不应触发的查询明显无关紧要。将“编写一个斐波那契函数”作为 PDF 技能的负面测试太简单了——它测试不出任何东西。负面用例应该真正棘手。
使用 HTML 模板向用户展示评估集以供审查:
assets/eval_review.html 读取模板__EVAL_DATA_PLACEHOLDER__ → 评估项的 JSON 数组(不要用引号括起来——它是一个 JS 变量赋值)__SKILL_NAME_PLACEHOLDER__ → 技能名称__SKILL_DESCRIPTION_PLACEHOLDER__ → 技能的当前描述/tmp/eval_review_<skill-name>.html)并打开:open /tmp/eval_review_<skill-name>.html~/Downloads/eval_set.json——如果存在多个版本(例如,eval_set (1).json),请检查 Downloads 文件夹以获取最新版本这一步很重要——差的评估查询会导致差的描述。
告诉用户:“这需要一些时间——我将在后台运行优化循环并定期检查。”
将评估集保存到工作区,然后在后台运行:
python -m scripts.run_loop \
--eval-set <path-to-trigger-eval.json> \
--skill-path <path-to-skill> \
--model <model-id-powering-this-session> \
--max-iterations 5 \
--verbose
使用系统提示中的模型 ID(为当前会话提供动力的那个),以便触发测试与用户实际体验的相匹配。
在它运行时,定期跟踪输出,向用户更新它在哪个迭代以及分数看起来如何。
这会自动处理完整的优化循环。它将评估集分为 60% 训练和 40% 保留测试,评估当前描述(对每个查询运行 3 次以获得可靠的触发率),然后调用 Claude 根据失败情况提出改进建议。它会在训练和测试集上重新评估每个新描述,最多迭代 5 次。完成后,它会在浏览器中打开一个 HTML 报告,显示每次迭代的结果,并返回包含 best_description 的 JSON——根据测试分数(而不是训练分数)选择,以避免过拟合。
理解触发机制有助于设计更好的评估查询。技能以其名称 + 描述出现在 Claude 的 available_skills 列表中,Claude 根据该描述决定是否查阅技能。需要知道的重要一点是,Claude 只对它自己不容易处理的任务查阅技能——简单的、一步到位的查询,如“读取这个 PDF”,即使描述完美匹配也可能不会触发技能,因为 Claude 可以使用基本工具直接处理它们。复杂、多步骤或专业化的查询在描述匹配时能可靠地触发技能。
这意味着你的评估查询应该有足够的内容,让 Claude 会真正从查阅技能中受益。像“读取文件 X”这样简单的查询是糟糕的测试用例——无论描述质量如何,它们都不会触发技能。
从 JSON 输出中获取 best_description,并更新技能的 SKILL.md 前置元数据。向用户展示前后对比,并报告分数。
---
present_files 工具可用时)检查你是否可以使用 present_files 工具。如果不可用,跳过此步骤。如果可以,打包技能并将 .skill 文件展示给用户:
python -m scripts.package_skill <path/to/skill-folder>
打包后,指导用户找到生成的 .skill 文件路径,以便他们安装。
---
在 Claude.ai 中,核心工作流是相同的(草稿 → 测试 → 审查 → 改进 → 重复),但由于 Claude.ai 没有子代理,一些机制需要改变。以下需要调整的内容:
运行测试用例:没有子代理意味着无法并行执行。对于每个测试用例,读取技能的 SKILL.md,然后按照其指令自己完成测试提示。一个一个地做。这不如独立的子代理严格(你编写了技能,并且也在运行它,所以你有完整的上下文),但这是一个有用的健全性检查——而人工审查步骤弥补了这一点。跳过基线运行——只需按照请求使用技能完成任务即可。
审查结果:如果你无法打开浏览器(例如,Claude.ai 的虚拟机没有显示器,或者你在远程服务器上),请完全跳过浏览器查看器。相反,直接在对话中呈现结果。对于每个测试用例,显示提示和输出。如果输出是用户需要查看的文件(如 .docx 或 .xlsx),将其保存到文件系统并告诉他们文件位置,以便他们下载和检查。内联征求反馈:“看起来怎么样?有什么需要修改的吗?”
基准测试:跳过定量基准测试——它依赖于基线的比较,而没有子代理是没有意义的。专注于来自用户的定性反馈。
迭代循环:与之前相同——改进技能,重新运行测试用例,征求反馈——只是中间没有浏览器查看器。如果你有文件系统,你仍然可以将结果组织到迭代目录中。
描述优化:此部分需要 claude CLI 工具(特别是 claude -p),该工具仅在 Claude Code 中可用。如果你在 Claude.ai 上,请跳过。
盲比较:需要子代理。跳过。
打包:package_skill.py 脚本可以在任何有 Python 和文件系统的地方工作。在 Claude.ai 上,你可以运行它,用户然后可以下载生成的 .skill 文件。
更新现有技能:用户可能要求你更新现有技能,而不是创建新技能。在这种情况下:
name 前置元数据字段——原样使用它们。例如,如果安装的技能是 research-helper,则输出 research-helper.skill(而不是 research-helper-v2)。/tmp/skill-name/,在那里编辑,然后从副本打包。/tmp/ 中暂存,然后复制到输出目录——直接写入可能因权限而失败。---
如果你在 Cowork 中,需要了解的主要内容是:
--static <output_path> 写入独立的 HTML 文件,而不是启动服务器。然后提供一个用户可以点击的链接,以便在浏览器中打开 HTML。generate_review.py(而不是编写你自己的定制 html 代码)。事先抱歉,但我要用全大写:在你亲自评估输入之前,先生成评估查看器。你想尽快把它们展示给人工!feedback.json 作为文件下载。然后你可以从那里读取(你可能需要先请求访问权限)。package_skill.py 只需要 Python 和文件系统。run_loop.py / run_eval.py)在 Cowork 中应该可以正常工作,因为它通过子进程使用 claude -p,而不是浏览器,但请将其保留到你完全完成技能制作并且用户同意技能状态良好时再进行。---
agents/ 目录包含专门子代理的指令。当你需要生成相关子代理时读取它们。
agents/grader.md —— 如何根据输出评估断言agents/comparator.md —— 如何在两个输出之间进行盲 A/B 比较agents/analyzer.md —— 如何分析一个版本击败另一个版本的原因references/ 目录有额外的文档:
references/schemas.md —— evals.json、grading.json 等的 JSON 结构---
此处再次强调核心循环:
eval-viewer/generate_review.py 以帮助用户审查它们请将步骤添加到你的 TodoList 中(如果你有这样的东西),以确保你不会忘记。如果你在 Cowork 中,请特别在你的 TodoList 中添加“创建 evals JSON 并运行 eval-viewer/generate_review.py 以便人工可以审查测试用例”,以确保它完成。
祝你好运!