vibe-heal

vibe-heal Architecture

Overview

vibe-heal follows a modular, layered architecture with clear separation of concerns.

System Architecture

┌─────────────────────────────────────────────────────────┐
│                     CLI Layer                           │
│  (typer, rich - user interface, progress, reporting)    │
└────────────────────┬────────────────────────────────────┘
                     │
┌────────────────────▼────────────────────────────────────┐
│              Orchestration Layer                        │
│  (VibeHealOrchestrator - main workflow logic)          │
└──┬──────────┬──────────┬──────────┬─────────────────────┘
   │          │          │          │
   ▼          ▼          ▼          ▼
┌──────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│Config│ │SonarQube│ │AI Tool│ │   Git    │
│ Mgmt │ │ Client  │ │Manager │ │ Manager  │
└──────┘ └────────┘ └────────┘ └──────────┘
   │          │          │          │
   ▼          ▼          ▼          ▼
┌──────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│.env  │ │SonarQube│ │Claude  │ │   Git    │
│files │ │   API   │ │Code/   │ │   Repo   │
│      │ │         │ │Aider   │ │          │
└──────┘ └────────┘ └────────┘ └──────────┘

Module Structure

src/vibe_heal/
├── __init__.py
├── __main__.py              # Entry point for `python -m vibe_heal`
├── cli.py                   # CLI interface (typer)
├── orchestrator.py          # Main workflow orchestration
├── config/
│   ├── __init__.py
│   ├── models.py           # Configuration Pydantic models
│   └── loader.py           # Configuration loading logic
├── sonarqube/
│   ├── __init__.py
│   ├── client.py           # SonarQube API client
│   └── models.py           # SonarQube response models
├── ai_tools/
│   ├── __init__.py
│   ├── base.py             # Abstract base class + AIToolType enum
│   ├── claude_code.py      # Claude Code implementation
│   ├── aider.py            # Aider implementation
│   ├── factory.py          # Factory for creating AI tool instances
│   └── models.py           # Shared models (FixResult, etc.)
├── git/
│   ├── __init__.py
│   └── manager.py          # Git operations
├── processor/
│   ├── __init__.py
│   ├── issue_processor.py  # Issue sorting and filtering
│   └── models.py           # Processing models
└── utils/
    ├── __init__.py
    ├── logging.py          # Logging setup
    └── validators.py       # Common validation utilities

Core Components

1. Configuration Management (config/)

Purpose: Load and validate configuration from environment variables and config files.

Key Classes:

Key fields: | Field | Default | Description | |—|—|—| | sonarqube_url | — | SonarQube server URL | | sonarqube_token | None | Auth token (preferred over username/password) | | sonarqube_project_key | — | SonarQube project key | | ai_tool | None | AI tool to use; auto-detected if not set | | code_context_lines | 5 | Lines of context shown around issue for AI | | include_rule_description | True | Include full rule docs in AI prompts | | pre_commit_command | None | Pre-commit hook command (see below) |

pre_commit_command values:

Example:

class VibeHealConfig(BaseSettings):
    sonarqube_url: str
    sonarqube_token: str | None = None
    sonarqube_username: str | None = None
    sonarqube_password: str | None = None
    sonarqube_project_key: str
    ai_tool: AIToolType | None = None  # auto-detect if None
    pre_commit_command: str | None = None  # auto-detect if None

    model_config = SettingsConfigDict(
        env_file=['.env.vibeheal', '.env'],
        env_file_encoding='utf-8',
        env_prefix='',
    )

2. SonarQube Client (sonarqube/)

Purpose: Interface with SonarQube Web API to fetch issues.

Key Classes:

SonarQube API Endpoints Used:

3. Issue Processor (processor/)

Purpose: Sort and filter issues to determine fix order.

Key Classes:

4. AI Tool Manager (ai_tools/)

Purpose: Abstract interface for AI coding tools with multiple implementations.

Key Classes:

Prompt Template:

Fix the following SonarQube issue in {file_path}:

Rule: {rule}
Line: {line}
Severity: {severity}
Message: {message}

Please fix this issue while maintaining code functionality and style.

5. Git Manager (git/)

Purpose: Handle git operations for committing fixes.

Key Classes:

Pre-commit Hook Integration:

_stage_and_commit() runs pre-commit hooks before calling repo.index.commit() so that formatters like ruff-format can auto-fix staged files without causing the commit to fail:

1. Stage files (repo.index.add)
2. Run _run_pre_commit_hooks(files)
   └─ pre-commit CLI (if installed) or git hook run fallback
3. If hooks modified files → re-stage them
4. Check if index differs from HEAD (skip if nothing to commit)
5. repo.index.commit(message) with one retry
   └─ On GitError: re-stage any newly dirty files and retry once

Hook runner priority:

  1. Custom pre_commit_command from config (if set)
  2. pre-commit run --files <files> (if pre-commit CLI is on PATH)
  3. git hook run --ignore-missing pre-commit (native git fallback)

Commit Message Format:

fix: [SQ-S1481] Remove unused import

SonarQube Issue: ABC123
Rule: python:S1481
Severity: MAJOR
Location: project:src/foo.py:42

Fixed by: vibe-heal using Claude Code

[vibe-heal](https://github.com/alexeieleusis/vibe-heal)

6. Orchestrator (orchestrator.py)

Purpose: Main workflow coordination.

Key Class:

Workflow:

  1. Validate preconditions (git clean, file exists, etc.)
  2. Fetch issues from SonarQube
  3. Sort and filter issues
  4. For each issue:
    • Show progress
    • Invoke AI tool
    • If success and not dry-run: commit
    • Track results
  5. Return summary

7. CLI (cli.py)

Purpose: User interface.

Key Functions:

Commands:

vibe-heal fix <file_path>           # Fix issues in file
  --dry-run                          # Preview without committing
  --max-issues N                     # Limit number of fixes
  --ai-tool {claude-code,aider}      # Override tool detection
  --verbose                          # Debug logging

vibe-heal config                     # Show current configuration
vibe-heal version                    # Show version

CLI uses AIToolType enum:

@app.command()
def fix(
    file_path: str,
    dry_run: bool = False,
    max_issues: int | None = None,
    ai_tool: AIToolType | None = typer.Option(None, help="AI tool to use"),
    verbose: bool = False,
):
    # ...

Data Flow

Happy Path: Fixing a File

1. User runs: vibe-heal fix src/foo.py

2. CLI parses arguments
   ├─> Load configuration
   └─> Create VibeHealOrchestrator

3. Orchestrator.__init__()
   ├─> Initialize components
   └─> _initialize_ai_tool()
       ├─> config.ai_tool is None
       ├─> AIToolFactory.detect_available()
       │   ├─> Try ClaudeCodeTool().is_available() → True
       │   └─> Return AIToolType.CLAUDE_CODE
       └─> AIToolFactory.create(AIToolType.CLAUDE_CODE)
           └─> Return ClaudeCodeTool instance

4. Orchestrator.fix_file("src/foo.py")
   ├─> GitManager.is_clean() → ✓
   ├─> SonarQubeClient.get_issues_for_file("src/foo.py")
   │   └─> Returns [Issue1(line=50), Issue2(line=30), Issue3(line=10)]
   ├─> IssueProcessor.sort_issues()
   │   └─> Returns [Issue1(line=50), Issue2(line=30), Issue3(line=10)]
   │
   ├─> For Issue1 (line=50):
   │   ├─> AITool.fix_issue(Issue1, "src/foo.py")
   │   │   └─> Returns FixResult(success=True, files_modified=["src/foo.py"])
   │   └─> GitManager.commit_fix(Issue1, ["src/foo.py"], AIToolType.CLAUDE_CODE)
   │
   ├─> For Issue2 (line=30):
   │   ├─> AITool.fix_issue(Issue2, "src/foo.py")
   │   │   └─> Returns FixResult(success=True, files_modified=["src/foo.py"])
   │   └─> GitManager.commit_fix(Issue2, ["src/foo.py"], AIToolType.CLAUDE_CODE)
   │
   └─> For Issue3 (line=10):
       ├─> AITool.fix_issue(Issue3, "src/foo.py")
       │   └─> Returns FixResult(success=False, error_message="...")
       └─> Track as failed

5. Return FixSummary(fixed=2, failed=1, skipped=0)

6. CLI displays summary report

Error Handling Strategy

Validation Errors (Fail Fast)

Recoverable Errors (Continue)

Rollback Strategy

Configuration Priority

  1. Command-line arguments (--ai-tool flag)
  2. .env.vibeheal file
  3. .env file
  4. Environment variables
  5. Auto-detection (if ai_tool not specified)

Testing Strategy

Unit Tests

Integration Tests

Manual Testing

Security Considerations

  1. Credentials: Never log tokens or passwords
  2. Code Execution: AI tools execute code - require clean git state
  3. Input Validation: Validate file paths to prevent directory traversal
  4. API Rate Limiting: Respect SonarQube API rate limits
  5. Secrets in .env: Add .env* to .gitignore (already done in template)

Performance Considerations

  1. Sequential Processing: Fix issues one at a time (safety over speed)
  2. HTTP Client: Use httpx with connection pooling
  3. Async Where Possible: Use async/await for I/O operations
  4. Lazy Loading: Only initialize components when needed

Future Architecture Improvements

  1. Plugin System: Allow custom AI tool implementations via enum extension
  2. Event System: Emit events for fixes, commits (for monitoring)
  3. Queue System: For multi-file processing
  4. Caching: Cache SonarQube responses
  5. State Management: Track progress across runs