# johnbean393/sidekick architecture

> Architecture diagram of the GitHub repository johnbean393/sidekick, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-01). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/johnbean393/sidekick
- Repository: https://github.com/johnbean393/sidekick

## Overview

Sidekick is a local-first macOS assistant for chatting with local or OpenAI-compatible models, grounding replies in user-selected resources, and running research and action tools. The main flow is prompt entry, retrieval and optional tool work, model inference, then a sourced response in the conversation. Experts/RAG, deep research, memory, Canvas, and rich Markdown are meaningful product branches. Some relationships below rely on README descriptions because their implementing source was not sampled; those edges cite the README.

Main entry points: [`Sidekick/Logic/Inference/Model.swift`](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/Model.swift) (Inference coordinator), [`Sidekick/Views/Chat/Conversation/ConversationManagerView.swift`](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Chat/Conversation/ConversationManagerView.swift) (Chat interface), [`Sidekick/Types/Conversation/Message/Message.swift`](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Conversation/Message/Message.swift) (Message context), [`Sidekick/Logic/View Controllers/PromptController.swift`](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/View%20Controllers/PromptController.swift) (Prompt handling)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_conversation["Conversation"]
  node_chatui["Chat interface"]
  node_prompt["Prompt handling"]
  node_conversationstate["Conversations"]
  node_message["Message context<br/>[Message.swift]"]
  node_markdown["Markdown rendering"]
end

subgraph group_inference["Inference"]
  node_model["Inference coordinator<br/>[Model.swift]"]
  node_llama["Local inference server<br/>[LlamaServer.swift]"]
  node_settings["Model settings"]
end

subgraph group_knowledge["Knowledge and Research"]
  node_expertui["Expert setup"]
  node_experts["Experts and resources"]
  node_indexing["Resource indexing"]
  node_retrieval["Resource retrieval<br/>[Resources.swift]"]
  node_websearch["Web search<br/>[WebSearch.swift]"]
  node_research["Deep research agent"]
end

subgraph group_capabilities["Assistant Capabilities"]
  node_functions["Function calling<br/>[Function.swift]"]
  node_memory["Cross-chat memory<br/>[Memories.swift]"]
  node_canvas["Canvas editing"]
  node_image["Image generation routing"]
end

subgraph group_platform["App and State"]
  node_persistence[("SwiftData persistence")]
end

node_person(("User"))
node_remote{{"OpenAI-compatible API"}}
node_storage[("Local data store")]

node_person -->|"enters prompt"| node_chatui
node_chatui -->|"submits prompt"| node_prompt
node_prompt -.->|"requests inference"| node_model
node_prompt -.->|"updates conversation"| node_conversationstate
node_message -->|"retrieves resources"| node_retrieval
node_message -->|"searches web"| node_websearch
node_model -->|"runs inference"| node_llama
node_model -->|"reads configuration"| node_settings
node_model -.->|"can use API"| node_remote
node_llama -.->|"serves remote requests"| node_remote
node_model -.->|"produces reply"| node_message
node_chatui -.->|"renders replies"| node_markdown
node_chatui -->|"selects expert"| node_expertui
node_expertui -->|"manages experts"| node_experts
node_experts -.->|"indexes resources"| node_indexing
node_indexing -->|"builds indexes"| node_retrieval
node_retrieval -.->|"supplies sources"| node_message
node_websearch -.->|"supplies results"| node_message
node_model -.->|"invokes tools"| node_functions
node_functions -.->|"returns tool results"| node_model
node_research -->|"uses inference"| node_llama
node_research -.->|"researches websites"| node_websearch
node_model -.->|"uses remembered facts"| node_memory
node_chatui -->|"opens Canvas"| node_canvas
node_canvas -->|"requests edits"| node_model
node_prompt -.->|"routes image prompts"| node_image
node_conversationstate -->|"stores conversations"| node_persistence
node_experts -->|"stores experts"| node_persistence
node_persistence -->|"reads and writes"| node_storage

click node_chatui "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Chat/Conversation/ConversationManagerView.swift"
click node_prompt "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/View%20Controllers/PromptController.swift"
click node_conversationstate "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Data%20Models/ConversationManager.swift"
click node_message "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Conversation/Message/Message.swift"
click node_markdown "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Chat/Markdown/ChatMarkdownWebView.swift"
click node_model "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/Model.swift"
click node_llama "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/llama.cpp/LlamaServer.swift"
click node_settings "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Settings/InferenceSettings.swift"
click node_expertui "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Expert/ExpertManagerView.swift"
click node_experts "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Data%20Models/ExpertManager.swift"
click node_indexing "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Services/RAGIndexingService.swift"
click node_retrieval "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Expert/Resources.swift"
click node_websearch "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Utilities/Web/WebSearch.swift"
click node_research "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Agent/DeepResearchAgent.swift"
click node_functions "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Conversation/Functions/Function.swift"
click node_memory "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Data%20Models/Memories.swift"
click node_canvas "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/View%20Controllers/Conversation/CanvasController.swift"
click node_image "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/Router/PromptAnalyzer.swift"
click node_persistence "https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Persistence/PersistenceController.swift"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_chatui,node_prompt,node_conversationstate,node_message,node_markdown,node_person toneBlue
class node_model,node_llama,node_settings,node_storage toneAmber
class node_expertui,node_experts,node_indexing,node_retrieval,node_websearch,node_research,node_remote toneMint
class node_functions,node_memory,node_canvas,node_image toneRose
class node_persistence toneIndigo
```

## Components

### Conversation

- [Chat interface](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Chat/Conversation/ConversationManagerView.swift): `Sidekick/Views/Chat/Conversation/ConversationManagerView.swift`
- [Prompt handling](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/View%20Controllers/PromptController.swift): `Sidekick/Logic/View Controllers/PromptController.swift`
- [Conversations](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Data%20Models/ConversationManager.swift): `Sidekick/Logic/Data Models/ConversationManager.swift`
- [Message context](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Conversation/Message/Message.swift): `Sidekick/Types/Conversation/Message/Message.swift`
- [Markdown rendering](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Chat/Markdown/ChatMarkdownWebView.swift): `Sidekick/Views/Chat/Markdown/ChatMarkdownWebView.swift`

### Inference

- [Inference coordinator](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/Model.swift): `Sidekick/Logic/Inference/Model.swift`
- [Local inference server](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/llama.cpp/LlamaServer.swift): `Sidekick/Logic/Inference/llama.cpp/LlamaServer.swift`
- [Model settings](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Settings/InferenceSettings.swift): `Sidekick/Logic/Settings/InferenceSettings.swift`

### Knowledge and Research

- [Expert setup](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Views/Expert/ExpertManagerView.swift): `Sidekick/Views/Expert/ExpertManagerView.swift`
- [Experts and resources](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Data%20Models/ExpertManager.swift): `Sidekick/Logic/Data Models/ExpertManager.swift`
- [Resource indexing](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Services/RAGIndexingService.swift): `Sidekick/Logic/Services/RAGIndexingService.swift`
- [Resource retrieval](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Expert/Resources.swift): `Sidekick/Types/Expert/Resources.swift`
- [Web search](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Utilities/Web/WebSearch.swift): `Sidekick/Logic/Utilities/Web/WebSearch.swift`
- [Deep research agent](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Agent/DeepResearchAgent.swift): `Sidekick/Types/Agent/DeepResearchAgent.swift`

### Assistant Capabilities

- [Function calling](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Types/Conversation/Functions/Function.swift): `Sidekick/Types/Conversation/Functions/Function.swift`
- [Cross-chat memory](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Data%20Models/Memories.swift): `Sidekick/Logic/Data Models/Memories.swift`
- [Canvas editing](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/View%20Controllers/Conversation/CanvasController.swift): `Sidekick/Logic/View Controllers/Conversation/CanvasController.swift`
- [Image generation routing](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Inference/Router/PromptAnalyzer.swift): `Sidekick/Logic/Inference/Router/PromptAnalyzer.swift`

### App and State

- [SwiftData persistence](https://github.com/johnbean393/sidekick/blob/main/Sidekick/Logic/Persistence/PersistenceController.swift): `Sidekick/Logic/Persistence/PersistenceController.swift`

### Other components

- **User**
- **OpenAI-compatible API**
- **Local data store**

## Connections

- User → Chat interface: enters prompt
- Chat interface → Prompt handling: submits prompt (evidence: `Sidekick/Views/Chat/Conversation/ConversationManagerView.swift`)
- Prompt handling → Inference coordinator: requests inference
- Prompt handling → Conversations: updates conversation
- Message context → Resource retrieval: retrieves resources (evidence: `Sidekick/Types/Conversation/Message/Message.swift`)
- Message context → Web search: searches web (evidence: `Sidekick/Types/Conversation/Message/Message.swift`)
- Inference coordinator → Local inference server: runs inference (evidence: `Sidekick/Logic/Inference/Model.swift`)
- Inference coordinator → Model settings: reads configuration (evidence: `Sidekick/Logic/Inference/Model.swift`)
- Inference coordinator → OpenAI-compatible API: can use API
- Local inference server → OpenAI-compatible API: serves remote requests
- Inference coordinator → Message context: produces reply (evidence: `Sidekick/Logic/Inference/Model.swift`)
- Chat interface → Markdown rendering: renders replies
- Chat interface → Expert setup: selects expert (evidence: `Sidekick/Views/Chat/Conversation/ConversationManagerView.swift`)
- Expert setup → Experts and resources: manages experts (evidence: `Sidekick/Views/Expert/ExpertManagerView.swift`)
- Experts and resources → Resource indexing: indexes resources
- Resource indexing → Resource retrieval: builds indexes (evidence: `Sidekick/Logic/Services/RAGIndexingService.swift`)
- Resource retrieval → Message context: supplies sources
- Web search → Message context: supplies results (evidence: `Sidekick/Types/Conversation/Message/Message.swift`)
- Inference coordinator → Function calling: invokes tools
- Function calling → Inference coordinator: returns tool results
- Deep research agent → Local inference server: uses inference (evidence: `Sidekick/Types/Agent/DeepResearchAgent.swift`)
- Deep research agent → Web search: researches websites
- Inference coordinator → Cross-chat memory: uses remembered facts
- Chat interface → Canvas editing: opens Canvas (evidence: `Sidekick/Views/Chat/Conversation/ConversationManagerView.swift`)
- Canvas editing → Inference coordinator: requests edits (evidence: `Sidekick/Logic/View Controllers/Conversation/CanvasController.swift`)
- Prompt handling → Image generation routing: routes image prompts
- Conversations → SwiftData persistence: stores conversations (evidence: `Sidekick/Logic/Data Models/ConversationManager.swift`)
- Experts and resources → SwiftData persistence: stores experts (evidence: `Sidekick/Logic/Data Models/ExpertManager.swift`)
- SwiftData persistence → Local data store: reads and writes (evidence: `Sidekick/Logic/Persistence/PersistenceController.swift`)
