Install command
Provided
A Claude Code hook that flags files exceeding complexity thresholds after you edit them — estimating cyclomatic complexity, line and function counts, and nesting depth (via ESLint's complexity rule and Radon).
Open the source and read safety notes before installing.
Source-backed facts for citing this resource, derived directly from the registry — also available as plain text for AI assistants.
Decision playbook
Signals are present but mixed. Use the checklist below to confirm the source and operational safety for your environment.
0
78
—
No baseline selected
No major trust-signal divergence detected in the current selection.
Confirm ownership and provenance before trusting install instructions.
Source link availableRequired
Open the canonical repository and verify ownership.
Source provenance statusRequired
Marked as source-backed.
Metadata reviewed
Registry metadata indicates a reviewed listing.
Validate risk disclosures before installation or API wiring.
Safety notes presentRequired
Review the listed safety guidance before running commands.
Privacy notes presentRequired
Review data handling notes before connecting accounts or secrets.
Trust level risk gateRequired
Trust level does not block evaluation.
Check package metadata and artifact integrity signals.
Install payload available
Install or copy payload is available for review.
Package verification flag
No package verification flag provided.
Checksum metadata
No checksum provided for downloaded artifact.
Use compare context to validate trade-offs before adoption.
Compare tray has multiple entries
Add at least one more entry to compare trust differences.
Baseline comparison available
No baseline peer selected yet.
Diverging trust signals identified
No major trust-signal divergence found.
Setup at a glance
Copy-ready — paste the snippet to get started.
Install command
Provided
Config snippet
Provided
Copy snippet
Provided
Prerequisites
None
Platforms
1 listed
Difficulty
0/100
Adoption plan
Current risk score 16/100. Use staged verification before broader rollout.
Validate source and review signals before any execution.
Confirm source provenanceRequired
Source URL/provenance metadata is present.
Confirm metadata review state
Listing has review metadata.
Verify install payload
Install/config payload exists and can be inspected.
Confirm safety, privacy, and package integrity signals.
Review safety notesRequired
Safety notes are present.
Review privacy notesRequired
Privacy notes are present.
Verify package integrity metadata
No package verification/checksum metadata.
Adopt in controlled steps based on the selected plan.
Run in isolated sandbox firstRequired
Use a constrained sandbox and observe behavior across multiple tasks.
Roll out graduallyRequired
Roll out to a small cohort before wider usage.
Set monitoring and fallback
Define rollback path and monitor errors after adoption.
Evidence readiness
Required evidence gates are covered (5/6 signals complete).
Source repository/provenance is listed.
Required in this preset
Review metadata is present.
Required in this preset
Safety notes are present.
Required in this preset
Privacy notes are present.
Optional in this preset
Package integrity metadata is missing.
Optional in this preset
Install payload is available.
Required in this preset
Required evidence gates are covered for this preset.
Decision timeline
5/6 steps complete with no blocking gaps for this preset.
triage
Source/provenance metadata is available.
triage
Review metadata is available.
verify
Safety notes are available.
verify
Privacy notes are available.
verify
Package integrity metadata is missing.
rollout
Install payload is available.
No required blockers for this timeline preset.
Safety & privacy surface
1 safety and 1 privacy notes across 1 risk area.
#!/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{
"hooks": {
"notification": {
"script": "./.claude/hooks/code-complexity-alert-monitor.sh"
}
}
}.claude/settings.local.json~/.claude/settings.json.claude/settings.json{
"hooks": {
"notification": {
"script": "./.claude/hooks/code-complexity-alert-monitor.sh"
}
}
}
#!/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
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
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"
}
]
}
]
}
}
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
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
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
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.
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.
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.
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.
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.
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.
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.
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.
Show that Code Complexity Alert Monitor - Hooks is listed on HeyClaude. Paste this Markdown into your README — it renders the badge and links back to this page.
[](https://heyclau.de/entry/hooks/code-complexity-alert-monitor)Code Complexity Alert Monitor - Hooks side by side with 3 alternatives on trust, install, platform support, and disclosed safety notes — all from reviewed registry metadata.
| Field | A Claude Code hook that flags files exceeding complexity thresholds after you edit them — estimating cyclomatic complexity, line and function counts, and nesting depth (via ESLint's complexity rule and Radon). Open dossier | A Claude Code SessionEnd hook that scans a project for dead code and writes a report to .claude/reports. It runs available tools per language: ESLint and Knip for JS/TS, autoflake or pylint for Python, Knip for unused npm dependencies, ripgrep for unreferenced src files, and jq to flag zero-coverage files. Open dossier | Alerts when files exceed size thresholds that could impact performance. This PostToolUse hook provides comprehensive file size monitoring when files are created or modified, automatically detecting files that exceed recommended size thresholds for different file types and providing optimization suggestions. Open dossier | Monitors memory usage and alerts when thresholds are exceeded. Open dossier |
|---|---|---|---|---|
| Next steps | ||||
| Trust | ||||
| Review status | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed | ReviewedMaintainer reviewed |
| Package trust | Package not verified | Package not verified | Package not verified | Package not verified |
| Source provenance | Source-backed | Source-backed | Source-backed | Source-backed |
| Submitter | — | — | — | — |
| Install risk | Review first | Review first | Review first | Review first |
| Notes | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ | Safety ✓ Privacy ✓ |
| Brand | — | — | — | — |
| Category | hooks | hooks | hooks | hooks |
| Source | source-backed | source-backed | source-backed | source-backed |
| Author | JSONbored | JSONbored | JSONbored | JSONbored |
| Added | 2025-09-19 | 2025-10-19 | 2025-09-19 | 2025-09-19 |
| Platforms | Claude Code | Claude Code | Claude Code | Claude Code |
| Source repo | — | — | — | — |
| Safety notes | ✓Runs after edits to JS/TS/Python files and prints advisory warnings only; the line/function/brace counts are heuristics, not a substitute for ESLint or Radon run on the full project. | ✓Registered as a SessionEnd hook, so it runs automatically every time a Claude Code session ends. Invokes external tools via npx (ts-prune, Knip, eslint) and locally installed binaries (autoflake, pylint, vulture, jq, rg), which can trigger package downloads and execute project tooling. Defaults to DRY_RUN=true and only writes a report; setting DRY_RUN=false is intended to enable destructive cleanup, so review the report before changing it. Creates directories under .claude/backups and .claude/reports in the working tree. | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. | ✓Runs automatically on its configured Claude Code hook event and executes shell logic that can read, modify, or delete files in your project (and may run builds, installs, or network calls); review the script and scope it to expected paths before enabling. |
| Privacy notes | ✓Reads the contents of files you edit to compute complexity locally; it prints warnings to hook output and does not transmit code, but those messages can reveal file structure. | ✓Writes a dead-code report containing file paths, export names, and dependency names from the project to .claude/reports/dead-code-report.txt and echoes it to stderr. Running tools via npx may fetch packages from the npm registry over the network. | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. | ✓Receives Claude Code hook input (session metadata, file paths, and tool output) and reads local project files; review what the script logs or forwards to external services and keep credentials out of its output. |
| Prerequisites | — none listed | — none listed | — none listed | — none listed |
| Install | | | | |
| Config | | | | |
| Citations | ||||
| Claim | Unclaimed | Unclaimed | Unclaimed | Unclaimed |
Loading live community signals…
A short, calm digest of reviewed Claude resources. Unsubscribe any time.