.cursor/skills/dotnet-version-detection/SKILL.md
Project has .csproj, global.json, or Directory.Build.props. Detects TFMs and SDK versions.
npx skillsauth add AGIBuild/Fulora dotnet-version-detectionInstall 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.
Detects .NET version information from project files and provides version-specific guidance. This skill runs first before any .NET development work. All other skills depend on the detected version to adapt their guidance.
Cross-cutting skill referenced by [skill:dotnet-advisor] and virtually all specialist skills. See also [skill:dotnet-file-based-apps] for .NET 10+ file-based apps that run without a .csproj.
Read project files in this strict order. Higher-numbered sources are lower priority. Stop falling through once a TFM is resolved.
<TargetFramework> in .csproj (highest priority)Read the nearest .csproj file to the current working file/directory.
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
If found and the value is a literal TFM (e.g., net10.0, not $(SomeProperty)), this is the authoritative TFM. Report it and proceed to additional detection (Step 5).
If the value is an MSBuild property expression (starts with $(), skip to Step 4 for unresolved property handling.
<TargetFrameworks> in .csproj (multi-targeting)<PropertyGroup>
<TargetFrameworks>net8.0;net10.0</TargetFrameworks>
</PropertyGroup>
If found:
Directory.Build.props shared TFMIf no <TargetFramework> or <TargetFrameworks> found in the .csproj (or if the .csproj inherits from shared props), read Directory.Build.props in the current directory or any parent directory up to the solution root.
<!-- Directory.Build.props -->
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
If found, use this as the TFM. Note: per-project .csproj values override Directory.Build.props.
If the TFM value is an MSBuild property expression rather than a literal:
<TargetFramework>$(MyCustomTfm)</TargetFramework>
Emit warning:
Warning: Unresolved MSBuild property
$(MyCustomTfm). Cannot determine TFM statically. Falling back to SDK version fromglobal.json.
Then fall through to global.json SDK version (Step 4a) or dotnet --version (Step 4b).
global.json SDK version{
"sdk": {
"version": "10.0.100"
}
}
Map SDK version to approximate TFM:
8.0.xxx -> net8.09.0.xxx -> net9.010.0.xxx -> net10.011.0.xxx-preview.x -> net11.0Report: "Inferred TFM from global.json SDK version. Verify actual TFM in project file."
dotnet --version (last resort)If no global.json exists, use dotnet --version output to infer SDK version. Same mapping as 4a.
Report: "Inferred TFM from installed SDK version. No global.json or .csproj found. Consider creating a project with dotnet new."
After resolving the TFM, also check these files for supplementary version information. Always perform these checks regardless of which precedence step resolved the TFM.
global.json SDK VersionEven if TFM was resolved from .csproj, read global.json for:
sdk.version -- the pinned SDK versionsdk.rollForward -- the rollForward policy (e.g., latestFeature, latestPatch)Report the SDK version alongside the TFM. Flag inconsistencies:
Warning: TFM
net10.0butglobal.jsonpins SDK9.0.100. The project targets a newer framework than the pinned SDK. Updateglobal.jsonor verify the build environment has the correct SDK.
Check for explicit <LangVersion> in .csproj or Directory.Build.props:
<LangVersion>preview</LangVersion>
preview -- report "C# preview features enabled. Unlocks the next C# version available in the installed SDK (e.g., C# 15 preview features with a .NET 11 preview SDK)."latest -- report the default C# version for the detected TFM12.0) -- report that version, warn if it's below the TFM defaultCheck for these properties in .csproj or Directory.Build.props:
EnablePreviewFeatures:
<EnablePreviewFeatures>true</EnablePreviewFeatures>
Report: ".NET preview features enabled. Access to preview APIs and types."
Runtime-async feature flag (.NET 11+):
<Features>$(Features);runtime-async=on</Features>
Report: "Runtime-async enabled. Async/await uses runtime-level execution instead of compiler state machines."
Note: runtime-async requires <EnablePreviewFeatures>true</EnablePreviewFeatures> as well.
If multi-targeting was detected (Step 2), also note:
After detection, present results in this structured format:
.NET Version Detection Results
==============================
TFM: net10.0 (or net8.0;net10.0 for multi-targeting)
Highest TFM: net10.0
C# Version: 14 (default for net10.0)
SDK Version: 10.0.100 (from global.json)
Preview Features: none
Runtime-Async: not enabled
Warnings: none
Guidance: This project targets .NET 10 LTS with C# 14. Use modern patterns
including field-backed properties, collection expressions, and primary
constructors. All guidance will target net10.0 capabilities.
For multi-targeting:
.NET Version Detection Results
==============================
TFMs: net8.0;net10.0
Highest TFM: net10.0
C# Version: 14 (default for highest TFM)
SDK Version: 10.0.100 (from global.json)
Preview Features: none
Warnings: net8.0 reaches end of support Nov 2026
Guidance: Multi-targeting net8.0 and net10.0. Guide on net10.0 patterns.
For net8.0 compatibility, use PolySharp/Polyfill for language features.
See [skill:dotnet-multi-targeting] for detailed polyfill guidance.
If no .csproj exists in the workspace:
.sln or .slnx files and look for referenced projectsglobal.json for SDK version (Step 4a) and infer TFM from itglobal.json, use dotnet --version (Step 4b) to infer TFMdotnet new to create a project."If <TargetFramework> contains $(PropertyName):
$(PropertyName). Cannot determine TFM from static analysis."global.json SDK version, then dotnet --versiondotnet --list-sdks or dotnet msbuild -getProperty:TargetFrameworkIf .csproj says net10.0 but global.json pins SDK 9.0.100:
global.json to matchIf dotnet --version fails or is not found:
.fsproj and .vbprojThe same detection logic applies to F# (.fsproj) and VB.NET (.vbproj) projects. The <TargetFramework> element is identical across all .NET project types.
Version detection results should be cached per-project (per .csproj path). Re-detect when:
.csproj, Directory.Build.props, or global.json file is modifiedLast updated: 2026-02-11
This reference data maps .NET versions to their C# language versions, key features, and support lifecycle. This section is separate from the detection logic above -- detection determines which version is in use; this data maps that version to available features.
| .NET Version | Status | C# Version | TFM | Support End | Notes | |-------------|--------|-------------|-----|-------------|-------| | .NET 8 | LTS (active) | C# 12 | net8.0 | Nov 2026 | Approaching end of support | | .NET 9 | STS | C# 13 | net9.0 | May 2026 | Approaching end of support | | .NET 10 | LTS (current) | C# 14 | net10.0 | Nov 2028 | Recommended for new projects | | .NET 11 | Preview 1 | C# 15 (preview) | net11.0 | TBD (expected STS end: ~May 2028 if Nov 2026 GA) | Preview only -- not for production |
C# 12 (net8.0)
[1, 2, 3])ref readonly parametersusingC# 13 (net9.0)
params collections (any collection type)Lock type (System.Threading.Lock)\eref and unsafe in iterators/asyncC# 14 (net10.0)
field contextual keyword)nameof for unbound generic typesSpan<T> in more contextsallows ref struct anti-constraint for genericsC# 15 preview (net11.0)
with() syntax for capacity/comparers):
List<int> nums = [with(capacity: 32), 0, ..evens, ..odds];
HashSet<string> names = [with(comparer: StringComparer.OrdinalIgnoreCase), "Alice"];
These features are available when net11.0 TFM is detected with preview features enabled:
<EnablePreviewFeatures>true</EnablePreviewFeatures> + <Features>$(Features);runtime-async=on</Features>)System.IO.Compression.Zstandard (2-7x faster than Brotli/Deflate)System.Numerics.BFloat16 for AI/ML workloadsConnectAlgorithm.Parallel for dual-stack networkingWhen reporting version information, include lifecycle context:
tools
Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.
testing
Security headers configuration and best practices for ASP.NET Core Razor Pages applications. Covers CSP, HSTS, X-Frame-Options, and comprehensive security middleware setup. Use when configuring security headers in ASP.NET Core applications, implementing Content Security Policy (CSP), or setting up HSTS and other security-related HTTP headers.
development
Reviews designs and business goals for security vulnerabilities, data protection (in transit/at rest), authorization, and compliance alignment. Use when the user asks for a security review, threat modeling, attack surface analysis, data leakage prevention, or compliance/security assessment.
development
Best practices for building production-grade ASP.NET Core Razor Pages applications. Focuses on structure, lifecycle, binding, validation, security, and maintainability in web apps using Razor Pages as the primary UI framework. Use when building Razor Pages applications, designing PageModels and handlers, implementing model binding and validation, or securing Razor Pages with authentication and authorization.