mcpField
T
template-authoring

template-authoring

github.com/dotnet开发5.8k3.4k 次安装1 天前更新
代码仓库

关于 template-authoring

帮助开发者从现有项目创建并验证自定义 dotnet new 模板的技能,也可用于编写模板配置和 NuGet 打包。它强调保留源项目的构建设置与包元数据,并要求创建的模板经过本地实例化和构建验证。

主要功能

  1. 01从现有项目生成模板配置
  2. 02验证 template.json
  3. 03保留项目与包设置
  4. 04配置参数、条件内容和后续操作
  5. 05安装并构建生成的项目

适用场景

  1. 01将 .csproj 项目制作成可复用模板
  2. 02发布前检查模板配置
  3. 03制作 NuGet 模板包

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dotnet/skills --skill template-authoring

安装后在 Claude Code 中输入/template-authoring确认已加载。

详细介绍

模板创作

此技能可帮助 Agent 创建并验证自定义 dotnet new 模板。它会引导用户从现有项目引导创建模板,并在发布前检查 template.json 文件的创作问题。

适用场景

  • 用户想从现有的 .csproj 创建可复用模板
  • 用户想在发布前验证正在编写的 template.json
  • 用户从头开始设置 .template.config/template.json
  • 用户想将模板打包后分发到 NuGet

不适用场景

  • 用户想查找或使用现有模板——转至 template-discovery 或 template-instantiation
  • 用户遇到与模板创作无关的 MSBuild 问题——转至 dotnet-msbuild 插件

输入

输入必需性描述
源项目路径创建时需要要用作模板源的 .csproj 路径
template.json 路径验证时需要要验证的现有 template.json 路径
模板名称创建时需要模板的易读名称
短名称建议提供用于 dotnet new <shortname> 的短名称

工作流

会影响答案的规则

严格使用以下结构;不要虚构其他模板功能中的字段。

交付所请求的内容。 当用户说“展示”“编写”或“给我内容”时,即使你也已将其写入磁盘,也要在最终回复中提供完整的 JSON/XML。绝不要用编辑此技能的 SKILL.md 或插件文档来代替编写用户的模板。只有在用户请求修改文件,且目标模板/项目已存在时,才创建或修改模板文件。

需求正确结构绝不可使用
.csproj 中的条件 XML使用 XML 注释(例如 和)包围完整元素单独的 #if 行,这会导致 XML 无效
还原生成的项目使用还原操作 210D431B-A78B-4D2F-B762-4ED3E3EA9025;使用 primaryOutputs,或使用包含源模板路径/通配符的 args.files在还原操作中使用 executable 等运行脚本字段
限定为 SDK 宿主使用 host 约束,其 args 是包含 { "hostname": "dotnetcli" } 的数组;其可选的 version 用于限制宿主/CLI 版本当需求明确是限制当前 SDK 版本时使用宿主 version,使用无效的宿主 ID dotnet-cli,或使用无关的 pattern / value 字段
限制当前 SDK 版本使用 sdk-version 约束,并在 args 中填写 NuGet 版本/范围字符串除非模板确实需要,否则使用特定于机器的精确补丁版本
保留 CPM让生成的 PackageReference 项不指定版本,并在模板可独立使用时一并打包所属的 Directory.Packages.props添加内联 Version 属性
打包模板使用包含 <PackageType>Template</PackageType> 的打包项目,并将模板内容打包到 content/ 下只描述目录结构,却不展示用户要求的项目文件
步骤 1:从现有项目创建模板

分析源 .csproj,并创建 .template.config/template.json:

  1. 默认将源项目复制到专用的模板源目录中,并保留原始项目不变。只有当用户明确要求采用该布局时,才在原位置修改项目。
  2. 在模板源目录中创建 .template.config。
  3. 生成 template.json,包含 identity(反向 DNS 格式)、name、shortName、sourceName(用于替换的项目名称)、classifications 和 tags。
  4. 保留源项目中的以下内容——通用的 dotnet new 模板经常会在这些方面出错,因此请逐项确认它们均从原始 .csproj 沿用:
    1. SDK 类型 — Microsoft.NET.Sdk、Microsoft.NET.Sdk.Web、Microsoft.NET.Sdk.Worker 等。
    2. 分析器/包引用元数据 — PrivateAssets、IncludeAssets、ExcludeAssets
    3. OutputType 和其他关键属性 — TreatWarningsAsErrors、Nullable、LangVersion
    4. 参与 CPM — 存在 Directory.Packages.props 时,不使用内联 Version 属性
    5. 自定义构建属性/目标和 Directory.Build.props 约定
    6. 仓库约定 — 文件夹布局、命名、global.json SDK 固定版本

最小示例:

{
  "$schema": "http://json.schemastore.org/template",
  "author": "MyOrg",
  "classifications": ["Library"],
  "identity": "MyOrg.Templates.MyLib",
  "name": "My Library Template",
  "shortName": "mylib",
  "sourceName": "MyLib",
  "tags": { "language": "C#", "type": "project" }
}

必需输出——不要只提供最简存根。 为实际源项目编写完整的 .template.config/template.json,然后简短确认已保留约定,让用户知道没有内容被悄悄遗漏。沿用这些内容正是此技能的全部价值;通用的 dotnet new 模板若丢失这些内容,编写模板还不如手写存根。

源 .csproj 设置是否沿用?方式
SDK(Microsoft.NET.Sdk.*)✅模板内容中的 .csproj 使用相同 SDK
TreatWarningsAsErrors / Nullable / LangVersion✅在模板 .csproj 中原样保留
PackageReference PrivateAssets / IncludeAssets / ExcludeAssets✅在每个引用上保留元数据
CPM(存在 Directory.Packages.props)✅ManagePackageVersionsCentrally 保持启用,且不生成内联 Version 属性

对有意省略的任何一行标记为 ⚠️,并说明原因——绝不能含糊带过。

步骤 2:验证 template.json

使用 template-validation 技能验证生成的 template.json(该技能涵盖全部规则——必需字段、identity 格式、保留的 shortName 冲突、参数数据类型、后置操作、约束和标签)。

检查内容概要:

  • 必需字段 — 必须包含 identity、name 和 shortName。
  • ShortName 冲突 — 避免使用与 dotnet new 子命令冲突的名称。请从已安装 SDK 的 dotnet new --help 中 Commands: 部分读取权威列表,不要将其硬编码(列表可能随版本变化);当前 SDK 的示例包括 install、uninstall、update、list、search、details、create。当 dotnet new <name> 被解析为同名子命令时,就会发生冲突。顶层 dotnet 动词(如 build、run、test 和 publish)不会冲突。运行 dotnet new list,确认该名称尚未被占用。
  • 参数、后置操作、标签 — 完整规则(包括有效的数据类型列表)请参阅 template-validation。
步骤 3:完善模板

根据验证结果和用户需求:

  1. 添加参数,并设置合适的类型(string、bool、choice)、默认值和描述

  2. 添加条件内容,使用文件类型支持的有效语法。在 XML 中,使用 XML 注释包裹模板指令,而不要直接使用预处理器指令:

    
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
    
    
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
    
    
  3. 配置后置操作,用于添加解决方案、还原或运行自定义脚本

  4. 设置约束,限制模板支持的 SDK 或工作负载

  5. 添加分类和标签,便于发现

对于还原后置操作,如果已知项目路径,优先使用 primaryOutputs:

"primaryOutputs": [{ "path": "MyProject.csproj" }],
"postActions": [{
  "description": "Restore NuGet packages.",
  "manualInstructions": [{ "text": "Run 'dotnet restore'." }],
  "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025",
  "continueOnError": true
}]

如果需要使用 args.files,其路径会在重命名前与源模板进行匹配,例如 "files": ["**/*.csproj"]。请说明这一区别。

步骤 4:在本地测试模板

对于基于现有项目创建模板的请求,此步骤是必需的,而非可选项: 安装编写好的模板,运行试运行,将模板实例化到临时输出文件夹中,并构建生成的项目。报告每项观察到的结果;仅检查 template.json 并不能证明可复用模板有效。

dotnet new install ./path/to/template/root
dotnet new mylib --name TestProject --dry-run
dotnet new mylib --name TestProject --output ./test-output
dotnet build ./test-output/TestProject

需要打包时,请提供完整的打包项目,而不只是目录树:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <PackageId>Contoso.ProjectTemplates</PackageId>
    <PackageType>Template</PackageType>
    <TargetFramework>net8.0</TargetFramework>
    <IncludeBuildOutput>false</IncludeBuildOutput>
    <NoWarn>$(NoWarn);NU5128</NoWarn>
  </PropertyGroup>
  <ItemGroup>
    <Compile Remove="**\*" />
    <Content Include="templates\**\*" Pack="true" PackagePath="content\" />
  </ItemGroup>
</Project>

打包项目的目标框架仅适用于仅包含内容的打包项目;它不会更改 templates/ 中项目的目标框架。除非打包项目本身使用了较新的构建功能,否则应优先选择广泛可用且受支持的框架。

对于独立的 CPM 模板,打包后的 Directory.Packages.props 必须包含 <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>,并且每个没有版本号的 PackageReference 都必须有匹配的 PackageVersion。将 props 文件保留在预期生成的存储库根目录;不要在项目附近放置重复文件,以免改变查找行为。

验证

  • template.json 通过手动验证,且无错误
  • 模板标识和 shortName 唯一且有意义
  • 所有参数都有描述和合适的默认值
  • 模板可以成功安装、试运行和实例化
  • 创建的项目可通过 dotnet build 顺利构建
  • 条件内容在所有参数组合下都能生成正确输出
  • XML 模板指令已用 XML 注释包裹,且生成的项目可正常解析
  • 主机约束使用 args[].hostname;还原操作使用 primaryOutputs 或 args.files

常见问题

问题解决方案
标识格式问题使用反向 DNS 格式(例如 MyOrg.Templates.WebApi)。避免使用空格或特殊字符。
ShortName 与 CLI 命令冲突避免使用与 dotnet new 子命令相同的名称;从 dotnet new --help 获取当前命令列表,不要将其硬编码(示例仅供说明:install、uninstall、update、list、search、details、create)。build/run/test/publish 等顶级动词可以使用。运行 dotnet new list,查看该名称是否已被占用。
缺少参数描述每个参数都应设置 description 和 displayName,以便用户发现。
未测试所有参数组合使用不同的参数值运行 dotnet new <template> --dry-run,验证条件内容是否正常工作。
在模板中硬编码版本使用 sourceName 替换项目名称,并考虑将框架版本参数化。
未设置分类添加适当的 classifications(例如 ["Web", "API"]),便于发现模板。
重用来自其他约束或后置操作的字段遵循确切的架构:使用 host.args[].hostname,还原操作使用 args.files,而不是运行脚本的字段。

更多信息

评论

支持 Markdown