skills/dotnet-new-app-slnx/SKILL.md
Scaffold a new .NET standalone application solution following codebelt engineering conventions. Use this skill when the user wants to create a new .NET application — Console, Web, or Worker service. Also use when the user mentions "new app", "new console app", "new web api", "new mvc app", "new razor app", "new web app", "new worker service", "scaffold app", "dotnet new web", "dotnet new webapi", "dotnet new mvc", "dotnet new webapp", "dotnet new worker", "dotnet new console", or wants a .NET application project with CI/CD pipeline, functional tests, and code quality tooling. ALWAYS use this skill when asked to scaffold or create a new .NET application solution.
npx skillsauth add codebeltnet/agentic dotnet-new-app-slnxInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Field | Value |
|-------|-------|
| Repo | https://github.com/codebeltnet/agentic |
| Branch | main |
| Shared assets root | skills/dotnet-new-app-slnx/assets/shared |
| Raw base URL | https://raw.githubusercontent.com/codebeltnet/agentic/main/skills/dotnet-new-app-slnx/assets/shared |
| Asset manifest | assets/shared.manifest.json |
This metadata is the single source of truth for restoring any file the installer may have dropped. Use it immediately — do not spend cycles confirming absence multiple ways first.
Scaffold new .NET standalone application solutions following the codebeltnet engineering conventions — the same pattern used across codebeltnet. Produces a fully wired solution with CI pipeline, centralized build config, semantic versioning, code quality tooling, and proper folder structure.
CRITICAL: All application projects must use the
Codebelt.Bootstrapper.*framework — never vanillaWebApplication.CreateBuilder()or rawHost.CreateDefaultBuilder(). The bootstrapper provides a uniform, convention-drivenProgram.cs(andStartup.csfor classic hosting). The asset templates inassets/app/already wire this up correctly — always copy from templates, never write Program.cs from scratch.
If a generated app fails because a bootstrapper type from the copied asset template does not resolve, first verify the copied template imports the correct
Codebelt.Bootstrapper.*namespace and that the matching package reference is present. If the bootstrapper type still cannot be resolved, halt and report the template/package mismatch. Do not substitute vanilla .NET hosting code as a workaround.
This skill produces a complete solution scaffold — project structure, build config, CI pipeline, governance docs, and bootstrapper-wired entry points. It does not generate application logic (endpoints, services, controllers, middleware). The scaffold is the foundation; the user adds their code on top.
Generate the scaffold in the user's current working directory. Do not create an extra top-level {REPO_SLUG} or {SOLUTION_NAME} folder unless the user explicitly asks for a nested output folder.
The scaffold is incomplete unless it produces all required artifacts for the selected host types. These are not optional, and they must not be silently skipped:
{SOLUTION_NAME}.slnx with the original user-facing casing preservedsrc/ project or projectstest/Directory.Build.propsDirectory.Packages.propstestenvironments.jsonassets/shared/If you cannot generate any required artifact from the documented templates and rules, halt and report the mismatch instead of improvising, omitting the file, or substituting a weaker fallback.
Treat the scaffold as a fidelity copy of the documented template set, not a "best effort" approximation. Do not cherry-pick only the files that seem important, and do not patch over structural problems by pushing configuration down into individual project files.
When to use this skill: The user wants a properly structured .NET solution from scratch — with conventions, CI, and tooling baked in from day one.
When NOT to use this skill: The user wants a quick, throwaway backend or a thin adapter layer. If the request is for a minimal placeholder (e.g. "just a basic API proxy"), do not invoke this skill — use standard .NET CLI tooling instead (dotnet new web) and let the user decide if they want to upgrade to a full scaffold later.
Read FORMS.md and collect all parameters by presenting each field to the user one at a time using the agent's native input mechanism when the host supports it. If the host does not render native form controls, follow the deterministic plain-text fallback defined in FORMS.md instead of improvising your own questioning style. Do not proceed to Step 2 until all required fields are collected and the user confirms the summary.
For fields that already present a recommended default or computed_default, treat a blank response as accepting that shown value. Do not get stuck in a clarification loop for root_namespace, target_framework, or any other defaultable field just because the user did not type over the recommended choice.
Consistency matters more than creativity during parameter collection. Do not paraphrase field prompts, merge questions, or switch interaction styles mid-flow.
Treat Web as the host family. When Web is selected, collect exactly one web_variant. If the user already said web api, mvc, razor, or web app, preselect the matching web_variant instead of asking them to repeat it.
If the user already said console or worker, preselect that host type and continue with the next unresolved field instead of re-asking app_host_types. In plain-text fallback mode, begin each step directly with the next Field: <field-name> block from FORMS.md; do not add extra conversational lead-ins between fields.
For target_framework, compute one quick-pick per generally supported non-preview .NET channel from https://raw.githubusercontent.com/dotnet/core/refs/heads/main/release-notes/releases-index.json, sorted newest to oldest before free text.
Filter to .NET entries whose support-phase is active or maintenance, exclude preview channels, and let the user choose any currently supported LTS or STS track.
For each selected host type, derive {AppType} as follows:
Console host type → {AppType} = ConsoleWeb + Empty Web → {AppType} = WebWeb + Web API → {AppType} = ApiWeb + MVC → {AppType} = MvcWeb + Web App / Razor → {AppType} = WebAppWorker host type → {AppType} = WorkerUse only one web-family variant per scaffold run. The solution may still include Console and/or Worker alongside that one web-family project.
Read references/app.md for the app-specific project structure, template file mapping, hosting patterns (Startup vs Minimal), .slnx format, and per-host-type NuGet packages.
Before writing Directory.Packages.props, resolve every *_VERSION placeholder in that file to the latest stable listed version for its matching package ID on NuGet.org.
When PowerShell is available, prefer the deterministic helper in scripts/resolve-package-versions.ps1 over manual lookup. By default it resolves placeholders from this skill's own assets/shared/Directory.Packages.props, so a normal scaffold run only needs -TargetFramework. Treat its JSON output as the source of truth for package placeholders.
https://api.nuget.org/v3/index.json to discover the package metadata endpointsMicrosoft.AspNetCore.OpenApi and Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation, resolve the latest stable version whose major matches the selected {TARGET_FRAMEWORK} major. Example: net9.0 must not get 10.x ASP.NET packages.Directory.Packages.props is the authoritative source of NuGet package versions for the generated app scaffold. Do not inline Version= attributes into .csproj files or Directory.Build.props as a workaround for restore or build issues.This includes shared and host-specific app packages such as:
Codebelt.Extensions.Xunit.AppMicrosoft.NET.Test.SdkMinVercoverlet.collectorcoverlet.msbuildxunit.v3xunit.v3.runner.consolexunit.runner.visualstudioCodebelt.Bootstrapper.ConsoleCodebelt.Bootstrapper.WebCodebelt.Bootstrapper.WorkerMicrosoft.AspNetCore.OpenApiMicrosoft.AspNetCore.Mvc.Razor.RuntimeCompilationMicrosoft.Extensions.HostingWhen copying template files, replace these placeholders in file contents:
| Placeholder | Value |
|-------------|-------|
| {SOLUTION_NAME} | Solution name (e.g. PaymentService) |
| {ROOT_NAMESPACE} | Root namespace prefix (e.g. Acme) |
| {REPO_SLUG} | Derived from solution name (lowercased, e.g. PaymentService → paymentservice) |
| {TARGET_FRAMEWORK} | e.g. net10.0 (single target) |
| {AppType} | Per-host-type output suffix: Console, Web, Api, Mvc, WebApp, or Worker |
| {UBUNTU_TESTRUNNER_TAG} | Docker runner image tag derived from {TARGET_FRAMEWORK}, e.g. codebeltnet/ubuntu-testrunner:10 |
For generated solution filenames, preserve the user-facing {SOLUTION_NAME} casing exactly. The solution file must be named {SOLUTION_NAME}.slnx, not {REPO_SLUG}.slnx and not any lowercased variant.
Directory.Packages.props also contains package-specific placeholders such as {CODEBELT_BOOTSTRAPPER_WEB_VERSION}, {MICROSOFT_ASPNETCORE_OPENAPI_VERSION}, {MICROSOFT_ASPNETCORE_MVC_RAZOR_RUNTIMECOMPILATION_VERSION}, {MICROSOFT_EXTENSIONS_HOSTING_VERSION}, and {MICROSOFT_NET_TEST_SDK_VERSION}. Resolve each of them from NuGet.org in Step 3 before writing the final file.
For Microsoft.AspNetCore.OpenApi and Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation, the resolved stable version must stay aligned with the selected {TARGET_FRAMEWORK} major version instead of blindly using the latest stable overall.
Keep Directory.Packages.props limited to packages that are actually referenced by the copied app and test templates for the selected host types, plus the shared MinVer package used for app versioning. Do not carry unused library-only or benchmark-only package versions into app scaffolds.
If restore/build fails, fix the central package management inputs instead of bypassing them. Do not replace centralized package versions with ad-hoc inline versions in generated project files.
TargetFramework belongs in the generated root Directory.Build.props, not in the generated app or test .csproj files. Do not "repair" framework resolution by adding <TargetFramework> to src/**/*.csproj or test/**/*.csproj; if framework resolution fails, fix the copied root build props or halt and report the mismatch.
After writing Directory.Packages.props, re-check the generated versions against the Step 3 lookup output before finalizing the scaffold. Do not assume an earlier guess was correct just because the project restores.
Generate files in this order:
Copy every file from assets/shared/ to the project root, preserving directory structure. Do not copy assets/shared.manifest.json — it is a skill-internal file used only for asset validation and restoration, and must never appear in a generated solution. Treat the current working directory as that project root. Apply placeholder substitution (Step 4) to all file contents during the copy.
Do this as a recursive, dotfile-aware copy. Hidden folders and files under assets/shared/ are part of the scaffold and must not be skipped. In particular, copy assets/shared/.bot/README.md as a real file in the generated repo; do not replace it with a synthetic .gitkeep or placeholder note.
Asset mismatch policy — pivot immediately to upstream. The npx skills add installer silently strips dot-prefixed entries (.bot/, .github/, .editorconfig, .gitattributes, .gitignore). Do not spend time re-proving what is absent. The moment any entry from assets/shared.manifest.json is missing from the installed skill copy, run scripts/restore-missing-shared-assets.ps1 to fetch every missing file directly from the upstream repository in one step, then continue. If PowerShell is unavailable, use the raw base URL in the Upstream Source table above to download each missing file manually. If upstream fetch fails, halt and report — do not substitute placeholders.
Do not selectively copy only "key" shared files. The intended output includes the complete shared asset inventory, including .gitignore, .gitattributes, AGENTS.md, CHANGELOG.md, .github/, and .bot/, in addition to the build and package-management files.
Exception: update testenvironments.json with the derived {UBUNTU_TESTRUNNER_TAG} instead of leaving a hardcoded runner image tag in place. Keep the WSL-Ubuntu entry and use the Docker major-tag convention documented for the shared Ubuntu test runner images.
testenvironments.json is a required shared scaffold asset. Do not silently omit it. If you cannot generate it from the shared template plus {UBUNTU_TESTRUNNER_TAG}, halt and report the mismatch instead of skipping the file.
Exception: if the user selected multiple host types, rewrite the root README.md running section to list one dotnet run --project ... command per generated host project instead of leaving a single {AppType} placeholder example.
Directory.Build.propsCopy assets/app/Directory.Build.props to the project root, applying placeholder substitution.
Overwrite the shared CI pipeline with assets/app/.github/workflows/ci-pipeline.yml. Apps have a simplified pipeline (build + test only).
Follow the variant guide (Step 2) for the remaining files. Do not write these files from scratch — use the asset templates in assets/app/ as the source of truth:
.csproj files → copy from assets/app/{type}.csproj for Console and Worker, or from the selected web variant asset (assets/app/web.csproj, assets/app/web-api.csproj, assets/app/web-mvc.csproj, or assets/app/webapp.csproj)Program.cs → copy from the matching asset folder's Program.minimal.cs (Minimal pattern) or Program.startup.cs (Startup pattern)Startup.cs → copy from the matching asset folder's Startup.cs (Startup pattern only)Worker.cs → copy from assets/app/worker/Worker.cs whenever generating a Worker host typeControllers/ plus Views/ from assets/app/web-mvc/ whenever generating the MVC variantPages/ from assets/app/webapp/ whenever generating the Web App / Razor variant.csproj → copy from assets/app/test.csprojApply placeholder substitution (Step 4) to all copied files. The user's business logic, endpoints, and service registrations go into Startup.cs (Startup pattern), the Program.cs configure methods (Minimal pattern), the MVC controller/view starter, the Razor Pages starter, or the default Worker.cs loop for Worker services — but the bootstrapper base classes must remain intact.
Generate the .slnx solution file and functional test project structure per the variant guide.
The .slnx file is required even for single-host scaffolds. Do not skip it just because the generated solution only contains one src/ project and one test/ project.
After generating, verify:
.slnx references all generated src/ and test/ projects{SOLUTION_NAME}.slnx with the original user-facing casing preservedassets/shared.manifest.json exists in the generated repo at its declared relative path (this covers all dotfiles and dotfolders)scripts/restore-missing-shared-assets.ps1 was run (or files fetched manually from the upstream raw URL) — not diagnosed iterativelyDirectory.Packages.props lists all <PackageReference> packages used in the solution (including host-type-specific packages)Directory.Packages.props contains concrete version numbers with no unresolved *_VERSION placeholders.csproj file or Directory.Build.props contains ad-hoc inline Version= attributes for packages that are supposed to be centrally managed by Directory.Packages.props.csproj file introduces <TargetFramework>; framework selection stays centralized in the generated root Directory.Build.propsci-pipeline.yml has the correct settings (build + test only)README.md, CHANGELOG.md, .github/CODE_OF_CONDUCT.md, .github/CONTRIBUTING.md.editorconfig is present with file-scoped namespace enforcementAGENTS.md references .bot/ and coding guidelines.github/copilot-instructions.md has project-specific patterns.bot/ folder exists and is listed in .gitignore.bot/README.md exists in the generated repo and came from the shared asset templatetestenvironments.json uses the major-tag codebeltnet/ubuntu-testrunner:{major} convention for the selected target frameworkProgram.cs only for Minimal, Program.cs + Startup.cs for Startup)Web API is the default web_variant when the user asked for a generic Web appEmpty Web uses the Web suffix, Web API uses Api, MVC uses Mvc, and Web App / Razor uses WebAppWorker.csIf the scaffold is generated outside a git-initialized and tagged repository, expect MinVer to report a placeholder pre-release version such as 0.0.0-alpha.0 until the user initializes git and adds a version tag. Treat that as expected bootstrap state, not as a reason to remove MinVer or change the generated versioning setup.
Summarize what was generated, note any manual steps, and mention the expected MinVer bootstrap behavior when the scaffold was created outside an initialized/tagged git repo.
testing
Generate GitHub release notes by summarizing all commits and pull requests between two Git tags, branches, or the current branch and the upstream default branch. Use when the user asks to write release notes, generate release notes, draft a GitHub release, create release notes from tags, summarize changes between versions, summarize the current branch, or provides a GitHub compare URL. Trigger phrases: "release notes", "generate release notes", "what changed between", "summarize changes from v1 to v2", "GitHub release", "summarize this branch", compare URLs like "github.com/owner/repo/compare/v1...v2". When no explicit input is given, detects the current branch and compares against the upstream default branch automatically.
development
Classifies .NET library or NuGet package changes and recommends the correct release bump: Major, Minor, or Patch. Applies both Semantic Versioning (MAJOR.MINOR.PATCH) and .NET assembly/file versioning (Major.Minor.Build.Revision), grounded in Microsoft’s official .NET library compatibility rules. Use when evaluating the current branch, breaking changes, API diffs, public API changes, dependency updates, TFM/platform support, interface or enum changes, overloads, analyzers, source generators, or binary/source/behavioral/design-time/backwards compatibility. When no explicit change details or compare range are provided, inspects the current Git branch and compares it against the upstream default branch automatically. Always returns structured compatibility reasoning with the recommendation.
documentation
Generate source-grounded repository digest markdown from deterministic local evidence bundles. Use when the user asks to create, refresh, or complete repo/package digests, family or project overview pages, .bot/digests output, digest workspace workflows, or result/Index.md plus result/{PackageName}.md files for any repository URL. The skill runs its bundled .NET file-based evidence generator over a git clone, separates authoritative XML evidence from Markdown prompts and reading aids, writes package digests first, then writes the overview from completed package digests, and enforces complete-read grounding and no-invention rules even when file output is capped.
testing
Turn many commits into a curated grouped squash summary compatible with the opinionated wording style of git-visual-commits. Use when the user asks to squash a branch into a concise summary, write a squash-and-merge summary, summarize this branch, summarize a commit range or PR as grouped lines, clean up noisy commit history, or asks for a curated summary without committing. For normal squash-and-merge requests, default to the full current feature branch from merge-base to HEAD against the base branch instead of a same-named tracking remote, include commits from all authors unless the user explicitly narrows by author, and do not ask for yolo because the skill is read-only. Returns grouped lines only, preserves identifiers, merges overlap, drops noise, and avoids changelog wording.