Every feature,
explained.
Five feature areas, nineteen MCP tools, one Rust binary. This page is the engineering reference — what each piece does, how it works, and the code signature you actually call.
Your agent's hippocampus,
in SQLite.
Memory is the core. biTurbo stores every remembered fact in SQLite, embeds it locally with BGE-small-en, and indexes it with turbovec. Per-project isolation means testy's decisions stay out of scout-qa's recall results — and the index never sends a byte to the cloud.
Use SQLite WAL mode for concurrent agent writes
Laravel + Inertia requests need X-Inertia header on every POST
pnpm 11 requires allowBuilds in workspace yaml for esbuild
WebView inspector reads DOM via executeJavaScript sync
Storage layer
- SQLite with WAL mode, r2d2 connection pool
- Memories table with kind, importance, tags, project_id, agent_id, timestamps
- Per-project turbovec IdMapIndex — one file per project, never shared
- Activity audit log for every write/delete, queryable for debugging
Memory kinds
- decision — architectural or product choices
- pattern — recurring solutions in this codebase
- gotcha — things that broke before and will break again
- context — current state, in-flight work, env specifics
- fact — verified truths about the project
Self-maintenance
- Scheduled decay: importance * 0.95 per day, with a floor at 0.05
- Dedup: cosine sim > 0.96 with same kind → merge into the higher-importance one
- Merge: near-duplicates get a new embedding that's the mean
- Configurable decay/dedup per project via INSTRUCTIONS.md rules
The protocol your agent
already speaks.
MCP is the universal adapter between an LLM and a tool. biTurbo exposes 19 of them — every operation your agent needs, from 'remember this' to 'recite everything relevant to this question' — over a single stdio socket. No HTTP, no auth, no proxy.
How it boots
- Standalone biturbo-mcp binary, spawned by your agent's MCP config
- Speaks stdio JSON-RPC — the official rmcp 1.7 Rust SDK
- First call: register_agent + list_projects (auto-bootstrapped)
- Every subsequent call scoped to a project_id
Why stdio, not HTTP
- Zero auth surface — the OS process boundary is the only access control
- No port to bind, no TLS to misconfigure, no firewall to argue with
- Works in any environment Claude Code / Cursor / Cline / Mavis can spawn a process in
- Latency: one pipe roundtrip per call, no HTTP overhead
The hot path
- recall_for_context(query, project_id, k) returns a <biTurboContext> block
- Pre-formatted for direct injection as system message or system prompt
- Hybrid ranking: cosine sim + tag match + importance + recency
- Average latency: < 2ms for k=8 on a 10k memory project
A force-directed map
of your codebase.
Drop a folder on a project. biTurbo walks it with tree-sitter, chunks per function, embeds each chunk, and renders a Barnes-Hut force layout in a Web Worker. 3,000+ nodes, 8,000+ edges, viewport-culled, with filter switches that cancel stale layout requests.
Code ingest
- tree-sitter 0.25 with language crates: rust, ts, js, py, go
- Per-function chunks (not whole files) for tight semantic search
- Respects .gitignore; configurable include/exclude globs
- Re-ingest on demand; future: watch-folder with debounce
Layout engine
- Barnes-Hut n-body approximation — O(n log n) instead of O(n²)
- Runs in a dedicated Web Worker, off the main thread
- Seed renders in < 5ms; worker refines in 200–800ms for 3k nodes
- Filter switches cancel the active layout request via AbortController
Interaction model
- Click a node → its neighborhood highlights, sidebar opens with chunks
- Right-click a node → context menu: open in editor, search memories, focus
- Pan/zoom with momentum; viewport culling keeps it at 60fps
- Saved view states per project, shareable as a URL
Sub-50ms cold start.
Sub-2ms recall.
biTurbo is fast because every layer of the stack is fast. The Rust binary is ~12MB, links zero Python, and cold-starts in under 50ms. The vector index is turbovec 4-bit — 16× smaller than float32, with recall parity you can actually measure.
Binary & startup
- Pure Rust 1.77+, no Python runtime, no Docker, no JVM
- Single ~12MB binary; release build with LTO + strip + codegen-units=1
- Cold start < 50ms on M1, < 80ms on Intel
- Idle RAM: ~25MB. Scales linearly with vector count, not corpus size
Vector compression
- turbovec 0.8 IdMapIndex, 4-bit product quantisation
- 16× smaller than float32 — 1M BGE-small-en vectors fit in 24MB
- Recall@10 within 0.5% of float32 on MS MARCO and BEIR subsets
- MIT licensed, beats FAISS-IVFPQ on the recall-per-byte curve
Embedding model
- fastembed 4 with BGE-small-en (~30MB ONNX, downloaded on first launch)
- CPU and Metal (Apple Silicon) backends; CUDA optional
- Per-agent override possible via INSTRUCTIONS.md (e.g. bge-large for accuracy)
- Embeddings cached by content hash; re-embed is a no-op if nothing changed
MIT. Forever.
No pro tier, ever.
biTurbo is, and will always be, MIT licensed. There is no enterprise edition. There is no usage-based pricing. The whole codebase is on GitHub — Rust backend, React frontend, MCP server, smoke test, the docs. Fork it, vendor it, ship it in your own product. We just ask for a star.
What's in the repo
- src/ — React 18 + Vite + Tailwind frontend (6 views, 5 primitives)
- src-tauri/src/ — Rust backend (db, index_engine, embed, memory, project, ingest, consolidate, mcp, scheduler, commands)
- src-tauri/bin/biturbo_mcp.rs — standalone MCP server
- scripts/mcp-smoke-test.ts — 19-tool validator (~2s end-to-end)
Contributing
- Issues and PRs welcome on GitHub
- No CLA — sign-off is the DCO (git commit -s)
- CI runs the smoke test on every PR (coming soon — Homebrew tap first)
- Roadmap and RFCs in the issue tracker
Roadmap (next)
- Watch-folder ingest — auto-reindex on file change
- Cross-encoder re-ranker for top-k (pluggable, opt-in)
- Encrypted-at-rest mode (project-level key, Argon2id-derived)
- Multi-device sync (CRDTs over the same on-disk format)
The 19 MCP tools.
Every tool is a JSON-RPC method. Schemas below match the actual rmcp generated bindings — copy-paste safe.
remember
remember(content, project_id, kind?, importance?)Persist a memory. Kind can be decision, pattern, gotcha, context, fact. Importance is 0..1 and decays over time unless reinforced.
remember("SQLite WAL allows concurrent reads during write", "testy", kind="decision", importance=0.9)forget
forget(memory_id, reason?)Delete a memory. Soft-delete by default; hard-delete with reason. Logs the deletion event in the activity audit.
forget("mem_abc123", reason="outdated after WAL migration")update
update(memory_id, content?, importance?, tags?)Patch any field of a memory. Updating content re-embeds automatically. Importance changes propagate to the recall ranker.
update("mem_abc123", importance=0.95, tags=["wal", "concurrency"])get_memory
get_memory(memory_id)Fetch the full record of a single memory by id, including metadata, tags, timestamps, and the originating agent.
get_memory("mem_abc123")search
search(query, project_id, k?, filters?)Hybrid semantic + lexical search over a project. Filters: kind, tag, importance_min, time_range. Returns top-k with scores.
search("agent auth flow", "scout-qa", k=8, filters={"kind": "pattern"})list
list(project_id, filters?)List memories in a project with optional filters and pagination. No semantic scoring — fast, deterministic.
list("testy", filters={"tag": "gotcha", "limit": 50})list_tags
list_tags(project_id)Enumerate all tags in a project with usage counts. Useful for the agent to discover its own vocabulary before searching.
list_tags("testy")recall_for_context
recall_for_context(query, project_id, k?)The hot path. Returns a formatted <biTurboContext> block ready to inject as system context. Use this before every non-trivial answer.
recall_for_context("why is the layout broken on mobile", "testy", k=4)list_projects
list_projects()Discover all projects on disk. Returns id, name, vector count, last activity. Usually the agent's first call after register_agent.
list_projects()
get_project
get_project(project_id)Fetch a single project record with full stats: memory count, vector size, ingest path, last consolidate run.
get_project("prj_testy")create_project
create_project(name, path?)Create a new isolated project. Path optionally binds it to a code root for auto-ingest. Index starts empty and warms on first remember().
create_project("testy", path="/Users/.../testy")delete_project
delete_project(project_id, confirm?)Delete a project and all its memories, vectors, audit logs. Requires confirm=true as a safety net for agents.
delete_project("prj_old", confirm=true)ingest_project
ingest_project(project_id, path, langs?)Walk a code root with tree-sitter, chunk per function, embed each chunk, and add as context-kind memories. Default langs: rust, ts, js, py, go.
ingest_project("prj_testy", "/Users/.../testy", langs=["rust", "ts"])consolidate
consolidate(project_id, mode?)Manually trigger decay/dedup/merge. mode can be 'decay', 'dedup', 'merge', or 'all'. Runs synchronously by default; async with mode='all' for big indexes.
consolidate("testy", mode="all")consolidate_status
consolidate_status(project_id)Inspect the last consolidate run: timestamp, memories removed/merged, scheduler next run, decay config in effect.
consolidate_status("testy")stats
stats(scope?)System-wide or per-project stats. scope can be 'global' or a project_id. Returns memory counts, vector sizes, recall latency p50/p95.
stats(scope="global")
bootstrap
bootstrap()First-run helper. Returns the recommended INSTRUCTIONS.md block for the agent kind (Claude Code, Cursor, Cline, Mavis).
bootstrap()
recent_activity
recent_activity(project_id?, n?)Stream of the last n writes (or all) for a project. Used to show the agent what its peers are doing.
recent_activity("testy", n=20)register_agent
register_agent(name, kind)Claim an agent identity. All subsequent writes are attributed. Kind can be claude-code, cursor, cline, mavis, or a custom string.
register_agent(name="claude-opus-4.5", kind="claude-code")
Give your agents
a memory.
Free. Open source (MIT). One Rust binary. Five minutes fromcargo installto your agent writing memories that survive a reboot.