Soma · Local-first semantic search

Search what you mean.
Not what you typed.

A semantic search engine for your own documents, PDFs, images, audio and video. Every model runs on your machine. 100% offline, no cloud, no API keys — one single binary.

Windows x64 · macOS ARM64 · Linux x64 — free and open source

Hybrid BM25 + vector HyDE retrieval Local LLM reranker OCR & vision Whisper transcription sqlite-vec index HTTP API for agents Air-gap ready
localhost:8181
HybridLexicalVector
4 results · 124 ms · expansion + BM25 + vector + RRF + rerank · fully local
soma://notes/api/authentication.md @a1b2c3markdown

Requests are authenticated at the gateway: the JWT is verified, then the session is resolved against the user store before routing downstream.

soma://research/zero-trust-design.pdf @d4e5f6pdf · p.14

Every request is treated as untrusted; identity is re-established per hop, and authorization decisions are made at the edge proxy.

soma://meetings/2024-06-11-platform-sync.m4a @8f0a11transcript · 12:41

“…so login goes through the gateway now — the token refresh is the part that still breaks after a deploy.”

soma://screenshots/2024-05-02-auth-flow.png @b7c2d9OCR + vision

Whiteboard diagram showing client → gateway → auth service → user store, with a dashed line for token refresh.

0

bytes leaving your machine

1

single native binary

3

search modes: hybrid · lexical · vector

6+

file families indexed, from PDF to video

Private by design

Privacy isn’t a setting.
It’s the architecture.

Cloud “AI search” understands what you mean — after you upload your notes, contracts, research papers and meeting recordings to somebody else’s server. Soma keeps all of it, and all of the intelligence, here.

Nothing is uploaded

Indexing, embedding, reranking and searching all happen on-device. There is no telemetry, no account and no background daemon you didn’t ask for.

No API keys

Soma bundles a local inference stack — llama.cpp and whisperfile — and downloads open-weight models. No OpenAI key. No subscription.

Air-gap ready

Export every model and tool as one reproducible ZIP on a connected machine, then --import it on an isolated one. Zero HTTP at runtime.

Your machine
Your files
Folders you choose, read-only
Your machine
Local models
Embedding · expansion · rerank · OCR · vision · Whisper
Your machine
Local SQLite index
Full-text + sqlite-vec vectors
Result
Answers, offline
CLI · web UI · HTTP API

Soma never modifies your source files. The index is fully derived state — if it ever breaks, soma sync rebuilds it.

Mental model

Add a folder.
Sync. Search.

That’s the whole product. Point Soma at a folder, let it read and understand the contents once, then ask questions in plain language — or hunt for an exact phrase.

Explore the three search modes

# 1. point Soma at a folder
$ soma project add ~/notes

# 2. index + extract + embed (fully local)
$ soma sync

# 3. ask in plain language
$ soma search "how does auth work" --limit 3

1. soma://notes/api/authentication.md   @a1b2c3
   Requests are authenticated at the gateway: the JWT is
   verified, then the session is resolved against the user
   store before routing downstream.

2. soma://notes/runbooks/login-failures.md   @d4e5f6
   ...

Features

A full retrieval stack,
shipped as one file.

Hybrid search

Lexical BM25 + dense embeddings + a HyDE passage, fused with Reciprocal Rank Fusion and reranked by a local LLM. Best relevance, out of the box.

Still great at exact matching

Prefix matching, "quoted phrases", -exclusions and per-project scoping. BM25 ranked — fast, deterministic, no models involved.

Multilingual & CJK

Unicode NFKC normalization, camelCase / snake_case / path tokenization, plus CJK unigram + bigram indexing so 1–2 character queries still work.

Built-in web UI

soma server serves a single-file browser interface on localhost:8181 — search, projects, status and documents.

Agent-friendly

JSON / CSV / Markdown / paths output and a JSON-RPC-style POST /api/run endpoint that mirrors the CLI. One contract to learn.

Local models only

EmbeddingGemma for embeddings, QMD for query expansion, Qwen3 Reranker, Qwen3-VL for images and Whisper for speech — all via llama.cpp / whisperfile, on CPU or GPU.

Workspaces & context hints

Run soma init to keep config and index inside ./.soma/ so the index travels with the folder. Attach descriptive hints to a path to sharpen relevance and snippets.

Search modes

Trade recall for precision.
Or speed. Your call.

Best relevance

A local LLM expands your query into lexical keywords, dense retrieval sentences and a HyDE passage. Every signal is fused with RRF, then reranked locally. Override any channel by hand with --lex, --vec, --hyde, or add background with --intent.

$ soma search "how does auth work"

$ soma s "performance" --intent "web page load times"

$ soma search hybrid --lex "CAP theorem" \
                    --vec "consistency tradeoffs"

All search and get commands support -f text|json|csv|md|paths — pipe straight into scripts, editors or AI agents.

How it works

Two pipelines.
Both entirely local.

Indexing pipeline

Run soma sync: pull → scan → extract → embed → clean.

Source
📁 Project folder
Read-only, never modified
Step 1
Scan
include / exclude globs · .gitignore aware
Step 2
Extract
PDF · Office · EPUBImage OCR · VisionTranscription
Step 3
Chunk + Embed
Local embedding model
Store
🗄️ SQLite index
Full-text + sqlite-vec vectors

Query pipeline

Expansion, embedding, retrieval and reranking — every stage runs on your hardware.

Input
🔍 Your question
“why do pods restart after deploy”
Expansion
🧠 Local LLM
lexical keywordsdense sentencesHyDE passage
Retrieval
Parallel search
📄 BM25 lexical🏹 Vector ANN
Fusion
RRF
Reciprocal Rank Fusion
Rerank
🧠 Local reranker
Qwen3 Reranker 0.6B
Output
✅ Ranked results
with snippets & DocIDs

Supported file types

It reads a lot more
than plain text.

Multimedia extraction is optional — text-only indexing runs happily on a modest machine.

Text & code

.md.txt.csvsource

Indexed directly, with camelCase / snake_case / path-aware tokenization.

PDF

.pdf

Text-layer extraction, page by page, then chunked and embedded.

Office & ebooks

.docx.xlsx.pptx.epub

Converted to Markdown via Pandoc, then chunked and embedded.

Images & screenshots

.png.jpg.webp

OCR text plus a vision-LLM description, so a whiteboard photo becomes findable.

Audio

.mp3.wav.m4a

FFmpeg + Whisper transcription. Transcribe once, then search what was actually said.

Video

.mp4.mkv.mov

Audio track extracted and transcribed, timestamps kept for jump-to-moment snippets.

Web UI & HTTP API

An agent that knows
soma --help already knows the API.

$ soma server --auto-sync     # http://localhost:8181
$ soma server --port 8080
GET /Built-in web interface
GET /healthHealth check
GET /assets/…Raw file under a project root
POST /api/runJSON RPC mirroring the CLI
$ curl -s localhost:8181/api/run \
  -H 'Content-Type: application/json' \
  -d '{"command":"search.hybrid",
       "args":["how does auth work"],
       "options":{"limit":5,"format":"json"}}'

{
  "success": true,
  "requestId": "xxx",
  "durationMs": 124,
  "exitCode": 0,
  "data": { ... },
  "stdout": "",
  "stderr": "",
  "error": null
}

Perfect for local RAG, coding assistants, MCP-style tooling and automation — with no vector database to operate.

Soma vs. other search tools

Meaning and exact matches.
Without the upload.

Soma grep / ripgrep Spotlight / Windows Search Cloud AI search
Natural-language questions✓✕✕✓
Exact keyword / phrase (BM25)✓✓ regexpartialvaries
PDF / Office / EPUB content✓✕partial✓
Images (OCR + vision)✓✕partialvaries
Audio / video transcripts✓✕✕varies
Runs fully offline✓✓✓✕
Data leaves your machineneverneverneveryes
Scriptable JSON output + HTTP API✓✓✕✓
Setupone binaryone binarybuilt inaccount + upload

Use cases

Built for the archives
you can’t hand over.

Second brain

Personal knowledge base

Search Obsidian, Logseq, Zettelkasten or plain Markdown vaults by meaning, not by filename.

Research

PDF library

Semantic search across hundreds of papers and books, by meaning.

Engineering

Code & internal docs

Find “where is retry logic handled” without knowing the function name.

Speech

Meetings & lectures

Transcribe recordings once, then search what was actually said — down to the timestamp.

Visual

Screenshot archives

OCR plus vision descriptions make years of screenshots and photos findable.

AI

Local RAG backend

A private retrieval layer with JSON output and an HTTP API. No vector DB to run.

Regulated

Air-gapped teams

Legal, medical, defense and finance environments where cloud search is simply not an option.

Get Soma

One file. Zero setup.

A single GraalVM native binary. No Python, no Docker, no vector database service. Pick your platform.

# macOS (Apple Silicon) · Homebrew
$ brew install AwesomeDog/tap/soma
$ soma --version

Tech specs

Everything, in detail.

System requirements

  • RAM — 8 GB minimum for text search
  • RAM — 24 GB+ while multimedia features run (OCR, vision, transcription)
  • GPU — optional; speeds up embedding, vision and transcription
  • OS — Windows x64 · macOS ARM64 · Linux x64
  • Disk — space for models downloaded on first sync
  • Network — only for the first sync or system pull

Local model stack

  • Embeddings — EmbeddingGemma 300M
  • Query expansion — QMD 1.7B
  • Reranker — Qwen3 Reranker 0.6B
  • Generation / vision — Qwen3-4B-Instruct · Qwen3-VL 4B
  • Speech — Whisper (whisper.cpp releases)
  • Runtimes — llama.cpp · whisperfile

Index & tooling

  • Store — local SQLite, full-text + sqlite-vec vectors
  • Fusion — Reciprocal Rank Fusion
  • PDF / OCR — pdfium helper · RapidOCR-CLI
  • Docs — Pandoc (Office / EPUB → Markdown)
  • Media — FFmpeg / Jellyfin FFmpeg
  • Binary — GraalVM native image

Where Soma stores data

  • Config — $XDG_CONFIG_HOME/soma/<ws>.yml
  • Index DB — $XDG_STATE_HOME/soma/<ws>.sqlite
  • Cache — $XDG_STATE_HOME/soma/caches/
  • Logs / locks — $XDG_STATE_HOME/soma/{logs,locks}/
  • Models & tools — $XDG_DATA_HOME/soma/
  • Source files are never modified.

Command cheat sheet

soma
├── project        add <root> · list (ls) · files <path> · update · remove · rename · show
├── sync           # pull → scan → extract → embed → clean
├── search (s)     [hybrid (h)] · lexical (l) · vector (v)
│                  --lex --vec --hyde --intent · -p/--project · --limit · --no-limit
│                  --full · --line-number · -f/--format [text|json|csv|md|paths]
├── get            @docid | soma://project/path | project/path | ./file
│                  --start-line · --max-lines · --line-number · --max-size · -f/--format
├── server         [http] [--port <n>] [--auto-sync]        # web UI + HTTP API
├── context        list (ls) · set <path> <text> · remove <path>   [-p/--project]
├── status         # workspace, index and artifact status
├── init           # create directory-local workspace (.soma/)
└── system         pull [--refresh | --export | --import] · scan · extract · embed [-p] · clean

GLOBAL: -w/--workspace | -v/--verbose [SOMA_VERBOSE=1]
        --no-color [NO_COLOR=1] | -h/--help | -V/--version
WORKSPACE: -w/--workspace > directory-local > SOMA_DEFAULT_WORKSPACE > XDG 'main'

FAQ

Good questions.

Does Soma send anything to the cloud?
No. Indexing and searching are 100% local. The only network access is downloading models and CLI tools on first use (soma sync / soma system pull), which you can also do offline via --export / --import.
Do I need an OpenAI / Anthropic API key?
No. Soma bundles a local inference stack (llama.cpp, whisperfile) and downloads open-weight models.
Do I need a GPU?
No. Everything runs on CPU. A GPU mainly accelerates embedding, vision extraction and transcription.
Does it modify or move my files?
No. Soma reads your files and writes its index elsewhere. Your folders stay untouched.
Which languages does it support?
Indexing and querying are multilingual, with dedicated CJK handling (unigram + bigram indexing) so short Chinese, Japanese and Korean queries remain retrievable.
How is this different from ripgrep?
ripgrep matches literal strings and regexes in text files. Soma additionally understands meaning, and can search inside PDFs, Office documents, images, audio and video.
Can I use Soma as a RAG backend for an AI agent?
Yes — use -f json from the CLI or POST /api/run over HTTP. The API mirrors the CLI, so there is only one contract to learn.
Where does the index live, and can I move it?
By default under XDG state directories. Run soma init in a folder to keep config and index in ./.soma/, so the searchable index travels with the directory.
Something looks stale or broken. What do I run?
soma sync for the normal cycle, soma system scan for a full re-read of every file, soma status for diagnostics.

Your files. Your models.
Your machine.

Add a project, run sync, and start asking questions.