Hybrid semantic search
Dense 384-dimension FastEmbed vectors fused with SQLite FTS5 BM25 through Reciprocal Rank Fusion (k = 60). Notes are chunked by ##/### headings so every answer is an atomic, deep-linkable section like [[Note#Section]].
GraphFinder turns Markdown vaults and entire codebases into a semantically indexed knowledge graph — giving humans a beautiful place to think and giving AI agents surgical, ~50-token retrieval through a native MCP server.
# Index any folder (notes + code) and export graph artifacts $ graphfinder sync ./my-repo --export # Register GraphFinder in every AI editor on this machine $ graphfinder config --install # Ask the graph $ graphfinder search "how is authentication handled?"
Everything runs on your machine: a Rust core with an embedded ONNX model, SQLite with FTS5, a force-directed graph UI and an MCP server that any AI editor can talk to.
Dense 384-dimension FastEmbed vectors fused with SQLite FTS5 BM25 through Reciprocal Rank Fusion (k = 60). Notes are chunked by ##/### headings so every answer is an atomic, deep-linkable section like [[Note#Section]].
No API keys, no telemetry. Your Markdown stays as plain files on disk.
Force-directed canvas with 1/2-hop highlighting, tag clusters and language-coded code rings.
AST-lite scanning of entire repositories: symbols (functions, classes, structs), local import graph and external packages — respecting .gitignore and syncing incrementally by SHA-256.
24 tools over Streamable HTTP/SSE (127.0.0.1:45123) while the app is open, or headless stdio via graphfinder mcp. Works with Cursor, Claude Desktop, Antigravity, Windsurf, Cline, Roo Code, Zed.
Community detection, degree centrality, God Nodes, cross-community surprises, cycles and shortest paths — exported as graph.json, GRAPH_REPORT.md and an offline graph.html.
Edit in VS Code, Cursor or Neovim — changes are re-indexed within 500 ms.
Isolated vaults, each with its own index. Rename refactors every incoming wikilink.
DNS-rebinding defense, Origin checks, strict CSP and DOMPurify sanitization.
Markdown notes and source files are parsed, chunked and embedded locally.
Wikilinks, tags and code imports become edges you can explore and analyze.
MCP tools return only the section or symbol needed — not whole files.
From installation to the internals of the search engine. Current release: v0.10.0.
GraphFinder is a cross-platform desktop application (Tauri v2 + Rust + React 19) and command-line tool that indexes Markdown knowledge vaults and source-code repositories into a single, semantically searchable graph.
Traditional RAG pipelines split documents into arbitrary fixed windows or push entire files into an LLM context, wasting thousands of tokens. Note-taking tools, in turn, rarely offer local vector search or an API agents can use. GraphFinder addresses both sides:
[[wikilinks]], explore connections in an interactive 2D graph and keep full ownership of your files.[[Note#Section]]) and individual code symbols, typically around 50 tokens per hit.| Concept | Meaning |
|---|---|
| Vault | A folder of .md files (and optionally code) indexed by GraphFinder. |
| Project | A registered vault with its own isolated SQLite index. Identified by a slug id (e.g. my-api). |
| Chunk | An atomic section of a note delimited by ## / ### headings, embedded independently. |
| Deep link | A reference to a specific section: [[Note Title#Section Heading]], or to a symbol: [[path/file.rs#function]]. |
| Node / Edge | Notes and code files are nodes; wikilinks and imports are edges. |
| God Node | A highly central hub in the graph, detected by degree centrality. |
Every tagged release is built by GitHub Actions for all three desktop platforms. Grab the latest from the Releases page:
After installing, enable the terminal command so graphfinder works from any shell:
# Windows: adds the install folder to your User PATH + creates graphfinder.cmd shims # macOS/Linux: creates a symlink in ~/.local/bin/graphfinder graphfinder install-cli
If graphfinder is not yet on your PATH, run the binary directly, e.g. "C:\Program Files\GraphFinder\GraphFinder.exe" install-cli. Open a new terminal afterwards.
libwebkit2gtk-4.1-dev, build-essential, libssl-dev, libayatana-appindicator3-dev, librsvg2-devgit clone https://github.com/GabrielTBeserra/GraphFinder.git cd GraphFinder npm install # Run the desktop app in development mode (Vite on :1420 + Tauri) npm run app # Produce installers in src-tauri/target/release/bundle/ npm run tauri build
On first launch the embedding model (all-MiniLM-L6-v2, ~90 MB) is downloaded once into .fastembed_cache. After that GraphFinder works fully offline.
graphfinder with no arguments). A default vault is created and the graph appears.# Title, a short summary, then ## sections. Link concepts with [[Other Note]] and finish with tags like #architecture. Save with Ctrl+S.graphfinder config --install or copy a snippet from the in-app MCP modal. Your agent now has 24 GraphFinder tools.Prefer the terminal? The same flow headless:
cd ~/code/my-project graphfinder sync # registers the folder as a project and indexes it graphfinder status # notes, code files, edges, database size graphfinder search "rate limiting middleware" graphfinder report # architecture audit + graph artifacts
The interface is organised around a sidebar, the central graph canvas and contextual panels.
| Area | What it does |
|---|---|
| Top bar | Project switcher, new project, Omnisearch, architectural report, MCP integration modal, dark/light theme toggle (persisted in localStorage). |
| Sidebar | Tabs for Notes and Code (with language filters), plus semantic search with a toggle between Markdown notes and code symbols. Toggle with Ctrl+B. |
| Graph view | Force-directed canvas. Click a node to focus it and highlight its 1- and 2-hop neighbourhood. Filter with [All], [Notes], [Code]. Notes are coloured by tag cluster; code files get language-coded rings; hubs glow proportionally to their degree. |
| Note editor | Markdown editor with live preview (sanitised by DOMPurify), wikilink autocomplete (type [[, navigate with ↑↓, accept with Enter/Tab, close with Esc) and Ctrl+S to save. |
| Code Inspector | Slide-out drawer for a code node: declared symbols with line ranges, import graph with clickable jumps, external packages and a surgical code viewer. |
| Omnisearch | Ctrl/⌘+K. Hybrid search across the active project, keyboard navigable. |
| Architectural report | Communities, God Nodes, coupling surprises and cycles for the active project, with one-click export. |
| MCP modal | Copy-ready config snippets for each AI editor, plus the agent rules (AGENTS.md) and curator skill. |
| Shortcut | Action |
|---|---|
| Ctrl/⌘ + K | Toggle Omnisearch |
| Ctrl/⌘ + B | Toggle sidebar |
| Ctrl/⌘ + S | Save current note |
| ↑ ↓ Enter Esc | Navigate search results and wikilink suggestions |
While the desktop app is open it also hosts the MCP server on http://127.0.0.1:45123, so notes created by your agent appear on the graph in real time.
GraphFinder works with any Markdown, but retrieval is most precise when notes follow this structure:
# Note Title) followed by a 2–3 line executive summary.##/### sections of roughly 40–150 tokens, with descriptive headings (## 2. SQLite WAL Configuration rather than ## Config). Each heading becomes its own embedding and deep-link target.[[Note]] or [[Note#Section]]. Aim for 1–3 links per note to avoid orphans.#architecture #sqlite #mcp at the end of sections or the note. They drive the coloured clusters in the graph.# Auth JWT How the API issues and validates JSON Web Tokens. Covers signing keys, expiry policy and refresh rotation. ## 1. Token Signing Tokens are signed with RS256. Keys rotate every 30 days and are loaded from the secrets store at boot. See [[System Architecture#2. Secrets]]. ## 2. Refresh Rotation Each refresh invalidates the previous token family to stop replay attacks. #auth #security #architecture
pulldown-cmark). Content inside fenced code blocks is isolated, so a # in code is never treated as a heading or tag.rename_note) rewrites every incoming [[Old Title]] across the vault.Every query runs two retrievers in parallel and merges them:
| Stage | Details |
|---|---|
| Dense vectors | FastEmbed on ONNX Runtime. Default model all-MiniLM-L6-v2 (384 dims). Optional MultilingualE5Small for non-English vaults. Cosine similarity over note_chunks / code_chunks. |
| Keyword (BM25) | SQLite FTS5 full-text index — catches exact identifiers, error codes and rare terms that embeddings miss. |
| Fusion | Reciprocal Rank Fusion: score = Σ 1 / (60 + rank). Robust without score normalisation. |
| Output | Top-N chunks with title, heading, deep link, affinity score and token estimate. |
Storage is a single SQLite database per project running in WAL mode for concurrent indexing and querying. Re-indexing is incremental: files are compared by timestamp and SHA-256 hash, and only changed files are re-parsed and re-embedded.
Point GraphFinder at a repository and it builds a symbol index and dependency graph without needing a compiler or language server.
| Language | Extensions | Imports parsed |
|---|---|---|
| TypeScript / TSX | .ts .mts .cts .tsx | import, require |
| JavaScript / JSX | .js .mjs .cjs .jsx | import, require |
| Python | .py .pyi | import, from … import |
| Rust | .rs | use, mod |
| Go | .go | import |
| C / C++ | .c .h .cpp .hpp .cc .cxx .hh | #include |
| Java / Kotlin | .java .kt .kts | import |
| C# / F# | .cs .fs | using |
| PHP · Ruby · Swift | .php .rb .swift | use/require/import |
| Web & config | .html .css .scss .sass .less .json .yaml .toml .sql | indexed as files |
| Shell | .sh .bash .zsh | source |
code_links): imports and dependents.rusqlite, react) listed per file.Anything in .gitignore, plus node_modules, target, dist, .git, binary files and files larger than 1 MB.
A pure-Rust analytics engine treats notes and code files as one unified graph and answers architectural questions.
| Analysis | Description |
|---|---|
| Communities | Label-propagation / Louvain-style clustering reveals modular subsystems. |
| Centrality & God Nodes | Degree centrality ranks nodes; the most connected hubs are flagged as God Nodes — refactor or document them first. |
| Cross-community surprises | Edges that couple otherwise distant subsystems — often hidden architectural debt. |
| Cycles | Circular dependency chains between files. |
| Shortest path | BFS across imports and wikilinks between any two nodes (graphfinder path, find_path). |
| Node explanation | 360° card: community, centrality rank, callers, callees, siblings (graphfinder explain, explain_node). |
graphfinder report, graphfinder export, sync --export or the export_graph tool write to ./graphfinder-out/:
graph.json — nodes (community, degree, centrality, god-node flag) and edges (source, target, label, weight). Ideal for agents and scripts.GRAPH_REPORT.md — executive summary, metrics, God Nodes table, subsystem list, coupling surprises and cycles.graph.html — zero-dependency offline visualiser with search, community colours and hub halos. Open it in any browser.The same binary is both the desktop app and the CLI. Running it without arguments opens the GUI; with a command it runs in the terminal.
graphfinder [COMMAND] [OPTIONS]
| Command (aliases) | Options | Description |
|---|---|---|
sync (syn, index) [path] | --json --export | Indexes notes and code in path (default: current dir). Registers a new project if unknown, otherwise updates incrementally via SHA-256. --export also writes graph artifacts. |
status (info) [path] | — | Shows notes, code files, graph edges and database statistics. |
projects (list) | — | Lists every registered project and its path. |
search <query> | --path --limit <n> | Hybrid semantic search (BM25 + embeddings) in a project. |
report (audit) [path] | --out-dir --json | Communities, God Nodes, surprises and cycles, plus all three artifacts. |
path <from> <to> | --path --json | Shortest multi-hop path between two files, symbols or notes. |
explain <node> | --path --json | Architectural context card for a node. |
export [path] | --out-dir | Writes graph.json, GRAPH_REPORT.md, graph.html silently. |
config (mcp-config, setup) | --install / -i --json | Prints MCP config for AI editors. --install auto-detects installed editors, registers GraphFinder in them and adds the CLI to PATH. |
tools (schemas, mcp-tools, export-schemas) [dir] | — | Exports all 24 tool JSON schemas, a tools.json manifest and instructions.md to ./mcp-tools. |
install-cli (install-path) | — | Adds graphfinder to the OS PATH. |
mcp (--mcp) | — | Starts the headless stdio MCP server. |
help (--help, -h) | — | Prints help. |
# Machine-readable sync for CI or scripts graphfinder sync ./services/api --json # How does the UI reach the database layer? graphfinder path "GraphView.tsx" "db.rs" # Why does this file matter? graphfinder explain "src-tauri/src/engine/db.rs" # Audit into a custom folder graphfinder report --out-dir ./docs/architecture # Search only 3 results in a specific project path graphfinder search "file watcher debounce" --path ./GraphFinder --limit 3
From a source checkout, npm scripts wrap the CLI: npm run sync, npm run status, npm run search, npm run projects, npm run mcp.
GraphFinder implements the Model Context Protocol with the official Rust SDK (rmcp) in two modes:
| Mode | Endpoint | Best for |
|---|---|---|
| A · Embedded HTTP/SSE (app running) | http://127.0.0.1:45123/mcp (Streamable HTTP)http://127.0.0.1:45123/sse (SSE) | Live updates: agent-created notes appear on the graph instantly. |
| B · Headless stdio | graphfinder mcp / GraphFinder.exe --mcp | Terminals, servers, CI, or when you don't want the GUI open. |
The fastest path is automatic registration:
graphfinder config --install # Cursor, Claude Desktop, Windsurf, Cline, Roo Code… graphfinder config --json # just print the JSON snippet
Or configure manually:
File: .cursor/mcp.json (workspace) or ~/.cursor/mcp.json (global).
{
"mcpServers": {
"graphfinder": {
"url": "http://127.0.0.1:45123/sse"
}
}
}File: %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS).
{
"mcpServers": {
"graphfinder": {
"command": "C:\\Program Files\\GraphFinder\\GraphFinder.exe",
"args": ["--mcp"]
}
}
}File: ~/.gemini/antigravity-ide/mcp_config.json.
{
"mcpServers": {
"graphfinder": {
"type": "sse",
"url": "http://127.0.0.1:45123/sse"
}
}
}Windsurf: ~/.codeium/windsurf/mcp_config.json. Cline / Roo Code: cline_mcp_settings.json in the extension's global storage.
{
"mcpServers": {
"graphfinder": {
"url": "http://127.0.0.1:45123/sse"
}
}
}Any MCP client that spawns a process (no GUI required):
{
"mcpServers": {
"graphfinder": {
"command": "graphfinder",
"args": ["--mcp"]
}
}
}In stdio mode the MCP handshake answers in under 50 ms — the embedding model loads and the vault syncs in the background.
Every tool accepts an optional project parameter to target a specific vault without cross-contamination. Dashed parameters are optional.
Knowledge retrieval
Hybrid vector + BM25 search over note chunks with RRF. Returns deep links and token estimates.
Reads exactly one section by heading or deep-link fragment.
Summary, links, tags and a heading map with per-section token costs — under 80 tokens.
Recently modified notes with one-line summaries and tags.
Authoring & linking
Embeds draft text and recommends existing notes/sections to link (prevents orphans).
Creates or updates a note, parses it and indexes it immediately.
Appends a [[wikilink]] from one note to another and updates the graph.
Renames a note and refactors all incoming wikilinks vault-wide.
Deletes the file and cleans chunks, embeddings, links and tags.
Graph & architecture
Nodes connected within 1 or 2 hops, without reading bodies.
BFS shortest path across wikilinks and imports between two nodes.
Centrality, community, God Node status, dependents, dependencies and siblings.
System-wide audit: communities, God Nodes, surprises and cycles.
Writes graph.json, GRAPH_REPORT.md and graph.html.
Notes, chunks, links, tags and total token estimates.
Codebase
Hybrid search over code symbols, signatures and comments. Returns [[file#symbol]] with line ranges.
Glob / substring matching over indexed file paths.
Symbols with line ranges, local imports, dependents and packages — under 80 tokens.
Returns only the body of a named function, class or struct.
What a file imports and who imports it.
Projects & sync
All registered vaults with paths and note counts.
Creates an isolated vault (optionally at any path on disk).
Changes the active default vault.
Hash-based incremental re-index; a path auto-maps to (or registers) a project.
Run graphfinder tools to export the JSON schemas of all tools for use with any agent framework.
GraphFinder ships three layers that work together: the agent (Cursor, Claude, Antigravity…) reasons and plans, the skill enforces token economy and note quality, and the MCP server executes retrieval and writes.
AGENTS.md — repository rules for agents (token economy, note schema, decision pipelines). Antigravity loads it automatically; in Cursor add it to Project Rules; in Claude paste it into the project prompt..agents/skills/graphfinder-curator — authoring and curation workflow (summaries, atomic sections, suggest_links before store_context, tags)..agents/skills/graphfinder — architecture auditing workflow (reports, paths, explain, exports).search_semantic("sqlite wal mode") → top 5 chunks (~50 tokens each)
└─ need the outline? get_compressed_context("System Architecture")
└─ need one section? read_section("System Architecture", "1. Local Storage")draft note (# Title + summary + ## sections) → suggest_links(draft) → e.g. "System Architecture: 85%" → insert [[System Architecture]] into draft → store_context(title, content, tags) → file written, indexed, graph updated
search_code("hybrid_search", language="rust")
→ get_file_context("src-tauri/src/engine/db.rs") # symbol map, <80 tokens
→ read_code_chunk("src-tauri/src/engine/db.rs", "hybrid_search")
→ get_code_dependencies("src-tauri/src/engine/db.rs") # impact analysisget_community_report() → subsystems, God Nodes, surprises, cycles
→ explain_node("db.rs") → why it matters
→ find_path("App.tsx", "db.rs")| Goal | Prompt |
|---|---|
| Surgical search | "Query the GraphFinder vault and explain how code indexing works without reading full files." |
| Connected note | "Document our OAuth2 flow as a GraphFinder note. Call suggest_links first and add relevant tags." |
| Code inspection | "Find where import parsing is implemented and read only that function with read_code_chunk." |
| Impact analysis | "Which files import GraphView.tsx? Summarise the architectural impact of changing it." |
| Architecture audit | "Run a GraphFinder community report and list the God Nodes we should document first." |
Each project is an isolated workspace with its own Markdown directory and its own SQLite vector database, so searches never leak between projects.
<data dir>/vault with index <data dir>/index.db.<data dir>/vaults/<project_id>/, created from the UI or create_project.graphfinder sync <path> or create_project(name, path).vaults/projects.json stores the active project, custom names and custom paths.{
"active_project": "default",
"custom_names": { "my-api": "My API" },
"custom_paths": { "my-api": "C:/Repos/MyAPI" }
}GRAPHFINDER_DATA_DIR, if set.package.json (source checkout / dev mode).%APPDATA%\GraphFinder (Windows), ~/Library/Application Support/GraphFinder (macOS), ~/.local/share/GraphFinder (Linux).GraphFinder is configured through environment variables — no config file required.
| Variable | Default | Effect |
|---|---|---|
GRAPHFINDER_DATA_DIR | see above | Base directory for vaults, registry and databases. |
GRAPHFINDER_VAULT | <data>/vault | Overrides the default vault folder. |
GRAPHFINDER_DB | <data>/index.db | Overrides the default SQLite database path. |
GRAPHFINDER_MODEL / GRAPHFINDER_EMBEDDING_MODEL | auto | multilingual, multilingual-e5-small or e5 load MultilingualE5Small; otherwise all-MiniLM-L6-v2. |
GRAPHFINDER_MODELS | — | Folder containing a local model.onnx + tokenizer.json for fully offline use (also auto-detected in models/all-MiniLM-L6-v2). |
GRAPHFINDER_MCP_PORT | 45123 | Port of the embedded HTTP/SSE MCP server. |
GRAPHFINDER_AUTO_APPEND_LINKS | false | 1/true automatically appends suggested wikilinks when storing notes. |
# Portuguese / multilingual vault on a custom port export GRAPHFINDER_MODEL=multilingual export GRAPHFINDER_MCP_PORT=47000 graphfinder
Changing the embedding model changes vector dimensions/semantics. Re-index your projects (delete the project's index.db and run graphfinder sync) after switching.
GraphFinder/ ├── src/ # React 19 + TypeScript frontend │ ├── components/ # GraphView, NoteEditor, CodeInspector, Sidebar, │ │ # OmnisearchModal, McpModal, ArchitecturalReportModal… │ ├── services/ # Tauri IPC bindings │ └── types.ts ├── src-tauri/ # Rust backend │ ├── src/main.rs # CLI entry point (GUI when no args) │ ├── src/lib.rs # Tauri setup, IPC commands, embedded MCP HTTP server │ ├── src/engine/ │ │ ├── parser.rs # CommonMark AST, chunking, wikilinks, tags │ │ ├── embeddings.rs # FastEmbed model loading & inference │ │ ├── db.rs # SQLite schema, FTS5, hybrid RRF search │ │ ├── vault.rs # Engine: sync, watcher, note lifecycle │ │ ├── code.rs # Language detection, symbols, imports │ │ ├── graph_analytics.rs# Communities, centrality, paths, exports │ │ └── project.rs # Multi-vault manager & registry │ └── src/mcp/ # MCP tool definitions (mod.rs) & transports (server.rs) ├── .agents/skills/ # graphfinder & graphfinder-curator skills ├── mcp-tools/ # Exported tool schemas ├── docs/ # This website (GitHub Pages) └── AGENTS.md · MCP_TOOLS.md · CHANGELOG.md
| Layer | Technology |
|---|---|
| Desktop runtime | Tauri 2.12 |
| Backend | Rust 2021 · Tokio · Axum 0.7 · rmcp 3.5 |
| Embeddings | fastembed 4 (ONNX Runtime) |
| Storage | rusqlite 0.32 (bundled SQLite, WAL, FTS5) |
| Parsing | pulldown-cmark 0.13 · regex · walkdir |
| File watching | notify-debouncer-mini 0.6 |
| Frontend | React 19.2 · TypeScript 6 · Vite 8 · Tailwind CSS 4 |
| UI | Radix UI · Phosphor Icons · force-graph · marked · DOMPurify |
127.0.0.1.Host header is validated on every request.tauri.conf.json.Report vulnerabilities privately as described in SECURITY.md.
| Script | Purpose |
|---|---|
npm run dev | Vite dev server for the frontend only (port 1420). |
npm run app | Full desktop app in dev mode (tauri dev). |
npm run build | Type-check and build the frontend into dist/. |
npm run tauri build | Release binaries and installers. |
npm run lint | Lint with oxlint. |
cargo test --manifest-path src-tauri/Cargo.toml | Rust unit tests (parser, FTS5, embeddings math, language detection, imports, code search). |
npm run sync | status | search | projects | mcp | Run CLI commands via cargo run. |
Pushing a tag matching v* (or running the Release workflow manually) triggers .github/workflows/release.yml: scripts/sync-version.js stamps the tag version into package.json, Cargo.toml and tauri.conf.json, then tauri-action builds and publishes installers for Windows, macOS and Linux.
git tag v0.11.0 git push origin v0.11.0
Bug reports, features, docs and PRs are welcome. Read CONTRIBUTING.md and the Code of Conduct.
127.0.0.1:45123.The HTTP/SSE endpoint only exists while the desktop app is running. Open the app, or switch your client to stdio mode ("command": "graphfinder", "args": ["--mcp"]). If you changed GRAPHFINDER_MCP_PORT, update the URL.
graphfinder is not recognised in the terminal.Run GraphFinder.exe install-cli (or graphfinder config --install) and open a new terminal so the updated PATH is loaded.
Set GRAPHFINDER_MODEL=multilingual and re-index.
The embedding model is downloaded once. Subsequent starts load it from .fastembed_cache; point GRAPHFINDER_MODELS to a local copy for air-gapped machines.
Check whether they are ignored by .gitignore, are binary, exceed 1 MB, or have an unsupported extension. Run graphfinder sync to force an incremental update.
No. Embeddings, search and analytics run locally. The only network access is the one-time model download (and this website checking the latest release on GitHub).
Full history in CHANGELOG.md and on the Releases page.
find_path, explain_node, get_community_report, export_graph (24 total).report, path, explain, export, config --install, tools, install-cli.graph.json, GRAPH_REPORT.md, offline graph.html; architectural report modal in the app.search_code, find_files, get_file_context, read_code_chunk, get_code_dependencies.[All]/[Notes]/[Code] filters, incremental SHA-256 code sync.--mcp).Free and open source under the MIT license. Runs entirely on your machine.