Hands-on tutorial · every output from real runs

From install to productive — step by step.

Local-first code-intelligence engine for AI agents and developers. CLI usage, MCP integration in Claude Code, a real Spring Boot example (Spring PetClinic), measuring token savings and optional semantic search — walked through against a real repo, not from memory.

Apache-2.0 Spring PetClinic · 48 Java files CLI · MCP · Metering

01What graphi is and why it pays off

An AI coding agent that greps half the repo and re-reads whole files on every question is slow, expensive (tokens) and guesses. graphi indexes the repo once into a graph — symbols (functions, types, files) as nodes, relationships (calls, references, defines, imports) as edges — and then answers questions like “who calls this”, “what breaks if I change it”, “how are these two functions connected” in one targeted lookup, entirely on your machine.

The five concrete benefits:

BenefitWhat it means for you
Fewer tokensInstead of reading whole files, only the relevant symbol + evidence comes back. graphi meters this per session and keeps a USD savings ledger you can read back — we publish no headline savings figure, because the ratio depends on your repo and your questions.
Exact, not guessedDeterministic graph with stable IDs.
TrustworthyEvery edge carries provenance: a confidence_tier (heuristic/derived/confirmed) + reason + evidence (file:line). Only Go reaches confirmed; Preview languages stay heuristic.
FreshIncremental re-indexing keeps the graph current as you edit; an optional hot daemon (Labs) keeps it resident. Index and query timings depend on your repository — the only published numbers are the fixture baselines in bench/bench-budget.yml.
Local-firstNot a byte leaves the machine: zero outbound network traffic, no telemetry, CGo-free, a single binary.

02Installation & build

Option A — prebuilt binary (fastest)

bash
# Linux/macOS – checksum-verified, no sudo, into ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/samibel/graphi/main/install.sh | sh
powershell
# Windows (PowerShell)
iwr -useb https://raw.githubusercontent.com/samibel/graphi/main/install.ps1 | iex

Option B — build from source (often the better fit for you as a developer)

Prerequisite: Go 1.26+ (no C toolchain needed — the default build is CGo-free).

bash
git clone https://github.com/samibel/graphi.git
cd graphi

# CGo-free build of just the CLI
CGO_ENABLED=0 go build -o graphi ./cmd/graphi

# optional: put it on your PATH
install -m755 graphi ~/.local/bin/    # or: sudo mv graphi /usr/local/bin/

graphi version   # check version/commit/build date
In practice

graphi uses a Go workspace (go.work). When building from source, do not override GOFLAGS, and set export GOTOOLCHAIN=auto if needed so the right Go version is pulled.

Optional flavors:

bash
# Broad language coverage (257 grammars, CGO, trusted sources only!)
CGO_ENABLED=1 go build -tags graphi_broad -o graphi-broad ./cmd/graphi

# With the embedded web UI
scripts/build-release-webui.sh

03Core concepts in 60 seconds

  • Code graph — repository → nodes (functions, types, files) + edges (calls, references, defines, imports), with deterministic IDs.
  • Provenance — every edge has a confidence tier (heuristic / derived / confirmed), a reason and evidence (file:line). So you can trust each relationship instead of guessing.
  • One engine, many surfaces — CLI, Unix-socket daemon, MCP-stdio server, loopback HTTP/SSE, web UI and VS Code extension all answer from the same engine → answers are byte-identical and can never drift apart.
  • Local-first — zero outbound network traffic, no telemetry, loopback-only. Provable with graphi privacy-audit.

Language coverage (default tier, CGo-free): Go, TypeScript/TSX/JSX/JavaScript, Python, Java, Kotlin, C#, Ruby, PHP, Lua, C, C++, Rust, Bash, SQL plus JSON/CSS/YAML/TOML/Markdown/HCL (the latter intra-file only).

Tiers

Go is GA, everything else is Preview. Go is the only language inside graphi's GA promise, and the only one that gets type-checker-confirmed edges via go/types. Every other language above — including the Java used in this tutorial's Spring Boot example — is Preview: it ships, it runs the same GA operations, and it resolves cross-file references at the heuristic tier with file:line evidence, but it is outside the GA promise and its accuracy is unproven. Preview is a real capability, not a stub — but it is not something we stand behind. See docs/stability-tiers.md.

04CLI usage — step by step

4.1 Index the repo

bash
mkdir -p ~/.graphi
graphi index -root . -db ~/.graphi/graph.db

This creates a persistent SQLite store (graph.db) that every further query reads from.

Everyday

Outside this tutorial you don't need any of these flags: graphi sync keeps an auto-managed per-repo store (~/.graphi/<fingerprint>/db.sqlite) matching whatever is checked out — run it after a branch switch, check freshness with graphi status, and force a clean pass with graphi rebuild. Queries run from inside the repo discover that store automatically. This tutorial passes an explicit -db so every step names its store and works from any directory. One thing to know: with no -root, sync binds the nearest enclosing .git/go.work/go.mod root above your current directory and announces it on stderr before indexing — run it from the project you mean, or pass -root. If an older graphi (< v0.6.1) ever exhausted your machine's memory while indexing, re-run the install script and check graphi version: ingest memory is now bounded by the worker pool, not the repo size.

4.2 Find symbols (search)

Search gives you the node_id that every structural query expects as -symbol:

bash
graphi search -db ~/.graphi/graph.db -limit 8 OwnerController

4.3 Structural queries (query <op>)

bash
# Who calls this symbol?
graphi query callers      -db ~/.graphi/graph.db -symbol <node_id>

# What does it call itself?
graphi query callees      -db ~/.graphi/graph.db -symbol <node_id>

# Where is it referenced?
graphi query references   -db ~/.graphi/graph.db -symbol <node_id>

# Where is it defined?
graphi query definition   -db ~/.graphi/graph.db -symbol <node_id>

# Neighborhood (with -depth N, capped at 5)
graphi query neighborhood -db ~/.graphi/graph.db -symbol <node_id> -depth 1

There are also the type-oriented ops: implementers, implements, overrides, subtypes, supertypes — ideal for Java interfaces/inheritance.

4.4 Analysis (analyze <analyzer>)

bash
# Blast radius: what depends on this symbol? (reverse = dependents)
graphi analyze impact -db ~/.graphi/graph.db -symbol <node_id> -direction reverse

# Call path between two symbols
graphi analyze call-chain -db ~/.graphi/graph.db -symbol <caller_id> -target <callee_id>

# Map a natural-language concept onto graph locations
graphi analyze concept -db ~/.graphi/graph.db -symbol <root_id> -concept "rate limiting"

# Graph metrics: hubs, bridges, high centrality
graphi analyze metrics -db ~/.graphi/graph.db -symbol <node_id>

More analyzers: taint, pdg, interproc, contracts, git-history, batched (impact + call-chain + metrics in one).

4.5 Hot daemon (for fast, repeated queries)

bash
graphi daemon start -socket /tmp/graphi.sock -db ~/.graphi/graph.db
graphi query callers -daemon /tmp/graphi.sock -symbol <node_id>
graphi daemon stop -socket /tmp/graphi.sock

05Real example: Spring Boot project (PetClinic)

All outputs below come from a real run against Spring PetClinic (48 Java files, classic controller/repository/entity structure).

Preview

This example runs on Preview, not GA. Java is a Preview language: the GA operations work on it, but its edges are heuristic-tier only (never confirmed), unresolved or ambiguous references are dropped rather than guessed, and its accuracy is unproven. Go is the only GA language. This example is here because Spring Boot is a realistic shape to explore — not because Java carries the GA promise.

Step 1 — index

bash
git clone --depth 1 https://github.com/spring-projects/spring-petclinic.git
graphi index -root ./spring-petclinic -db /tmp/petclinic.db
output
graphi: scanning repo…
graphi: indexing 128 files…
graphi: indexing… 100% (128/128)
graphi: linking cross-file references…
graphi: resolving types…
graphi: indexed 128 files in 30.5s
graphi index: ingested ./spring-petclinic

Step 2 — find a controller

bash
graphi search -db /tmp/petclinic.db -limit 8 OwnerController

Abbreviated output (JSON):

json
{"query":"OwnerController","matches":[
  {"node_id":"40631158f9245d47","kind":"type",
   "qualified_name":"owner.OwnerController",
   "source_path":".../owner/OwnerController.java","line":49},
  {"node_id":"48deb92bf1ca3194","kind":"type",
   "qualified_name":"owner.OwnerControllerTests","line":61}
]}

graphi cleanly separates the production class from the test class and gives you file + line directly.

Step 3 — blast radius: “who calls Owner.getPet?”

bash
graphi query callers -db /tmp/petclinic.db -symbol 057c32558eb28540
json
{
  "operation": "callers",
  "outcome": "found",
  "nodes": [
    {"id":"057c32558eb28540","kind":"method","qualified_name":"owner.getPet",
     "source_path":".../owner/Owner.java","line":108},
    {"id":"0b3b441c0d5adf92","kind":"method","qualified_name":"owner.addVisit",
     "source_path":".../owner/Owner.java","line":164}
  ],
  "edges": [
    {"from":"0b3b441c0d5adf92","to":"057c32558eb28540","kind":"calls",
     "confidence_tier":"derived","confidence":0.9,
     "reason":"call resolved to an in-file definition",
     "evidence":["src/main/java/.../owner/Owner.java:169"]}
  ]
}

That is the core value: in one call you know that addVisit calls getPetwith evidence (Owner.java:169) and confidence tier derived. No file reading, no guessing.

Step 4 — neighborhood with a confirmed edge

bash
graphi query neighborhood -db /tmp/petclinic.db -symbol 3bcd1cf3c507e981 -depth 1

Excerpt: the defines edge from OwnerRepository.java to findByLastNameStartingWith is confidence_tier: "confirmed" (confidence 1.0) with evidence OwnerRepository.java:45. “Defined in file” is provable — hence the highest tier.

06MCP integration in Claude Code & other agents

graphi talks to agents over MCP (stdio, JSON-RPC). That turns “the agent reads through the repo” into “the agent asks the graph”.

6.1 Setup in one command

bash
# 1) prime the graph (optional — an MCP session syncs the repo's
#    auto-managed store on start anyway; this just makes it instant)
cd your-repo && graphi sync

# 2) register graphi with every detected local MCP client
graphi setup
#   Default --client all: Claude Code, Copilot, Cursor, Devin CLI, Windsurf, Claude Desktop
#   Claude Code only:  graphi setup --client claude
#   Dry run (no writes):  graphi setup --dry-run

# 3) restart claude – graphi's tools are now visible

The setup command writes the stdio MCP entry idempotently, atomically and offline into the client config (for Claude Code, e.g. ~/.claude.json).

6.2 Manual, for any MCP client

bash
graphi mcp -db ~/.graphi/graph.db

The handshake follows the MCP standard. Real initialize response:

json
{"jsonrpc":"2.0","id":1,"result":{
  "capabilities":{"tools":{}},
  "protocolVersion":"2024-11-05",
  "serverInfo":{"name":"graphi-query","version":"1"}}}

And tools/list returns, among others, callers, callees, references, definition, neighborhood, implementers, implements, overrides, subtypes, supertypes, search — each with a JSON schema that expects symbol (the node_id).

6.3 The toolbox the agent gets

All tools are read-only by default. By default the MCP server advertises only the 11 GA tools below — everything marked [labs] requires an explicit graphi mcp -labs and is not part of the GA promise. Labs tool descriptions carry a [labs] prefix at runtime; tool names never do. Tier definitions: docs/stability-tiers.md.

  • Structure (GA): callers, callees, references, definition, neighborhood
  • Context & risk (GA): agent_brief, related_files, explain_symbol, change_risk, impact
  • Search (GA): search (lexical / symbol)
  • Type hierarchy [labs]: implementers, implements, overrides, subtypes, supertypes
  • Search extras [labs]: search_semantic, search_hybrid (embedding-free multi-token ranking), compound (Cypher-like)
  • Patterns [labs]: search_ast, find_clones
  • Analysis [labs]: analyze (the generic selector), analyze_taint, analyze_pdg, analyze_interproc, analyze_contracts, analyze_githistory
  • PR review [labs]: analyze_pr_risk, triage_prs, suggest_reviewers, compare_branches, critique_review, pr_comment and more
  • Edit (opt-in) & readout [labs]: refactor_preview, refactor, undo, savings
  • Agent intelligence [labs]: symbol_context (one-call symbol view incl. snippet, tests, risk), task_context (free-text task → ranked, token-budgeted bundle), repo_overview (one-call repository summary)
  • Test & change intelligence [labs]: test_impact (must-run / recommended / probably-unaffected test buckets for a diff), change_impact (Change Risk 2.0 incl. co-change partners)
  • Git intelligence [labs]: hotspots (churn × dependency centrality with bus-factor warnings)
  • Architecture & dead-code intelligence [labs]: architecture (community/layer view: Louvain + dependency direction), architecture_violations (cycles, back-edges, high coupling, god modules), dead_code (scored candidates with exclusion reasons), framework_map (routes, events, DI from recorded annotations)
  • Trust [labs]: graph_health, strict_query
  • Memory & skills [labs]: memory, distill, skillgen

6.4 Typical agent prompts (applied to a repo)

What you tell the agentWhich tool firesWhy it helps
“I want to rework IngestAll. What depends on it?”callers + analyze impact (reverse)All dependent symbols with evidence, without reading half the repo
“Where is X handled?”search + neighborhood + analyze conceptLands directly on the right spot
“Is there a path from an input source to a dangerous sink?”analyze_taintFlow-sensitive source→sink paths
“How risky is this diff?”analyze_pr_risk / analyze_pr_signalsRisk-scored diff + signals
“Rename price to cost — across all call sites”refactor_previewrefactorundoAtomic saga with rollback
“I’m new to this repo — where do I start?”repo_overview labsStructure, languages, entry points and central symbols in one call
“Which tests must I run for this diff?”test_impact labsMust-run / recommended buckets with call-edge evidence — 7 tests instead of the whole suite
“What am I about to break — and what did I forget?”change_impact labsDependents, covering tests, co-change partners (“B usually changes with A”) and a risk level
“Where does this repository hurt?”hotspots labsChurn × dependency centrality with bus-factor warnings
“Does the intended layering match reality?”architecture labsLouvain communities layered by dependency direction — then architecture_violations for cycles and back-edges
“What can I safely delete?”dead_code labsScored candidates with visible exclusions — entry points and exported API are never silently flagged
“What are this service’s endpoints and listeners?”framework_map labsRoutes, event handlers and DI wiring derived from recorded framework annotations

07Measuring token savings (metering & pricing)

graphi measures, per call, how many tokens it saved versus the “read whole files” baseline, prices it with an embedded price table (no network), and keeps a durable ledger — even across daemon restarts.

7.1 The chain

flow
meter.Record → price.Savings → cap.Apply → ledger.RecordCapped → Ledger.Readout
  • Baseline (frozen, versioned): whole-file-read-v1. The baseline value is a pure function of (artifacts, file bytes) and the version. Older records stay tied to their method — no silent recomputation.
  • Honest, not embellished: if a baseline can’t be determined honestly (empty artifacts), BaselineAvailable = false is set and zero savings are reported. Negative savings (graphi used more) are reported raw, not hidden.
  • Anti-gaming cap: engine/cap caps per op and per session; an outlier can’t inflate the headline. An applied cap is transparently marked with CapApplied.

7.2 Price table (engine/price/data/prices.json, version prices-v1)

ModelInput (micro-USD/token)Output (micro-USD/token)
gpt-4o250010000
gpt-4o-mini150600
claude-sonnet300015000
claude-haiku2501250

(1e6 micro-USD = 1 USD. The calculation is exact integer multiplication, no float rounding.)

7.3 View the readout

After an MCP/daemon session that wrote a ledger:

bash
graphi savings -ledger <path>
# →  ⚡  Saved $0.42 this session  (cumulative $3.10)

MCP and CLI read the same canonical readout — the numbers are byte-identical.

7.4 Your own benchmark (like the bundled report)

Want to prove the savings for your own realistic agent questions? Compare WITH graphi (tokens of the returned context bundle) against WITHOUT graphi (the whole-file-read equivalent of the files an agent would otherwise open), using graphi’s own engine/meter (whole-file-read-v1) and engine/price (prices-v1). Exclude empty-result queries honestly.

08Understanding provenance — why you can trust the answers

Every edge carries a confidence tier:

TierMeaningExample from PetClinic
confirmed (1.0)Provable (e.g. type checker or “defined in file”)defines edge OwnerRepository.java → findByLastNameStartingWith
derived (~0.9)Safely resolved within a single filecalls edge addVisit → getPet (Owner.java:169)
heuristicFile/line evidence, but cross-file resolved heuristicallymost cross-file calls/imports

Important: graphi never invents an edge. Unresolvable or ambiguous references are deterministically dropped and counted (“skip+count”), never fabricated. For Go, the stdlib go/types checker additionally runs and lifts proven edges to confirmed.

09Semantic search (optional, off by default)

Beside the lexical search, graphi can also search embedding-based — by meaning instead of exact tokens (e.g. “where do we validate auth tokens?”). This is deliberately an opt-in feature and disabled in the standard binary: no embedder shipped, CGo-free, zero non-loopback network calls.

Behavior without an embedder (default) — an honest graceful skip

Without a configured embedder nothing is ever missing and nothing crashes — you get a typed “not available” response. This is exactly how it behaves in a real run:

bash
# Instructions to enable it (text only, changes nothing, no network):
graphi setup-embedder

# Semantic search without an embedder → typed unavailable response, NO error:
graphi search -semantic "where do we validate auth tokens" -db ~/.graphi/graph.db
json
{"query":"where do we validate auth tokens","available":false,
 "reason":"no embedder configured; run `graphi setup-embedder ...`","hits":[]}

And indexing with --semantic without an embedder runs the lexical indexing normally — only the embedding step cleanly reports “unavailable” (real PetClinic run, 128 files):

output
graphi: indexed 128 files in 30.4s
graphi index: ingested .../spring-petclinic
graphi index --semantic: unavailable — no embedder configured; run `graphi setup-embedder ...`

This unavailable response comes from one engine-owned type (engine/search.SemanticResponse) and is byte-identical across CLI, MCP and HTTP — the surfaces can never diverge.

Enabling it — two ways

You opt in via the GRAPHI_EMBEDDER environment variable and then re-index with embeddings. Important: index and search must share the same -db and -meta sidecar so the generated vectors survive between calls.

bash
# Option A — Ollama (loopback only, opt-in). Needs a local Ollama daemon.
export GRAPHI_EMBEDDER=ollama                 # default 127.0.0.1:11434
# or pin the endpoint explicitly:
export GRAPHI_EMBEDDER=ollama:127.0.0.1:11434

# Option B — ONNX (local, CGO). Needs a build with the embed_onnx tag:
#   go build -tags embed_onnx ./cmd/graphi
export GRAPHI_EMBEDDER=onnx:/path/to/model.onnx

# Then embed the graph and query it (shared store + meta sidecar!):
mkdir -p ~/.graphi
graphi index --semantic -root ./my-repo -db ~/.graphi/graph.db -meta ~/.graphi/meta
graphi search -semantic "where do we validate auth tokens" -db ~/.graphi/graph.db -meta ~/.graphi/meta

graphi index --semantic embeds every node (key = node_id) and writes the vectors into a durable vectors table in the -meta sidecar, tagged with embedder identity + dimension. graphi search -semantic reloads those vectors on startup — a pure local read, no re-embedding, no embedder dial — and returns cosine-ranked hits with node_id + score.

Safety guarantees (hold regardless of configuration)

  • Ollama is loopback-only and fail-closed: a non-loopback host is rejected at construction time (plus a runtime canary as defense-in-depth). On the default path it is never constructed.
  • ONNX (CGO) is build-tag-gated behind //go:build embed_onnx and provably absent from the default binary (verified by import-graph scan + no-CGO guard).
  • Brute-force cosine over an in-memory index is a deliberate choice for this first cut; HNSW/ANN indexing is planned as a follow-up.
In practice

No Ollama daemon was available in this test environment, so the enabled embedding path could not be walked through live. What is verified and shown above is the real graceful-skip behavior without an embedder — exactly the default case.

10Limits & pitfalls (honest)

From the real PetClinic run and the docs:

  • Spring Data proxy methods: interface methods like findByLastNameStartingWith (which Spring implements at runtime) often have no callers/references edges, because the call goes through a dynamic proxy. graphi then honestly reports outcome: "empty" instead of guessing. → For DI/proxy-heavy calls, query the concrete implementation methods.
  • Cross-file resolution is heuristic for non-Go: for Java/TS/Python etc., cross-file edges are heuristic (with evidence), never confirmed. Always read the confidence tier along with it.
  • Branch comparison works over frozen states, not git refs: graphi snapshot <name> freezes the currently checked-out code under a name, and graphi compare <base> <head> diffs two names (the reserved current means the live graph) — so check out each branch, snapshot it, then compare. The raw form compare-branches -base/-head takes explicit SQLite paths and never resolves main/feature from git itself.
  • safe-delete only removes the declaration line: for multi-line bodies, check the diff.
  • graphi-broad (CGO) is not memory-isolated: for trusted/CI sources only. A C-grammar crash isn’t caught by Go’s safety mechanisms.
  • Git-derived signals need local history: hotspots, change_impact’s co-change section and the git-history/pr-signals/suggest-reviewers analyzers read a bounded window of the local git log (surface boundary only). Outside a git repository or in attach mode (-db) they return a typed unavailable/empty outcome instead of guessing.
  • Semantic search is off by default: without a configured embedder, search -semantic returns a typed “unavailable” response (no error, no network). Details and enabling in section 9.

11Recommended workflow for everyday use

For your context (Spring Boot services, deep code analysis, MCP, repo comparisons):

  1. Once per repo: cd into the repo and run graphi sync — it builds and maintains the auto-managed store that flagless queries and MCP sessions discover. (Explicit form: graphi index -root . -db ~/.graphi/<repo>.db.)
  2. Wire up agents: graphi setup --client claude (or all), restart claude.
  3. Before every refactor: have the agent run callers + analyze impact -direction reverse on the target symbol → blast radius with evidence.
  4. Understand unfamiliar code: searchneighborhoodanalyze concept.
  5. For DI/proxy code: query concrete implementations instead of interface methods.
  6. Keep it fresh: graphi sync after a branch switch (it detects the switch and re-processes only the difference); graphi status tells you whether anything is stale. For continuous use, start the daemon.
  7. Prove the value: check graphi savings regularly — it makes the token savings visible.
  8. Prove local-first (e.g. for compliance): graphi privacy-audit.

12Quick reference (cheat sheet)

bash
# BUILD
CGO_ENABLED=0 go build -o graphi ./cmd/graphi

# KEEP THE GRAPH CURRENT (auto-managed per-repo store; run inside the repo)
graphi sync        # incremental update — run after a branch switch
graphi status      # is the graph current? exit 0 = yes, 1 = run sync (--json)
graphi rebuild     # full re-index from scratch

# FREEZE + DIFF BRANCH STATES (labs)
graphi snapshot main            # freeze the current checkout under a name
graphi compare main current     # diff a snapshot against the live graph

# INDEX (explicit paths — advanced form of sync/rebuild)
graphi index -root . -db ~/.graphi/graph.db

# SEARCH (returns node_id)
graphi search -db ~/.graphi/graph.db -limit 8 <term>

# STRUCTURE
graphi query callers|callees|references|definition|neighborhood \
  -db ~/.graphi/graph.db -symbol <node_id> [-depth N]
graphi query implementers|implements|overrides|subtypes|supertypes \
  -db ~/.graphi/graph.db -symbol <node_id>

# ANALYSIS
graphi analyze impact     -db ... -symbol <id> -direction reverse|forward
graphi analyze call-chain -db ... -symbol <id> -target <id>
graphi analyze concept    -db ... -symbol <id> -concept "..."
graphi analyze metrics|taint|pdg|interproc|contracts|git-history|batched -db ... -symbol <id>

# AGENT / TEST / CHANGE / GIT INTELLIGENCE (labs)
graphi symbol-context <symbol>                    # one-call symbol view
graphi task-context "add rate limiting"           # task → ranked context bundle
graphi repo-overview [-communities]               # one-call repository summary
git diff HEAD~1..HEAD | graphi test-impact -diff -    # which tests must run
git diff HEAD~1..HEAD | graphi change-impact -diff -  # Change Risk 2.0
graphi hotspots [-max-commits n]                  # churn × centrality ranking

# DAEMON (fast repeated queries)
graphi daemon start -socket /tmp/graphi.sock -db ~/.graphi/graph.db
graphi query callers -daemon /tmp/graphi.sock -symbol <id>
graphi daemon stop  -socket /tmp/graphi.sock

# MCP / AGENTS
graphi setup [--client claude|copilot|cursor|devin|windsurf|claude-desktop|all] [--dry-run]
graphi mcp -db ~/.graphi/graph.db      # manual, for any MCP client

# OTHER SURFACES
graphi ui                              # web UI + browser
graphi http -addr 127.0.0.1:8080 -db ~/.graphi/graph.db -root .

# SAVINGS & TRUST
graphi savings -ledger <path>
graphi privacy-audit

# SEMANTIC SEARCH (opt-in)
graphi setup-embedder
export GRAPHI_EMBEDDER=ollama:127.0.0.1:11434
graphi index  --semantic -root . -db ~/.graphi/graph.db -meta ~/.graphi/meta
graphi search -semantic  "where do we validate auth tokens" -db ~/.graphi/graph.db -meta ~/.graphi/meta

Sources

  • graphi README & docs: github.com/samibel/graphi (readme.md, docs/HOWTO.md, docs/tutorial/graphi-with-claude-cli.md, docs/meter/metering.md, docs/price/pricing.md, docs/savings/cap-readout.md)
  • Landing page: samibel.github.io/graphi
  • Example repo: Spring PetClinic — github.com/spring-projects/spring-petclinic
  • All command outputs in sections 5, 6 & 9 come from real runs of graphi against Spring PetClinic (the semantic outputs show the default case without an embedder).

Ready? Install graphi and index your first repo.