home / skills / williamzujkowski / cognitive-toolworks / tooling-csharp-generator

tooling-csharp-generator skill

/skills/tooling-csharp-generator

This skill generates complete C# .NET project scaffolding with dotnet CLI, testing, analyzers, NuGet packaging, and Docker integration.

npx playbooks add skill williamzujkowski/cognitive-toolworks --skill tooling-csharp-generator

Review the files below or copy the command above to add this skill to your agents.

Files (12)
SKILL.md
18.0 KB
---
name: "C# .NET Tooling Specialist"
slug: "tooling-csharp-generator"
description: "Generate C# .NET project scaffolding with dotnet CLI, xUnit/NUnit, StyleCop analyzers, and packaging (NuGet/Docker)."
capabilities:
  - Project structure generation (library, console, web-api, blazor, wpf, maui)
  - Build tool setup (dotnet CLI, MSBuild, solution files)
  - Testing framework configuration (xUnit, NUnit, MSTest, Moq)
  - Code quality tools (StyleCop, Roslyn analyzers, SonarAnalyzer)
  - Packaging and distribution (NuGet, Docker, native AOT)
  - ASP.NET Core setup (minimal APIs, MVC, Blazor)
inputs:
  - project_type: "library | console | web-api | blazor | wpf | maui (string)"
  - dotnet_version: "6.0 | 7.0 | 8.0 (string)"
  - test_framework: "xunit | nunit | mstest (string)"
  - project_name: "Name of the project (string)"
outputs:
  - project_structure: "Directory layout with all config files (JSON)"
  - csproj_file: "Complete .csproj configuration"
  - solution_file: ".sln file for multi-project solutions"
  - test_project: "Test project configuration"
keywords:
  - csharp
  - dotnet
  - tooling
  - nuget
  - xunit
  - aspnet
  - blazor
  - roslyn
  - msbuild
version: "1.0.0"
owner: "cognitive-toolworks"
license: "MIT"
security: "Public; no secrets or PII; safe for open repositories"
links:
  - https://learn.microsoft.com/en-us/dotnet/core/
  - https://learn.microsoft.com/en-us/aspnet/core/
  - https://xunit.net/docs/getting-started/netcore/
  - https://learn.microsoft.com/en-us/nuget/
  - https://github.com/DotNetAnalyzers/StyleCopAnalyzers
---

## Purpose & When-To-Use

**Trigger conditions:**
- Starting a new C# .NET project requiring modern tooling
- Creating ASP.NET Core web APIs or Blazor applications
- Building cross-platform console applications or libraries
- Setting up .NET MAUI mobile applications
- Creating NuGet packages for distribution
- Migrating .NET Framework projects to .NET Core/5+

**Not for:**
- Legacy .NET Framework 4.x projects (use older MSBuild templates)
- Unity game development (use Unity's project templates)
- Xamarin projects (migrated to .NET MAUI)

---

## Pre-Checks

**Time normalization:**
- Compute `NOW_ET` using NIST/time.gov semantics (America/New_York, ISO-8601)
- Use `NOW_ET` for all citation access dates

**Input validation:**
- `project_type` must be one of: library, console, web-api, blazor, wpf, maui
- `dotnet_version` must be one of: 6.0, 7.0, 8.0
- `test_framework` must be one of: xunit, nunit, mstest
- `project_name` must be valid .NET identifier (PascalCase recommended)

**Source freshness:**
- .NET docs must be accessible [accessed 2025-10-26](https://learn.microsoft.com/en-us/dotnet/core/)
- ASP.NET Core docs must be accessible [accessed 2025-10-26](https://learn.microsoft.com/en-us/aspnet/core/)
- xUnit docs must be accessible [accessed 2025-10-26](https://xunit.net/docs/getting-started/netcore/)
- NuGet docs must be accessible [accessed 2025-10-26](https://learn.microsoft.com/en-us/nuget/)

---

## Procedure

### T1: Basic Project Structure (≤2k tokens)

**Fast path for common cases:**

1. **Directory Layout Generation**
   ```
   ProjectName/
     src/
       ProjectName/
         ProjectName.csproj
         Class1.cs
     tests/
       ProjectName.Tests/
         ProjectName.Tests.csproj
         UnitTest1.cs
     ProjectName.sln
     .gitignore
     README.md
   ```

2. **Core .csproj** [accessed 2025-10-26](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview)
   ```xml
   <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
       <TargetFramework>net8.0</TargetFramework>
       <Nullable>enable</Nullable>
       <ImplicitUsings>enable</ImplicitUsings>
       <LangVersion>latest</LangVersion>
     </PropertyGroup>

     <ItemGroup>
       <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
         <PrivateAssets>all</PrivateAssets>
         <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       </PackageReference>
     </ItemGroup>
   </Project>
   ```

3. **Solution File** (.sln)
   ```
   Microsoft Visual Studio Solution File, Format Version 12.00
   Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectName", "src\ProjectName\ProjectName.csproj", "{GUID}"
   EndProject
   Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProjectName.Tests", "tests\ProjectName.Tests\ProjectName.Tests.csproj", "{GUID}"
   EndProject
   ```

**Decision:** If only basic scaffolding needed → STOP at T1; otherwise proceed to T2.

---

### T2: Full Tooling Setup (≤6k tokens)

**Extended configuration with testing and web frameworks:**

1. **Testing Framework Configuration**

   **xUnit** [accessed 2025-10-26](https://xunit.net/docs/getting-started/netcore/)
   ```xml
   <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
       <TargetFramework>net8.0</TargetFramework>
       <IsPackable>false</IsPackable>
       <IsTestProject>true</IsTestProject>
     </PropertyGroup>

     <ItemGroup>
       <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
       <PackageReference Include="xunit" Version="2.7.0" />
       <PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
         <PrivateAssets>all</PrivateAssets>
         <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       </PackageReference>
       <PackageReference Include="Moq" Version="4.20.70" />
       <PackageReference Include="FluentAssertions" Version="6.12.0" />
       <PackageReference Include="coverlet.collector" Version="6.0.0">
         <PrivateAssets>all</PrivateAssets>
         <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
       </PackageReference>
     </ItemGroup>

     <ItemGroup>
       <ProjectReference Include="..\..\src\ProjectName\ProjectName.csproj" />
     </ItemGroup>
   </Project>
   ```

   **NUnit** (alternative) [accessed 2025-10-26](https://docs.nunit.org/)
   ```xml
   <ItemGroup>
     <PackageReference Include="NUnit" Version="4.1.0" />
     <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
     <PackageReference Include="NUnit.Analyzers" Version="4.1.0" />
   </ItemGroup>
   ```

2. **Code Quality and Analyzers**

   **StyleCop + Roslyn Analyzers** [accessed 2025-10-26](https://github.com/DotNetAnalyzers/StyleCopAnalyzers)
   ```xml
   <ItemGroup>
     <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
     <PackageReference Include="SonarAnalyzer.CSharp" Version="9.23.0.88079">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
   </ItemGroup>
   ```

   .editorconfig:
   ```ini
   # Top-most EditorConfig file
   root = true

   [*.cs]
   # Code style rules
   dotnet_sort_system_directives_first = true
   csharp_style_var_for_built_in_types = true
   csharp_style_var_when_type_is_apparent = true

   # Naming conventions
   dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = warning
   dotnet_naming_rule.interfaces_should_be_prefixed_with_i.symbols = interface
   dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = begins_with_i

   # StyleCop rules
   dotnet_diagnostic.SA1633.severity = none  # File header
   dotnet_diagnostic.SA1200.severity = none  # Using directives placement
   ```

3. **ASP.NET Core Web API**

   **Minimal API** [accessed 2025-10-26](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis)
   ```xml
   <Project Sdk="Microsoft.NET.Sdk.Web">
     <PropertyGroup>
       <TargetFramework>net8.0</TargetFramework>
       <Nullable>enable</Nullable>
       <ImplicitUsings>enable</ImplicitUsings>
     </PropertyGroup>

     <ItemGroup>
       <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
       <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
     </ItemGroup>
   </Project>
   ```

   Program.cs (minimal API):
   ```csharp
   var builder = WebApplication.CreateBuilder(args);

   builder.Services.AddEndpointsApiExplorer();
   builder.Services.AddSwaggerGen();

   var app = builder.Build();

   if (app.Environment.IsDevelopment())
   {
       app.UseSwagger();
       app.UseSwaggerUI();
   }

   app.UseHttpsRedirection();

   app.MapGet("/api/health", () => Results.Ok(new { status = "healthy" }))
      .WithName("GetHealth")
      .WithOpenApi();

   app.Run();
   ```

4. **Blazor WebAssembly**

   ```xml
   <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
     <PropertyGroup>
       <TargetFramework>net8.0</TargetFramework>
     </PropertyGroup>

     <ItemGroup>
       <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.4" />
       <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.4" PrivateAssets="all" />
     </ItemGroup>
   </Project>
   ```

---

### T3: Advanced Configuration (≤12k tokens)

**Deep configuration for NuGet packaging and production:**

1. **NuGet Package Configuration** [accessed 2025-10-26](https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package-msbuild)

   ```xml
   <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
       <TargetFramework>net8.0</TargetFramework>
       <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
       <PackageId>CompanyName.ProjectName</PackageId>
       <Version>1.0.0</Version>
       <Authors>Your Name</Authors>
       <Company>Company Name</Company>
       <Description>Package description</Description>
       <PackageTags>tag1;tag2;tag3</PackageTags>
       <PackageLicenseExpression>MIT</PackageLicenseExpression>
       <PackageProjectUrl>https://github.com/user/repo</PackageProjectUrl>
       <RepositoryUrl>https://github.com/user/repo</RepositoryUrl>
       <RepositoryType>git</RepositoryType>
       <PublishRepositoryUrl>true</PublishRepositoryUrl>
       <EmbedUntrackedSources>true</EmbedUntrackedSources>
       <IncludeSymbols>true</IncludeSymbols>
       <SymbolPackageFormat>snupkg</SymbolPackageFormat>
     </PropertyGroup>

     <ItemGroup>
       <PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
     </ItemGroup>
   </Project>
   ```

2. **Multi-Target Framework**

   ```xml
   <PropertyGroup>
     <TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
   </PropertyGroup>

   <ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
     <PackageReference Include="System.Text.Json" Version="6.0.0" />
   </ItemGroup>

   <ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
     <PackageReference Include="System.Text.Json" Version="8.0.0" />
   </ItemGroup>
   ```

3. **Native AOT Publishing** [accessed 2025-10-26](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/)

   ```xml
   <PropertyGroup>
     <PublishAot>true</PublishAot>
     <InvariantGlobalization>true</InvariantGlobalization>
     <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
   </PropertyGroup>
   ```

   Publish command:
   ```bash
   dotnet publish -c Release -r linux-x64 --self-contained
   ```

4. **Docker Configuration**

   Dockerfile (multi-stage):
   ```dockerfile
   FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
   WORKDIR /src
   COPY ["src/ProjectName/ProjectName.csproj", "src/ProjectName/"]
   RUN dotnet restore "src/ProjectName/ProjectName.csproj"
   COPY . .
   WORKDIR "/src/src/ProjectName"
   RUN dotnet build "ProjectName.csproj" -c Release -o /app/build

   FROM build AS publish
   RUN dotnet publish "ProjectName.csproj" -c Release -o /app/publish

   FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
   WORKDIR /app
   EXPOSE 8080
   COPY --from=publish /app/publish .
   ENTRYPOINT ["dotnet", "ProjectName.dll"]
   ```

   .dockerignore:
   ```
   **/bin
   **/obj
   **/out
   **/.vs
   **/.vscode
   ```

5. **CI/CD Pipeline** (GitHub Actions)

   ```.github/workflows/dotnet.yml
   name: .NET CI

   on:
     push:
       branches: [ main ]
     pull_request:
       branches: [ main ]

   jobs:
     build:
       runs-on: ubuntu-latest
       steps:
       - uses: actions/checkout@v4
       - name: Setup .NET
         uses: actions/setup-dotnet@v4
         with:
           dotnet-version: 8.0.x
       - name: Restore dependencies
         run: dotnet restore
       - name: Build
         run: dotnet build --no-restore
       - name: Test
         run: dotnet test --no-build --verbosity normal --collect:"XPlat Code Coverage"
       - name: Upload coverage
         uses: codecov/codecov-action@v4
   ```

6. **Solution-Level Configuration**

   Directory.Build.props (applies to all projects):
   ```xml
   <Project>
     <PropertyGroup>
       <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
       <AnalysisMode>AllEnabledByDefault</AnalysisMode>
       <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
       <EnableNETAnalyzers>true</EnableNETAnalyzers>
     </PropertyGroup>
   </Project>
   ```

---

## Decision Rules

**Project Type Selection:**
- **library:** Class library for NuGet distribution, multi-targeting
- **console:** Command-line application, single executable
- **web-api:** ASP.NET Core minimal API or MVC for REST services
- **blazor:** Blazor WebAssembly or Server for SPAs
- **wpf:** Windows desktop application (Windows-only)
- **maui:** Cross-platform mobile and desktop (.NET MAUI)

**Test Framework Selection:**
- **xUnit:** Modern, recommended for new projects, parallel execution
- **NUnit:** Mature, feature-rich, parameterized tests
- **MSTest:** Microsoft's framework, Visual Studio integration

**Abort Conditions:**
- Invalid `project_name` (contains spaces, special chars) → error
- Conflicting frameworks (WPF + MAUI) → error
- Unsupported .NET version → error

**.NET Version Selection:**
- Use .NET 8.0 for new projects (LTS with long-term support)
- .NET 6.0 for compatibility with older systems (LTS)
- .NET 7.0 for latest features (standard support)

---

## Output Contract

**Schema (JSON):**

```json
{
  "project_name": "string",
  "project_type": "library | console | web-api | blazor | wpf | maui",
  "dotnet_version": "string",
  "test_framework": "xunit | nunit | mstest",
  "structure": {
    "directories": ["string"],
    "files": {
      "path/to/file": "file content (string)"
    }
  },
  "commands": {
    "restore": "string",
    "build": "string",
    "test": "string",
    "run": "string",
    "publish": "string"
  },
  "next_steps": ["string"],
  "timestamp": "ISO-8601 string (NOW_ET)"
}
```

**Required Fields:**
- All fields mandatory
- File contents must be syntactically valid (XML, C#, JSON)
- Include inline comments explaining configuration choices

---

## Examples

**Quick Start: C# Library** (26 lines)

```csharp
// examples/LibraryExample.cs
namespace Example.Utils;

public sealed class TextAnalyzer
{
    public record AnalysisResult(int Length, int WordCount, DateTime Analyzed);

    private readonly List<string> _history = new();

    public AnalysisResult Analyze(string text)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(text);
        _history.Add(text);
        var wordCount = text.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
        return new AnalysisResult(text.Length, wordCount, DateTime.UtcNow);
    }

    public IReadOnlyList<string> GetHistory() => _history.AsReadOnly();

    public void Clear() => _history.Clear();
}
```

**Additional Examples:**
- **CLI Tool**: `examples/CliExample.cs` (22 lines) - System.CommandLine, async/await, file I/O
- **Minimal API**: `examples/ApiExample.cs` (30 lines) - ASP.NET Core endpoints, concurrent collections

**Template Resources** (see `resources/`)
- .csproj: `Library.csproj` / `Console.csproj` / `WebApi.csproj`
- Testing: `Tests.csproj` with xUnit, Moq, FluentAssertions / `ExampleTest.cs`
- Packaging: `NuGetPackage.csproj` - complete NuGet metadata and SourceLink

---

## Quality Gates

**Token Budgets:**
- **T1:** ≤2k tokens (basic structure + .csproj + .sln)
- **T2:** ≤6k tokens (testing, analyzers, ASP.NET Core, Blazor)
- **T3:** ≤12k tokens (NuGet packaging, multi-targeting, Docker, CI/CD, native AOT)

**Safety:**
- No hardcoded API keys or secrets
- .gitignore includes bin/, obj/, .vs/, .user files
- Roslyn analyzers configured to catch security issues

**Auditability:**
- All configurations cite official Microsoft documentation
- Version constraints explicit
- Generation timestamp included

**Determinism:**
- Same inputs → identical structure
- Versions pinned where appropriate
- No randomness in generation

**Performance:**
- T1 generation: <1 second
- T2 generation: <3 seconds
- T3 generation: <5 seconds

---

## Resources

**Official Documentation (accessed 2025-10-26):**
1. [.NET Documentation](https://learn.microsoft.com/en-us/dotnet/core/) - Core .NET reference
2. [ASP.NET Core Documentation](https://learn.microsoft.com/en-us/aspnet/core/) - Web framework
3. [xUnit Getting Started](https://xunit.net/docs/getting-started/netcore/) - Testing framework
4. [NuGet Documentation](https://learn.microsoft.com/en-us/nuget/) - Package management
5. [StyleCop Analyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) - Code quality
6. [Blazor Documentation](https://learn.microsoft.com/en-us/aspnet/core/blazor/) - WebAssembly/Server
7. [.NET MAUI Documentation](https://learn.microsoft.com/en-us/dotnet/maui/) - Cross-platform apps

**Testing:**
- [NUnit](https://docs.nunit.org/) - Alternative testing framework
- [MSTest](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest) - Microsoft testing framework
- [Moq](https://github.com/moq/moq4) - Mocking library
- [FluentAssertions](https://fluentassertions.com/) - Assertion library

**Build Tools:**
- [MSBuild](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild) - Build engine
- [Native AOT](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/) - Ahead-of-time compilation

**Best Practices:**
- [C# Coding Conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions) - Style guide
- [.NET Design Guidelines](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/) - API design

Overview

This skill scaffolds modern C# .NET projects and configures tooling end-to-end. It generates cross-platform project layouts, csproj templates, test projects (xUnit/NUnit/MSTest), StyleCop/roslyn analyzers, and packaging options for NuGet and Docker. It targets .NET 6/7/8 and common project types (library, console, web-api, blazor, wpf, maui).

How this skill works

Given validated inputs (project_name, project_type, dotnet_version, test_framework), the skill emits a directory structure, syntactically valid project files, solution entries, and CI/publishing artifacts. It provides optional levels: T1 basic scaffolding, T2 full tooling with tests and analyzers, and T3 advanced packaging (NuGet, native AOT, Docker, GitHub Actions). Outputs include recommended dotnet commands and next steps plus a NOW_ET timestamp for citations.

When to use it

  • Starting a new .NET 6/7/8 project that needs modern defaults
  • Creating ASP.NET Core Web APIs or Blazor single-page apps
  • Building libraries for NuGet distribution or multi-targeting
  • Setting up test projects with xUnit, NUnit, or MSTest
  • Packaging apps for Docker or native AOT publishing

Best practices

  • Validate project_name as a .NET identifier (PascalCase recommended) and enforce no spaces or special chars
  • Prefer .NET 8.0 for new work; use 6.0 for long-term compatibility
  • Include StyleCop.Analyzers and an .editorconfig at solution root to enforce consistent style
  • Keep test projects IsPackable=false and reference source projects via ProjectReference
  • Enable GeneratePackageOnBuild and SourceLink for NuGet packages; use CI to automate build/test/publish

Example use cases

  • Generate a class library with multi-targeting and NuGet packaging metadata for immediate publishing
  • Scaffold an ASP.NET Core minimal web-api with Swagger, HTTPS redirection, and Dockerfile for container deployment
  • Create a console app with native AOT publish and cross-platform Docker CI pipeline
  • Set up a repository with src/, tests/, solution file, StyleCop rules and GitHub Actions for build/test/coverage
  • Migrate a library to net8.0, add analyzers, and produce a .snupkg symbol package

FAQ

Which test framework should I choose?

xUnit is recommended for new projects due to modern features and parallelism; choose NUnit for advanced parameterized testing or MSTest for tight Visual Studio integration.

When should I use multi-targeting?

Use multi-targeting when publishing a library that must support multiple runtime versions or maintain compatibility across consumer platforms.

Can this scaffold Windows-only projects?

Yes—WPF is included but note it is Windows-only; prefer MAUI for cross-platform mobile/desktop apps.