csharp-scripts
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file…
Calculates CRAP (Change Risk Anti-Patterns) for a named .NET method, class, or file. USE FOR: explicit CRAP calculation or coverage-and-complexity risk within that named target, including which tests to prioritize. DO NOT USE FOR: project-wide coverage/CRAP, plateaus, or
$ npx -y skills add dotnet/skills --skill crap-score --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/crap-scoreContext preview
The summary Claude sees to decide when to auto-load this skill.
Calculates CRAP (Change Risk Anti-Patterns) for a named .NET method, class, or file. USE FOR: explicit CRAP calculation or coverage-and-complexity risk within that named target, including which tests to prioritize. DO NOT USE FOR: project-wide coverage/CRAP, plateaus, or
name: crap-score description: > Calculates CRAP (Change Risk Anti-Patterns) for a named .NET method, class, or file. USE FOR: explicit CRAP calculation or coverage-and-complexity risk within that named target, including which tests to prioritize. DO NOT USE FOR: project-wide coverage/CRAP, plateaus, or project-wide blockers/priorities (coverage-analysis); behavioral/pseudo-mutation gaps (test-gap-analysis); writing tests; test runs without CRAP context. license: MIT
Calculate CRAP (Change Risk Anti-Patterns) scores for .NET methods to identify code that is both complex and undertested.
The CRAP score combines **cyclomatic complexity** and **code coverage** into a single metric:
$$\text{CRAP}(m) = \text{comp}(m)^2 \times (1 - \text{cov}(m))^3 + \text{comp}(m)$$
Where:
| CRAP Score | Risk Level | Interpretation | |------------|------------|----------------| | < 5 | Low | Simple and well-tested | | 5 to < 15 | Moderate | Acceptable for most code | | 15 to 30 | High | Needs more tests or simplification | | > 30 | Critical | Refactor and add coverage urgently |
A method with 100% coverage has CRAP = complexity (the minimum). A method with 0% coverage has CRAP = complexity^2 + complexity.
| Input | Required | Description | |-------|----------|-------------| | Target scope | Yes | Method name, class name, or file path to analyze | | Test project path | No | Path to the test project. Defaults to discovering test projects in the solution. | | Source project path | No | Path to the source project under analysis |
If no coverage data exists yet, classify the test project first. For SDK-style projects, run `dotnet test` with coverage collection. For classic non-SDK projects (`ToolsVersion`, explicit compile items, or `packages.config`), use only a repository-provided coverage command that emits Cobertura. If none exists, ask for Cobertura XML and stop; do not migrate the project or inject an SDK-style coverage package. CRAP scores always require real coverage data.
Check the test project's `.csproj` for the coverage package, then run the appropriate command:
| Coverage Package | Command | Output Location | |---|---|---| | `coverlet.collector` | `dotnet test --collect:"XPlat Code Coverage" --results-directory ./TestResults` | Typically under `TestResults/<guid>/coverage.cobertura.xml`. Search recursively under the results directory (for example, `TestResults/**/coverage.cobertura.xml`) or use any explicit coverage path the user provides. | | `Microsoft.Testing.Extensions.CodeCoverage` (.NET 9) | `dotnet test -- --coverage --coverage-output-format cobertura --coverage-output ./TestResults` | `--coverage-output` path | | `Microsoft.Testing.Extensions.CodeCoverage` (.NET 10+) | `dotnet test --coverage --coverage-output-format cobertura --coverage-output ./TestResults` | `--coverage-output` path |
**Guessed coverage produces wrong CRAP scores, which is worse than no answer.** For a classic project with no repository coverage command or existing report, stop here and request Cobertura; do not use any collection fallback below.
For SDK-style projects, if the first command yields no Cobertura XML, work down this collection list before giving up:
1. For SDK-style projects only, add a provider if none is referenced: `dotnet add <test.csproj> package coverlet.collector`, then re-run. Never use this fallback for `packages.config` or classic non-SDK projects. 2. Use the standalone collector, which works even when the test host or a shared assembly blocks the in-proc collector: `dotnet tool install --global dotnet-coverage` then `dotnet-coverage collect -f cobertura -o coverage.cobertura.xml "dotnet test <test.csproj>"`.
For any project type, if a real binary `.coverage` report already exists, convert or summarize that existing data with ReportGenerator:
3. Convert the existing report: `dotnet tool install --global dotnet-reportgenerator-globaltool` then `reportgenerator -reports:<file> -targetdir:cov -reporttypes:Cobertura`. 4. Tests fail but still run? Coverage is collected from the tests that executed — continue with that data and note the failures.
If every path fails, **report that coverage could not be collected, show the commands you tried and their errors, and stop.** Report complexity on its own if useful, but never publish a CRAP number derived from an assumed coverage percentage.
Before using a report, verify that it parses, contains at least one class and method, and contains the requested target. An empty report or a report that omits the target is failed collection or filtering, not 0% coverage. Regenerate coverage when possible; otherwise stop without publishing a CRAP score.
If the user supplies an existing report, state that it was not regenerated. Do not describe its data as current unless its provenance is established by running the repository's coverage command in this analysis.
Prefer a machine-produced per-method complexity from a repository-provided code metrics re
This repository contains the .NET team's curated set of core skills and custom agents for coding agents. For information about the Agent Skills standard, see agentskills.io.
Repo: dotnet/skills
Run file-based C# apps with the .NET CLI when the user explicitly wants C#/.NET code without creating a project. Use for C# language/API experiments, one-file…
Correctly call native (C/C++) libraries from .NET using P/Invoke and LibraryImport. Covers function signatures, string marshalling, memory lifetime,…
Set up NuGet trusted publishing (OIDC) on a GitHub Actions repo — replaces long-lived API keys with short-lived tokens. USE FOR: trusted publishing, NuGet…
Design, implement, optimize, and review SIMD code in .NET. USE FOR: vectorizing scalar loops with TensorPrimitives, Vector64/128/256/512, or platform hardware…
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent…
Configure OpenTelemetry distributed tracing, metrics, and logging in ASP.NET Core using the .NET OpenTelemetry SDK. Use when adding observability, setting up…