AI memory engine. Store everything, find anything. One binary. One SQLite file. Zero cloud dependencies.
brew tap shamim0902/tap && brew install locus
locus init
locus search "database migration strategy"# Install
brew tap shamim0902/tap && brew install locus
# init in any project
locus init
# Use MCP
locus mcp
# connect with Claude
claude mcp add locus locus mcp start
- Why Locus
- Installation
- Quick Start
- Connect to AI (MCP)
- CLI Reference
- REST API
- Web Dashboard
- Embedding Models
- How Search Works
- Knowledge Graph
- Supported File Types
- Configuration
- Architecture
- Build from Source
- License
You talk to AI every day. You make decisions, debug problems, settle on approaches — all inside conversations that vanish when the session closes.
Most memory tools solve this with cloud vector databases, LLM summarization calls, or massive dependency trees. Locus takes a different approach:
- No cloud. Everything stays on your machine in one SQLite file.
- No API keys. No subscription. No internet required.
- No LLM in the loop. Stores raw text, not lossy summaries.
- No heavy dependencies. Single ~17MB binary. Ships with
brew install. - Hybrid search. BM25 lexical + semantic vectors + rank fusion. Finds results that pure vector search misses.
- Optional Ollama integration. Plug in transformer-quality embeddings when you want them. Falls back to built-in TF-IDF when you don't.
The result: a portable memory engine you can scp to another machine.
brew tap shamim0902/tap
brew install locusVerify:
locus version
command not found? Homebrew's bin directory may not be in your PATH:# Apple Silicon Mac: echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc && source ~/.zshrc # Intel Mac: echo 'eval "$(/usr/local/bin/brew shellenv)"' >> ~/.zshrc && source ~/.zshrc # Linux: echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bashrc && source ~/.bashrc
Requires Go 1.19+:
go install github.com/shamim0902/locus/cmd/locus@latest
command not found? Add Go's bin to PATH:echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
Download the latest release for your platform from GitHub Releases:
# Example: macOS Apple Silicon
tar xzf locus_0.2.0_darwin_arm64.tar.gz
sudo mv locus /usr/local/bin/Available for: macOS (arm64/amd64), Linux (arm64/amd64), Windows (arm64/amd64).
cd into any project directory and run:
cd ~/projects/myapp
locus init -> Initializing Locus
Directory /Users/you/projects/myapp
Wing myapp (auto-detected)
Embedder tfidf
Mining files...
✓ Mining complete
Summary
═════════
Files scanned 127
Files changed 127
Memories added 843
Locus walks the directory, chunks every supported file, embeds each chunk, and stores everything in ~/.locus/memory.db. The wing name is auto-detected from the folder name.
locus search "database migration strategy" -> Found 5 results
──────────────────────────────────────
1. [myapp/data] ██████████ 100%
We decided to use PostgreSQL for the migration because...
──────────────────────────────────────
2. [myapp/backend] ████████░░ 82%
The schema migration runs on deploy via...
Use --wing and --room to scope results. Use --top-k 10 for more.
locus wake-up --wing myapp --budget 300The packer sorts memories by importance and recency, then fills your token budget with the richest summary level that fits.
locus kg add "Team" "decided" "PostgreSQL"
locus kg query "Team"
locus kg timeline "Team"locus mine ~/projects/another-project
locus mine --wing api-serviceRun locus mine anytime. Unchanged files are skipped (SHA-256 hash check). Changed files have their old memories retired and new ones created.
Locus includes a Model Context Protocol (MCP) server with 19 tools. Run locus mcp install for setup instructions tailored to your system:
locus mcp installThis shows config snippets for each supported tool:
claude mcp add locus -- /path/to/locus mcp startAdd to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"locus": {
"command": "/path/to/locus",
"args": ["mcp", "start"]
}
}
}Add the same command and args to your MCP settings. Run locus mcp install --tool cursor or locus mcp install --tool vscode for exact snippets.
After connecting, ask your AI: "What do you remember about database decisions?". It will call locus_search automatically.
locus mcp Show setup guide (or auto-start if called by an MCP client)
locus mcp start Start the JSON-RPC server over stdin/stdout
locus mcp install Show config snippets for your AI tool
locus mcp status Check if MCP is configured correctly
| Category | Tools |
|---|---|
| Search | locus_search, locus_wake_up, locus_find_related |
| Memory | locus_add, locus_update, locus_delete, locus_check_duplicate |
| KG | locus_kg_add, locus_kg_query, locus_kg_invalidate, locus_kg_timeline, locus_kg_stats |
| Navigation | locus_list_wings, locus_list_rooms, locus_taxonomy |
| Agent | locus_diary_write, locus_diary_read, locus_agent_summary |
| Status | locus_status |
locus init [path] Initialize + mine (defaults to current directory)
locus mine [path] Mine files into memory
locus search <query> Hybrid search
locus wake-up Generate packed context for AI
locus status Show system overview
locus reindex Rebuild all embeddings
locus kg add <subj> <pred> <obj> Add a knowledge graph triple
locus kg query <entity> Query entity facts
locus kg timeline <entity> Show chronological facts
locus serve Start REST API + web dashboard
locus mcp MCP server management
locus version Print version
| Flag | Commands | Description |
|---|---|---|
--wing |
init, mine, search, wake-up | Filter or set the wing name |
--room |
search | Filter by room |
--top-k |
search | Number of results (default: 5) |
--budget |
search, wake-up | Token budget for context packing |
--embedder |
init, mine, search, reindex | Embedding model: auto, ollama, tfidf |
--port |
serve | API server port (default: 8765) |
--db |
all | Path to SQLite database |
Start the server:
locus serve --port 8765GET / Web dashboard
GET /v1/health Health check
GET /v1/status System stats
GET /v1/analytics Wing stats, daily counts, recent activity
GET /v1/wings List wings with counts
GET /v1/wings/{wing}/rooms List rooms in a wing
GET /v1/memories Paginated memory listing (?wing=&room=&limit=&offset=)
GET /v1/export Download wing data as JSON (?wing=)
POST /v1/search Hybrid search
POST /v1/memories Add new memory
PUT /v1/memories/{id} Edit memory
DELETE /v1/memories/{id} Delete memory
POST /v1/memories/bulk-delete Batch delete by IDs
POST /v1/mine Trigger mining
POST /v1/wake-up Context packing with budget
POST /v1/kg/triples Add KG triple
GET /v1/kg/entities/{name} Query entity facts (?as_of= for point-in-time)
GET /v1/kg/timeline/{name} Entity chronology
# Search
curl -s -X POST http://localhost:8765/v1/search \
-d '{"query": "auth migration", "wing": "myapp", "top_k": 3}' | jq
# Add memory
curl -s -X POST http://localhost:8765/v1/memories \
-d '{"wing": "myapp", "room": "auth", "content": "Decided to use Clerk."}' | jq
# Wake-up context
curl -s -X POST http://localhost:8765/v1/wake-up \
-d '{"wing": "myapp", "budget": 300}' | jqAll responses are JSON. Errors return {"error": "message"} with appropriate HTTP status codes.
Start the server and open http://localhost:8765/ in your browser.
Eight pages:
- Overview -- Stats cards, 14-day activity chart, wing cards
- Browse -- Paginated memory listing, bulk select/delete, edit modal
- Search -- Query with wing/room filters, result cards
- Add Memory -- Form for manual memory creation
- Knowledge Graph -- Entity query, timeline, add triples
- Context -- Budget slider, wake-up generator, copy to clipboard
- Analytics -- 30-day chart, wing/room breakdown tables
- Manage -- Mine from UI, import/export wing data as JSON
The dashboard is a single embedded HTML file with inline CSS/JS. No npm. No build step. No external dependencies.
Locus supports pluggable embedding models via the --embedder flag.
Zero dependencies. Works offline. Instant.
- 2048-dimensional IDF-weighted term frequency vectors
- Vocabulary built from your full corpus
- Good for keyword-heavy queries and exact term matching
When Ollama is running locally, Locus auto-detects it and uses transformer-quality embeddings.
# Install Ollama and pull the model
ollama pull nomic-embed-text
# Mine with semantic embeddings (auto-detected)
locus mine .
# Or force Ollama explicitly
locus mine . --embedder ollamaOllama gives you semantic understanding -- a search for "payment form customization" finds content about "checkout billing fields" even when the exact words don't match.
Re-embed your entire database with a different model:
locus reindex --embedder ollama # Switch to Ollama
locus reindex --embedder tfidf # Switch back to TF-IDFWhen --embedder is auto (the default):
- Check if Ollama is running at
http://localhost:11434 - If yes, use
nomic-embed-textfor semantic embeddings - If no, fall back to built-in TF-IDF
This means search quality improves automatically when Ollama is available, with zero configuration.
Locus uses hybrid retrieval: two independent search methods combined with rank fusion.
SQLite FTS5 with Porter stemming. Finds documents containing your search terms. Handles exact keyword matches, typos caught by stemming, and boolean queries.
Cosine similarity between the query embedding and stored embeddings. Captures meaning beyond exact words. Model-aware: only compares vectors from the same embedding model.
Both ranked lists are combined:
score(doc) = 1/(60 + bm25_rank) + 1/(60 + vector_rank)
Documents ranked highly in both lists score highest. This consistently outperforms either method alone.
Use --wing and --room to scope search to a specific project or topic area. Filters are applied before scoring, narrowing the candidate pool for better precision.
Track structured facts about entities and their relationships over time.
# Add facts
locus kg add "Kai" "works_on" "Orion"
locus kg add "Team" "decided" "PostgreSQL"
# Query current facts
locus kg query "Kai"
# View chronological history
locus kg timeline "Kai"Every fact has a time window. When Kai moves from Orion to Nova, the old fact is invalidated (sets valid_to) and a new one is added. Query with ?as_of=2025-06-01 for point-in-time views.
When your search query contains entity names, Locus automatically fetches their KG facts and includes them in the response alongside text results.
| Category | Extensions |
|---|---|
| Code | .go .py .js .ts .tsx .jsx .rs .java .rb .sh |
| Docs | .txt .md .html .css |
| Config | .json .yaml .yml .toml |
| Data | .sql .csv |
Skipped directories: .git, node_modules, __pycache__, dist, build, vendor, .venv, .next, and anything starting with .
Limits: Files over 512KB are skipped. Non-UTF-8 files are skipped.
Locus has minimal configuration by design.
~/.locus/identity.txt -- loaded as the first item in every wake-up context. Write whatever your AI should always know:
Senior engineer at Acme Corp. Team: Kai, Maya, Priya.
Current project: Orion. Stack: Go, PostgreSQL, React.
Default: ~/.locus/memory.db. Override with the --db flag:
locus --db /other/path/memory.db search "query"~/.locus/
memory.db Single database file. Everything lives here.
identity.txt Your identity text (optional).
That's it. One database file. Back it up with cp. Transfer it with scp. Delete it to start fresh.
INTERFACE LAYER
┌──────────┬──────────┬──────────────┐
│ CLI │ REST API │ MCP Server │
│ (cobra) │(net/http)│ (JSON-RPC) │
└────┬─────┴────┬─────┴──────┬───────┘
└──────────┼────────────┘
│
┌─────▼──────┐
│ ENGINE │
│ engine.go │
└──┬──┬──┬───┘
┌─────────────┘ │ └─────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼──────┐ ┌─────▼──────┐
│ INGESTION │ │ RETRIEVAL │ │ KNOWLEDGE │
│ mine.go │ │ search.go │ │ GRAPH │
│ chunk.go │ │ embed.go │ │ kg.go │
│ adapters/ │ │ ollama.go │ │ │
│ │ │ pack.go │ │ │
└─────┬─────┘ └─────┬──────┘ └─────┬─────┘
└────────────────┼────────────────┘
│
┌──────▼───────┐
│ STORAGE │
│ SQLite DB │ ~/.locus/memory.db
│ 10 tables │ 12 indexes, 3 FTS triggers
│ WAL mode │
└──────────────┘
- Pure Go, CGO_ENABLED=0. Single binary, true cross-compilation, no C dependencies.
- SQLite over vector databases. One file, zero runtime dependencies, FTS5 for BM25 built-in.
- Hybrid search over pure vector. BM25 + vector + RRF fusion catches what each method alone misses.
- Sentence-boundary chunking. No mid-sentence cuts. Paragraph breaks are hard boundaries.
- Incremental mining. SHA-256 hash ledger skips unchanged files. Safe to run repeatedly.
- Pluggable embedder.
Embedderinterface -- swap TF-IDF for Ollama (or any future model) with one flag. - Embedded dashboard. Single HTML file with inline CSS/JS. No npm, no build step.
| Table | Purpose |
|---|---|
memories |
Raw verbatim text chunks (source of truth) |
memories_fts |
FTS5 virtual table for BM25 search |
embeddings |
Vector embeddings (JSON float arrays, model-tagged) |
summaries |
Three levels per memory (keywords, 1-sentence, 2-sentence) |
entities |
Knowledge graph nodes |
triples |
Temporal facts with validity windows |
mining_ledger |
File path to content hash mapping |
embedding_cache |
Content hash to vector cache (avoids re-embedding) |
agent_diaries |
Per-agent journal entries |
event_log |
Append-only audit trail |
Requires Go 1.19+. No CGo, no C compiler, no Python, no Docker.
git clone https://github.com/shamim0902/locus.git
cd locus
make build # ./locus binary (~17MB)
make install # sudo cp to /usr/local/bin
make install-user # cp to ~/.local/bin (no sudo)
make test # go test ./...
make build-all # cross-compile for 5 platforms
make clean # remove binary + databaseMIT