tomware.Cyclo 0.1.0

dotnet tool install --global tomware.Cyclo --version 0.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local tomware.Cyclo --version 0.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=tomware.Cyclo&version=0.1.0
                    
nuke :add-package tomware.Cyclo --version 0.1.0
                    

Cyclo

A CLI for calculating the cyclomatic complexity of code.

Maintainers

  • Thomas Duft

Usage

Analyze a C# source file, project, solution, or directory:

dotnet run --project src/Cyclo.Cli -- analyze <path> [options]

Supported paths are directories, .slnx solution files, .csproj project files, and individual .cs files. For example:

dotnet run --project src/Cyclo.Cli -- analyze src/MyProject --threshold 8 --fail-on-threshold

Options

Option Description
-t, --threshold <integer> Maximum allowed cyclomatic complexity. Must be a positive integer; defaults to 10. A result is above the threshold only when its complexity is greater than this value.
-o, --output <directory> Generate a Markdown report in the specified directory, creating the directory if needed. Without this option, output is console-only.
--fail-on-threshold Return exit code 2 if any result exceeds the threshold. Without this option, findings do not cause a nonzero exit code.

After a successful analysis, Cyclo prints the result counts and any above-threshold findings in an aligned table. The console table includes complexity, function, source location, project, and target framework, preserving full paths and using - for unavailable context. Only when -o or --output is supplied does it write all analyzed function results to cyclo-report.md in the output directory and print the report path. The Markdown report includes project and target-framework context where available. Invalid input or threshold values, analysis failures, and report-generation failures return exit code 1; successful analysis returns 0 unless --fail-on-threshold is set and findings exceed the threshold.

To also generate a Markdown report:

dotnet run --project src/Cyclo.Cli -- analyze src/MyProject --output ./reports

How complexity is counted

Each result starts at a score of 1. Cyclo reports members with executable block or expression bodies: methods, constructors, destructors, operators, conversion operators, and executable accessors (including init), including executable interface members. An expression-bodied property or indexer produces one getter result. Members with no body and auto-property accessors do not produce results. Top-level statements in a file produce one synthetic <top-level>.<main> result.

The following syntax contributes one point per occurrence:

  • if, while, do, for, and foreach loops, including deconstructing foreach.
  • Each switch-statement case label except default and discard labels, and each switch-expression arm except an arm with a top-level discard pattern.
  • Each catch clause, plus each catch filter and each when guard on a switch case label or switch-expression arm.
  • Each conditional expression (?:) and each conditional access (?. or ?[]).
  • Each &&, ||, ??, and ??= operator.
  • Each and or or pattern combinator.

Decisions inside local functions, lambdas, and anonymous methods are folded into the enclosing member's score; nested functions do not get separate results. Functions that appear only in field, property, or event initializers are not reported or included in a member's score.

Cyclo counts syntax without semantic resolution. Consequently, it does not infer extra decisions from the structure of property or recursive patterns, and LINQ query clauses do not add points by themselves. Explicitly counted operators and pattern combinators still count wherever they occur, including in queries and patterns. A bare _ in a switch case label is treated as a discard; escaped @_ is treated as a constant label.

As general guidance, scores of 1-10 are simple, 11-20 moderate, 21-50 complex, and over 50 untestable. These risk bands are guidance, not the configurable threshold: a result exceeds the threshold only when its score is strictly greater than the selected threshold. Risk bands are not emitted as labels in console output or Markdown reports.

Development checks

CI checks Cyclo's own solution with a maximum complexity of 8. Build and test the current sources in Release before running the same check locally:

./build.sh test
dotnet run --no-build --configuration Release --project src/Cyclo.Cli -- analyze cyclo.slnx --threshold 8 --fail-on-threshold
Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.1.0 49 11/7/2026