Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

🚧 Early Prototype - This project is under active development and APIs may change

Debtmap is a fast code complexity and technical debt analyzer written in Rust. Debtmap identifies which code to refactor for maximum cognitive debt reduction and which code to test for maximum risk reduction, providing data-driven prioritization for both.

What is Debtmap?

Unlike traditional static analysis tools that simply flag complex code, Debtmap answers two critical questions:

  1. “What should I refactor to reduce cognitive burden?” - Identifies overly complex code that slows down development
  2. “What should I test first to reduce the most risk?” - Pinpoints untested complex code that threatens stability

Debtmap analyzes your codebase to identify complexity hotspots, technical debt patterns, and architectural risks. It supports Rust, Python, JavaScript, and TypeScript with full AST parsing and analysis capabilities. Rust includes additional advanced features like macro expansion and trait tracking.

What Makes Debtmap Different:

  • Entropy-Based Complexity Analysis: Uses information theory to distinguish genuinely complex code from pattern-based repetitive code, reducing false positives by up to 70%
  • Coverage-Risk Correlation: The only tool that combines complexity metrics with test coverage to identify genuinely risky code (high complexity + low coverage = critical risk)
  • Risk-Driven Prioritization: Prioritizes refactoring and testing efforts based on complexity, coverage, and dependency factors
  • Actionable Guidance: Provides specific recommendations like “extract nested conditions” or “split this 80-line function” rather than just flagging issues
  • Performance: 10-100x faster than Java/Python-based competitors (written in Rust with parallel processing)

Why Use Debtmap?

Debtmap helps you make data-driven decisions about where to focus your refactoring and testing efforts:

  • Identify Complexity - Find complex functions and modules that need refactoring, with concrete metrics showing which changes will have the most impact
  • Detect Technical Debt - Discover 30+ debt patterns including code smells, security vulnerabilities, resource management issues, and architectural problems
  • Assess Risk - Prioritize improvements based on sophisticated risk scoring that combines complexity, test coverage, and dependency impact
  • Track Quality - Monitor code quality metrics over time with the compare command (which can track improvements against implementation plan targets) to verify that refactoring efforts achieved their goals
  • Get Actionable Recommendations - Receive specific guidance like “refactoring this will reduce complexity by 60%” or “testing this will reduce risk by 5%”
  • Automated Debt Reduction - Integrates with Prodigy workflows for AI-driven automated refactoring with iterative validation and testing

Key Features

Analysis Capabilities

  • Multi-language support - Full support for Rust, Python, JavaScript, and TypeScript with AST parsing, complexity analysis, and debt detection
  • Entropy-based complexity analysis - Distinguishes between genuinely complex code and pattern-based repetitive code using information theory
  • Token classification system - Advanced token categorization with weighted entropy for accurate complexity assessment
  • Comprehensive debt detection - Identifies 30+ technical debt patterns across security (5 types), code organization (god objects, feature envy, magic values), resource management (5 types), testing quality (3 types), and error handling (4 types)
  • Security vulnerability detection - Finds hardcoded secrets, weak crypto, SQL injection risks, and unsafe code patterns
  • Resource management analysis - Identifies inefficient allocations, nested loops, and blocking I/O patterns
  • Code organization analysis - Detects god objects, feature envy, primitive obsession, and magic values
  • Testing quality assessment - Analyzes test complexity, flaky patterns, and assertion quality
  • Context-aware analysis - Reduces false positives through intelligent context detection (enabled by default)

Risk Analysis & Prioritization

  • Coverage-based risk analysis - Correlates complexity with test coverage to identify truly risky code
  • Risk-driven testing recommendations - Prioritizes testing efforts based on complexity-coverage correlation and dependency impact
  • Call graph analysis - Tracks upstream callers and downstream callees to understand dependency impact
  • Tiered prioritization - Surfaces critical architectural issues above simple testing gaps
  • Quantified impact - Shows concrete metrics like “refactoring this will reduce complexity by 60%”

Performance & Output

  • Parallel processing - Built with Rust and Rayon for blazing-fast analysis of large codebases
  • Multiple output formats - JSON, Markdown, and human-readable terminal formats
  • Configurable thresholds - Customize complexity and duplication thresholds to match your standards
  • Incremental analysis - Smart caching system for analyzing only changed files
  • Intelligent caching - Smart cache system with automatic pruning, configurable strategies (LRU, LFU, FIFO), and environment-based configuration for fast repeated analysis
  • Verbosity controls - Multiple verbosity levels (-v, -vv, -vvv) for progressive detail

Configuration & Customization

  • Flexible suppression - Inline comment-based suppression for specific code sections
  • Configuration file - .debtmap.toml for project-specific settings
  • Test-friendly - Easily exclude test fixtures and example code from debt analysis
  • Macro expansion support - Handles Rust macro expansions with configurable warnings

Commands

  • analyze - Comprehensive debt analysis with unified prioritization
  • validate - Enforce quality thresholds in CI/CD pipelines
  • compare - Track improvements over time and verify refactoring goals
  • init - Generate configuration file with sensible defaults

Target Audience

Debtmap is designed for:

  • Development teams - Get concrete metrics for planning sprints. Know exactly which refactoring will reduce complexity by 60% or which function needs 6 unit tests for full coverage.
  • Engineering managers - Track quality trends over time with the compare command. Monitor whether refactoring efforts are actually improving codebase health.
  • Code reviewers - Focus reviews on high-risk areas identified by Debtmap. Prioritize reviewing untested complex code over simple utility functions.
  • Developers refactoring legacy codebases - Receive actionable guidance like “extract nested conditions”, “split this 80-line function into 3 smaller functions”, or “add error handling for this catch block”.

Getting Started

Ready to analyze your codebase? Check out:

Getting Started

This guide will help you install Debtmap and run your first analysis in just a few minutes.

Prerequisites

Before installing Debtmap, you’ll need:

  • For pre-built binaries: No prerequisites! The install script handles everything.
  • For cargo install or building from source:
    • Rust toolchain (rustc and cargo)
    • Supported platforms: Linux, macOS, Windows
    • Rust edition 2021 or later

Optional (for coverage-based risk analysis):

  • Rust projects: cargo-tarpaulin for coverage data
  • JavaScript/TypeScript: Jest or other tools generating LCOV format
  • Python: pytest with coverage plugin

Installation

Install the latest release with a single command:

curl -sSL https://raw.githubusercontent.com/iepathos/debtmap/master/install.sh | bash

Or with wget:

wget -qO- https://raw.githubusercontent.com/iepathos/debtmap/master/install.sh | bash

This will:

  • Automatically detect your OS and architecture
  • Download the appropriate pre-built binary from the latest GitHub release
  • Install debtmap to ~/.cargo/bin if it exists, otherwise ~/.local/bin
  • Offer to automatically add the install directory to your PATH if needed

Using Cargo

If you have Rust installed:

cargo install debtmap

From Source

For the latest development version:

# Clone the repository
git clone https://github.com/iepathos/debtmap.git
cd debtmap

# Build and install
cargo install --path .

Verify Installation

After installation, verify Debtmap is working:

# Check version
debtmap --version

# See available commands
debtmap --help

Common installation issues:

  • Binary not in PATH: Add ~/.cargo/bin or ~/.local/bin to your PATH
    export PATH="$HOME/.cargo/bin:$PATH"  # Add to ~/.bashrc or ~/.zshrc
    
  • Permission issues: Run the install script with your current user (don’t use sudo)
  • Cargo not found: Install Rust from https://rustup.rs

Quick Start

Here are the most common commands to get you started:

# Analyze current directory (simplest command)
debtmap analyze .

# Analyze with coverage data for risk scoring (recommended)
# Note: --lcov is a shorthand alias for --coverage-file
debtmap analyze . --lcov target/coverage/lcov.info

# Generate coverage first (for Rust projects)
cargo tarpaulin --out lcov --output-dir target/coverage
debtmap analyze . --lcov target/coverage/lcov.info

# Analyze with custom thresholds
# Note: threshold-duplication specifies minimum lines of duplicated code to detect
debtmap analyze ./src --threshold-complexity 15 --threshold-duplication 50

# Output as JSON (for CI/CD integration)
debtmap analyze ./src --format json --output report.json

# Show only top 10 high-priority issues
debtmap analyze . --top 10

# Initialize configuration file for project-specific settings
debtmap init

# Validate against thresholds (CI/CD integration)
debtmap validate ./src --max-debt-density 5.0

# Compare before/after to track improvements
debtmap analyze . --format json --output before.json
# ... make improvements ...
debtmap analyze . --format json --output after.json
debtmap compare --before before.json --after after.json

# Advanced comparison: focus on specific function
debtmap compare --before before.json --after after.json --target-location src/main.rs:main:10

# Extract target from implementation plan
debtmap compare --before before.json --after after.json --plan IMPLEMENTATION_PLAN.md

Advanced Options

Debtmap provides many powerful options to customize your analysis:

Verbosity Levels:

# Show main factors contributing to scores
debtmap analyze . -v

# Show detailed calculations
debtmap analyze . -vv

# Show all debug information
debtmap analyze . -vvv

Filtering and Prioritization:

# Only show high-priority items
debtmap analyze . --min-priority high

# Filter by specific categories
debtmap analyze . --filter Architecture,Testing

# Group results by debt category
debtmap analyze . --group-by-category

Cache Management:

# Skip cache for fresh analysis
debtmap analyze . --no-cache

# Clear cache and rebuild
debtmap analyze . --clear-cache

# View cache statistics
debtmap analyze . --cache-stats

# Specify custom cache location
debtmap analyze . --cache-location /custom/path

# Migrate cache from local to shared location
debtmap analyze . --migrate-cache

Performance Control:

# Limit parallel jobs
debtmap analyze . --jobs 4

# Disable parallel processing
debtmap analyze . --no-parallel

Output Control:

# Plain output (no colors/emoji, for CI/CD)
debtmap analyze . --plain

# Compact summary output
debtmap analyze . --summary

# Control aggregation behavior
debtmap analyze . --aggregate-only          # Show only aggregated results
debtmap analyze . --no-aggregation          # Skip aggregation entirely
debtmap analyze . --aggregation-method sum  # Choose aggregation method

# Adjust detail level in output
debtmap analyze . --detail-level high       # More detailed output

Expert Options:

These advanced options are available for power users and specialized use cases:

# Analysis behavior
--semantic-off              # Disable semantic analysis
--no-context-aware          # Disable context-aware analysis
--multi-pass                # Enable multi-pass analysis for deeper insights
--validate-loc              # Validate lines of code calculations

# Rust-specific options
--verbose-macro-warnings    # Show detailed macro expansion warnings
--show-macro-stats          # Display macro usage statistics

# Filtering and thresholds
--threshold-preset <name>   # Use predefined threshold preset
--min-problematic <count>   # Minimum problematic items to report
--max-files <count>         # Limit analysis to N files
--no-god-object             # Disable god object detection

# Advanced reporting
--attribution               # Include code attribution information

For detailed documentation of these options, run debtmap analyze --help.

First Analysis

Let’s run your first analysis! Navigate to a project directory and run:

debtmap analyze .

What happens during analysis:

  1. File Discovery - Debtmap scans your project for supported source files (Rust, Python, JavaScript, TypeScript)
  2. Parsing - Each file is parsed into an Abstract Syntax Tree (AST)
  3. Metrics Calculation - Complexity, debt patterns, and risk scores are computed
  4. Prioritization - Results are ranked by priority (CRITICAL, HIGH, MEDIUM, LOW)
  5. Output - Results are displayed in your chosen format

Expected timing: Analyzing a 10,000 LOC project typically takes 2-5 seconds. The first run may be slightly slower as Debtmap builds its cache.

About Caching: Debtmap caches parsed ASTs and computed metrics to speed up subsequent analyses:

  • Cache location: XDG_CACHE_HOME/debtmap on Linux, ~/Library/Caches/debtmap on macOS, %LOCALAPPDATA%/debtmap on Windows
  • What’s cached: Parsed ASTs and computed metrics for each file
  • Invalidation: Cache is automatically invalidated when files are modified
  • Management: Use --clear-cache to clear, --no-cache to skip, or --cache-stats to view statistics

Language support:

  • Rust: Full support with advanced features (trait detection, purity analysis, call graphs)
  • Python: Partial support (complexity metrics, basic debt detection)
  • JavaScript/TypeScript: Partial support (complexity metrics, basic debt detection)

Example Output

When you run debtmap analyze ., you’ll see output like this:

════════════════════════════════════════════
    PRIORITY TECHNICAL DEBT FIXES
════════════════════════════════════════════

🎯 TOP 3 RECOMMENDATIONS (by unified priority)

#1 SCORE: 8.9 [CRITICAL]
├─ TEST GAP: ./src/analyzers/rust_call_graph.rs:38 add_function_to_graph()
├─ ACTION: Add 6 unit tests for full coverage
├─ IMPACT: Full test coverage, -3.7 risk
├─ COMPLEXITY: cyclomatic=6, branches=6, cognitive=8, nesting=2, lines=32
├─ DEPENDENCIES: 0 upstream, 11 downstream
└─ WHY: Business logic with 0% coverage, manageable complexity (cyclo=6, cog=8)

#2 SCORE: 8.9 [CRITICAL]
├─ TEST GAP: ./src/debt/smells.rs:196 detect_data_clumps()
├─ ACTION: Add 5 unit tests for full coverage
├─ IMPACT: Full test coverage, -3.7 risk
├─ COMPLEXITY: cyclomatic=5, branches=5, cognitive=11, nesting=5, lines=31
├─ DEPENDENCIES: 0 upstream, 4 downstream
└─ WHY: Business logic with 0% coverage, manageable complexity (cyclo=5, cog=11)

#3 SCORE: 8.6 [CRITICAL]
├─ TEST GAP: ./src/risk/context/dependency.rs:247 explain()
├─ ACTION: Add 5 unit tests for full coverage
├─ IMPACT: Full test coverage, -3.6 risk
├─ COMPLEXITY: cyclomatic=5, branches=5, cognitive=9, nesting=1, lines=24
├─ DEPENDENCIES: 0 upstream, 1 downstream
└─ WHY: Business logic with 0% coverage, manageable complexity (cyclo=5, cog=9)


📊 TOTAL DEBT SCORE: 4907
📈 OVERALL COVERAGE: 67.12%

Understanding the Output

Let’s break down what this output means:

Priority Levels

  • CRITICAL (9.0-10.0): Immediate action required - high complexity with no test coverage
  • HIGH (7.0-8.9): Should be addressed soon - moderate-high complexity with poor coverage
  • MEDIUM (5.0-6.9): Plan for next sprint - moderate complexity or partial coverage gaps
  • LOW (3.0-4.9): Nice to have - well-tested or simple functions

Note: These are default priority thresholds. You can customize them in .debtmap.toml under the [tiers] section to match your team’s standards.

Key Metrics

  • Unified Score (0-10 scale): Overall priority combining complexity, coverage, and dependencies

    • Higher score = higher priority
    • Takes into account multiple risk factors
  • Debt Type: Category of the issue

    • TestGap: Missing test coverage
    • Complexity: Exceeds complexity thresholds
    • Duplication: Repeated code blocks
    • CodeSmell: Anti-patterns and bad practices
  • Complexity Metrics:

    • Cyclomatic: Number of decision points (branches, loops)
    • Cognitive: How difficult the code is to understand
    • Nesting: Maximum indentation depth
    • Lines: Function length
  • Dependencies:

    • Upstream callers: Functions that call this function
    • Downstream callees: Functions this function calls
    • More dependencies = higher impact when this code breaks

Recommendation Structure

Each recommendation shows:

  • ACTION: What you should do (e.g., “Add 6 unit tests”)
  • IMPACT: Expected improvement (e.g., “Full test coverage, -3.7 risk”)
  • WHY: The reasoning behind this recommendation

Organizing Results

When analyzing large codebases, you can organize and filter results to focus on specific areas:

Group by Debt Category:

debtmap analyze . --group-by-category

This organizes results by type: Architecture, Testing, Performance, CodeQuality

Filter by Priority:

# Show only high and critical priority items
debtmap analyze . --min-priority high

# Combine with --top to limit results
debtmap analyze . --min-priority high --top 10

Filter by Category:

# Focus on specific debt types
debtmap analyze . --filter Architecture,Testing

# Available categories: Architecture, Testing, Performance, CodeQuality

These filtering options help you focus on specific types of technical debt, making it easier to plan targeted improvements.

Summary Statistics

  • Total Debt Score: Sum of all debt scores across your codebase

    • Lower is better
    • Track over time to measure improvement
  • Overall Coverage: Percentage of code covered by tests

    • Only shown when coverage data is provided

Output Formats

Debtmap supports multiple output formats:

  • Terminal (default): Human-readable colored output with tables
  • JSON: Machine-readable format for CI/CD integration
  • Markdown: Documentation-friendly format for reports

Example JSON output:

# By default, JSON uses legacy format
debtmap analyze . --format json --output report.json

# For the new unified format (with consistent structure and type field):
debtmap analyze . --format json --output-format unified --output report.json

JSON Format Options:

  • legacy (default): Uses {File: {...}} and {Function: {...}} wrappers for backward compatibility with existing tools
  • unified: New format (spec 108) with consistent structure and type field for all items

Recommendation: Use unified for new integrations, legacy only for compatibility with existing tooling.

Example Markdown output:

debtmap analyze . --format markdown --output report.md

What’s Next?

Now that you’ve run your first analysis, explore these topics:

  • Analysis Guide - Deep dive into complexity metrics, debt patterns, and risk scoring
  • Output Formats - Detailed guide to JSON schema and integration options
  • Configuration - Customize thresholds and filters with .debtmap.toml
  • CI/CD Integration - Use the validate command to enforce quality gates

Generate a Configuration File

Create a project-specific configuration:

debtmap init

This creates a .debtmap.toml file with sensible defaults that you can customize for your project.

Key Configuration Options:

The configuration file allows you to customize:

  • Threshold customization - Adjust complexity, duplication, and file size thresholds
  • Scoring weights - Fine-tune how coverage, complexity, and dependencies are weighted
  • Language selection - Enable/disable specific language analyzers
  • Ignore patterns - Exclude test files or generated code from analysis
  • God object thresholds - Configure what constitutes a “god object” anti-pattern
  • Entropy analysis - Control entropy-based complexity detection
  • Priority tiers - Customize CRITICAL/HIGH/MEDIUM/LOW threshold ranges

See the Configuration chapter for complete documentation of all available options.

Try Analysis with Coverage

For more accurate risk assessment, run analysis with coverage data:

# For Rust projects
cargo tarpaulin --out lcov --output-dir target/coverage
debtmap analyze . --lcov target/coverage/lcov.info

# For Python projects
pytest --cov --cov-report=lcov
debtmap analyze . --lcov coverage.lcov

# For JavaScript/TypeScript projects
jest --coverage --coverageReporters=lcov
debtmap analyze . --lcov coverage/lcov.info

Coverage data helps Debtmap identify truly risky code - functions that are both complex AND untested.


Need help? Report issues at https://github.com/iepathos/debtmap/issues

CLI Reference

Complete reference for Debtmap command-line interface.

Quick Start

# Basic analysis
debtmap analyze src/

# With coverage integration
debtmap analyze src/ --coverage-file coverage.lcov

# Generate JSON report
debtmap analyze . --format json --output report.json

# Show top 10 priority items only
debtmap analyze . --top 10 --min-priority high

# Initialize configuration and validate
debtmap init
debtmap validate . --config debtmap.toml

Commands

Debtmap provides four main commands:

analyze

Analyze code for complexity and technical debt.

Usage:

debtmap analyze <PATH> [OPTIONS]

Arguments:

  • <PATH> - Path to analyze (file or directory)

Description: Primary command for code analysis. Supports multiple output formats (json, markdown, terminal), coverage file integration, caching, parallel processing, context-aware risk analysis, and comprehensive filtering options.

See Options section below for all available flags.

init

Initialize a Debtmap configuration file.

Usage:

debtmap init [OPTIONS]

Options:

  • -f, --force - Force overwrite existing config

Description: Creates a debtmap.toml configuration file in the current directory with default settings. Use --force to overwrite an existing configuration file.

validate

Validate code against thresholds defined in configuration file.

Usage:

debtmap validate <PATH> [OPTIONS]

Arguments:

  • <PATH> - Path to analyze

Options:

Configuration & Output:

  • -c, --config <CONFIG> - Configuration file path
  • -f, --format <FORMAT> - Output format: json, markdown, terminal
  • -o, --output <OUTPUT> - Output file path (defaults to stdout)

Coverage & Context:

  • --coverage-file <PATH> / --lcov <PATH> - LCOV coverage file for risk analysis
  • --context / --enable-context - Enable context-aware risk analysis
  • --context-providers <PROVIDERS> - Context providers to use (comma-separated)
  • --disable-context <PROVIDERS> - Disable specific context providers

Thresholds & Validation:

  • --max-debt-density <N> - Maximum debt density allowed (per 1000 LOC)

Display Filtering:

  • --top <N> / --head <N> - Show only top N priority items
  • --tail <N> - Show only bottom N priority items
  • -s, --summary - Use summary format with tiered priority display

Analysis Control:

  • --semantic-off - Disable semantic analysis (fallback mode)

Debugging & Verbosity:

  • -v, --verbose - Increase verbosity level (can be repeated: -v, -vv, -vvv)

Description: Similar to analyze but enforces thresholds defined in configuration file. Returns non-zero exit code if thresholds are exceeded, making it suitable for CI/CD integration.

The validate command supports a focused subset of analyze options, primarily for output control, coverage integration, context-aware analysis, and display filtering. The validate command does not support --threshold-complexity, --threshold-duplication, or --threshold-preset flags (these are analyze-only). Instead, configure thresholds in the .debtmap.toml config file. Performance options like --jobs, --cache-*, and --languages are also not available in validate.

Exit Codes:

  • 0 - Success (no errors, all thresholds passed)
  • Non-zero - Failure (errors occurred or thresholds exceeded)

compare

Compare two analysis results and generate a diff report.

Usage:

debtmap compare --before <FILE> --after <FILE> [OPTIONS]

Required Options:

  • --before <FILE> - Path to “before” analysis JSON
  • --after <FILE> - Path to “after” analysis JSON

Optional Target Location:

  • --plan <FILE> - Path to implementation plan (to extract target location)
  • --target-location <LOCATION> - Target location in format file:function:line

Note: --plan and --target-location are mutually exclusive options. Using both together will cause a CLI error. Use one or the other to specify the target location.

Output Options:

  • -f, --format <FORMAT> - Output format: json, markdown, terminal (default: json)
  • -o, --output <OUTPUT> - Output file (defaults to stdout)

Description: Compares two analysis results and generates a diff showing improvements or regressions in code quality metrics.

Options

Options are organized by category for clarity. Most options apply to the analyze command, with a subset available for validate.

Output Control

Control how analysis results are formatted and displayed.

Format Options:

  • -f, --format <FORMAT> - Output format: json, markdown, terminal (default: terminal for analyze)
  • --output-format <JSON_FORMAT> - JSON structure format: legacy or unified (default: legacy)
    • legacy - Current format with {File: {...}} and {Function: {...}} wrappers
    • unified - New format with consistent structure and ‘type’ field
  • -o, --output <OUTPUT> - Output file path (defaults to stdout)
  • --plain - Plain output mode: ASCII-only, no colors, no emoji, machine-parseable

Display Filtering:

  • --top <N> / --head <N> - Show only top N priority items
  • --tail <N> - Show only bottom N priority items (lowest priority)
  • -s, --summary - Use summary format with tiered priority display (compact output)
  • --min-priority <PRIORITY> - Minimum priority to display: low, medium, high, critical
  • --filter <CATEGORIES> - Filter by debt categories (comma-separated)
  • --aggregate-only - Show only aggregated file-level scores
  • --group-by-category - Group output by debt category

Analysis Control

Configure analysis behavior, thresholds, and language selection.

Thresholds:

  • --threshold-complexity <N> - Complexity threshold (default: 10) [analyze command]
  • --threshold-duplication <N> - Duplication threshold in lines (default: 50) [analyze command]
  • --threshold-preset <PRESET> - Complexity threshold preset: strict, balanced, lenient [analyze command]
    • strict - Strict thresholds for high code quality standards
    • balanced - Balanced thresholds for typical projects (default)
    • lenient - Lenient thresholds for legacy or complex domains
  • --max-debt-density <N> - Maximum debt density allowed per 1000 LOC [validate command]

Note: Threshold options (--threshold-complexity, --threshold-duplication, --threshold-preset) are command-line options for the analyze command. For the validate command, these thresholds are configured via the --config file (debtmap.toml) rather than as command-line flags.

Language Selection:

  • --languages <LANGS> - Comma-separated list of languages to analyze
    • Example: --languages rust,python,javascript
    • Supported: rust, python, javascript, typescript

Analysis Modes:

  • --semantic-off - Disable semantic analysis (fallback mode)
  • --no-context-aware - Disable context-aware false positive reduction (enabled by default)
  • --multi-pass - Enable multi-pass analysis with attribution
  • --attribution - Show complexity attribution details

Context & Coverage

Enable context-aware risk analysis and integrate test coverage data.

Context-Aware Risk Analysis:

  • --context / --enable-context - Enable context-aware risk analysis
  • --context-providers <PROVIDERS> - Context providers to use (comma-separated)
    • Available: critical_path, dependency, git_history
    • Example: --context-providers critical_path,git_history
  • --disable-context <PROVIDERS> - Disable specific context providers (comma-separated)

Coverage Integration:

  • --coverage-file <PATH> / --lcov <PATH> - LCOV coverage file for risk analysis
    • Coverage data dampens debt scores for well-tested code (multiplier = 1.0 - coverage)
    • Surfaces untested complex functions as higher priority
    • Total debt score with coverage ≤ score without coverage
  • --validate-loc - Validate LOC consistency across analysis modes (with/without coverage)

Performance & Caching

Optimize analysis performance through parallelization and caching.

Parallel Processing:

  • --no-parallel - Disable parallel call graph construction (enabled by default)
  • -j, --jobs <N> - Number of threads for parallel processing
    • 0 = use all available CPU cores (default)
    • Specify number to limit thread count

Caching:

  • --no-cache - Disable caching for this run (caching is enabled by default)
  • --clear-cache - Clear cache before running analysis
  • --force-cache-rebuild - Force cache rebuild (same as –clear-cache)
  • --cache-stats - Show cache statistics and location
  • --migrate-cache - Migrate cache from local to shared location
  • --cache-location <LOCATION> - Cache location strategy: local, shared, or path
    • Can also be set via DEBTMAP_CACHE_DIR environment variable
    • Affects where analysis results are cached for faster subsequent runs

Other Performance:

  • --max-files <N> - Maximum number of files to analyze (0 = no limit)

Debugging & Verbosity

Control diagnostic output and debugging information.

Verbosity Levels:

  • -v, --verbose - Increase verbosity level (can be repeated: -v, -vv, -vvv)
    • -v - Show main score factors
    • -vv - Show detailed calculations
    • -vvv - Show all debug information

Specialized Debugging:

  • --verbose-macro-warnings - Show verbose macro parsing warnings (Rust analysis)
  • --show-macro-stats - Show macro expansion statistics at end of analysis
  • --detail-level <LEVEL> - Detail level for diagnostic reports
    • Options: summary, standard, comprehensive, debug (default: standard)

Aggregation

Control file-level aggregation and god object detection.

File Aggregation:

  • --aggregate-only - Show only aggregated file-level scores
  • --no-aggregation - Disable file-level aggregation
  • --aggregation-method <METHOD> - File aggregation method (default: weighted_sum)
    • Options: sum, weighted_sum, logarithmic_sum, max_plus_average
  • --min-problematic <N> - Minimum number of problematic functions for file aggregation
  • --no-god-object - Disable god object detection

Option Aliases

Common option shortcuts and aliases for convenience:

  • --lcov is alias for --coverage-file
  • --enable-context is alias for --context
  • --head is alias for --top
  • -s is short form for --summary
  • -v is short form for --verbose
  • -f is short form for --format
  • -o is short form for --output
  • -c is short form for --config
  • -j is short form for --jobs

Deprecated Options

The following options are deprecated and should be migrated:

  • --cache (hidden) - Deprecated: caching is now enabled by default
    • Migration: Remove this flag, use --no-cache to disable if needed
  • --explain-score (hidden) - Deprecated: use -v instead
    • Migration: Use -v, -vv, or -vvv for increasing verbosity levels

Configuration

Configuration File

Created via debtmap init command. The configuration file (debtmap.toml) is used by the validate command for threshold enforcement and default settings.

Creating Configuration:

# Create new config
debtmap init

# Overwrite existing config
debtmap init --force

Environment Variables

  • DEBTMAP_CACHE_DIR - Override default cache directory location
    • Can also be set via --cache-location flag
    • Affects where analysis results are cached for faster subsequent runs

Getting Help

Get help for any command:

# General help
debtmap --help

# Command-specific help
debtmap analyze --help
debtmap validate --help
debtmap compare --help
debtmap init --help

Common Workflows

Basic Analysis

Analyze a project and view results in terminal:

debtmap analyze src/

Generate JSON report for further processing:

debtmap analyze . --format json --output report.json

Generate Markdown report:

debtmap analyze . --format markdown --output report.md

Coverage-Integrated Analysis

Analyze with test coverage to surface untested complex code:

# Generate coverage file first (example for Rust)
cargo tarpaulin --out lcov

# Run analysis with coverage
debtmap analyze src/ --coverage-file lcov.info

Coverage dampens debt scores for well-tested code, making untested complex functions more visible.

Context-Aware Analysis

Enable context providers for risk-aware prioritization:

# Use all context providers
debtmap analyze . --context

# Use specific context providers
debtmap analyze . --context --context-providers critical_path,git_history

Context-aware analysis reduces false positives and prioritizes code based on:

  • Critical execution paths
  • Dependency relationships
  • Git history (change frequency)

Filtered & Focused Analysis

Show only top priority items:

debtmap analyze . --top 10 --min-priority high

Filter by specific debt categories:

debtmap analyze . --filter complexity,duplication

Use summary mode for compact output:

debtmap analyze . --summary

Show only file-level aggregations:

debtmap analyze . --aggregate-only

Performance Tuning

Control parallelization:

# Use 8 threads
debtmap analyze . --jobs 8

# Disable parallel processing
debtmap analyze . --no-parallel

Manage caching:

# Use shared cache location
debtmap analyze . --cache-location shared

# Clear cache and rebuild
debtmap analyze . --clear-cache

# Show cache statistics
debtmap analyze . --cache-stats

Limit analysis scope:

# Analyze maximum 100 files
debtmap analyze . --max-files 100

# Analyze specific languages only
debtmap analyze . --languages rust,python

CI/CD Integration

Use the validate command in CI/CD pipelines:

# Initialize configuration (one time)
debtmap init

# Edit debtmap.toml to set thresholds
# ...

# In CI pipeline: validate against thresholds
debtmap validate . --config debtmap.toml --max-debt-density 50

The validate command returns non-zero exit code if thresholds are exceeded, failing the build.

Comparison & Tracking

Compare analysis results before and after changes:

# Before changes
debtmap analyze . --format json --output before.json

# Make code changes...

# After changes
debtmap analyze . --format json --output after.json

# Generate comparison report
debtmap compare --before before.json --after after.json --format markdown

With implementation plan:

debtmap compare --before before.json --after after.json --plan IMPLEMENTATION_PLAN.md

Debugging Analysis

Increase verbosity to understand scoring:

# Show main score factors
debtmap analyze src/ -v

# Show detailed calculations
debtmap analyze src/ -vv

# Show all debug information
debtmap analyze src/ -vvv

Show macro expansion statistics (Rust):

debtmap analyze . --show-macro-stats --verbose-macro-warnings

Use detailed diagnostic reports:

debtmap analyze . --detail-level comprehensive

Examples

Basic Analysis

# Analyze current directory
debtmap analyze .

# Analyze specific directory
debtmap analyze src/

# Generate JSON output
debtmap analyze . --format json --output report.json

With Coverage

# Analyze with LCOV coverage file
debtmap analyze src/ --coverage-file coverage.lcov

# Alternative alias
debtmap analyze src/ --lcov coverage.lcov

Context-Aware Analysis

# Enable all context providers
debtmap analyze . --context

# Use specific context providers
debtmap analyze . --context --context-providers critical_path,git_history

# Disable specific providers
debtmap analyze . --context --disable-context dependency

Filtered Output

# Top 10 priority items only
debtmap analyze . --top 10

# High priority and above
debtmap analyze . --min-priority high

# Specific categories
debtmap analyze . --filter complexity,duplication

# Summary format
debtmap analyze . --summary

# Group by category
debtmap analyze . --group-by-category

Performance Tuning

# Use 8 threads
debtmap analyze . --jobs 8

# Disable parallelization
debtmap analyze . --no-parallel

# Limit file count
debtmap analyze . --max-files 100

# Shared cache
debtmap analyze . --cache-location shared

# Clear and rebuild cache
debtmap analyze . --clear-cache

Validation

# Initialize config
debtmap init --force

# Validate against config
debtmap validate . --config debtmap.toml

# With max debt density threshold
debtmap validate . --max-debt-density 50

Comparison

# Compare two analyses
debtmap compare --before before.json --after after.json

# With markdown output
debtmap compare --before before.json --after after.json --format markdown

# With implementation plan
debtmap compare --before before.json --after after.json --plan IMPLEMENTATION_PLAN.md

# With target location
debtmap compare --before before.json --after after.json --target-location "src/main.rs:process_file:42"

Language Selection

# Analyze only Rust files
debtmap analyze . --languages rust

# Multiple languages
debtmap analyze . --languages rust,python,javascript

Threshold Configuration

# Custom complexity threshold
debtmap analyze . --threshold-complexity 15

# Use preset
debtmap analyze . --threshold-preset strict

# Custom duplication threshold
debtmap analyze . --threshold-duplication 100

Plain/Machine-Readable Output

# Plain output (no colors, no emoji)
debtmap analyze . --plain

# Combine with JSON for CI
debtmap analyze . --format json --plain --output report.json

Command Compatibility Matrix

Optionanalyzevalidatecompareinit
<PATH> argument
--format
--output
--coverage-file
--context
--threshold-*
--top / --tail
--cache-*
--jobs
--verbose
--config
--before / --after
--force

Note: The validate command supports output control (--format, --output), coverage integration (--coverage-file), context-aware analysis (--context), display filtering (--top, --tail, --summary), and verbosity options (--verbose) from the analyze command. Analysis thresholds (--threshold-complexity, --threshold-duplication, --threshold-preset) are configured via the --config file rather than as command-line options. Performance options like --cache-* and --jobs are specific to the analyze command.

Troubleshooting

Performance Issues

Problem: Analysis is slow on large codebases

Solutions:

# Use more threads (if you have CPU cores available)
debtmap analyze . --jobs 16

# Enable caching (on by default, but ensure it's not disabled)
debtmap analyze . # caching is automatic

# Use shared cache for team
debtmap analyze . --cache-location shared

# Limit analysis scope
debtmap analyze . --max-files 500 --languages rust

Memory Issues

Problem: Analysis runs out of memory

Solutions:

# Disable parallelization
debtmap analyze . --no-parallel

# Limit file count
debtmap analyze . --max-files 100

# Analyze in batches by language
debtmap analyze . --languages rust
debtmap analyze . --languages python

Output Issues

Problem: Terminal output has garbled characters

Solution:

# Use plain mode
debtmap analyze . --plain

Problem: Want machine-readable output

Solution:

# Use JSON with plain mode
debtmap analyze . --format json --plain --output report.json

Cache Issues

Problem: Stale cached results

Solutions:

# Clear cache
debtmap analyze . --clear-cache

# Check cache statistics
debtmap analyze . --cache-stats

# Disable cache temporarily
debtmap analyze . --no-cache

Threshold Issues

Problem: Too many items flagged

Solutions:

# Use lenient preset
debtmap analyze . --threshold-preset lenient

# Increase threshold
debtmap analyze . --threshold-complexity 20

# Filter to high priority only
debtmap analyze . --min-priority high

Problem: Not enough items flagged

Solutions:

# Use strict preset
debtmap analyze . --threshold-preset strict

# Lower threshold
debtmap analyze . --threshold-complexity 5

# Show all items
debtmap analyze . --min-priority low

Best Practices

Regular Analysis

Run analysis regularly to track code quality trends:

# Daily in CI
debtmap validate . --config debtmap.toml

# Weekly deep analysis with coverage
debtmap analyze . --coverage-file coverage.lcov --format json --output weekly-report.json

Team Workflows

Use shared cache for consistent team experience:

# Set environment variable for all team members
export DEBTMAP_CACHE_DIR=/shared/team/debtmap-cache

# Or use flag
debtmap analyze . --cache-location shared

Performance Optimization

For large codebases:

# Use maximum parallelization
debtmap analyze . --jobs 0  # 0 = all cores

# Cache aggressively
debtmap analyze . --cache-location shared

# Focus on changed files in CI
# (implement via custom scripts to analyze git diff)

Integration with Coverage

Always analyze with coverage when available:

# Rust example
cargo tarpaulin --out lcov
debtmap analyze src/ --coverage-file lcov.info

# Python example
pytest --cov --cov-report=lcov
debtmap analyze . --coverage-file coverage.lcov

Coverage integration helps prioritize untested complex code.

Additional Tools

prodigy-validate-debtmap-improvement

Specialized validation tool for Prodigy workflow integration.

Description: This binary is part of the Prodigy workflow system and provides specialized validation for Debtmap improvement workflows.

Usage: See Prodigy documentation for detailed usage instructions.

See Also

Analysis Guide

This guide explains Debtmap’s analysis capabilities, metrics, and methodologies in depth. Use this to understand what Debtmap measures, how it scores technical debt, and how to interpret analysis results for maximum impact.

Overview

Debtmap analyzes code through multiple lenses to provide a comprehensive view of technical health:

  • Complexity Metrics - Quantifies how difficult code is to understand and test
  • Debt Patterns - Identifies 13 types of technical debt requiring attention
  • Risk Scoring - Correlates complexity with test coverage to find truly risky code
  • Prioritization - Ranks findings by impact to guide refactoring efforts

The goal is to move beyond simple “here are your problems” to “here’s what to fix first and why.”

Complexity Metrics

Debtmap measures complexity using multiple complementary approaches. Each metric captures a different aspect of code difficulty.

Cyclomatic Complexity

Measures the number of linearly independent paths through code - essentially counting decision points.

How it works:

  • Start with a base complexity of 1
  • Add 1 for each: if, else if, match arm, while, for, &&, ||, ? operator
  • Does NOT increase for else (it’s the alternate path, not a new decision)

Thresholds:

  • 1-5: Simple, easy to test - typically needs 1-3 test cases
  • 6-10: Moderate complexity - needs 4-8 test cases
  • 11-20: Complex, consider refactoring - needs 9+ test cases
  • 20+: Very complex, high risk - difficult to test thoroughly

Example:

#![allow(unused)]
fn main() {
fn validate_user(age: u32, has_license: bool, country: &str) -> bool {
    // Complexity: 4
    // Base (1) + if (1) + && (1) + match (1) = 4
    if age >= 18 && has_license {
        match country {
            "US" | "CA" => true,
            _ => false,
        }
    } else {
        false
    }
}
}

Cognitive Complexity

Measures how difficult code is to understand by considering nesting depth and control flow interruptions.

How it differs from cyclomatic:

  • Nesting increases weight (deeply nested code is harder to understand)
  • Linear sequences don’t increase complexity (easier to follow)
  • Breaks and continues add complexity (interrupt normal flow)

Calculation:

  • Each structure (if, loop, match) gets a base score
  • Nesting multiplies the weight (nested structures = harder to understand)
  • Break/continue/return in middle of function adds cognitive load

Example:

#![allow(unused)]
fn main() {
// Cyclomatic: 5, Cognitive: 8
fn process_items(items: Vec<Item>) -> Vec<Result> {
    let mut results = vec![];

    for item in items {                    // +1 cognitive
        if item.is_valid() {               // +2 (nested in loop)
            match item.type {              // +3 (nested 2 levels)
                Type::A => results.push(process_a(item)),
                Type::B => {
                    if item.priority > 5 { // +4 (nested 3 levels)
                        results.push(process_b_priority(item));
                    }
                }
                _ => continue,             // +1 (control flow interruption)
            }
        }
    }

    results
}
}

Thresholds:

  • 0-5: Trivial - anyone can understand
  • 6-10: Simple - straightforward logic
  • 11-20: Moderate - requires careful reading
  • 21-40: Complex - difficult to understand
  • 40+: Very complex - needs refactoring

Entropy-Based Complexity Analysis

Uses information theory to distinguish genuinely complex code from pattern-based repetitive code. This dramatically reduces false positives for validation functions, dispatchers, and configuration parsers.

How it works:

  1. Token Entropy (0.0-1.0): Measures variety in code tokens

    • High entropy (0.7+): Diverse logic, genuinely complex
    • Low entropy (0.0-0.4): Repetitive patterns, less complex than it appears
  2. Pattern Repetition (0.0-1.0): Detects repetitive structures in AST

    • High repetition (0.7+): Similar blocks repeated (validation checks, case handlers)
    • Low repetition: Unique logic throughout
  3. Branch Similarity (0.0-1.0): Analyzes similarity between conditional branches

    • High similarity (0.8+): Branches do similar things (consistent handling)
    • Low similarity: Each branch has unique logic
  4. Token Classification: Categorizes tokens by type with weighted importance

    • Variables, methods, literals weighted differently
    • Focuses on structural complexity over superficial differences

Dampening logic: Dampening is applied when multiple factors indicate repetitive patterns:

  • Low token entropy (< 0.4) indicates simple, repetitive patterns
  • High pattern repetition (> 0.6) shows similar code blocks
  • High branch similarity (> 0.7) indicates consistent branching logic

When these conditions are met:

effective_complexity = entropy × pattern_factor × similarity_factor

Dampening cap: The dampening factor has a minimum of 0.7, ensuring no more than 30% reduction in complexity scores. This prevents over-correction of pattern-based code and maintains a baseline complexity floor for functions that still require understanding and maintenance.

Example:

#![allow(unused)]
fn main() {
// Without entropy: Cyclomatic = 15 (appears very complex)
// With entropy: Effective = 5 (pattern-based, dampened 67%)
fn validate_config(config: &Config) -> Result<(), ValidationError> {
    if config.name.is_empty() { return Err(ValidationError::EmptyName); }
    if config.port == 0 { return Err(ValidationError::InvalidPort); }
    if config.host.is_empty() { return Err(ValidationError::EmptyHost); }
    if config.timeout == 0 { return Err(ValidationError::InvalidTimeout); }
    // ... 11 more similar checks
    Ok(())
}
}

Enable in .debtmap.toml:

[entropy]
enabled = true                 # Enable entropy analysis (default: true)
weight = 0.5                  # Weight in adjustment (0.0-1.0)
use_classification = true     # Advanced token classification
pattern_threshold = 0.7       # Pattern detection threshold
entropy_threshold = 0.4       # Entropy below this triggers dampening
branch_threshold = 0.8        # Branch similarity threshold
max_combined_reduction = 0.3  # Maximum 30% reduction

Output fields in EntropyScore:

  • unique_variables: Count of distinct variables in the function (measures variable diversity)
  • max_nesting: Maximum nesting depth detected (contributes to dampening calculation)
  • dampening_applied: Actual dampening factor applied to the complexity score

Nesting Depth

Maximum level of indentation in a function. Deep nesting makes code hard to follow.

Thresholds:

  • 1-2: Flat, easy to read
  • 3-4: Moderate nesting
  • 5+: Deep nesting, consider extracting functions

Example:

#![allow(unused)]
fn main() {
// Nesting depth: 4 (difficult to follow)
fn process(data: Data) -> Result<Output> {
    if data.is_valid() {                    // Level 1
        for item in data.items {            // Level 2
            if item.active {                // Level 3
                match item.type {           // Level 4
                    Type::A => { /* ... */ }
                    Type::B => { /* ... */ }
                }
            }
        }
    }
}
}

Refactored:

#![allow(unused)]
fn main() {
// Nesting depth: 2 (much clearer)
fn process(data: Data) -> Result<Output> {
    if !data.is_valid() {
        return Err(Error::Invalid);
    }

    data.items
        .iter()
        .filter(|item| item.active)
        .map(|item| process_item(item))     // Extract to separate function
        .collect()
}
}

Function Length

Number of lines in a function. Long functions often violate single responsibility principle.

Thresholds:

  • 1-20 lines: Good - focused, single purpose
  • 21-50 lines: Acceptable - may have multiple steps
  • 51-100 lines: Long - consider breaking up
  • 100+ lines: Very long - definitely needs refactoring

Why length matters:

  • Harder to understand and remember
  • Harder to test thoroughly
  • Often violates single responsibility
  • Difficult to reuse

Debt Patterns

Debtmap detects 24 types of technical debt, organized into 4 strategic categories. Each debt type is mapped to a category that guides prioritization and remediation strategies.

Debt Type Enum

The DebtType enum defines all specific debt patterns that Debtmap can detect:

Testing Debt:

  • TestingGap - Functions with insufficient test coverage
  • TestTodo - TODO comments in test code
  • TestComplexity - Test functions exceeding complexity thresholds
  • TestDuplication - Duplicated code in test files
  • TestComplexityHotspot - Complex test logic that’s hard to maintain
  • AssertionComplexity - Complex test assertions
  • FlakyTestPattern - Non-deterministic test behavior

Architecture Debt:

  • ComplexityHotspot - Functions exceeding complexity thresholds
  • DeadCode - Unreachable or unused code
  • GodObject - Classes with too many responsibilities
  • GodModule - Modules with too many responsibilities
  • FeatureEnvy - Using more data from other objects than own
  • PrimitiveObsession - Overusing basic types instead of domain objects
  • MagicValues - Unexplained literal values

Performance Debt:

  • AllocationInefficiency - Inefficient memory allocations
  • StringConcatenation - Inefficient string building in loops
  • NestedLoops - Multiple nested iterations (O(n²) or worse)
  • BlockingIO - Blocking I/O in async contexts
  • SuboptimalDataStructure - Wrong data structure for access pattern
  • AsyncMisuse - Improper async/await usage
  • ResourceLeak - Resources not properly released
  • CollectionInefficiency - Inefficient collection operations

Code Quality Debt:

  • Risk - High-risk code (complex + poorly tested)
  • Duplication - Duplicated code blocks
  • ErrorSwallowing - Errors caught but ignored

Debt Categories

The DebtCategory enum groups debt types into strategic categories:

#![allow(unused)]
fn main() {
pub enum DebtCategory {
    Architecture,  // Structure, design, complexity
    Testing,       // Coverage, test quality
    Performance,   // Speed, memory, efficiency
    CodeQuality,   // Maintainability, readability
}
}

Category Mapping:

Debt TypeCategoryStrategic Focus
ComplexityHotspot, DeadCode, GodObject, GodModule, FeatureEnvy, PrimitiveObsession, MagicValuesArchitectureStructural improvements, design patterns
TestingGap, TestTodo, TestComplexity, TestDuplication, TestComplexityHotspot, AssertionComplexity, FlakyTestPatternTestingTest coverage, test quality
AllocationInefficiency, StringConcatenation, NestedLoops, BlockingIO, SuboptimalDataStructure, AsyncMisuse, ResourceLeak, CollectionInefficiencyPerformanceRuntime efficiency, resource usage
Risk, Duplication, ErrorSwallowingCodeQualityMaintainability, reliability

Examples by Category

Architecture Debt

ComplexityHotspot: Functions exceeding complexity thresholds

#![allow(unused)]
fn main() {
// Cyclomatic: 22, Cognitive: 35
fn process_transaction(tx: Transaction, account: &mut Account) -> Result<Receipt> {
    if tx.amount <= 0 {
        return Err(Error::InvalidAmount);
    }
    // ... deeply nested logic with many branches
    Ok(receipt)
}
}

When detected: Cyclomatic > 10 OR Cognitive > 15 (configurable) Action: Break into smaller functions, extract validation, simplify control flow

GodObject / GodModule: Too many responsibilities

#![allow(unused)]
fn main() {
// God module: handles parsing, validation, storage, notifications
mod user_service {
    fn parse_user() { /* ... */ }
    fn validate_user() { /* ... */ }
    fn save_user() { /* ... */ }
    fn send_email() { /* ... */ }
    fn log_activity() { /* ... */ }
    // ... 20+ more functions
}
}

When detected: Pattern analysis for responsibility clustering Action: Split into focused modules (parser, validator, repository, notifier)

MagicValues: Unexplained literals

#![allow(unused)]
fn main() {
// Bad: Magic numbers
fn calculate_price(quantity: u32) -> f64 {
    quantity as f64 * 19.99 + 5.0  // What are these numbers?
}

// Good: Named constants
const UNIT_PRICE: f64 = 19.99;
const SHIPPING_COST: f64 = 5.0;
fn calculate_price(quantity: u32) -> f64 {
    quantity as f64 * UNIT_PRICE + SHIPPING_COST
}
}

Testing Debt

TestingGap: Functions with insufficient test coverage

#![allow(unused)]
fn main() {
// 0% coverage - critical business logic untested
fn calculate_tax(amount: f64, region: &str) -> f64 {
    // Complex tax calculation logic
    // No tests exist for this function!
}
}

When detected: Coverage data shows function has < 80% line coverage Action: Add unit tests to cover all branches and edge cases

TestComplexity: Test functions too complex

#![allow(unused)]
fn main() {
#[test]
fn complex_test() {
    // Cyclomatic: 12 (too complex for a test)
    for input in test_cases {
        if input.is_special() {
            match input.type {
                /* complex test logic */
            }
        }
    }
}
}

When detected: Test functions with cyclomatic > 10 or cognitive > 15 Action: Split into multiple focused tests, use test fixtures

FlakyTestPattern: Non-deterministic tests

#![allow(unused)]
fn main() {
#[test]
fn flaky_test() {
    let result = async_operation().await;  // Timing-dependent
    thread::sleep(Duration::from_millis(100));  // Race condition!
    assert_eq!(result.status, "complete");
}
}

When detected: Pattern analysis for timing dependencies, random values Action: Use mocks, deterministic test data, proper async test utilities

Performance Debt

AllocationInefficiency: Excessive allocations

#![allow(unused)]
fn main() {
// Bad: Allocates on every iteration
fn process_items(items: &[Item]) -> Vec<String> {
    let mut results = Vec::new();
    for item in items {
        results.push(item.name.clone());  // Unnecessary clone
    }
    results
}

// Good: Pre-allocate, avoid clones
fn process_items(items: &[Item]) -> Vec<&str> {
    items.iter().map(|item| item.name.as_str()).collect()
}
}

BlockingIO: Blocking operations in async contexts

#![allow(unused)]
fn main() {
// Bad: Blocks async runtime
async fn load_data() -> Result<Data> {
    let file = std::fs::read_to_string("data.json")?;  // Blocking!
    parse_json(&file)
}

// Good: Async I/O
async fn load_data() -> Result<Data> {
    let file = tokio::fs::read_to_string("data.json").await?;
    parse_json(&file)
}
}

NestedLoops: O(n²) or worse complexity

#![allow(unused)]
fn main() {
// Bad: O(n²) nested loops
fn find_duplicates(items: &[Item]) -> Vec<(Item, Item)> {
    let mut dupes = vec![];
    for i in 0..items.len() {
        for j in i+1..items.len() {
            if items[i] == items[j] {
                dupes.push((items[i].clone(), items[j].clone()));
            }
        }
    }
    dupes
}

// Good: O(n) with HashSet
fn find_duplicates(items: &[Item]) -> Vec<Item> {
    let mut seen = HashSet::new();
    items.iter().filter(|item| !seen.insert(item)).cloned().collect()
}
}

Code Quality Debt

Duplication: Duplicated code blocks

#![allow(unused)]
fn main() {
// File A:
fn process_user(user: User) -> Result<()> {
    validate_email(&user.email)?;
    validate_age(user.age)?;
    save_to_database(&user)?;
    send_welcome_email(&user.email)?;
    Ok(())
}

// File B: Duplicated validation
fn process_admin(admin: Admin) -> Result<()> {
    validate_email(&admin.email)?;  // Duplicated
    validate_age(admin.age)?;       // Duplicated
    save_to_database(&admin)?;
    grant_admin_privileges(&admin)?;
    Ok(())
}
}

When detected: Similar code blocks > 50 lines (configurable) Action: Extract shared code into reusable functions

ErrorSwallowing: Errors caught but ignored

#![allow(unused)]
fn main() {
// Bad: Error swallowed, no context
match risky_operation() {
    Ok(result) => process(result),
    Err(_) => {}, // Silent failure!
}

// Good: Error handled with context
match risky_operation() {
    Ok(result) => process(result),
    Err(e) => {
        log::error!("Risky operation failed: {}", e);
        return Err(e.into());
    }
}
}

When detected: Empty catch blocks, ignored Results Action: Add proper error logging and propagation

Risk: High-risk code (complex + poorly tested)

#![allow(unused)]
fn main() {
// Cyclomatic: 18, Coverage: 20%, Risk Score: 47.6 (HIGH)
fn process_payment(tx: Transaction) -> Result<Receipt> {
    // Complex payment logic with minimal testing
    // High risk of bugs in production
}
}

When detected: Combines complexity metrics with coverage data Action: Either add comprehensive tests OR refactor to reduce complexity

Debt Scoring Formula

Each debt item gets a score based on priority and type:

debt_score = priority_weight × type_weight

Priority weights:

  • Low = 1
  • Medium = 3
  • High = 5
  • Critical = 10

Combined examples:

  • Low Todo = 1 × 1 = 1
  • Medium Fixme = 3 × 2 = 6
  • High Complexity = 5 × 5 = 25
  • Critical Complexity = 10 × 5 = 50

Total debt score = Sum of all debt item scores

Lower is better. Track over time to measure improvement.

Risk Scoring

Debtmap’s risk scoring identifies code that is both complex AND poorly tested - the true risk hotspots.

Unified Scoring System

Debtmap uses a unified scoring system (0-10 scale) as the primary prioritization mechanism. This multi-factor approach balances complexity, test coverage, and dependency impact, adjusted by function role.

Score Scale and Priority Classifications

Functions receive scores from 0 (minimal risk) to 10 (critical risk):

Score RangePriorityDescriptionAction
9.0-10.0CriticalSevere risk requiring immediate attentionAddress immediately
7.0-8.9HighSignificant risk, should be addressed soonPlan for this sprint
5.0-6.9MediumModerate risk, plan for future workSchedule for next sprint
3.0-4.9LowMinor risk, lower priorityMonitor and address as time permits
0.0-2.9MinimalWell-managed codeContinue monitoring

Scoring Formula

The unified score combines three weighted factors:

Base Score = (Complexity Factor × 0.40) + (Coverage Factor × 0.40) + (Dependency Factor × 0.20)

Final Score = Base Score × Role Multiplier

Factor Calculations:

Complexity Factor (0-10 scale):

Complexity Factor = min(10, ((cyclomatic / 10) + (cognitive / 20)) × 5)

Normalized to 0-10 range based on cyclomatic and cognitive complexity.

Coverage Factor (0-10 scale):

Coverage Factor = 10 × (1 - coverage_percentage) × complexity_weight

Uncovered complex code scores higher than uncovered simple code. Coverage dampens the score - well-tested code gets lower scores.

Dependency Factor (0-10 scale): Based on call graph analysis:

  • High upstream caller count (many functions depend on this): 8-10
  • On critical paths from entry points: 7-9
  • Moderate dependencies: 4-6
  • Isolated utilities: 1-3

Default Weights

The scoring formula uses configurable weights (default values shown):

  • Complexity: 40% - How difficult the code is to understand and test
  • Coverage: 40% - How well the code is tested
  • Dependency: 20% - How many other functions depend on this code

These weights can be adjusted in .debtmap.toml to match your team’s priorities.

Role-Based Prioritization

The unified score is multiplied by a role multiplier based on the function’s semantic classification:

RoleMultiplierDescriptionExample
Entry Points1.5×main(), HTTP handlers, API endpointsUser-facing code where bugs have immediate impact
Business Logic1.2×Core domain functions, algorithmsCritical functionality
Data Access1.0×Database queries, file I/OBaseline importance
Infrastructure0.8×Logging, configuration, monitoringSupporting code
Utilities0.5×Helpers, formatters, convertersLower impact
Test Code0.1×Test functions, fixtures, mocksInternal quality

How role classification works:

Debtmap identifies function roles through pattern analysis:

  • Entry points: Functions named main, handlers with routing decorators, public API functions
  • Business logic: Core domain operations, calculation functions, decision-making code
  • Data access: Database queries, file operations, network calls
  • Infrastructure: Logging, config parsing, monitoring, error handling
  • Utilities: Helper functions, formatters, type converters, validators
  • Test code: Functions in test modules, test functions, fixtures

Example: Same complexity, different priorities

Consider a function with base score 8.0:

If classified as Entry Point:
  Final Score = 8.0 × 1.5 = 12.0 (capped at 10.0) → CRITICAL priority

If classified as Business Logic:
  Final Score = 8.0 × 1.2 = 9.6 → CRITICAL priority

If classified as Data Access:
  Final Score = 8.0 × 1.0 = 8.0 → HIGH priority

If classified as Utility:
  Final Score = 8.0 × 0.5 = 4.0 → LOW priority

This ensures that complex code in critical paths gets higher priority than equally complex utility code.

Coverage Propagation

Coverage impact flows through the call graph using transitive coverage:

Transitive Coverage = Direct Coverage + Σ(Caller Coverage × Weight)

How it works:

Functions called by well-tested code inherit some coverage benefit, reducing their urgency. This helps identify which untested functions are on critical paths versus safely isolated utilities.

Example scenarios:

Scenario 1: Untested function with well-tested callers

Function A: 0% direct coverage
  Called by:
    - handle_request (95% coverage)
    - process_payment (90% coverage)
    - validate_order (88% coverage)

Transitive coverage: ~40% (inherits coverage benefit from callers)
Final priority: Lower than isolated 0% coverage function

Scenario 2: Untested function on critical path

Function B: 0% direct coverage
  Called by:
    - main (0% coverage)
    - startup (10% coverage)

Transitive coverage: ~5% (minimal coverage benefit)
Final priority: Higher - on critical path with no safety net

Coverage propagation prevents false alarms about utility functions called only by well-tested code, while highlighting genuinely risky untested code on critical paths.

Unified Score Example

Function: process_payment
  Location: src/payments.rs:145

Metrics:
  - Cyclomatic complexity: 18
  - Cognitive complexity: 25
  - Test coverage: 20%
  - Upstream callers: 3 (high dependency)
  - Role: Business Logic

Calculation:
  Complexity Factor = min(10, ((18/10) + (25/20)) × 5) = min(10, 8.75) = 8.75
  Coverage Factor = 10 × (1 - 0.20) × 1.0 = 8.0
  Dependency Factor = 7.5 (3 upstream callers, moderate impact)

  Base Score = (8.75 × 0.40) + (8.0 × 0.40) + (7.5 × 0.20)
             = 3.5 + 3.2 + 1.5
             = 8.2

  Final Score = 8.2 × 1.2 (Business Logic multiplier)
              = 9.84 → CRITICAL priority

Legacy Risk Scoring (Pre-0.2.x)

Prior to the unified scoring system, Debtmap used a simpler additive risk formula. This is still available for compatibility but unified scoring is now the default and provides better prioritization.

Risk Categories

Note: The RiskLevel enum (Low, Medium, High, Critical) is used for legacy risk scoring compatibility. When using unified scoring (0-10 scale), refer to the priority classifications shown in the Unified Scoring System section above.

Legacy RiskLevel Enum

For legacy risk scoring, Debtmap classifies functions into four risk levels:

#![allow(unused)]
fn main() {
pub enum RiskLevel {
    Low,       // Score < 10
    Medium,    // Score 10-24
    High,      // Score 25-49
    Critical,  // Score ≥ 50
}
}

Critical (legacy score ≥ 50)

  • High complexity (cyclomatic > 15) AND low coverage (< 30%)
  • Untested code that’s likely to break and hard to fix
  • Action: Immediate attention required - add tests or refactor

High (legacy score 25-49)

  • High complexity (cyclomatic > 10) AND moderate coverage (< 60%)
  • Risky code with incomplete testing
  • Action: Should be addressed soon

Medium (legacy score 10-24)

  • Moderate complexity (cyclomatic > 5) AND low coverage (< 50%)
  • OR: High complexity with good coverage
  • Action: Plan for next sprint

Low (legacy score < 10)

  • Low complexity OR high coverage
  • Well-managed code
  • Action: Monitor, low priority

Unified Scoring Priority Levels

When using unified scoring (default), functions are classified using the 0-10 scale:

  • Critical (9.0-10.0): Immediate attention
  • High (7.0-8.9): Address this sprint
  • Medium (5.0-6.9): Plan for next sprint
  • Low (3.0-4.9): Monitor and address as time permits
  • Minimal (0.0-2.9): Well-managed code

Well-tested complex code is an outcome in both systems, not a separate category:

  • Complex function (cyclomatic 18, cognitive 25) with 95% coverage
  • Unified score: ~2.5 (Minimal priority due to coverage dampening)
  • Legacy risk score: ~8 (Low risk)
  • Falls into low-priority categories because good testing mitigates complexity
  • This is the desired state for inherently complex business logic

Legacy Risk Calculation

Note: The legacy risk calculation is still supported for compatibility but has been superseded by the unified scoring system (see above). Unified scoring provides better prioritization through its multi-factor, weighted approach with role-based adjustments.

The legacy risk score uses a simpler additive formula:

#![allow(unused)]
fn main() {
risk_score = complexity_factor + coverage_factor + debt_factor

where:
  complexity_factor = (cyclomatic / 5) + (cognitive / 10)
  coverage_factor = (1 - coverage_percentage) × 50
  debt_factor = debt_score / 10  // If debt data available
}

Example (legacy scoring):

Function: process_payment
  - Cyclomatic complexity: 18
  - Cognitive complexity: 25
  - Coverage: 20%
  - Debt score: 15

Calculation:
  complexity_factor = (18 / 5) + (25 / 10) = 3.6 + 2.5 = 6.1
  coverage_factor = (1 - 0.20) × 50 = 40
  debt_factor = 15 / 10 = 1.5

  risk_score = 6.1 + 40 + 1.5 = 47.6 (HIGH RISK)

When to use legacy scoring:

  • Comparing with historical data from older Debtmap versions
  • Teams with existing workflows built around the old scale
  • Gradual migration to unified scoring

Why unified scoring is better:

  • Normalized 0-10 scale is more intuitive
  • Weighted factors (40% complexity, 40% coverage, 20% dependency) provide better balance
  • Role multipliers adjust priority based on function importance
  • Coverage propagation reduces false positives for utility functions

Test Effort Assessment

Debtmap estimates testing difficulty based on cognitive complexity:

Difficulty Levels:

  • Trivial (cognitive < 5): 1-2 test cases, < 1 hour
  • Simple (cognitive 5-10): 3-5 test cases, 1-2 hours
  • Moderate (cognitive 10-20): 6-10 test cases, 2-4 hours
  • Complex (cognitive 20-40): 11-20 test cases, 4-8 hours
  • VeryComplex (cognitive > 40): 20+ test cases, 8+ hours

Test Effort includes:

  • Cognitive load: How hard to understand the function
  • Branch count: Number of paths to test
  • Recommended test cases: Suggested number of tests

Risk Distribution

Debtmap provides codebase-wide risk metrics:

{
  "risk_distribution": {
    "critical_count": 12,
    "high_count": 45,
    "medium_count": 123,
    "low_count": 456,
    "minimal_count": 234,
    "total_functions": 870
  },
  "codebase_risk_score": 1247.5
}

Interpreting distribution:

  • Healthy codebase: Most functions in Low/Minimal priority (unified scoring) or Low/WellTested (legacy)
  • Needs attention: Many Critical/High priority functions
  • Technical debt: High codebase risk score

Note on well-tested functions: In unified scoring, well-tested complex code simply scores low (0-2.9 Minimal or 3-4.9 Low) due to coverage dampening - it’s not a separate category. The minimal_count in the distribution represents functions with unified scores 0-2.9, which includes well-tested complex code.

Testing Recommendations

When coverage data is provided, Debtmap generates prioritized testing recommendations with ROI analysis:

{
  "function": "process_transaction",
  "file": "src/payments.rs",
  "line": 145,
  "current_risk": 47.6,
  "potential_risk_reduction": 35.2,
  "test_effort_estimate": {
    "estimated_difficulty": "Complex",
    "cognitive_load": 25,
    "branch_count": 18,
    "recommended_test_cases": 12
  },
  "roi": 4.4,
  "rationale": "High complexity with low coverage (20%) and 3 downstream dependencies. Testing will reduce risk by 74%.",
  "dependencies": {
    "upstream_callers": ["handle_payment_request"],
    "downstream_callees": ["validate_amount", "check_balance", "record_transaction"]
  }
}

ROI calculation:

roi = potential_risk_reduction / estimated_effort_hours

Higher ROI = better return on testing investment

Interpreting Results

Understanding Output Formats

Debtmap provides three output formats:

Terminal (default): Human-readable with colors and tables

debtmap analyze .

JSON: Machine-readable for CI/CD integration

debtmap analyze . --format json --output report.json

Markdown: Documentation-friendly

debtmap analyze . --format markdown --output report.md

JSON Structure

{
  "timestamp": "2025-10-09T12:00:00Z",
  "project_path": "/path/to/project",
  "complexity": {
    "metrics": [
      {
        "name": "process_data",
        "file": "src/main.rs",
        "line": 42,
        "cyclomatic": 15,
        "cognitive": 22,
        "nesting": 4,
        "length": 68,
        "is_test": false,
        "visibility": "Public",
        "is_trait_method": false,
        "in_test_module": false,
        "entropy_score": {
          "token_entropy": 0.65,
          "pattern_repetition": 0.25,
          "branch_similarity": 0.30,
          "effective_complexity": 0.85
        },
        "is_pure": false,
        "purity_confidence": 0.8,
        "detected_patterns": ["validation_pattern"],
        "upstream_callers": ["main", "process_request"],
        "downstream_callees": ["validate", "save", "notify"]
      }
    ],
    "summary": {
      "total_functions": 150,
      "average_complexity": 5.3,
      "max_complexity": 22,
      "high_complexity_count": 8
    }
  },
  "technical_debt": {
    "items": [
      {
        "id": "complexity_src_main_rs_42",
        "debt_type": "Complexity",
        "priority": "High",
        "file": "src/main.rs",
        "line": 42,
        "column": 1,
        "message": "Function exceeds complexity threshold",
        "context": "Cyclomatic: 15, Cognitive: 22"
      }
    ],
    "by_type": {
      "Complexity": [...],
      "Duplication": [...],
      "Todo": [...]
    }
  }
}

Reading Function Metrics

Key fields:

  • cyclomatic: Decision points - guides test case count
  • cognitive: Understanding difficulty - guides refactoring priority
  • nesting: Indentation depth - signals need for extraction
  • length: Lines of code - signals SRP violations
  • visibility: Function visibility ("Private", "Crate", or "Public" from FunctionVisibility enum)
  • is_pure: No side effects - easier to test (Option type, may be None)
  • purity_confidence: How certain we are about purity 0.0-1.0 (Option type, may be None)
  • is_trait_method: Whether this function implements a trait method
  • in_test_module: Whether function is inside a #[cfg(test)] module
  • detected_patterns: Complexity adjustment patterns identified (e.g., “validation_pattern”)
  • entropy_score: Pattern analysis for false positive reduction
  • upstream_callers: Impact radius if this function breaks
  • downstream_callees: Functions this depends on

Entropy interpretation:

  • token_entropy < 0.4: Repetitive code, likely pattern-based
  • pattern_repetition > 0.7: High similarity between blocks
  • branch_similarity > 0.8: Similar conditional branches
  • effective_complexity < 1.0: Dampening applied

Prioritizing Work

Debtmap provides multiple prioritization strategies, with unified scoring (0-10 scale) as the recommended default for most workflows:

1. By Unified Score (default - recommended)

debtmap analyze . --top 10

Shows top 10 items by combined complexity, coverage, and dependency factors, weighted and adjusted by function role.

Why use unified scoring:

  • Balances complexity (40%), coverage (40%), and dependency impact (20%)
  • Adjusts for function importance (entry points prioritized over utilities)
  • Normalized 0-10 scale is intuitive and consistent
  • Reduces false positives through coverage propagation
  • Best for sprint planning and function-level refactoring decisions

Example:

# Show top 20 critical items
debtmap analyze . --min-priority 7.0 --top 20

# Focus on high-impact functions (score >= 7.0)
debtmap analyze . --format json | jq '.functions[] | select(.unified_score >= 7.0)'

2. By Risk Category (legacy compatibility)

debtmap analyze . --min-priority high

Shows only HIGH and CRITICAL priority items using legacy risk scoring.

Note: Legacy risk scoring uses additive formulas and unbounded scales. Prefer unified scoring for new workflows.

3. By Debt Type

debtmap analyze . --filter Architecture,Testing

Focuses on specific categories:

  • Architecture: God objects, complexity, dead code
  • Testing: Coverage gaps, test quality
  • Performance: Resource leaks, inefficiencies
  • CodeQuality: Code smells, maintainability

4. By ROI (with coverage)

debtmap analyze . --lcov coverage.lcov --top 20

Prioritizes by return on investment for testing/refactoring. Combines unified scoring with test effort estimates to identify high-value work.

Choosing the right strategy:

  • Sprint planning for developers: Use unified scoring (--top N)
  • Architectural review: Use tiered prioritization (--summary)
  • Category-focused work: Use debt type filtering (--filter)
  • Testing priorities: Use ROI analysis with coverage data (--lcov)
  • Historical comparisons: Use legacy risk scoring (for consistency with old reports)

Tiered Prioritization

Note: Tiered prioritization uses traditional debt scoring (additive, higher = worse) and is complementary to the unified scoring system (0-10 scale). Both systems can be used together:

  • Unified scoring (0-10 scale): Best for function-level prioritization and sprint planning
  • Tiered prioritization (debt tiers): Best for architectural focus and strategic debt planning

Use --summary for tiered view focusing on architectural issues, or default output for function-level unified scores.

Debtmap uses a tier-based system to map debt scores to actionable priority levels. Each tier includes effort estimates and strategic guidance for efficient debt remediation.

Tier Levels

The Tier enum defines four priority levels based on score thresholds:

#![allow(unused)]
fn main() {
pub enum Tier {
    Critical,  // Score ≥ 90
    High,      // Score 70-89.9
    Moderate,  // Score 50-69.9
    Low,       // Score < 50
}
}

Score-to-Tier Mapping:

  • Critical (≥ 90): Immediate action required - blocks progress
  • High (70-89.9): Should be addressed this sprint
  • Moderate (50-69.9): Plan for next sprint
  • Low (< 50): Background maintenance work

Effort Estimates Per Tier

Each tier includes estimated effort based on typical remediation patterns:

TierEstimated EffortTypical Work
Critical1-2 daysMajor refactoring, comprehensive testing, architectural changes
High2-4 hoursExtract functions, add test coverage, fix resource leaks
Moderate1-2 hoursSimplify logic, reduce duplication, improve error handling
Low30 minutesAddress TODOs, minor cleanup, documentation

Effort calculation considers:

  • Complexity metrics (cyclomatic, cognitive)
  • Test coverage gaps
  • Number of dependencies (upstream/downstream)
  • Debt category (Architecture debt takes longer than CodeQuality)

Tiered Display Grouping

TieredDisplay groups similar debt items for batch action recommendations:

#![allow(unused)]
fn main() {
pub struct TieredDisplay {
    pub tier: Tier,
    pub items: Vec<DebtItem>,
    pub total_score: f64,
    pub estimated_total_effort_hours: f64,
    pub batch_recommendations: Vec<String>,
}
}

Grouping strategy:

  • Groups items by tier and similarity pattern
  • Prevents grouping of god objects (always show individually)
  • Prevents grouping of Critical items (each needs individual attention)
  • Suggests batch actions for similar Low/Moderate items

Example batch recommendations:

{
  "tier": "Moderate",
  "total_score": 245.8,
  "estimated_total_effort_hours": 12.5,
  "batch_recommendations": [
    "Extract 5 validation functions from similar patterns",
    "Add test coverage for 8 moderately complex functions (grouped by module)",
    "Refactor 3 functions with similar nested loop patterns"
  ]
}

Using Tiered Prioritization

1. Start with Critical tier:

debtmap analyze . --min-priority critical

Focus on items with score ≥ 90. These typically represent:

  • Complex functions with 0% coverage
  • God objects blocking feature development
  • Critical resource leaks or security issues

2. Plan High tier work:

debtmap analyze . --min-priority high --format json > sprint-plan.json

Schedule 2-4 hours per item for this sprint. Look for:

  • Functions approaching complexity thresholds
  • Moderate coverage gaps on important code paths
  • Performance bottlenecks with clear solutions

3. Batch Moderate tier items:

debtmap analyze . --min-priority moderate

Review batch recommendations. Examples:

  • “10 validation functions detected - extract common pattern”
  • “5 similar test files with duplication - create shared fixtures”
  • “8 functions with magic values - create constants module”

4. Schedule Low tier background work: Address during slack time or as warm-up tasks for new contributors.

Strategic Guidance by Tier

Critical Tier Strategy:

  • Block new features until addressed
  • Pair programming recommended for complex items
  • Architectural review before major refactoring
  • Comprehensive testing after changes

High Tier Strategy:

  • Sprint planning priority
  • Impact analysis before changes
  • Code review from senior developers
  • Integration testing after changes

Moderate Tier Strategy:

  • Batch similar items for efficiency
  • Extract patterns across multiple files
  • Incremental improvement over multiple PRs
  • Regression testing for affected areas

Low Tier Strategy:

  • Good first issues for new contributors
  • Documentation improvements
  • Code cleanup during refactoring nearby code
  • Technical debt gardening sessions

Categorized Debt Analysis

Debtmap provides CategorizedDebt analysis that groups debt items by category and identifies cross-category dependencies. This helps teams understand strategic relationships between different types of technical debt.

CategorySummary

Each category gets a summary with metrics for planning:

#![allow(unused)]
fn main() {
pub struct CategorySummary {
    pub category: DebtCategory,
    pub total_score: f64,
    pub item_count: usize,
    pub estimated_effort_hours: f64,
    pub average_severity: f64,
    pub top_items: Vec<DebtItem>,  // Up to 5 highest priority
}
}

Effort estimation formulas:

  • Architecture debt: complexity_score / 10 × 2 hours (structural changes take longer)
  • Testing debt: complexity_score / 10 × 1.5 hours (writing tests)
  • Performance debt: complexity_score / 10 × 1.8 hours (profiling + optimization)
  • CodeQuality debt: complexity_score / 10 × 1.2 hours (refactoring)

Example category summary:

{
  "category": "Architecture",
  "total_score": 487.5,
  "item_count": 15,
  "estimated_effort_hours": 97.5,
  "average_severity": 32.5,
  "top_items": [
    {
      "debt_type": "GodObject",
      "file": "src/services/user_service.rs",
      "score": 95.0,
      "estimated_effort_hours": 16.0
    },
    {
      "debt_type": "ComplexityHotspot",
      "file": "src/payments/processor.rs",
      "score": 87.3,
      "estimated_effort_hours": 14.0
    }
  ]
}

Cross-Category Dependencies

CrossCategoryDependency identifies blocking relationships between different debt categories:

#![allow(unused)]
fn main() {
pub struct CrossCategoryDependency {
    pub from_category: DebtCategory,
    pub to_category: DebtCategory,
    pub blocking_items: Vec<(DebtItem, DebtItem)>,
    pub impact_level: ImpactLevel,  // Critical, High, Medium, Low
    pub recommendation: String,
}
}

Common dependency patterns:

1. Architecture blocks Testing:

  • Pattern: God objects are too complex to test effectively
  • Example: UserService has 50+ functions, making comprehensive testing impractical
  • Impact: Critical - cannot improve test coverage without refactoring
  • Recommendation: “Split god object into 4-5 focused modules before adding tests”

2. Async issues require Architecture changes:

  • Pattern: Blocking I/O in async contexts requires architectural redesign
  • Example: Sync database calls in async handlers
  • Impact: High - performance problems require design changes
  • Recommendation: “Introduce async database layer before optimizing handlers”

3. Complexity affects Testability:

  • Pattern: High cyclomatic complexity makes thorough testing difficult
  • Example: Function with 22 branches needs 22+ test cases
  • Impact: High - testing effort grows exponentially with complexity
  • Recommendation: “Reduce complexity to < 10 before writing comprehensive tests”

4. Performance requires Architecture:

  • Pattern: O(n²) nested loops need different data structures
  • Example: Linear search in loops should use HashMap
  • Impact: Medium - optimization requires structural changes
  • Recommendation: “Refactor data structure before micro-optimizations”

Example cross-category dependency:

{
  "from_category": "Architecture",
  "to_category": "Testing",
  "impact_level": "Critical",
  "blocking_items": [
    {
      "blocker": {
        "debt_type": "GodObject",
        "file": "src/services/user_service.rs",
        "functions": 52,
        "score": 95.0
      },
      "blocked": {
        "debt_type": "TestingGap",
        "file": "src/services/user_service.rs",
        "coverage": 15,
        "score": 78.0
      }
    }
  ],
  "recommendation": "Split UserService into focused modules (auth, profile, settings, notifications) before attempting to improve test coverage. Current structure makes comprehensive testing impractical.",
  "estimated_unblock_effort_hours": 16.0
}

Using Categorized Debt Analysis

View all category summaries:

debtmap analyze . --format json | jq '.categorized_debt.summaries'

Focus on specific category:

debtmap analyze . --filter Architecture --top 10

Identify blocking relationships:

debtmap analyze . --format json | jq '.categorized_debt.cross_category_dependencies[] | select(.impact_level == "Critical")'

Strategic planning workflow:

  1. Review category summaries:

    • Identify which category has highest total score
    • Check estimated effort hours per category
    • Note average severity to gauge urgency
  2. Check cross-category dependencies:

    • Find Critical and High impact blockers
    • Prioritize blockers before blocked items
    • Plan architectural changes before optimization
  3. Plan remediation order:

    Example decision tree:
    - Architecture score > 400? → Address god objects first
    - Testing gap with low complexity? → Quick wins, add tests
    - Performance issues + architecture debt? → Refactor structure first
    - High code quality debt but good architecture? → Incremental cleanup
    
  4. Use category-specific strategies:

    • Architecture: Pair programming, design reviews, incremental refactoring
    • Testing: TDD for new code, characterization tests for legacy
    • Performance: Profiling first, optimize hot paths, avoid premature optimization
    • CodeQuality: Code review focus, linting rules, consistent patterns

CategorizedDebt Output Structure

{
  "categorized_debt": {
    "summaries": [
      {
        "category": "Architecture",
        "total_score": 487.5,
        "item_count": 15,
        "estimated_effort_hours": 97.5,
        "average_severity": 32.5,
        "top_items": [...]
      },
      {
        "category": "Testing",
        "total_score": 356.2,
        "item_count": 23,
        "estimated_effort_hours": 53.4,
        "average_severity": 15.5,
        "top_items": [...]
      },
      {
        "category": "Performance",
        "total_score": 234.8,
        "item_count": 12,
        "estimated_effort_hours": 42.3,
        "average_severity": 19.6,
        "top_items": [...]
      },
      {
        "category": "CodeQuality",
        "total_score": 189.3,
        "item_count": 31,
        "estimated_effort_hours": 22.7,
        "average_severity": 6.1,
        "top_items": [...]
      }
    ],
    "cross_category_dependencies": [
      {
        "from_category": "Architecture",
        "to_category": "Testing",
        "impact_level": "Critical",
        "blocking_items": [...],
        "recommendation": "..."
      }
    ]
  }
}

Debt Density Metric

Debt density normalizes technical debt scores across projects of different sizes, providing a per-1000-lines-of-code metric for fair comparison.

Formula

debt_density = (total_debt_score / total_lines_of_code) × 1000

Example calculation:

Project A:
  - Total debt score: 1,250
  - Total lines of code: 25,000
  - Debt density: (1,250 / 25,000) × 1000 = 50

Project B:
  - Total debt score: 2,500
  - Total lines of code: 50,000
  - Debt density: (2,500 / 50,000) × 1000 = 50

Projects A and B have equal debt density (50) despite B having twice the absolute debt, because B is also twice as large. They have proportionally similar technical debt.

Interpretation Guidelines

Use these thresholds to assess codebase health:

Debt DensityAssessmentDescription
0-50CleanWell-maintained codebase, minimal debt
51-100ModerateTypical technical debt, manageable
101-150HighSignificant debt, prioritize remediation
150+CriticalSevere debt burden, may impede development

Context matters:

  • Early-stage projects: Often have higher density (rapid iteration)
  • Mature projects: Should trend toward lower density over time
  • Legacy systems: May have high density, track trend over time
  • Greenfield rewrites: Aim for density < 50

Using Debt Density

1. Compare projects fairly:

# Small microservice (5,000 LOC, debt = 250)
# Debt density: 50

# Large monolith (100,000 LOC, debt = 5,000)
# Debt density: 50

# Equal health despite size difference

2. Track improvement over time:

Sprint 1: 50,000 LOC, debt = 7,500, density = 150 (High)
Sprint 5: 52,000 LOC, debt = 6,500, density = 125 (Improving)
Sprint 10: 54,000 LOC, debt = 4,860, density = 90 (Moderate)

3. Set team goals:

Current density: 120
Target density: < 80 (by Q4)
Reduction needed: 40 points

Strategy:
- Fix 2-3 Critical items per sprint
- Prevent new debt (enforce thresholds)
- Refactor before adding features in high-debt modules

4. Benchmark across teams/projects:

{
  "team_metrics": [
    {
      "project": "auth-service",
      "debt_density": 45,
      "assessment": "Clean",
      "trend": "stable"
    },
    {
      "project": "billing-service",
      "debt_density": 95,
      "assessment": "Moderate",
      "trend": "improving"
    },
    {
      "project": "legacy-api",
      "debt_density": 165,
      "assessment": "Critical",
      "trend": "worsening"
    }
  ]
}

Limitations

Debt density doesn’t account for:

  • Code importance: 100 LOC in payment logic ≠ 100 LOC in logging utils
  • Complexity distribution: One 1000-line god object vs. 1000 simple functions
  • Test coverage: 50% coverage on critical paths vs. low-priority features
  • Team familiarity: New codebase vs. well-understood legacy system

Best practices:

  • Use density as one metric among many
  • Combine with category analysis and tiered prioritization
  • Focus on trend (improving/stable/worsening) over absolute number
  • Consider debt per module for more granular insights

Debt Density in CI/CD

Track density over time:

# Generate report with density
debtmap analyze . --format json --output debt-report.json

# Extract density for trending
DENSITY=$(jq '.debt_density' debt-report.json)

# Store in metrics database
echo "debtmap.density:${DENSITY}|g" | nc -u -w0 statsd 8125

Set threshold gates:

# .github/workflows/debt-check.yml
- name: Check debt density
  run: |
    DENSITY=$(debtmap analyze . --format json | jq '.debt_density')
    if (( $(echo "$DENSITY > 150" | bc -l) )); then
      echo "❌ Debt density too high: $DENSITY (limit: 150)"
      exit 1
    fi
    echo "✅ Debt density acceptable: $DENSITY"

Actionable Insights

Each recommendation includes:

ACTION: What to do

  • “Add 6 unit tests for full coverage”
  • “Refactor into 3 smaller functions”
  • “Extract validation to separate function”

IMPACT: Expected improvement

  • “Full test coverage, -3.7 risk”
  • “Reduce complexity from 22 to 8”
  • “Eliminate 120 lines of duplication”

WHY: Rationale

  • “Business logic with 0% coverage, manageable complexity”
  • “High complexity with low coverage threatens stability”
  • “Repeated validation pattern across 5 files”

Example workflow:

  1. Run analysis with coverage: debtmap analyze . --lcov coverage.lcov
  2. Filter to CRITICAL items: --min-priority critical
  3. Review top 5 recommendations
  4. Start with highest ROI items
  5. Rerun analysis to track progress

Common Patterns to Recognize

Pattern 1: High Complexity, Well Tested

Complexity: 25, Coverage: 95%, Risk: LOW

This is actually good! Complex but thoroughly tested code. Learn from this approach.

Pattern 2: Moderate Complexity, No Tests

Complexity: 12, Coverage: 0%, Risk: CRITICAL

Highest priority - manageable complexity, should be easy to test.

Pattern 3: Low Complexity, No Tests

Complexity: 3, Coverage: 0%, Risk: LOW

Low priority - simple code, less risky without tests.

Pattern 4: Repetitive High Complexity (Dampened)

Cyclomatic: 20, Effective: 7 (65% dampened), Risk: LOW

Validation or dispatch pattern - looks complex but is repetitive. Lower priority.

Pattern 5: God Object

File: services.rs, Functions: 50+, Responsibilities: 15+

Architectural issue - split before adding features.

Analyzer Types

Debtmap supports multiple programming languages with varying levels of analysis capability.

Supported Languages

Rust (Full Support)

  • Parser: syn (native Rust AST)
  • Capabilities:
    • Full complexity metrics (cyclomatic, cognitive, entropy)
    • Trait implementation tracking
    • Purity detection with confidence scoring
    • Call graph analysis (upstream callers, downstream callees)
    • Semantic function classification (entry points, business logic, data access, infrastructure, utilities, test code)
    • Enhanced call graph with transitive relationships
    • Macro expansion support for accurate complexity analysis
    • Pattern-based adjustments for macros and code generation
    • Visibility tracking (pub, pub(crate), private)
    • Test module detection (#[cfg(test)])

Semantic Classification:

Debtmap automatically identifies function roles in Rust code to apply appropriate role multipliers in unified scoring:

  • Entry Points: Functions named main, start, or public functions in bin/ modules
  • Business Logic: Core domain functions with complex logic, algorithms, business rules
  • Data Access: Functions performing database queries, file I/O, network operations
  • Infrastructure: Logging, configuration, monitoring, error handling utilities
  • Utilities: Helper functions, formatters, type converters, validation functions
  • Test Code: Functions in #[cfg(test)] modules, functions with #[test] attribute

This classification feeds directly into the unified scoring system’s role multiplier (see Risk Scoring section).

Python (Partial Support)

  • Parser: rustpython-parser
  • Capabilities:
    • Complexity metrics (cyclomatic, cognitive)
    • Python-specific error handling patterns
    • Purity detection for pure functions
    • Basic debt pattern detection
    • Limited call graph support

JavaScript (Partial Support)

  • Parser: tree-sitter (JavaScript grammar)
  • File extensions: .js, .jsx, .mjs, .cjs
  • Capabilities:
    • ECMAScript complexity patterns
    • Basic complexity metrics
    • Function extraction
    • Limited pattern detection

TypeScript (Partial Support)

  • Parser: tree-sitter (TypeScript grammar)
  • File extensions: .ts, .tsx, .mts, .cts
  • Capabilities:
    • Similar to JavaScript support
    • Type information currently not utilized
    • Basic complexity metrics
    • Limited pattern detection

Unsupported Languages:

Debtmap’s Language enum contains only the four supported languages: Rust, Python, JavaScript, and TypeScript. Files with unsupported extensions are filtered out during the file discovery phase and never reach the analysis stage.

File filtering behavior:

  • Discovery scans project for files matching supported extensions
  • Unsupported files (.cpp, .java, .go, etc.) are skipped silently
  • No analysis, metrics, or debt patterns are generated for filtered files
  • Use --languages flag to explicitly control which languages to analyze

Example:

# Only analyze Rust files (skip Python/JS/TS)
debtmap analyze . --languages rust

# Analyze Rust and Python only
debtmap analyze . --languages rust,python

Language Detection

Automatic detection by file extension:

#![allow(unused)]
fn main() {
let language = Language::from_path(&path);
}

Explicit language selection:

debtmap analyze . --languages rust,python

Extensibility

Debtmap’s architecture allows adding new languages:

  1. Implement Analyzer trait:
#![allow(unused)]
fn main() {
pub trait Analyzer: Send + Sync {
    fn parse(&self, content: &str, path: PathBuf) -> Result<Ast>;
    fn analyze(&self, ast: &Ast) -> FileMetrics;
    fn language(&self) -> Language;
}
}
  1. Register in get_analyzer():
#![allow(unused)]
fn main() {
pub fn get_analyzer(language: Language) -> Box<dyn Analyzer> {
    match language {
        Language::Rust => Box::new(RustAnalyzer::new()),
        Language::YourLanguage => Box::new(YourAnalyzer::new()),
        // ...
    }
}
}

See src/analyzers/rust.rs for a complete implementation example.

Advanced Features

Purity Detection

Debtmap detects pure functions - those without side effects that always return the same output for the same input.

What makes a function pure:

  • No I/O operations (file, network, database)
  • No mutable global state
  • No random number generation
  • No system calls
  • Deterministic output

Purity detection is optional:

  • Both is_pure and purity_confidence are Option types
  • May be None for some functions or languages where detection is not available
  • Rust has the most comprehensive purity detection support

Confidence scoring (when available):

  • 0.9-1.0: Very confident (no side effects detected)
  • 0.7-0.8: Likely pure (minimal suspicious patterns)
  • 0.5-0.6: Uncertain (some suspicious patterns)
  • 0.0-0.4: Likely impure (side effects detected)

Example:

#![allow(unused)]
fn main() {
// Pure: confidence = 0.95
fn calculate_total(items: &[Item]) -> f64 {
    items.iter().map(|i| i.price).sum()
}

// Impure: confidence = 0.1 (I/O detected)
fn save_total(items: &[Item]) -> Result<()> {
    let total = items.iter().map(|i| i.price).sum();
    write_to_file(total)  // Side effect!
}
}

Benefits:

  • Pure functions are easier to test
  • Can be safely cached or memoized
  • Safe to parallelize
  • Easier to reason about

Data Flow Analysis

Debtmap builds a comprehensive DataFlowGraph that extends basic call graph analysis with variable dependencies, data transformations, I/O operations, and purity tracking.

Call Graph Foundation

Upstream callers - Who calls this function

  • Indicates impact radius
  • More callers = higher impact if it breaks

Downstream callees - What this function calls

  • Indicates dependencies
  • More callees = more integration testing needed

Example:

{
  "name": "process_payment",
  "upstream_callers": [
    "handle_checkout",
    "process_subscription",
    "handle_refund"
  ],
  "downstream_callees": [
    "validate_payment_method",
    "calculate_fees",
    "record_transaction",
    "send_receipt"
  ]
}

Variable Dependency Tracking

DataFlowGraph tracks which variables each function depends on:

#![allow(unused)]
fn main() {
pub struct DataFlowGraph {
    // Maps function_id -> set of variable names used
    variable_dependencies: HashMap<String, HashSet<String>>,
    // ...
}
}

What it tracks:

  • Local variables accessed in function body
  • Function parameters
  • Captured variables (closures)
  • Mutable vs immutable references

Benefits:

  • Identify functions coupled through shared state
  • Detect potential side effect chains
  • Guide refactoring to reduce coupling

Example output:

{
  "function": "calculate_total",
  "variable_dependencies": ["items", "tax_rate", "discount", "total"],
  "parameter_count": 3,
  "local_var_count": 1
}

Data Transformation Patterns

DataFlowGraph identifies common functional programming patterns:

#![allow(unused)]
fn main() {
pub enum TransformationType {
    Map,        // Transform each element
    Filter,     // Select subset of elements
    Reduce,     // Aggregate to single value
    FlatMap,    // Transform and flatten
    Unknown,    // Other transformations
}
}

Pattern detection:

  • Recognizes iterator chains (.map(), .filter(), .fold())
  • Identifies functional vs imperative data flow
  • Tracks input/output variable relationships

Example:

#![allow(unused)]
fn main() {
// Detected as: Filter → Map → Reduce pattern
fn total_active_users(users: &[User]) -> f64 {
    users.iter()
        .filter(|u| u.active)      // Filter transformation
        .map(|u| u.balance)        // Map transformation
        .sum()                      // Reduce transformation
}
}

Transformation metadata:

{
  "function": "total_active_users",
  "input_vars": ["users"],
  "output_vars": ["sum_result"],
  "transformation_type": "Reduce",
  "is_functional_style": true,
  "pipeline_length": 3
}

I/O Operation Detection

Tracks functions performing I/O operations for purity and performance analysis:

I/O categories tracked:

  • File I/O: std::fs, File::open, read_to_string
  • Network I/O: HTTP requests, socket operations
  • Database I/O: SQL queries, ORM operations
  • System calls: Process spawning, environment access
  • Blocking operations: thread::sleep, synchronous I/O in async

Example detection:

#![allow(unused)]
fn main() {
// Detected I/O operations: FileRead, FileWrite
fn save_config(config: &Config, path: &Path) -> Result<()> {
    let json = serde_json::to_string(config)?;  // No I/O
    std::fs::write(path, json)?;                 // FileWrite detected
    Ok(())
}
}

I/O metadata:

{
  "function": "save_config",
  "io_operations": ["FileWrite"],
  "is_blocking": true,
  "affects_purity": true,
  "async_safe": false
}

Purity Analysis Integration

DataFlowGraph integrates with purity detection to provide comprehensive side effect analysis:

Side effect tracking:

  • I/O operations (file, network, console)
  • Global state mutations
  • Random number generation
  • System time access
  • Non-deterministic behavior

Purity confidence factors:

  • 1.0: Pure mathematical function, no side effects
  • 0.8: Pure with deterministic data transformations
  • 0.5: Mixed - some suspicious patterns
  • 0.2: Likely impure - I/O detected
  • 0.0: Definitely impure - multiple side effects

Example analysis:

{
  "function": "calculate_discount",
  "is_pure": true,
  "purity_confidence": 0.95,
  "side_effects": [],
  "deterministic": true,
  "safe_to_parallelize": true,
  "safe_to_cache": true
}

Modification Impact Analysis

DataFlowGraph calculates the impact of modifying a function:

#![allow(unused)]
fn main() {
pub struct ModificationImpact {
    pub function_name: String,
    pub affected_functions: Vec<String>,  // Upstream callers
    pub dependency_count: usize,          // Downstream callees
    pub has_side_effects: bool,
    pub risk_level: RiskLevel,
}
}

Risk level calculation:

  • Critical: Many upstream callers + side effects + low test coverage
  • High: Many callers OR side effects with moderate coverage
  • Medium: Few callers with side effects OR many callers with good coverage
  • Low: Few callers, no side effects, or well-tested

Example impact analysis:

{
  "function": "validate_payment_method",
  "modification_impact": {
    "affected_functions": [
      "process_payment",
      "refund_payment",
      "update_payment_method",
      "validate_subscription"
    ],
    "affected_count": 4,
    "dependency_count": 8,
    "has_side_effects": true,
    "io_operations": ["DatabaseRead", "NetworkCall"],
    "risk_level": "High",
    "recommendation": "Comprehensive testing required - 4 functions depend on this, performs I/O"
  }
}

Using modification impact:

# Analyze impact before refactoring
debtmap analyze . --format json | jq '.functions[] | select(.name == "validate_payment_method") | .modification_impact'

Impact analysis uses:

  • Refactoring planning: Understand blast radius before changes
  • Test prioritization: Focus tests on high-impact functions
  • Code review: Flag high-risk changes for extra scrutiny
  • Dependency management: Identify tightly coupled components

DataFlowGraph Methods

Key methods for data flow analysis:

#![allow(unused)]
fn main() {
// Add function with its dependencies
pub fn add_function(&mut self, function_id: String, callees: Vec<String>)

// Track variable dependencies
pub fn add_variable_dependency(&mut self, function_id: String, var_name: String)

// Record I/O operations
pub fn add_io_operation(&mut self, function_id: String, io_type: IoType)

// Calculate modification impact
pub fn calculate_modification_impact(&self, function_id: &str) -> ModificationImpact

// Get all functions affected by a change
pub fn get_affected_functions(&self, function_id: &str) -> Vec<String>

// Find functions with side effects
pub fn find_functions_with_side_effects(&self) -> Vec<String>
}

Integration in analysis pipeline:

  1. Parser builds initial call graph
  2. DataFlowGraph extends with variable/I/O tracking
  3. Purity analyzer adds side effect information
  4. Modification impact calculated for each function
  5. Results used in prioritization and risk scoring

Connection to Unified Scoring:

The dependency analysis from DataFlowGraph directly feeds into the unified scoring system’s dependency factor (20% weight):

  • Dependency Factor Calculation: Functions with high upstream caller count or on critical paths from entry points receive higher dependency scores (8-10)
  • Isolated Utilities: Functions with few or no callers score lower (1-3) on dependency factor
  • Impact Prioritization: This helps prioritize functions where bugs have wider impact across the codebase
  • Modification Risk: The modification impact analysis uses dependency data to calculate blast radius when changes are made

Example:

Function: validate_payment_method
  Upstream callers: 4 (high impact)
  → Dependency Factor: 8.0

Function: format_currency_string
  Upstream callers: 0 (utility)
  → Dependency Factor: 1.5

Both have same complexity, but validate_payment_method gets higher unified score
due to its critical role in the call graph.

This integration ensures that the unified scoring system considers not just internal function complexity and test coverage, but also the function’s importance in the broader codebase architecture.

Entropy-Based Complexity

Advanced pattern detection to reduce false positives.

Token Classification:

#![allow(unused)]
fn main() {
enum TokenType {
    Variable,     // Weight: 1.0
    Method,       // Weight: 1.5 (more important)
    Literal,      // Weight: 0.5 (less important)
    Keyword,      // Weight: 0.8
    Operator,     // Weight: 0.6
}
}

Shannon Entropy Calculation:

H(X) = -Σ p(x) × log₂(p(x))

where p(x) is the probability of each token type.

Dampening Decision:

#![allow(unused)]
fn main() {
if entropy_score.token_entropy < 0.4
   && entropy_score.pattern_repetition > 0.6
   && entropy_score.branch_similarity > 0.7
{
    // Apply dampening
    effective_complexity = base_complexity × (1 - dampening_factor);
}
}

Output explanation:

Function: validate_input
  Cyclomatic: 15 → Effective: 5
  Reasoning:
    - High pattern repetition detected (85%)
    - Low token entropy indicates simple patterns (0.32)
    - Similar branch structures found (92% similarity)
    - Complexity reduced by 67% due to pattern-based code

Entropy Analysis Caching

EntropyAnalyzer includes an LRU-style cache for performance optimization when analyzing large codebases or performing repeated analysis.

Cache Structure

#![allow(unused)]
fn main() {
struct CacheEntry {
    score: EntropyScore,
    timestamp: Instant,
    hit_count: usize,
}
}

Cache configuration:

  • Default size: 1000 entries
  • Eviction policy: LRU (Least Recently Used)
  • Memory per entry: ~128 bytes
  • Total memory overhead: ~128 KB for default size

Cache Statistics

The analyzer tracks cache performance:

#![allow(unused)]
fn main() {
pub struct CacheStats {
    pub hits: usize,
    pub misses: usize,
    pub evictions: usize,
    pub hit_rate: f64,
    pub memory_bytes: usize,
}
}

Example stats output:

{
  "entropy_cache_stats": {
    "hits": 3427,
    "misses": 1573,
    "evictions": 573,
    "hit_rate": 0.685,
    "memory_bytes": 128000
  }
}

Hit rate interpretation:

  • > 0.7: Excellent - many repeated analyses, cache is effective
  • 0.4-0.7: Good - moderate reuse, typical for incremental analysis
  • < 0.4: Low - mostly unique functions, cache less helpful

Performance Benefits

Typical performance gains:

  • Cold analysis: 100ms baseline (no cache benefit)
  • Incremental analysis: 30-40ms (~60-70% faster) for unchanged functions
  • Re-analysis: 15-20ms (~80-85% faster) for recently analyzed functions

Best for:

  • Watch mode: Analyzing on file save (repeated analysis of same files)
  • CI/CD: Comparing feature branch to main (overlap in functions)
  • Large codebases: Many similar functions benefit from pattern caching

Memory estimation:

Total cache memory = entry_count × 128 bytes

Examples:
- 1,000 entries: ~128 KB (default)
- 5,000 entries: ~640 KB (large projects)
- 10,000 entries: ~1.25 MB (very large)

Cache Management

Automatic eviction:

  • When cache reaches size limit, oldest entries evicted
  • Hit count influences retention (frequently accessed stay longer)
  • Timestamp used for LRU ordering

Cache invalidation:

  • Function source changes invalidate entry
  • Cache cleared between major analysis runs
  • No manual invalidation needed

Configuration (if exposed in future):

[entropy.cache]
enabled = true
size = 1000           # Number of entries
ttl_seconds = 3600    # Optional: expire after 1 hour

Context-Aware Analysis

Debtmap adjusts analysis based on code context:

Pattern Recognition:

  • Validation patterns (repetitive checks)
  • Dispatcher patterns (routing logic)
  • Builder patterns (fluent APIs)
  • Configuration parsers (key-value processing)

Adjustment Strategies:

  • Reduce false positives for recognized patterns
  • Apply appropriate thresholds by pattern type
  • Consider pattern confidence in scoring

Example:

#![allow(unused)]
fn main() {
// Recognized as "validation_pattern"
// Complexity dampening applied
fn validate_user_input(input: &UserInput) -> Result<()> {
    if input.name.is_empty() { return Err(Error::EmptyName); }
    if input.email.is_empty() { return Err(Error::EmptyEmail); }
    if input.age < 13 { return Err(Error::TooYoung); }
    // ... more similar validations
    Ok(())
}
}

Coverage Integration

Debtmap parses LCOV coverage data for risk analysis:

LCOV Support:

  • Standard format from most coverage tools
  • Line-level coverage tracking
  • Function-level aggregation

Coverage Index:

  • O(1) exact name lookups (~0.5μs)
  • O(log n) line-based fallback (~5-8μs)
  • ~200 bytes per function
  • Thread-safe (Arc)

Performance Characteristics

Index Build Performance:

  • Index construction: O(n), approximately 20-30ms for 5,000 functions
  • Memory usage: ~200 bytes per record (~2MB for 5,000 functions)
  • Scales linearly with function count

Lookup Performance:

  • Exact match (function name): O(1) average, ~0.5μs per lookup
  • Line-based fallback: O(log n), ~5-8μs per lookup
  • Cache-friendly data structure for hot paths

Analysis Overhead:

  • Coverage integration overhead: ~2.5x baseline analysis time
  • Target overhead: ≤3x (maintained through optimizations)
  • Example timing: 53ms baseline → 130ms with coverage (2.45x overhead)
  • Overhead includes index build + lookups + coverage propagation

Thread Safety:

  • Coverage index wrapped in Arc<CoverageIndex> for lock-free parallel access
  • Multiple analyzer threads can query coverage simultaneously
  • No contention on reads, suitable for parallel analysis pipelines

Memory Footprint:

Total memory = (function_count × 200 bytes) + index overhead

Examples:
- 1,000 functions: ~200 KB
- 5,000 functions: ~2 MB
- 10,000 functions: ~4 MB

Scalability:

  • Tested with codebases up to 10,000 functions
  • Performance remains predictable and acceptable
  • Memory usage stays bounded and reasonable

Generating coverage:

# Rust
cargo tarpaulin --out lcov --output-dir target/coverage

# Python
pytest --cov --cov-report=lcov

# JavaScript/TypeScript
jest --coverage --coverageReporters=lcov

# Go
go test -coverprofile=coverage.out
gocover-cobertura < coverage.out > coverage.lcov

Using with Debtmap:

debtmap analyze . --lcov target/coverage/lcov.info

Coverage dampening: When coverage data is provided, debt scores are dampened for well-tested code:

final_score = base_score × (1 - coverage_percentage)

This ensures well-tested complex code gets lower priority than untested simple code.

Example Outputs

High Complexity Function (Needs Refactoring)

Terminal Output:

#1 SCORE: 9.2 [CRITICAL]
├─ COMPLEXITY: ./src/payments/processor.rs:145 process_transaction()
├─ ACTION: Refactor into 4 smaller functions
├─ IMPACT: Reduce complexity from 25 to 8, improve testability
├─ COMPLEXITY: cyclomatic=25, branches=25, cognitive=38, nesting=5, lines=120
├─ DEPENDENCIES: 3 upstream, 8 downstream
└─ WHY: Exceeds all complexity thresholds, difficult to test and maintain

JSON Output:

{
  "id": "complexity_src_payments_processor_rs_145",
  "debt_type": "Complexity",
  "priority": "Critical",
  "file": "src/payments/processor.rs",
  "line": 145,
  "message": "Function exceeds complexity threshold",
  "context": "Cyclomatic: 25, Cognitive: 38, Nesting: 5",
  "function_metrics": {
    "name": "process_transaction",
    "cyclomatic": 25,
    "cognitive": 38,
    "nesting": 5,
    "length": 120,
    "is_pure": false,
    "purity_confidence": 0.15,
    "upstream_callers": ["handle_payment", "handle_subscription", "handle_refund"],
    "downstream_callees": ["validate", "calculate_fees", "record_transaction", "send_receipt", "update_balance", "log_transaction", "check_fraud", "notify_user"]
  }
}

Well-Tested Complex Function (Good Example)

Terminal Output:

Function: calculate_tax (WELL TESTED - Good Example!)
  File: src/tax/calculator.rs:78
  Complexity: Cyclomatic=18, Cognitive=22
  Coverage: 98%
  Risk: LOW

  Why this is good:
  - High complexity is necessary (tax rules are complex)
  - Thoroughly tested with 45 test cases
  - Clear documentation of edge cases
  - Good example to follow for other complex logic

Test Gap (Needs Testing)

Terminal Output:

#2 SCORE: 8.9 [CRITICAL]
├─ TEST GAP: ./src/analyzers/rust_call_graph.rs:38 add_function_to_graph()
├─ ACTION: Add 6 unit tests for full coverage
├─ IMPACT: Full test coverage, -3.7 risk reduction
├─ COMPLEXITY: cyclomatic=6, branches=6, cognitive=8, nesting=2, lines=32
├─ DEPENDENCIES: 0 upstream, 11 downstream
├─ TEST EFFORT: Simple (2-3 hours)
└─ WHY: Business logic with 0% coverage, manageable complexity (cyclo=6, cog=8)
    High impact - 11 functions depend on this

JSON Output:

{
  "function": "add_function_to_graph",
  "file": "src/analyzers/rust_call_graph.rs",
  "line": 38,
  "current_risk": 8.9,
  "potential_risk_reduction": 3.7,
  "recommendation": {
    "action": "Add unit tests",
    "details": "Add 6 unit tests for full coverage",
    "effort_estimate": "2-3 hours"
  },
  "test_effort": {
    "estimated_difficulty": "Simple",
    "cognitive_load": 8,
    "branch_count": 6,
    "recommended_test_cases": 6
  },
  "complexity": {
    "cyclomatic": 6,
    "cognitive": 8,
    "nesting": 2,
    "length": 32
  },
  "dependencies": {
    "upstream_callers": [],
    "downstream_callees": [
      "get_function_name", "extract_parameters", "parse_return_type",
      "add_to_registry", "update_call_sites", "resolve_types",
      "track_visibility", "record_location", "increment_counter",
      "validate_signature", "log_registration"
    ]
  },
  "roi": 4.5
}

Entropy-Dampened Validation Function

Terminal Output:

Function: validate_config
  File: src/config/validator.rs:23
  Cyclomatic: 20 → Effective: 7 (65% dampened)
  Risk: LOW

  Entropy Analysis:
    ├─ Token Entropy: 0.28 (low variety - repetitive patterns)
    ├─ Pattern Repetition: 0.88 (high similarity between checks)
    ├─ Branch Similarity: 0.91 (consistent validation structure)
    └─ Reasoning: Complexity reduced by 65% due to pattern-based code

  This appears complex but is actually a repetitive validation pattern.
  Lower priority for refactoring.

Before/After Refactoring Comparison

Before:

Function: process_order
  Cyclomatic: 22
  Cognitive: 35
  Coverage: 15%
  Risk Score: 52.3 (CRITICAL)
  Debt Score: 50 (Critical Complexity)

After:

Function: process_order (refactored)
  Cyclomatic: 5
  Cognitive: 6
  Coverage: 92%
  Risk Score: 2.1 (LOW)
  Debt Score: 0 (no debt)

Extracted functions:
  - validate_order (Cyclomatic: 4, Coverage: 100%)
  - calculate_totals (Cyclomatic: 3, Coverage: 95%)
  - apply_discounts (Cyclomatic: 6, Coverage: 88%)
  - finalize_order (Cyclomatic: 4, Coverage: 90%)

Impact:
  ✓ Complexity reduced by 77%
  ✓ Coverage improved by 513%
  ✓ Risk reduced by 96%
  ✓ Created 4 focused, testable functions

Next Steps

For questions or issues, visit GitHub Issues.

Configuration

Debtmap is highly configurable through a .debtmap.toml file. This chapter explains how to customize Debtmap’s behavior for your project’s specific needs.

Config Files

Creating a Configuration File

Debtmap looks for a .debtmap.toml file in the current directory and up to 10 parent directories. To create an initial configuration:

debtmap init

This command creates a .debtmap.toml file with sensible defaults.

Configuration File Discovery

When you run debtmap, it searches for .debtmap.toml starting in your current directory and traversing up to 10 parent directories. The first configuration file found is used.

If no configuration file is found, Debtmap uses built-in defaults that work well for most projects.

Basic Example

Here’s a minimal .debtmap.toml configuration:

[scoring]
coverage = 0.50      # 50% weight for test coverage gaps
complexity = 0.35    # 35% weight for code complexity
dependency = 0.15    # 15% weight for dependency criticality

[thresholds]
complexity = 10
max_file_length = 500
max_function_length = 50

[languages]
enabled = ["rust", "python", "javascript", "typescript"]

Scoring Configuration

Scoring Weights

The [scoring] section controls how different factors contribute to the overall debt score. Debtmap uses a weighted sum model where weights must sum to 1.0.

[scoring]
coverage = 0.50      # Weight for test coverage gaps (default: 0.50)
complexity = 0.35    # Weight for code complexity (default: 0.35)
dependency = 0.15    # Weight for dependency criticality (default: 0.15)

Active weights (used in scoring):

  • coverage - Prioritizes untested code (default: 0.50)
  • complexity - Identifies complex areas (default: 0.35)
  • dependency - Considers impact radius (default: 0.15)

Unused weights (reserved for future features):

  • semantic - Not currently used (default: 0.00)
  • security - Not currently used (default: 0.00)
  • organization - Not currently used (default: 0.00)

Validation rules:

  • All weights must be between 0.0 and 1.0
  • Active weights (coverage + complexity + dependency) must sum to 1.0 (±0.001 tolerance)
  • If weights don’t sum to 1.0, they will be automatically normalized

Example - Prioritize complexity over coverage:

[scoring]
coverage = 0.30
complexity = 0.55
dependency = 0.15

Role Multipliers

Role multipliers adjust complexity scores based on a function’s semantic role:

[role_multipliers]
pure_logic = 1.2        # Prioritize pure computation (default: 1.2)
orchestrator = 0.8      # Reduce for delegation functions (default: 0.8)
io_wrapper = 0.7        # Reduce for I/O wrappers (default: 0.7)
entry_point = 0.9       # Slight reduction for main/CLI (default: 0.9)
pattern_match = 0.6     # Reduce for pattern matching (default: 0.6)
unknown = 1.0           # No adjustment (default: 1.0)

These multipliers help reduce false positives by recognizing that different function types have naturally different complexity levels.

Role Coverage Weights

Adjust how coverage gaps are weighted based on function role:

[role_coverage_weights]
entry_point = 0.6       # Reduce coverage penalty (often integration tested)
orchestrator = 0.8      # Reduce coverage penalty (tested via higher-level tests)
pure_logic = 1.0        # Full penalty (should have unit tests)
io_wrapper = 1.0        # Full penalty (should have unit tests)
pattern_match = 1.0     # Full penalty (should have unit tests)
unknown = 1.0           # Full penalty (default behavior)

Entry points and orchestrators get reduced coverage penalties since they’re often tested through integration tests rather than unit tests.

Thresholds Configuration

Basic Thresholds

Control when code is flagged as technical debt:

[thresholds]
complexity = 10                      # Cyclomatic complexity threshold
duplication = 50                     # Duplication threshold
max_file_length = 500                # Maximum lines per file
max_function_length = 50             # Maximum lines per function

Minimum Thresholds

Filter out trivial functions that aren’t really technical debt:

[thresholds]
minimum_debt_score = 2.0              # Only show items with debt score ≥ 2.0
minimum_cyclomatic_complexity = 3     # Ignore functions with cyclomatic < 3
minimum_cognitive_complexity = 5      # Ignore functions with cognitive < 5
minimum_risk_score = 2.0              # Only show Risk items with score ≥ 2.0

These minimum thresholds help focus on significant issues by filtering out simple functions with minor complexity.

Validation Thresholds

The [thresholds.validation] subsection configures limits for the debtmap validate command:

[thresholds.validation]
max_average_complexity = 10.0         # Maximum allowed average complexity (default: 10.0)
max_high_complexity_count = 100       # Maximum high complexity functions (default: 100)
max_debt_items = 2000                 # Maximum technical debt items (default: 2000)
max_total_debt_score = 1000           # Maximum total debt score (default: 1000)
max_codebase_risk_score = 7.0         # Maximum codebase risk score (default: 7.0)
max_high_risk_functions = 50          # Maximum high-risk functions (default: 50)
min_coverage_percentage = 0.0         # Minimum required coverage % (default: 0.0)
max_debt_density = 50.0               # Maximum debt per 1000 LOC (default: 50.0)

Use debtmap validate in CI to enforce code quality standards:

# Fail build if validation thresholds are exceeded
debtmap validate

Language Configuration

Enabling Languages

Specify which languages to analyze:

[languages]
enabled = ["rust", "python", "javascript", "typescript"]

Language-Specific Features

Configure features for individual languages:

[languages.rust]
detect_dead_code = false        # Rust: disabled by default (compiler handles it)
detect_complexity = true
detect_duplication = true

[languages.python]
detect_dead_code = true
detect_complexity = true
detect_duplication = true

[languages.javascript]
detect_dead_code = true
detect_complexity = true
detect_duplication = true

[languages.typescript]
detect_dead_code = true
detect_complexity = true
detect_duplication = true

Note: Rust’s dead code detection is disabled by default since the Rust compiler already provides excellent unused code warnings.

Exclusion Patterns

File and Directory Exclusion

Use glob patterns to exclude files and directories from analysis:

[ignore]
patterns = [
    "target/**",              # Rust build output
    "venv/**",                # Python virtual environment
    "node_modules/**",        # JavaScript dependencies
    "*.min.js",               # Minified files
    "benches/**",             # Benchmark code
    "tests/**/*",             # Test files
    "**/test_*.rs",           # Test files (prefix)
    "**/*_test.rs",           # Test files (suffix)
    "**/fixtures/**",         # Test fixtures
    "**/mocks/**",            # Mock implementations
    "**/stubs/**",            # Stub implementations
    "**/examples/**",         # Example code
    "**/demo/**",             # Demo code
]

Glob pattern syntax:

  • * - Matches any characters except /
  • ** - Matches any characters including / (recursive)
  • ? - Matches a single character
  • [abc] - Matches any character in the set

Note: Function-level filtering (e.g., ignoring specific function name patterns) is handled by role detection and context-aware analysis rather than explicit ignore patterns. See the Context-Aware Detection section for function-level filtering options.

Display Configuration

Control how results are displayed:

[display]
tiered = true           # Use tiered priority display (default: true)
items_per_tier = 5      # Show 5 items per tier (default: 5)

When tiered = true, Debtmap groups results into priority tiers (Critical, High, Medium, Low) and shows the top items from each tier.

Output Configuration

Set the default output format:

[output]
default_format = "terminal"    # Options: "terminal", "json", "markdown"

Supported formats:

  • "terminal" - Human-readable colored output for the terminal (default)
  • "json" - Machine-readable JSON for integration with other tools
  • "markdown" - Markdown format for documentation and reports

This can be overridden with the --format CLI flag:

debtmap analyze --format json      # JSON output
debtmap analyze --format markdown  # Markdown output

Normalization Configuration

Control how raw scores are normalized to a 0-10 scale:

[normalization]
linear_threshold = 10.0         # Use linear scaling below this value
logarithmic_threshold = 100.0   # Use logarithmic scaling above this value
sqrt_multiplier = 3.33          # Multiplier for square root scaling
log_multiplier = 10.0           # Multiplier for logarithmic scaling
show_raw_scores = true          # Show both raw and normalized scores

Normalization ensures scores are comparable across different codebases and prevents extreme outliers from dominating the results.

Advanced Configuration

Entropy-Based Complexity Scoring

Entropy analysis helps identify repetitive code patterns (like large match statements) that inflate complexity metrics:

[entropy]
enabled = true                      # Enable entropy analysis (default: true)
weight = 1.0                        # Weight in complexity adjustment (default: 1.0)
min_tokens = 20                     # Minimum tokens for analysis (default: 20)
pattern_threshold = 0.7             # Pattern similarity threshold (default: 0.7)
entropy_threshold = 0.4             # Low entropy threshold (default: 0.4)
branch_threshold = 0.8              # Branch similarity threshold (default: 0.8)
use_classification = false          # Use smarter token classification (default: false)

# Maximum reductions to prevent over-correction
max_repetition_reduction = 0.20     # Max 20% reduction for repetition (default: 0.20)
max_entropy_reduction = 0.15        # Max 15% reduction for low entropy (default: 0.15)
max_branch_reduction = 0.25         # Max 25% reduction for similar branches (default: 0.25)
max_combined_reduction = 0.30       # Max 30% total reduction (default: 0.30)

Entropy scoring reduces false positives from functions like parsers and state machines that have high cyclomatic complexity but are actually simple and maintainable.

God Object Detection

Configure detection of classes/structs with too many responsibilities:

[god_object_detection]
enabled = true

# Rust-specific thresholds
[god_object_detection.rust]
max_methods = 20        # Maximum methods before flagging (default: 20)
max_fields = 15         # Maximum fields before flagging (default: 15)
max_traits = 5          # Maximum implemented traits
max_lines = 1000        # Maximum lines of code
max_complexity = 200    # Maximum total complexity

# Python-specific thresholds
[god_object_detection.python]
max_methods = 15
max_fields = 10
max_traits = 3
max_lines = 500
max_complexity = 150

# JavaScript-specific thresholds
[god_object_detection.javascript]
max_methods = 15
max_fields = 20         # JavaScript classes often have more properties
max_traits = 3
max_lines = 500
max_complexity = 150

Note: Different languages have different defaults. Rust allows more methods since trait implementations add methods, while JavaScript classes should be smaller.

Context-Aware Detection

Enable context-aware pattern detection to reduce false positives:

[context]
enabled = false         # Opt-in (default: false)

# Custom context rules
[[context.rules]]
name = "allow_blocking_in_main"
pattern = "blocking_io"
action = "allow"
priority = 100
reason = "Main function can use blocking I/O"

[context.rules.context]
role = "main"

# Function pattern configuration
[context.function_patterns]
test_patterns = ["test_*", "bench_*"]
config_patterns = ["load_*_config", "parse_*_config"]
handler_patterns = ["handle_*", "*_handler"]
init_patterns = ["initialize_*", "setup_*"]

Context-aware detection adjusts severity based on where code appears (main functions, test code, configuration loaders, etc.).

Error Handling Detection

Configure detection of error handling anti-patterns:

[error_handling]
detect_async_errors = true          # Detect async error issues (default: true)
detect_context_loss = true          # Detect error context loss (default: true)
detect_propagation = true           # Analyze error propagation (default: true)
detect_panic_patterns = true        # Detect panic/unwrap usage (default: true)
detect_swallowing = true            # Detect swallowed errors (default: true)

# Custom error patterns
[[error_handling.custom_patterns]]
name = "custom_panic"
pattern = "my_panic_macro"
pattern_type = "macro_name"
severity = "high"
description = "Custom panic macro usage"
remediation = "Replace with Result-based error handling"

# Severity overrides
[[error_handling.severity_overrides]]
pattern = "unwrap"
context = "test"
severity = "low"        # Unwrap is acceptable in test code

External API Configuration

Mark functions as public API for enhanced testing recommendations:

[external_api]
detect_external_api = false         # Auto-detect public APIs (default: false)
api_functions = []                  # Explicitly mark API functions
api_files = []                      # Explicitly mark API files

When enabled, public API functions receive higher priority for test coverage.

Additional Advanced Options

Debtmap supports additional advanced configuration options:

  • [loc] - Lines of code counting configuration. Controls whether to include tests (include_tests), generated files (include_generated), comments (count_comments), and blank lines (count_blank_lines) in LOC counts. All default to false.

  • [tiers] - Tier threshold configuration for prioritization. Allows customization of complexity and dependency thresholds for different priority tiers (T2, T3, T4). Used internally for tiered reporting.

  • [complexity_thresholds] - Enhanced complexity detection thresholds. Configures minimum total, cyclomatic, and cognitive complexity thresholds for flagging functions. Supplements the basic [thresholds] section with more granular control.

These options are advanced features with sensible defaults. Most users won’t need to configure them explicitly.

CLI Integration

CLI flags can override configuration file settings:

# Override complexity threshold
debtmap analyze --threshold-complexity 15

# Provide coverage file
debtmap analyze --coverage-file coverage.json

# Enable context-aware detection
debtmap analyze --context

# Override output format
debtmap analyze --format json

CLI flags take precedence over .debtmap.toml settings, allowing per-run customization.

Configuration Validation

Automatic Validation

Debtmap automatically validates your configuration when loading:

  • Scoring weights must sum to 1.0 (±0.001 tolerance)
  • Individual weights must be between 0.0 and 1.0
  • Invalid configurations fall back to defaults with a warning

Normalization

If scoring weights don’t sum exactly to 1.0, Debtmap automatically normalizes them:

# Input (sums to 0.80)
[scoring]
coverage = 0.40
complexity = 0.30
dependency = 0.10

# Automatically normalized to:
# coverage = 0.50
# complexity = 0.375
# dependency = 0.125

Debug Validation

To verify which configuration file is being loaded, check debug logs:

RUST_LOG=debug debtmap analyze

Look for log messages like:

DEBUG debtmap::config: Loaded config from /path/to/.debtmap.toml

Complete Configuration Example

Here’s a comprehensive configuration showing all major sections:

# Scoring configuration
[scoring]
coverage = 0.50
complexity = 0.35
dependency = 0.15

# Basic thresholds
[thresholds]
complexity = 10
duplication = 50
max_file_length = 500
max_function_length = 50
minimum_debt_score = 2.0
minimum_cyclomatic_complexity = 3
minimum_cognitive_complexity = 5
minimum_risk_score = 2.0

# Validation thresholds for CI
[thresholds.validation]
max_average_complexity = 10.0
max_high_complexity_count = 100
max_debt_items = 2000
max_total_debt_score = 1000
max_codebase_risk_score = 7.0
max_high_risk_functions = 50
min_coverage_percentage = 0.0
max_debt_density = 50.0

# Language configuration
[languages]
enabled = ["rust", "python", "javascript", "typescript"]

[languages.rust]
detect_dead_code = false
detect_complexity = true
detect_duplication = true

# Exclusion patterns
[ignore]
patterns = [
    "target/**",
    "node_modules/**",
    "tests/**/*",
    "**/*_test.rs",
]

# Display configuration
[display]
tiered = true
items_per_tier = 5

# Output configuration
[output]
default_format = "terminal"

# Entropy configuration
[entropy]
enabled = true
weight = 1.0
min_tokens = 20

# God object detection
[god_object_detection]
enabled = true

[god_object_detection.rust]
max_methods = 20
max_fields = 15

Configuration Best Practices

For Strict Quality Standards

[scoring]
coverage = 0.60         # Emphasize test coverage
complexity = 0.30
dependency = 0.10

[thresholds]
minimum_debt_score = 3.0        # Higher bar for flagging issues
max_function_length = 30        # Enforce smaller functions

[thresholds.validation]
max_average_complexity = 8.0    # Stricter complexity limits
max_debt_items = 500            # Stricter debt limits
min_coverage_percentage = 80.0  # Require 80% coverage

For Legacy Codebases

[scoring]
coverage = 0.30         # Reduce coverage weight (legacy code often lacks tests)
complexity = 0.50       # Focus on complexity
dependency = 0.20

[thresholds]
minimum_debt_score = 5.0        # Only show highest priority items
minimum_cyclomatic_complexity = 10   # Filter out moderate complexity

[thresholds.validation]
max_debt_items = 10000          # Accommodate large debt
max_total_debt_score = 5000     # Higher limits for legacy code

For Open Source Libraries

[scoring]
coverage = 0.55         # Prioritize test coverage (public API)
complexity = 0.30
dependency = 0.15

[external_api]
detect_external_api = true      # Flag untested public APIs

[thresholds.validation]
min_coverage_percentage = 90.0  # High coverage for public API
max_high_complexity_count = 20  # Keep complexity low

Troubleshooting

Configuration Not Loading

Check file location:

# Ensure file is named .debtmap.toml (note the dot prefix)
ls -la .debtmap.toml

# Debtmap searches current directory + 10 parent directories
pwd

Check file syntax:

# Verify TOML syntax is valid
debtmap analyze 2>&1 | grep -i "failed to parse"

Weights Don’t Sum to 1.0

Error message:

Warning: Invalid scoring weights: Active scoring weights must sum to 1.0, but sum to 0.800. Using defaults.

Fix: Ensure coverage + complexity + dependency = 1.0

[scoring]
coverage = 0.50
complexity = 0.35
dependency = 0.15    # Sum = 1.0 ✓

No Results Shown

Possible causes:

  1. Minimum thresholds too high
  2. All code excluded by ignore patterns
  3. No supported languages in project

Solutions:

# Lower minimum thresholds
[thresholds]
minimum_debt_score = 1.0
minimum_cyclomatic_complexity = 1

# Check language configuration
[languages]
enabled = ["rust", "python", "javascript", "typescript"]

# Review ignore patterns
[ignore]
patterns = [
    # Make sure you're not excluding too much
]

Output Formats

Debtmap provides multiple output formats to suit different workflows, from interactive terminal reports to machine-readable JSON for CI/CD integration. This chapter covers all available formats and how to use them effectively.

Format Selection

Select the output format using the -f or --format flag:

# Terminal output (default) - human-readable with colors
debtmap analyze .

# JSON output - machine-readable for tooling
debtmap analyze . --format json

# Markdown output - documentation and reports
debtmap analyze . --format markdown

Available formats:

  • terminal (default): Interactive output with colors, emoji, and formatting
  • json: Structured data for programmatic processing
  • markdown: Reports suitable for documentation and PR comments

Writing to Files

By default, output goes to stdout. Use -o or --output to write to a file:

# Write JSON to file
debtmap analyze . --format json -o report.json

# Write markdown report
debtmap analyze . --format markdown -o DEBT_REPORT.md

# Terminal output to file (preserves colors)
debtmap analyze . -o analysis.txt

Terminal Output

The terminal format provides an interactive, color-coded report designed for developer workflows. It’s the default format and optimized for readability.

Output Structure

Terminal output is organized into five main sections:

  1. Header - Analysis report title
  2. Codebase Summary - High-level metrics and debt score
  3. Complexity Hotspots - Top 5 most complex functions with refactoring guidance
  4. Technical Debt - High-priority debt items requiring attention
  5. Pass/Fail Status - Overall quality assessment

Example Terminal Output

═══════════════════════════════════════════
           DEBTMAP ANALYSIS REPORT
═══════════════════════════════════════════

📊 CODEBASE Summary
───────────────────────────────────────────
  Files analyzed:      42
  Total functions:     287
  Average complexity:  6.3
  Debt items:          15
  Total debt score:    156 (threshold: 100)

⚠️  COMPLEXITY HOTSPOTS (Top 5)
───────────────────────────────────────────
  1. src/analyzers/rust.rs:245 parse_function() - Cyclomatic: 18, Cognitive: 24
     ACTION: Extract 3-5 pure functions using decompose-then-transform strategy
     PATTERNS: Decompose into logical units, then apply functional patterns
     BENEFIT: Pure functions are easily testable and composable

  2. src/debt/smells.rs:196 detect_data_clumps() - Cyclomatic: 15, Cognitive: 20
     ↓ Entropy: 0.32, Repetition: 85%, Effective: 0.6x
       High pattern repetition detected (85%)

🔧 TECHNICAL DEBT (15 items)
───────────────────────────────────────────
  High Priority (5):
    - src/risk/scoring.rs:142 - TODO: Implement caching for score calculations
    - src/core/metrics.rs:89 - High complexity: cyclomatic=16
    - src/debt/patterns.rs:201 - Code duplication: 65 lines duplicated

✓ Pass/Fail: PASS

Color Coding and Symbols

The terminal output uses colors and symbols for quick visual scanning:

Status Indicators:

  • ✓ Green: Passing, good, well-tested
  • ⚠️ Yellow: Warning, moderate complexity
  • ✗ Red: Failing, critical, high complexity
  • 📊 Blue: Information, metrics
  • 🔧 Orange: Technical debt items
  • 🎯 Cyan: Recommendations

Complexity Classification:

  • LOW (0-5): Green - Simple, easy to maintain
  • MODERATE (6-10): Yellow - Consider refactoring
  • HIGH (11-15): Orange - Should refactor
  • SEVERE (>15): Red - Urgent refactoring needed

Note: These levels match the ComplexityLevel enum in the implementation.

Debt Score Thresholds:

The default debt threshold is 100. Scores are colored based on this threshold:

  • Green (≤50): Healthy - Below half threshold (score ≤ threshold/2)
  • Yellow (51-100): Attention needed - Between half and full threshold (threshold/2 < score ≤ threshold)
  • Red (>100): Action required - Exceeds threshold (score > threshold)

Note: Boundary values use strict inequalities: 50 is Green, 100 is Yellow (not Red), 101+ is Red.

Refactoring Guidance

For complex functions (cyclomatic complexity > 5), the terminal output provides actionable refactoring recommendations:

ACTION: Extract 3-5 pure functions using decompose-then-transform strategy
PATTERNS: Decompose into logical units, then apply functional patterns
BENEFIT: Pure functions are easily testable and composable

Guidance levels:

  • Moderate (6-10): Extract 2-3 pure functions using direct functional transformation
  • High (11-15): Extract 3-5 pure functions using decompose-then-transform strategy
  • Severe (>15): Extract 5+ pure functions into modules with functional core/imperative shell

See the Analysis Guide for metric explanations.

Plain Terminal Mode

For environments without color support or when piping to tools, use --plain:

# ASCII-only output, no colors, no emoji
debtmap analyze . --plain

Plain mode:

  • Removes ANSI color codes
  • Replaces emoji with text labels
  • Uses ASCII box-drawing characters
  • Machine-parseable structure

Note: Terminal output formatting (colors, symbols, etc.) can be customized internally via FormattingConfig. These customization options are currently not exposed through the CLI interface.

Verbosity Levels

Control detail level with -v flags (can be repeated):

# Standard output
debtmap analyze .

# Level 1: Show main score factors
debtmap analyze . -v

# Level 2: Show detailed calculations
debtmap analyze . -vv

# Level 3: Show all debug information
debtmap analyze . -vvv

Verbosity features:

  • -v: Show main score factors (complexity, coverage, dependency breakdown)
  • -vv: Show detailed calculations with formulas and intermediate values
  • -vvv: Show all debug information including entropy metrics, role detection, and cache hits

Note: Verbosity flags affect terminal output only. JSON and markdown formats include all data regardless of verbosity level.

Each level includes all information from the previous levels, progressively adding more detail to help understand how scores are calculated.

Example Output Differences:

Standard output shows basic metrics:

Total debt score: 156 (threshold: 100)

Level 1 (-v) adds score breakdowns:

Total debt score: 156 (threshold: 100)
  Complexity contribution: 85 (54%)
  Coverage gaps: 45 (29%)
  Dependency issues: 26 (17%)

Level 2 (-vv) adds detailed calculations:

Total debt score: 156 (threshold: 100)
  Complexity contribution: 85 (54%)
    Formula: sum(cyclomatic_weight * severity_multiplier)
    High complexity functions: 5 × 12 = 60
    Medium complexity: 8 × 3 = 24
    Base penalty: 1
  Coverage gaps: 45 (29%)
    Uncovered complex functions: 3 × 15 = 45

Level 3 (-vvv) adds all internal details:

Total debt score: 156 (threshold: 100)
  ... (all level 2 output) ...
  Debug info:
    Entropy metrics cached: 42/50 functions
    Function role detection: BusinessLogic=12, Utility=8, TestHelper=5
    Cache hit rate: 84%

Risk Analysis Output

When coverage data is provided via --lcov, terminal output includes a dedicated risk analysis section:

═══════════════════════════════════════════
           RISK ANALYSIS REPORT
═══════════════════════════════════════════

📈 RISK Summary
───────────────────────────────────────────
Codebase Risk Score: 45.5 (MEDIUM)
Complexity-Coverage Correlation: -0.65

Risk Distribution:
  Critical: 2 functions
  High: 5 functions
  Medium: 10 functions
  Low: 15 functions
  Well Tested: 20 functions

🎯 CRITICAL RISKS
───────────────────────────────────────────
1. src/core/parser.rs:142 parse_complex_ast()
   Risk: 85.0 | Complexity: 15 | Coverage: 0%
   Recommendation: Add 5 unit tests (est: 2-3 hours)
   Impact: -40 risk reduction

💡 RECOMMENDATIONS (by ROI)
───────────────────────────────────────────
1. test_me() - ROI: 5.0x
   Current Risk: 75 | Reduction: 40 | Effort: Moderate
   Rationale: High risk function with low coverage

Risk Level Classification:

  • LOW (<30): Green - score < 30.0
  • MEDIUM (30-59): Yellow - 30.0 ≤ score < 60.0
  • HIGH (≥60): Red - score ≥ 60.0

Note: 60 is the start of HIGH risk level.

JSON Output

JSON output provides complete analysis results in a machine-readable format, ideal for CI/CD pipelines, custom tooling, and programmatic analysis.

Basic Usage

# Generate JSON output
debtmap analyze . --format json

# Save to file
debtmap analyze . --format json -o report.json

# Pretty-printed by default for readability
debtmap analyze . --format json | jq .

Note: JSON output is automatically pretty-printed for readability.

JSON Schema Structure

Debtmap outputs a structured JSON document with the following top-level fields:

{
  "project_path": "/path/to/project",
  "timestamp": "2025-01-09T12:00:00Z",
  "complexity": { ... },
  "technical_debt": { ... },
  "dependencies": { ... },
  "duplications": [ ... ]
}

Full Schema Example

Here’s a complete annotated JSON output example:

{
  // Project metadata
  "project_path": "/Users/dev/myproject",
  "timestamp": "2025-01-09T15:30:00Z",

  // Complexity analysis results
  "complexity": {
    "metrics": [
      {
        "name": "calculate_risk_score",
        "file": "src/risk/scoring.rs",
        "line": 142,
        "cyclomatic": 12,
        "cognitive": 18,
        "nesting": 4,
        "length": 85,
        "is_test": false,
        "visibility": "pub",
        "is_trait_method": false,
        "in_test_module": false,
        "entropy_score": {
          "token_entropy": 0.65,
          "pattern_repetition": 0.30,
          "branch_similarity": 0.45,
          "effective_complexity": 0.85
        },
        "is_pure": false,
        "purity_confidence": 0.75,
        "detected_patterns": ["nested_loops", "complex_conditionals"],
        "upstream_callers": ["analyze_codebase", "generate_report"],
        "downstream_callees": ["get_metrics", "apply_weights"]
      }
    ],
    "summary": {
      "total_functions": 287,
      "average_complexity": 6.3,
      "max_complexity": 24,
      "high_complexity_count": 12
    }
  },

  // Technical debt items
  "technical_debt": {
    "items": [
      {
        "id": "debt_001",
        "debt_type": "Complexity",
        "priority": "High",
        "file": "src/analyzers/rust.rs",
        "line": 245,
        "column": 5,
        "message": "High cyclomatic complexity: 18",
        "context": "Function parse_function has excessive branching"
      },
      {
        "id": "debt_002",
        "debt_type": "Todo",
        "priority": "Medium",
        "file": "src/core/cache.rs",
        "line": 89,
        "column": null,
        "message": "TODO: Implement LRU eviction policy",
        "context": null
      }
    ],
    "by_type": {
      "Complexity": [ /* same structure as items */ ],
      "Todo": [ /* ... */ ],
      "Duplication": [ /* ... */ ]
    },
    "priorities": ["Low", "Medium", "High", "Critical"]
  },

  // Dependency analysis
  "dependencies": {
    "modules": [
      {
        "module": "risk::scoring",
        "dependencies": ["core::metrics", "debt::patterns"],
        "dependents": ["commands::analyze", "io::output"]
      }
    ],
    "circular": [
      {
        "cycle": ["module_a", "module_b", "module_c", "module_a"]
      }
    ]
  },

  // Code duplication blocks
  "duplications": [
    {
      "hash": "abc123def456",
      "lines": 15,
      "locations": [
        {
          "file": "src/parser/rust.rs",
          "start_line": 42,
          "end_line": 57
        },
        {
          "file": "src/parser/python.rs",
          "start_line": 89,
          "end_line": 104
        }
      ]
    }
  ]
}

Field Descriptions

FunctionMetrics Fields:

  • name: Function name

  • file: Path to source file

  • line: Line number where function is defined

  • cyclomatic: Cyclomatic complexity score

  • cognitive: Cognitive complexity score

  • nesting: Maximum nesting depth

  • length: Lines of code in function

  • is_test: Whether this is a test function

  • visibility: Rust visibility modifier (pub, pub(crate), or null)

  • is_trait_method: Whether this implements a trait

  • in_test_module: Whether inside #[cfg(test)]

  • entropy_score: Optional entropy analysis with structure:

    {
      "token_entropy": 0.65,        // Token distribution entropy (0-1): measures variety of tokens
      "pattern_repetition": 0.30,   // Pattern repetition score (0-1): detects repeated code patterns
      "branch_similarity": 0.45,    // Branch similarity metric (0-1): compares similarity between branches
      "effective_complexity": 0.85  // Adjusted complexity multiplier: complexity adjusted for entropy
    }
    

    EntropyScore Fields:

    • token_entropy: Measures the variety and distribution of tokens in the function (0-1, higher = more variety)
    • pattern_repetition: Detects repeated code patterns within the function (0-1, higher = more repetition)
    • branch_similarity: Measures similarity between different code branches (0-1, higher = more similar)
    • effective_complexity: The overall complexity multiplier adjusted for entropy effects
  • is_pure: Whether function is pure (no side effects)

  • purity_confidence: Confidence level (0.0-1.0)

  • detected_patterns: List of detected code patterns

  • upstream_callers: Functions that call this one

  • downstream_callees: Functions this one calls

DebtItem Fields:

  • id: Unique identifier
  • debt_type: Type of debt (see DebtType enum below)
  • priority: Priority level (Low, Medium, High, Critical)
  • file: Path to file containing debt
  • line: Line number
  • column: Optional column number
  • message: Human-readable description
  • context: Optional additional context

DebtType Enum:

  • Todo: TODO markers
  • Fixme: FIXME markers
  • CodeSmell: Code smell patterns
  • Duplication: Duplicated code
  • Complexity: Excessive complexity
  • Dependency: Dependency issues
  • ErrorSwallowing: Suppressed errors
  • ResourceManagement: Resource management issues
  • CodeOrganization: Organizational problems
  • TestComplexity: Complex test code
  • TestTodo: TODOs in tests
  • TestDuplication: Duplicated test code
  • TestQuality: Test quality issues

JSON Format Variants

Debtmap supports two JSON output formats:

# Legacy format (default) - backward compatible
debtmap analyze . --format json --output-format legacy

# Unified format - new consistent structure
debtmap analyze . --format json --output-format unified

Note: The --output-format flag only applies when using --format json. It has no effect with markdown or terminal formats.

Legacy format: Uses {File: {...}} and {Function: {...}} wrappers for backward compatibility with existing tooling.

Unified format: Consistent structure with a type field, making parsing simpler and more predictable. Recommended for new integrations.

Risk Insights JSON

When using --lcov, debtmap also outputs risk analysis in JSON:

{
  "items": [
    {
      "location": {
        "file": "src/risk/scoring.rs",
        "function": "calculate_priority",
        "line": 66
      },
      "debt_type": "TestGap",
      "unified_score": {
        "complexity_factor": 3.2,
        "coverage_factor": 10.0,
        "dependency_factor": 2.5,
        "role_multiplier": 1.2,
        "final_score": 9.4
      },
      "function_role": "BusinessLogic",
      "recommendation": {
        "action": "Add unit tests",
        "details": "Add 6 unit tests for full coverage",
        "effort_estimate": "2-3 hours"
      },
      "expected_impact": {
        "risk_reduction": 3.9,
        "complexity_reduction": 0,
        "coverage_improvement": 100
      },
      "upstream_dependencies": 0,
      "downstream_dependencies": 3,
      "nesting_depth": 1,
      "function_length": 13
    }
  ],
  "call_graph": {
    "total_functions": 1523,
    "entry_points": 12,
    "test_functions": 456,
    "max_depth": 8
  },
  "overall_coverage": 82.3,
  "total_impact": {
    "risk_reduction": 45.2,
    "complexity_reduction": 12.3,
    "coverage_improvement": 18.5
  }
}

Markdown Output

Markdown format generates documentation-friendly reports suitable for README files, PR comments, and technical documentation.

Basic Usage

# Generate markdown report
debtmap analyze . --format markdown

# Save to documentation
debtmap analyze . --format markdown -o docs/DEBT_REPORT.md

Markdown Structure

Markdown output includes:

  1. Executive Summary - High-level metrics and health dashboard
  2. Complexity Analysis - Detailed complexity breakdown by file
  3. Technical Debt - Categorized debt items with priorities
  4. Dependencies - Module dependencies and circular references
  5. Recommendations - Prioritized action items

Example Markdown Output

# Debtmap Analysis Report

**Generated:** 2025-01-09 15:30:00 UTC
**Project:** /Users/dev/myproject

## Executive Summary

- **Files Analyzed:** 42
- **Total Functions:** 287
- **Average Complexity:** 6.3
- **Total Debt Items:** 15
- **Debt Score:** 156/100 ⚠️

### Health Dashboard

| Metric | Value | Status |
|--------|-------|--------|
| Complexity | 6.3 avg | ✅ Good |
| Debt Score | 156 | ⚠️ Attention |
| High Priority Items | 5 | ⚠️ Action Needed |

## Complexity Analysis

### Top 5 Complex Functions

| Function | File | Cyclomatic | Cognitive | Priority |
|----------|------|-----------|-----------|----------|
| parse_function | src/analyzers/rust.rs:245 | 18 | 24 | High |
| detect_data_clumps | src/debt/smells.rs:196 | 15 | 20 | Medium |
| analyze_dependencies | src/core/deps.rs:89 | 14 | 18 | Medium |

### Refactoring Recommendations

**src/analyzers/rust.rs:245** - `parse_function()`
- **Complexity:** Cyclomatic: 18, Cognitive: 24
- **Action:** Extract 3-5 pure functions using decompose-then-transform strategy
- **Patterns:** Decompose into logical units, then apply functional patterns
- **Benefit:** Improved testability and maintainability

## Technical Debt

### High Priority (5 items)

- **src/risk/scoring.rs:142** - TODO: Implement caching for score calculations
- **src/core/metrics.rs:89** - High complexity: cyclomatic=16
- **src/debt/patterns.rs:201** - Code duplication: 65 lines duplicated

### Medium Priority (8 items)

...

## Dependencies

### Circular Dependencies

- `risk::scoring` → `core::metrics` → `risk::scoring`

## Recommendations

1. **Refactor parse_function** (High Priority)
   - Reduce complexity from 18 to <10
   - Extract helper functions
   - Estimated effort: 4-6 hours

2. **Add tests for scoring module** (High Priority)
   - Current coverage: 35%
   - Target coverage: 80%
   - Estimated effort: 2-3 hours

Enhanced Markdown Features

Debtmap can generate enhanced markdown reports with additional visualizations and insights:

  • Complexity distribution charts - Visual representation of complexity across codebase
  • Risk heat maps - Color-coded risk matrices
  • Dependency graphs - Module relationship diagrams
  • Quick wins section - Low-effort, high-impact improvements
  • Strategic priorities - Long-term architectural improvements
  • Team guidance - Role-specific recommendations

Note: Enhanced markdown features are implemented in the codebase (src/io/writers/enhanced_markdown/ module) but the specific flags or configuration options to enable them are not currently documented. Refer to the source code or use --help to discover available options.

Rendering to HTML/PDF

Markdown reports can be converted to other formats:

# Generate markdown
debtmap analyze . --format markdown -o report.md

# Convert to HTML with pandoc
pandoc report.md -o report.html --standalone --css style.css

# Convert to PDF
pandoc report.md -o report.pdf --pdf-engine=xelatex

Tool Integration

CI/CD Pipelines

Debtmap JSON output integrates seamlessly with CI/CD systems.

GitHub Actions

name: Code Quality

on: [pull_request]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install debtmap
        run: cargo install debtmap

      - name: Run analysis
        run: |
          debtmap analyze . \
            --format json \
            --output analysis.json \
            --lcov coverage/lcov.info

      - name: Check thresholds
        run: |
          DEBT_SCORE=$(jq '.technical_debt.items | length' analysis.json)
          if [ "$DEBT_SCORE" -gt 100 ]; then
            echo "❌ Debt score too high: $DEBT_SCORE"
            exit 1
          fi

      - name: Comment on PR
        uses: actions/github-script@v6
        with:
          script: |
            const fs = require('fs');
            const analysis = JSON.parse(fs.readFileSync('analysis.json'));
            const summary = `## Debtmap Analysis

            - **Debt Items:** ${analysis.technical_debt.items.length}
            - **Average Complexity:** ${analysis.complexity.summary.average_complexity}
            - **High Complexity Functions:** ${analysis.complexity.summary.high_complexity_count}
            `;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: summary
            });

GitLab CI

code_quality:
  stage: test
  script:
    - cargo install debtmap
    - debtmap analyze . --format json --output gl-code-quality.json
    - |
      DEBT=$(jq '.technical_debt.items | length' gl-code-quality.json)
      if [ "$DEBT" -gt 50 ]; then
        echo "Debt threshold exceeded"
        exit 1
      fi
  artifacts:
    reports:
      codequality: gl-code-quality.json

Jenkins Pipeline

pipeline {
    agent any

    stages {
        stage('Analyze') {
            steps {
                sh 'debtmap analyze . --format json -o report.json'

                script {
                    def json = readJSON file: 'report.json'
                    def debtScore = json.technical_debt.items.size()

                    if (debtScore > 100) {
                        error("Debt score ${debtScore} exceeds threshold")
                    }
                }
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: 'report.json'
        }
    }
}

Querying JSON with jq

Common jq queries for analyzing debtmap output:

# Get total debt items
jq '.technical_debt.items | length' report.json

# Get high-priority items only
jq '.technical_debt.items[] | select(.priority == "High")' report.json

# Get functions with complexity > 10
jq '.complexity.metrics[] | select(.cyclomatic > 10)' report.json

# Calculate average complexity
jq '.complexity.summary.average_complexity' report.json

# Get all TODO items
jq '.technical_debt.items[] | select(.debt_type == "Todo")' report.json

# Get top 5 complex functions
jq '.complexity.metrics | sort_by(-.cyclomatic) | .[0:5] | .[] | {name, file, cyclomatic}' report.json

# Get files with circular dependencies
jq '.dependencies.circular[] | .cycle' report.json

# Count debt items by type
jq '.technical_debt.items | group_by(.debt_type) | map({type: .[0].debt_type, count: length})' report.json

# Get functions with 0% coverage (when using --lcov)
jq '.complexity.metrics[] | select(.coverage == 0)' report.json

# Extract file paths with high debt
jq '.technical_debt.items[] | select(.priority == "High" or .priority == "Critical") | .file' report.json | sort -u

Filtering and Transformation Examples

Python Script to Parse JSON

#!/usr/bin/env python3
import json
import sys

def analyze_debtmap_output(json_file):
    with open(json_file) as f:
        data = json.load(f)

    # Get high-priority items
    high_priority = [
        item for item in data['technical_debt']['items']
        if item['priority'] in ['High', 'Critical']
    ]

    # Group by file
    by_file = {}
    for item in high_priority:
        file = item['file']
        if file not in by_file:
            by_file[file] = []
        by_file[file].append(item)

    # Print summary
    print(f"High-priority debt items: {len(high_priority)}")
    print(f"Files affected: {len(by_file)}")
    print("\nBy file:")
    for file, items in sorted(by_file.items(), key=lambda x: -len(x[1])):
        print(f"  {file}: {len(items)} items")

    return by_file

if __name__ == '__main__':
    analyze_debtmap_output(sys.argv[1])

Shell Script for Threshold Checking

#!/bin/bash
set -e

REPORT="$1"
DEBT_THRESHOLD=100
COMPLEXITY_THRESHOLD=10

# Check debt score
DEBT_SCORE=$(jq '.technical_debt.items | length' "$REPORT")
if [ "$DEBT_SCORE" -gt "$DEBT_THRESHOLD" ]; then
    echo "❌ Debt score $DEBT_SCORE exceeds threshold $DEBT_THRESHOLD"
    exit 1
fi

# Check average complexity
AVG_COMPLEXITY=$(jq '.complexity.summary.average_complexity' "$REPORT")
if (( $(echo "$AVG_COMPLEXITY > $COMPLEXITY_THRESHOLD" | bc -l) )); then
    echo "❌ Average complexity $AVG_COMPLEXITY exceeds threshold $COMPLEXITY_THRESHOLD"
    exit 1
fi

echo "✅ All quality checks passed"
echo "   Debt score: $DEBT_SCORE/$DEBT_THRESHOLD"
echo "   Avg complexity: $AVG_COMPLEXITY"

Editor Integration

VS Code Tasks

Create .vscode/tasks.json:

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Debtmap: Analyze",
      "type": "shell",
      "command": "debtmap",
      "args": [
        "analyze",
        ".",
        "--format",
        "terminal"
      ],
      "problemMatcher": [],
      "presentation": {
        "reveal": "always",
        "panel": "new"
      }
    },
    {
      "label": "Debtmap: Generate Report",
      "type": "shell",
      "command": "debtmap",
      "args": [
        "analyze",
        ".",
        "--format",
        "markdown",
        "-o",
        "DEBT_REPORT.md"
      ],
      "problemMatcher": []
    }
  ]
}

Problem Matcher for VS Code

Parse debtmap output in VS Code’s Problems panel:

{
  "problemMatcher": {
    "owner": "debtmap",
    "fileLocation": "absolute",
    "pattern": {
      "regexp": "^(.+?):(\\d+):(\\d+)?\\s*-\\s*(.+)$",
      "file": 1,
      "line": 2,
      "column": 3,
      "message": 4
    }
  }
}

Webhook Integration

Send debtmap results to webhooks for notifications:

#!/bin/bash

# Run analysis
debtmap analyze . --format json -o report.json

# Send to Slack
DEBT_SCORE=$(jq '.technical_debt.items | length' report.json)
curl -X POST "$SLACK_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\": \"Debtmap Analysis Complete\n• Debt Score: $DEBT_SCORE\n• High Priority: $(jq '[.technical_debt.items[] | select(.priority == "High")] | length' report.json)\"}"

# Send to custom webhook
curl -X POST "$CUSTOM_WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d @report.json

Output Filtering

Debtmap provides several flags to filter and limit output:

Note: Filtering options (--top, --tail, --summary, --filter) apply to all output formats (terminal, JSON, and markdown). The filtered data is applied at the analysis level before formatting, ensuring consistent results across all output types.

Limiting Results

# Show only top 10 priority items
debtmap analyze . --top 10

# Show bottom 5 lowest priority items
debtmap analyze . --tail 5

Priority Filtering

# Show only high and critical priority items
debtmap analyze . --min-priority high

# Filter by specific debt categories
debtmap analyze . --filter Architecture,Testing

Available categories:

  • Architecture: God objects, complexity hotspots, dead code
  • Testing: Testing gaps, coverage issues
  • Performance: Resource leaks, inefficient patterns
  • CodeQuality: Code smells, maintainability

Grouping Output

# Group results by debt category
debtmap analyze . --group-by-category

# Combine filters for focused analysis
debtmap analyze . --filter Architecture --min-priority high --top 5

Summary Mode

# Compact tiered priority display
debtmap analyze . --summary

# Combines well with filtering
debtmap analyze . --summary --min-priority medium

Best Practices

When to Use Each Format

Use Terminal Format When:

  • Developing locally and reviewing code
  • Getting quick feedback on changes
  • Presenting results to team members
  • Exploring complexity hotspots interactively

Use JSON Format When:

  • Integrating with CI/CD pipelines
  • Building custom analysis tools
  • Tracking metrics over time
  • Programmatically processing results
  • Feeding into dashboards or monitoring systems

Use Markdown Format When:

  • Generating documentation
  • Creating PR comments
  • Sharing reports with stakeholders
  • Archiving analysis results
  • Producing executive summaries

Quick Reference Table

FormatBest ForMachine ReadableHuman ReadableFile Extension
TerminalDevelopmentNoYes.txt
JSONAutomationYesNo.json
MarkdownDocumentationPartiallyYes.md

Combining Formats

Use multiple formats for comprehensive workflows:

# Generate terminal output for review
debtmap analyze .

# Generate JSON for automation
debtmap analyze . --format json -o ci-report.json

# Generate markdown for documentation
debtmap analyze . --format markdown -o docs/DEBT.md

Performance Considerations

  • Terminal format: Fastest, minimal overhead
  • JSON format: Fast serialization, efficient for large codebases
  • Markdown format: Slightly slower due to formatting, but still performant

For very large codebases (>10,000 files), use --top or --filter to limit output size.

Troubleshooting

Common Issues

Colors not showing in terminal:

  • Check if terminal supports ANSI colors
  • Use --plain flag for ASCII-only output
  • Some CI systems may not support color codes

JSON parsing errors:

  • Ensure output is complete (check for errors during analysis)
  • Validate JSON with jq or online validators
  • Check for special characters in file paths

Markdown rendering issues:

  • Some markdown renderers don’t support all features
  • Use standard markdown for maximum compatibility
  • Test with pandoc or GitHub/GitLab preview

File encoding problems:

  • Ensure UTF-8 encoding for all output files
  • Use --plain for pure ASCII output
  • Check locale settings (LC_ALL, LANG environment variables)

Exit Codes

IMPORTANT: Exit codes 1 and 2 are NOT YET IMPLEMENTED. Current behavior: Always returns 0 on successful analysis, regardless of threshold violations.

Planned behavior includes:

  • 0: Success, all checks passed
  • 1: Analysis completed, but validation thresholds exceeded
  • 2: Error during analysis (invalid path, parsing error, etc.)

For now, use the validate command with threshold checks to enforce quality gates:

# Use validate command for threshold enforcement
debtmap validate . --config debtmap.toml

# Or parse JSON output for threshold checking
debtmap analyze . --format json -o report.json
DEBT_SCORE=$(jq '.technical_debt.items | length' report.json)
if [ "$DEBT_SCORE" -gt 100 ]; then
    echo "Debt threshold exceeded"
    exit 1
fi

See Also

Tiered Prioritization

Debtmap uses a sophisticated tiered prioritization system to surface critical architectural issues above simple testing gaps. This chapter explains the tier strategy, how to interpret tier classifications, and how to customize tier thresholds for your project.

Overview

The tiered prioritization system organizes technical debt into four distinct tiers based on impact, urgency, and architectural significance. This prevents “walls of similar-scored items” and ensures critical issues don’t get lost among minor problems.

The Four Tiers

Tier 1: Critical Architecture

Description: God Objects, God Modules, excessive complexity requiring immediate architectural attention

Priority: Must address before adding new features

Weight: 1.5x (highest priority multiplier)

Impact: High impact on maintainability and team velocity

Examples:

  • Files with 15+ responsibilities
  • Modules with 50+ methods
  • God objects flagged by detection algorithms
  • Circular dependencies affecting core modules

When to Address: Immediately, before sprint work begins. These issues compound over time and block progress.

# Focus on Tier 1 items
debtmap analyze . --filter Architecture --min-priority high

Tier 2: Complex Untested

Description: Untested code with high complexity or critical dependencies

Priority: Risk of bugs in critical paths

Weight: 1.0x (standard multiplier)

Action: Should be tested before refactoring to prevent regressions

Examples:

  • Functions with cyclomatic complexity > 15 and 0% coverage
  • Business logic entry points without tests
  • Complex error handling without validation

When to Address: Within current sprint. Add tests before making changes.

# See Tier 2 testing gaps
debtmap analyze . --lcov coverage.lcov --filter Testing

Tier 3: Testing Gaps

Description: Untested code with moderate complexity

Priority: Improve coverage to prevent future issues

Weight: 0.7x (reduced multiplier)

Action: Add tests opportunistically or during related changes

Examples:

  • Functions with cyclomatic complexity 10-15 and low coverage
  • Utility functions without edge case tests
  • Moderate complexity with partial coverage

When to Address: Next sprint or when touching related code.

Tier 4: Maintenance

Description: Low-complexity issues and code quality improvements

Priority: Address opportunistically during other work

Weight: 0.3x (lowest multiplier)

Action: Fix when convenient, low urgency

Examples:

  • Simple functions with minor code quality issues
  • TODO markers in well-tested code
  • Minor duplication in test code

When to Address: During cleanup sprints or when refactoring nearby code.

Configuration

Default Tier Thresholds

[tiers]
# Tier 2 thresholds (Complex Untested)
t2_complexity_threshold = 15         # Cyclomatic complexity cutoff
t2_dependency_threshold = 10         # Dependency count cutoff

# Tier 3 thresholds (Testing Gaps)
t3_complexity_threshold = 10         # Lower complexity threshold

# Display options
show_t4_in_main_report = false      # Hide Tier 4 from main output

# Tier weights
[tiers.tier_weights]
t1 = 1.5    # Critical architecture
t2 = 1.0    # Complex untested
t3 = 0.7    # Testing gaps
t4 = 0.3    # Maintenance

Customizing Tier Thresholds

Adjust thresholds to match your team’s standards:

# Stricter thresholds for high-quality codebases
[tiers]
t2_complexity_threshold = 12
t3_complexity_threshold = 8

# More lenient for legacy codebases
[tiers]
t2_complexity_threshold = 20
t3_complexity_threshold = 15

Tier Weight Customization

Adjust weights based on your priorities:

# Emphasize testing over architecture
[tiers.tier_weights]
t1 = 1.2    # Reduce architecture weight
t2 = 1.3    # Increase testing weight
t3 = 0.8
t4 = 0.3

# Focus on architecture first
[tiers.tier_weights]
t1 = 2.0    # Maximize architecture weight
t2 = 1.0
t3 = 0.5
t4 = 0.2

Use Cases

Sprint Planning

Use tiered prioritization to allocate work:

# See Tier 1 items for architectural planning
debtmap analyze . --filter Architecture --top 5

# See Tier 2/3 for testing sprint work
debtmap analyze . --filter Testing --min-priority medium

Code Review Focus

Prioritize review attention based on tiers:

  • Tier 1: Architectural review required, senior dev attention
  • Tier 2: Test coverage validation critical
  • Tier 3: Standard review process
  • Tier 4: Quick review or automated checks

Refactoring Strategy

# Phase 1: Address Tier 1 architectural issues
debtmap analyze . --filter Architecture

# Phase 2: Add tests for Tier 2 complex code
debtmap analyze . --lcov coverage.lcov --min-priority high

# Phase 3: Improve Tier 3 coverage
debtmap analyze . --lcov coverage.lcov --min-priority medium

Best Practices

  1. Always address Tier 1 before feature work - Architectural issues compound
  2. Test Tier 2 items before refactoring - Avoid regressions
  3. Batch Tier 3 items - Address multiple in one sprint
  4. Defer Tier 4 items - Only fix during cleanup or when convenient
  5. Track tier distribution over time - Aim to reduce Tier 1/2 counts

Interpreting Tier Output

Terminal Output

════════════════════════════════════════════
    TIERED TECHNICAL DEBT REPORT
════════════════════════════════════════════

🔴 TIER 1: CRITICAL ARCHITECTURE (3 items)
  1. src/services.rs - God Object (85% god score, 52 methods)
  2. src/core/engine.rs - Circular dependency with parsers module
  3. src/api/handlers.rs - God Module (15 responsibilities)

🟠 TIER 2: COMPLEX UNTESTED (12 items)
  1. src/processing/transform.rs:145 - Complexity 18, Coverage 0%
  ...

🟡 TIER 3: TESTING GAPS (45 items)
  ...

⚪ TIER 4: MAINTENANCE (120 items) [hidden]
  Use --show-t4 to display maintenance items

JSON Output

{
  "tier_distribution": {
    "t1_count": 3,
    "t2_count": 12,
    "t3_count": 45,
    "t4_count": 120
  },
  "items": [
    {
      "tier": "T1_CriticalArchitecture",
      "priority_weight": 1.5,
      "base_score": 8.5,
      "final_score": 12.75
    }
  ]
}

Troubleshooting

Issue: Too many Tier 1 items

Solution: Lower tier weights or increase thresholds temporarily:

[tiers.tier_weights]
t1 = 1.2    # Reduce from 1.5

Issue: Not enough items in Tier 1

Solution: Check if god object detection is enabled:

[god_object_detection]
enabled = true

Issue: All items in Tier 4

Solution: Lower minimum thresholds:

[thresholds]
minimum_debt_score = 1.0
minimum_cyclomatic_complexity = 2

See Also

Scoring Strategies

Debtmap provides two complementary scoring approaches: file-level and function-level. Understanding when to use each approach helps you make better refactoring decisions and prioritize work effectively.

Overview

Different refactoring scenarios require different levels of granularity:

  • File-level scoring: Identifies architectural issues and planning major refactoring initiatives
  • Function-level scoring: Pinpoints specific hot spots for targeted improvements

This chapter explains both approaches, when to use each, and how to interpret the results.

File-Level Scoring

File-level scoring aggregates metrics across all functions in a file to identify architectural problems and module-level refactoring opportunities.

Formula

File Score = Size × Complexity × Coverage × Density × GodObject × FunctionScores

Where each factor is calculated as:

  • Size = sqrt(total_lines / 100)
  • Complexity = (avg_complexity / 5.0) × sqrt(total_complexity / 50.0)
  • Coverage = (1 - coverage_percent) × 2 + 1
  • Density = max(1.0, function_count / 50) if function_count > 50
  • GodObject = 2.0 + god_object_score if detected
  • FunctionScores = sum(function_scores) / 10

Factors

Size Factor: sqrt(total_lines / 100)

  • Larger files have higher impact
  • Square root dampens the effect to avoid over-penalizing large files
  • Rationale: Refactoring a 1000-line file affects more code than a 100-line file

Complexity Factor: Combines average and total complexity

  • (average_cyclomatic + total_cyclomatic / function_count) / 2
  • Balances per-function and aggregate complexity
  • Rationale: Both concentrated complexity and spread-out complexity matter

Coverage Factor: (1 - coverage_percent) × 2 + 1

  • Lower coverage increases score multiplicatively
  • Range: 1.0 (100% coverage) to 3.0 (0% coverage)
  • Rationale: Untested files are riskier to refactor

Density Factor: Penalizes files with excessive function count

  • Triggers when function count > 50
  • max(1.0, function_count / 50)
  • Rationale: Files with 100+ functions likely violate single responsibility

God Object Multiplier: 2.0 + god_object_score when detected

  • Applies when god object detection flags the file
  • Range: 2.0 (borderline) to 3.0 (severe god object)
  • Rationale: God objects need immediate architectural attention

Function Scores: sum(all_function_scores) / 10

  • Normalized sum of individual function debt scores
  • Provides baseline before modifiers

Use Cases

1. Planning Major Refactoring Initiatives

# Show top 10 files needing architectural refactoring
debtmap analyze . --aggregate-only --top 10

Use when:

  • Planning sprint or quarterly refactoring work
  • Deciding which modules to split
  • Prioritizing architectural improvements
  • Allocating team resources

Note: File-level scoring is enabled with the --aggregate-only flag, which changes output to show only file-level metrics instead of function-level details.

2. Identifying Architectural Issues

File-level scoring excels at finding:

  • God objects with too many responsibilities
  • Files with poor cohesion
  • Modules that should be split
  • Files with too many functions
# Focus on architectural problems
debtmap analyze . --aggregate-only --filter Architecture

3. Breaking Up Monolithic Modules

# Find files with excessive function counts
debtmap analyze . --aggregate-only --min-problematic 50

4. Evaluating Overall Codebase Health

# Generate file-level report for executive summary
debtmap analyze . --aggregate-only --format markdown -o report.md

Aggregation Methods

Debtmap supports multiple aggregation methods for file-level scores, configurable via CLI or configuration file.

Weighted Sum (Default)

debtmap analyze . --aggregation-method weighted_sum

Or via configuration:

[aggregation]
method = "weighted_sum"
  • Weights functions by complexity and coverage
  • Emphasizes high-impact functions
  • Best for most use cases

Simple Sum

[aggregation]
method = "sum"
  • Adds all function scores directly
  • Treats all functions equally
  • Useful for broad overview

Logarithmic Sum

[aggregation]
method = "logarithmic_sum"
  • Dampens impact of many small issues
  • log(1 + sum_of_scores)
  • Useful for legacy codebases with many minor issues

Max Plus Average

[aggregation]
method = "max_plus_average"
  • Considers worst function plus average of others
  • max_score × 0.6 + average_score × 0.4
  • Balances worst-case and typical-case analysis

Configuration

[aggregation]
method = "weighted_sum"
min_problematic = 3              # Need 3+ problematic functions for file-level score

[god_object_detection]
enabled = true
max_methods = 20
max_fields = 15
max_responsibilities = 5

Function-Level Scoring

Function-level scoring identifies specific functions needing attention for targeted improvements.

Formula

Function Score = (Complexity × 0.35) + (Coverage × 0.50) + (Dependency × 0.15)
Final Score = Base Score × Role Multiplier

Note: These weights are configurable via the [scoring] section in .debtmap.toml. See Configuration below.

Metrics

Cyclomatic Complexity

  • Counts decision points (if, match, loops)
  • Guides test case count

Cognitive Complexity

  • Measures understanding difficulty
  • Accounts for nesting depth

Coverage Percentage

  • Direct line coverage from LCOV
  • 0% coverage = maximum urgency

Dependency Count

  • Upstream callers + downstream callees
  • Higher dependencies = higher impact

Role Multiplier

Functions are classified by role, and each role receives a multiplier based on its architectural importance:

  • Entry points: 1.5x - Public APIs, main functions, HTTP handlers
  • Pure logic / Business logic: 1.2x-1.3x - Core business rules and algorithms (multiplier increases with complexity)
  • Orchestrator: 0.8x - Functions that coordinate other functions
  • IO wrapper: 0.5x - Simple file/network I/O wrappers
  • Pattern match: 0.6x - Functions primarily doing pattern matching
  • Utility: 0.5x - Helper functions and utilities

Note: Role multipliers are configurable via the [role_multipliers] section in .debtmap.toml.

Use Cases

1. Identifying Specific Hot Spots

# Show top 20 functions needing attention
debtmap analyze . --top 20

Use when:

  • Planning individual developer tasks
  • Assigning specific refactoring work
  • Identifying functions to test first
  • Code review focus

2. Sprint Planning for Developers

# Get function-level tasks for this sprint
debtmap analyze . --top 10 --format json -o sprint-tasks.json

3. Writing Unit Tests

# Find untested complex functions
debtmap analyze . --lcov coverage.lcov --filter Testing --top 15

4. Targeted Performance Optimization

# Find complex hot paths
debtmap analyze . --filter Performance --context --top 10

Configuration

[scoring]
coverage = 0.50              # Weight for coverage gaps (default)
complexity = 0.35            # Weight for complexity (default)
dependency = 0.15            # Weight for dependency impact (default)

[role_multipliers]
entry_point = 1.5
business_logic = 1.2
pure_logic = 1.2
orchestrator = 0.8
io_wrapper = 0.7
utility = 0.5

When to Use Each Approach

Use File-Level Scoring When:

✅ Planning architectural refactoring ✅ Quarterly or annual planning ✅ Deciding which modules to split ✅ Executive summaries and high-level reports ✅ Team capacity planning ✅ Identifying god objects ✅ Module reorganization

Command:

debtmap analyze . --aggregate-only

Use Function-Level Scoring When:

✅ Sprint planning ✅ Individual developer task assignment ✅ Writing specific unit tests ✅ Code review preparation ✅ Pair programming sessions ✅ Daily or weekly development work ✅ Targeted hot spot fixes

Command:

debtmap analyze . --top 20

Use Both Together:

Many workflows benefit from both views:

# Step 1: Identify problematic files
debtmap analyze . --aggregate-only --top 5 -o files.json

# Step 2: Drill into specific file
debtmap analyze src/problematic/module.rs --format terminal

Comparison Examples

Example 1: God Object Detection

File-Level View:

src/services/user_service.rs - Score: 245.8
  - 850 lines, 45 methods
  - God Object: 78% score
  - Action: Split into UserAuth, UserProfile, UserNotifications

Function-Level View:

src/services/user_service.rs:142 - authenticate_user() - Score: 8.5
src/services/user_service.rs:298 - update_profile() - Score: 7.2
src/services/user_service.rs:456 - send_notification() - Score: 6.8

Decision: File-level score (245.8) correctly identifies architectural issue. Individual functions aren’t exceptionally complex, but the file has too many responsibilities. Solution: Split the file.

Example 2: Targeted Function Fix

File-Level View:

src/parsers/expression.rs - Score: 45.2
  - 320 lines, 12 functions
  - No god object detected

Function-Level View:

src/parsers/expression.rs:89 - parse_complex_expression() - Score: 9.1
  - Cyclomatic: 22, Cognitive: 35
  - Coverage: 0%
  - Action: Add tests and refactor

Decision: File as a whole is acceptable, but one function needs attention. Solution: Focus on that specific function.

Example 3: Balanced Refactoring

File-Level View:

src/analysis/scoring.rs - Score: 125.6
  - 580 lines, 18 functions
  - High complexity, low coverage

Function-Level View:

calculate_score() - Score: 8.8 (15% coverage)
apply_weights() - Score: 8.2 (10% coverage)
normalize_results() - Score: 7.5 (0% coverage)

Decision: Both file and functions need work. Solution: Add tests first (function-level), then consider splitting if complexity persists (file-level).

Score Normalization

Both scoring approaches normalize to a 0-10 scale for consistency.

Normalization Strategy

#![allow(unused)]
fn main() {
score_normalized = if raw_score < 10.0 {
    raw_score  // Linear below 10
} else if raw_score < 100.0 {
    sqrt(raw_score) × 3.33  // Square root 10-100
} else {
    log10(raw_score) × 10.0  // Logarithmic above 100
}
}

Configuration

[normalization]
linear_threshold = 10.0       # Scores below this use linear scaling (1:1 mapping)
logarithmic_threshold = 100.0 # Scores above this use logarithmic dampening
sqrt_multiplier = 3.33        # Applied to scores between linear and log thresholds
log_multiplier = 10.0         # Applied to scores above logarithmic threshold
show_raw_scores = true        # Display both normalized (0-10) and raw scores in output

Explanation:

  • linear_threshold: Scores below this value are mapped 1:1 (no scaling)
  • logarithmic_threshold: Scores above this value are dampened logarithmically to prevent extreme values
  • sqrt_multiplier: Square root scaling applied to mid-range scores (between linear and logarithmic thresholds)
  • log_multiplier: Logarithmic dampening factor for very high scores
  • show_raw_scores: When enabled, output includes both the normalized 0-10 score and the raw calculated score

Best Practices

Workflow Integration

Week 1: File-Level Assessment

# Identify architectural problems
debtmap analyze . --aggregate-only --top 10

Week 2-4: Function-Level Work

# Work through specific functions
debtmap analyze src/target/module.rs

Monthly: Compare Progress

debtmap compare --before baseline.json --after current.json

Team Collaboration

  • Architects: Use file-level scores for strategic planning
  • Tech Leads: Use both for sprint planning
  • Developers: Use function-level for daily work
  • QA: Use function-level for test prioritization

CI/CD Integration

# Gate: No new file-level regressions
debtmap analyze . --aggregate-only --format json -o file-scores.json

# Gate: No new critical function-level issues
debtmap analyze . --min-priority critical --format json -o critical-items.json

Troubleshooting

Issue: File-level scores seem too high

Solution: Check aggregation method:

[aggregation]
method = "logarithmic_sum"  # Dampen scores

Issue: Function-level scores all similar

Solution: Adjust scoring weights to emphasize different factors:

[scoring]
coverage = 0.60    # Emphasize testing gaps more
complexity = 0.30
dependency = 0.10

Issue: Too many low-priority items

Solution: Use minimum thresholds:

[thresholds]
minimum_debt_score = 3.0

See Also

Prodigy Integration

Debtmap integrates with Prodigy to provide fully automated technical debt reduction through AI-driven workflows. This chapter explains how to set up and use Prodigy workflows to automatically refactor code, add tests, and improve codebase quality.

What is Prodigy?

Prodigy is an AI-powered workflow automation system that uses Claude to execute complex multi-step tasks. When integrated with Debtmap, it can:

  • Automatically refactor high-complexity functions identified by Debtmap
  • Add unit tests for untested code
  • Fix code duplication by extracting shared logic
  • Improve code organization by addressing architectural issues
  • Validate improvements with automated testing

All changes are made in isolated git worktrees, validated with tests and linting, and only committed if all checks pass.

Benefits

Automated Debt Reduction

Instead of manually addressing each technical debt item, Prodigy can:

  1. Analyze Debtmap’s output
  2. Select high-priority items
  3. Generate refactoring plans
  4. Execute refactorings automatically
  5. Validate with tests
  6. Commit clean changes

Iterative Improvement

Prodigy supports iterative workflows:

  • Run analysis → fix top items → re-analyze → fix more
  • Configurable iteration count (default: 5 iterations)
  • Each iteration focuses on highest-priority remaining items

Safe Experimentation

All changes happen in isolated git worktrees:

  • Original branch remains untouched
  • Failed attempts don’t affect main codebase
  • Easy to review before merging
  • Automatic cleanup after workflow

Prerequisites

Install Prodigy

# Install Prodigy CLI
cargo install prodigy

# Verify installation
prodigy --version

Configure Claude API

# Set Claude API key
export ANTHROPIC_API_KEY="your-api-key-here"

# Or in ~/.prodigy/config.toml:
[api]
anthropic_key = "your-api-key-here"

Ensure Debtmap is Installed

# Install Debtmap
cargo install debtmap

# Verify installation
debtmap --version

Quick Start

1. Initialize Workflow

Create a workflow file workflows/debtmap.yml:

# Sequential workflow. Fix top technical debt item

# Phase 1: Generate coverage data
- shell: "just coverage-lcov"

# Phase 2: Analyze tech debt and capture baseline
- shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-before.json --format json"

# Phase 3: Create implementation plan (PLANNING PHASE)
- claude: "/prodigy-debtmap-plan --before .prodigy/debtmap-before.json --output .prodigy/IMPLEMENTATION_PLAN.md"
  capture_output: true
  validate:
    commands:
      - claude: "/prodigy-validate-debtmap-plan --before .prodigy/debtmap-before.json --plan .prodigy/IMPLEMENTATION_PLAN.md --output .prodigy/plan-validation.json"
    result_file: ".prodigy/plan-validation.json"
    threshold: 75
    on_incomplete:
      commands:
        - claude: "/prodigy-revise-debtmap-plan --gaps ${validation.gaps} --plan .prodigy/IMPLEMENTATION_PLAN.md"
      max_attempts: 3
      fail_workflow: false

# Phase 4: Execute the plan (IMPLEMENTATION PHASE)
- claude: "/prodigy-debtmap-implement --plan .prodigy/IMPLEMENTATION_PLAN.md"
  commit_required: true
  validate:
    commands:
      - shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-after.json --format json"
      - shell: "debtmap compare --before .prodigy/debtmap-before.json --after .prodigy/debtmap-after.json --plan .prodigy/IMPLEMENTATION_PLAN.md --output .prodigy/comparison.json --format json"
      - claude: "/prodigy-validate-debtmap-improvement --comparison .prodigy/comparison.json --output .prodigy/debtmap-validation.json"
    result_file: ".prodigy/debtmap-validation.json"
    threshold: 75
    on_incomplete:
      commands:
        - claude: "/prodigy-complete-debtmap-fix --gaps ${validation.gaps} --plan .prodigy/IMPLEMENTATION_PLAN.md"
          commit_required: true
        - shell: "just coverage-lcov"
        - shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-after.json --format json"
        - shell: "debtmap compare --before .prodigy/debtmap-before.json --after .prodigy/debtmap-after.json --plan .prodigy/IMPLEMENTATION_PLAN.md --output .prodigy/comparison.json --format json"
      max_attempts: 5
      fail_workflow: true

# Phase 5: Run tests with automatic fixing
- shell: "just test"
  on_failure:
    claude: "/prodigy-debug-test-failure --output ${shell.output}"
    max_attempts: 5
    fail_workflow: true

# Phase 6: Run linting and formatting
- shell: "just fmt-check && just lint"
  on_failure:
    claude: "/prodigy-lint ${shell.output}"
    max_attempts: 5
    fail_workflow: true

2. Run Workflow

# Run with worktree, auto-confirm, 5 iterations
prodigy cook workflows/debtmap.yml -wyn 5

# Run with custom iteration count
prodigy cook workflows/debtmap.yml -wyn 10

# Run single iteration for testing
prodigy cook workflows/debtmap.yml -wyn 1

Command Flags:

  • -w - Create an isolated git worktree for changes
  • -y - Auto-confirm workflow steps (skip prompts)
  • -n 5 - Run workflow for up to 5 iterations

3. Review Results

Prodigy creates a detailed report:

📊 WORKFLOW SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Iterations: 5
Items Fixed: 12
Tests Added: 8
Complexity Reduced: 145 → 78 (-46%)
Coverage Improved: 45% → 72% (+27%)

✅ All validations passed

Workflow Configuration

Prodigy workflows are defined as YAML lists of steps. Each step can be either a shell command or a claude slash command.

Workflow Step Types

Shell Commands

Execute shell commands directly:

- shell: "cargo test"

With error handling:

- shell: "just test"
  on_failure:
    claude: "/prodigy-debug-test-failure --output ${shell.output}"
    max_attempts: 5
    fail_workflow: true

Claude Commands

Execute Claude Code slash commands:

- claude: "/prodigy-debtmap-plan --before .prodigy/debtmap-before.json --output .prodigy/IMPLEMENTATION_PLAN.md"
  capture_output: true
  commit_required: true

Step-Level Validation

Steps can include validation that must pass:

- claude: "/prodigy-debtmap-implement --plan .prodigy/IMPLEMENTATION_PLAN.md"
  commit_required: true
  validate:
    commands:
      - shell: "cargo test"
      - shell: "cargo clippy -- -D warnings"
    result_file: ".prodigy/validation.json"
    threshold: 75
    on_incomplete:
      commands:
        - claude: "/prodigy-complete-debtmap-fix --gaps ${validation.gaps} --plan .prodigy/IMPLEMENTATION_PLAN.md"
          commit_required: true
      max_attempts: 5
      fail_workflow: true

Validation Options:

  • commands: List of commands to run for validation
  • result_file: JSON file containing validation results
  • threshold: Minimum score (0-100) required to pass
  • on_incomplete: Actions to take if validation score < threshold
  • max_attempts: Maximum retry attempts
  • fail_workflow: Whether to fail entire workflow if validation never passes

Error Handling

Use on_failure to handle command failures:

- shell: "just fmt-check && just lint"
  on_failure:
    claude: "/prodigy-lint ${shell.output}"
    max_attempts: 5
    fail_workflow: true

Error Handling Options:

  • claude: Slash command to fix the failure
  • max_attempts: Maximum fix attempts
  • fail_workflow: If true, workflow fails after max_attempts; if false, continues to next step

Coverage Integration

Generate and use coverage data in workflows:

# Generate coverage
- shell: "just coverage-lcov"

# Use coverage in analysis
- shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-before.json --format json"

Claude Slash Commands

Prodigy workflows use Claude Code slash commands to perform analysis, planning, and implementation. The key commands used in the debtmap workflow are:

Planning Commands

/prodigy-debtmap-plan

Creates an implementation plan for the top priority debt item.

- claude: "/prodigy-debtmap-plan --before .prodigy/debtmap-before.json --output .prodigy/IMPLEMENTATION_PLAN.md"
  capture_output: true

Parameters:

  • --before: Path to debtmap analysis JSON file
  • --output: Path to write implementation plan

/prodigy-validate-debtmap-plan

Validates that the implementation plan is complete and addresses the debt item.

- claude: "/prodigy-validate-debtmap-plan --before .prodigy/debtmap-before.json --plan .prodigy/IMPLEMENTATION_PLAN.md --output .prodigy/plan-validation.json"

Parameters:

  • --before: Original debtmap analysis
  • --plan: Implementation plan to validate
  • --output: Validation results JSON (with score 0-100)

/prodigy-revise-debtmap-plan

Revises an incomplete plan based on validation gaps.

- claude: "/prodigy-revise-debtmap-plan --gaps ${validation.gaps} --plan .prodigy/IMPLEMENTATION_PLAN.md"

Parameters:

  • --gaps: List of missing items from validation
  • --plan: Plan file to update

Implementation Commands

/prodigy-debtmap-implement

Executes the implementation plan.

- claude: "/prodigy-debtmap-implement --plan .prodigy/IMPLEMENTATION_PLAN.md"
  commit_required: true

Parameters:

  • --plan: Path to implementation plan

/prodigy-validate-debtmap-improvement

Validates that the implementation successfully addressed the debt item.

- claude: "/prodigy-validate-debtmap-improvement --comparison .prodigy/comparison.json --output .prodigy/debtmap-validation.json"

Parameters:

  • --comparison: Debtmap comparison results (before vs after)
  • --output: Validation results JSON (with score 0-100)

/prodigy-complete-debtmap-fix

Completes a partial fix based on validation gaps.

- claude: "/prodigy-complete-debtmap-fix --gaps ${validation.gaps} --plan .prodigy/IMPLEMENTATION_PLAN.md"
  commit_required: true

Parameters:

  • --gaps: Validation gaps to address
  • --plan: Original implementation plan

Testing and Quality Commands

/prodigy-debug-test-failure

Automatically fixes failing tests.

- shell: "just test"
  on_failure:
    claude: "/prodigy-debug-test-failure --output ${shell.output}"
    max_attempts: 5

Parameters:

  • --output: Test failure output from shell command

/prodigy-lint

Fixes linting and formatting issues.

- shell: "just fmt-check && just lint"
  on_failure:
    claude: "/prodigy-lint ${shell.output}"
    max_attempts: 5

Parameters:

  • Shell output with linting errors

Target Selection

Target selection happens through the debtmap analysis and slash commands, not through workflow configuration:

How Targets Are Selected

  1. Debtmap analyzes the codebase and scores all items by complexity, coverage, and risk
  2. Planning command (/prodigy-debtmap-plan) selects the highest priority item
  3. Implementation command (/prodigy-debtmap-implement) fixes that specific item
  4. Next iteration re-analyzes and selects the next highest priority item

Factors in Prioritization

  • Complexity score: Functions with cyclomatic complexity > 10
  • Coverage percentage: Lower coverage increases priority
  • Risk score: Complexity × (100 - coverage%)
  • Debt type: Complexity, TestGap, Duplication, GodObject, DeepNesting

Customizing Target Selection

To focus on specific debt types or modules, modify the slash commands or create custom commands in .claude/commands/

Map-Reduce Workflows

Prodigy supports map-reduce workflows for processing multiple items in parallel. This is useful for large-scale refactoring tasks.

When to Use Map-Reduce

  • Processing multiple independent debt items simultaneously
  • Applying the same fix pattern across many files
  • Large-scale codebase cleanup tasks

Map-Reduce Structure

The exact syntax for map-reduce workflows in Prodigy may differ from sequential workflows. Consult the Prodigy documentation for current map-reduce syntax and examples.

Key Concepts:

  • Map phase: Process items in parallel using multiple agents
  • Reduce phase: Aggregate results and ensure consistency
  • Isolation: Each map agent works in its own worktree
  • Validation: All changes must pass validation before merging

Iteration Strategy

How Iterations Work

When you run prodigy cook workflows/debtmap.yml -wyn 5, the workflow executes up to 5 times:

  1. Iteration 1:

    • Analyze codebase with debtmap
    • Select highest priority item
    • Create implementation plan
    • Execute plan and validate
    • Run tests and linting
  2. Iteration 2:

    • Re-analyze codebase (scores updated based on Iteration 1 changes)
    • Select next highest priority item
    • Repeat plan/implement/validate cycle
  3. Continue until iteration limit reached or workflow completes without finding issues

Controlling Iterations

Iterations are controlled via the -n flag:

# Single iteration (testing)
prodigy cook workflows/debtmap.yml -wyn 1

# Standard run (5 iterations)
prodigy cook workflows/debtmap.yml -wyn 5

# Deep cleanup (10+ iterations)
prodigy cook workflows/debtmap.yml -wyn 20

What Happens Each Iteration

Each iteration runs the entire workflow from start to finish:

  1. Generate coverage data
  2. Analyze technical debt
  3. Create implementation plan
  4. Execute plan
  5. Validate improvement
  6. Run tests (with auto-fixing)
  7. Run linting (with auto-fixing)

The workflow continues to the next iteration automatically if all steps succeed.

Example Output

Iteration 1:
  - Fixed: parse_expression() (9.2 → 5.1)
  - Fixed: calculate_score() (8.8 → 4.2)
  - Fixed: apply_weights() (8.5 → 5.8)
  ✓ Tests pass

Iteration 2:
  - Fixed: normalize_results() (7.5 → 3.9)
  - Fixed: aggregate_data() (7.2 → 4.1)
  ✓ Tests pass

Iteration 3:
  - No items above threshold (6.0)
  ✓ Early stop

Final Results:
  Items fixed: 5
  Average complexity: 15.2 → 8.6

Validation

Prodigy validates changes at the workflow step level, not as a standalone configuration.

Step-Level Validation

Validation is attached to specific workflow steps:

- claude: "/prodigy-debtmap-implement --plan .prodigy/IMPLEMENTATION_PLAN.md"
  commit_required: true
  validate:
    commands:
      - shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-after.json --format json"
      - shell: "debtmap compare --before .prodigy/debtmap-before.json --after .prodigy/debtmap-after.json --plan .prodigy/IMPLEMENTATION_PLAN.md --output .prodigy/comparison.json --format json"
      - claude: "/prodigy-validate-debtmap-improvement --comparison .prodigy/comparison.json --output .prodigy/debtmap-validation.json"
    result_file: ".prodigy/debtmap-validation.json"
    threshold: 75
    on_incomplete:
      commands:
        - claude: "/prodigy-complete-debtmap-fix --gaps ${validation.gaps} --plan .prodigy/IMPLEMENTATION_PLAN.md"
          commit_required: true
        - shell: "just coverage-lcov"
        - shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-after.json --format json"
        - shell: "debtmap compare --before .prodigy/debtmap-before.json --after .prodigy/debtmap-after.json --plan .prodigy/IMPLEMENTATION_PLAN.md --output .prodigy/comparison.json --format json"
      max_attempts: 5
      fail_workflow: true

Validation Process

  1. Commands run: Execute validation commands (shell or claude)
  2. Check result file: Read JSON file specified in result_file
  3. Compare to threshold: Score must be >= threshold (0-100 scale)
  4. On incomplete: If score < threshold, run on_incomplete commands
  5. Retry: Repeat up to max_attempts times
  6. Fail or continue: If fail_workflow: true, stop workflow; otherwise continue

Validation Result Format

The result_file JSON should contain:

{
  "score": 85,
  "passed": true,
  "gaps": [],
  "details": "All debt improvement criteria met"
}

Test Validation with Auto-Fix

Tests are validated with automatic fixing on failure:

- shell: "just test"
  on_failure:
    claude: "/prodigy-debug-test-failure --output ${shell.output}"
    max_attempts: 5
    fail_workflow: true

If tests fail, Prodigy automatically attempts to fix them up to 5 times before failing the workflow.

Output and Metrics

Workflow Report

{
  "workflow": "debtmap-debt-reduction",
  "iterations": 5,
  "items_processed": 12,
  "items_fixed": 10,
  "items_failed": 2,
  "metrics": {
    "complexity_before": 145,
    "complexity_after": 78,
    "complexity_reduction": -46.2,
    "coverage_before": 45.3,
    "coverage_after": 72.1,
    "coverage_improvement": 26.8
  },
  "changes": [
    {
      "file": "src/parser.rs",
      "function": "parse_expression",
      "before_score": 9.2,
      "after_score": 5.1,
      "improvements": ["Reduced complexity", "Added tests"]
    }
  ]
}

Commit Messages

Prodigy generates descriptive commit messages:

refactor(parser): reduce complexity in parse_expression

- Extract nested conditionals to helper functions
- Add unit tests for edge cases
- Coverage: 0% → 85%
- Complexity: 22 → 8

Generated by Prodigy workflow: debtmap-debt-reduction
Iteration: 1/5

Integration with CI/CD

GitHub Actions

name: Prodigy Debt Reduction

on:
  schedule:
    - cron: '0 0 * * 0'  # Weekly on Sunday
  workflow_dispatch:

jobs:
  reduce-debt:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Rust
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable

      - name: Install Prodigy
        run: cargo install prodigy

      - name: Install dependencies
        run: |
          cargo install debtmap
          cargo install just

      - name: Run Prodigy workflow
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: prodigy cook workflows/debtmap.yml -wyn 5

      - name: Create PR
        uses: peter-evans/create-pull-request@v5
        with:
          title: "chore: automated debt reduction via Prodigy"
          body: |
            Automated technical debt reduction using Prodigy workflow.

            This PR was generated by the weekly debt reduction workflow.
            Review changes carefully before merging.
          branch: prodigy-debt-reduction

GitLab CI

prodigy-debt-reduction:
  stage: quality
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
  script:
    - cargo install prodigy
    - cargo install debtmap
    - cargo install just
    - prodigy cook workflows/debtmap.yml -wyn 5
  artifacts:
    paths:
      - .prodigy/debtmap-*.json
      - .prodigy/comparison.json

Important CI Considerations

  • API Keys: Store ANTHROPIC_API_KEY as a secret
  • Worktrees: The -w flag creates isolated worktrees automatically
  • Dependencies: Install prodigy, debtmap, and just (or your build tool)
  • Timeout: CI jobs may need extended timeout for multiple iterations
  • Review: Always create a PR for human review before merging automated changes

Best Practices

1. Start Small

Begin with low iteration counts:

# First run: 1 iteration to test workflow
prodigy cook workflows/debtmap.yml -wyn 1

# Standard run: 3-5 iterations
prodigy cook workflows/debtmap.yml -wyn 5

2. Focus on High-Priority Items

The debtmap analysis automatically prioritizes by:

  • Complexity score (cyclomatic complexity)
  • Coverage percentage (lower coverage = higher priority)
  • Risk score (complexity × (100 - coverage%))

To focus on specific areas, create custom slash commands in .claude/commands/ that filter by:

  • Module/file patterns
  • Specific debt types (Complexity, TestGap, Duplication)
  • Score thresholds

3. Validate Thoroughly

Use comprehensive validation in your workflow:

- shell: "just test"
  on_failure:
    claude: "/prodigy-debug-test-failure --output ${shell.output}"
    max_attempts: 5
    fail_workflow: true

- shell: "just fmt-check && just lint"
  on_failure:
    claude: "/prodigy-lint ${shell.output}"
    max_attempts: 5
    fail_workflow: true

4. Review Before Merging

Always review Prodigy’s changes:

# Find your worktree
ls ~/.prodigy/worktrees/

# Check changes
cd ~/.prodigy/worktrees/session-xxx
git diff main

# Review commit history
git log --oneline

# Run full test suite
cargo test --all-features

5. Monitor Progress

Track debt reduction over iterations:

# Compare before and after
debtmap compare --before .prodigy/debtmap-before.json --after .prodigy/debtmap-after.json

# View detailed metrics
cat .prodigy/comparison.json | jq

Troubleshooting

Workflow Fails to Start

Issue: “Prodigy not found” or “API key missing”

Solution:

# Install Prodigy
cargo install prodigy

# Set API key
export ANTHROPIC_API_KEY="your-key"

# Verify installation
prodigy --version

Validation Failures

Issue: Validation score below threshold

Solution: Check validation results:

# View validation details
cat .prodigy/debtmap-validation.json

# Check what gaps remain
cat .prodigy/debtmap-validation.json | jq '.gaps'

# Review comparison results
cat .prodigy/comparison.json

The workflow will automatically retry up to max_attempts times with /prodigy-complete-debtmap-fix.

Test Failures

Issue: Tests fail after implementation

Solution: The workflow includes automatic test fixing:

- shell: "just test"
  on_failure:
    claude: "/prodigy-debug-test-failure --output ${shell.output}"
    max_attempts: 5
    fail_workflow: true

If tests still fail after 5 attempts, review manually:

# Check test output
just test

# Review recent changes
git diff HEAD~1

No Items Processed

Issue: Workflow completes but doesn’t find debt to fix

Possible Causes:

  1. Codebase has very low debt scores (below selection threshold)
  2. Coverage data not generated properly
  3. Debtmap analysis found no high-priority items

Solution:

# Check debtmap analysis results
cat .prodigy/debtmap-before.json | jq '.items | sort_by(-.unified_score.final_score) | .[0:5]'

# Verify coverage was generated
ls -lh target/coverage/lcov.info

# Run debtmap manually to see what's detected
debtmap analyze . --lcov target/coverage/lcov.info

Workflow Hangs or Times Out

Issue: Workflow takes too long or appears stuck

Possible Causes:

  • Large codebase with many files
  • Complex refactoring requiring extensive analysis
  • Network issues with Claude API

Solution:

  • Reduce iteration count for testing (-n 1)
  • Check Claude API connectivity
  • Monitor worktree for progress: cd ~/.prodigy/worktrees/session-xxx && git log

Example Workflows

Full Repository Cleanup

For comprehensive debt reduction, use a higher iteration count:

# Run 10 iterations for deeper cleanup
prodigy cook workflows/debtmap.yml -wyn 10

# Run 20 iterations for major refactoring
prodigy cook workflows/debtmap.yml -wyn 20

The workflow automatically:

  1. Selects highest priority items each iteration
  2. Addresses different debt types (Complexity, TestGap, Duplication)
  3. Validates all changes with tests and linting
  4. Commits only successful improvements

Custom Workflow for Specific Focus

Create a custom workflow file for focused improvements:

workflows/add-tests.yml - Focus on test coverage:

# Generate coverage
- shell: "just coverage-lcov"

# Analyze with focus on test gaps
- shell: "debtmap analyze . --lcov target/coverage/lcov.info --output .prodigy/debtmap-before.json --format json"

# Create plan (slash command will prioritize TestGap items)
- claude: "/prodigy-debtmap-plan --before .prodigy/debtmap-before.json --output .prodigy/IMPLEMENTATION_PLAN.md"

# ... rest of standard workflow steps

Run with:

prodigy cook workflows/add-tests.yml -wyn 5

Targeted Module Cleanup

Create a custom slash command to focus on specific modules:

.claude/commands/refactor-module.md:

# /refactor-module

Refactor the highest complexity item in the specified module.

Arguments: --module <module_name>

... implementation details ...

Then create a workflow using this command for targeted refactoring.

See Also

Examples

This chapter provides practical, real-world examples of using Debtmap across different project types and workflows. All examples use current CLI syntax verified against the source code.

Quick Start: New to Debtmap? Start with Basic Rust Analysis for the simplest introduction, then explore Coverage Integration for risk-based prioritization.

Quick Navigation: For detailed explanations of all CLI options, see the CLI Reference chapter.

Overview

This chapter demonstrates:

  • Language-specific analysis: Rust, Python, JavaScript/TypeScript with their respective testing tools
  • CI/CD integration: GitHub Actions, GitLab CI, CircleCI with validation gates
  • Output formats: Terminal, JSON, and Markdown with interpretation guidance
  • Advanced features: Context-aware analysis, multi-pass processing, cache management
  • Configuration patterns: Tailored settings for different project types
  • Progress tracking: Using the compare command to validate refactoring improvements

All examples are copy-paste ready and tested against the current Debtmap implementation.

Table of Contents

Analyzing Rust Projects

Basic Rust Analysis

Start with a simple analysis of your Rust project:

# Analyze all Rust files in current directory
debtmap analyze .

# Analyze specific directory
debtmap analyze ./src

# Analyze with custom complexity threshold
debtmap analyze ./src --threshold-complexity 15

Coverage Integration with cargo-tarpaulin

Combine complexity analysis with test coverage for risk-based prioritization:

# Generate LCOV coverage data
cargo tarpaulin --out lcov --output-dir target/coverage

# Analyze with coverage data
debtmap analyze . --lcov target/coverage/lcov.info

# Or use the shorter alias
debtmap analyze . --coverage-file target/coverage/lcov.info

What this does:

  • Functions with 0% coverage and high complexity get marked as [CRITICAL]
  • Well-tested functions (>80% coverage) are deprioritized
  • Shows risk reduction potential for each untested function

Custom Thresholds

Configure thresholds to match your project standards:

# Set both complexity and duplication thresholds
debtmap analyze . \
  --threshold-complexity 15 \
  --threshold-duplication 50

# Use preset configurations for quick setup
debtmap analyze . --threshold-preset strict    # Strict standards
debtmap analyze . --threshold-preset balanced  # Default balanced
debtmap analyze . --threshold-preset lenient   # Lenient for legacy code

God Object Detection

Identify classes and modules with too many responsibilities:

# Standard analysis includes god object detection
debtmap analyze .

# Disable god object detection for specific run
debtmap analyze . --no-god-object

God objects are flagged with detailed metrics:

  • Number of methods and fields
  • Responsibility count (grouped by naming patterns)
  • God object score (0-100%)
  • Recommendations for splitting

Filtering and Focusing

# Analyze only Rust files
debtmap analyze . --languages rust

# Focus on architecture issues (god objects, complexity)
debtmap analyze . --filter Architecture

# Focus on testing gaps
debtmap analyze . --filter Testing

# Filter by multiple categories
debtmap analyze . --filter Architecture,Testing

# Show only top 10 issues
debtmap analyze . --top 10

# Show only high-priority items
debtmap analyze . --min-priority high

Valid filter categories:

  • Architecture - God objects, high complexity, structural issues
  • Testing - Test coverage gaps, untested critical code
  • Duplication - Code duplication and similar patterns
  • Maintainability - Long functions, deep nesting, readability issues

Output Formats

# JSON output for CI integration
debtmap analyze . --format json --output report.json

# Markdown report
debtmap analyze . --format markdown --output DEBT_REPORT.md

# Terminal output (default) - prettified
debtmap analyze .

Multi-Pass Analysis

For deeper analysis with context awareness:

# Enable context-aware analysis with multiple providers
debtmap analyze . \
  --context \
  --context-providers critical_path,dependency,git_history

# Multi-pass analysis with attribution
debtmap analyze . --multi-pass --attribution

Complete CI Example

This is from Debtmap’s own .github/workflows/debtmap.yml:

# 1. Install cargo-tarpaulin
cargo install cargo-tarpaulin

# 2. Build debtmap
cargo build --release

# 3. Generate coverage
cargo tarpaulin --config .tarpaulin.toml --out Lcov --timeout 300

# 4. Run validation with coverage
./target/release/debtmap validate . \
  --coverage-file target/coverage/lcov.info \
  --format json \
  --output debtmap-report.json

Python Analysis

Basic Python Analysis

# Analyze Python files only
debtmap analyze . --languages python

# Analyze specific Python directory
debtmap analyze src --languages python

Coverage Integration with pytest

Generate coverage and analyze risk:

# Generate LCOV coverage with pytest
pytest --cov --cov-report=lcov

# Analyze with coverage data
debtmap analyze . \
  --languages python \
  --lcov coverage.lcov

Python-Specific Patterns

# Focus on testing gaps in Python code
debtmap analyze . \
  --languages python \
  --filter Testing

# Find god objects in Python modules
debtmap analyze . \
  --languages python \
  --filter Architecture

Example Configuration for Python Projects

Create .debtmap.toml:

[languages]
enabled = ["python"]

[thresholds]
complexity = 12
max_function_lines = 40

[ignore]
patterns = [
  "**/*_test.py",
  "tests/**",
  ".venv/**",
  "**/__pycache__/**",
]

[god_object]
enabled = true
max_methods = 15
max_responsibilities = 4

JavaScript/TypeScript

Analyzing JS/TS Projects

# Analyze JavaScript and TypeScript
debtmap analyze . --languages javascript,typescript

# TypeScript only
debtmap analyze . --languages typescript

Coverage Integration with Jest

# Generate LCOV with Jest
jest --coverage --coverageReporters=lcov

# Analyze with coverage
debtmap analyze . \
  --languages javascript,typescript \
  --lcov coverage/lcov.info

Node.js Project Patterns

# Exclude node_modules and focus on source
debtmap analyze src --languages javascript,typescript

# With custom complexity thresholds for JS
debtmap analyze . \
  --languages javascript,typescript \
  --threshold-complexity 10

TypeScript Configuration Example

Create .debtmap.toml:

[languages]
enabled = ["typescript", "javascript"]

[thresholds]
complexity = 10
max_function_lines = 50

[ignore]
patterns = [
  "node_modules/**",
  "**/*.test.ts",
  "**/*.spec.ts",
  "dist/**",
  "build/**",
  "**/*.d.ts",
]

Monorepo Analysis

# Analyze specific package
debtmap analyze packages/api --languages typescript

# Analyze all packages, grouped by category
debtmap analyze packages \
  --languages typescript \
  --group-by-category

CI Integration

GitHub Actions

Complete workflow example (from .github/workflows/debtmap.yml):

name: Debtmap

on:
  push:
    branches: [ main, master ]
  pull_request:
    branches: [ main, master ]
  workflow_dispatch:

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  validate:
    name: Technical Debt Validation
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v5
      with:
        fetch-depth: 0

    - name: Setup Rust
      uses: dtolnay/rust-toolchain@stable
      with:
        components: rustfmt, clippy

    - name: Cache cargo dependencies
      uses: actions/cache@v4
      with:
        path: |
          ~/.cargo/bin/
          ~/.cargo/registry/index/
          ~/.cargo/registry/cache/
          ~/.cargo/git/db/
          target/
        key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
        restore-keys: |
          ${{ runner.os }}-cargo-

    - name: Install cargo-tarpaulin
      run: |
        if ! command -v cargo-tarpaulin &> /dev/null; then
          cargo install cargo-tarpaulin
        else
          echo "cargo-tarpaulin already installed"
        fi

    - name: Build debtmap
      run: cargo build --release

    - name: Generate coverage data
      run: cargo tarpaulin --config .tarpaulin.toml --out Lcov --timeout 300

    - name: Run debtmap validation with coverage
      run: |
        if [ -f "target/coverage/lcov.info" ]; then
          ./target/release/debtmap validate . --coverage-file target/coverage/lcov.info --format json --output debtmap-report.json
        else
          echo "Warning: LCOV file not found, running validation without coverage data"
          ./target/release/debtmap validate . --format json --output debtmap-report.json
        fi

    - name: Upload debtmap report and coverage
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: debtmap-analysis-artifacts
        path: |
          debtmap-report.json
          target/coverage/lcov.info
        retention-days: 7

GitLab CI

debtmap:
  stage: quality
  image: rust:latest
  script:
    # Install debtmap
    - cargo install debtmap

    # Run tests with coverage
    - cargo install cargo-tarpaulin
    - cargo tarpaulin --out Lcov

    # Validate with debtmap
    - debtmap validate .
        --coverage-file cobertura.xml
        --format json
        --output debtmap-report.json
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: cobertura.xml
    paths:
      - debtmap-report.json
    expire_in: 1 week

CircleCI

version: 2.1

jobs:
  debtmap:
    docker:
      - image: cimg/rust:1.75
    steps:
      - checkout

      - run:
          name: Install debtmap
          command: cargo install debtmap

      - run:
          name: Generate coverage
          command: |
            cargo install cargo-tarpaulin
            cargo tarpaulin --out Lcov

      - run:
          name: Run debtmap
          command: |
            debtmap validate . \
              --coverage-file lcov.info \
              --format json \
              --output debtmap.json

      - store_artifacts:
          path: debtmap.json

workflows:
  version: 2
  build:
    jobs:
      - debtmap

Using debtmap validate for PR Gates

# Fail build if thresholds are exceeded
debtmap validate . --coverage-file lcov.info

# With custom thresholds
debtmap validate . \
  --coverage-file lcov.info \
  --threshold-complexity 15

# Exit code 0 if passing, 1 if failing

Compare Command in CI

Track technical debt trends over time:

# Generate baseline (on main branch)
debtmap analyze . --format json --output baseline.json

# After PR changes
debtmap analyze . --format json --output current.json

# Compare and fail if regressions detected
debtmap compare \
  --before baseline.json \
  --after current.json \
  --format json

Output Formats

Terminal Output (Default)

The default terminal output is prettified with colors and priorities:

debtmap analyze . --lcov coverage.lcov --top 3

Example output:

════════════════════════════════════════════
    PRIORITY TECHNICAL DEBT FIXES
════════════════════════════════════════════

🎯 TOP 3 RECOMMENDATIONS (by unified priority)

#1 SCORE: 8.9 [CRITICAL]
├─ TEST GAP: ./src/analyzers/rust.rs:38 parse_function()
├─ ACTION: Add 6 unit tests for full coverage
├─ IMPACT: Full test coverage, -3.7 risk
├─ COMPLEXITY: cyclomatic=6, cognitive=8, nesting=2, lines=32
├─ DEPENDENCIES: 0 upstream, 11 downstream
└─ WHY: Business logic with 0% coverage, manageable complexity

📊 TOTAL DEBT SCORE: 4907
📈 OVERALL COVERAGE: 67.12%

JSON Output

Machine-readable format for CI/CD integration:

debtmap analyze . --format json --output report.json

Using JSON output programmatically:

# Extract total debt score
debtmap analyze . --format json | jq '.total_debt_score'

# Count critical items
debtmap analyze . --format json | jq '[.items[] | select(.unified_score.final_score >= 8)] | length'

# Get top 5 functions by score
debtmap analyze . --format json | jq '.items | sort_by(-.unified_score.final_score) | .[0:5] | .[].location'

# Extract all test gap items
debtmap analyze . --format json | jq '[.items[] | select(.debt_type == "TestGap")]'

Structure:

{
  "items": [
    {
      "location": {
        "file": "src/main.rs",
        "function": "process_data",
        "line": 42
      },
      "debt_type": "TestGap",
      "unified_score": {
        "complexity_factor": 3.2,
        "coverage_factor": 10.0,
        "dependency_factor": 2.5,
        "role_multiplier": 1.2,
        "final_score": 9.4
      },
      "function_role": "BusinessLogic",
      "recommendation": {
        "action": "Add unit tests",
        "details": "Add 6 unit tests for full coverage",
        "effort_estimate": "2-3 hours"
      },
      "expected_impact": {
        "risk_reduction": 3.9,
        "complexity_reduction": 0,
        "coverage_improvement": 100
      }
    }
  ],
  "overall_coverage": 67.12,
  "total_debt_score": 4907
}

Markdown Report

debtmap analyze . --format markdown --output DEBT_REPORT.md

Great for documentation or PR comments.

Understanding Output Formats

# JSON output (default is legacy format)
debtmap analyze . --format json

# Unified JSON format (alternative to legacy)
debtmap analyze . --format json --output-format unified

# Legacy JSON format (default, for backward compatibility)
debtmap analyze . --format json --output-format legacy

# Output format options: terminal, json, markdown
debtmap analyze . --format terminal

Advanced Usage

Context-Aware Analysis

Enable advanced context providers for more accurate prioritization:

# Enable all context providers
debtmap analyze . \
  --context \
  --context-providers critical_path,dependency,git_history

# Disable specific providers
debtmap analyze . \
  --context \
  --disable-context git_history

Multi-Pass Analysis

# Multi-pass with attribution tracking
debtmap analyze . --multi-pass --attribution

# Shows which functions contribute to which patterns

Cache Management

# Show cache statistics
debtmap cache stats

# Clear cache for current project
debtmap cache clear

# Prune old cache entries
debtmap cache prune --max-age-days 7

Aggregation Methods

# Use logarithmic sum for aggregation
debtmap analyze . --aggregation-method logarithmic_sum

# Standard sum (default)
debtmap analyze . --aggregation-method sum

Filtering and Grouping

# Group results by debt category
debtmap analyze . --group-by-category

# Filter specific categories
debtmap analyze . --filter Architecture,Testing

# Show only high-priority items
debtmap analyze . --min-priority high --top 10

Verbosity Levels

# Level 1: Show main score factors
debtmap analyze . -v

# Level 2: Show detailed calculations
debtmap analyze . -vv

# Level 3: Show all debug information
debtmap analyze . -vvv

# Long form also available
debtmap analyze . --verbose

# Show macro expansion details (Rust)
debtmap analyze . --verbose-macro-warnings --show-macro-stats

Parallel Processing Control

# Use 8 parallel jobs
debtmap analyze . --jobs 8

# Disable parallel processing
debtmap analyze . --no-parallel

Configuration Examples

Basic Configuration

Create .debtmap.toml:

[thresholds]
complexity = 15
duplication = 25
max_function_lines = 50
max_nesting_depth = 4

[languages]
enabled = ["rust", "python"]

[ignore]
patterns = [
  "tests/**/*",
  "**/*.test.rs",
  "target/**",
]

Entropy-Based Complexity

[entropy]
enabled = true
weight = 0.5
use_classification = true
pattern_threshold = 0.7
entropy_threshold = 0.4
branch_threshold = 0.8
max_combined_reduction = 0.3

This reduces false positives for repetitive code patterns.

Custom Scoring Weights

[scoring]
coverage = 0.40      # Test coverage gaps
complexity = 0.40    # Code complexity
dependency = 0.20    # Dependency criticality

God Object Detection Tuning

[god_object]
enabled = true
max_methods = 20
max_fields = 15
max_responsibilities = 5

External API Configuration

For libraries (not CLI tools):

[external_api]
detect_external_api = true

api_functions = [
  "parse",
  "Parser::new",
  "client::connect",
]

api_files = [
  "src/lib.rs",
  "src/api.rs",
  "src/public/*.rs",
]

Complete Multi-Language Configuration

[thresholds]
complexity = 12
duplication = 30
max_file_lines = 400
max_function_lines = 40
minimum_debt_score = 1.0
minimum_cyclomatic_complexity = 2

[entropy]
enabled = true
weight = 0.5

[scoring]
coverage = 0.40
complexity = 0.40
dependency = 0.20

[languages]
enabled = ["rust", "python", "javascript", "typescript"]

[ignore]
patterns = [
  # Tests
  "tests/**/*",
  "**/*.test.*",
  "**/*_test.*",

  # Build artifacts
  "target/**",
  "dist/**",
  "build/**",
  "node_modules/**",

  # Python
  ".venv/**",
  "**/__pycache__/**",

  # Generated code
  "*.generated.*",
  "*.pb.*",
]

[god_object]
enabled = true
max_methods = 18
max_fields = 12

Compare Command

The compare command helps validate that refactoring achieved its goals.

Basic Comparison Workflow

# 1. Generate baseline before refactoring
debtmap analyze . --format json --output before.json

# 2. Make your code improvements
#    ... refactor, add tests, etc ...

# 3. Generate new analysis
debtmap analyze . --format json --output after.json

# 4. Compare and verify improvements
debtmap compare --before before.json --after after.json

Target-Specific Comparison

Focus on whether a specific function improved:

# Target format: file:function:line
debtmap compare \
  --before before.json \
  --after after.json \
  --target-location src/main.rs:process_data:100

Using with Implementation Plans

Extract target automatically from plan files:

# If IMPLEMENTATION_PLAN.md contains:
# **Target**: src/parser.rs:parse_expression:45

debtmap compare \
  --before before.json \
  --after after.json \
  --plan IMPLEMENTATION_PLAN.md

Output Formats

# JSON output (default)
debtmap compare --before before.json --after after.json

# Terminal output (explicit)
debtmap compare \
  --before before.json \
  --after after.json \
  --format terminal

# JSON for CI integration (explicit output file)
debtmap compare \
  --before before.json \
  --after after.json \
  --format json \
  --output comparison.json

# Markdown report
debtmap compare \
  --before before.json \
  --after after.json \
  --format markdown \
  --output COMPARISON.md

Interpreting Results

Target Status:

  • Resolved: Function no longer appears (complexity reduced below threshold)
  • Improved: Metrics improved (complexity down, coverage up)
  • Unchanged: No significant change
  • Regressed: Metrics got worse
  • Not Found: Target not found in baseline

Overall Trend:

  • Improving: More items resolved/improved than regressed
  • Stable: No significant changes
  • Regressing: New critical debt introduced

Example Output:

Target Status: Resolved ✅
- src/parser.rs:parse_expression:45 reduced from complexity 22 to 8
- Coverage improved from 0% to 85%

Overall Trend: Improving
- 3 items resolved
- 2 items improved
- 0 regressions
- Total debt score: 450 → 285 (-37%)

CI Integration

Use in pull request validation:

# In CI script
debtmap compare \
  --before baseline.json \
  --after current.json \
  --format json | jq -e '.overall_trend == "Improving"'

# Exit code 0 if improving, 1 otherwise

Tips and Best Practices

  1. Start Simple: Begin with basic analysis, add coverage later
  2. Use Filters: Focus on one category at a time (Architecture, Testing)
  3. Iterate: Run analysis, fix top items, repeat
  4. CI Integration: Automate validation in your build pipeline
  5. Track Progress: Use compare command to validate improvements
  6. Configure Thresholds: Adjust to match your team’s standards
  7. Leverage Coverage: Always include coverage data for accurate risk assessment

Next Steps

Troubleshooting

Common issues and solutions for using debtmap effectively.

Quick Fixes for Common Issues

If you’re experiencing problems, try these first:

  1. Analysis is slow: Check --cache-stats, ensure caching is enabled, adjust threads with -j
  2. Parse errors: Use --semantic-off for faster fallback mode or exclude problematic files
  3. No output: Increase verbosity with -v or lower --min-priority
  4. Cache corruption: Run with --clear-cache to rebuild
  5. Inconsistent results: Check if coverage file changed or context providers are enabled

Common Issues

Parse Errors

Problem: Encountering “Parse error in file:line:column” messages

Causes:

  • Unsupported language syntax or version
  • Complex macro expansions (Rust)
  • Type inference edge cases (Python, TypeScript)

Solutions:

# Try fallback mode without semantic analysis
debtmap --semantic-off

# For Rust macro issues, see detailed warnings
debtmap --verbose-macro-warnings --show-macro-stats

# Exclude specific problematic files
# Add to .debtmap/config.toml:
# exclude = ["path/to/problematic/file.rs"]

Out of Memory Errors

Problem: Analysis crashes or runs out of memory on large codebases

Solutions:

# Limit parallel processing
debtmap --jobs 2

# Disable parallel processing entirely
debtmap --no-parallel

# Test with limited files first
debtmap --max-files 100

# Analyze subdirectories separately
debtmap path/to/subset

Performance Issues

Problem: Analysis takes too long to complete

Solutions:

# Check cache statistics
debtmap --cache-stats

# Ensure caching is enabled (it is by default)
# If cache was disabled, remove --no-cache flag

# Use all available CPU cores
debtmap --jobs 0

# Try faster fallback mode (less accurate)
debtmap --semantic-off

# Use plain output for faster terminal rendering
debtmap --plain

See Performance Tips for detailed optimization strategies.

Cache Corruption

Problem: Getting “Cache error” messages or stale results

Solutions:

# Clear cache and rebuild
debtmap --clear-cache

# Force cache rebuild
debtmap --force-cache-rebuild

# Check cache status
debtmap --cache-stats

# Use different cache location
debtmap --cache-location /path/to/cache

See Cache Troubleshooting for more details.

File Permission Errors

Problem: “File system error” when accessing files

Solutions:

  • Ensure you have read permissions for all source files
  • Check that the project directory is accessible
  • Verify cache directory is writable (default: .debtmap/cache)
  • Use --cache-location to specify an accessible cache directory

Git History Errors

Problem: Errors when using git_history context provider

Causes:

  • Not running in a git repository
  • Git history not available for files
  • Insufficient git permissions

Solutions:

# Disable git_history context provider
debtmap --context --disable-context git_history

# Disable all context providers
debtmap --no-context-aware

# Check if in git repository
git status

Coverage File Issues

Problem: Coverage file not being processed or causing errors

Causes:

  • Non-LCOV format coverage file
  • Malformed coverage data
  • Path mismatches between coverage and source files

Solutions:

# Verify coverage file format (must be LCOV)
head coverage.info

# Check coverage file path
debtmap --coverage-file path/to/coverage.info -v

# Ensure paths in coverage file match source paths
# Coverage paths are relative to project root

Threshold and Preset Confusion

Problem: Unexpected filtering or priority levels

Solutions:

# Check what threshold preset does
debtmap --threshold-preset strict --help

# Override specific thresholds
debtmap --min-priority 3

# See all items regardless of thresholds
debtmap --min-priority 0

# Use category filters instead
debtmap --filter "complexity,debt"

JSON Format Issues

Problem: JSON output parsing errors or unexpected structure

Solutions:

# Use unified JSON format (consistent structure)
debtmap --format json --output-format unified

# Legacy format (default, uses {File: {...}} structure)
debtmap --format json --output-format legacy

# Validate JSON output
debtmap --format json | jq .

# Write to file for easier inspection
debtmap --format json --output results.json

Context Provider Errors

Problem: Errors with critical_path, dependency, or git_history providers

Solutions:

# Enable specific providers only
debtmap --context --context-providers critical_path,dependency

# Disable problematic provider
debtmap --context --disable-context git_history

# Disable context-aware filtering
debtmap --no-context-aware

# Check context provider details
debtmap --context -vvv

See Context Provider Troubleshooting for details.

Debug Mode

Use verbosity flags to diagnose issues and understand analysis behavior.

Verbosity Levels

# Level 1: Show main score factors
debtmap -v

# Level 2: Show detailed calculations
debtmap -vv

# Level 3: Show all debug information
debtmap -vvv

What each level shows:

  • -v: Score breakdowns, main contributing factors
  • -vv: Detailed metric calculations, file processing
  • -vvv: Full debug output, context provider details, cache operations

Diagnostic Options

# Show macro parsing warnings (Rust)
debtmap --verbose-macro-warnings

# Show macro expansion statistics (Rust)
debtmap --show-macro-stats

# Disable semantic analysis (fallback mode)
debtmap --semantic-off

# Validate LOC consistency
debtmap --validate-loc

# Show cache statistics
debtmap --cache-stats

Debugging Score Calculations

# Use verbosity levels to see score breakdown
debtmap -v    # Shows score factors

# See how coverage affects scores
debtmap --coverage-file coverage.info -v

# See how context affects scores
debtmap --context --context-providers critical_path -v

Example Debug Session

# Step 1: Run with verbosity to see what's happening
debtmap -vv

# Step 2: Check cache stats
debtmap --cache-stats

# Step 3: Try without semantic analysis
debtmap --semantic-off -v

# Step 4: Check specific file
debtmap path/to/file.rs -vvv

# Step 5: Validate results
debtmap --validate-loc

Performance Tips

Optimize debtmap analysis speed and resource usage.

Parallel Processing

# Use all CPU cores (default)
debtmap --jobs 0

# Limit to 4 threads
debtmap --jobs 4

# Disable parallel processing (debugging)
# Note: --no-parallel is equivalent to --jobs 1 (single-threaded)
debtmap --no-parallel

When to adjust parallelism:

  • Use --jobs 0 (default): Maximum performance on dedicated machine
  • Use --jobs N: Limit resource usage while other tasks run
  • Use --no-parallel: Debugging concurrency issues

Caching Strategies

Caching is enabled by default and provides the biggest performance improvement.

Note: The --cache flag (to enable caching) is deprecated and hidden. Caching is now always enabled by default; use --no-cache to disable it.

# Check cache effectiveness
debtmap --cache-stats

# Clear cache if corrupted
debtmap --clear-cache

# Force cache rebuild
debtmap --force-cache-rebuild

# Disable cache (not recommended)
debtmap --no-cache

Cache locations:

# Local cache (default): .debtmap/cache
debtmap

# Shared cache for multiple projects
debtmap --cache-location ~/.cache/debtmap

# Migrate existing cache to shared location
debtmap --migrate-cache

# Set via environment variable
export DEBTMAP_CACHE_DIR=~/.cache/debtmap
debtmap

Cache best practices:

  1. Use shared cache for multiple similar projects
  2. Monitor cache size with --cache-stats periodically
  3. Clear cache after major refactorings
  4. Use local cache for project-specific configurations

Analysis Optimizations

# Fast mode: disable semantic analysis
debtmap --semantic-off

# Plain output: faster terminal rendering
debtmap --plain

# Limit files for testing
debtmap --max-files 100

# Analyze subdirectory only
debtmap src/specific/module

# Reduce output with filters
debtmap --min-priority 4 --top 20

Performance Comparison

ConfigurationSpeedAccuracy
Default (cached)FastHigh
--no-cacheSlowHigh
--semantic-offFastestMedium
--no-parallelSlowestHigh
--jobs 4MediumHigh

Monitoring Performance

# Time analysis
time debtmap

# Check cache hit rate
debtmap --cache-stats

# Profile with verbosity
debtmap -vv 2>&1 | grep "processed in"

Cache Troubleshooting

Detailed guidance for cache-related issues.

Check Cache Status

# View cache statistics
debtmap --cache-stats

# Sample output:
# Cache location: .debtmap/cache
# Cache entries: 1,234
# Cache size: 45.2 MB
# Hit rate: 87.3%

Clear Corrupted Cache

# Clear all cache entries
debtmap --clear-cache

# Force rebuild on next run
debtmap --force-cache-rebuild

# Manual cache deletion
rm -rf .debtmap/cache
# or for shared cache:
rm -rf ~/.cache/debtmap

Cache Location Management

# Use local cache (default)
debtmap
# Cache at: .debtmap/cache

# Use shared cache
debtmap --cache-location ~/.cache/debtmap

# Set permanently via environment
export DEBTMAP_CACHE_DIR=~/.cache/debtmap
debtmap

# Migrate existing cache
debtmap --migrate-cache

Cache Strategies

Local cache (.debtmap/cache):

  • Pros: Isolated per project, automatically managed
  • Cons: Duplicates across projects

Shared cache (~/.cache/debtmap):

  • Pros: Shared across projects, saves disk space
  • Cons: Requires manual management, may mix unrelated projects

Cache Consistency

# Validate LOC consistency
debtmap --validate-loc

# Cache automatically invalidates on file changes
# Uses file hashes to detect modifications

# Force fresh analysis
debtmap --no-cache

Cache Size Monitoring

# Check cache size
debtmap --cache-stats

# Clean up old entries (manual)
# No automatic cleanup - manage cache size manually
# Consider clearing cache periodically for large projects

Context Provider Troubleshooting

Diagnose and fix issues with context providers (critical_path, dependency, git_history).

Enable Context Analysis

# Enable with default providers
debtmap --context

# Or use explicit flag
debtmap --enable-context

# Specify specific providers
debtmap --context --context-providers critical_path,dependency,git_history

Disable Specific Providers

# Disable git_history only
debtmap --context --disable-context git_history

# Disable multiple providers
debtmap --context --disable-context git_history,dependency

# Disable context-aware filtering
debtmap --no-context-aware

Git History Provider Issues

Problem: “Git history error” when running analysis

Causes:

  • Not in a git repository
  • No git history for files
  • Git not installed or accessible

Solutions:

# Verify in git repository
git status

# Disable git_history provider
debtmap --context --disable-context git_history

# Initialize git repo if needed
git init

Dependency Provider Issues

Problem: “Dependency error” or incomplete dependency graph

Causes:

  • Complex import structures
  • Circular dependencies
  • Unsupported dependency patterns

Solutions:

# Disable dependency provider
debtmap --context --disable-context dependency

# Try with verbosity to see details
debtmap --context -vvv

# Use without context
debtmap

Critical Path Provider Issues

Problem: Critical path analysis fails or produces unexpected results

Causes:

  • Invalid call graph
  • Missing function definitions
  • Complex control flow

Solutions:

# Disable critical_path provider
debtmap --context --disable-context critical_path

# Try with semantic analysis disabled
debtmap --context --semantic-off

# Debug with verbosity
debtmap --context --context-providers critical_path -vvv

Context Impact on Scoring

Context providers add additional risk factors to scoring:

# See context contribution to scores
debtmap --context -v

# Compare with and without context
debtmap --output baseline.json
debtmap --context --output with_context.json
debtmap compare --before baseline.json --after with_context.json

Performance Impact

Context analysis adds processing overhead:

# Faster: no context
debtmap

# Slower: with all context providers
debtmap --context --context-providers critical_path,dependency,git_history

# Medium: selective providers
debtmap --context --context-providers dependency

Debug Context Providers

# See detailed context provider output
debtmap --context -vvv

# Check which providers are active
debtmap --context -v | grep "context provider"

Advanced Analysis Troubleshooting

Advanced CLI flags for specialized analysis scenarios.

Multi-Pass Analysis

Flag: --multi-pass

Multi-pass analysis performs multiple iterations to refine results.

# Enable multi-pass analysis
debtmap --multi-pass

# Useful for complex projects with intricate dependencies
# May increase analysis time but improve accuracy

When to use:

  • Complex dependency graphs
  • Large codebases with deep nesting
  • When single-pass results seem incomplete

Attribution Output

Flag: --attribution

Shows attribution information for detected issues.

# Enable attribution output
debtmap --attribution

# Combine with verbosity for details
debtmap --attribution -v

Troubleshooting:

  • Requires git history provider for author information
  • May slow down analysis
  • Use --disable-context git_history if causing errors

Aggregation Methods

Flag: --aggregation-method <method>

Controls how results are aggregated across files.

# Available aggregation methods:
debtmap --aggregation-method weighted_sum  # (default)
debtmap --aggregation-method sum
debtmap --aggregation-method logarithmic_sum
debtmap --aggregation-method max_plus_average

Common issues:

  • Different methods produce different result structures
  • Choose method based on your reporting needs
  • Use consistent method for comparison over time

Minimum Problematic Threshold

Flag: --min-problematic <number>

Sets the minimum score for an item to be considered problematic.

# Default threshold
debtmap --min-problematic 3

# More strict (show more issues)
debtmap --min-problematic 1

# Less strict (show only serious issues)
debtmap --min-problematic 5

Relationship to other filters:

  • Works alongside --min-priority
  • Filters at analysis level vs display level
  • Lower values = more issues shown

God Object Detection

Flag: --no-god-object

Disables god object (large class/module) detection.

# Disable god object detection
debtmap --no-god-object

# Useful if false positives on legitimately large modules
# Or if your architecture uses centralized classes

When to use:

  • False positives on framework files
  • Intentional large aggregator classes
  • Reducing noise in results

Detail Level Control

Flag: --detail-level <level>

Controls the level of detail in analysis output.

# Available detail levels:
debtmap --detail-level summary        # High-level overview only
debtmap --detail-level standard       # (default) Balanced detail
debtmap --detail-level comprehensive  # Detailed analysis
debtmap --detail-level debug         # Full debug information

When to use:

  • summary: Quick overview for large codebases
  • standard: Default, appropriate for most use cases
  • comprehensive: Deep dive into specific issues
  • debug: Troubleshooting analysis behavior

Aggregation Control

Flags: --aggregate-only, --no-aggregation

Control file-level score aggregation.

# Show only aggregated file-level scores
debtmap --aggregate-only

# Disable file-level aggregation entirely
debtmap --no-aggregation

# Default: show both individual items and file aggregates
debtmap

Use cases:

  • --aggregate-only: Focus on file-level technical debt
  • --no-aggregation: See individual functions/classes only
  • Default: Full picture with both levels

Combining Advanced Flags

# Comprehensive analysis with all features
debtmap --multi-pass --attribution --context -vv

# Minimal filtering for exploration
debtmap --min-problematic 1 --min-priority 0 --no-god-object

# Performance-focused advanced analysis
debtmap --multi-pass --jobs 8 --cache-location ~/.cache/debtmap

# Summary view with aggregated scores
debtmap --detail-level summary --aggregate-only

Error Messages Reference

Understanding common error messages and how to resolve them.

File System Errors

Message: File system error: Permission denied

Meaning: Cannot read file or directory due to permissions

Solutions:

  • Check file permissions: ls -la <file>
  • Ensure user has read access
  • Verify cache directory is writable
  • Use --cache-location for accessible directory

Message: File system error: No such file or directory

Meaning: File or directory does not exist

Solutions:

  • Verify path is correct
  • Check current working directory: pwd
  • Use absolute paths if needed
  • Ensure files weren’t moved or deleted

Parse Errors

Message: Parse error in file.rs:line:column: unexpected token

Meaning: Syntax debtmap cannot parse

Solutions:

# Try fallback mode
debtmap --semantic-off

# For Rust macros
debtmap --verbose-macro-warnings --show-macro-stats

# Exclude problematic file
# In .debtmap/config.toml:
# exclude = ["path/to/file.rs"]

Analysis Errors

Message: Analysis error: internal analysis failure

Meaning: Internal error during analysis phase

Solutions:

# Try fallback mode
debtmap --semantic-off

# Report with debug info
debtmap -vvv 2>&1 | tee error.log

# Isolate problem file
debtmap --max-files 1 path/to/suspected/file

Configuration Errors

Message: Configuration error: invalid config value

Meaning: Invalid configuration in .debtmap/config.toml or CLI

Solutions:

  • Check .debtmap/config.toml syntax
  • Validate TOML format: cat .debtmap/config.toml
  • Review CLI flag values
  • Check for typos in flag names

Cache Errors

Message: Cache error: corrupted cache entry

Meaning: Cache data is invalid or corrupted

Solutions:

# Clear cache
debtmap --clear-cache

# Force rebuild
debtmap --force-cache-rebuild

# Use different cache location
debtmap --cache-location /tmp/debtmap-cache

Validation Errors

Message: Validation error: threshold validation failed

Meaning: Threshold configuration is invalid

Solutions:

  • Check threshold values in config
  • Ensure --min-priority is in valid range (0-10)
  • Verify threshold preset exists
  • Use --threshold-preset with valid preset name

Dependency Errors

Message: Dependency error: cannot resolve dependency graph

Meaning: Cannot build dependency relationships

Solutions:

# Disable dependency provider
debtmap --context --disable-context dependency

# Try without context
debtmap

# Debug with verbosity
debtmap -vvv

Concurrency Errors

Message: Concurrency error: parallel processing failure

Meaning: Error during parallel execution

Solutions:

# Disable parallel processing
debtmap --no-parallel

# Reduce thread count
debtmap --jobs 1

# Report issue with debug output
debtmap -vvv 2>&1 | tee error.log

Unsupported Errors

Message: Unsupported: feature not available for <language>

Meaning: Language or construct not supported

Solutions:

  • Use supported languages: Rust, Python, JavaScript, TypeScript
  • Check if language is enabled in config
  • Some advanced features may not be available for all languages
  • Try --semantic-off for basic analysis

Pattern Errors

Message: Pattern error: invalid glob pattern

Meaning: Invalid glob pattern in configuration or CLI

Solutions:

  • Check glob pattern syntax
  • Escape special characters if needed
  • Test pattern with shell glob: ls <pattern>
  • Use simpler patterns or path prefixes

Language-Specific Issues

Rust

Macro Expansion Issues

# See macro warnings
debtmap --verbose-macro-warnings

# Show macro statistics
debtmap --show-macro-stats

# Common issue: Complex macros may not expand correctly
# Solution: Use --semantic-off for faster fallback

Trait and Generic Complexity

Complex trait bounds and generic constraints may affect analysis accuracy:

# Full semantic analysis (default)
debtmap

# Fallback mode for edge cases
debtmap --semantic-off

Python

Type Inference Limitations

Dynamic typing makes some analysis challenging:

# Best effort type inference (default)
debtmap

# Fallback mode if issues
debtmap --semantic-off

Import Resolution

Complex import structures may not resolve fully:

  • Relative imports usually work
  • Dynamic imports may not be detected
  • __init__.py packages are supported

JavaScript/TypeScript

JSX/TSX Parsing

Ensure files have correct extensions:

  • .jsx for JavaScript + JSX
  • .tsx for TypeScript + JSX
  • Configure extensions in .debtmap/config.toml if needed

Type Resolution

TypeScript type resolution in complex projects:

# Full type checking (default for .ts files)
debtmap

# Fallback if type issues
debtmap --semantic-off

Mixed Language Projects

# Analyze all supported languages (default)
debtmap

# Filter specific languages
# In .debtmap/config.toml:
# languages = ["rust", "python"]

Unsupported Language Constructs

Some advanced language features may show as “Unsupported”:

  • Rust: Some macro patterns, const generics edge cases
  • Python: Some metaclass patterns, dynamic code generation
  • JavaScript: Some advanced AST manipulation

Solutions:

  • Use --semantic-off for basic analysis
  • Exclude problematic files if needed
  • Report unsupported patterns as feature requests

False Positives

# Reduce false positives with context
debtmap --context

# Adjust thresholds
debtmap --threshold-preset lenient

# Disable context-aware filtering if too aggressive
debtmap --no-context-aware

Missing Detections

# Ensure semantic analysis is enabled
debtmap  # (default, semantic ON)

# Increase verbosity to see what's detected
debtmap -vv

# Check if files are being analyzed
debtmap -v 2>&1 | grep "Processing"

Output Formatting Issues

Choose Output Format

# Terminal format (default, human-readable)
debtmap

# JSON format
debtmap --format json

# Markdown format
debtmap --format markdown

JSON Format Options

# Legacy format (default): {File: {...}}
debtmap --format json --output-format legacy

# Unified format: consistent structure with 'type' field
debtmap --format json --output-format unified

# Validate JSON
debtmap --format json | jq .

# Write to file
debtmap --format json --output results.json

Plain Output Mode

For environments without color/emoji support:

# ASCII-only, no colors, no emoji
debtmap --plain

# Or set environment variable
export NO_EMOJI=1
debtmap

Terminal Color Issues

Problem: Colors not rendering or showing escape codes

Solutions:

# Use plain mode
debtmap --plain

# Check TERM environment variable
echo $TERM

# Set appropriate TERM
export TERM=xterm-256color

Emoji Issues

Problem: Emojis showing as boxes or ??

Solutions:

# Disable emojis
debtmap --plain

# Or environment variable
export NO_EMOJI=1
debtmap

Markdown Rendering

Ensure viewer supports GitHub-flavored markdown:

  • Tables
  • Code blocks with syntax highlighting
  • Task lists

Write Output to File

# JSON to file
debtmap --format json --output results.json

# Markdown to file
debtmap --format markdown --output report.md

# Terminal format to file (preserves colors)
debtmap --output results.txt

# Plain format to file
debtmap --plain --output results.txt

Summary vs Full Output

# Summary mode (compact)
debtmap --summary
debtmap -s

# Full output (default)
debtmap

# Limit number of items
debtmap --top 10       # Top 10 by priority
debtmap --tail 10      # Bottom 10 by priority

Filtering Output

# Minimum priority level
debtmap --min-priority 5

# Category filters
debtmap --filter "complexity,debt"

# Combine filters
debtmap --min-priority 3 --top 20 --filter complexity

Compare Command Issues

The compare command helps track changes in technical debt over time.

Basic Usage

Note: The compare command defaults to JSON output format (unlike analyze which defaults to terminal). Use --format terminal or --format markdown if you need different output.

# Save baseline results
debtmap --format json --output before.json

# Make code changes...

# Save new results
debtmap --format json --output after.json

# Compare results (outputs JSON by default)
debtmap compare --before before.json --after after.json

# Compare with terminal output
debtmap compare --before before.json --after after.json --format terminal

Targeted Comparison

Use --plan and --target-location for focused debt analysis:

# Compare based on implementation plan
debtmap compare --before before.json --after after.json --plan implementation-plan.json

# Compare specific code location
debtmap compare --before before.json --after after.json \
  --target-location src/main.rs:calculate_score:42

# Combine both for precise tracking
debtmap compare --before before.json --after after.json \
  --plan implementation-plan.json \
  --target-location src/analyzers/complexity.rs:analyze_function:128

Use cases:

  • --plan: Track debt changes for planned refactoring tasks
  • --target-location: Focus on specific function or code location
  • Combine for granular technical debt tracking

Incompatible Format Errors

Problem: “Incompatible formats” error when comparing files

Causes:

  • Mixing legacy and unified JSON formats
  • Files from different debtmap versions
  • Corrupted JSON files

Solutions:

# Ensure both files use same output format
debtmap --format json --output-format unified --output before.json
# ... make changes ...
debtmap --format json --output-format unified --output after.json
debtmap compare --before before.json --after after.json

# Validate JSON files are well-formed
jq . before.json > /dev/null
jq . after.json > /dev/null

Comparing Across Branches

# Save baseline on main branch
git checkout main
debtmap --format json --output main.json

# Switch to feature branch
git checkout feature-branch
debtmap --format json --output feature.json

# Compare branches
debtmap compare --before main.json --after feature.json

Missing Files Error

Problem: “File not found” when running compare

Solutions:

  • Verify file paths are correct (use absolute paths if needed)
  • Ensure JSON files weren’t moved or deleted
  • Check current working directory with pwd

Format Mismatch Issues

Problem: Compare shows unexpected differences or errors

Solutions:

# Regenerate both files with same debtmap version
debtmap --format json --output before.json
# ... make changes ...
debtmap --format json --output after.json

# Use same output format for both
debtmap --format json --output-format unified --output before.json
debtmap --format json --output-format unified --output after.json

Validate Command Issues

The validate command checks if a codebase meets specified quality thresholds, useful for CI/CD pipelines.

Basic Validation

# Validate codebase passes default thresholds
debtmap validate /path/to/project

# Exit code 0 if passes, non-zero if validation fails

Debt Density Validation

Flag: --max-debt-density <number>

Sets the maximum acceptable technical debt per 1000 lines of code.

# Set maximum acceptable debt density (per 1000 LOC)
debtmap validate /path/to/project --max-debt-density 10.0

# Stricter threshold for critical projects
debtmap validate /path/to/project --max-debt-density 5.0

# Lenient threshold for legacy code
debtmap validate /path/to/project --max-debt-density 20.0

Troubleshooting validation failures:

# See which files exceed threshold
debtmap validate /path/to/project --max-debt-density 10.0 -v

# Get detailed breakdown
debtmap validate /path/to/project --max-debt-density 10.0 -vv

# Analyze specific files that failed
debtmap /path/to/problematic/file.rs -v

CI/CD Integration

# In CI pipeline (fails build if validation fails)
debtmap validate . --max-debt-density 10.0 || exit 1

# With verbose output for debugging
debtmap validate . --max-debt-density 10.0 -v

# Save validation report
debtmap validate . --max-debt-density 10.0 --format json --output validation.json

Use cases:

  • Enforce quality gates in CI/CD pipelines
  • Prevent accumulation of technical debt over time
  • Track debt density trends across releases
  • Set different thresholds for different parts of codebase

FAQ

General Questions

Q: Why is my analysis slow?

A: Check several factors:

# Check cache status
debtmap --cache-stats

# Ensure caching is enabled (default)
# Remove --no-cache if present

# Use all CPU cores
debtmap --jobs 0

# Check for large files or complex macros
debtmap -vv

Q: What does ‘Parse error’ mean?

A: File contains syntax debtmap cannot parse. Solutions:

  • Try --semantic-off for fallback mode
  • Use --verbose-macro-warnings for Rust macros
  • Exclude problematic files in .debtmap/config.toml
  • Report parse errors as potential bugs

Q: Why do scores differ between runs?

A: Several factors affect scores:

  • Coverage file changed (use --coverage-file)
  • Context providers enabled/disabled (--context)
  • Cache was cleared (--clear-cache)
  • Code changes (intended behavior)
  • Different threshold settings

Q: How do I reduce noise in results?

A: Use filtering options:

# Increase minimum priority
debtmap --min-priority 5

# Use threshold preset
debtmap --threshold-preset strict

# Filter categories
debtmap --filter "complexity,debt"

# Limit output
debtmap --top 20

Format and Output

Q: What’s the difference between legacy and unified JSON?

A: Two JSON output formats:

  • Legacy: {File: {...}} - nested file-based structure
  • Unified: Consistent structure with type field for each item
# Legacy (default)
debtmap --format json --output-format legacy

# Unified (recommended for parsing)
debtmap --format json --output-format unified

Q: Can I analyze partial codebases?

A: Yes, several approaches:

# Limit file count
debtmap --max-files 100

# Analyze specific directory
debtmap src/specific/module

# Use filters in config
# .debtmap/config.toml:
# include = ["src/**/*.rs"]

Coverage and Testing

Q: How does coverage affect scores?

A: Coverage dampens scores to surface untested code:

  • Formula: score_multiplier = 1.0 - coverage
  • 0% coverage → full score (highest priority)
  • 100% coverage → score multiplied by 0 (lowest priority)
  • Untested complex code rises to the top
# Use coverage file
debtmap --coverage-file coverage.info

# See coverage impact
debtmap --coverage-file coverage.info -v

Context and Analysis

Q: What are context providers?

A: Additional analysis for prioritization:

  • critical_path: Call graph analysis, entry point distance
  • dependency: Dependency relationships and coupling
  • git_history: Change frequency and authorship
# Enable all
debtmap --context

# Specific providers
debtmap --context --context-providers critical_path,dependency

# See context impact
debtmap --context -v

Results and Comparison

Q: Why no output?

A: Check verbosity and filtering:

# Increase verbosity
debtmap -v

# Lower priority threshold
debtmap --min-priority 0

# Check if files were analyzed
debtmap -vv 2>&1 | grep "Processed"

# Ensure not using strict threshold
debtmap --threshold-preset lenient

Q: How to compare results over time?

A: Use the compare command:

# Save baseline
debtmap --format json --output before.json

# Make changes...

# Analyze again
debtmap --format json --output after.json

# Compare
debtmap compare --before before.json --after after.json

Q: Why does compare fail with ‘incompatible formats’?

A: The JSON files must use the same output format:

# Use unified format for both
debtmap --format json --output-format unified --output before.json
# ... make changes ...
debtmap --format json --output-format unified --output after.json
debtmap compare --before before.json --after after.json

# Or use legacy format for both (but unified is recommended)
debtmap --format json --output-format legacy --output before.json
debtmap --format json --output-format legacy --output after.json

Q: How do I compare results from different branches?

A: Generate JSON output on each branch and compare:

# On main branch
git checkout main
debtmap --format json --output main.json

# On feature branch
git checkout feature-branch
debtmap --format json --output feature.json

# Compare (from either branch)
debtmap compare --before main.json --after feature.json

Q: Can I compare legacy and unified JSON formats?

A: No, both files must use the same format. Regenerate with matching formats:

# Convert both to unified format
debtmap --format json --output-format unified --output before.json
debtmap --format json --output-format unified --output after.json
debtmap compare --before before.json --after after.json

Performance and Optimization

Q: How many threads should I use?

A: Depends on your machine:

# Use all cores (default, recommended)
debtmap --jobs 0

# Limit to 4 threads (if other work running)
debtmap --jobs 4

# Single threaded (debugging only)
debtmap --no-parallel

Q: Should I use shared or local cache?

A: Depends on your workflow:

  • Local cache (.debtmap/cache): Isolated, automatic
  • Shared cache (~/.cache/debtmap): Saves space across projects
# Shared cache
debtmap --cache-location ~/.cache/debtmap

# Set permanently
export DEBTMAP_CACHE_DIR=~/.cache/debtmap

When to File Bug Reports

File a bug report when:

These are bugs:

  • Parse errors on valid syntax
  • Crashes or panics
  • Incorrect complexity calculations
  • Cache corruption
  • Concurrency errors
  • Incorrect error messages

These are not bugs:

  • Unsupported language constructs (file feature request)
  • Disagreement with complexity scores (subjective)
  • Performance on very large codebases (optimization request)
  • Missing documentation (docs issue, not code bug)

How to Report Issues

  1. Reproduce with minimal example
  2. Include debug output: debtmap -vvv 2>&1 | tee error.log
  3. Include version: debtmap --version
  4. Include platform: OS, Rust version if relevant
  5. Include configuration: .debtmap/config.toml if used
  6. Expected vs actual behavior

Before Filing

  1. Check this troubleshooting guide
  2. Try --semantic-off fallback mode
  3. Clear cache with --clear-cache
  4. Update to latest version
  5. Search existing issues on GitHub

Troubleshooting Checklist

When debugging issues, work through this checklist:

  • Run with -vv to see detailed output
  • Check --cache-stats for cache issues
  • Try --clear-cache to rule out cache corruption
  • Try --semantic-off to use fallback mode
  • Check file permissions and paths
  • Verify configuration in .debtmap/config.toml
  • Test with --max-files 10 to isolate issues
  • Try --no-parallel to rule out concurrency
  • Check debtmap --version for updates
  • Review error messages in this guide
  • Search GitHub issues for similar problems
  • Create minimal reproduction case
  • File bug report with debug output