smoking-mirror 1.1.0 → 1.2.0

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.
Files changed (3) hide show
  1. package/README.md +344 -204
  2. package/dist/index.js +1180 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,42 +1,277 @@
1
1
  # smoking-mirror
2
2
 
3
- > Obsidian vault intelligence for Claude Code - graph queries, wikilink suggestions, and vault health
3
+ > Your vault's secrets stay yours. Claude sees only what it needs.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/smoking-mirror.svg)](https://www.npmjs.com/package/smoking-mirror)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
 
8
- ## What is smoking-mirror?
8
+ ---
9
+
10
+ ## The Problem with AI + Your Notes
11
+
12
+ ```
13
+ ┌─────────────────────────────────────────────────────────────────┐
14
+ │ THE OLD WAY │
15
+ │ │
16
+ │ "Claude, find notes about Project X" │
17
+ │ │
18
+ │ ┌──────────┐ ENTIRE VAULT ┌──────────┐ │
19
+ │ │ Claude │ ◄──────────────────── │ 1,500 │ │
20
+ │ │ Code │ (~50MB of text) │ Notes │ │
21
+ │ └──────────┘ └──────────┘ │
22
+ │ │
23
+ │ • Your private journals? Sent. │
24
+ │ • Financial notes? Sent. │
25
+ │ • That embarrassing poetry? Definitely sent. │
26
+ │ • Token bill? Astronomical. │
27
+ │ │
28
+ └─────────────────────────────────────────────────────────────────┘
29
+ ```
30
+
31
+ ```
32
+ ┌─────────────────────────────────────────────────────────────────┐
33
+ │ THE SMOKING-MIRROR WAY │
34
+ │ │
35
+ │ "Claude, find notes about Project X" │
36
+ │ │
37
+ │ ┌──────────┐ STRUCTURED QUERY ┌──────────┐ │
38
+ │ │ Claude │ ◄───────────────────► │ smoking │ │
39
+ │ │ Code │ { backlinks: [...], │ -mirror │ │
40
+ │ └──────────┘ tags: [...] } └────┬─────┘ │
41
+ │ │ │
42
+ │ ONLY searches │ │
43
+ │ the index! ▼ │
44
+ │ ┌──────────┐ │
45
+ │ │ 1,500 │ │
46
+ │ │ Notes │ │
47
+ │ └──────────┘ │
48
+ │ │
49
+ │ • Your secrets? Never leave your machine. │
50
+ │ • Claude sees? Filenames, links, tags. That's it. │
51
+ │ • Token usage? Minimal. Blazing fast. │
52
+ │ │
53
+ └─────────────────────────────────────────────────────────────────┘
54
+ ```
55
+
56
+ ---
57
+
58
+ ## What IS smoking-mirror?
59
+
60
+ "Smoking mirror" (tezcatl in Nahuatl) is the literal translation of **obsidian**. This MCP server acts as a reflective surface that reveals the *structure* of your vault—without exposing the *content*.
61
+
62
+ **47 tools** that answer questions like:
63
+ - "What links to this note?" → **Backlinks returned, content untouched**
64
+ - "Find orphan notes" → **Paths only, privacy intact**
65
+ - "Search by #tag or frontmatter" → **Metadata queries, not content dumps**
66
+
67
+ ---
68
+
69
+ ## Privacy Architecture
70
+
71
+ ```
72
+ YOUR MACHINE │ CLOUD
73
+ ────────────────────────────────────── │ ────────────────
74
+
75
+ ┌─────────────────┐ │
76
+ │ Obsidian │ │
77
+ │ Vault │ │
78
+ │ ┌───────────┐ │ │
79
+ │ │ 📓 Notes │ │ NEVER LEAVES │
80
+ │ │ 📊 Data │ │ ───────────► │ ❌ Blocked
81
+ │ │ 📝 Journal│ │ │
82
+ │ └───────────┘ │ │
83
+ └────────┬────────┘ │
84
+ │ │
85
+ │ Parse locally │
86
+ ▼ │
87
+ ┌─────────────────┐ │
88
+ │ smoking-mirror │ │
89
+ │ ┌───────────┐ │ │
90
+ │ │ Index │ │ │
91
+ │ │ • links │ │ │
92
+ │ │ • tags │ │ │
93
+ │ │ • paths │ │ │
94
+ │ └───────────┘ │ │
95
+ └────────┬────────┘ │
96
+ │ │
97
+ │ Structured responses only │
98
+ ▼ │
99
+ ┌─────────────────┐ API calls ┌─────────────────┐
100
+ │ Claude Code │ ───────────────► │ Claude AI │
101
+ │ │ (metadata only) │ │
102
+ │ "Find hubs" │ ◄─────────────── │ (processes │
103
+ │ │ { paths, counts }│ structure) │
104
+ └─────────────────┘ └─────────────────┘
105
+ ```
106
+
107
+ **What Claude receives:**
108
+ - File paths and names
109
+ - Link relationships (A → B)
110
+ - Tag lists
111
+ - Frontmatter keys/values
112
+ - Word counts, modification dates
113
+
114
+ **What Claude NEVER receives:**
115
+ - Your actual note content (unless you explicitly Read it)
116
+ - Personal journals
117
+ - Private thoughts
118
+ - Sensitive data
119
+
120
+ ---
121
+
122
+ ## Speed Demon
123
+
124
+ Forget waiting for full-vault searches. smoking-mirror pre-indexes everything.
125
+
126
+ ```
127
+ ┌────────────────────────────────────────────────────────────────┐
128
+ │ PERFORMANCE BENCHMARKS │
129
+ ├────────────────┬───────────────┬───────────────┬───────────────┤
130
+ │ Vault Size │ Index Build │ Query Time │ Memory │
131
+ ├────────────────┼───────────────┼───────────────┼───────────────┤
132
+ │ 100 notes │ <200ms │ <10ms │ ~20MB │
133
+ │ 500 notes │ <500ms │ <10ms │ ~30MB │
134
+ │ 1,500 notes │ <2s │ <10ms │ ~50MB │
135
+ │ 5,000 notes │ <5s │ <10ms │ ~100MB │
136
+ └────────────────┴───────────────┴───────────────┴───────────────┘
137
+
138
+
139
+ Queries are INSTANT because
140
+ they hit an in-memory index,
141
+ not your filesystem.
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Token Economy
147
+
148
+ Every character Claude reads costs you tokens. Here's the math:
149
+
150
+ ```
151
+ ┌─────────────────────────────────────────────────────────────────┐
152
+ │ TOKEN COMPARISON │
153
+ │ │
154
+ │ Traditional approach: "Read all notes with #project tag" │
155
+ │ ───────────────────────────────────────────────────────── │
156
+ │ 📄 50 notes × ~2,000 tokens each = 100,000 tokens │
157
+ │ 💰 Cost: ~$0.30 per query (Claude pricing) │
158
+ │ │
159
+ │ smoking-mirror: search_notes({ has_tag: "project" }) │
160
+ │ ───────────────────────────────────────────────────────── │
161
+ │ 📊 Returns: paths, titles, metadata │
162
+ │ 🎯 ~500 tokens total │
163
+ │ 💰 Cost: ~$0.0015 per query │
164
+ │ │
165
+ │ ═══════════════════════════════════════════════════════════ │
166
+ │ SAVINGS: 200x fewer tokens per query │
167
+ │ ═══════════════════════════════════════════════════════════ │
168
+ │ │
169
+ └─────────────────────────────────────────────────────────────────┘
170
+ ```
171
+
172
+ Then Claude can surgically `Read` only the 2-3 notes it actually needs.
173
+
174
+ ---
175
+
176
+ ## 47 Tools at Your Service
9
177
 
10
- "Smoking mirror" (tezcatl in Nahuatl) is the literal translation of "obsidian". This MCP server acts as a reflective surface that reveals the hidden structure of your Obsidian vault to Claude Code.
178
+ ### Graph Intelligence
179
+ | Tool | What it does |
180
+ |------|--------------|
181
+ | `get_backlinks` | Who's linking to this note? |
182
+ | `get_forward_links` | What does this note link to? |
183
+ | `find_orphan_notes` | Notes nobody loves (no incoming links) |
184
+ | `find_hub_notes` | Your vault's superstars (highly connected) |
185
+
186
+ ### Wikilink Services
187
+ | Tool | What it does |
188
+ |------|--------------|
189
+ | `suggest_wikilinks` | "You mentioned 'John'—want to link to [[John Smith]]?" |
190
+ | `validate_links` | Find broken links before they embarrass you |
191
+ | `find_broken_links` | [[Dead Note]] → nowhere |
192
+ | `get_unlinked_mentions` | "John" mentioned 47 times, linked 3 times |
11
193
 
12
- **First-to-market** features:
13
- - **Graph Intelligence** - Backlinks, forward links, orphan detection, hub analysis
14
- - **Wikilink Services** - Auto-suggest entities, validate links
15
- - **Vault Health** - Broken link detection, comprehensive statistics
16
- - **Frontmatter Queries** - Search notes by metadata, tags, folders
194
+ ### Vault Health
195
+ | Tool | What it does |
196
+ |------|--------------|
197
+ | `get_vault_stats` | The big picture: notes, links, tags, orphans |
198
+ | `get_folder_structure` | Your vault's anatomy |
199
+ | `get_activity_summary` | What's been happening lately? |
200
+
201
+ ### Smart Search
202
+ | Tool | What it does |
203
+ |------|--------------|
204
+ | `search_notes` | Query by frontmatter, tags, folders—Dataview vibes |
205
+ | `get_recent_notes` | Modified in the last N days |
206
+ | `get_stale_notes` | Important notes gathering dust |
207
+ | `get_notes_modified_on` | What happened on 2024-01-15? |
208
+ | `get_notes_in_range` | Activity between two dates |
209
+
210
+ ### Deep Graph Analysis
211
+ | Tool | What it does |
212
+ |------|--------------|
213
+ | `get_link_path` | How do these two notes connect? (A → B → C → D) |
214
+ | `get_common_neighbors` | What do these notes have in common? |
215
+ | `find_bidirectional_links` | Mutual admirers (A ↔ B) |
216
+ | `find_dead_ends` | Popular notes that link nowhere |
217
+ | `find_sources` | Link-givers, not link-receivers |
218
+ | `get_connection_strength` | How related are these notes, really? |
219
+
220
+ ### Structure Analysis
221
+ | Tool | What it does |
222
+ |------|--------------|
223
+ | `get_note_structure` | Full heading tree and sections |
224
+ | `get_headings` | Just the headings, quick |
225
+ | `get_section_content` | Extract a specific section |
226
+ | `find_sections` | Find all "## References" across the vault |
227
+
228
+ ### Task Management
229
+ | Tool | What it does |
230
+ |------|--------------|
231
+ | `get_all_tasks` | Every `- [ ]` in your vault |
232
+ | `get_tasks_from_note` | Tasks in a specific note |
233
+ | `get_tasks_with_due_dates` | What's due? |
234
+
235
+ ### Frontmatter Intelligence
236
+ | Tool | What it does |
237
+ |------|--------------|
238
+ | `get_frontmatter_schema` | What fields exist across your vault? |
239
+ | `get_field_values` | All unique values for `status` field |
240
+ | `find_frontmatter_inconsistencies` | `status: "done"` vs `status: true` chaos |
241
+
242
+ ### Temporal Analysis
243
+ | Tool | What it does |
244
+ |------|--------------|
245
+ | `get_contemporaneous_notes` | Edited around the same time |
246
+ | `get_note_metadata` | Quick stats without reading content |
247
+
248
+ ### System
249
+ | Tool | What it does |
250
+ |------|--------------|
251
+ | `refresh_index` | Rebuilt after Obsidian changes |
252
+ | `get_all_entities` | Every linkable thing (titles + aliases) |
253
+
254
+ ---
17
255
 
18
256
  ## Installation
19
257
 
20
258
  ### Quick Install (Claude Code CLI)
21
259
 
22
260
  **macOS / Linux:**
23
-
24
261
  ```bash
25
262
  claude mcp add smoking-mirror -e OBSIDIAN_VAULT_PATH=/path/to/your/vault -- npx -y smoking-mirror
26
263
  ```
27
264
 
28
265
  **Windows:**
29
-
30
266
  ```bash
31
267
  claude mcp add smoking-mirror -e OBSIDIAN_VAULT_PATH=C:\path\to\your\vault -- cmd /c npx -y smoking-mirror
32
268
  ```
33
269
 
34
270
  ### Manual Configuration
35
271
 
36
- Alternatively, add to your `.mcp.json` file:
272
+ Add to your `.mcp.json`:
37
273
 
38
274
  **Windows:**
39
-
40
275
  ```json
41
276
  {
42
277
  "mcpServers": {
@@ -52,7 +287,6 @@ Alternatively, add to your `.mcp.json` file:
52
287
  ```
53
288
 
54
289
  **macOS / Linux:**
55
-
56
290
  ```json
57
291
  {
58
292
  "mcpServers": {
@@ -67,241 +301,147 @@ Alternatively, add to your `.mcp.json` file:
67
301
  }
68
302
  ```
69
303
 
70
- ### Verify Installation
71
-
72
- After adding, verify with:
304
+ ### Verify
73
305
 
74
306
  ```bash
75
307
  claude mcp list
308
+ # Should show: smoking-mirror ✓
76
309
  ```
77
310
 
78
- You should see `smoking-mirror` in the list of configured servers.
79
-
80
- ## Tools
311
+ ---
81
312
 
82
- ### Graph Intelligence
83
-
84
- #### `get_backlinks`
85
- Find all notes that link TO a specific note.
313
+ ## Real-World Example
86
314
 
87
315
  ```
88
- Input: { path: "projects/My Project.md" }
89
- Output: [{ source: "daily/2024-01-15.md", line: 42, context: "Working on [[My Project]] today" }]
90
- ```
316
+ You: "What are my most connected project notes?"
91
317
 
92
- #### `get_forward_links`
93
- Find all notes that a specific note links TO.
318
+ Claude uses: find_hub_notes({ min_links: 10 })
94
319
 
95
- ```
96
- Input: { path: "projects/My Project.md" }
97
- Output: [{ target: "Team Members", exists: true, resolved_path: "people/Team Members.md" }]
98
- ```
99
-
100
- #### `find_orphan_notes`
101
- Find notes with no incoming links (potential cleanup candidates).
102
-
103
- ```
104
- Input: { folder: "archive" } // optional folder filter
105
- Output: [{ path: "archive/old-idea.md", title: "old-idea", modified: "2024-01-01" }]
106
- ```
107
-
108
- #### `find_hub_notes`
109
- Find highly connected notes (potential MOCs or index notes).
110
-
111
- ```
112
- Input: { min_links: 10 } // minimum total connections
113
- Output: [{ path: "MOC.md", backlink_count: 45, forward_link_count: 23, total_connections: 68 }]
114
- ```
115
-
116
- ### Wikilink Services
117
-
118
- #### `suggest_wikilinks`
119
- Analyze text and suggest where wikilinks could be added based on existing notes.
120
-
121
- ```
122
- Input: { text: "Meeting with John about the API project" }
123
- Output: [
124
- { entity: "John", start: 13, end: 17, target: "people/John Smith.md" },
125
- { entity: "API project", start: 28, end: 39, target: "projects/API Project.md" }
126
- ]
127
- ```
128
-
129
- #### `validate_links`
130
- Check wikilinks in a note (or all notes) and report broken links.
131
-
132
- ```
133
- Input: { path: "projects/My Project.md" } // optional, validates all if omitted
134
- Output: [{ source: "projects/My Project.md", target: "Missing Note", line: 15, exists: false }]
135
- ```
136
-
137
- ### Vault Health
138
-
139
- #### `get_vault_stats`
140
- Get comprehensive statistics about your vault.
141
-
142
- ```
143
- Output: {
144
- total_notes: 1444,
145
- total_links: 20373,
146
- total_tags: 431,
147
- orphan_notes: 971,
148
- broken_links: 8565,
149
- average_links_per_note: 14.11,
150
- most_linked_notes: [...],
151
- top_tags: [...],
152
- folders: [...]
320
+ Response (what Claude actually sees):
321
+ {
322
+ "hubs": [
323
+ { "path": "projects/Main Project.md", "connections": 47 },
324
+ { "path": "areas/Work.md", "connections": 34 },
325
+ { "path": "resources/API Docs.md", "connections": 28 }
326
+ ]
153
327
  }
154
- ```
155
-
156
- #### `find_broken_links`
157
- Find all wikilinks that point to non-existent notes.
158
-
159
- ```
160
- Input: { folder: "projects" } // optional folder filter
161
- Output: [{ source: "projects/Old.md", target: "Deleted Note", line: 5 }]
162
- ```
163
-
164
- ### Query
165
-
166
- #### `search_notes`
167
- Search notes by frontmatter fields, tags, folders, or title. Covers ~80% of Dataview use cases.
168
328
 
329
+ Your actual note content? Still safely on your disk.
330
+ Claude knows the STRUCTURE, not the SECRETS.
169
331
  ```
170
- Input: {
171
- has_tag: "project",
172
- where: { status: "active" },
173
- folder: "work",
174
- sort_by: "modified",
175
- limit: 10
176
- }
177
- Output: [{ path: "work/Current.md", title: "Current", frontmatter: {...}, tags: [...] }]
178
- ```
179
-
180
- **Parameters:**
181
- - `where` - Frontmatter key-value filters (e.g., `{ type: "book", rating: 5 }`)
182
- - `has_tag` - Filter by single tag
183
- - `has_any_tag` - Filter by any of these tags
184
- - `has_all_tags` - Filter by all of these tags
185
- - `folder` - Limit to notes in this folder
186
- - `title_contains` - Filter by title substring
187
- - `sort_by` - Sort by "modified", "created", or "title"
188
- - `order` - "asc" or "desc"
189
- - `limit` - Maximum results to return
190
332
 
191
- ### System (v1.1)
192
-
193
- #### `refresh_index`
194
- Rebuild the vault index without restarting the server.
195
-
196
- ```
197
- Output: { success: true, notes_count: 1444, entities_count: 3421, duration_ms: 1823 }
198
- ```
199
-
200
- #### `get_all_entities`
201
- Get all linkable entities (note titles and aliases).
202
-
203
- ```
204
- Input: { include_aliases: true, limit: 100 }
205
- Output: { entity_count: 100, entities: [{ name: "John Smith", path: "people/John Smith.md", is_alias: false }] }
206
- ```
207
-
208
- #### `get_recent_notes`
209
- Get notes modified within the last N days.
210
-
211
- ```
212
- Input: { days: 7, limit: 50 }
213
- Output: { count: 23, days: 7, notes: [{ path: "daily/2024-01-15.md", title: "2024-01-15", modified: "...", tags: [...] }] }
214
- ```
215
-
216
- #### `get_unlinked_mentions`
217
- Find mentions of an entity that aren't linked (linking opportunities).
218
-
219
- ```
220
- Input: { entity: "John Smith", limit: 50 }
221
- Output: { entity: "John Smith", mention_count: 12, mentions: [{ path: "meetings/standup.md", line: 5, context: "Talked to John Smith about..." }] }
222
- ```
223
-
224
- #### `get_note_metadata`
225
- Get metadata about a note without reading full content.
226
-
227
- ```
228
- Input: { path: "projects/API.md", include_word_count: true }
229
- Output: { path: "...", title: "API", frontmatter: {...}, tags: [...], outlink_count: 15, backlink_count: 8, word_count: 2340 }
230
- ```
231
-
232
- #### `get_folder_structure`
233
- Get the folder structure of the vault with note counts.
234
-
235
- ```
236
- Output: { folder_count: 12, folders: [{ path: "daily", note_count: 365, subfolder_count: 0 }] }
237
- ```
333
+ ---
238
334
 
239
335
  ## Architecture
240
336
 
241
- - **File-first**: Parses markdown directly, no database required
242
- - **Works offline**: No connection to Obsidian needed
243
- - **Fast startup**: <2s for 1500+ notes
244
- - **Memory efficient**: ~50MB for large vaults
245
- - **Parallel parsing**: Processes files in batches for speed
337
+ ```
338
+ ┌────────────────────────────────┐
339
+ │ smoking-mirror │
340
+ │ │
341
+ ┌──────────┐ │ ┌──────────────────────────┐ │
342
+ │ │ │ │ VaultIndex │ │
343
+ │ Obsidian │ scan │ │ │ │
344
+ │ Vault │───────►│ │ notes: Map<path, Note> │ │
345
+ │ │ │ │ backlinks: Map<→Set> │ │
346
+ │ 📁 .md │ │ │ entities: Map<name→path>│ │
347
+ │ files │ │ │ tags: Map<tag→Set> │ │
348
+ │ │ │ │ │ │
349
+ └──────────┘ │ └──────────────────────────┘ │
350
+ │ │ │
351
+ │ ▼ │
352
+ │ ┌──────────────────────────┐ │
353
+ │ │ 47 MCP Tools │ │
354
+ │ │ │ │
355
+ │ │ Queries return │ │
356
+ │ │ STRUCTURE not CONTENT │ │
357
+ │ │ │ │
358
+ │ └──────────────────────────┘ │
359
+ │ │
360
+ └────────────────────────────────┘
361
+
362
+ │ MCP Protocol
363
+
364
+ ┌──────────────┐
365
+ │ Claude Code │
366
+ └──────────────┘
367
+ ```
368
+
369
+ **Key Design Decisions:**
370
+ - **File-first**: Parses markdown directly, no database
371
+ - **Works offline**: No connection to Obsidian app needed
372
+ - **Eager loading**: Full index on startup (fine for <5000 notes)
373
+ - **In-memory graph**: Lightning-fast queries
374
+ - **Privacy by design**: Content stays local
375
+
376
+ ---
377
+
378
+ ## Error Handling
379
+
380
+ | Situation | Behavior |
381
+ |-----------|----------|
382
+ | Malformed YAML | Gracefully skipped, file treated as content |
383
+ | Binary files | Detected and skipped |
384
+ | Empty files | Indexed with no links/tags |
385
+ | Large files (>10MB) | Skipped with warning |
386
+ | Missing files | Graceful degradation |
387
+
388
+ ---
246
389
 
247
- ### Performance
390
+ ## Why not Dataview?
248
391
 
249
- | Vault Size | Startup Time | Memory |
250
- |------------|--------------|--------|
251
- | 100 notes | <200ms | ~20MB |
252
- | 500 notes | <500ms | ~30MB |
253
- | 1500 notes | <2s | ~50MB |
254
- | 5000 notes | <5s | ~100MB |
392
+ We wanted to use `obsidian-dataview` as a library, but it requires Obsidian's internal `CachedMetadata` API and cannot run standalone. See [this discussion](https://github.com/blacksmithgu/obsidian-dataview/discussions/1811).
255
393
 
256
- ### Error Handling
394
+ Instead, smoking-mirror:
395
+ - Parses markdown directly using `gray-matter`
396
+ - Builds its own in-memory graph index
397
+ - Provides ~80% of Dataview functionality with simpler syntax
398
+ - And does it all **without exposing your content to AI**
257
399
 
258
- - Malformed YAML frontmatter: Gracefully skipped, file treated as content
259
- - Binary files: Detected and skipped
260
- - Empty files: Indexed with no links/tags
261
- - Large files (>10MB): Skipped with warning
262
- - Timeout protection: 5-minute default for vault indexing
400
+ ---
263
401
 
264
402
  ## Development
265
403
 
266
404
  ```bash
267
- # Install dependencies
268
405
  bun install
269
-
270
- # Run in development mode
271
406
  OBSIDIAN_VAULT_PATH=/path/to/vault bun run dev
272
-
273
- # Build for distribution
274
407
  bun run build
275
-
276
- # Test with MCP inspector
277
408
  bun run inspect
278
-
279
- # Run tests
280
409
  bun test
281
410
  ```
282
411
 
283
- ## Why not Dataview?
284
-
285
- We initially planned to use `obsidian-dataview` as a library, but discovered it requires Obsidian's internal `CachedMetadata` API and cannot run standalone. See [this discussion](https://github.com/blacksmithgu/obsidian-dataview/discussions/1811).
286
-
287
- Instead, smoking-mirror:
288
- - Parses markdown files directly using `gray-matter`
289
- - Builds its own in-memory graph index
290
- - Provides ~80% of Dataview functionality with simpler syntax
412
+ ---
291
413
 
292
414
  ## Roadmap
293
415
 
294
- - [ ] MarkdownDB integration for SQL-like queries
295
416
  - [ ] Watch mode for incremental updates
296
417
  - [ ] `rename_with_links` - Safe note renaming with reference updates
297
- - [ ] Obsidian REST API integration for live Dataview queries
418
+ - [ ] MarkdownDB integration for SQL-like queries
419
+ - [ ] Semantic search via local embeddings
420
+
421
+ ---
298
422
 
299
423
  ## License
300
424
 
301
425
  MIT - Ben Cassie
302
426
 
427
+ ---
428
+
429
+ ## The Philosophy
430
+
431
+ > Your notes are yours. Your thoughts are private. Your vault is sacred.
432
+ >
433
+ > AI should help you navigate your knowledge—not consume it.
434
+ >
435
+ > smoking-mirror gives Claude the **map**, not the **territory**.
436
+
437
+ ---
438
+
303
439
  ## Related
304
440
 
305
441
  - [Model Context Protocol](https://modelcontextprotocol.io/)
306
442
  - [Claude Code](https://claude.ai/code)
307
443
  - [Obsidian](https://obsidian.md/)
444
+
445
+ ---
446
+
447
+ *"tezcatl" — the obsidian mirror that reveals truth without taking it*