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:
| Benefit | What it means for you |
|---|---|
| Fewer tokens | Instead 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 guessed | Deterministic graph with stable IDs. |
| Trustworthy | Every edge carries provenance: a confidence_tier (heuristic/derived/confirmed) + reason + evidence (file:line). Only Go reaches confirmed; Preview languages stay heuristic. |
| Fresh | Incremental 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-first | Not a byte leaves the machine: zero outbound network traffic, no telemetry, CGo-free, a single binary. |
02Installation & build
Option A — prebuilt binary (fastest)
# Linux/macOS – checksum-verified, no sudo, into ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/samibel/graphi/main/install.sh | sh# Windows (PowerShell)
iwr -useb https://raw.githubusercontent.com/samibel/graphi/main/install.ps1 | iexOption 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).
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 dategraphi 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:
# 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.sh03Core 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).
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
mkdir -p ~/.graphi
graphi index -root . -db ~/.graphi/graph.dbThis creates a persistent SQLite store (graph.db) that every further query reads from.
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:
graphi search -db ~/.graphi/graph.db -limit 8 OwnerController4.3 Structural queries (query <op>)
# 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 1There are also the type-oriented ops: implementers, implements, overrides, subtypes, supertypes — ideal for Java interfaces/inheritance.
4.4 Analysis (analyze <analyzer>)
# 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)
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.sock05Real example: Spring Boot project (PetClinic)
All outputs below come from a real run against Spring PetClinic (48 Java files, classic controller/repository/entity structure).
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
git clone --depth 1 https://github.com/spring-projects/spring-petclinic.git
graphi index -root ./spring-petclinic -db /tmp/petclinic.dbgraphi: 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-petclinicStep 2 — find a controller
graphi search -db /tmp/petclinic.db -limit 8 OwnerControllerAbbreviated output (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?”
graphi query callers -db /tmp/petclinic.db -symbol 057c32558eb28540{
"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 getPet — with evidence (Owner.java:169) and confidence tier derived. No file reading, no guessing.
Step 4 — neighborhood with a confirmed edge
graphi query neighborhood -db /tmp/petclinic.db -symbol 3bcd1cf3c507e981 -depth 1Excerpt: 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
# 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 visibleThe 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
graphi mcp -db ~/.graphi/graph.dbThe handshake follows the MCP standard. Real initialize response:
{"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_commentand 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 agent | Which tool fires | Why 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 concept | Lands directly on the right spot |
| “Is there a path from an input source to a dangerous sink?” | analyze_taint | Flow-sensitive source→sink paths |
| “How risky is this diff?” | analyze_pr_risk / analyze_pr_signals | Risk-scored diff + signals |
“Rename price to cost — across all call sites” | refactor_preview → refactor → undo | Atomic saga with rollback |
| “I’m new to this repo — where do I start?” | repo_overview labs | Structure, languages, entry points and central symbols in one call |
| “Which tests must I run for this diff?” | test_impact labs | Must-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 labs | Dependents, covering tests, co-change partners (“B usually changes with A”) and a risk level |
| “Where does this repository hurt?” | hotspots labs | Churn × dependency centrality with bus-factor warnings |
| “Does the intended layering match reality?” | architecture labs | Louvain communities layered by dependency direction — then architecture_violations for cycles and back-edges |
| “What can I safely delete?” | dead_code labs | Scored candidates with visible exclusions — entry points and exported API are never silently flagged |
| “What are this service’s endpoints and listeners?” | framework_map labs | Routes, 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
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 = falseis set and zero savings are reported. Negative savings (graphi used more) are reported raw, not hidden. - Anti-gaming cap:
engine/capcaps per op and per session; an outlier can’t inflate the headline. An applied cap is transparently marked withCapApplied.
7.2 Price table (engine/price/data/prices.json, version prices-v1)
| Model | Input (micro-USD/token) | Output (micro-USD/token) |
|---|---|---|
| gpt-4o | 2500 | 10000 |
| gpt-4o-mini | 150 | 600 |
| claude-sonnet | 3000 | 15000 |
| claude-haiku | 250 | 1250 |
(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:
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:
| Tier | Meaning | Example 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 file | calls edge addVisit → getPet (Owner.java:169) |
heuristic | File/line evidence, but cross-file resolved heuristically | most 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:
# 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{"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):
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.
# 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/metagraphi 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_onnxand 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.
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 nocallers/referencesedges, because the call goes through a dynamic proxy. graphi then honestly reportsoutcome: "empty"instead of guessing. → For DI/proxy-heavy calls, query the concrete implementation methods. - Cross-file resolution is
heuristicfor non-Go: for Java/TS/Python etc., cross-file edges are heuristic (with evidence), neverconfirmed. 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, andgraphi compare <base> <head>diffs two names (the reservedcurrentmeans the live graph) — so check out each branch, snapshot it, then compare. The raw formcompare-branches -base/-headtakes explicit SQLite paths and never resolvesmain/featurefrom git itself. safe-deleteonly 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 thegit-history/pr-signals/suggest-reviewersanalyzers read a bounded window of the localgit 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 -semanticreturns 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):
- Once per repo:
cdinto the repo and rungraphi 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.) - Wire up agents:
graphi setup --client claude(orall), restart claude. - Before every refactor: have the agent run
callers+analyze impact -direction reverseon the target symbol → blast radius with evidence. - Understand unfamiliar code:
search→neighborhood→analyze concept. - For DI/proxy code: query concrete implementations instead of interface methods.
- Keep it fresh:
graphi syncafter a branch switch (it detects the switch and re-processes only the difference);graphi statustells you whether anything is stale. For continuous use, start the daemon. - Prove the value: check
graphi savingsregularly — it makes the token savings visible. - Prove local-first (e.g. for compliance):
graphi privacy-audit.
12Quick reference (cheat sheet)
# 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/metaSources
- 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.