dotnet-coupling 0.6.1

dotnet tool install --global dotnet-coupling --version 0.6.1
                    
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 dotnet-coupling --version 0.6.1
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=dotnet-coupling&version=0.6.1
                    
nuke :add-package dotnet-coupling --version 0.6.1
                    

dotnet-coupling

NuGet Version NuGet Downloads CI GitHub Release License: MIT .NET 10

Experimental coupling balance analyzer for C#/.NET projects.

dotnet-coupling scans C# source and reports coupling risks using three dimensions from Vlad Khononov's balancing-coupling model:

  • integration strength
  • distance
  • volatility from Git history

By default, dotnet-coupling runs in syntax mode for broad compatibility. It also provides an opt-in semantic preview for .csproj, .sln, and .slnx inputs so project boundaries and symbol-aware dependencies can be inspected without changing the default contract.

Experimental project

Grades, thresholds, and detected patterns are still being tuned through dogfooding and OSS feedback. Treat the report as decision support, not as a proof that a codebase is free of coupling risk.

Table of Contents

Quick Start

1. Install

dotnet tool install --global dotnet-coupling

2. Analyze

dotnet-coupling ./src
dotnet-coupling --summary ./src
dotnet-coupling --json ./src

3. Gate in CI

dotnet-coupling --check --min-grade B ./src
dotnet-coupling --check --baseline main --fail-on High ./src
dotnet-coupling --sarif --output dotnet-coupling.sarif ./src

Example summary:

Grade: A | Avg Score: 0.79 | Basis: issue-density
Files: 24 | Types: 63 | Couplings: 201 internal / 0 external
Issues: 0 Critical, 0 High, 12 Medium
Git: disabled (--no-git)

What It Reports

The default report highlights the overall grade, average balance score, issue counts, and the most important coupling problems found in the analyzed scope.

The analyzer currently focuses on:

  • structural dependencies observed from source
  • project / assembly / NuGet package boundaries in semantic mode
  • Git co-change data for volatility and hidden coupling heuristics
  • issue patterns such as global complexity, circular dependency, hidden coupling, scattered external coupling, and fan-in / fan-out concentration

Common Commands

# Default text report
dotnet-coupling ./src

# Summary only
dotnet-coupling --summary ./src

# Machine-readable JSON
dotnet-coupling --json ./src

# GitHub Code Scanning compatible SARIF
dotnet-coupling --sarif --output dotnet-coupling.sarif ./src

# Top refactoring candidates
dotnet-coupling --hotspots 10 ./src

# Reverse dependency impact
dotnet-coupling --impact MyApp.Domain.Order --depth 3 ./src

# Semantic member trace
dotnet-coupling --trace Save --mode semantic ./sample.sln

# Shareable and coding-agent reports
dotnet-coupling --markdown --impact Order ./src
dotnet-coupling --ai ./src

# Skip Git history for faster local runs
dotnet-coupling --no-git ./src

# Apply JSON or TOML config
dotnet-coupling --config .coupling.json ./src
dotnet-coupling --config .coupling.toml ./src

# CI gate on minimum grade
dotnet-coupling --check --min-grade B ./src

# Ratchet gate against a baseline branch
dotnet-coupling --check --baseline main --fail-on High ./src

# Opt in to semantic preview for project-aware analysis
dotnet-coupling --mode semantic --summary ./sample.sln

Syntax and Semantic Modes

syntax mode is the default and is the stable compatibility path today.

  • works well against plain source directories
  • avoids workspace-loading prerequisites
  • preserves the established CLI and JSON contract

semantic mode is preview-only and must be enabled explicitly.

  • accepts .csproj, .sln, and .slnx
  • resolves project graph, assembly boundaries, package references, and more symbol-aware dependencies
  • emits recoverable workspace diagnostics when the environment cannot fully load the target

Configuration

JSON and TOML configuration are supported via --config <file>. Automatic discovery checks .coupling.json and coupling.json first, then .coupling.toml and coupling.toml.

Current supported settings include:

  • analysis excludes
  • test project path patterns for issue-noise reduction
  • fan-in and fan-out thresholds
  • temporal coupling thresholds
  • scattered external breadth thresholds
  • ignore rules for paths, namespaces, issue types, and precise issue suppressions
  • domain context for user-supplied core/supporting/generic subdomain categories and expected volatility
  • role context for strategic boundaries and technical areas
  • complexity thresholds and weight for remediation prioritization

TOML keys use snake_case; JSON keeps the existing camelCase schema shape. analysis.test_projects / analysis.testProjects marks test project files. Those couplings remain visible as observed data, but couplings whose source file matches a test project pattern are excluded from active issue detection and grade calculation. Domain context does not infer subdomain categories; it uses only the paths and categories provided in config. Supporting or generic subdomains with high observed Git churn and lower expected volatility are reported as AccidentalVolatility. Subdomain names must be unique. If multiple path patterns match the same component, the first matching subdomain in the config is used. Domain paths are repository/workspace-relative, so moving the config file or passing it with --config does not change their meaning. Summary output and JSON manifest.domainContext show how many components matched configured subdomains and how many AccidentalVolatility issues were produced.

Role context separates strategic boundary meaning from technical scoring hints. strategicRole / strategic_role can describe boundary meanings such as sharedKernel / shared_kernel and remains advisory. domain.areas assigns technical roles such as domainModel, applicationService, adapter, compositionRoot, contract, and testSupport. contract targets and compositionRoot sources reduce over-reporting for intentional contracts and orchestration, so technical roles can affect scores, issue counts, grades, and --check exit codes. Other technical roles are shown in summaries, JSON manifest data, and hotspot reasons without changing scoring.

Use contract for stable API shapes even inside a core subdomain: value objects, identifier types, DTOs, published language models, and shared-kernel contracts. Put these area patterns before broader domainModel patterns because the first matching area wins. Use compositionRoot for Program, Startup, module startup, DI registration, and host bootstrapping code. Summary output and JSON run notes include coverage hints when configured subdomains or technical roles leave components unmatched.

See .coupling.example.json, .coupling.example.toml, and schemas/dotnet-coupling-config-0.2.schema.json.

Baseline Gate

--baseline <ref> compares current issues with a Git ref and classifies them as new, resolved, or unchanged.

With --check --baseline, the gate fails only for new issues at --fail-on severity or higher. If --fail-on is omitted, the baseline gate uses High.

This makes it practical to adopt in an existing codebase without forcing a one-shot cleanup of all historical debt.

For long-lived accepted debt, use .coupling.json ignore.issues with a stable (type, source, target) key and a required reason. Suppressed issues are excluded from active counts, grade, --check, and SARIF upload, but remain visible in summary and JSON output.

SARIF and Hotspots

--sarif emits SARIF 2.1.0 using Microsoft's Sarif.Sdk, with issue types mapped to SARIF rules and source locations normalized to repository-relative URIs for GitHub Code Scanning.

dotnet-coupling --sarif --output dotnet-coupling.sarif --no-git ./src

--hotspots [N] ranks the top coupling repair candidates from active issues, fan-in, fan-out, volatility, boundary crossing, cycle participation, and syntax-based cyclomatic/cognitive complexity. The default count is 10. Treat hotspots as a remediation priority list; the project Grade remains the health gate based on issue density. Complexity can change hotspot priority and reasons, but it does not change issue severity, Grade, or --check exit codes.

Complexity uses the sonar-dotnet 10.27 C# metric profile. Cyclomatic Complexity counts executable entry points and C# control-flow decisions. Cognitive Complexity counts flow breaks, logical-operator sequences, and nesting while discounting shorthand such as null coalescing. Top-level statements are not attributed because the report model ranks named components.

dotnet-coupling --hotspots ./src
dotnet-coupling --json --hotspots 5 ./src

Investigation

--impact <component> performs a bounded, cycle-safe reverse dependency walk. --trace <symbol> uses semantic observations to identify type or member callers; it therefore requires --mode semantic and a project or solution input. --depth defaults to 3, and 0 means unlimited traversal.

dotnet-coupling --impact Order --depth 2 ./src
dotnet-coupling --trace Repository.Save --mode semantic ./MyApp.sln
dotnet-coupling --json --impact Order ./src
dotnet-coupling --markdown --impact Order ./src
dotnet-coupling --ai --trace Repository.Save --mode semantic ./MyApp.sln
dotnet-coupling --summary --jp ./src

Markdown is intended for artifacts and PR summaries. --ai emits deterministic evidence and bounded recommendations from the report; it does not call an LLM or invent source changes. --jp / --japanese localizes human-readable output without changing JSON or SARIF.

Output and Schema

JSON output includes:

  • $schema and schemaVersion
  • analysis metadata
  • issue-density grade
  • issue counts and issue details
  • manifest run notes and blind spots
  • optional project-model metadata for project / assembly / package boundaries
  • optional hotspots, hotspot complexity, and suppressed issues when requested
  • optional impact or trace evidence in schema 0.5

Schema files live under schemas/.

CI and Quality Gates

Mutation score is the primary test-quality signal. Coverage is collected as a supporting signal to find unexercised areas, not as the main quality gate.

Current CI posture:

  • pull_request: build, test, format, package smoke, report aggregation, and coupling feedback
  • main push: build, test, format, package smoke, and report aggregation
  • same-repo PR / main push: coupling SARIF upload to GitHub Code Scanning
  • nightly-mutation: full Stryker run on schedule or manual dispatch
  • release: build, test, format, pack, local tool smoke, publish

CI uploads coverage-report, semantic-self-report, dotnet-coupling-sarif, dotnet-coupling-hotspots, and dogfood artifacts for inspection. octocov adds line and branch coverage, the main-branch delta, and same-repository PR feedback. Line coverage must remain at least 90%, branch coverage at least 80%, and neither may regress by more than 0.1 percentage points. Mutation appears as not available in PR CI and is reported by the nightly workflow instead.

Current Blind Spots

  • syntax mode does not use semantic symbol resolution
  • semantic preview still depends on workspace prerequisites being loadable
  • runtime DI container dependencies are not analyzed
  • reflection and dynamic calls may be incomplete
  • generated code is excluded by default

Treat a clean report as "no observed issues", not as a guarantee that no coupling risk exists.

Development

dotnet restore dotnet-coupling.slnx --locked-mode
dotnet build dotnet-coupling.slnx --configuration Release --no-restore
dotnet test dotnet-coupling.slnx --configuration Release --no-restore
dotnet format dotnet-coupling.slnx --verify-no-changes --no-restore
dotnet test dotnet-coupling.slnx --configuration Release --results-directory TestResults/Coverage --coverage --coverage-output coverage.cobertura.xml --coverage-output-format cobertura
dotnet tool restore
dotnet tool run dotnet-stryker -- --config-file stryker-config.json
dotnet tool run dotnet-stryker -- --config-file stryker-complexity-config.json

Release history is collected in CHANGELOG.md.

License

MIT. See LICENSE.

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.6.1 234 7/11/2026
0.6.0 119 7/11/2026
0.5.0 123 7/9/2026
0.4.0 128 7/4/2026
0.3.1 122 6/28/2026
0.3.0 126 6/28/2026
0.2.0-alpha.1 83 6/27/2026