Internals

This section describes the high-level architecture of sharur: how its components are organized, how data flows through the system, and how the key abstractions relate to each other.


Directory Structure

sharur/
โ”‚   โ”œโ”€โ”€ internal/
โ”‚   โ”‚   โ”œโ”€โ”€ service/        # Central AgentService implementation + in-process client
โ”‚   โ”‚   โ”œโ”€โ”€ gen/            # Generated Protobuf stubs (pb.AgentServiceClient/Server)
โ”‚   โ”‚   โ”œโ”€โ”€ agent/          # Core agentic loop, event bus, state machine
โ”‚   โ”‚   โ”œโ”€โ”€ llm/            # LLM provider adapters (Ollama, OpenAI, Anthropic, llama.cpp, Google)
โ”‚   โ”‚   โ”œโ”€โ”€ tools/          # Built-in tool implementations + registry
โ”‚   โ”‚   โ”œโ”€โ”€ session/        # JSONL-backed session persistence, branching, tree
โ”‚   โ”‚   โ”œโ”€โ”€ modes/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ interactive/ # Bubble Tea TUI (pb client)
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ print.go    # One-shot CLI JSONL mode (pb client)
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ grpc.go     # gRPC server mode (wraps Service)
โ”‚   โ”‚   โ”œโ”€โ”€ config/         # Config loading (global + project layering)
โ”‚   โ”‚   โ”œโ”€โ”€ themes/         # TUI colour themes
โ”‚   โ”‚   โ”œโ”€โ”€ types/          # Shared value types (Message, Session, ThinkingLevel)
โ”‚   โ”‚   โ”œโ”€โ”€ events/         # Generic publish-subscribe event bus
โ”‚   โ”‚   โ”œโ”€โ”€ skills/         # Skill discovery (Markdown files โ†’ slash commands)
โ”‚   โ”‚   โ”œโ”€โ”€ prompts/        # Prompt template discovery
โ”‚   โ”‚   โ””โ”€โ”€ contextfiles/   # Auto-discovered context file injection (AGENTS.md, etc.)
โ”‚   โ”œโ”€โ”€ cmd/                # Entry points (shr)
โ”‚   โ”œโ”€โ”€ proto/              # Protobuf definitions (sharur/v1/agent.proto)
โ”‚   โ”œโ”€โ”€ extensions/         # gRPC extension loader + proto definitions
โ”‚   โ””โ”€โ”€ sdk/                # Public Go SDK

Component Diagram

flowchart TD
    CLI["CLI flags & Config"] --> Svc

    subgraph core ["internal/agent"]
        Agent["Agent
Messages ยท SteerQueue ยท FollowUpQueue
StateMachine"]
        RunTurn["runTurn
provider.Stream ยท consumeStream ยท execTools"]
        EB["EventBus
async ยท non-blocking ยท 4096-item buffer"]
        Agent --> RunTurn
        RunTurn -->|publishes| EB
    end

    Svc["internal/service
AgentService"] --> core

    RunTurn --> LLM

    subgraph llm ["internal/llm"]
        LLM["Provider interface
Stream ยท Info"]
        Adapters["Ollama ยท OpenAI ยท Anthropic
llama.cpp ยท Google"]
        LLM --> Adapters
    end

    EB --> TUI["TUI"]
    EB --> JSON["JSON stdout"]
    EB --> GRPC["gRPC stream"]
    EB --> Session["session saver"]

Data Flow Summary

flowchart TD
    Input["User Input"] --> Mode["TUI ยท JSON ยท Remote Client"]
    Mode --> PBClient["pb.AgentServiceClient
bufconn or TCP"]
    PBClient --> Service["internal/service
getOrCreate / loadIfExists"]
    Service --> AP["agent.Prompt(ctx, text)"]
    AP --> MI["ext.ModifyInput()"]
    MI --> SS["ext.SessionStart() ยท ext.AgentStart()
EventAgentStart"]

    SS --> Loop

    subgraph Loop ["runTurn loop"]
        direction TB
        BP["ext.BeforePrompt() ยท ModifySystemPrompt()
ModifyContext() ยท BeforeProviderRequest()"]
        LLMStream["llm.Provider.Stream()
EventTextDelta ยท EventThinkingDelta ยท EventToolCall"]
        APR["ext.AfterProviderResponse()
EventTurnStart ยท ext.TurnStart()"]
        ToolExec["ext.BeforeToolCall() ยท execTool() ยท ext.AfterToolCall()
EventToolDelta ยท EventToolOutput"]
        TE["ext.TurnEnd()"]
        More{"more tool calls?"}
        BP --> LLMStream --> APR --> ToolExec --> TE --> More
        More -->|yes| BP
    end

    More -->|no| AgEnd["EventAgentEnd ยท ext.AgentEnd()"]
    AgEnd --> Save["service saves session to disk"]
    Save --> Stream["Stream Protobuf Events to client"]
    Stream --> Render["Render: TUI ยท JSONL stdout ยท gRPC stream"]