πŸ”§

Ripperdoc

Architecture

Technical architecture of Ripperdoc

This document describes the internal architecture of Ripperdoc.

Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         CLI Layer                            β”‚
β”‚  (ripperdoc/cli/)                                           β”‚
β”‚  - Terminal UI, Commands, User Interaction                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        Core Layer                            β”‚
β”‚  (ripperdoc/core/)                                          β”‚
β”‚  - Query Loop, Tool Registry, Permissions, Hooks            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β–Ό               β–Ό               β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     Providers     β”‚ β”‚    Tools    β”‚ β”‚      Utilities      β”‚
β”‚  (core/providers/)β”‚ β”‚  (tools/)   β”‚ β”‚      (utils/)       β”‚
β”‚  - Anthropic      β”‚ β”‚  - Bash     β”‚ β”‚  - File Watch       β”‚
β”‚  - OpenAI         β”‚ β”‚  - Read     β”‚ β”‚  - Session Mgmt     β”‚
β”‚  - Gemini         β”‚ β”‚  - Edit     β”‚ β”‚  - Logging          β”‚
β”‚  - DeepSeek       β”‚ β”‚  - Glob     β”‚ β”‚  - Permissions      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚  - Grep     β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                      β”‚  - Task     β”‚
                      β”‚  - ...      β”‚
                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core Components

Query Loop (core/query.py)

The main query loop handles:

  1. Building the system prompt with tool definitions
  2. Sending messages to the LLM provider
  3. Parsing tool calls from responses
  4. Executing tools and collecting results
  5. Handling errors and context overflow
async def query(messages, system_prompt, context, query_context):
    for iteration in range(MAX_ITERATIONS):
        # Build full prompt
        full_prompt = build_full_system_prompt(...)

        # Call LLM
        response = await query_llm(messages, full_prompt, tools)

        # Extract and execute tool calls
        tool_calls = extract_tool_use_blocks(response)
        for tool_call in tool_calls:
            result = await execute_tool(tool_call)

        # Continue or return based on response

Tool System (core/tool.py)

Tools follow a common interface:

class Tool(Generic[TInput, TOutput]):
    @property
    def name(self) -> str: ...

    @property
    def input_schema(self) -> type[TInput]: ...

    async def validate_input(self, input_data, context) -> ValidationResult: ...

    async def call(self, input_data, context) -> AsyncGenerator[ToolOutput]: ...

    def needs_permissions(self, input_data) -> bool: ...

Provider Abstraction (core/providers/)

Providers normalize different LLM APIs:

class ProviderClient:
    async def call(
        self,
        model_profile: ModelProfile,
        system_prompt: str,
        normalized_messages: List[Dict],
        tools: List[Tool],
        **kwargs
    ) -> ProviderResponse: ...

Hook System (core/hooks/)

Hooks intercept lifecycle events:

Event Flow:
1. UserPromptSubmit β†’ User sends message
2. PreToolUse β†’ Before tool execution
3. PermissionRequest β†’ When permission needed
4. PostToolUse β†’ After tool completes
5. Stop β†’ Agent finishes responding

Data Flow

Message Flow

User Input
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CLI Input      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Hook: Submit   │────▢│ May modify     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚ or block       β”‚
        β”‚              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Query Loop     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LLM Provider   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Tool Execution │◀───── Hooks: Pre/Post
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Response       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CLI Output     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Tool Execution Flow

Tool Call (from LLM)
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Resolve Tool   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Parse Input    β”‚ ← Pydantic validation
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PreToolUse     β”‚ ← Hook can block/modify
β”‚ Hook           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Permission     β”‚ ← May prompt user
β”‚ Check          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Execute Tool   β”‚ ← Yields progress/result
β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PostToolUse    β”‚ ← Hook can add context
β”‚ Hook           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Modules

ripperdoc/cli/

  • cli.py - Main entry point
  • ui/ - Terminal UI components
  • commands/ - Slash command implementations

ripperdoc/core/

  • query.py - Main query loop
  • tool.py - Tool base class
  • permissions.py - Permission checking
  • config.py - Configuration management
  • providers/ - LLM provider implementations
  • hooks/ - Hook system

ripperdoc/tools/

23 tool implementations for file operations, search, execution, etc.

ripperdoc/utils/

  • file_watch.py - File change detection
  • session_*.py - Session management
  • conversation_compaction.py - Context compaction
  • permissions/ - Permission utilities

Extension Points

Adding Providers

  1. Create ripperdoc/core/providers/my_provider.py
  2. Implement ProviderClient interface
  3. Register in provider factory

Adding Tools

  1. Create ripperdoc/tools/my_tool.py
  2. Extend Tool base class
  3. Register in default_tools.py

Adding Hooks

  1. Define hook event in hooks/events.py
  2. Implement handler in hooks/executor.py
  3. Integrate in query loop

Performance Considerations

  • Streaming: All LLM responses stream for responsiveness
  • Caching: File contents cached to avoid re-reading
  • Compaction: Automatic context compaction for long sessions
  • Concurrency: Safe tools run in parallel