Skip to content

indexer

code_context_agent.indexer

Deterministic indexing pipeline for code analysis without LLM invocations.

Runs static analysis tools (ripgrep, semgrep, radon, vulture, knip, repomix), git history analysis, and GitNexus graph indexing. All external tool calls are graceful -- if a tool is missing the step is skipped and indexing continues.

build_index async

build_index(repo_path, output_dir=None, quiet=False)

Build a deterministic index of a codebase without LLM invocations.

Pipeline: 1. File manifest via ripgrep 1a. Write file manifest to disk 2. Language detection from file extensions 3. GitNexus analyze (graph indexing) 4. Git hotspots + co-changes -> JSON files 5. Repomix compressed signatures 6. Repomix orientation 7. BM25 index prebuild 8. Semgrep auto 9. Semgrep OWASP 10. Type checker 11. Linter 12. Complexity analysis 13. Dead code (Python) 14. Dead code (TypeScript) 15. Dependencies 16. Generate heuristic_summary.json

Parameters:

Name Type Description Default
repo_path Path

Path to the repository root.

required
output_dir Path | None

Where to save artifacts (default: repo_path/.code-context/).

None
quiet bool

Suppress progress output.

False
Source code in packages/code-context-agent/src/code_context_agent/indexer.py
async def build_index(
    repo_path: Path,
    output_dir: Path | None = None,
    quiet: bool = False,
) -> None:
    """Build a deterministic index of a codebase without LLM invocations.

    Pipeline:
    1.  File manifest via ripgrep
    1a. Write file manifest to disk
    2.  Language detection from file extensions
    3.  GitNexus analyze (graph indexing)
    4.  Git hotspots + co-changes -> JSON files
    5.  Repomix compressed signatures
    6.  Repomix orientation
    7.  BM25 index prebuild
    8.  Semgrep auto
    9.  Semgrep OWASP
    10. Type checker
    11. Linter
    12. Complexity analysis
    13. Dead code (Python)
    14. Dead code (TypeScript)
    15. Dependencies
    16. Generate heuristic_summary.json

    Args:
        repo_path: Path to the repository root.
        output_dir: Where to save artifacts (default: repo_path/.code-context/).
        quiet: Suppress progress output.
    """
    repo = repo_path.resolve()
    out = output_dir or (repo / DEFAULT_OUTPUT_DIR)
    out.mkdir(parents=True, exist_ok=True)

    # Step 1: File manifest
    files = _get_file_manifest(repo)
    if not quiet:
        logger.info(f"Indexing {len(files)} files in {repo}")

    # Step 1a: Write file manifest to disk (BM25 search checks for this)
    manifest_path = out / "files.all.txt"
    manifest_path.write_text("\n".join(files))

    # Step 2: Detect languages
    lang_files = _detect_languages(files)
    if not quiet:
        lang_summary = {lang: len(fs) for lang, fs in lang_files.items()}
        logger.info(f"Languages detected: {lang_summary}")

    # Step 3: GitNexus analyze
    gitnexus_ok = _run_gitnexus_analyze(repo, quiet)

    # Step 4: Git hotspots + co-changes (write to JSON)
    _ingest_git(repo, out, quiet)

    # Step 5: Repomix compressed signatures
    _run_repomix_signatures(repo, out, quiet)

    # Step 6: Repomix orientation
    _run_repomix_orientation(repo, out, quiet)

    # Step 7: BM25 index prebuild
    _prebuild_bm25(files, repo, quiet)

    # Step 8-9: Semgrep
    _run_semgrep_auto(repo, out, quiet)
    _run_semgrep_owasp(repo, out, quiet)

    # Step 10: Type checker
    _run_typecheck(repo, out, lang_files, quiet)

    # Step 11: Linter
    _run_lint(repo, out, quiet)

    # Step 12: Complexity
    _run_complexity(repo, out, lang_files, quiet)

    # Step 13-14: Dead code
    _run_dead_code_py(repo, out, lang_files, quiet)
    _run_dead_code_ts(repo, out, lang_files, quiet)

    # Step 15: Dependencies
    _run_deps(repo, out, lang_files, quiet)

    # Step 16: Generate heuristic_summary.json
    _generate_heuristic_summary(files, lang_files, out, repo, gitnexus_ok, quiet)