@djolex999/vir-cli 0.4.0 → 0.5.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.
package/README.md CHANGED
@@ -5,67 +5,95 @@
5
5
  <h1 align="center">vir</h1>
6
6
 
7
7
  <p align="center">
8
- Distills Claude Code sessions into a compounding knowledge vault.
8
+ An LLM Wiki for Claude Code, in your Obsidian vault.
9
9
  </p>
10
10
 
11
11
  <!--
12
12
  GitHub topics (add manually: repo → About → ⚙ → Topics):
13
13
  claude, claude-code, ai-memory, obsidian, knowledge-base, llm,
14
- developer-tools, mcp, local-first, cross-platform
14
+ developer-tools, mcp, local-first, cross-platform, llm-wiki
15
15
  -->
16
16
 
17
17
  <p align="center">
18
18
  <a href="https://www.npmjs.com/package/@djolex999/vir-cli"><img src="https://img.shields.io/npm/v/@djolex999/vir-cli?color=7c6af7&label=npm" alt="npm version"></a>
19
19
  <a href="https://www.npmjs.com/package/@djolex999/vir-cli"><img src="https://img.shields.io/npm/dw/@djolex999/vir-cli?color=4fd1a0" alt="npm downloads"></a>
20
20
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-22d3ee" alt="license"></a>
21
- <a href="#quality"><img src="https://img.shields.io/badge/tests-25%20passing-22c55e" alt="tests"></a>
22
- <a href="#quality"><img src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-lightgrey" alt="platforms"></a>
21
+ <a href="#project-status"><img src="https://img.shields.io/badge/tests-59%20passing-22c55e" alt="tests"></a>
22
+ <a href="#project-status"><img src="https://img.shields.io/badge/platforms-macOS%20%7C%20Linux-lightgrey" alt="platforms"></a>
23
23
  <a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/MCP-server-c084fc" alt="mcp"></a>
24
24
  <a href="#"><img src="https://img.shields.io/badge/local--first-yes-f59e0b" alt="local-first"></a>
25
25
  <a href="https://github.com/djolex999/vir"><img src="https://img.shields.io/github/stars/djolex999/vir?style=social" alt="stars"></a>
26
26
  </p>
27
27
 
28
- <p align="center">
29
- <img src="assets/demo.gif" width="800" alt="vir demo">
30
- </p>
28
+ ## The pattern
29
+
30
+ Recently, Andrej Karpathy described a pattern he calls the **LLM Wiki** — AI work
31
+ that feeds back into itself through a persistent, curated, structured artifact,
32
+ instead of resetting at the end of every session. He ended his post with: _"I
33
+ think there is room here for an incredible new product instead of a hacky
34
+ collection of scripts."_
35
+
36
+ Vir is one implementation of that pattern, focused on Claude Code sessions with
37
+ Obsidian as the frontend.
31
38
 
32
- ## What it does
39
+ [Karpathy's post →](https://x.com/karpathy/status/2039805659525644595)
33
40
 
34
- Every Claude Code session produces patterns, gotchas, and architecture
35
- decisions — and 95% of it sits in JSONL transcripts you never open again.
41
+ ## Why this exists
36
42
 
37
- Vir runs on a schedule, distills your sessions into structured markdown in your
38
- Obsidian vault, and feeds that knowledge back into your `CLAUDE.md` files. Every
39
- future session starts sharper than the last.
43
+ Every Claude Code session produces patterns, gotchas, and architecture decisions.
44
+ Almost all of it ends up in `~/.claude/projects/**/*.jsonl` transcripts you
45
+ open once and never again. The knowledge is real; the storage is a graveyard.
46
+
47
+ Vir reads those transcripts, distills the durable knowledge into typed markdown
48
+ notes in your Obsidian vault, and feeds the best of it back into your `CLAUDE.md`
49
+ files — so every future session starts sharper than the last. It's a concrete
50
+ implementation of [the pattern above](#the-pattern).
51
+
52
+ <p align="center">
53
+ <img src="assets/demo.gif" width="800" alt="vir distilling Claude Code sessions into notes in an Obsidian vault">
54
+ </p>
55
+
56
+ ## Quality controls
57
+
58
+ Auto-distilled notes can be wrong. The most common concern from early users:
59
+ _"if your distillations are wrong, Claude treats them as truth and you get worse
60
+ results, not better."_ Fair. Vir addresses it in layers:
61
+
62
+ - **Confidence scores on every note**, written into the frontmatter
63
+ (`confidence: 0.xx`). A cheap heuristic pre-filter drops low-signal sessions
64
+ before any LLM call; classification then scores what survives, and anything at
65
+ or below `0.6` is dropped _before_ the more expensive distill step. Only
66
+ high-confidence notes reach the vault.
67
+ - **Opt-in `CLAUDE.md` sync.** Nothing vir generates touches your prompt context
68
+ automatically. `vir sync-claude` shows a diff and waits for your confirmation —
69
+ you decide what reaches Claude.
70
+ - **Plain markdown output.** Every note is a file in your Obsidian vault. Read
71
+ it, edit it, delete it. Nothing is hidden in a compressed database you can't
72
+ inspect.
73
+ - **Lint and dedupe.** `vir lint` flags contradictions and stale notes;
74
+ `vir dedupe` merges similar notes that have drifted apart.
75
+ - **Active learning** via `vir review`. Walk through new distillations and
76
+ approve, edit, or reject each one. Verified notes get retrieval priority over
77
+ unverified ones (in `vir query` and the MCP server). Rejected notes are moved
78
+ to `.rejected/` — recoverable, not deleted.
79
+
80
+ The bet: with these controls, signal-to-noise stays high enough that the vault
81
+ is a net positive. If your discipline is strong enough to maintain `CLAUDE.md`
82
+ and `lessons.md` by hand, you may not need this. If — like most of us — you let
83
+ those files drift after the first week, Vir catches what slips through.
40
84
 
41
85
  ## How it works
42
86
 
43
- Vir reads your Claude Code transcripts from `~/.claude/projects/**/*.jsonl`,
44
- runs each session through a cheap heuristic filter, then classifies the
45
- survivors with Haiku and distills durable knowledge with Sonnet. Before
46
- distillation, **tool calls are filtered**: it preserves tool *intent* (file
47
- paths, commands, search patterns, errors, and short results) for better notes,
48
- while truncating large embedded content (file writes, edit strings, long bash
49
- logs, big grep dumps) to keep token cost bounded tunable via `filterToolCalls`.
50
- The results are
51
- written as typed notes (patterns, gotchas, decisions, tools) into your Obsidian
52
- vault, cross-linked with wikilinks and indexed. State lives in a local SQLite
53
- database — content hashes make reruns idempotent, and embeddings (optional, via
54
- Ollama) power semantic search. An MCP server exposes the whole vault to Claude
55
- Code as queryable tools, so future sessions can consult what past sessions
56
- learned.
57
-
58
- ## Why Vir?
59
-
60
- Vir (вир) is the Serbian word for whirlpool — the place where a river pulls
61
- everything in and concentrates it. That is exactly what this tool does.
62
- Sessions flow in, Vir pulls out what matters, and deposits it somewhere
63
- permanent.
64
-
65
- The name felt right for a tool whose job is to take the chaos of a Claude Code
66
- session and find the still point at the center.
67
-
68
- ## The loop
87
+ Vir reads your transcripts from `~/.claude/projects/**/*.jsonl`, runs each
88
+ session through a cheap heuristic filter, classifies the survivors with Haiku,
89
+ and distills durable knowledge with Sonnet. Before distillation it **filters tool
90
+ calls** preserving intent (file paths, commands, search patterns, errors, short
91
+ results) while truncating large embedded content (file writes, long bash logs,
92
+ big grep dumps) to keep token cost bounded (tunable via `filterToolCalls`).
93
+ Results are written as typed notes patterns, gotchas, decisions, tools
94
+ cross-linked with wikilinks and indexed. State lives in local SQLite; content
95
+ hashes make reruns idempotent. Optional Ollama embeddings power semantic search,
96
+ and an MCP server exposes the whole vault to Claude Code mid-session.
69
97
 
70
98
  ```
71
99
  Claude Code sessions
@@ -81,17 +109,46 @@ better sessions
81
109
  ...
82
110
  ```
83
111
 
84
- ## After one night
112
+ ## How Vir compares
113
+
114
+ The AI memory space has grown fast. An honest comparison to the options worth
115
+ knowing about:
116
+
117
+ | | Vir | claude-mem | claude-memory | mem0 |
118
+ | ----------------------------------- | ------------------------------- | ----------------------- | -------------------------- | ----------------- |
119
+ | Reads existing Claude Code sessions | ✓ | from install forward | from install forward | n/a |
120
+ | Markdown output (Obsidian-native) | ✓ | ChromaDB | LanceDB | various backends |
121
+ | MCP server | ✓ | ✓ | ✓ | n/a |
122
+ | Setup complexity | `npm install -g` | Bun + Python + ChromaDB | pnpm + LM Studio + LanceDB | API/cloud setup |
123
+ | Cross-platform daemon | mac launchd, linux systemd/cron | mac, linux | mac, linux | n/a |
124
+ | Open source license | MIT | Apache 2.0 | MIT | open core + cloud |
125
+
126
+ **Different tools for different needs:**
127
+
128
+ - Want a heavyweight memory plugin with real-time capture and vector storage?
129
+ Use **claude-mem**.
130
+ - Want sophisticated retrieval (MMR diversity, web dashboard, multi-phase
131
+ maintenance)? Use **claude-memory**.
132
+ - Building AI applications that need to remember users long-term? Use **mem0** —
133
+ it's infrastructure for apps.
134
+ - Want your Claude Code sessions distilled into markdown notes you can browse,
135
+ edit, and own in Obsidian? Use **Vir**.
136
+
137
+ These aren't all competitors. mem0 is a different layer of the stack entirely.
138
+ claude-mem and claude-memory share the same input data as Vir but take different
139
+ opinions on storage and integration.
140
+
141
+ ## Real-world results
85
142
 
86
143
  Real output from the author's first run across 226 Claude Code sessions.
87
144
 
88
- | Metric | Value |
89
- |---|---|
90
- | Sessions scanned | 226 |
91
- | Notes distilled | 126 |
92
- | Avg confidence | 0.91 |
93
- | High signal (≥0.8) | 121 of 126 |
94
- | Projects covered | 8 projects |
145
+ | Metric | Value |
146
+ | ------------------- | ------------------------------------------------- |
147
+ | Sessions scanned | 226 |
148
+ | Notes distilled | 126 |
149
+ | Avg confidence | 0.91 |
150
+ | High signal (≥0.8) | 121 of 126 |
151
+ | Projects covered | 8 projects |
95
152
  | Knowledge breakdown | 54 patterns · 47 decisions · 23 gotchas · 2 tools |
96
153
 
97
154
  Example query against the distilled vault:
@@ -99,6 +156,7 @@ Example query against the distilled vault:
99
156
  ```bash
100
157
  $ vir query "what gotchas should I know about my auth implementation"
101
158
  ```
159
+
102
160
  Based on the notes, here are the key auth gotchas:
103
161
 
104
162
  JWT dual-token setup needs silent refresh on mount — access tokens
@@ -117,7 +175,7 @@ Logout must clear both the access token cookie and the refresh
117
175
  token — clearing only one leaves the session partially alive and
118
176
  causes confusing re-auth loops.
119
177
 
120
- sources 4 · via embedding · searched 126
178
+ sources 4 · via embedding · searched 126
121
179
 
122
180
  ## Prerequisites
123
181
 
@@ -163,12 +221,12 @@ Pass `--yes` to skip the cost confirmation prompt.
163
221
 
164
222
  ## Platform support
165
223
 
166
- | Platform | Daemon | Notifications | Status |
167
- |---|---|---|---|
168
- | macOS | launchd | osascript | Stable |
169
- | Linux (systemd) | systemd user timer | notify-send | Experimental |
170
- | Linux (cron) | crontab | notify-send | Experimental |
171
- | Windows | Not supported | — | Planned |
224
+ | Platform | Daemon | Notifications | Status |
225
+ | --------------- | ------------------ | ------------- | ------------ |
226
+ | macOS | launchd | osascript | Stable |
227
+ | Linux (systemd) | systemd user timer | notify-send | Experimental |
228
+ | Linux (cron) | crontab | notify-send | Experimental |
229
+ | Windows | Not supported | — | Planned |
172
230
 
173
231
  Linux support is **experimental and untested** — `vir schedule install` prefers
174
232
  a systemd user timer and falls back to a crontab entry when systemd is absent.
@@ -178,59 +236,33 @@ with your distro, init system, and Node version.
178
236
 
179
237
  ## Commands
180
238
 
181
- | Command | Cost | Description |
182
- |---|---|---|
183
- | `vir init` | free | Interactive setup |
184
- | `vir run` | cheap | Process new sessions |
185
- | `vir run --full` | $$ | Reprocess all sessions |
186
- | `vir run --rewrite-only` | free | Reformat notes, no API calls |
187
- | `vir run --yes` | cheap | Skip cost confirmation |
188
- | `vir query "<question>"` | cheap | Semantic search your vault |
189
- | `vir summarize <project>` | cheap | Cross-session project synthesis |
190
- | `vir summarize --all` | $$ | Summarize all projects |
191
- | `vir lint` | cheap | Find orphans, stale notes, contradictions |
192
- | `vir lint --orphans` | free | Orphan check only |
193
- | `vir lint --stale` | free | Staleness check only |
194
- | `vir lint --contradictions` | cheap | Contradiction check (Haiku) |
195
- | `vir dedupe` | cheap | Interactive duplicate detection |
196
- | `vir sync-claude` | free | Inject top knowledge into CLAUDE.md |
197
- | `vir sync-claude --dry-run` | free | Preview changes, no writes |
198
- | `vir sync-claude --force` | free | Apply without confirmation |
199
- | `vir embed` | free | Generate embeddings for semantic search |
200
- | `vir embed --force` | free | Regenerate all embeddings |
201
- | `vir schedule install` | free | Register the background daemon |
202
- | `vir schedule uninstall` | free | Remove the background daemon |
203
- | `vir status` | free | Knowledge heatmap + daemon status |
204
- | `vir doctor` | cheap | Diagnose installation issues |
205
-
206
- ## Quality
207
-
208
- | | |
209
- |---|---|
210
- | Tests | 30 passing |
211
- | Platforms | macOS (launchd), Linux (systemd/cron) |
212
- | Node | 20+ |
213
- | First-run cost | $1–5 (Kie.ai recommended for 72% savings) |
214
- | Ongoing cost | ~$0.05 per run |
215
-
216
- ## Semantic search (optional)
217
-
218
- Vir uses TF-IDF by default. For semantic search via embeddings:
219
-
220
- ```bash
221
- brew install ollama
222
- ollama pull nomic-embed-text
223
- ollama serve
224
- ```
225
-
226
- Then in a new terminal:
227
-
228
- ```bash
229
- vir embed
230
- vir query "how do I handle rate limiting in Next.js"
231
- ```
232
-
233
- Falls back to TF-IDF automatically if Ollama is not running.
239
+ | Command | Cost | Description |
240
+ | --------------------------- | ----- | ----------------------------------------- |
241
+ | `vir init` | free | Interactive setup |
242
+ | `vir run` | cheap | Process new sessions |
243
+ | `vir run --full` | $$ | Reprocess all sessions |
244
+ | `vir run --rewrite-only` | free | Reformat notes, no API calls |
245
+ | `vir run --yes` | cheap | Skip cost confirmation |
246
+ | `vir query "<question>"` | cheap | Semantic search your vault |
247
+ | `vir summarize <project>` | cheap | Cross-session project synthesis |
248
+ | `vir summarize --all` | $$ | Summarize all projects |
249
+ | `vir lint` | cheap | Find orphans, stale notes, contradictions |
250
+ | `vir lint --orphans` | free | Orphan check only |
251
+ | `vir lint --stale` | free | Staleness check only |
252
+ | `vir lint --contradictions` | cheap | Contradiction check (Haiku) |
253
+ | `vir dedupe` | cheap | Interactive duplicate detection |
254
+ | `vir review` | free | Walk new notes: approve/edit/reject |
255
+ | `vir review --project <s>` | free | Review one project's notes |
256
+ | `vir review --all` | free | Re-review, including verified notes |
257
+ | `vir sync-claude` | free | Inject top knowledge into CLAUDE.md |
258
+ | `vir sync-claude --dry-run` | free | Preview changes, no writes |
259
+ | `vir sync-claude --force` | free | Apply without confirmation |
260
+ | `vir embed` | free | Generate embeddings for semantic search |
261
+ | `vir embed --force` | free | Regenerate all embeddings |
262
+ | `vir schedule install` | free | Register the background daemon |
263
+ | `vir schedule uninstall` | free | Remove the background daemon |
264
+ | `vir status` | free | Knowledge heatmap + daemon status |
265
+ | `vir doctor` | cheap | Diagnose installation issues |
234
266
 
235
267
  ## MCP server (Claude Code integration)
236
268
 
@@ -245,6 +277,8 @@ vir mcp install
245
277
 
246
278
  Restart Claude Code. The vault is now queryable mid-session via four tools:
247
279
  `vir_query`, `vir_status`, `vir_recent_notes`, `vir_project_summary`.
280
+ Human-verified notes (approved via `vir review`) are ranked first; pass
281
+ `verified_only: true` to `vir_query` or `vir_recent_notes` to see only those.
248
282
 
249
283
  To unregister:
250
284
 
@@ -252,23 +286,42 @@ To unregister:
252
286
  vir mcp uninstall
253
287
  ```
254
288
 
289
+ ## Semantic search (optional)
290
+
291
+ Vir uses TF-IDF by default. For semantic search via embeddings:
292
+
293
+ ```bash
294
+ brew install ollama
295
+ ollama pull nomic-embed-text
296
+ ollama serve
297
+ ```
298
+
299
+ Then in a new terminal:
300
+
301
+ ```bash
302
+ vir embed
303
+ vir query "how do I handle rate limiting in Next.js"
304
+ ```
305
+
306
+ Falls back to TF-IDF automatically if Ollama is not running.
307
+
255
308
  ## Config reference
256
309
 
257
310
  Located at `~/.vir/config.json`.
258
311
 
259
- | Field | Default | Description |
260
- |---|---|---|
261
- | `vaultPath` | — | Absolute path to Obsidian vault |
262
- | `outputDir` | `vir` | Subdir inside vault |
263
- | `claudeProjectsDir` | `~/.claude/projects` | Claude Code sessions |
264
- | `cadenceHours` | `3` | Daemon run frequency (hours) |
265
- | `provider` | `anthropic` | `anthropic` or `kie` |
266
- | `anthropicApiKey` | — | Required if `provider=anthropic` |
267
- | `kieApiKey` | — | Required if `provider=kie` |
268
- | `filterThreshold` | `0.4` | Heuristic pre-filter (0..1) |
269
- | `filterToolCalls` | `moderate` | Tool-output filtering: `aggressive` \| `moderate` \| `off` |
270
- | `models.classify` | `claude-haiku-4-5-20251001` | Classify model |
271
- | `models.distill` | `claude-sonnet-4-6` | Distill model |
312
+ | Field | Default | Description |
313
+ | ------------------- | --------------------------- | ---------------------------------------------------------- |
314
+ | `vaultPath` | — | Absolute path to Obsidian vault |
315
+ | `outputDir` | `vir` | Subdir inside vault |
316
+ | `claudeProjectsDir` | `~/.claude/projects` | Claude Code sessions |
317
+ | `cadenceHours` | `3` | Daemon run frequency (hours) |
318
+ | `provider` | `anthropic` | `anthropic` or `kie` |
319
+ | `anthropicApiKey` | — | Required if `provider=anthropic` |
320
+ | `kieApiKey` | — | Required if `provider=kie` |
321
+ | `filterThreshold` | `0.4` | Heuristic pre-filter (0..1) |
322
+ | `filterToolCalls` | `moderate` | Tool-output filtering: `aggressive` \| `moderate` \| `off` |
323
+ | `models.classify` | `claude-haiku-4-5-20251001` | Classify model |
324
+ | `models.distill` | `claude-sonnet-4-6` | Distill model |
272
325
 
273
326
  ## Vault structure
274
327
 
@@ -292,20 +345,20 @@ vault/vir/
292
345
  ~/.vir/daemon.log — daemon run log
293
346
  ```
294
347
 
295
- ## How it compares
348
+ ## Project status
296
349
 
297
- | | Vir | mem0 | Manual notes |
298
- |---|---|---|---|
299
- | Source | Claude Code sessions | Any conversation | You |
300
- | Output | Typed markdown vault | Key-value store | Anything |
301
- | CLAUDE.md injection | | ✗ | Manual |
302
- | Local / private | | | |
303
- | Semantic search | (Ollama) | ✓ | ✗ |
304
- | Cost | ~$0.05/run | Subscription | Free |
350
+ | | |
351
+ | -------------- | ----------------------------------------- |
352
+ | Tests | 59 passing |
353
+ | Platforms | macOS (launchd), Linux (systemd/cron) |
354
+ | Node | 20+ |
355
+ | First-run cost | $1–5 (Kie.ai recommended for 72% savings) |
356
+ | Ongoing cost | ~$0.05 per run |
305
357
 
306
358
  ## Roadmap
307
359
 
308
360
  - [x] Linux support (systemd timer + cron fallback) — experimental
361
+ - [x] Active learning — `vir review` to approve, edit, or reject distillations, with verified notes prioritized in retrieval
309
362
  - [ ] Windows support
310
363
  - [ ] GUI installer for non-developers
311
364
  - [ ] Obsidian plugin for in-vault queries
@@ -331,10 +384,14 @@ npm test
331
384
 
332
385
  MIT
333
386
 
334
- ## Author
387
+ ## Author & credits
335
388
 
336
389
  Built by Djordje Marković / GrowthQ Lab DOO.
337
390
 
391
+ Vir (вир) is the Serbian word for _whirlpool_ — the place where a river pulls
392
+ everything in and concentrates it. Sessions flow in, Vir pulls out what matters,
393
+ and deposits it somewhere permanent.
394
+
338
395
  Inspired by Andrej Karpathy's LLM Wiki pattern and Uros Pesic's KB Brain concept.
339
396
 
340
397
  [GitHub](https://github.com/djolex999) ·