Satori
Helps coding agents find and inspect relevant code before making an edit. Search, source evidence, and symbol navigation run locally by default.
The problem
A coding agent needs to understand the code it is about to change. A plausible search result is only a starting point: the source may be stale, the result may belong to the wrong symbol, or the relevant behavior may span several files.
I built Satori to help an agent move from a question to inspectable source evidence before editing. It can search a repository, identify the relevant symbol, follow supported relationships, and read the source in a bounded span.
The key decision
Search results and source navigation need to describe the same repository state. I made a complete, immutable Publication the unit a reader sees.
The architecture simplification removed the older graph of separate policy, marker, navigation, snapshot, and repair authorities. A current Satori index is now one immutable Publication containing its vector resources, navigation, selection policy/format identity, and source checkpoint.
A reader atomically pins one Publication for the lifetime of the request. Sync builds the replacement privately and activates it only when complete, so a concurrent reader sees the complete old Publication or the complete new one—never a mixed generation.
Ordinary source divergence converges through sync. Missing, corrupt, or incompatible authority requires reindex; the public lifecycle deliberately no longer exposes a repair command for retired authority formats.
Measured evidence
The current repository publishes its own qualification evidence rather than borrowing model-card numbers.
A checksum-sealed local Potion + LanceDB run indexed 488 files and 10,830 chunks. The recorded warm-search p95 was 154.543 ms; zero-change synchronization p95 was 185.662 ms.
A separate exploratory two-task OpenCode comparison produced correct answers in both Satori and native file-discovery arms:
| Observation | Satori tools | Native grep / glob / read |
|---|---|---|
| Tool calls | 16 | 25 |
| Tool-output bytes | 76,113 | 96,801 |
| Agent wall time | 51.65 s | 96.04 s |
| Total model tokens | 46,767 | 46,759 |
That run is evidence of a shorter evidence route on those tasks, not a universal token or speed claim. It was one run per task, and total model-token usage was effectively unchanged.
Trade-offs and limits
TypeScript, JavaScript, Python, Go, Java, C#, C++, Rust, and Scala now expose production symbol navigation plus qualified CALLS v0 support for the slices Satori can actually prove.
The important word is qualified. Dynamic or receiver-heavy relationships that the current resolver cannot establish are omitted instead of guessed. call_graph is navigation evidence, not a compiler-grade blast-radius claim, and manage_index status remains the authority for which capabilities are ready in a specific Publication.
Making the architecture smaller
Local-first retrieval originally forced Satori to model freshness, runtime compatibility, navigation, and publication safety explicitly. The next step was deleting duplicated proof machinery once those boundaries were understood.
The current design has one Publication owner, one activation point, one root writer fence, and Publication-ID read leases. Runtime compatibility and source freshness remain real boundaries, but they no longer require several durable databases to repeatedly prove that copies of the same generation agree.
That simplification is important to me because it makes the product easier to reason about without weakening the fail-closed behavior that protects agents from stale or half-published evidence.
What I learned
The project started as “semantic search for coding agents.” That description is now too small.
The harder system is the evidence contract around search: source freshness, exact identifiers, lexical and semantic retrieval, conservative language relationships, immutable publication, bounded disclosure, runtime compatibility, and a tool surface that tells the agent when it should stop guessing.
That is the part I now consider the product.
Runtime and tools
Satori turns a repository into a freshness-aware code map. An MCP-compatible agent can search by intent, inspect the real owner, follow nearby relationships, and read an exact symbol or bounded span instead of reconstructing the codebase from repeated broad file dumps.
The default Linux x64 / WSL2 path is local-first:
source repository
-> source + language/navigation evidence
-> exact evidence + BM25 + dense retrieval
-> Potion Code 16M v2 embeddings
-> LanceDB Publication
-> LateOn D32 query-time reranking
-> owner-oriented groups + bounded reads
No model API key is required for that default runtime. Compatible Codex, Claude Code, OpenCode, and subagent sessions can share one managed local host over a private Unix-domain socket instead of starting one heavy runtime per session.
Connected deployments can still use Voyage Code 3 and LanceDB or Milvus/Zilliz. Existing Ollama users can select an explicit local embedding model. Provider choice changes model-specific vectors; it does not become the authority for source truth.
The public tools
Continuation lets an agent inspect more of a frozen search result without rerunning retrieval.
| Tool | What it owns |
|---|---|
manage_index | create, sync, status, reindex, clear |
search_codebase | freshness-aware hybrid search |
continue_search | disclose more from the same frozen result set |
file_outline | indexed symbols and exact spans in one file |
call_graph | advisory callers, callees, imports, exports |
read_file | bounded source span or exact indexed symbol |
list_codebases | known repositories and readiness/runtime state |
Satori intentionally has no write-capable MCP tool. The host environment still owns source edits.
Related notes
- Why semantic code search is not enough for coding agents
- When index cleanup lies, agents make unsafe decisions
- Why MCP CLIs fail when stdout is treated like logs
- Why naive RAG fails for coding agents