Content
# Locus
**Everything has a center. This is yours.**
A local-first desktop AI runtime. Bring your own models — Ollama, Claude, or GPT-4 — install agent Skills, and run multi-agent workflows entirely on your machine. No accounts. No cloud. No vendor lock-in.
<!-- Replace with a demo GIF once available -->
<!--  -->
## Why I built this
Every AI tool I use daily is stateless. Skills, context, history, and configs are fragmented across browser tabs, CLI sessions, and vendor dashboards. Every session starts cold. And to use private data with a capable model, you either accept that data leaving your machine, or you give up capability.
Locus is a runtime layer that sits between you and your models:
- **Local-first** — SQLite on disk, AES-256-GCM encrypted API keys, zero mandatory network calls
- **Model-agnostic** — swap Ollama ↔ Claude ↔ OpenAI per session, same interface, no reconfig
- **Skill-driven** — agents load `SKILL.md` manifests ([agentskills.io](https://agentskills.io) open standard), not proprietary prompt configs
- **Multi-agent** — decompose a goal into a DAG of tasks, run sub-agents in parallel, aggregate results
## How it works
```mermaid
sequenceDiagram
actor User
participant UI as React UI
participant IPC as Tauri IPC
participant Orch as Orchestrator (Rust)
participant LLM as LLM Adapter
participant MCP as MCP Tool Server
User->>UI: send message
UI->>IPC: invoke send_message
IPC->>Orch: assemble prompt (skill context + history)
Orch->>LLM: stream chat request
loop token streaming
LLM-->>UI: emit chat_token
end
LLM->>Orch: tool_call requested
Orch->>Orch: risk check (Safe / Moderate / Destructive)
Orch->>MCP: execute tool
MCP-->>Orch: tool result
Orch->>LLM: continue with tool result
LLM-->>UI: emit chat_done
```
## Engineering decisions worth noting
### Multi-agent DAG orchestration
Rather than a simple linear chain, goals are decomposed into a plan DAG by a planner call. Tasks that have no dependency on each other run in parallel via `tokio::task::JoinSet`. A `ReadinessTracker` gates each node — it only fires when all its dependencies have written their outputs to the `SharedStore`. This keeps the orchestrator lock-free for the hot path.
```
Goal → Planner → [Task A] ──┐
[Task B] ──┼──► Aggregator → Response
[Task C ← depends on A] ──┘
```
### MCP as the tool execution layer
Tools are not baked into the app. Skills declare MCP servers in their `SKILL.md`. The backend spawns those servers (stdio or SSE), discovers their tools, and registers them. This means a skill can bring its own file system tools, browser automation, database access — whatever it needs — without any app changes.
Tool names go through a sanitization layer: stored as `server/tool`, exposed to the LLM as `server__tool` (the Anthropic API disallows `/` in names). Desanitization on the response side keeps the protocol clean.
### Tool risk classification with human-in-the-loop
Every tool in the registry is classified `Safe | Moderate | Destructive`. Destructive calls surface a confirmation dialog before execution. This is the minimum viable safety gate for an autonomous agent that can touch the file system and run shell commands.
### Trait-based LLM provider abstraction
```rust
#[async_trait]
pub trait LlmProvider: Send + Sync {
async fn chat(&self, request: ChatRequest) -> Result<ChatResponse, AppError>;
async fn stream(&self, request: ChatRequest, tx: Sender<StreamEvent>) -> Result<(), AppError>;
}
```
Adding a new provider is implementing this trait — the orchestration layer never touches provider-specific code. Ollama, Anthropic, and OpenAI are the three current implementations.
### Privacy: API keys never leave the Rust layer
Keys are encrypted with AES-256-GCM before `INSERT`, decrypted only inside the LLM adapter at call time. No `get_*` command ever returns a key to the frontend. The encryption key itself lives in the OS app data directory, not in the project.
## Features
| Area | What it does |
|---|---|
| Chat | Streaming responses, skill context injected as system prompt, session auto-saved |
| Skills | Install from local path, activate per session, SKILL.md open standard |
| MCP | Spawn tool servers per skill, full tool-use loop, working directory injection |
| Multi-agent | Goal → plan → parallel sub-agent execution → aggregated response |
| Plan approval | Human review of generated task graph before execution begins |
| Providers | Ollama, Anthropic API, OpenAI API — configurable per session |
| History | Browse and reopen past sessions |
| Security | AES-256-GCM encrypted keys, tool risk gates, keys never returned to frontend |
## Getting started
### Prerequisites
- [Rust](https://rustup.rs/) (stable)
- [Node.js](https://nodejs.org/) 18+
- [Tauri v2 prerequisites](https://v2.tauri.app/start/prerequisites/) for your OS
- At least one of: Ollama running locally, an Anthropic API key, or an OpenAI API key
### Run in development
```bash
git clone https://github.com/jairamish/locus.git
cd locus
npm install
npm run tauri dev
```
The first `cargo` build will take a few minutes. Subsequent builds are incremental.
### First run
1. Open Locus — the onboarding screen will appear
2. Go to **Settings → LLM Providers** and add a provider
3. Go to **Skills** and install a skill from a local folder (any folder with a `SKILL.md` file)
4. Start a new chat, select your skill and provider, and go
Connection Info
You Might Also Like
ai-native-pm-os
The exhaustive guide to mastering Claude for Product Managers. Build your...
Train-in-Silence
The first Task-Aware MCP server and automated VRAM calculator for LLM...
stacklit
108,000 lines of code. 4,000 tokens of index. One command makes any repo...
AppClaw
AI-powered mobile automation agent — describe what you want in plain...
pdf-mcp
Production-ready MCP server for PDF processing with intelligent caching....
kotadb
Local-only code intelligence API for AI developer workflows (Bun +...