Structural code intelligence, locally on your machine.

9 tools for navigating and searching your code — computed locally from your own repositories.

JARVIS gives your coding agent go-to-definition, find-references, call and type hierarchy, and semantic search across your own code. Everything runs on your machine — nothing is uploaded.

Installs SCIP, Zoekt, and language indexers into ~/.jarvis/bin

MIT licensed macOS / Linux open source

See it in action

Try before you install

Three real scenarios — pick a question, see the MCP call and the recorded result.

getIndexStatus(repo="toy-repo") Recorded result
{
  "repo": "toy-repo"
}
{
  "repo": "toy-repo",
  "indexed": true,
  "status": "indexed",
  "commit": "abc1234",
  "generated_at": "2026-07-08T12:00:00+00:00",
  "stale": false,
  "freshness": "fresh",
  "checked_at": "2026-07-08T12:00:05+00:00",
  "searchCoverage": {
    "expected": 120,
    "indexed": 120,
    "complete": true
  },
  "last_index_run": {
    "outcome": "indexed",
    "origin": "signature",
    "reason": null,
    "recovery": null
  },
  "capabilities": {
    "navigation": {
      "available": true,
      "reason": null,
      "recovery": null
    },
    "search": {
      "available": true,
      "reason": null
    },
    "semantic": {
      "available": false,
      "reason": "semantic index not built for this repo (requires the `semantic` extra)"
    }
  }
}
1 / 3

Tools

9 tools, honestly tiered

7 core tools work out of the box. Two advanced tools require extra setup.

getIndexStatus

Index status

Check whether a repo is indexed, how fresh it is, and which capabilities are available.

goToDefinition

Go to definition

Jump to where a symbol is defined — resolved via SCIP's precise AST.

findReferences

Find references

List every occurrence of a symbol across the codebase, definition included.

callHierarchy

Call hierarchy

Walk callers and callees of a function — single-level, bidirectional.

documentSymbols

Document symbols

List every top-level symbol defined in a file with its range.

searchCode

Search code

Lexical search via an embedded Zoekt index — fast, precise, always available.

blastRadius

Blast radius

2-hop bounded BFS over the package dependency graph to scope change impact.

Languages

Four families get navigation

TypeScript, Python, Java/Kotlin, and Swift. Everything else gets search only.

Language Navigation Caveat
TypeScript / TSX✅ Yes—
Python✅ Yes—
Java / Kotlin ✅ Yes Android/Gradle, Kotlin version, Maven on macOS
Swift ✅ Yes Version floor + code-signed targets
Go——
Ruby——
Rust——
C——
C++——
C#——
PHP——
Scala——
shell——
SQL——

Privacy

Local-first. Nothing leaves your machine.

All computation is local. No telemetry, no network, no cloud.

Zero telemetry. jarvis phones home to exactly zero endpoints. No usage data, no error reports, no analytics. The server process connects to nothing outside your filesystem.

Zero cloud. Every index, every search, every hierarchy walk is computed on your machine from your own git-tracked source. There is no jarvis API, no jarvis account, and no jarvis server that sees your code.

Zero network at runtime. After the one-time install, jarvis needs no network. The MCP server listens on a local stdio pipe. Your code never leaves your machine.

Architecture

Seven layers, two halves, one seam

The runtime half reads storage to answer your queries. The indexing half writes storage when you build or update an index. The seam between them is the only shared state — and it flips atomically.

jarvis 7-layer architecture — runtime half, storage seam, indexing half Seven layers split into a runtime half (clients, MCP server, engines) that reads storage, and an indexing half (orchestration, language indexers, external toolchain) that writes storage. L4 is the storage seam between them. RUNTIME HALF (reads storage, never writes) L1 · Clients Claude Code · Cursor · any MCP host L2 · MCP Server server.py — FastMCP stdio, 9 tools L3 · Engines query.py · search.py · graph.py · semantic.py reads (mode=ro) L4 · STORAGE (the seam) index-<sha>.db + current pointer · .zoekt/ shards · registry.db · lancedb/ writes (atomic os.replace) INDEXING HALF (writes storage, never reads on query path) L5 · Indexing orchestration index_cli.py — detect → index → convert → graph+zoekt → atomic publish L6 · Language indexers scip-typescript · scip-python · scip-java · scip-swift L7 · External toolchain Node/npm · Python · JDK · (Swift) Xcode + iOS SDK

The storage seam (L4) is the only shared state. The runtime half reads it; the indexing half writes it atomically.

jarvis index pipeline — two publish modes with failure semantics Preflight checks feed a publish-mode diamond. Full mode runs SCIP + search indexing then atomically publishes. Search-only mode skips SCIP. Any error leaves the previous index live (no half-published state). PREFLIGHT (index_cli.index_repo) P1 resolve path + slug · git HEAD sha P2 one-slug-per-path gate · scip >= 0.9.0 check P3 resolve sticky flags (search_only · language · scheme · semantic_include) publish mode? full search-only FULL (SCIP + search) F1 scip-* indexer → index.scip F2 scip expt-convert → index.db (scratch) F3 populate_graph_for_repo → registry.db F4 zoekt-git-index (HEAD · coverage warn) F5 semantic stage (optional, NON-FATAL) F6 ATOMIC PUBLISH — os.replace() pointer flip SEARCH-ONLY S1 retire prior SCIP artifacts S2 zoekt-git-index + semantic stage OK status: indexed SO status: search-only FAIL previous index stays live any error known-unfixable

Any step that raises leaves the previous index live — the pointer is never touched until the new version is fully ready.