junhewk2k downloadsBuild a knowledge graph from your notes using LLM-powered entity extraction. Supports Claude, OpenAI, Gemini, and Ollama.
This plugin builds a lightweight knowledge graph from users' Obsidian notes using LLM-powered entity extraction with a simple yet expressive ontology model to provide knowledge extraction, exploration, and RAG search. Since Obsidian provides wonderful links between notes, implementing ontology model would meet users' (especially researchers') needs.

Keep configuration files and other unwanted notes out of analysis with the new
Excluded files and folders setting under Analysis. For example, add
skills/** to skip that folder and everything beneath it.
See Analysis Exclusions for supported patterns and Upgrading to 0.6.0 for the previous release’s write-back and storage improvements. Addresses issue #1.
Traditional knowledge graphs often require complex schemas with dozens of entity and relationship types, making them difficult to maintain and query. Simple Graph Builder takes a different approach:
detail field for nuanced descriptions without schema explosionThis design provides structured entity classification with expressive relationships, making it easy to build, query, and maintain your personal knowledge graph.
[[wikilinks]] to build note-to-note connectionsA key insight from recent knowledge graph research is that entity resolution is critical for quality knowledge graphs [3]. Without proper deduplication, "AI", "artificial intelligence", and "Artificial Intelligence" appear as separate nodes, fragmenting your knowledge.
Simple Graph Builder uses a hybrid resolution pipeline (opt-in feature):
| Stage | Method | Speed |
|---|---|---|
| 1. Persistent cache | Previously resolved tokens | O(1) |
| 2. Session cache | Same name resolved this session | O(1) |
| 3. Exact name | Hash lookup on canonical name | O(1) |
| 4. Alias match | Hash lookup on stored aliases | O(1) |
| 5. Embedding similarity | Cosine similarity > 0.90 = auto-merge | O(n) |
| 6. LLM verification | Ambiguous matches (0.80-0.90) verified by LLM | API call |
| 7. Create new | No match found | - |
This approach resolves most entities via fast hash lookups, reserving expensive embedding searches and LLM calls for genuinely ambiguous cases.
| Command | Description |
|---|---|
Analyze current note |
Extract entities from the active note |
Search related notes |
Find notes by entity name (exact/fuzzy match) |
Smart Search (AI) |
Natural language search using LLM to explore the graph |
Open graph view |
Show the knowledge graph visualization |
Open note neighborhood panel |
Show current note's connections in sidebar |
Remove current note from graph |
Remove active note from the graph |
Rebuild note layer |
Recreate note nodes and their links from existing data (no API calls) |
Write graph links into notes |
Apply the graph to your vault as Obsidian links (no API calls) |
Remove graph links from notes |
Take the link property back out of every note |
Clear all graph data |
Reset the entire graph |
The LLM must classify each entity into one of these types:
| Type | Description | Examples |
|---|---|---|
PERSON |
People, individuals | Authors, researchers, team members |
ORGANIZATION |
Companies, institutions | Google, MIT, research labs |
CONCEPT |
Ideas, theories, principles | Machine learning, API design |
PROJECT |
Projects, products, initiatives | Obsidian, GraphRAG |
TOOL |
Software, hardware, instruments | Python, VS Code, Docker |
EVENT |
Meetings, conferences, milestones | NeurIPS 2024, sprint review |
PLACE |
Locations, venues, geography | San Francisco, AWS us-east-1 |
DOCUMENT |
Papers, books, articles, notes | "Attention Is All You Need" |
METHOD |
Techniques, approaches, workflows | Agile, TDD, fine-tuning |
TOPIC |
Subjects, themes, fields, domains | NLP, distributed systems |
One further type, NOTE, is created by the plugin rather than the LLM. Each
analyzed note becomes a NOTE node that mentions the entities extracted from
it and links to the notes it wikilinks, which is what ties separate notes into
one graph. Turn them off with Show note nodes for an entity-only view.
Relationships are expressed as active verbs describing how entities relate:
| Verb Examples | Meaning |
|---|---|
develops, creates, builds |
Creation, authorship |
uses, applies, implements |
Usage, application |
causes, leads to, enables |
Causality, dependency |
contains, includes, has |
Composition, membership |
cites, references, based on |
Citation, source |
relates to, similar to |
General association |
Each relationship also includes an optional detail field for additional context.
Click the graph icon in the left ribbon to access:
Shows real-time graph statistics with node counts by label.
A sidebar panel showing:
Right-click a node to:
--api-key./api/chat) or OpenAI-compatible (/v1/chat/completions). Use OpenAI-compatible for llama.cpp's llama-server, LM Studio, vLLM and similar; set Host to the base address without the /v1 suffix.claude-haiku-4-5) are flagged in settings and simply ignore it.Under Analysis, add one vault-relative path or pattern per line to Excluded files and folders. Exclusions apply to Analyze current note, Analyze entire vault, and Auto-analyze on save, before note content is read or sent to a provider. Vault analysis reports excluded notes separately from unchanged or short notes.
| Pattern | Excludes |
|---|---|
skills or skills/ |
The root skills folder and all its descendants |
skills/** |
Everything beneath the root skills folder |
templates/*.md |
Markdown files immediately inside templates |
**/SKILL.md |
Files named SKILL.md anywhere, including the vault root |
notes/draft.md |
That exact file |
Patterns are anchored at the vault root. * matches characters within a path
segment, ? matches one character, and a whole ** segment crosses any number of
folders. Other characters are literal; regex, negation, and comment syntax are
not supported. Blank lines and surrounding whitespace are ignored. Matching is
case-insensitive and Unicode-normalized; both / and \ separators work.
Respect Obsidian excluded files additionally honors Files and links → Excluded files, using Obsidian’s matching rules rather than interpreting its entries as plugin globs. This toggle is off by default. If the native matcher is unavailable, the plugin stops opted-in analysis and asks you to turn the toggle off; your custom patterns continue to work with it off.
Changing exclusions affects queued and future analysis; a note already being analyzed finishes. Existing graph data, search results, and written links are kept. Use Remove current note from graph to remove prior contributions. Standalone write-back commands remain independent of analysis exclusions. Plugin-managed entity notes are always excluded from analysis.
You can configure a separate model for Smart Search queries, allowing you to use faster/cheaper models for extraction while using more capable models for search:
This is useful for optimizing cost vs. quality - e.g., use gpt-5.4-mini for extraction and gpt-5.6-luna for search.
Enable embedding-based entity resolution for intelligent deduplication:
/api/embed) or OpenAI-compatible (/v1/embeddings), set separately from the chat provider's APItext-embedding-3-small (1536 dims), text-embedding-3-large (3072 dims)gemini-embedding-001 (768 / 1536 / 3072 dims)nomic-embed-text (768 dims), mxbai-embed-large (1024 dims)Off by default. This is the only part of the plugin that writes into your notes.
Entities). Notes in this folder are never analyzedrelated)What the plugin edits, exactly: in your own notes, only that one property — your prose is never touched. In entity notes, the aliases, entity-type and sgb-id properties and the text between the %% sgb:managed:start %% and %% sgb:managed:end %% markers. Anything you write outside those markers is kept through every regeneration, and a file that does not carry the plugin's sgb-id is never overwritten or deleted.
Note analysis requires a model that can return structured output (JSON schema). Models that cannot are refused with a message rather than silently producing a lower-quality graph, and the settings panel flags them as you select them.
| Provider | Models |
|---|---|
| Claude | claude-sonnet-5, claude-haiku-4-5 |
| OpenAI | gpt-5.6-luna, gpt-5.4-mini |
| Gemini | gemini-3.6-flash, gemini-3.5-flash-lite |
| Local | any model your server exposes — Ollama, or an OpenAI-compatible server such as llama.cpp's llama-server, LM Studio or vLLM |
Any other model can be typed into the Custom… field. Smart Search additionally needs tool calling; for local servers, start llama-server with --jinja, and prefer qwen3:* or gpt-oss:* on Ollama.
This release adds vault write-back and makes the data file smaller. Nothing is re-analyzed, no API calls are made, and no existing data is lost.
related: property on each analyzed note. Both are off until you turn them on, and Remove written links undoes the property across the vault.mentions / links to edges are no longer stored: they are rebuilt from your notes and Obsidian's link index every time the plugin loads, so keeping a second copy on disk only cost space. mentions is one edge per note-entity pair, usually the largest single population in the file. Your graph loads with exactly the same nodes and edges as before; the saving is larger the more entities per note you extract.This release fixes a bug that made large graphs dense and slow to load, and repairs the damage automatically on first load. Nothing is re-analyzed and no API calls are made.
NOTE node that mentions its entities and links to the notes it wikilinks — one edge per link, as intended. The note layer is rebuilt from Obsidian's own link index. Turn it off with Show note nodes, or rebuild it any time with the Rebuild note layer command.The same vault above went from 191,436 edges / 115 MB to 7,449 edges / 6.3 MB, with average connections per node dropping from 178 to 6.6.
This release moves to each provider's current API. Two things happen automatically on first load:
claude-sonnet-4-5-20250929 → claude-sonnet-5, gpt-4o → gpt-5.6-luna). Ollama model names are left alone, since those refer to models you have pulled locally. Check your model selection afterwards if you had a specific one configured.text-embedding-004 was shut down in January 2026, so it is replaced by gemini-embedding-001. Stored embeddings from the old model are discarded and you will be prompted to recompute them; entity resolution is paused until you do. OpenAI and Ollama embeddings are unaffected.junhewk/simple-graph-buildermain.js, styles.css, and manifest.json from the latest releaseVaultFolder/.obsidian/plugins/simple-graph-builder/Analyze current noteOpen graph viewNode colors are determined by entity type (10 predefined colors). Node diameter scales logarithmically with visible connections, and edge opacity reflects the average importance of its endpoints. Relationship verbs remain available on hover.
Graphs are laid out with fCoSE, then refined so the result is readable at vault scale:
How much space that pass aims for depends on how big the graph is. Small graphs get the full width of a label, so nothing collides at the zoom they open at. Large ones get less: the whole layout is fitted to the pane, so spacing every node a label apart makes a 5000-node graph so wide that each node lands on a fraction of a pixel and the view looks empty. Those are read by zooming in, where the tighter spacing is still ample.
Edges follow the same logic. Zoomed out they are drawn bold, because a 1px line covers a fraction of a pixel there and only the mass of them registers; zoom in and they thin out so they sit behind the nodes and labels rather than across them.
The result is a graph of distinct clusters rather than one dense block. If yours still looks crowded, raise Minimum connections or turn off Show note nodes to thin it out.
Two search modes are available:
Search related notesSmart Search (AI)Note: Smart Search requires models with tool calling support. Some Ollama models (deepseek-r1:*, gemma3:*) have limited support. Recommended: qwen3:*, gpt-oss:* for Ollama.
This plugin makes API calls to extract entities from your notes.
text-embedding-3-smallgemini-embedding-001nomic-embed-text)Consider using Ollama for cost-free operation, or batch analyze during off-peak hours to manage costs.
embeddings.bin)Obsidian stores plugin settings — including your API keys — in
.obsidian/plugins/simple-graph-builder/data.json, together with the graph
itself. If your vault is a git repository, add this to your .gitignore:
.obsidian/plugins/simple-graph-builder/data.json
Pushing that file to a public repository publishes your keys in plaintext, and deleting it later does not help — git keeps the history. If it has already been pushed, revoke the key at your provider's console and issue a new one.
This plugin's entity resolution approach is inspired by recent advances in knowledge graph construction:
Simple Graph Builder combines the simplicity of LightRAG with KGGen's hybrid resolution approach, adapted for Obsidian's local-first architecture.
npm install
npm run dev # watch build
npm run build # production build (typecheck + bundle)
npm test # provider wire-level tests
npm test -- gemini # run one suite
npm run eval # live end-to-end check against the real provider APIs
npm test bundles each tests/*.test.ts with esbuild, stubbing Obsidian's requestUrl so outgoing requests can be captured, then asserts the exact JSON each provider adapter builds. No test framework is involved — esbuild is already a dev dependency, and the plugin ships its whole bundle.
These are deliberately wire-level, because that is where the bugs are: a parameter a model rejects, a tool result dropped from a loop, embeddings written at the wrong vector width. Each suite exits non-zero on failure, and the release workflow runs them before publishing.
tests/layout.test.ts is the exception: it scores the graph layout instead of asserting a payload. It generates a vault-shaped graph, lays it out headlessly, and measures how many nodes are individually visible, how many have room for their label, how long edges are relative to typical node spacing, and how well clusters separate — against thresholds and against the layout the previous release shipped. To see the numbers at real-vault scale, bundle it and run it directly:
npx esbuild tests/layout.test.ts --bundle --platform=node --outfile=/tmp/layout.cjs
SGB_LAYOUT_BENCH=1 node /tmp/layout.cjs
npm run eval is the opposite end: it bundles tests/*.eval.ts against a stub whose requestUrl performs real HTTP, then runs the full extraction pipeline against every provider you have a key for in the environment. Providers without a key are skipped, so it is safe to run with just one.
ANTHROPIC_API_KEY=... OPENAI_API_KEY=... GEMINI_API_KEY=... npm run eval
[1] Guo, Z., et al. (2024). "LightRAG: Simple and Fast Retrieval-Augmented Generation." https://github.com/HKUDS/LightRAG
[2] Edge, D., et al. (2024). "From Local to Global: A Graph RAG Approach to Query-Focused Summarization." arXiv:2404.16130. https://github.com/microsoft/graphrag
[3] Shu, Y., et al. (2025). "KGGen: Extracting Knowledge Graphs from Plain Text with Language Models." NeurIPS 2025. arXiv:2502.09956. https://github.com/stair-lab/kggen
[4] Neo4j, Inc. (2024). "Neo4j GraphRAG Package for Python." https://neo4j.com/docs/neo4j-graphrag-python/current/
[5] Veen, A. (2024). "pgvector: Open-source vector similarity search for Postgres." https://github.com/pgvector/pgvector
MIT License - see LICENSE for details.