obsidian-llm-wiki
LLM wiki kit
First committed by kytmanov
Published in kytmanov/obsidian-llm-wiki-local. Publisher page
849 GitHub stars
What it is
Karpathy’s LLM Wiki, 100% local with Ollama. Drop Markdown notes → AI extracts concepts → your Obsidian wiki auto-links and grows. Zero sharing. Your notes stay yours.
AutoGineer overview, from the brain’s own files
obsidian-llm-wiki is a practical implementation of the LLM Wiki pattern, designed to turn unstructured notes into a structured, persistent knowledge base. It operates by treating raw Markdown files as source material, which an LLM then synthesizes into interlinked wiki articles. The system is built for local-first operation, defaulting to Ollama for privacy, though it supports various OpenAI-compatible endpoints. It features incremental compilation, meaning only notes affected by changes are reprocessed, and it preserves manual edits by detecting content changes. The tool includes a file watcher for background processing, interactive draft reviews with feedback loops, and query capabilities that synthesize answers from the wiki without requiring vector databases.
How it works
Memory model: LLM wiki
AutoGineer overview, from the brain’s own files
The system processes notes in three stages. First, the ingest stage uses a fast LLM to analyze raw Markdown files, extract concepts, and create source summary pages. Second, the compile stage uses a heavier LLM to gather source notes for each concept and generate wiki articles with internal links, which are saved as drafts. Finally, the review stage allows users to approve or reject drafts, with rejections providing feedback that informs future compilations. The system uses a SQLite database to track the lifecycle of notes and concepts, and it maintains the wiki structure directly within an Obsidian vault.
| Folder | Role | Files |
|---|---|---|
| .github | agent-config | 4 |
| docs | docs | 2 |
| scripts | scripts | 4 |
| src | source-code | 36 |
| tests | tests | 59 |
The agent writes
- update_in_place evidence: CLAUDE.md
- save_with_suffix evidence: README.md
Requirements
Runtimes: Python >=3.11
Databases: SQLite
API keys (by name): GROQ_API_KEY, OLW_API_KEY
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)
Set it up
This brain runs code automatically: 1 script. Review install.py before opening the folder in Claude Code. No step below turns a hook on for you.
install.py:python install.py
Clone the repository at the commit AutoGineer scanned:
git clone https://github.com/kytmanov/obsidian-llm-wiki-local.git && cd obsidian-llm-wiki-local && git checkout ad2e425f20f348154dde19d7c895b9bba69b7ad5Claude Code reads CLAUDE.md from this folder automatically.
cd obsidian-llm-wiki-local && claude
AutoGineer scanned these files at commit ad2e425.
- Not scanned by AutoGineerThe author’s README also describes installing it from a clone of its repository. Read its install section: AutoGineer did not scan that path. https://github.com/kytmanov/obsidian-llm-wiki-local/blob/ad2e425f20f348154dde19d7c895b9bba69b7ad5/README.md#1-install
- Not scanned by AutoGineerThe author’s README also describes installing it from a clone of its repository. Read its install section: AutoGineer did not scan that path. https://github.com/kytmanov/obsidian-llm-wiki-local/blob/ad2e425f20f348154dde19d7c895b9bba69b7ad5/README.md#running-the-tests
- Not scanned by AutoGineerIts dependencies are installed by pip or uv when you run it and were not scanned by AutoGineer (7 declared). https://pypi.org/project/obsidian-llm-wiki/
First committed by kytmanov. Published in kytmanov/obsidian-llm-wiki-local. Licence: MIT License.
Usage
AutoGineer overview, from the brain’s own files
- Automating the creation of a structured wiki from raw notes.
- Maintaining a personal knowledge base that grows and links concepts automatically.
- Querying a local knowledge base to synthesize answers from existing notes.
- Managing knowledge locally without relying on cloud-based vector databases or embeddings.
- Iteratively refining wiki content through an interactive review and feedback process.
- “olw watch”
- Starts a background process that automatically ingests and compiles any new Markdown files dropped into the raw/ folder.
- “olw query "What is backpropagation?"”
- Generates an answer based on the existing wiki content without using embeddings or a vector database.
- “olw review”
- Opens an interactive menu to approve or reject generated wiki drafts, allowing for manual refinement.
- “olw compare --heavy-model qwen2.5:14b”
- Builds an isolated preview vault to test how a different model performs before committing to a configuration change.
Documentation by kytmanov
obsidian-llm-wiki
<p align="center"> <a href="https://pepy.tech/projects/obsidian-llm-wiki"><img src="https://static.pepy.tech/personalized-badge/obsidian-llm-wiki?period=total&units=NONE&left_color=BLACK&right_color=GREEN&left_text=downloads" alt="PyPI Downloads"></a> <a href="https://github.com/kytmanov/obsidian-llm-wiki-local/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/kytmanov/obsidian-llm-wiki-local?style=flat"></a> <a href="https://github.com/kytmanov/obsidian-llm-wiki-local/network/members"><img alt="GitHub forks" src="https://img.shields.io/github/forks/kytmanov/obsidian-llm-wiki-local?style=flat"></a> <a href="https://github.com/kytmanov/obsidian-llm-wiki-local/commits/master"><img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/kytmanov/obsidian-llm-wiki-local?style=flat"></a> <a href="https://github.com/kytmanov/obsidian-llm-wiki-local/actions/workflows/ci.yml"><img alt="CI status" src="https://img.shields.io/github/actions/workflow/status/kytmanov/obsidian-llm-wiki-local/ci.yml?style=flat&label=CI"></a> <a href="https://pypi.org/project/obsidian-llm-wiki/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/obsidian-llm-wiki?style=flat"></a> </p>
Turn your raw notes into a self-improving, interlinked wiki — powered by a local LLM.
Drop a markdown file into a folder. The pipeline reads it, extracts concepts, and creates or updates wiki articles. If a draft is wrong, reject it and explain why; the next compile addresses your feedback. Over time, every note you add and every draft you review makes the wiki smarter.
Local-first, provider-flexible. Runs 100% locally with Ollama by default. Also works with any OpenAI-compatible endpoint — Groq, Together AI, LM Studio, vLLM, Azure OpenAI, and more.
NOTE
obsidian-llm-wiki is now in maintenance mode. → Check out SyntoBug fixes will continue. New features are being developed in Synto — the successor with a broader scope than the Obsidian LLM wiki pattern.
Migration is handled by Synto's migration command: point it at your existing vault and it converts the project to Synto's format. Your notes and wiki content remain the source of truth. If you're happy with what this tool does today, it keeps working; when you're ready for more, Synto provides the upgrade path.
<p align="center"> <img width="400" height="390" alt="image" src="https://github.com/user-attachments/assets/0b3998bd-af4d-4f3f-a2da-8334a0e81711"/> </p>
The idea (Karpathy's LLM Wiki)
This project is a practical implementation of the pattern described by Andrej Karpathy in "The LLM Wiki" — a vision for a personal knowledge base where:
"The LLM doesn't just store what you tell it — it synthesizes, cross-references, and keeps everything current. You add raw material; it does the bookkeeping."
The key insight: treat your notes as source material, not as the final artifact. The LLM compiles them into a structured wiki that grows smarter as you add more. Unlike a chatbot that forgets, the wiki persists and compounds.
You write raw notes → LLM extracts concepts → Wiki articles created/updated
raw/ (automatic) wiki/
quantum.md "Qubit", "Superposition" Qubit.md ←──┐
ml-basics.md "Neural Network", "SGD" Superposition.md │
physics.md "Qubit" (again!) Neural Network.md │
↑ linked via [[wikilinks]]The wiki lives in Obsidian, so you get the graph view, backlinks, and Dataview queries for free.
Features
Incremental compiles. Each concept gets its own article. When you change a source note, only the articles tied to that note recompile, not the whole vault.
File watcher. Run olw watch once and it processes anything you drop into raw/ automatically. Ingest and compile run in the background, so the wiki keeps improving while you keep writing notes.
Rejection feedback. Reject a draft and attach a reason. The next compile of that concept includes your feedback in the prompt, so the model can address it. Five rejections without an approval auto-blocks the concept until you re-enable it.
Hand-edits are preserved. Edit an article in Obsidian and the compiler will detect the change on the next run and skip it. Your edits aren't overwritten by regeneration.
Query and synthesize. olw query "what is X?" answers from your published wiki without embeddings or a vector DB. With --synthesize it saves the answer as a permanent wiki page, complete with source hashes and the same hand-edit protection.
Self-maintenance. Aliases like PC for Program Counter are extracted at ingest and used to repair broken wikilinks. olw lint reports orphans and stale articles; olw maintain --fix rewrites alias links and creates stubs for missing targets.
Provider-flexible. Ollama by default, fully offline. You can also point it at Groq, Together AI, LM Studio, vLLM, Azure OpenAI, or any OpenAI-compatible endpoint via olw setup. olw compare previews a switch in isolated vaults so you can decide before editing wiki.toml.
Multi-language. Each note's language is auto-detected at ingest and the article is written in that language. Extraction rules don't depend on hard-coded word lists, so any language works.
Git-aware. Every automatic action commits with an [olw] prefix, and olw undo reverts the last one. Raw notes are never modified; olw only writes to wiki/ and .olw/.
Quick start
1. Install
From PyPI (recommended):
pip install obsidian-llm-wikiOr with uv:
uv tool install obsidian-llm-wikiFrom source (latest development version):
git clone https://github.com/kytmanov/obsidian-llm-wiki-local
cd obsidian-llm-wiki-local
python install.pyinstall.py detects uv or falls back to pip, verifies the install, and tells you to run the next step.
2. Install and start Ollama
# Install Ollama: https://ollama.com/download
ollama pull gemma4:e4b # fast model — analysis and routing
ollama pull qwen2.5:14b # heavy model — article writing (optional, 7B+ recommended)Minimal setup: pull only
gemma4:e4band set bothfastandheavyto it in the wizard.
3. Run the setup wizard
olw setupAn interactive wizard selects a provider, configures the URL and optional API key, picks fast and heavy models, sets an optional default vault, and offers experimental features. Takes ~30 seconds.
╭──────────────────────────────────────────────────╮
│ obsidian-llm-wiki · setup │
╰──────────────────────────────────────────────────╯
Step 1 Provider
Local (no API key needed):
1. Ollama http://localhost:11434 [default]
2. LM Studio http://localhost:1234/v1
3. vLLM http://localhost:8000/v1
...
Cloud (API key required):
10. Groq https://api.groq.com/openai/v1
11. Together AI https://api.together.xyz/v1
...
Select provider (number or name) [1]: _
Step 2 URL
Base URL [http://localhost:11434]: _
✓ connected
Step 3 Fast model (analysis & routing · 3–8B recommended)
# Model Size
1 gemma4:e4b 9.6 GB
2 phi4-mini 2.5 GB
Select (number or name) [1]: _
...Settings are saved to ~/.config/olw/config.toml (Mac/Linux) or %APPDATA%\olw\config.toml (Windows). API keys are stored only in this user-private file, never in wiki.toml.
Experimental setup choices are saved only as defaults for new vaults. Runtime behavior is controlled by each vault's wiki.toml.
4. Set up your vault
olw init ~/my-wikiThis creates the folder structure and a wiki.toml pre-filled with your setup wizard choices.
To enable experimental inline source citations for an existing vault:
olw config inline-source-citations on --vault ~/my-wiki
olw config inline-source-citations status --vault ~/my-wikiTurn them off at any time with:
olw config inline-source-citations off --vault ~/my-wikiManual fallback:
[pipeline]
inline_source_citations = true5. Add some notes
Drop any .md files into ~/my-wiki/raw/. Web clips, book notes, meeting notes, anything.
~/my-wiki/raw/
quantum-computing.md
ml-fundamentals.md
physics-lecture.md6. Run the full pipeline
# One command: ingest + compile + lint + optional auto-approve
olw run
# Or step by step:
olw ingest --all
olw compile
olw review # interactive draft reviewIf you set a default vault in olw setup, the --vault flag is optional. Otherwise use --vault ~/my-wiki or export OLW_VAULT=~/my-wiki.
Open ~/my-wiki as an Obsidian vault. The graph view shows your connected wiki.
Before approving drafts, use a draft-review graph filter:
-path:raw -path:wiki/sources -path:_resources -file:WelcomeAfter approving drafts, use a published-only graph filter:
-path:raw -path:wiki/sources -path:wiki/.drafts -path:_resources -file:WelcomeThe published-only filter hides wiki/.drafts, so it will look empty until drafts are approved. Run olw doctor to print graph guidance for the current vault.
Want to preview a model or provider switch before changing wiki.toml?
olw compare --heavy-model qwen2.5:14bolw compare rebuilds isolated preview vaults from the same raw/ notes and tells you whether to switch, keep your current config, or review the diffs manually.
7. Keep it running (optional)
olw watch
# Drop a file in raw/ → ingest + compile happen automatically (selective: only linked concepts)Query synthesis
olw query answers from the published wiki without embeddings. Use --save to keep a dated Q&A note in wiki/queries/, or --synthesize to publish a reusable synthesis page in wiki/synthesis/.
# Just answer in the terminal
olw query "What is backpropagation?"
# Save a dated Q&A note under wiki/queries/
olw query "What is backpropagation?" --save
# Save a reusable synthesis article under wiki/synthesis/
olw query "What is backpropagation?" --synthesizeSynthesis behavior:
synthesis pages are published notes tagged with
synthesisthey store the source question, selected source pages, and source page body hashes in frontmatter
wiki/index.mdincludes a capped## Synthesissection sourced from the DB, ordered by newest first and then titlecompare runs stay side-effect-free: query evaluation never writes to the active vault during
olw comparequery-time synthesis does not create a new
[olw]git commit
Duplicate handling:
default behavior is
keep_existingfor the same normalized questioninteractive terminals only prompt for a strategy when a duplicate already exists
save_with_suffixkeeps the existing page and writes a new suffixed fileupdate_in_placerewrites the existing synthesis only when its body still matches the DB-tracked hashif the existing synthesis was manually edited,
update_in_placerefuses to overwrite itsynthesis pages cannot cite another synthesis page as a source
Compare a new model or provider
olw compare is a vault switch advisor, not a benchmark harness. It compares your
current vault config against one challenger config using the same active vault and
the same raw/ notes.
# Same provider, different heavy model
olw compare --heavy-model qwen2.5:14b
# Try a different local provider
olw compare \
--provider lm_studio \
--provider-url http://localhost:1234/v1 \
--fast-model google/gemma-4-e4b \
--heavy-model google/gemma-4-e4b
# Quick spot-check on a large vault
olw compare --heavy-model qwen2.5:14b --sample-n 20What it does:
rebuilds the current config and challenger config in isolated preview vaults
writes reports under
.olw/compare/<run_id>/leaves your active
raw/andwiki/untouched and does not modify active.olw/state outside.olw/compare/returns one verdict:
switch,keep_current, ormanual_review
Useful options:
--queries path/to/queries.tomladds a few representative questions to the comparison--out /tmp/my-comparewrites artifacts outside the vault if you want to inspect them elsewhere--keep-artifactsretains the ephemeral preview vaults instead of deleting them after the run--sample-n Nlimits the preview to the firstNraw notes for a fast spot-check--allow-cloud-uploadis required when the challenger uses a cloud provider
Notes:
compare previews automated generated output, not the final curated vault after human review
the report includes a ready-to-copy
wiki.tomlsnippet for the challenger when the verdict isswitch
Minimal queries.toml example:
[[query]]
id = "backprop"
question = "What is backpropagation?"
expected_contains = ["chain rule"]Reports are written as Markdown and JSON by default:
report.md— recommendation-first summary with next stepsreport.json— full machine-readable reportsummary.json— compact verdict and reason summary
How it works
The pipeline has three stages, each using the LLM for a different purpose:
raw/note.md
│
▼ olw ingest (or olw run)
Fast LLM (3B–8B)
• Reads note
• Extracts concept names
• Preserves explicitly evidenced named references as knowledge item candidates
• Writes quality score + summary to state.db
• Creates wiki/sources/Note.md (source summary page)
│
▼ olw compile
Heavy LLM (7B–14B)
• For each concept: gathers all source notes that mention it
• Injects rejection feedback from previous reviews into the prompt
• Writes a wiki article with [[wikilinks]] to related concepts
• Adds quality annotations if confidence is low or sources are sparse
• Lands in wiki/.drafts/ for review
│
▼ olw review (or olw approve)
• Interactive numbered menu — approve / reject / diff / edit
• Rejection feedback stored and injected into next compile
• On approve: annotations stripped, article published to wiki/
• Updates wiki/index.md (navigation layer)
• Git commits the changeNo vector databases, no embeddings. wiki/index.md acts as the routing layer for olw query. This keeps the setup simple and works well up to ~100 source notes.
The pipeline is intentionally conservative. Strong concepts become draft articles; explicitly evidenced named references become auditable knowledge item candidates. This keeps source-specific names visible without generating low-evidence articles from them.
Multi-language support
olw detects the language of each raw note during ingest and stores it. At compile time, the article is written in that language — no configuration needed.
Extraction and cleanup are designed to be language-agnostic. The pipeline avoids hard-coded natural-language word lists for title/entity promotion. Instead, it uses structural evidence, explicit source evidence, and conservative confidence levels so notes in any language follow the same rules.
How it works:
Ingest — the fast model detects the primary language and stores an ISO 639-1 code (
en,fr,de, …) per note in the state DB.Compile — when all source notes for a concept share the same language, the heavy model is instructed to write the article in that language. If sources are mixed, it falls back to matching the source text.
Config override — set
languageinwiki.tomlto force a specific output language for the whole vault, regardless of what the model detected.
[pipeline]
language = "fr" # all articles will be written in FrenchLeave language unset (the default) to let auto-detection drive it per concept.
Example: a French note ingested alongside English notes produces a French article for French-only concepts and an English article for concepts sourced from English notes. Setting language = "en" forces everything to English.
This language setting controls generated article language only. It does not enable language-specific concept merging or ontology decisions.
Knowledge item candidates
Not every useful reference deserves a wiki article. During ingest, olw keeps a separate knowledge item ledger for ambiguous, low-evidence references found explicitly in notes:
LLM-proposed named references accepted only when the exact text appears in the title, filename, or body
structurally prominent quoted titles, such as
"A Practical Guide To Notes"confirmed concepts mirrored into the ledger as confirmed knowledge items
These items are not compiled into articles by default. They are preserved for later review, classification, or future evidence accumulation.
olw items audit
olw items show "Example Reference"This is deliberately conservative: a named reference should not become a concept article unless the source content supports it. The item ledger keeps the reference from disappearing while avoiding hallucinated articles.
Rejection feedback loop
When you reject a draft:
olw review
# Select draft → [r]eject → "The overview section is too vague, needs concrete examples"The feedback is stored in the state database. On the next compile of that concept, the prompt includes:
PREVIOUS REJECTIONS — address these issues:
- The overview section is too vague, needs concrete examplesAfter 5 rejections of the same concept without an approval, the concept is auto-blocked and excluded from future compiles until you explicitly re-enable it:
olw unblock "Quantum Computing"Draft annotations
Drafts with low confidence or sparse sources are annotated with HTML comments that are invisible in Obsidian's preview but visible in the editor:
<!-- olw-auto: low-confidence (0.32) — verify before publishing -->
<!-- olw-auto: single-source — cross-reference recommended -->
## Overview
...Annotations are stripped automatically when you approve a draft. olw review surfaces them as a warning in the draft list.
Vault structure
my-wiki/
├── raw/ ← YOUR NOTES (never modified by olw)
│ ├── quantum-computing.md
│ └── ml-fundamentals.md
├── wiki/
│ ├── Quantum Computing.md ← concept articles (flat, one per concept)
│ ├── Machine Learning.md
│ ├── sources/ ← auto-generated source summaries
│ │ ├── Quantum Computing Fundamentals.md
│ │ └── ML Fundamentals.md
│ ├── queries/ ← saved Q&A answers (olw query --save)
│ ├── synthesis/ ← saved synthesis articles (olw query --synthesize)
│ ├── .drafts/ ← pending human review
│ ├── index.md ← auto-generated navigation + routing layer
│ └── log.md ← append-only operation history
├── vault-schema.md ← LLM context: conventions for this vault
├── wiki.toml ← configuration
└── .olw/
├── compare/ ← compare reports + optional preview vault artifacts
├── state.db ← SQLite: notes, concepts, articles, items, rejections, stubs
└── pipeline.lock ← advisory lock (auto-released when the holding process exits)raw/ is immutable — olw never writes to it. All metadata lives in state.db.
Configuration
wiki.toml (created by olw init):
[models]
fast = "gemma4:e4b" # extraction, analysis, query routing
heavy = "qwen2.5:14b" # article generation, Q&A answers
# Single-model: set heavy = fast
# ── Local Ollama (default) ────────────────────────────────────────────────────
[ollama]
url = "http://localhost:11434" # supports LAN: http://192.168.1.x:11434
timeout = 600
fast_ctx = 16384 # context window for fast model (tokens)
heavy_ctx = 32768 # context window for heavy model (tokens)
# ── Any other provider (replaces [ollama] when present) ──────────────────────
# [provider]
# name = "groq" # or lm_studio, vllm, together, azure, custom …
# url = "https://api.groq.com/openai/v1"
# timeout = 120
# fast_ctx = 8192
# heavy_ctx = 32768
# azure_api_version = "2024-02-15-preview" # Azure only
[pipeline]
auto_approve = false # true = skip draft review
auto_commit = true # git commit after each operation
auto_maintain = false # true = run maintain checks after each compile
max_concepts_per_source = 8 # limit concepts extracted per note
watch_debounce = 3.0 # seconds after last file event before processing
ingest_parallel = false # true = parallel chunk analysis (needs OLLAMA_NUM_PARALLEL>=4)
# language = "en" # ISO 639-1 output language; autodetects from notes if unset
# inline_source_citations = false
# source_citation_style = "legend-only" # legend-only | inline-wikilink
# draft_media = "reference" # reference | embed | omitAPI keys are never stored in
wiki.toml. They are read at runtime from the provider-specific env var (e.g.GROQ_API_KEY), the genericOLW_API_KEYenv var, or theapi_keyfield in~/.config/olw/config.toml(written byolw setup).
Tuning context windows
heavy_ctx controls how much source material the heavy model reads when writing articles (source budget = heavy_ctx / 2 chars) and how long the generated article can be. Defaults target 16 GB VRAM. If you use a model with a large context window (e.g. gemma4:e4b supports 128K), increase it.
| VRAM | Recommended heavy_ctx | Source budget | Notes |
|---|---|---|---|
| 8 GB | 8192 | ~4K chars | Minimum; short articles |
| 16 GB | 32768 | ~16K chars | Default |
| 32 GB+ | 65536 | ~32K chars | Rich multi-source articles |
fast_ctx controls ingest analysis. Notes longer than fast_ctx / 2 chars are automatically split into chunks and analyzed in sequence — all content is covered, no truncation.
| VRAM | Recommended fast_ctx | Notes per chunk |
|---|---|---|
| 8 GB | 8192 | ~4K chars |
| 16 GB | 16384 | ~8K chars — Default |
| 32 GB+ | 32768 | ~16K chars |
Speeding up long-note ingest
For vaults with many long notes (>8K chars), enable parallel chunk analysis:
[pipeline]
ingest_parallel = true # requires OLLAMA_NUM_PARALLEL>=4Also set in your shell before starting Ollama:
OLLAMA_NUM_PARALLEL=4 ollama serveThis lets Ollama process multiple chunks simultaneously. On 16 GB VRAM with gemma4:e4b (9.6 GB), 4 parallel slots fit comfortably (~12.8 GB total). Wall time for a 25K-char note drops from ~39s to ~14s.
After editing wiki.toml, no reinstall is needed. Run olw compile --force to regenerate articles with the new context budget.
Commands
| Command | Description |
|---|---|
olw setup | Interactive setup wizard: pick provider, models, vault |
olw init PATH | Create vault structure and git repo |
olw init PATH --existing | Adopt an existing Obsidian vault |
olw doctor | Check provider connectivity, models, vault structure |
olw run | Full pipeline: ingest → compile → lint → [approve] |
olw run --auto-approve | Full pipeline, publish without review |
olw run --dry-run | Report what would happen, make no changes |
olw compare --heavy-model MODEL | Compare current vault config against one challenger model |
olw compare --provider NAME --provider-url URL ... | Compare a provider switch safely in isolated preview vaults |
olw ingest --all | Analyze all raw notes |
olw ingest FILE | Analyze one note |
olw compile | Generate wiki articles → .drafts/ |
olw compile --retry-failed | Retry previously failed notes |
olw review | Interactive draft review (approve / reject / diff) |
olw approve --all | Publish all drafts without review |
olw approve FILE | Publish one draft |
olw reject FILE | Discard a draft (prompts for feedback) |
olw reject FILE --feedback "..." | Discard with feedback for next compile |
olw reject --all | Discard all drafts (prompts once for shared feedback) |
olw reject --all --feedback "..." | Discard all drafts with feedback |
olw unblock "Concept" | Re-enable a concept blocked after 5 rejections |
olw maintain | Health check + stubs + orphan and merge suggestions |
olw maintain --fix | Repair broken alias links, create stubs, normalize alias wikilinks |
olw maintain --dry-run | Report issues without making changes |
olw items audit | Show preserved non-concept knowledge item candidates |
olw items show NAME | Show one knowledge item and its source mentions |
olw status | Show pipeline state and pending drafts |
olw status --failed | List failed notes with error messages |
olw query "question" | Answer from your wiki |
olw query "..." --save | Answer and save to wiki/queries/ |
olw query "..." --synthesize | Answer and save a synthesis article to wiki/synthesis/ |
olw lint | Health check: orphans, broken links, stale articles |
olw lint --fix | Auto-fix missing frontmatter fields |
olw watch | File watcher — auto-pipeline on new notes |
olw watch --auto-approve | Watch + auto-publish (no manual review) |
olw undo | Revert last [olw] git commit |
olw clean | Clear state DB + wiki/, keep raw/ notes |
All commands accept --vault PATH or the env var OLW_VAULT.
Providers
Run olw setup to pick a provider interactively. All providers are also configurable directly in wiki.toml.
| Provider | Type | Embeddings | Notes |
|---|---|---|---|
| Ollama | local | ✓ | default; full offline |
| LM Studio | local | ✓ | |
| vLLM | local | ✓ | |
| llama.cpp | local | — | |
| LocalAI | local | ✓ | |
| TGI | local | — | |
| SGLang | local | ✓ | |
| Llamafile | local | — | |
| Lemonade | local | — | |
| Groq | cloud | — | fast inference, free tier |
| Together AI | cloud | ✓ | |
| Fireworks AI | cloud | ✓ | |
| DeepInfra | cloud | ✓ | |
| OpenRouter | cloud | — | routes to many models |
| Mistral AI | cloud | ✓ | |
| DeepSeek | cloud | — | |
| SiliconFlow | cloud | ✓ | |
| Perplexity | cloud | — | |
| xAI (Grok) | cloud | — | |
| Azure OpenAI | cloud | ✓ | see azure_api_version |
| Custom | any | — | enter URL manually |
RAG (embeddings) requires a provider that supports /v1/embeddings. The default index-based query works with all providers.
Model recommendations
| Role | Ollama | Cloud |
|---|---|---|
| Fast (analysis + routing) | gemma4:e4b, llama3.2:3b | llama-3.1-8b-instant (Groq), mistral-7b |
| Heavy (article writing) | qwen2.5:14b, llama3.1:8b | llama-3.3-70b (Groq), mistral-large |
| Single model (everything) | llama3.1:8b, mistral:7b | any 7B+ |
Any model with JSON format / response_format: json_object support works. The tool degrades gracefully with smaller models.
Obsidian tips
Graph view — concept pages link to source pages and each other via
[[wikilinks]]; before approval use-path:raw -path:wiki/sources -path:_resources -file:Welcome, after approval add-path:wiki/.draftsSource citations — when inline citations are enabled, the default style stays graph-quiet as
[S1](#Sources)links while source pages link once in## Sources; setsource_citation_style = "inline-wikilink"if you want every citation to create a source edgeMedia — source pages preserve
![[media]]embeds; generated drafts default to plain media references to avoid attachment nodes dominating the graph (draft_media = "reference")Draft review — drafts live in
wiki/.drafts/and may not appear in Obsidian's default graph filters; useolw doctorfor the recommended draft-review and published-only filtersDataview — query by
status: published,confidence: > 0.7,tags: [physics], etc.Backlinks — every concept page shows which source pages mention it
Web Clipper — save web articles directly to
raw/(see docs/web-clipper-setup.md)
Quality principles for contributors and AI agents
Prefer deterministic, auditable cleanup over broad LLM-driven merging.
Do not use LLM aliases as automatic merge authority; aliases are weak evidence.
Keep concept extraction language-agnostic. Avoid hard-coded English or other language-specific word lists unless the feature is explicitly scoped to that language.
Preserve weak entity references as knowledge item candidates rather than generating unsupported concept articles.
Source pages and
[S1](#Sources)citations should remain graph-quiet by default; source-page edges belong in## Sources.Generated drafts should avoid media embeds by default. Source pages can preserve embeds; draft articles should usually contain plain media references.
Raw notes are immutable. All generated state belongs under
wiki/and.olw/.
Running the tests
All tests are offline — no Ollama required.
git clone https://github.com/kytmanov/obsidian-llm-wiki-local
cd obsidian-llm-wiki-local
uv sync --group dev
uv run pytestFor the full end-to-end smoke test (requires a running provider):
# Ollama (default)
bash scripts/smoke_test.sh
# LM Studio or any other OpenAI-compatible endpoint
PROVIDER=lm_studio bash scripts/smoke_test.sh
# LM Studio with the validated local baseline model
PROVIDER=lm_studio FAST_MODEL=gemma4:e4b HEAVY_MODEL=gemma4:e4b \
bash scripts/smoke_test.sh
# Compare smoke test
PROVIDER=lm_studio FAST_MODEL=gemma4:e4b HEAVY_MODEL=gemma4:e4b \
bash scripts/compare_smoke.shIf LM Studio rejects the short alias, use the exact loaded model id it reports, for example google/gemma-4-e4b.
FAQ
Q: I ran olw compile but nothing appears in Obsidian.
Drafts land in wiki/.drafts/ — Obsidian hides dotfolders by default so they won't show in the graph yet. Run:
olw review # interactive review
# or
olw approve --allArticles move to wiki/ and become fully visible.
Q: Compile says "2 article(s) failed: Methodology, Sprints" — what do I do?
Failed concepts are retried automatically on the next run. Or force a retry:
olw compile --retry-failedIf the same concepts keep failing, the LLM is likely struggling with JSON output for those specific titles. Try increasing heavy_ctx in wiki.toml (see Tuning context windows).
Q: I see structured_output attempt N failed messages during compile — is something broken?
No. This is the built-in 3-tier retry system working as designed. The model occasionally echoes the JSON schema structure instead of flat output — the retry corrects it. Articles are still generated. A real failure surfaces as article(s) failed: ... in the summary line.
Q: olw ingest --all && olw compile gives "Missing option '--vault'".
Run olw setup first to configure a default vault, or pass it explicitly:
export OLW_VAULT=~/my-wiki
olw ingest --all && olw compileQ: I changed models in olw setup but olw compile still uses the old model.
Re-run olw init on your vault — it syncs the model settings from your global config into wiki.toml:
olw init ~/my-wikiQ: A concept keeps getting rejected — how do I stop it from recompiling?
After 5 rejections with feedback (olw reject --feedback "…"), the concept is auto-blocked and excluded from future compiles. olw status lists blocked concepts. To re-enable one:
olw unblock "Concept Name"Q: Can I use a cloud provider like Groq or Together AI instead of Ollama?
Yes. Run olw setup and select the provider from the numbered list. Enter your API key when prompted — it is stored only in ~/.config/olw/config.toml. Alternatively set the provider-specific env var before each command:
export GROQ_API_KEY=gsk_...
olw runThe pipeline, vault structure, and all olw commands work identically regardless of provider.
Q: I changed providers in olw setup but wiki.toml still shows [ollama].
Re-run olw init on your vault to sync the global config into wiki.toml:
olw init ~/my-wikiFor existing vaults with a [ollama] section you can also add a [provider] block manually — it takes precedence over [ollama] when present.
Why not just use a chatbot?
Chatbots forget. Every conversation starts fresh. This tool builds a persistent artifact — a wiki that grows with every note you add, that you can open in Obsidian, search, query, and edit by hand.
The LLM is a compiler, not a conversation partner. You give it raw material; it produces structured knowledge. The output is plain markdown files you own forever.
Feedback
olw does not collect telemetry.
If something was confusing, useful, annoying, or missing, please tell us:
Bug reports: https://github.com/kytmanov/obsidian-llm-wiki-local/issues
Suggestions and experience reports: https://github.com/kytmanov/obsidian-llm-wiki-local/discussions
Source code: https://github.com/kytmanov/obsidian-llm-wiki-local
License
MIT — see LICENSE.
AUTOGINEER-RUNS.md
What this brain runs
AutoGineer's scanner lists the code that "obsidian-llm-wiki-local" can run on your machine. Review each item before you open the folder in an agent or enable a plugin: nothing here is turned on for you.
install-script: install.py runs python install.py
116 files · 107 not served here
- .github/FUNDING.yml (not served here)
- .github/workflows/benchmark.yml (not served here)
- .github/workflows/ci.yml (not served here)
- .github/workflows/release.yml (not served here)
- .gitignore (not served here)
- ATTRIBUTION.md
- AUTOGINEER-RUNS.md
- CHANGELOG.md
- CLAUDE.md
- LICENSE
- README.md
- RELEASE.md
- docs/issue-30-inline-source-citations-plan.md
- docs/web-clipper-setup.md
- install.py (not served here)
- pyproject.toml (not served here)
- scripts/benchmark.sh (not served here)
- scripts/compare_smoke.sh (not served here)
- scripts/release.sh (not served here)
- scripts/smoke_test.sh (not served here)
- src/obsidian_llm_wiki/__init__.py (not served here)
- src/obsidian_llm_wiki/cli.py (not served here)
- src/obsidian_llm_wiki/client_factory.py (not served here)
- src/obsidian_llm_wiki/compare/__init__.py (not served here)
- src/obsidian_llm_wiki/compare/metrics.py (not served here)
- src/obsidian_llm_wiki/compare/models.py (not served here)
- src/obsidian_llm_wiki/compare/report.py (not served here)
- src/obsidian_llm_wiki/compare/runner.py (not served here)
- src/obsidian_llm_wiki/config.py (not served here)
- src/obsidian_llm_wiki/engines.py (not served here)
- src/obsidian_llm_wiki/git_ops.py (not served here)
- src/obsidian_llm_wiki/global_config.py (not served here)
- src/obsidian_llm_wiki/indexer.py (not served here)
- src/obsidian_llm_wiki/markdown_math.py (not served here)
- src/obsidian_llm_wiki/models.py (not served here)
- src/obsidian_llm_wiki/ollama_client.py (not served here)
- src/obsidian_llm_wiki/openai_compat_client.py (not served here)
- src/obsidian_llm_wiki/pipeline/__init__.py (not served here)
- src/obsidian_llm_wiki/pipeline/compile.py (not served here)
- src/obsidian_llm_wiki/pipeline/ingest.py (not served here)
- src/obsidian_llm_wiki/pipeline/items.py (not served here)
- src/obsidian_llm_wiki/pipeline/lint.py (not served here)
- src/obsidian_llm_wiki/pipeline/lock.py (not served here)
- src/obsidian_llm_wiki/pipeline/maintain.py (not served here)
- src/obsidian_llm_wiki/pipeline/orchestrator.py (not served here)
- src/obsidian_llm_wiki/pipeline/query.py (not served here)
- src/obsidian_llm_wiki/pipeline/review.py (not served here)
- src/obsidian_llm_wiki/protocols.py (not served here)
- src/obsidian_llm_wiki/providers.py (not served here)
- src/obsidian_llm_wiki/readers.py (not served here)
- src/obsidian_llm_wiki/sanitize.py (not served here)
- src/obsidian_llm_wiki/state.py (not served here)
- src/obsidian_llm_wiki/structured_output.py (not served here)
- src/obsidian_llm_wiki/telemetry.py (not served here)
- src/obsidian_llm_wiki/vault.py (not served here)
- src/obsidian_llm_wiki/watcher.py (not served here)
- tests/compare_corpus/corpus.toml (not served here)
- tests/compare_corpus/notes/ambiguous_entity.md (not served here)
- tests/compare_corpus/notes/cross_reference.md (not served here)
- tests/compare_corpus/notes/data_heavy_table.md (not served here)
- tests/compare_corpus/notes/edge_empty_list.md (not served here)
- tests/compare_corpus/notes/long_dense_technical.md (not served here)
- tests/compare_corpus/notes/moderate_overlap.md (not served here)
- tests/compare_corpus/notes/multi_concept_overlap.md (not served here)
- tests/compare_corpus/notes/narrative_essay.md (not served here)
- tests/compare_corpus/notes/noisy_low_quality.md (not served here)
- tests/compare_corpus/notes/short_factual.md (not served here)
- tests/compare_corpus/queries.toml (not served here)
- tests/conftest.py (not served here)
- tests/fixtures/analysis_valid.json (not served here)
- tests/fixtures/compile_plan_valid.json (not served here)
- tests/fixtures/single_article_valid.json (not served here)
- tests/test_benchmarks.py (not served here)
- tests/test_cli_compile.py (not served here)
- tests/test_cli_model_flags.py (not served here)
- tests/test_cli_query.py (not served here)
- tests/test_cli_reject.py (not served here)
- tests/test_cli_status.py (not served here)
- tests/test_cli_support.py (not served here)
- tests/test_compare_cli.py (not served here)
- tests/test_compare_metrics.py (not served here)
- tests/test_compare_report.py (not served here)
- tests/test_compare_runner.py (not served here)
- tests/test_compare_safety.py (not served here)
- tests/test_compile.py (not served here)
- tests/test_compile_v2.py (not served here)
- tests/test_config.py (not served here)
- tests/test_indexer.py (not served here)
- tests/test_ingest.py (not served here)
- tests/test_items.py (not served here)
- tests/test_lint.py (not served here)
- tests/test_lock.py (not served here)
- tests/test_maintain.py (not served here)
- tests/test_markdown_math.py (not served here)
- tests/test_ollama_client.py (not served here)
- tests/test_openai_compat_client.py (not served here)
- tests/test_orchestrator.py (not served here)
- tests/test_phase0_engines.py (not served here)
- tests/test_phase0_migration_v8.py (not served here)
- tests/test_phase0_readers.py (not served here)
- tests/test_phase0_schemas.py (not served here)
- tests/test_pipeline_language.py (not served here)
- tests/test_pipeline_reject_all.py (not served here)
- tests/test_providers.py (not served here)
- tests/test_query.py (not served here)
- tests/test_query_git_behavior.py (not served here)
- tests/test_query_synthesize.py (not served here)
- tests/test_review.py (not served here)
- tests/test_sanitize.py (not served here)
- tests/test_setup.py (not served here)
- tests/test_state.py (not served here)
- tests/test_structured_output.py (not served here)
- tests/test_telemetry.py (not served here)
- tests/test_vault.py (not served here)
- tests/test_watcher.py (not served here)
- uv.lock (not served here)
Advantages
- Operates 100% locally with Ollama, ensuring data privacy and no external dependency for processing. evidence: README.md
- Preserves manual edits made to wiki articles by detecting content changes and skipping them during recompilation. evidence: README.md
- Supports incremental compilation, which optimizes performance by only updating articles linked to modified source notes. evidence: README.md
- Provides an interactive feedback loop where rejected drafts incorporate user feedback into future model prompts. evidence: README.md
Limitations
- The system is currently in maintenance mode, with new features being developed in a successor project called Synto. evidence: README.md
- The query synthesis feature is optimized for smaller vaults and may be less efficient as the number of source notes grows significantly beyond 100. evidence: README.md
Security
Risk level: Low risk
This brain runs
Agent instructions that run or fetch something (11)
CLAUDE.md:# Install (editable, auto-detects uv/pip)CLAUDE.md:python install.pyCLAUDE.md:uv sync --group devCLAUDE.md:uv run pytestCLAUDE.md:uv run pytest tests/test_ingest.py::test_function_name -v # single testCLAUDE.md:uv run pytest --cov=src/obsidian_llm_wiki # with coverageCLAUDE.md:uv run ruff check src/ tests/CLAUDE.md:uv run ruff format --check src/ tests/CLAUDE.md:uv run ruff format src/ tests/ # auto-fixCLAUDE.md:# Smoke tests (user preference: run against LM Studio with gemma4:e4b)CLAUDE.md:`git_ops.py` — Auto-commit with `[olw]` prefix, safe undo via `git revert`
Install scripts (1)
install.py:python install.py
- Low risk: scripts-present (install.py)
- Low risk: scripts-present (scripts/compare_smoke.sh)
- Low risk: scripts-present (scripts/smoke_test.sh)
Attribution and licence
- First committed by
kytmanov
- Declared authors
- kytmanov (declared in pyproject.toml)
- Publisher
- Alexander (Community)
- Source
- kytmanov/obsidian-llm-wiki-local · commit ad2e425
- Licence
- MIT License (files served here)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- kytmanov, ys-qb
AutoGineer is not affiliated with or endorsed by kytmanov.
Install from source
107 of its files are not served here, so there is no ZIP. kytmanov/obsidian-llm-wiki-local at ad2e425