/template-authoring
Guides creation and validation of custom dotnet new templates from existing projects. Generates a .template.config/template.json that preserves the source project's conventions. USE FOR: creating a reusable dotnet new template from an existing project, bootstrapping
Claude Code
$ npx -y skills add dotnet/skills --skill template-authoring --agent claude-code
Codex
$ npx skills add dotnet/skills --skill template-authoring -a codex -y
Cursor
$ npx skills add dotnet/skills --skill template-authoring -a cursor -y
Gemini CLI
$ npx skills add dotnet/skills --skill template-authoring -a gemini-cli -y
GitHub Copilot
$ npx skills add dotnet/skills --skill template-authoring -a github-copilot -y
OpenCode
$ npx skills add dotnet/skills --skill template-authoring -a opencode -y
Windsurf
$ npx skills add dotnet/skills --skill template-authoring -a windsurf -y
SKILL.md
template-authoring.SKILL.mdname: template-authoring
description: >
Guides creation and validation of custom dotnet new templates from existing projects.
Generates a .template.config/template.json that preserves the source project's conventions.
USE FOR: creating a reusable dotnet new template from an existing project, bootstrapping
.template.config/template.json with correct identity, shortName, parameters, and
post-actions, adding parameters or conditional content to a template you are authoring,
validating the template.json you are authoring before publishing,
packaging templates as NuGet packages for distribution.
DO NOT USE FOR: validating an existing template.json as a standalone task (use
template-validation), finding or using existing templates (use template-discovery and
template-instantiation), MSBuild project file issues unrelated to template authoring,
NuGet package publishing (only template packaging structure).
license: MIT
Template Authoring
This skill helps an agent create and validate custom `dotnet new` templates. It guides bootstrapping templates from existing projects and validates `template.json` files for authoring issues before publishing.
When to Use
- User wants to create a reusable template from an existing .csproj
- User wants to validate a template.json they are authoring before publishing
- User is setting up `.template.config/template.json` from scratch
- User wants to package a template for NuGet distribution
When Not to Use
- User wants to find or use existing templates — route to `template-discovery` or `template-instantiation`
- User has MSBuild issues unrelated to template authoring — route to `dotnet-msbuild` plugin
Inputs
| Input | Required | Description | |-------|----------|-------------| | Source project path | For creation | Path to the .csproj to use as template source | | template.json path | For validation | Path to an existing template.json to validate | | Template name | For creation | Human-readable name for the template | | Short name | Recommended | Short name for `dotnet new <shortname>` usage |
Workflow
Rules that change the answer
Use these structures exactly; do not invent fields from other template features.
**Deliver the requested artifact.** When the user says "show", "write", or "give me the content", put the complete JSON/XML in the final response even if you also wrote it to disk. Never edit this skill's `SKILL.md` or plugin documentation as a substitute for authoring the user's template. Only create or modify template files when the user requested file changes and the target template/project is present.
| Need | Correct structure | Never use | |------|-------------------|-----------| | Conditional XML in a `.csproj` | XML comments such as `<!--#if (database == "SqlServer") -->` and `<!--#endif -->` around the complete element | bare `#if` lines, which make the XML invalid | | Restore generated projects | restore action `210D431B-A78B-4D2F-B762-4ED3E3EA9025`; use `primaryOutputs`, or `args.files` containing source-template paths/globs | run-script fields such as `executable` on the restore action | | Restrict to the SDK host | a `host` constraint whose `args` is an array containing `{ "hostname": "dotnetcli" }`; its optional `version` restricts the host/CLI version | using host `version` when the requirement is specifically the active SDK version, the invalid host ID `dotnet-cli`, or unrelated `pattern` / `value` fields | | Restrict the active SDK version | an `sdk-version` constraint with a NuGet version/range string in `args` | a machine-specific exact patch unless the template truly requires it | | Preserve CPM | keep generated `PackageReference` items versionless and package the owning `Directory.Packages.props` when the template is self-contained | adding inline `Version` attributes | | Package templates | a pack project with `<PackageType>Template</PackageType>` and template content packed below `content/` | describing a layout without showing the requested project file |
Step 1: Bootstrap from existing project
Analyze the source `.csproj` and create a `.template.config/template.json`:
1. Copy the source project into a dedicated template-source directory by default, preserving the original project untouched. Modify the original in place only when the user explicitly asks for that layout. 2. Create `.template.config` inside the template-source directory. 3. Generate `template.json` with `identity` (reverse-DNS), `name`, `shortName`, `sourceName` (project name for replacement), `classifications`, and `tags` 4. Preserve from source — generic `dotnet new` templates frequently get these wrong, so verify each is carried over from the original `.csproj`: 1. **SDK type** — `Microsoft.NET.Sdk`, `Microsoft.NET.Sdk.Web`, `Microsoft.NET.Sdk.Worker`, etc. 2. **Analyzer/package reference metadata** — `PrivateAssets`, `IncludeAssets`, `ExcludeAssets` 3. **`OutputType` and other key properties** — `TreatWarningsAsErrors`, `Nullable`, `LangVersion` 4. **CPM participation** — no inline `Version` attributes when a `Directory.Packages.props` is present 5. **Custom build props/targets** and `Directory.Build.props` conventions 6. **Repo conventions** — folder layout, naming, `global.json` SDK pin
Minimal example:
{
"$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" }
}**Required output — do not stop at a minimal stub.** Write the *complete* `.template.config/template.json` for the actual source project, then emit a short **conventions-preserved** confirmation so the user can see nothing was silently dropped. This carry-over is the whole value of the skill; a generic `dotnet new` template that loses these is why authoring ties with a hand-written
Read more
name: template-authoring description: > Guides creation and validation of custom dotnet new templates from existing projects. Generates a .template.config/template.json that preserves the source project's conventions. USE FOR: creating a reusable dotnet new template from an existing project, bootstrapping .template.config/template.json with correct identity, shortName, parameters, and post-actions, adding parameters or conditional content to a template you are authoring, validating the template.json you are authoring before publishing, packaging templates as NuGet packages for distribution. DO NOT USE FOR: validating an existing template.json as a standalone task (use template-validation), finding or using existing templates (use template-discovery and template-instantiation), MSBuild project file issues unrelated to template authoring, NuGet package publishing (only template packaging structure). license: MIT
Template Authoring
This skill helps an agent create and validate custom `dotnet new` templates. It guides bootstrapping templates from existing projects and validates `template.json` files for authoring issues before publishing.
When to Use
- User wants to create a reusable template from an existing .csproj
- User wants to validate a template.json they are authoring before publishing
- User is setting up `.template.config/template.json` from scratch
- User wants to package a template for NuGet distribution
When Not to Use
- User wants to find or use existing templates — route to `template-discovery` or `template-instantiation`
- User has MSBuild issues unrelated to template authoring — route to `dotnet-msbuild` plugin
Inputs
| Input | Required | Description | |-------|----------|-------------| | Source project path | For creation | Path to the .csproj to use as template source | | template.json path | For validation | Path to an existing template.json to validate | | Template name | For creation | Human-readable name for the template | | Short name | Recommended | Short name for `dotnet new <shortname>` usage |
Workflow
Rules that change the answer
Use these structures exactly; do not invent fields from other template features.
**Deliver the requested artifact.** When the user says "show", "write", or "give me the content", put the complete JSON/XML in the final response even if you also wrote it to disk. Never edit this skill's `SKILL.md` or plugin documentation as a substitute for authoring the user's template. Only create or modify template files when the user requested file changes and the target template/project is present.
| Need | Correct structure | Never use | |------|-------------------|-----------| | Conditional XML in a `.csproj` | XML comments such as `<!--#if (database == "SqlServer") -->` and `<!--#endif -->` around the complete element | bare `#if` lines, which make the XML invalid | | Restore generated projects | restore action `210D431B-A78B-4D2F-B762-4ED3E3EA9025`; use `primaryOutputs`, or `args.files` containing source-template paths/globs | run-script fields such as `executable` on the restore action | | Restrict to the SDK host | a `host` constraint whose `args` is an array containing `{ "hostname": "dotnetcli" }`; its optional `version` restricts the host/CLI version | using host `version` when the requirement is specifically the active SDK version, the invalid host ID `dotnet-cli`, or unrelated `pattern` / `value` fields | | Restrict the active SDK version | an `sdk-version` constraint with a NuGet version/range string in `args` | a machine-specific exact patch unless the template truly requires it | | Preserve CPM | keep generated `PackageReference` items versionless and package the owning `Directory.Packages.props` when the template is self-contained | adding inline `Version` attributes | | Package templates | a pack project with `<PackageType>Template</PackageType>` and template content packed below `content/` | describing a layout without showing the requested project file |
Step 1: Bootstrap from existing project
Analyze the source `.csproj` and create a `.template.config/template.json`:
1. Copy the source project into a dedicated template-source directory by default, preserving the original project untouched. Modify the original in place only when the user explicitly asks for that layout. 2. Create `.template.config` inside the template-source directory. 3. Generate `template.json` with `identity` (reverse-DNS), `name`, `shortName`, `sourceName` (project name for replacement), `classifications`, and `tags` 4. Preserve from source — generic `dotnet new` templates frequently get these wrong, so verify each is carried over from the original `.csproj`: 1. **SDK type** — `Microsoft.NET.Sdk`, `Microsoft.NET.Sdk.Web`, `Microsoft.NET.Sdk.Worker`, etc. 2. **Analyzer/package reference metadata** — `PrivateAssets`, `IncludeAssets`, `ExcludeAssets` 3. **`OutputType` and other key properties** — `TreatWarningsAsErrors`, `Nullable`, `LangVersion` 4. **CPM participation** — no inline `Version` attributes when a `Directory.Packages.props` is present 5. **Custom build props/targets** and `Directory.Build.props` conventions 6. **Repo conventions** — folder layout, naming, `global.json` SDK pin
Minimal example:
{
"$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" }
}**Required output — do not stop at a minimal stub.** Write the *complete* `.template.config/template.json` for the actual source project, then emit a short **conventions-preserved** confirmation so the user can see nothing was silently dropped. This carry-over is the whole value of the skill; a generic `dotnet new` template that loses these is why authoring ties with a hand-written
This repository contains the .NET team's curated set of portable skills and host-specific custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.
Other skills on skills.
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about template-authoring.
- Which coding agents can use template-authoring?
- template-authoring installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

