<!-- Generated by codeindex at 2026-02-12T22:59:54+08:00 -->

# README_AI.md - codeindex

## Overview

- **Files**: 42
- **Symbols**: 320+
- **Subdirectories**: 2

## Subdirectories

- **extractors/** - Framework-specific route extractors.
- **parsers/** - Java language parser module.

## Files

- __init__.py
- **adaptive_config.py** - AdaptiveSymbolsConfig
- **adaptive_selector.py** - AdaptiveSymbolSelector
- **ai_helper.py** - aggregate_parse_results
- **cli.py** - main
- cli_common.py
- **cli_config.py** - init (with interactive wizard), status, list_dirs, _print_post_init_message
- **cli_config_commands.py** - config command group, explain command
- **cli_docs.py** - docs, show_ai_guide
- **cli_hooks.py** - HookStatus, HookManager, generate_hook_script
- **cli_parse.py** - parse
- **cli_scan.py** - _process_directory_with_smartwriter, scan, scan_all
- **cli_symbols.py** - extract_module_purpose, index, symbols
- **cli_tech_debt.py** - _find_source_files, _analyze_files, _format_and_output
- **config.py** - SymbolsConfig, GroupingConfig, SemanticConfig
- **config_help.py** - CONFIG_PARAMS, show_full_config_help, explain_parameter, get_current_config_value
- **directory_tree.py** - DirectoryNode, DirectoryTree, walk_directory
- **docstring_processor.py** - DocstringProcessor
- **errors.py** - ErrorCode, ErrorInfo, create_error_response
- __init__.py
- **spring.py** - SpringRouteExtractor
- **thinkphp.py** - ThinkPHPRouteExtractor
- **file_classifier.py** - FileSizeCategory, FileSizeAnalysis, FileSizeClassifier
- **framework_detect.py** - RouteInfo, ModelInfo, FrameworkInfo
- **hierarchical.py** - DirectoryInfo, build_directory_hierarchy, create_processing_batches
- **incremental.py** - UpdateLevel, FileChange, ChangeAnalysis
- **init_wizard.py** - WizardResult, PARSER_PACKAGES, CLAUDE_MD_MARKER_START, CLAUDE_MD_MARKER_END, CLAUDE_MD_SECTION, check_parser_installed, get_parser_install_guidance, detect_languages, detect_frameworks, infer_include_patterns, infer_exclude_patterns, calculate_parallel_workers, calculate_batch_size, count_files, inject_claude_md, has_claude_md_injection, run_interactive_wizard, generate_config_yaml, create_codeindex_md
- **invoker.py** - InvokeResult, clean_ai_output, validate_markdown_output
- **parallel.py** - BatchResult, parse_files_parallel, scan_directories_parallel
- **parser.py** - CallType, Call, Symbol, Import, Inheritance, ParseResult, JAVA_LANG_CLASSES, build_alias_map, resolve_alias, _extract_python_calls_from_tree, _extract_decorator_calls, _extract_python_calls, _parse_python_call, _determine_python_call_type, _extract_call_name, _is_simple_decorator, _extract_decorator_name, _count_arguments, _extract_package_namespace, _strip_generic_type, _resolve_java_type, _build_java_import_map, _extract_java_inheritances, _extract_type_from_node, _get_parser, _get_node_text, parse_file, _build_java_static_import_map, _resolve_java_static_import, _parse_java_method_call, _parse_java_constructor_call, _extract_java_calls, _extract_java_calls_from_tree, _extract_php_calls_from_tree, _extract_php_calls, _parse_php_function_call, _parse_php_member_call, _parse_php_scoped_call, _parse_php_object_creation
- __init__.py
- **java_parser.py** - is_java_file, get_java_parser, parse_java_file
- **route_extractor.py** - ExtractionContext, RouteExtractor
- **route_registry.py** - RouteExtractorRegistry
- **scanner.py** - ScanResult, get_language_extensions, is_pass_through, should_exclude
- **semantic_extractor.py** - DirectoryContext, BusinessSemantic, SimpleDescriptionGenerator
- **smart_writer.py** - WriteResult, SmartWriter, determine_level
- **symbol_index.py** - SymbolEntry, GlobalSymbolIndex
- **symbol_scorer.py** - ScoringContext, SymbolImportanceScorer
- **tech_debt.py** - DebtSeverity, DebtIssue, DebtAnalysisResult
- **tech_debt_formatters.py** - ReportFormatter, ConsoleFormatter, MarkdownFormatter
- **writer.py** - WriteResult, format_symbols_for_prompt, format_imports_for_prompt

---

## Key Components

### Version Management

**File**: `__init__.py`

**Purpose**: Package initialization with dynamic version resolution

**Version Strategy**:
- Uses `importlib.metadata.version("ai-codeindex")` to read version from installed package metadata (sourced from `pyproject.toml`)
- Falls back to `"0.0.0-dev"` if package metadata is unavailable (e.g., during development without install)
- **No hardcoded version** — `pyproject.toml` is the single source of truth

### Interactive Setup Wizard

**File**: `init_wizard.py`

**Purpose**: Intelligent, interactive setup wizard for `codeindex init` command (Epic 15 Story 15.1)

**Core Features**:
- Auto-detects project languages (Python, PHP, Java - fully supported with parsers)
- Infers include/exclude patterns from project structure
- Auto-tunes performance settings (parallel_workers, batch_size)
- Configures AI CLI integration and Git Hooks
- Generates CODEINDEX.md guide for AI agents (includes auto-update hooks section)
- **CLAUDE.md injection**: Injects codeindex instructions into project's CLAUDE.md (idempotent, marker-based)
- Supports both interactive and non-interactive (`--yes`) modes
- **Parser detection**: Checks if tree-sitter parsers are installed for detected languages and provides install guidance

**Language Support**:
- **Fully supported (with parser)**: Python, PHP, Java
- **Planned support**: JavaScript, TypeScript, Go, Rust, Ruby (detection only, parser implementation pending)

**Parser Detection (Epic 19)**:
- `PARSER_PACKAGES` - Maps language names to tree-sitter package names (e.g., `"python"` → `"tree_sitter_python"`)
- `check_parser_installed(language)` - Checks if a language's tree-sitter parser package is importable
- `get_parser_install_guidance(languages)` - Returns dict with `installed`, `missing` lists and `install_command` (e.g., `pip install ai-codeindex[java,php]`)
- Used by `cli_config.py` non-interactive mode to warn about missing parsers during `codeindex init --yes`

**CLAUDE.md Injection**:
- `CLAUDE_MD_MARKER_START` / `CLAUDE_MD_MARKER_END` - HTML comment markers (`<!-- codeindex:start -->` / `<!-- codeindex:end -->`) for idempotent section management
- `CLAUDE_MD_SECTION` - Template content injected between markers, containing codeindex usage instructions for AI agents
- `inject_claude_md(project_dir)` - Creates or updates CLAUDE.md with codeindex instructions:
  - Creates CLAUDE.md if it doesn't exist (section only)
  - Prepends section if no existing injection found
  - Replaces between markers if already injected (idempotent update via regex)
- `has_claude_md_injection(project_dir)` - Checks if CLAUDE.md already contains the codeindex marker
- `WizardResult.inject_claude_md` - Boolean field (default `True`) controlling whether CLAUDE.md injection is performed
- `WizardResult.claude_md_injected` - Boolean field tracking whether injection was actually performed

**CODEINDEX.md Auto-Update Hooks Section**:
- `create_codeindex_md()` now includes an "Auto-Update Hooks" section in the generated guide
- Documents `codeindex hooks install post-commit` and `codeindex hooks status` commands
- Shows `.codeindex.yaml` hooks configuration example with `mode: auto | sync | async | prompt | disabled`

**Key Functions**:
- `detect_languages()` - Scans file extensions to identify programming languages
- `detect_frameworks()` - Identifies web frameworks (Spring, ThinkPHP, Laravel, etc.)
- `infer_include_patterns()` - Suggests source directories to scan
- `infer_exclude_patterns()` - Suggests directories to exclude (node_modules, __pycache__, etc.)
- `calculate_parallel_workers()` - Auto-tunes based on project size and CPU count
- `calculate_batch_size()` - Optimizes batch processing size
- `inject_claude_md()` - Injects codeindex instructions into CLAUDE.md (idempotent)
- `has_claude_md_injection()` - Checks if CLAUDE.md already has codeindex injection
- `run_interactive_wizard()` - 6-step interactive setup flow (languages, frameworks, structure, performance, CLAUDE.md injection, optional features)
- `generate_config_yaml()` - Creates .codeindex.yaml from wizard results
- `create_codeindex_md()` - Generates AI agent integration guide

**Design Philosophy**:
- Smart defaults requiring zero manual input
- Complete setup in under 1 minute
- Support both interactive and CI/CD-friendly non-interactive modes

### Enhanced CLI Configuration

**File**: `cli_config.py`

**New Features**:
- `init` command now runs interactive wizard by default
- `--help-config` flag to show complete configuration reference
- `--yes` flag for non-interactive mode (CI/CD friendly)
- `--quiet` flag for minimal output
- `--force` flag to overwrite existing config
- Automatic Git Hooks installation (if enabled)
- CODEINDEX.md generation for AI agents
- **CLAUDE.md injection**: Both interactive and non-interactive modes inject codeindex instructions into CLAUDE.md
- Parser installation check with guidance for missing parsers (non-interactive mode)

**Behavior**:
- Interactive mode: 6-step wizard with smart defaults (includes CLAUDE.md injection prompt)
- Non-interactive mode: Auto-detect everything, use conservative defaults, warn about missing parsers, always inject CLAUDE.md
- Post-setup: Unified `_print_post_init_message()` provides clear next steps for both interactive and non-interactive modes

**CLAUDE.md Integration**:
- Non-interactive (`--yes`): Always calls `inject_claude_md()` as a safe default, reports injection in output
- Interactive: Calls `inject_claude_md()` only if user confirms in wizard Step 5/6
- Both paths set `result.claude_md_injected = True` and display the injected file name

**Post-Init Message**:
- `_print_post_init_message()` - Shared helper that displays next steps after config creation
- Shows structural documentation commands (`scan-all`, `status`)
- Mentions AI-enhanced documentation as optional (`--ai` flag)
- Used by both interactive and non-interactive code paths for consistency

### CLI Scan Commands - Reversed Defaults (Epic 19)

**File**: `cli_scan.py`

**Purpose**: `scan` and `scan-all` commands for README_AI.md generation

**Reversed Default Behavior (v0.16.0+)**:
- **Structural mode is now the default** — generates documentation without AI
- **`--ai` flag opts into AI-enhanced documentation** (previously AI was default)
- `--dry-run` now requires `--ai` (only meaningful for AI prompt preview)
- `--ai` requires `ai_command` to be configured in `.codeindex.yaml`

**Deprecated Flags**:
- `scan --fallback` — deprecated, structural mode is already the default (hidden from help)
- `scan-all --no-ai` — deprecated, structural mode is already the default (hidden from help)
- `scan-all --fallback` — deprecated alias for `--no-ai` (hidden from help)
- All deprecated flags emit a yellow warning when used

**Validation**:
- `--dry-run` without `--ai` → error with usage hint
- `--ai` without `ai_command` in config → error with configuration example

**AI Fallback Behavior**:
- When AI output validation fails in `--ai` mode, falls back to structural README with clear messaging ("structural fallback")
- AI CLI errors now suggest removing `--ai` flag instead of using `--fallback`

### Config - AI Command Default Change

**File**: `config.py`

**Change (v0.16.0+)**:
- `DEFAULT_AI_COMMAND` changed from `'claude -p "{prompt}" --allowedTools "Read"'` to `""` (empty string)
- AI is now opt-in: `ai_command` must be explicitly configured in `.codeindex.yaml` to use `--ai` mode
- Aligns with the reversed scan defaults where structural mode is the default

### CLI Hooks - Post-Commit Hook with Auto-Update & Auto-Commit (Epic 19)

**File**: `cli_hooks.py`

**Purpose**: HookManager generates and installs Git hooks for automated README_AI.md updates

**Post-Commit Hook Behavior**:
- Removes `set -e` to prevent hook from aborting on non-fatal errors
- Sets working directory to repo root (`cd "$REPO_ROOT"`) before activating venv or running commands
- Iterates over affected directories and runs `codeindex scan` for each directory that has an existing README_AI.md
- Skips directories without README_AI.md (shows warning to run `codeindex scan` first)
- **Auto-commits updated README_AI.md files** after successful scan:
  - Stages all updated README_AI.md files
  - Checks if there are actual staged changes (skips if already up to date)
  - Creates a `--no-verify` commit with message `"docs: auto-update README_AI.md for <short-hash>"`
  - Commit message includes update level from change analysis

**Hook Script Generation**:
- `generate_hook_script()` produces shell scripts with colored output, venv activation, and change analysis
- Post-commit hook uses `codeindex affected` to determine which directories need updating
- Temporary file (`/tmp/codeindex_updated_$$`) tracks which README_AI.md files were successfully updated

### Enhanced Help System (Epic 15 Story 15.3)

**Files**: `config_help.py`, `cli_config_commands.py`

**Purpose**: Comprehensive configuration documentation and parameter explanation system

**Core Features**:

**config_help.py**:
- `CONFIG_PARAMS` dictionary with complete parameter documentation
- `show_full_config_help()` - Display full configuration reference with all parameters
- `explain_parameter()` - Explain individual configuration parameters with context
- `get_current_config_value()` - Retrieve current value from .codeindex.yaml

**Language Parameter Documentation**:
- **Supported Languages**: Python, PHP, Java (fully supported with parsers)
- **Description**: "Programming languages to index"
- **Example Configuration**:
  ```yaml
  languages:
    - python
    - php
    - java
  ```
- Note: Only Python, PHP, and Java have full parser support currently

**cli_config_commands.py**:
- `config` command group for configuration-related operations
- `config explain <parameter>` - Interactive parameter explanation
- Context-aware help showing current values and system-specific recommendations

**Documentation Coverage**:
- Performance settings (parallel_workers, batch_size)
- AI integration (ai_command)
- Project structure (languages, include, exclude)
- Git Hooks (hooks.post_commit.enabled, hooks.post_commit.mode)
- Output settings (output_file)

**Each Parameter Includes**:
- Description and purpose
- Type and default value
- Valid ranges/options
- Performance recommendations
- Trade-offs and considerations
- Current value (if config exists)
- System-specific validation (e.g., CPU count checks)
- YAML examples

**Usage Examples**:
```bash
# Show full configuration reference
codeindex init --help-config

# Explain specific parameters
codeindex config explain parallel_workers
codeindex config explain hooks.post_commit.mode
codeindex config explain languages
```

**Design Philosophy**:
- Context-aware help (shows current values)
- System-aware validation (warns about CPU count mismatches)
- Progressive disclosure (brief help → detailed explanation)
- Examples-driven documentation
- Clear language support indication (parser availability)

### CLI Entry Point

**File**: `cli.py`

**Purpose**: Main CLI entry point with command registration

**New Commands**:
- `config` - Configuration help and explanation command group (Epic 15 Story 15.3)

**Command Registration**:
- All CLI commands are registered through the `main` group
- New `config` command group added alongside existing commands (scan, init, status, hooks, etc.)

### Scanner - Unified Language Extension Handling & Pass-Through Detection

**File**: `scanner.py`

**Key Functions**:
- `get_language_extensions(languages)` - Returns a unified set of file extensions for all configured languages
- `is_pass_through(dir_path, config)` - Detects pass-through directories (no code files, single subdirectory) to avoid redundant README_AI.md generation in deep structures like Java Maven paths (`src/main/java/com/zcyl/module/`)
- `scan_directory()` - Directory walking with file filtering by language extensions
- `find_all_directories()` - Discovers all directories containing indexable files

**Pass-Through Directory Detection**:
- A pass-through directory has: (1) no code files of its own, and (2) exactly one non-excluded subdirectory
- Used by `DirectoryTree.get_processing_order()` to skip redundant directories
- Prevents empty/duplicate README_AI.md files in deep package hierarchies (e.g., Java Maven `src/main/java/com/...`)
- Handles filesystem errors gracefully (PermissionError, OSError)

**Unified Extension Map**:
- Replaces per-language if/elif chains with a single `get_language_extensions()` lookup
- `scan_directory()` uses `item.suffix in get_language_extensions(config.languages)` for file filtering
- `find_all_directories()` uses the same unified extension set for consistency
- Adding new language support requires only updating the extension map, not multiple code paths

### Directory Tree - Pass-Through Filtering & Logging

**File**: `directory_tree.py`

**Key Classes**:
- `DirectoryNode` - Tree node representing a directory with depth, level, children, and file info
- `DirectoryTree` - Hierarchical directory structure for smart README_AI.md generation

**Pass-Through Directory Skipping (Epic 19)**:
- `get_processing_order()` now filters out pass-through directories using `scanner.is_pass_through()`
- Pass-through directories (no code files, single subdirectory) are excluded from processing order
- Prevents redundant README_AI.md generation in deep structures like Java Maven paths
- Remaining directories are still sorted by depth (deepest first) for child-before-parent processing

**Logging**:
- `print_tree()` now uses `logger.debug()` instead of `print()` for tree visualization output
- Follows standard Python logging conventions for library code

### Tech Debt CLI - Auto-Recursive for Java Projects

**File**: `cli_tech_debt.py`

**Java-Specific UX**:
- Automatically enables `--recursive` mode when Java is a configured language
- Rationale: Java projects have deep package structures (e.g., `src/main/java/com/example/...`) where non-recursive scans at the root find no files
- No user action required — the CLI detects Java configuration and applies recursive scanning transparently
- Replaces the previous hint-based approach (which only showed a suggestion after empty results) with proactive auto-enabling

### Tech Debt Detector - Language-Aware Noise Analysis

**File**: `tech_debt.py`

**Language-Aware Noise Breakdown**:
- `_analyze_noise_breakdown()` now accepts a `file_type` parameter to make noise categorization language-aware
- The file type is derived from the `ScoringContext.file_type` attribute during analysis
- **Java getter/setter handling**: In Java files, methods matching the `get*`/`set*` pattern are recognized as standard JavaBeans convention and are **not** counted as noise (they are skipped in noise categorization)
- Non-Java files retain the existing behavior where `get*`/`set*` methods are categorized as getter/setter noise

### Symbol Scorer - Java-Aware Getter/Setter Scoring

**File**: `symbol_scorer.py`

**Java-Specific Behavior**:
- Getter/setter penalty (`-10.0`) is skipped for Java files
- Java getters/setters follow standard JavaBeans convention and are not considered noise
- Uses `file_type` attribute from `ScoringContext` to determine language
- Non-Java files retain the existing penalty for `get*`, `set*`, `is*`, `has*` prefixed methods

---

## Recent Changes

**CLAUDE.md Injection Feature**:
- **init_wizard.py**: New `CLAUDE_MD_MARKER_START`, `CLAUDE_MD_MARKER_END` constants and `CLAUDE_MD_SECTION` template for marker-based idempotent injection
- **init_wizard.py**: New `inject_claude_md()` function — creates CLAUDE.md if missing, prepends section if no markers found, replaces between markers if already injected
- **init_wizard.py**: New `has_claude_md_injection()` helper to check for existing injection
- **init_wizard.py**: `WizardResult` gains `inject_claude_md` (default `True`) and `claude_md_injected` fields
- **init_wizard.py**: Interactive wizard expanded from 5 to 6 steps — new Step 5/6 asks "Inject codeindex instructions into CLAUDE.md?"
- **cli_config.py**: Non-interactive mode (`--yes`) always calls `inject_claude_md()` as safe default
- **cli_config.py**: Interactive mode calls `inject_claude_md()` when `result.inject_claude_md` is True
- **cli_config.py**: Both paths report injection in console output (`✓ Injected: CLAUDE.md`)

**Post-Commit Hook Auto-Update & Auto-Commit (Epic 19 Story 19.3)**:
- **cli_hooks.py**: Removed `set -e` from post-commit hook to prevent aborting on non-fatal errors
- **cli_hooks.py**: Hook now `cd`s to repo root before activating venv or running commands
- **cli_hooks.py**: Hook iterates affected directories, runs `codeindex scan` for each with existing README_AI.md, and auto-commits updated files with `--no-verify`
- **cli_hooks.py**: Skips directories without README_AI.md (warns user to run `codeindex scan` first)
- **init_wizard.py**: `create_codeindex_md()` now includes "Auto-Update Hooks" section documenting `codeindex hooks install post-commit`, `codeindex hooks status`, and `.codeindex.yaml` hooks configuration

**Parser Detection + Init Wizard Updates (Epic 19 Stories 19.4 + 19.2)**:
- **init_wizard.py**: New `PARSER_PACKAGES` mapping, `check_parser_installed()`, and `get_parser_install_guidance()` functions for detecting installed tree-sitter parsers and generating install commands
- **cli_config.py**: Non-interactive mode (`--yes`) now checks for missing parsers and warns with install guidance; new `_print_post_init_message()` helper provides unified post-init next steps for both interactive and non-interactive modes; post-init message now highlights AI as optional (`--ai` flag); AI configure comment clarified as "AI is opt-in"

**Java Tech-Debt Improvements (Epic 19 Stories 19.6a + 19.6b)**:
- **cli_tech_debt.py**: Auto-enables `--recursive` for Java projects instead of showing a post-hoc hint; removes the empty-directory hint code in favor of proactive behavior
- **tech_debt.py**: `_analyze_noise_breakdown()` is now language-aware via a `file_type` parameter; Java getter/setter methods (`get*`/`set*`) are no longer counted as noise, recognizing them as standard JavaBeans convention

**Pass-Through Directory Skipping (Epic 19 Story 19.5)**:
- **scanner.py**: New `is_pass_through()` function detects directories with no code files and a single subdirectory
- **directory_tree.py**: `get_processing_order()` filters out pass-through directories to avoid redundant README_AI.md generation in deep structures (e.g., Java Maven `src/main/java/com/...`)
- **directory_tree.py**: `print_tree()` switched from `print()` to `logger.debug()` for proper logging

**Reversed Scan Defaults (Epic 19 - v0.16.0+)**:
- **Structural mode is now the default** for both `scan` and `scan-all` commands
- New `--ai` opt-in flag replaces the previous AI-by-default behavior
- `DEFAULT_AI_COMMAND` in `config.py` changed to empty string (AI requires explicit configuration)
- Deprecated flags (`--fallback`, `--no-ai`) are hidden but still functional with deprecation warnings
- `--dry-run` now requires `--ai` flag (validates at command level)
- `--ai` validates that `ai_command` is configured in `.codeindex.yaml`
- Error messages and fallback text updated to reflect new terminology ("structural fallback")

**Dynamic Version Resolution**:
- `__init__.py` now uses `importlib.metadata.version("ai-codeindex")` instead of a hardcoded version string
- Falls back to `"0.0.0-dev"` when package metadata is unavailable
- `pyproject.toml` is the single source of truth for version numbers

**Language Support Clarification**:
- **Supported Languages**: Documentation now correctly reflects that only Python, PHP, and Java have full parser support
- `config_help.py`: Updated language parameter to show "python, php, java (fully supported with parsers)"
- `init_wizard.py`: Commented out detection patterns for languages without parser support (JavaScript, TypeScript, Go, Rust, Ruby) with note "detection only, no parser yet"

**Implementation Details**:
- Detection logic preserved for future language support expansion
- Clear distinction between "fully supported" (with parser) and "planned support" (detection only)
- YAML examples updated to show Python, PHP, and Java configuration

**Java scan-all, Tech Debt, and Getter/Setter Scoring Fixes**:
- **scanner.py**: Replaced per-language if/elif extension checks with unified `get_language_extensions()` call in both `scan_directory()` and `find_all_directories()`, making language support extensible via a single map
- **cli_tech_debt.py**: Added Java-aware hint when tech-debt analysis on a non-recursive scan returns empty results for Java-configured projects
- **symbol_scorer.py**: Java files no longer penalize getter/setter method names (`get*`, `set*`, `is*`, `has*`) since these follow standard JavaBeans convention; penalty retained for other languages
