v0.1.19 · 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. Purely structural — no embeddings, no vector store.

12
MCP tools
11
Languages parsed
0
Network calls 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, no embeddings layer at all.

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 12 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

No outbound network calls of any kind. 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%

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

12 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 opt-in grouped mode: directory-based node/edge grouping with cross-group edge counts — structural, not a guess at which directory is "the API layer."
Search & trace
search_graph
Structural search over indexed symbols by name substring.
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 affect, plus an opt-in blast_radius mode: walks direct and transitive callers of each changed symbol, so an agent can see the real impact before editing, not just what moved.
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.

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

Multiple 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. A follow-up audit then found the check wasn't wired into every repo_path-accepting tool yet — it now covers all of them, with symlink-escape and confused-deputy adversarial tests to prove it.

Markdown OOM path high

A large flat markdown file with no headings could balloon into one untruncated multi-MB chunk at indexing time. Routed through the same content-size 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.

Resource bounds on repo-size-dependent work fixed

A bounded watcher event channel, a capped traversal depth, a per-file indexable-size ceiling, and a cooperative graph-query timeout — so a pathological repo or query can't hang or OOM the daemon, with live RSS/queue-depth observability to see the pressure, not just trust the cap.

Symlink-substitution TOCTOU, defense-in-depth fixed

O_NOFOLLOW on both filesystem-read hot paths closes the cheapest symlink-swap race between the allowlist check and the actual read. Stated plainly, not oversold: this is defense-in-depth, not full TOCTOU-proofing — see the Security Model doc for the exact gap that remains.

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.19bash
# 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.