A command-line tool to analyze Swift code complexity and quality metrics using swift-syntax.
- Multiple Complexity Metrics: Supports cyclomatic complexity, cognitive complexity, and LCOM4 cohesion analysis
- LCOM4 Class Cohesion: High-precision class cohesion measurement using IndexStore-DB semantic analysis
- Web-based Debug Interface: Interactive browser-based complexity analyzer (Try it online)
- Xcode Integration: Seamless integration with Xcode via Build Tool Plugin for complexity feedback during build phase
- Xcode Diagnostics: Display complexity warnings and errors directly in Xcode editor with accurate line numbers
- Configurable Thresholds: Set custom complexity thresholds via Xcode Build Settings or environment variables
- Per-Type Thresholds: Assign different thresholds to types by name (prefix/suffix) via a
.swift-complexity.ymlconfig — e.g. stricter limits for*Repository, looser for*UseCase - Exit Code Integration: Returns exit code 1 when complexity thresholds are exceeded, perfect for CI/CD pipelines
- Multiple Output Formats: Text, JSON, XML, Xcode diagnostics, and SARIF output for different use cases
- Flexible Analysis: Single files, directories, or recursive directory analysis
- Swift Syntax Based: Uses
swift-syntaxfor accurate Swift code parsing - Cross-Platform Support: CLI works on macOS and Linux, library works on iOS 13+.
- MCP Server: Expose complexity analysis as tools for LLM agents (Claude Code, etc.) via Model Context Protocol
- Claude Plugin: Ready-to-use Claude Code plugin with MCP server and analysis skill
- Extensible Architecture: Designed to support additional quality metrics in the future
Visit swift-complexity.fummicc1.dev to analyze Swift code instantly in your browser.
On macOS the recommended path is Homebrew:
brew install fummicc1/tap/swift-complexityOr build from source:
git clone https://github.com/fummicc1/swift-complexity
cd swift-complexity
swift build -c releasePre-built binaries are also available from GitHub Releases as Swift Artifact Bundles, or via nest install fummicc1/swift-complexity.
# Analyze a single file
swift run SwiftComplexityCLI path/to/file.swift
# Analyze a directory with threshold enforcement
swift run SwiftComplexityCLI Sources --threshold 10
# JSON output for tooling integration
swift run SwiftComplexityCLI Sources --format json --recursive
# Xcode diagnostics format (for IDE integration)
swift run SwiftComplexityCLI Sources --format xcode --threshold 15
# SARIF format (for GitHub Code Scanning)
swift run SwiftComplexityCLI Sources --format sarif --threshold 10 --recursive > swift-complexity.sarif
# LCOM4 class cohesion analysis (requires swift build first)
swift build # Generate index
swift run SwiftComplexityCLI Sources --lcom4 --index-store-path .build/debug/index/storeThe tool returns exit code 1 when any function exceeds the specified complexity threshold, making it ideal for:
- CI/CD Pipelines: Fail builds when complexity thresholds are exceeded
- Git Hooks: Prevent commits with overly complex code
- Code Quality Gates: Enforce complexity standards across teams
# Example: Fail if any function has complexity > 15
swift run SwiftComplexityCLI Sources --threshold 15 --recursive
# Exit code 0: All functions below threshold
# Exit code 1: One or more functions exceed thresholdAssign different thresholds per nominal type (class/struct/enum/actor and extensions)
so each layer or feature gets its own complexity budget. Create a
.swift-complexity.yml (auto-discovered in the current directory, or pass --config <path>):
# .swift-complexity.yml
defaultThreshold: 10 # Fallback for types matching no rule (optional)
rules:
- prefix: Toilet # Feature grouping (type name prefix)
threshold: 12
- suffix: Repository # Layer grouping (type name suffix)
threshold: 5
- suffix: UseCase
threshold: 15A function's threshold is resolved from its enclosing type name: among all matching
rules the strictest (lowest) wins (e.g. ToiletRepository matches Toilet=12 and
Repository=5 → 5). Unmatched types fall back to --threshold or defaultThreshold.
# Auto-discovers .swift-complexity.yml
swift run SwiftComplexityCLI Sources --recursive
# Explicit config path
swift run SwiftComplexityCLI Sources --recursive --config config/complexity.ymlSee the Usage Guide for full resolution rules.
- Cyclomatic Complexity: Measures the number of linearly independent paths through code
- Cognitive Complexity: Measures how difficult code is for humans to understand
- LCOM4 (Lack of Cohesion of Methods): Measures class cohesion by analyzing method-property relationships
- Connected Components: Counts independent groups of related methods
- High Precision: Semantic analysis powered by IndexStore-DB
- Implicit self Detection: Automatically detects both
self.propertyandpropertyaccesses - Requirements: Requires
swift buildto generate index data
- User Guide: Installation, usage, and examples
- Complexity Metrics: Detailed metric explanations and examples
- Output Formats: Text, JSON, XML, Xcode diagnostics, and SARIF format specifications
- Development Guide: Setup for contributors
- Debug Website: Web-based interactive analyzer documentation
Unified package with multiple components:
- SwiftComplexityCore: Core analysis library (supports macOS 14+, iOS 13+)
- SwiftComplexityCLI: Command-line interface
- SwiftComplexityMCP: MCP server for LLM agent integration
- SwiftComplexityPlugin: Xcode Build Tool Plugin
- Frontend: Next.js application deployed on Cloudflare Workers
- Backend: Vapor 4 API containerized on Cloudflare Containers.
- Live Demo: swift-complexity.fummicc1.dev
# Analyze with verbose output
swift run SwiftComplexityCLI Sources --verbose --recursive
# Exclude test files with pattern matching
swift run SwiftComplexityCLI Sources --recursive --exclude "*Test*.swift"
# Show only cognitive complexity above threshold
swift run SwiftComplexityCLI Sources --cognitive-only --threshold 5
# Analyze class cohesion with LCOM4
swift build # Generate index first
swift run SwiftComplexityCLI Sources --lcom4 --index-store-path .build/debug/index/store --format jsonThe MCP (Model Context Protocol) server exposes complexity analysis as tools for LLM agents like Claude Code.
# Homebrew (macOS, recommended)
brew install fummicc1/tap/swift-complexity-mcp
# Mint: MCP server only
mint install fummicc1/swift-complexity SwiftComplexityMCP
# Mint: both CLI and MCP server at once
mint install fummicc1/swift-complexity| Tool | Description |
|---|---|
analyze_complexity |
Analyze Swift files/directories on disk (recursive, threshold, per-type thresholds via config_path, LCOM4 support) |
analyze_code_string |
Analyze a Swift code string directly without files on disk |
Claude Code (settings.json):
{
"mcpServers": {
"swift-complexity": {
"command": "SwiftComplexityMCP"
}
}
}Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"swift-complexity": {
"command": "SwiftComplexityMCP"
}
}
}A ready-to-use Claude Code plugin is available in claude-plugin/.
Prerequisite: The plugin requires SwiftComplexityMCP binary in your PATH. Install via Mint first:
mint install fummicc1/swift-complexity SwiftComplexityMCPThen load the plugin:
# Load the plugin
claude --plugin-dir ./claude-plugin
# Use the skill
/swift-complexity:analyze-complexityThe plugin bundles the MCP server configuration and an analyze-complexity skill that guides Claude through complexity analysis workflows.
Integrates with both Swift Package Manager and Xcode projects for automatic complexity analysis during builds.
// swift-tools-version: 6.2
import PackageDescription
let package = Package(
name: "YourProject",
dependencies: [
.package(url: "https://github.com/fummicc1/swift-complexity.git", from: "1.0.0")
],
targets: [
.target(
name: "YourTarget",
plugins: [
.plugin(name: "SwiftComplexityPlugin", package: "swift-complexity")
]
)
]
)- Add swift-complexity package to your Xcode project
- In Build Phases, add "SwiftComplexityPlugin" to Run Build Tool Plug-ins
- Configure threshold in Build Settings (optional)
Xcode Build Settings:
- Key:
SWIFT_COMPLEXITY_THRESHOLD - Value:
15(or any number, defaults to 10)
Environment Variable (SPM):
SWIFT_COMPLEXITY_THRESHOLD=15
- Real-time feedback: Complexity warnings appear directly in Xcode editor
- Accurate positioning: Errors show at exact function locations
- Build integration: Builds fail when thresholds are exceeded
- Configurable per target: Different thresholds for different modules
File: Sources/ComplexityAnalyzer.swift
+------------------+----------+----------+
| Function/Method | Cyclo. | Cogn. |
+------------------+----------+----------+
| analyzeFunction | 3 | 2 |
| calculateTotal | 5 | 7 |
+------------------+----------+----------+
Total: 2 functions, Average Cyclomatic: 4.0, Average Cognitive: 4.5
Class Cohesion (LCOM4):
+--------------------+----------+----------+----------+----------+
| Class/Struct | LCOM4 | Methods | Props | Level |
+--------------------+----------+----------+----------+----------+
| ComplexityAnalyzer | 1 | 5 | 3 | High |
| FileProcessor | 2 | 8 | 4 | Moderate |
+--------------------+----------+----------+----------+----------+
/path/to/Sources/MyFile.swift:45:1: error: Function 'complexFunction' has high complexity (Cyclomatic: 15, Cognitive: 23, Threshold: 10)
/path/to/Sources/MyFile.swift:89:1: warning: Function 'anotherFunction' has high complexity (Cyclomatic: 12, Cognitive: 18, Threshold: 10)
Generate a SARIF report and upload it to GitHub Code Scanning to get complexity violations as inline pull request annotations:
- name: Analyze complexity
run: swift-complexity Sources --format sarif --threshold 10 --recursive > swift-complexity.sarif
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: swift-complexity.sarifViolations are reported per metric (cyclomatic_complexity, cognitive_complexity,
and lcom4_cohesion) with warning level, escalating to error at twice the threshold.
- Swift 6.2+
- macOS 14+ or Linux
- Swift 6.2+
- macOS 14+, iOS 13+, or Linux
- macOS 14+: Xcode toolchain is auto-detected
- Linux: Requires
--toolchain-pathoption pointing to Swift toolchain - Project must be buildable with
swift build - Index data at
.build/debug/index/store(generated by build)
Linux Example:
# Using Swiftly-installed toolchain
TOOLCHAIN=~/.local/share/swiftly/toolchains/swift-6.2.2-RELEASE
swift build \
-Xcxx -I${TOOLCHAIN}/usr/lib/swift \
-Xcxx -I${TOOLCHAIN}/usr/lib/swift/Block
.build/debug/SwiftComplexityCLI Sources --lcom4 \
--index-store-path .build/debug/index/store \
--toolchain-path ${TOOLCHAIN}MIT License

