Code Complexity Alert Monitor - Hooks
Alerts when code complexity exceeds thresholds in real-time using cyclomatic complexity analysis, line count monitoring, function count analysis, and nesting level detection.
Open the source and read safety notes before installing.
Schema details
- Install type
- cli
- Reading time
- 1 min
- Difficulty score
- 0
- Troubleshooting
- Yes
- Breaking changes
- No
- Trigger
- Notification
- Script language
- bash
Script body
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if it's a supported file type
if [[ "$FILE_PATH" == *.js ]] || [[ "$FILE_PATH" == *.jsx ]] || [[ "$FILE_PATH" == *.ts ]] || [[ "$FILE_PATH" == *.tsx ]] || [[ "$FILE_PATH" == *.py ]]; then
echo "🔍 Analyzing code complexity for $FILE_PATH..." >&2
# Check file exists
if [ ! -f "$FILE_PATH" ]; then
echo "📁 File does not exist yet, skipping complexity analysis" >&2
exit 0
fi
# Line count analysis
LINES=$(wc -l < "$FILE_PATH" 2>/dev/null || echo "0")
if [ "$LINES" -gt 500 ]; then
echo "⚠️ COMPLEXITY: File exceeds 500 lines ($LINES lines) - consider splitting into smaller modules" >&2
elif [ "$LINES" -gt 300 ]; then
echo "📊 INFO: File is getting large ($LINES lines) - monitor for complexity" >&2
fi
# Function/method count analysis
FUNCTION_COUNT=$(grep -E '(function|def |const.*=>|class |async |export function)' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$FUNCTION_COUNT" -gt 20 ]; then
echo "⚠️ COMPLEXITY: Too many functions/methods ($FUNCTION_COUNT) - consider modularization" >&2
elif [ "$FUNCTION_COUNT" -gt 15 ]; then
echo "📊 INFO: High function count ($FUNCTION_COUNT) - good candidate for refactoring" >&2
fi
# Nesting level analysis (rough estimate)
OPEN_BRACES=$(grep -o '{' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
CLOSE_BRACES=$(grep -o '}' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$OPEN_BRACES" -gt 50 ]; then
echo "⚠️ COMPLEXITY: High nesting detected ($OPEN_BRACES braces) - consider flattening logic" >&2
fi
# Python-specific checks
if [[ "$FILE_PATH" == *.py ]]; then
INDENT_DEPTH=$(grep -E '^[ ]{12,}' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$INDENT_DEPTH" -gt 5 ]; then
echo "⚠️ COMPLEXITY: Deep indentation detected in Python code - consider function extraction" >&2
fi
fi
echo "✅ Complexity analysis completed for $FILE_PATH" >&2
else
echo "File $FILE_PATH is not a supported type for complexity analysis" >&2
fi
exit 0Full copyable content
{
"hooks": {
"notification": {
"script": "./.claude/hooks/code-complexity-alert-monitor.sh"
}
}
}About this resource
Features
- Real-time complexity monitoring for JavaScript, TypeScript, and Python using pattern matching and AST-based analysis with support for ESLint v9.37.0+ complexity rules
- Configurable line count thresholds (default: 500 lines) with customizable warning (300 lines) and error (500 lines) levels for early detection
- Function count analysis and alerting to detect over-modularization (>20 functions) or under-modularization (<5 functions) patterns
- Nesting level detection for code structure using brace counting (JavaScript/TypeScript) and indentation depth analysis (Python 12+ spaces)
- Instant feedback on code maintainability issues with severity levels (INFO for 300+ lines, WARNING for 500+ lines, ERROR for critical complexity)
- Multi-language support with pattern matching for .js, .jsx, .ts, .tsx, and .py files with language-specific complexity heuristics
- Cyclomatic complexity estimation using control flow analysis counting conditional branches, loops, and switch statements
- Integration with ESLint complexity rules (max-complexity) and Radon ^6.0.0 for Python for comprehensive AST-based complexity analysis
Use Cases
- Real-time code quality monitoring during development providing immediate feedback when complexity thresholds are exceeded
- Automated complexity alerts in CI/CD pipelines preventing complex code from being merged into main branches
- Code review assistance and maintainability checks helping reviewers identify refactoring opportunities before code review
- Technical debt prevention and early detection catching complexity issues before they accumulate into larger problems
- Team coding standards enforcement ensuring consistent complexity thresholds across all team members and projects
- Refactoring guidance identifying specific files and functions that exceed complexity thresholds and need modularization
Installation
- Create hooks directory: mkdir -p .claude/hooks
- Create hook file: touch .claude/hooks/code-complexity-alert-monitor.sh
- Make executable: chmod +x .claude/hooks/code-complexity-alert-monitor.sh
- Add configuration from Hook Configuration section above to .claude/settings.json or ~/.claude/settings.json
- Alternative: Use the interactive /hooks command in Claude Code
Config paths
- Local (not committed):
.claude/settings.local.json - User settings (global):
~/.claude/settings.json - Project-wide (committed):
.claude/settings.json
Requirements
- Claude Code CLI installed
- Project directory initialized
- Bash shell available
- jq installed (for JSON parsing from stdin)
- Optional: ESLint ^9.37.0 (npm install -g eslint) for JavaScript/TypeScript complexity analysis, Radon ^6.0.0 (pip install radon) for Python cyclomatic complexity analysis
- Standard Unix utilities: grep, awk, wc (for pattern matching and line counting) and file system access for reading source code files
Hook Configuration
{
"hooks": {
"notification": {
"script": "./.claude/hooks/code-complexity-alert-monitor.sh"
}
}
}
Hook Script
#!/usr/bin/env bash
# Read the tool input from stdin
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // ""')
if [ -z "$FILE_PATH" ]; then
exit 0
fi
# Check if it's a supported file type
if [[ "$FILE_PATH" == *.js ]] || [[ "$FILE_PATH" == *.jsx ]] || [[ "$FILE_PATH" == *.ts ]] || [[ "$FILE_PATH" == *.tsx ]] || [[ "$FILE_PATH" == *.py ]]; then
echo "🔍 Analyzing code complexity for $FILE_PATH..." >&2
# Check file exists
if [ ! -f "$FILE_PATH" ]; then
echo "📁 File does not exist yet, skipping complexity analysis" >&2
exit 0
fi
# Line count analysis
LINES=$(wc -l < "$FILE_PATH" 2>/dev/null || echo "0")
if [ "$LINES" -gt 500 ]; then
echo "⚠️ COMPLEXITY: File exceeds 500 lines ($LINES lines) - consider splitting into smaller modules" >&2
elif [ "$LINES" -gt 300 ]; then
echo "📊 INFO: File is getting large ($LINES lines) - monitor for complexity" >&2
fi
# Function/method count analysis
FUNCTION_COUNT=$(grep -E '(function|def |const.*=>|class |async |export function)' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$FUNCTION_COUNT" -gt 20 ]; then
echo "⚠️ COMPLEXITY: Too many functions/methods ($FUNCTION_COUNT) - consider modularization" >&2
elif [ "$FUNCTION_COUNT" -gt 15 ]; then
echo "📊 INFO: High function count ($FUNCTION_COUNT) - good candidate for refactoring" >&2
fi
# Nesting level analysis (rough estimate)
OPEN_BRACES=$(grep -o '{' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
CLOSE_BRACES=$(grep -o '}' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$OPEN_BRACES" -gt 50 ]; then
echo "⚠️ COMPLEXITY: High nesting detected ($OPEN_BRACES braces) - consider flattening logic" >&2
fi
# Python-specific checks
if [[ "$FILE_PATH" == *.py ]]; then
INDENT_DEPTH=$(grep -E '^[ ]{12,}' "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$INDENT_DEPTH" -gt 5 ]; then
echo "⚠️ COMPLEXITY: Deep indentation detected in Python code - consider function extraction" >&2
fi
fi
echo "✅ Complexity analysis completed for $FILE_PATH" >&2
else
echo "File $FILE_PATH is not a supported type for complexity analysis" >&2
fi
exit 0
Examples
Code Complexity Alert Monitor Hook Script
Complete hook script that monitors code complexity in real-time for JavaScript, TypeScript, and Python files
#!/usr/bin/env bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r ".tool_name")
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path // .tool_input.path // \"\"")
if [ -z "$FILE_PATH" ]; then exit 0; fi
if [[ "$FILE_PATH" == *.js ]] || [[ "$FILE_PATH" == *.ts ]] || [[ "$FILE_PATH" == *.py ]]; then
LINES=$(wc -l < "$FILE_PATH" 2>/dev/null || echo "0")
if [ "$LINES" -gt 500 ]; then
echo "⚠️ COMPLEXITY: File exceeds 500 lines ($LINES lines) - consider splitting" >&2
fi
fi
exit 0
Hook Configuration
Complete hook configuration for .claude/settings.json to enable complexity monitoring on file write operations
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "./.claude/hooks/code-complexity-alert-monitor.sh"
}
]
}
]
}
}
Python Complexity with Radon
Enhanced hook script using Radon for accurate Python cyclomatic complexity analysis
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path // .tool_input.path // \"\"")
if [ -z "$FILE_PATH" ] || [[ ! "$FILE_PATH" == *.py ]]; then exit 0; fi
if command -v radon >/dev/null 2>&1; then
COMPLEXITY=$(radon cc "$FILE_PATH" -a -nc 2>/dev/null | grep -oP "Average complexity: \\K[0-9]+\.[0-9]+" || echo "0")
if (( $(echo "$COMPLEXITY > 10" | bc -l) )); then
echo "⚠️ COMPLEXITY: High cyclomatic complexity ($COMPLEXITY) - consider refactoring" >&2
fi
fi
exit 0
JavaScript/TypeScript Complexity with ESLint
Enhanced hook script using ESLint complexity rule for accurate JavaScript/TypeScript cyclomatic complexity analysis
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path // .tool_input.path // \"\"")
if [ -z "$FILE_PATH" ] || [[ ! "$FILE_PATH" == *.{js,jsx,ts,tsx} ]]; then exit 0; fi
if command -v eslint >/dev/null 2>&1; then
COMPLEXITY=$(eslint --format json "$FILE_PATH" 2>/dev/null | jq -r ".[0].messages[] | select(.ruleId==\"complexity\") | .message" || echo "")
if [ -n "$COMPLEXITY" ]; then
echo "⚠️ COMPLEXITY: $COMPLEXITY" >&2
fi
fi
exit 0
Multi-Metric Complexity Analysis
Comprehensive hook script that analyzes multiple complexity metrics simultaneously for better detection
#!/usr/bin/env bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r ".tool_input.file_path // .tool_input.path // \"\"")
if [ -z "$FILE_PATH" ]; then exit 0; fi
LINES=$(wc -l < "$FILE_PATH" 2>/dev/null || echo "0")
FUNCTION_COUNT=$(grep -E "(function|def |const.*=>|class |async |export function)" "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
OPEN_BRACES=$(grep -o "{" "$FILE_PATH" 2>/dev/null | wc -l || echo "0")
if [ "$LINES" -gt 500 ] || [ "$FUNCTION_COUNT" -gt 20 ] || [ "$OPEN_BRACES" -gt 50 ]; then
echo "⚠️ COMPLEXITY: Multiple thresholds exceeded - Lines: $LINES, Functions: $FUNCTION_COUNT, Nesting: $OPEN_BRACES" >&2
fi
exit 0
Troubleshooting
Notification hook not running on file write operations
Verify hook is registered under hooks.notification in .claude/settings.json. Check script has executable permissions: chmod +x. Ensure jq is installed for JSON parsing from stdin input. Test hook manually with a test JSON input. Verify Notification hook type is correct in configuration.
Complexity alerts not showing for TypeScript files
Check file extension matches supported types: .js, .jsx, .ts, .tsx, .py. Verify FILE_PATH extraction from tool_input using jq processes correctly. Test with echo command to debug input parsing. Ensure file exists before analysis.
False positives for brace count in JSX files
Hook counts all braces including JSX elements which inflates nesting metrics. Adjust thresholds in script for JSX-heavy files: increase OPEN_BRACES threshold from 50 to 100. Consider implementing AST-based complexity analysis using ESLint instead of regex pattern matching. Use ESLint complexity rule for accurate cyclomatic complexity.
File does not exist error during notification processing
Hook runs after tool execution but file may not be written yet. Add delay with sleep 1 before analysis. Check tool_name matches write or edit operations. Verify path resolution is absolute. Add file existence check before processing.
Python indentation warnings incorrect for valid code
Hook detects 12+ space indentation as deep nesting. Adjust threshold for projects using different indent styles. Use Radon for accurate Python complexity: radon cc file.py -a. Consider using 8-space threshold for projects with 4-space indentation.
Complexity analysis is too slow for large files
Add timeout wrapper: timeout 5s complexity-command. Limit analysis scope: only analyze files under 1000 lines. Use faster tools: ESLint with --cache for JavaScript, Radon with --min B for Python. Skip analysis for generated files: exclude node_modules, dist, build directories.
ESLint complexity rule not detecting issues
Verify ESLint is installed: eslint --version. Check ESLint configuration includes complexity rule. Ensure ESLint can parse file type: install @typescript-eslint/parser for TypeScript. Test manually with eslint --rule complexity command. Check ESLint version: upgrade to ESLint ^9.37.0 for latest complexity analysis.
Radon not calculating Python complexity correctly
Verify Radon is installed: radon --version. Check Python version compatibility: Radon requires Python 3.7+. Test manually: radon cc file.py -a. Ensure file is valid Python syntax. Use specific complexity threshold: radon cc file.py -nc. Check Radon version: upgrade to Radon ^6.0.0 for latest features.
- Features
- Use Cases
- Installation
- Config paths
- Requirements
- Hook Configuration
- Hook Script
- Examples
- Code Complexity Alert Monitor Hook Script
- Hook Configuration
- Python Complexity with Radon
- JavaScript/TypeScript Complexity with ESLint
- Multi-Metric Complexity Analysis
- Troubleshooting
- Notification hook not running on file write operations
- Complexity alerts not showing for TypeScript files
Source citations
Signals
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.