Context
Creating a new Roslyn analyzer or source generator project that uses Scribe requires significant manual setup — even more so now that the Scribe SDK (#4) is in place, because the SDK's existence makes it possible to scaffold a fully working project from a template with zero manual configuration.
Currently, developers must:
- Create a new class library project
- Manually configure all analyzer/generator properties (or adopt the SDK)
- Add the correct PackageReferences with the right
PrivateAssets settings
- Set up the test project with analyzer testing infrastructure
- Configure LocalDev if working cross-repo
dotnet new templates can automate all of this into a single command.
Goal
Create a template pack NuGet package (BulletsForHumanity.Scribe.Templates) containing project templates that scaffold fully working analyzer/generator projects.
Depends on: #4 (Scribe SDK) — templates use the SDK.
Related: #8 (Solution Analyzer support) — templates should consider the standalone vs. solution-local distinction.
Key Design Decisions (from SDK implementation)
- Templates must use the Scribe SDK (
<Project Sdk="BulletsForHumanity.Scribe.Sdk">) — not raw boilerplate
- Templates auto-include
BulletsForHumanity.Scribe as a PackageReference — the SDK deliberately does not auto-reference Scribe (to support SDK-only use cases), but templates should include it since they scaffold generator/analyzer code that uses Quill and other Scribe APIs
global.json with SDK version symbol — each template includes a global.json with "msbuild-sdks": { "BulletsForHumanity.Scribe.Sdk": "{{SdkVersion}}" }, where {{SdkVersion}} is a template symbol injected at install time from the template pack version
Proposed templates
1. scribe-analyzer — Roslyn Analyzer Project
Scaffolds a project with:
- Scribe SDK via
global.json
PackageReference to BulletsForHumanity.Scribe (auto-included)
PackageReference to Microsoft.CodeAnalysis.CSharp
- A sample
DiagnosticAnalyzer with a DiagnosticDescriptor
- A companion code fixer
dotnet new scribe-analyzer -n MyAnalyzer
2. scribe-generator — Roslyn Source Generator Project
Scaffolds a project with:
- Scribe SDK via
global.json
PackageReference to BulletsForHumanity.Scribe (auto-included)
PackageReference to Microsoft.CodeAnalysis.CSharp
- A sample
IIncrementalGenerator using the Transform → Register → Render pattern
- Quill usage for source output (demonstrating the recommended pattern)
dotnet new scribe-generator -n MyGenerator
3. scribe-analyzer-test — Analyzer/Generator Test Project
Scaffolds a test project with:
- xUnit v3, Shouldly
CSharpAnalyzerVerifier / CSharpCodeFixVerifier setup from Microsoft.CodeAnalysis.Testing
- A sample test that verifies the sample analyzer from template 1 or 2
- Project reference to the analyzer/generator project
dotnet new scribe-analyzer-test -n MyAnalyzer.Tests
Implementation plan
1. Template pack structure
templates/
scribe-analyzer/
.template.config/
template.json
MyAnalyzer.csproj
SampleAnalyzer.cs
SampleCodeFix.cs
scribe-generator/
.template.config/
template.json
MyGenerator.csproj
SampleGenerator.cs
scribe-analyzer-test/
.template.config/
template.json
MyAnalyzer.Tests.csproj
SampleAnalyzerTests.cs
BulletsForHumanity.Scribe.Templates.csproj ← pack-only project
2. template.json configuration
Each template needs:
identity, shortName, sourceName (for name substitution)
tags for discoverability (type: project, language: C#)
symbols for template parameters (e.g. --framework for optional multi-targeting)
sources with rename/exclude rules
3. Pack as a template NuGet package
The .csproj uses <PackageType>Template</PackageType> and includes the template directories as content.
4. Installation and usage
# Install
dotnet new install BulletsForHumanity.Scribe.Templates
# Use
dotnet new scribe-analyzer -n MyAnalyzer
dotnet new scribe-analyzer-test -n MyAnalyzer.Tests
Templates also appear in Visual Studio's "New Project" dialog automatically once installed.
Hints
- See Microsoft's template authoring docs for the
template.json schema.
- The
sourceName field in template.json controls find-and-replace of the template name (e.g. "sourceName": "MyAnalyzer" → replaced with whatever -n value the user provides).
- Include a
global.json in the template with "msbuild-sdks": { "BulletsForHumanity.Scribe.Sdk": "version" } — use a template symbol to inject the current SDK version.
- The sample analyzer/generator code should be simple but functional — a real diagnostic that fires, a real generator that emits code. Not just empty stubs.
- Consider using the Quill builder in the generator template sample to demonstrate the recommended pattern.
Acceptance criteria
Context
Creating a new Roslyn analyzer or source generator project that uses Scribe requires significant manual setup — even more so now that the Scribe SDK (#4) is in place, because the SDK's existence makes it possible to scaffold a fully working project from a template with zero manual configuration.
Currently, developers must:
PrivateAssetssettingsdotnet newtemplates can automate all of this into a single command.Goal
Create a template pack NuGet package (
BulletsForHumanity.Scribe.Templates) containing project templates that scaffold fully working analyzer/generator projects.Depends on: #4 (Scribe SDK) — templates use the SDK.
Related: #8 (Solution Analyzer support) — templates should consider the standalone vs. solution-local distinction.
Key Design Decisions (from SDK implementation)
<Project Sdk="BulletsForHumanity.Scribe.Sdk">) — not raw boilerplateBulletsForHumanity.Scribeas aPackageReference— the SDK deliberately does not auto-reference Scribe (to support SDK-only use cases), but templates should include it since they scaffold generator/analyzer code that uses Quill and other Scribe APIsglobal.jsonwith SDK version symbol — each template includes aglobal.jsonwith"msbuild-sdks": { "BulletsForHumanity.Scribe.Sdk": "{{SdkVersion}}" }, where{{SdkVersion}}is a template symbol injected at install time from the template pack versionProposed templates
1.
scribe-analyzer— Roslyn Analyzer ProjectScaffolds a project with:
global.jsonPackageReferencetoBulletsForHumanity.Scribe(auto-included)PackageReferencetoMicrosoft.CodeAnalysis.CSharpDiagnosticAnalyzerwith aDiagnosticDescriptor2.
scribe-generator— Roslyn Source Generator ProjectScaffolds a project with:
global.jsonPackageReferencetoBulletsForHumanity.Scribe(auto-included)PackageReferencetoMicrosoft.CodeAnalysis.CSharpIIncrementalGeneratorusing the Transform → Register → Render pattern3.
scribe-analyzer-test— Analyzer/Generator Test ProjectScaffolds a test project with:
CSharpAnalyzerVerifier/CSharpCodeFixVerifiersetup fromMicrosoft.CodeAnalysis.TestingImplementation plan
1. Template pack structure
2. template.json configuration
Each template needs:
identity,shortName,sourceName(for name substitution)tagsfor discoverability (type: project,language: C#)symbolsfor template parameters (e.g.--frameworkfor optional multi-targeting)sourceswith rename/exclude rules3. Pack as a template NuGet package
The
.csprojuses<PackageType>Template</PackageType>and includes the template directories as content.4. Installation and usage
Templates also appear in Visual Studio's "New Project" dialog automatically once installed.
Hints
template.jsonschema.sourceNamefield intemplate.jsoncontrols find-and-replace of the template name (e.g."sourceName": "MyAnalyzer"→ replaced with whatever-nvalue the user provides).global.jsonin the template with"msbuild-sdks": { "BulletsForHumanity.Scribe.Sdk": "version" }— use a template symbol to inject the current SDK version.Acceptance criteria
dotnet new install BulletsForHumanity.Scribe.Templatesinstalls successfullydotnet new scribe-analyzer -n Foocreates a buildable analyzer project using the Scribe SDK with Scribe auto-includeddotnet new scribe-generator -n Foocreates a buildable generator project using the Scribe SDK with Scribe auto-includeddotnet new scribe-analyzer-test -n Foo.Testscreates a buildable test projectglobal.jsoncontains the correct SDK version symboldotnet testdotnet packon the generated projects produces correct analyzer NuGet packages