Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generate C# .NET project scaffolding with dotnet CLI, xUnit/NUnit, StyleCop analyzers, and packaging (NuGet/Docker).
.claude/skills/williamzujkowski-c-net-tooling-specialist/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 121% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 163% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 51% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 199% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 218% | 0% |
Trigger conditions:
Not for:
Time normalization:
NOW_ET using NIST/time.gov semantics (America/New_York, ISO-8601)NOW_ET for all citation access datesInput validation:
project_type must be one of: library, console, web-api, blazor, wpf, mauidotnet_version must be one of: 6.0, 7.0, 8.0test_framework must be one of: xunit, nunit, mstestproject_name must be valid .NET identifier (PascalCase recommended)Source freshness:
Fast path for common cases:
ProjectName/ src/ ProjectName/ ProjectName.csproj Class1.cs tests/ ProjectName.Tests/ ProjectName.Tests.csproj UnitTest1.cs ProjectName.sln .gitignore README.md
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>
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.
Extended configuration with testing and web frameworks:
xUnit accessed 2025-10-26 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 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>
StyleCop + Roslyn Analyzers accessed 2025-10-26 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
Minimal API accessed 2025-10-26 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();
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>
Deep configuration for NuGet packaging and production:
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>
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>
xml <PropertyGroup> <PublishAot>true</PublishAot> <InvariantGlobalization>true</InvariantGlobalization> <JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault> </PropertyGroup>
Publish command: bash dotnet publish -c Release -r linux-x64 --self-contained
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
.github/workflows/dotnet.yml name: .NET CI
on: push: branches: main ] pull_request: branches: main ]
jobs: build: runs-on: ubuntu-latest steps:
uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x
run: dotnet restore
run: dotnet build --no-restore
run: dotnet test --no-build --verbosity normal --collect:"XPlat Code Coverage"
uses: codecov/codecov-action@v4
Directory.Build.props (applies to all projects): xml <Project> <PropertyGroup> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> <AnalysisMode>AllEnabledByDefault</AnalysisMode> <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> <EnableNETAnalyzers>true</EnableNETAnalyzers> </PropertyGroup> </Project>
Project Type Selection:
Test Framework Selection:
Abort Conditions:
project_name (contains spaces, special chars) → error.NET Version Selection:
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:
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:
examples/CliExample.cs (22 lines) - System.CommandLine, async/await, file I/Oexamples/ApiExample.cs (30 lines) - ASP.NET Core endpoints, concurrent collectionsTemplate Resources (see resources/)
Library.csproj / Console.csproj / WebApi.csprojTests.csproj with xUnit, Moq, FluentAssertions / ExampleTest.csNuGetPackage.csproj - complete NuGet metadata and SourceLinkToken Budgets:
Safety:
Auditability:
Determinism:
Performance:
Official Documentation (accessed 2025-10-26):
Testing:
Build Tools:
Best Practices:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-12 | pass→pass | 12,660 | 14,083 | +11% | 1 | 1 | 0% | 2,652 | 8,500 | +221% | 0 | 0 | — |
case-01 | fail→pass | 13,913 | 14,265 | +3% | 1 | 1 | 0% | 3,948 | 8,734 | +121% | 0 | 0 | — |
case-02 | fail→pass | 14,296 | 17,289 | +21% | 1 | 1 | 0% | 3,762 | 9,899 | +163% | 0 | 0 | — |
case-03 | fail→pass | 24,411 | 17,346 | -29% | 1 | 1 | 0% | 6,225 | 9,383 | +51% | 0 | 0 | — |
case-04 | fail→pass | 9,837 | 8,554 | -13% | 1 | 1 | 0% | 2,446 | 7,316 | +199% | 0 | 0 | — |
case-05 | fail→pass | 11,460 | 13,730 | +20% | 1 | 1 | 0% | 2,677 | 8,501 | +218% | 0 | 0 | — |
case-06 | pass→pass | 6,855 | 14,487 | +111% | 1 | 1 | 0% | 1,740 | 9,012 | +418% | 0 | 0 | — |
case-07 | fail→pass | 15,687 | 15,794 | +1% | 1 | 1 | 0% | 3,562 | 9,442 | +165% | 0 | 0 | — |
case-08 | fail→pass | 12,897 | 16,649 | +29% | 1 | 1 | 0% | 3,393 | 9,289 | +174% | 0 | 0 | — |
case-09 | fail→pass | 18,570 | 14,270 | -23% | 1 | 1 | 0% | 4,369 | 8,628 | +97% | 0 | 0 | — |
case-10 | fail→pass | 6,733 | 10,639 | +58% | 1 | 1 | 0% | 1,339 | 7,401 | +453% | 0 | 0 | — |
case-11 | pass→pass | 9,134 | 14,190 | +55% | 1 | 1 | 0% | 2,312 | 8,415 | +264% | 0 | 0 | — |
case-13 | pass→pass | 14,024 | 13,678 | -2% | 1 | 1 | 0% | 3,033 | 8,872 | +193% | 0 | 0 | — |
case-14 | pass→pass | 11,232 | 11,552 | +3% | 1 | 1 | 0% | 2,839 | 7,866 | +177% | 0 | 0 | — |
case-15 | fail→pass | 15,544 | 13,430 | -14% | 1 | 1 | 0% | 3,533 | 8,066 | +128% | 0 | 0 | — |
case-16 | fail→pass | 5,939 | 10,046 | +69% | 1 | 1 | 0% | 1,225 | 6,843 | +459% | 0 | 0 | — |
case-17 | fail→fail | 8,297 | 8,164 | -2% | 1 | 1 | 0% | 1,740 | 6,828 | +292% | 0 | 0 | — |
case-18 | fail→pass | 20,949 | 11,513 | -45% | 1 | 1 | 0% | 4,919 | 7,141 | +45% | 0 | 0 | — |
case-19 | fail→pass | 3,386 | 13,819 | +308% | 1 | 1 | 0% | 627 | 8,314 | +1226% | 0 | 0 | — |
case-20 | fail→pass | 12,928 | 16,967 | +31% | 1 | 1 | 0% | 3,049 | 8,729 | +186% | 0 | 0 | — |
case-21 | fail→fail | 16,381 | 14,805 | -10% | 1 | 1 | 0% | 3,288 | 7,845 | +139% | 0 | 0 | — |
case-22 | pass→pass | 15,303 | 17,479 | +14% | 1 | 1 | 0% | 2,841 | 9,180 | +223% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +64 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.