mcpField
T
template-authoring

template-authoring

github.com/dotnet開発5.8k3.4k 回インストール1 日前に更新
リポジトリ

template-authoring について

既存プロジェクトを基にカスタム `dotnet new` テンプレートを作成・検証するスキルです。プロジェクト設定やパッケージ情報を引き継ぎ、生成物をローカルで試します。

主な機能

  1. 01プロジェクトからテンプレート設定を作成
  2. 02`template.json` を検証
  3. 03プロジェクトとパッケージ設定を維持
  4. 04パラメーター、条件、後処理を設定
  5. 05生成物をインストールしてビルド

活用シーン

  1. 01.csproj を再利用可能なテンプレートにする
  2. 02公開前にテンプレート設定を確認
  3. 03NuGet テンプレートパッケージを作成

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/template-authoringを入力して読み込まれたか確認します。

詳細

テンプレートの作成

このスキルは、エージェントがカスタムの 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 コメントXML が無効になる、単独の #if 行
生成されたプロジェクトの復元復元アクション 210D431B-A78B-4D2F-B762-4ED3E3EA9025。primaryOutputs、またはソーステンプレートのパス/glob を含む args.files を使用復元アクションでの executable などのスクリプト実行フィールド
SDK ホストに限定args が { "hostname": "dotnetcli" } を含む配列である host 制約。オプションの version でホスト/CLI のバージョンを制限要件がアクティブな SDK のバージョンである場合に host の version を使うこと、無効なホスト ID dotnet-cli、または無関係な pattern/value フィールド
アクティブな SDK バージョンの制限args に NuGet のバージョン/範囲文字列を指定する sdk-version 制約テンプレートが本当に必要とする場合を除き、マシン固有の完全一致パッチバージョン
CPM の維持生成される PackageReference 項目のバージョン指定を省略し、テンプレートを自己完結型にする場合は、パッケージを所有する Directory.Packages.props を含めるインラインの Version 属性を追加すること
テンプレートのパッケージ化<PackageType>Template</PackageType> を指定し、テンプレートのコンテンツを content/ 以下にパッケージ化する pack プロジェクト依頼されたプロジェクトファイルを提示せず、構成だけを説明すること
ステップ 1:既存のプロジェクトからひな形を作成する

ソース .csproj を分析し、.template.config/template.json を作成します。

  1. デフォルトでは、元のプロジェクトを変更せずに保持したまま、専用のテンプレートソースディレクトリにソースプロジェクトをコピーします。元のプロジェクトを直接変更するのは、その配置をユーザーが明示的に指定した場合のみです。
  2. テンプレートソースディレクトリ内に .template.config を作成します。
  3. identity(逆 DNS 形式)、name、shortName、sourceName(置換対象のプロジェクト名)、classifications、tags を指定して template.json を生成します。
  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. カスタムビルドの props/targets と 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.json を template-validation スキルで検証します(必須フィールド、identity の形式、予約済みの shortName との競合、パラメーターのデータ型、事後アクション、制約、タグなど、すべてのルールを管理しています)。

検証項目の概要:

  • 必須フィールド — identity、name、shortName を指定する必要があります。
  • shortName の競合 — dotnet new のサブコマンドと重複する名前は避けてください。インストール済み SDK の dotnet new --help にある Commands: セクションから正確な一覧を取得し、ハードコードしないでください(バージョンによって変わる可能性があります)。現在の SDK における例としては、install、uninstall、update、list、search、details、create があります。dotnet new <name> が同じ名前のサブコマンドとして解析されるため、競合が発生します。build、run、test、publish などのトップレベルの dotnet 動詞は競合しません。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

パッケージ化が要求された場合は、ディレクトリツリーだけでなく、完全な pack プロジェクトを含めてください。

<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>

pack プロジェクトのターゲットフレームワークは、コンテンツのみのパッケージ化プロジェクトにのみ適用されます。 templates/ 内のプロジェクトのターゲットを変更するものではありません。パッケージ化プロジェクト自体が 新しいビルド機能を使用していない限り、広く利用可能なサポート対象のフレームワークを優先してください。

セルフコンテインドな CPM テンプレートの場合、パッケージ化された Directory.Packages.props には <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> を含める必要があり、バージョン指定のない すべての PackageReference には、対応する PackageVersion が必要です。props ファイルは、意図した生成先 リポジトリのルートに置いてください。参照方法が変わる位置のプロジェクトの近くに重複して置かないでください。

検証

  • template.json が手動検証にエラーゼロで合格する
  • テンプレートの identity と shortName が一意で意味がある
  • すべてのパラメーターに説明と適切な既定値がある
  • テンプレートをインストール、ドライラン、インスタンス化できる
  • 作成されたプロジェクトが dotnet build でクリーンにビルドできる
  • 条件付きコンテンツがすべてのパラメーターの組み合わせで正しい出力を生成する
  • XML テンプレートディレクティブが XML コメントで囲まれており、生成されたプロジェクトがパースできる
  • ホスト制約は args[].hostname を使用し、復元アクションは primaryOutputs または args.files を使用している

よくある落とし穴

落とし穴解決策
identity の形式の問題逆 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 を設定していないテンプレートの検出のために、適切な classifications(例: ["Web", "API"])を追加してください。
別の制約やポストアクションのフィールドを再利用している正確なスキーマに従ってください。host.args[].hostname や、run-script のフィールドではなく復元の args.files を使用します。

詳細情報

コメント