obsidian-notes-rag 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- obsidian_notes_rag-0.1.2/.github/workflows/ci.yml +42 -0
- obsidian_notes_rag-0.1.2/.github/workflows/release-please.yml +20 -0
- obsidian_notes_rag-0.1.2/.github/workflows/release.yml +50 -0
- obsidian_notes_rag-0.1.2/.gitignore +40 -0
- obsidian_notes_rag-0.1.2/.release-please-manifest.json +3 -0
- obsidian_notes_rag-0.1.2/CHANGELOG.md +39 -0
- obsidian_notes_rag-0.1.2/CLAUDE.md +85 -0
- obsidian_notes_rag-0.1.2/CONTRIBUTING.md +116 -0
- obsidian_notes_rag-0.1.2/LICENSE +21 -0
- obsidian_notes_rag-0.1.2/PKG-INFO +171 -0
- obsidian_notes_rag-0.1.2/PLAN.md +144 -0
- obsidian_notes_rag-0.1.2/README.md +149 -0
- obsidian_notes_rag-0.1.2/extras/com.obsidian-rag.watcher.plist +55 -0
- obsidian_notes_rag-0.1.2/pyproject.toml +47 -0
- obsidian_notes_rag-0.1.2/pyrightconfig.json +8 -0
- obsidian_notes_rag-0.1.2/release-please-config.json +17 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/__init__.py +3 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/cli.py +494 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/config.py +157 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/indexer.py +276 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/server.py +272 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/store.py +160 -0
- obsidian_notes_rag-0.1.2/src/obsidian_rag/watcher.py +330 -0
- obsidian_notes_rag-0.1.2/tests/__init__.py +1 -0
- obsidian_notes_rag-0.1.2/tests/test_indexer.py +77 -0
- obsidian_notes_rag-0.1.2/uv.lock +2496 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Install uv
|
|
16
|
+
uses: astral-sh/setup-uv@v4
|
|
17
|
+
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
run: uv python install 3.13
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: uv sync --dev
|
|
23
|
+
|
|
24
|
+
- name: Type check
|
|
25
|
+
run: uv run pyright
|
|
26
|
+
|
|
27
|
+
test:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
|
|
32
|
+
- name: Install uv
|
|
33
|
+
uses: astral-sh/setup-uv@v4
|
|
34
|
+
|
|
35
|
+
- name: Set up Python
|
|
36
|
+
run: uv python install 3.13
|
|
37
|
+
|
|
38
|
+
- name: Install dependencies
|
|
39
|
+
run: uv sync --dev
|
|
40
|
+
|
|
41
|
+
- name: Run tests
|
|
42
|
+
run: uv run pytest -v
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: Release Please
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
pull-requests: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
release-please:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: googleapis/release-please-action@v4
|
|
17
|
+
with:
|
|
18
|
+
release-type: python
|
|
19
|
+
config-file: release-please-config.json
|
|
20
|
+
manifest-file: .release-please-manifest.json
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
tag:
|
|
9
|
+
description: 'Git tag to publish (e.g., v0.1.0)'
|
|
10
|
+
required: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
ref: ${{ inputs.tag || github.ref }}
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v4
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
run: uv python install 3.11
|
|
25
|
+
|
|
26
|
+
- name: Build package
|
|
27
|
+
run: uv build
|
|
28
|
+
|
|
29
|
+
- name: Upload dist artifacts
|
|
30
|
+
uses: actions/upload-artifact@v4
|
|
31
|
+
with:
|
|
32
|
+
name: dist
|
|
33
|
+
path: dist/
|
|
34
|
+
|
|
35
|
+
publish:
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
environment: pypi
|
|
39
|
+
permissions:
|
|
40
|
+
contents: write
|
|
41
|
+
id-token: write
|
|
42
|
+
steps:
|
|
43
|
+
- name: Download dist artifacts
|
|
44
|
+
uses: actions/download-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
- name: Publish to PyPI
|
|
50
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
.venv/
|
|
25
|
+
venv/
|
|
26
|
+
ENV/
|
|
27
|
+
|
|
28
|
+
# IDE
|
|
29
|
+
.idea/
|
|
30
|
+
.vscode/
|
|
31
|
+
*.swp
|
|
32
|
+
*.swo
|
|
33
|
+
|
|
34
|
+
# Project specific
|
|
35
|
+
data/
|
|
36
|
+
.claude/
|
|
37
|
+
|
|
38
|
+
# OS
|
|
39
|
+
.DS_Store
|
|
40
|
+
Thumbs.db
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.2](https://github.com/ernestkoe/obsidian-rag/compare/v0.1.1...v0.1.2) (2026-01-04)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* disable attestations for token-based auth ([8d70f98](https://github.com/ernestkoe/obsidian-rag/commit/8d70f989f3e50c7d9f6a5f045d0cc767646c0686))
|
|
9
|
+
* use API token for PyPI publish ([51a2c09](https://github.com/ernestkoe/obsidian-rag/commit/51a2c0958e226b128a2a34c9ec0a8e2c75102a93))
|
|
10
|
+
|
|
11
|
+
## [0.1.1](https://github.com/ernestkoe/obsidian-rag/compare/v0.1.0...v0.1.1) (2026-01-04)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* add manual trigger to release workflow ([130dfd0](https://github.com/ernestkoe/obsidian-rag/commit/130dfd0cfddce817863998042ee783791b8204a9))
|
|
17
|
+
|
|
18
|
+
## 0.1.0 (2026-01-03)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### ⚠ BREAKING CHANGES
|
|
22
|
+
|
|
23
|
+
* Project renamed from obsidian-memory to mcp-obsidianRAG
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
* add file watcher daemon with launchd integration ([23d2429](https://github.com/ernestkoe/obsidian-rag/commit/23d2429c61d82e98610c0180f7044b807ad9cd60))
|
|
28
|
+
* add OpenAI embeddings and setup wizard ([e1e363e](https://github.com/ernestkoe/obsidian-rag/commit/e1e363ee26a70d82635d7c8bf2bec38afaf28383))
|
|
29
|
+
* consolidate CLI entry points for uvx workflow ([95eb546](https://github.com/ernestkoe/obsidian-rag/commit/95eb546b0a7d6d89d30da8d0dd4f7c4c64600657))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Documentation
|
|
33
|
+
|
|
34
|
+
* add TODOs for Linux/Windows service support ([569a830](https://github.com/ernestkoe/obsidian-rag/commit/569a830b5272c7fdd0c8ba826063b765706ecdcf))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Code Refactoring
|
|
38
|
+
|
|
39
|
+
* rename project to mcp-obsidianRAG ([16a83d9](https://github.com/ernestkoe/obsidian-rag/commit/16a83d9ebe142f25231a33824b7c27237f61da73))
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
obsidian-rag is an MCP (Model Context Protocol) server that provides semantic search over Obsidian notes. It uses OpenAI embeddings by default (or Ollama for local processing) with ChromaDB for vector storage.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Install dependencies
|
|
13
|
+
uv sync --dev
|
|
14
|
+
|
|
15
|
+
# Run tests
|
|
16
|
+
.venv/bin/python -m pytest -v
|
|
17
|
+
|
|
18
|
+
# Type checking
|
|
19
|
+
.venv/bin/python -m pyright
|
|
20
|
+
|
|
21
|
+
# Interactive setup wizard
|
|
22
|
+
uv run obsidian-rag setup
|
|
23
|
+
|
|
24
|
+
# Index vault (manual refresh)
|
|
25
|
+
uv run obsidian-rag index
|
|
26
|
+
|
|
27
|
+
# Run the MCP server (stdio transport)
|
|
28
|
+
uv run obsidian-rag serve
|
|
29
|
+
|
|
30
|
+
# Watch vault for changes
|
|
31
|
+
uv run obsidian-rag watch
|
|
32
|
+
|
|
33
|
+
# Search from CLI
|
|
34
|
+
uv run obsidian-rag search "query"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Architecture
|
|
38
|
+
|
|
39
|
+
### Data Flow
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Obsidian Vault → VaultIndexer → Embedder (OpenAI/Ollama) → VectorStore (ChromaDB)
|
|
43
|
+
↓
|
|
44
|
+
MCP Client ← FastMCP Server ← search_notes/get_similar/etc.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Key Components (src/obsidian_rag/)
|
|
48
|
+
|
|
49
|
+
- **config.py**: `Config` dataclass, `load_config()`/`save_config()` for TOML config file, cross-platform paths via `platformdirs`
|
|
50
|
+
- **indexer.py**: `VaultIndexer` scans markdown files, `chunk_by_heading()` splits content by `##`/`###` headings, `OpenAIEmbedder` and `OllamaEmbedder` generate embeddings, `create_embedder()` factory selects provider
|
|
51
|
+
- **store.py**: `VectorStore` wraps ChromaDB with cosine similarity search, handles upsert/delete by file path
|
|
52
|
+
- **server.py**: FastMCP server exposing 5 tools: `search_notes`, `get_similar`, `get_note_context`, `get_stats`, `reindex`
|
|
53
|
+
- **watcher.py**: `VaultWatcher` uses watchdog with debouncing (default 2s) to incrementally re-index on file changes
|
|
54
|
+
- **cli.py**: Click-based CLI with `setup` wizard, `--provider` option, commands for indexing, searching, watching, and service management
|
|
55
|
+
|
|
56
|
+
### Chunking Strategy
|
|
57
|
+
|
|
58
|
+
Files are split by `##` and `###` headings. Chunks smaller than `min_chunk_size` (default 100 chars) merge with the previous chunk. Files without headings become a single chunk.
|
|
59
|
+
|
|
60
|
+
### Metadata
|
|
61
|
+
|
|
62
|
+
Each chunk stores: `file_path`, `heading`, `heading_level`, `type` ("daily" if path starts with "Daily Notes/", else "note"), and tags from YAML frontmatter.
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
Config file location (created by `setup` command):
|
|
67
|
+
- macOS/Linux: `~/.config/obsidian-rag/config.toml`
|
|
68
|
+
- Windows: `%APPDATA%/obsidian-rag/config.toml`
|
|
69
|
+
|
|
70
|
+
Environment variables (override config file):
|
|
71
|
+
- `OPENAI_API_KEY` - OpenAI API key (required for default provider)
|
|
72
|
+
- `OBSIDIAN_RAG_PROVIDER` - `openai` (default) or `ollama`
|
|
73
|
+
- `OBSIDIAN_RAG_VAULT` - Path to Obsidian vault
|
|
74
|
+
- `OBSIDIAN_RAG_DATA` - ChromaDB storage path
|
|
75
|
+
- `OBSIDIAN_RAG_OLLAMA_URL` - Ollama API (default: `http://localhost:11434`)
|
|
76
|
+
- `OBSIDIAN_RAG_MODEL` - Override embedding model
|
|
77
|
+
|
|
78
|
+
## Testing
|
|
79
|
+
|
|
80
|
+
Tests are in `tests/`. Current coverage focuses on `test_indexer.py` for frontmatter parsing and chunking logic.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
# Run a specific test
|
|
84
|
+
uv run pytest tests/test_indexer.py::TestChunkByHeading::test_multiple_headings -v
|
|
85
|
+
```
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Contributing to obsidian-rag
|
|
2
|
+
|
|
3
|
+
## Development Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
# Clone the repository
|
|
7
|
+
git clone https://github.com/ernestkoe/obsidian-rag.git
|
|
8
|
+
cd obsidian-rag
|
|
9
|
+
|
|
10
|
+
# Install with dev dependencies
|
|
11
|
+
uv sync --dev
|
|
12
|
+
|
|
13
|
+
# Pull the embedding model
|
|
14
|
+
ollama pull nomic-embed-text
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Project Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
src/obsidian_rag/
|
|
21
|
+
├── __init__.py # Package version
|
|
22
|
+
├── cli.py # Click CLI commands
|
|
23
|
+
├── server.py # MCP server (FastMCP)
|
|
24
|
+
├── indexer.py # Markdown parsing, chunking, Ollama embeddings
|
|
25
|
+
├── store.py # ChromaDB vector store wrapper
|
|
26
|
+
└── watcher.py # File watcher daemon (watchdog)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
### Indexing Pipeline
|
|
32
|
+
|
|
33
|
+
1. **VaultIndexer** scans markdown files, excludes patterns (`.obsidian/`, etc.)
|
|
34
|
+
2. **parse_frontmatter()** extracts YAML frontmatter
|
|
35
|
+
3. **chunk_by_heading()** splits content by `##` and `###` headings
|
|
36
|
+
4. **OllamaEmbedder** generates embeddings via local Ollama API
|
|
37
|
+
5. **VectorStore** persists chunks + embeddings to ChromaDB
|
|
38
|
+
|
|
39
|
+
### MCP Server
|
|
40
|
+
|
|
41
|
+
The server exposes 5 tools via FastMCP:
|
|
42
|
+
- `search_notes` - Semantic search
|
|
43
|
+
- `get_similar` - Find similar notes
|
|
44
|
+
- `get_note_context` - Note + related context
|
|
45
|
+
- `get_stats` - Index statistics
|
|
46
|
+
- `reindex` - Re-index vault
|
|
47
|
+
|
|
48
|
+
### File Watcher
|
|
49
|
+
|
|
50
|
+
Uses watchdog to monitor the vault directory:
|
|
51
|
+
- Debounces rapid file changes (default 2s)
|
|
52
|
+
- Handles create/modify/delete/move events
|
|
53
|
+
- Can run as macOS launchd service
|
|
54
|
+
|
|
55
|
+
## Running Tests
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uv run pytest -v
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Type Checking
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
uv run pyright
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Code Style
|
|
68
|
+
|
|
69
|
+
- Python 3.11+
|
|
70
|
+
- Type hints required
|
|
71
|
+
- Docstrings for public functions
|
|
72
|
+
|
|
73
|
+
## Making Changes
|
|
74
|
+
|
|
75
|
+
1. Create a feature branch
|
|
76
|
+
2. Make changes with tests
|
|
77
|
+
3. Ensure `pytest` and `pyright` pass
|
|
78
|
+
4. Submit PR with conventional commit message
|
|
79
|
+
|
|
80
|
+
### Commit Messages
|
|
81
|
+
|
|
82
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/):
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
feat: add new search filter
|
|
86
|
+
fix: handle empty vault gracefully
|
|
87
|
+
docs: update installation instructions
|
|
88
|
+
refactor: simplify chunking logic
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Release Process
|
|
92
|
+
|
|
93
|
+
Releases are automated via [release-please](https://github.com/googleapis/release-please). When PRs with conventional commits are merged to `main`, release-please creates a release PR that bumps the version and updates the changelog.
|
|
94
|
+
|
|
95
|
+
## Environment Variables
|
|
96
|
+
|
|
97
|
+
For development, you can set these in your shell or a `.env` file:
|
|
98
|
+
|
|
99
|
+
| Variable | Default | Description |
|
|
100
|
+
|----------|---------|-------------|
|
|
101
|
+
| `OBSIDIAN_RAG_VAULT` | (hardcoded) | Path to Obsidian vault |
|
|
102
|
+
| `OBSIDIAN_RAG_DATA` | (hardcoded) | Path to ChromaDB data |
|
|
103
|
+
| `OBSIDIAN_RAG_OLLAMA_URL` | `http://localhost:11434` | Ollama API URL |
|
|
104
|
+
| `OBSIDIAN_RAG_MODEL` | `nomic-embed-text` | Embedding model |
|
|
105
|
+
| `OBSIDIAN_RAG_DEBOUNCE` | `2.0` | Watcher debounce seconds |
|
|
106
|
+
|
|
107
|
+
## Key Dependencies
|
|
108
|
+
|
|
109
|
+
| Package | Purpose |
|
|
110
|
+
|---------|---------|
|
|
111
|
+
| chromadb | Vector store |
|
|
112
|
+
| watchdog | File system monitoring |
|
|
113
|
+
| mcp | MCP server framework |
|
|
114
|
+
| httpx | HTTP client for Ollama |
|
|
115
|
+
| click | CLI framework |
|
|
116
|
+
| pyyaml | Frontmatter parsing |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ernest Koe
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: obsidian-notes-rag
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: MCP server for semantic search over Obsidian notes using local RAG
|
|
5
|
+
Project-URL: Homepage, https://github.com/ernestkoe/obsidian-rag
|
|
6
|
+
Project-URL: Repository, https://github.com/ernestkoe/obsidian-rag
|
|
7
|
+
Project-URL: Issues, https://github.com/ernestkoe/obsidian-rag/issues
|
|
8
|
+
Author: Ernest Koe
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Python: >=3.11
|
|
12
|
+
Requires-Dist: chromadb>=0.4.0
|
|
13
|
+
Requires-Dist: click>=8.0.0
|
|
14
|
+
Requires-Dist: httpx>=0.25.0
|
|
15
|
+
Requires-Dist: mcp>=1.0.0
|
|
16
|
+
Requires-Dist: openai>=1.0.0
|
|
17
|
+
Requires-Dist: platformdirs>=3.0.0
|
|
18
|
+
Requires-Dist: pyyaml>=6.0
|
|
19
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
20
|
+
Requires-Dist: watchdog>=3.0.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# obsidian-rag
|
|
24
|
+
|
|
25
|
+
[](https://opensource.org/licenses/MIT)
|
|
26
|
+
|
|
27
|
+
MCP server for semantic search over your Obsidian vault. Uses OpenAI embeddings by default (or Ollama for local processing) with ChromaDB for vector storage.
|
|
28
|
+
|
|
29
|
+
## What it does
|
|
30
|
+
|
|
31
|
+
Ask natural language questions about your notes:
|
|
32
|
+
- "What did I write about project planning?"
|
|
33
|
+
- "Find notes similar to my meeting notes from last week"
|
|
34
|
+
- "What's in my daily notes about the API refactor?"
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
- Python 3.11+
|
|
39
|
+
- `OPENAI_API_KEY` environment variable (or [Ollama](https://ollama.ai/) for local embeddings)
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
The easiest way to get started is with [uvx](https://docs.astral.sh/uv/guides/tools/) (no installation required):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Run the setup wizard
|
|
47
|
+
uvx obsidian-rag setup
|
|
48
|
+
|
|
49
|
+
# Add to Claude Code
|
|
50
|
+
claude mcp add obsidian-rag -- uvx obsidian-rag serve
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Alternative: Clone and install
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/ernestkoe/obsidian-rag.git
|
|
57
|
+
cd obsidian-rag
|
|
58
|
+
uv sync
|
|
59
|
+
|
|
60
|
+
uv run obsidian-rag setup
|
|
61
|
+
claude mcp add obsidian-rag -- uv run --directory /path/to/obsidian-rag obsidian-rag serve
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The setup wizard will:
|
|
65
|
+
1. Ask for your embedding provider (OpenAI or Ollama)
|
|
66
|
+
2. Configure your API key (for OpenAI)
|
|
67
|
+
3. Set your Obsidian vault path
|
|
68
|
+
4. Choose where to store the search index
|
|
69
|
+
5. Optionally run the initial indexing
|
|
70
|
+
|
|
71
|
+
### Manual Setup (alternative)
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Set your API key and index directly
|
|
75
|
+
export OPENAI_API_KEY=sk-...
|
|
76
|
+
uv run obsidian-rag index --vault /path/to/your/vault
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Using Ollama (local, offline)
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Install Ollama and pull the embedding model
|
|
83
|
+
ollama pull nomic-embed-text
|
|
84
|
+
|
|
85
|
+
# Run setup with Ollama, or index directly:
|
|
86
|
+
uv run obsidian-rag --provider ollama index --vault /path/to/your/vault
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## MCP Tools
|
|
90
|
+
|
|
91
|
+
Once connected, these tools are available to Claude:
|
|
92
|
+
|
|
93
|
+
| Tool | What it does |
|
|
94
|
+
|------|--------------|
|
|
95
|
+
| `search_notes` | Find notes matching a query |
|
|
96
|
+
| `get_similar` | Find notes similar to a given note |
|
|
97
|
+
| `get_note_context` | Get a note with related context |
|
|
98
|
+
| `get_stats` | Show index statistics |
|
|
99
|
+
| `reindex` | Update the index |
|
|
100
|
+
|
|
101
|
+
## Keeping the Index Fresh
|
|
102
|
+
|
|
103
|
+
### Option 1: Manual reindex
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
uv run obsidian-rag index
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Option 2: Watch for changes
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
uv run obsidian-rag watch
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Option 3: Auto-start on login (macOS)
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
uv run obsidian-rag install-service
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## CLI Reference
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
obsidian-rag setup # Interactive setup wizard
|
|
125
|
+
obsidian-rag serve # Start MCP server (for Claude Code)
|
|
126
|
+
obsidian-rag index [--clear] # Index vault (--clear to rebuild)
|
|
127
|
+
obsidian-rag search "query" # Search from command line
|
|
128
|
+
obsidian-rag watch # Watch for file changes
|
|
129
|
+
obsidian-rag stats # Show index stats
|
|
130
|
+
obsidian-rag install-service # Install macOS launchd service
|
|
131
|
+
obsidian-rag uninstall-service # Remove service
|
|
132
|
+
obsidian-rag service-status # Check service status
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Configuration
|
|
136
|
+
|
|
137
|
+
Set your vault path and provider via CLI options or environment variables:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# CLI options
|
|
141
|
+
uv run obsidian-rag --vault /path/to/vault index
|
|
142
|
+
uv run obsidian-rag --provider ollama index
|
|
143
|
+
|
|
144
|
+
# Environment variables
|
|
145
|
+
export OBSIDIAN_RAG_VAULT=/path/to/vault
|
|
146
|
+
export OBSIDIAN_RAG_PROVIDER=ollama # or "openai" (default)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
| Variable | Description |
|
|
150
|
+
|----------|-------------|
|
|
151
|
+
| `OPENAI_API_KEY` | OpenAI API key (required for default provider) |
|
|
152
|
+
| `OBSIDIAN_RAG_PROVIDER` | Embedding provider: `openai` (default) or `ollama` |
|
|
153
|
+
| `OBSIDIAN_RAG_VAULT` | Path to Obsidian vault |
|
|
154
|
+
| `OBSIDIAN_RAG_DATA` | Where to store the index (default: `./data`) |
|
|
155
|
+
| `OBSIDIAN_RAG_OLLAMA_URL` | Ollama API URL (default: `http://localhost:11434`) |
|
|
156
|
+
| `OBSIDIAN_RAG_MODEL` | Override embedding model |
|
|
157
|
+
|
|
158
|
+
## How it works
|
|
159
|
+
|
|
160
|
+
1. Parses your markdown files and splits them by headings
|
|
161
|
+
2. Generates embeddings using OpenAI API (or Ollama for local processing)
|
|
162
|
+
3. Stores vectors in ChromaDB (local, persistent)
|
|
163
|
+
4. MCP server provides semantic search to Claude
|
|
164
|
+
|
|
165
|
+
## Contributing
|
|
166
|
+
|
|
167
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup.
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
MIT
|