v0.1.17 · self-hosted · MCP-native

Your agent stops grepping blind and starts tracing a real graph

NexusContext parses your codebase into functions, types, and call edges — resolved across file boundaries, now optionally sharpened by a real language server — and answers search_graph, trace_call_path, and get_architecture over a local MCP connection. No embeddings required to get started.

14
MCP tools
11
Languages parsed
0
Embeddings required
6
Platform × arch builds

Design philosophy

The agent is the intelligence. NexusContext is the memory.

No LLM lives in the daemon. It builds structure and answers queries — your agent still does all the reasoning.

A graph, not just vectors

Tree-sitter parses 11 languages into a SQLite graph of functions, types, and call edges, resolved across file boundaries — plus full-text search and dead-code detection on the same graph, zero embeddings required.

Resolution you can verify

An optional LSP enrichment pass (rust-analyzer today) adds real reference-resolved call edges alongside the static ones — kept as a distinct, auditable edge kind, never silently merged in.

MCP-native

A real JSON-RPC 2.0 stdio server with 14 tools, verified against real IDE-style sessions — drop it into any MCP-compatible agent, or auto-configure Claude Code/Desktop with one command.

Desktop-first on Linux

A native GTK4 + libadwaita manager app and a thin GNOME Shell status indicator — not a web dashboard bolted on afterward. Call-graph visualization renders a bounded neighborhood, not an unreadable whole-project hairball.

Safe by construction

Embeddings endpoints are blocked unless loopback/private or explicitly allowed. Path traversal, decompression bombs, and permission leaks are closed at the check itself, not just at the call sites that found them.

Team-shareable index

Export a compressed, size-capped graph snapshot next to your source so teammates skip the first reindex on clone — never committed unless you choose to.


Measured, not promised

Four real questions, tokenized, not estimated

Run live against v0.1.4 on a real 2,414-node production Go monorepo, counted with tiktoken. Two questions win big. Two don't — shown here anyway.

Find real callers, with code

trace_call_path plus two scoped get_file_context calls return exactly 2 real callers with line ranges — and correctly skip a same-named test file that plain grep flagged as a false positive.

8,096 → 551 tokens · −93%

"How does this actually work?"

One query_memory semantic call over the indexed docs beats reading the two most relevant files in full — the specifics it surfaced (an env var, a cache field name) checked out against the real source.

4,797 → 1,785 tokens · −63%

Every symbol tied to a concept

search_graph found 37 real declarations against grep's 79 raw text hits (comments included) — fewer results, but each one is structured, so it costs slightly more, not less.

2,338 → 2,647 tokens · +13%

Cold-start architecture read

get_architecture ranks files by real definition density and adds a language breakdown — wc -l is cheaper, but only measures line count, and a naive version of it silently swept in node_modules.

127 → 340 tokens · +168%

Combined across all four: 15,358 → 5,323 tokens (−65%) — but that average blends two clear wins with two honest losses, not four wins. Navigation and conceptual questions are where the graph pays for itself; a plain-text or line-count answer can still be cheaper when the question itself is shallow enough that a shallow answer is fine. A newer, in-daemon accounting of this same tradeoff — get_session_usage's reads_avoided counterfactual — is covered below.


What your agent can actually call

14 MCP tools, grouped by what they answer

Every tool is backed by the same SQLite graph — no separate index to keep in sync, no silent fallback that hides what actually ran.

Index & read
index_repositorydeep
Build or rebuild the knowledge graph. deep: true also runs LSP-resolved-symbol enrichment, if configured.
get_file_context
Read a file, or a specific line range, from an indexed project.
get_architecture
Node/edge counts, busiest files, language breakdown — plus an index_freshness field.
Search & trace
search_graph
Structural search over indexed symbols by name substring — no embeddings required.
search_code
Grep-like full-text search over indexed file content via SQLite FTS5 — code and markdown alike.
trace_call_path
BFS over the CALLS graph — now unioned with LSP-resolved edges when a deep reindex has run.
Quality & usage
detect_dead_code
Functions with no inbound call edge — candidates worth a second look.
detect_changes
Map uncommitted git changes to the graph symbols they actually affect.
query_planner
Picks the cheapest retrieval strategy and returns the answer in-band, plus index_freshness.
get_session_usagericher
This session's usage, plus schema_tax and reads_avoided — an auditable counterfactual for tokens this daemon actually saved.
Query & manage
query_graph
Ad-hoc pattern query: MATCH (a:Kind)-[:EDGE]->(b:Kind) RETURN a|b.
delete_projectdestructive
Remove a project's indexed data. Never touches the source directory.
search_codebase / query_memoryopt-in
Cosine-similarity semantic search against any OpenAI-compatible endpoint (Ollama, LM Studio, vLLM) — off by default.

How it fits together

One daemon, two transports, one optional resolver

stdio is reserved for MCP agents; a Unix socket serves the GUI and Shell extension — they never compete for the same pipe. LSP enrichment runs only inside an explicit deep reindex.

MCP clients (Claude Code, etc.) nexusd mcp stdio · per-session GUI + Shell ext nexusd serve Unix socket · systemd rust-analyzer spawned on deep reindex only graph.db SQLite, WAL mode CALLS + CALLS_RESOLVED
Storage
SQLite, WAL journal mode
Indexing
Two-pass: per-file, then project-wide call resolution
Enrichment
Optional LSP pass, opt-in, deep reindex only
Concurrency
BEGIN IMMEDIATE + busy_timeout, safe under concurrent reindex
Live sync
Debounced file watcher, warm/cold gated by real usage
Packaging
.deb, .rpm, tarball + hardened user-mode systemd unit

Two review rounds, findings public

Hardened against its own audits, not just designed safe

Every finding below was filed as a GitHub issue before it was fixed, and stayed open until a regression test proved the fix — not just a description of it.

allowed_roots path traversal critical

A raw, not-yet-canonicalized path let .. escape an opt-in directory allowlist. Fixed at the check itself, not just the call sites that found it — so a future caller getting the ordering wrong is still protected.

Markdown OOM path high

A large flat markdown file with no headings could balloon into one untruncated multi-MB chunk during embedding. Routed through the same cap the code path already had.

Decompression-bomb import, data-dir permissions fixed

Team-shareable index import is now streamed and capped at 2GiB with cleanup on any error; every data file is owner-only (0600), directories owner-only (0700) — closing a file-name-listing leak a reviewer caught on top of the file-level fix.

Query batching, panic isolation, O(n²) fixes fixed

Call-graph BFS batched into one query per level instead of one per node; a panic in MCP tool dispatch is now isolated to that one call instead of killing the session; heading-range computation dropped a redundant O(n²) pass.

Full writeup, every issue and PR linked, in the Security Model doc.


Parsing, honestly tiered

11 languages — call-graph quality stated plainly, not smoothed over

Definitions, types, and architecture summaries are solid for all 11. Full call-graph resolution depends on how complete each language's own tree-sitter tagging convention is, so it's shown, not hidden.

Rust
Full call graph
+ LSP resolution
Python
Full call graph
JavaScript
Full call graph
TypeScript / TSX
Full call graph
Go
Full call graph
Java
Full call graph
Ruby
Full call graph
C
Structural only
C++
Structural only
C#
Structural only
PHP
Structural only
Full — functions, types, and call edges all resolve, verified against real multi-file projects Structural only — functions and types are correct; call edges are incomplete or absent in that language's own tagging convention

Get running in a minute

Install, index, ask

Every tier below runs both architectures - native builds, no emulation.

PlatformArchitecturesnexusd mcpnexusd serveGUI
Linux x86_64 · arm64
macOS arm64 (x86_64 via Rosetta 2)
Windows new x86_64 · arm64

Windows doesn't have serve (the control API, background watcher, GUI target) yet - see issue #16. Every MCP tool works fully without it; reindex manually rather than relying on the background watcher.

v0.1.17bash
# build & package
cargo build --release
cargo deb -p nexusd --no-build
sudo dpkg -i target/debian/nexuscontext_*.deb

# run the daemon persistently
systemctl --user enable --now nexuscontext.service

# index a project, try LSP-resolved calls (Rust, opt-in)
nexus reindex /path/to/your/project --deep
nexus search-graph SomeFunction --project /path/to/your/project

# auto-configure Claude Code / Claude Desktop
nexus install

Prefer a prebuilt binary? Grab a .deb, .rpm, or .tar.gz for Linux/macOS, or a .zip for Windows, for either architecture, from the latest release instead. Full walkthrough — GUI, GNOME extension, config, packaging — in INSTALL.md.