@djolex999/vir-cli 0.4.0 → 0.4.1

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 (2) hide show
  1. package/README.md +178 -130
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -5,67 +5,91 @@
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-50%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
+
76
+ The bet: with these controls, signal-to-noise stays high enough that the vault
77
+ is a net positive. If your discipline is strong enough to maintain `CLAUDE.md`
78
+ and `lessons.md` by hand, you may not need this. If — like most of us — you let
79
+ those files drift after the first week, Vir catches what slips through.
40
80
 
41
81
  ## How it works
42
82
 
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
83
+ Vir reads your transcripts from `~/.claude/projects/**/*.jsonl`, runs each
84
+ session through a cheap heuristic filter, classifies the survivors with Haiku,
85
+ and distills durable knowledge with Sonnet. Before distillation it **filters tool
86
+ calls** preserving intent (file paths, commands, search patterns, errors, short
87
+ results) while truncating large embedded content (file writes, long bash logs,
88
+ big grep dumps) to keep token cost bounded (tunable via `filterToolCalls`).
89
+ Results are written as typed notes patterns, gotchas, decisions, tools
90
+ cross-linked with wikilinks and indexed. State lives in local SQLite; content
91
+ hashes make reruns idempotent. Optional Ollama embeddings power semantic search,
92
+ and an MCP server exposes the whole vault to Claude Code mid-session.
69
93
 
70
94
  ```
71
95
  Claude Code sessions
@@ -81,17 +105,46 @@ better sessions
81
105
  ...
82
106
  ```
83
107
 
84
- ## After one night
108
+ ## How Vir compares
109
+
110
+ The AI memory space has grown fast. An honest comparison to the options worth
111
+ knowing about:
112
+
113
+ | | Vir | claude-mem | claude-memory | mem0 |
114
+ | ----------------------------------- | ------------------------------- | ----------------------- | -------------------------- | ----------------- |
115
+ | Reads existing Claude Code sessions | ✓ | from install forward | from install forward | n/a |
116
+ | Markdown output (Obsidian-native) | ✓ | ChromaDB | LanceDB | various backends |
117
+ | MCP server | ✓ | ✓ | ✓ | n/a |
118
+ | Setup complexity | `npm install -g` | Bun + Python + ChromaDB | pnpm + LM Studio + LanceDB | API/cloud setup |
119
+ | Cross-platform daemon | mac launchd, linux systemd/cron | mac, linux | mac, linux | n/a |
120
+ | Open source license | MIT | Apache 2.0 | MIT | open core + cloud |
121
+
122
+ **Different tools for different needs:**
123
+
124
+ - Want a heavyweight memory plugin with real-time capture and vector storage?
125
+ Use **claude-mem**.
126
+ - Want sophisticated retrieval (MMR diversity, web dashboard, multi-phase
127
+ maintenance)? Use **claude-memory**.
128
+ - Building AI applications that need to remember users long-term? Use **mem0** —
129
+ it's infrastructure for apps.
130
+ - Want your Claude Code sessions distilled into markdown notes you can browse,
131
+ edit, and own in Obsidian? Use **Vir**.
132
+
133
+ These aren't all competitors. mem0 is a different layer of the stack entirely.
134
+ claude-mem and claude-memory share the same input data as Vir but take different
135
+ opinions on storage and integration.
136
+
137
+ ## Real-world results
85
138
 
86
139
  Real output from the author's first run across 226 Claude Code sessions.
87
140
 
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 |
141
+ | Metric | Value |
142
+ | ------------------- | ------------------------------------------------- |
143
+ | Sessions scanned | 226 |
144
+ | Notes distilled | 126 |
145
+ | Avg confidence | 0.91 |
146
+ | High signal (≥0.8) | 121 of 126 |
147
+ | Projects covered | 8 projects |
95
148
  | Knowledge breakdown | 54 patterns · 47 decisions · 23 gotchas · 2 tools |
96
149
 
97
150
  Example query against the distilled vault:
@@ -99,6 +152,7 @@ Example query against the distilled vault:
99
152
  ```bash
100
153
  $ vir query "what gotchas should I know about my auth implementation"
101
154
  ```
155
+
102
156
  Based on the notes, here are the key auth gotchas:
103
157
 
104
158
  JWT dual-token setup needs silent refresh on mount — access tokens
@@ -117,7 +171,7 @@ Logout must clear both the access token cookie and the refresh
117
171
  token — clearing only one leaves the session partially alive and
118
172
  causes confusing re-auth loops.
119
173
 
120
- sources 4 · via embedding · searched 126
174
+ sources 4 · via embedding · searched 126
121
175
 
122
176
  ## Prerequisites
123
177
 
@@ -163,12 +217,12 @@ Pass `--yes` to skip the cost confirmation prompt.
163
217
 
164
218
  ## Platform support
165
219
 
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 |
220
+ | Platform | Daemon | Notifications | Status |
221
+ | --------------- | ------------------ | ------------- | ------------ |
222
+ | macOS | launchd | osascript | Stable |
223
+ | Linux (systemd) | systemd user timer | notify-send | Experimental |
224
+ | Linux (cron) | crontab | notify-send | Experimental |
225
+ | Windows | Not supported | — | Planned |
172
226
 
173
227
  Linux support is **experimental and untested** — `vir schedule install` prefers
174
228
  a systemd user timer and falls back to a crontab entry when systemd is absent.
@@ -178,59 +232,30 @@ with your distro, init system, and Node version.
178
232
 
179
233
  ## Commands
180
234
 
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.
235
+ | Command | Cost | Description |
236
+ | --------------------------- | ----- | ----------------------------------------- |
237
+ | `vir init` | free | Interactive setup |
238
+ | `vir run` | cheap | Process new sessions |
239
+ | `vir run --full` | $$ | Reprocess all sessions |
240
+ | `vir run --rewrite-only` | free | Reformat notes, no API calls |
241
+ | `vir run --yes` | cheap | Skip cost confirmation |
242
+ | `vir query "<question>"` | cheap | Semantic search your vault |
243
+ | `vir summarize <project>` | cheap | Cross-session project synthesis |
244
+ | `vir summarize --all` | $$ | Summarize all projects |
245
+ | `vir lint` | cheap | Find orphans, stale notes, contradictions |
246
+ | `vir lint --orphans` | free | Orphan check only |
247
+ | `vir lint --stale` | free | Staleness check only |
248
+ | `vir lint --contradictions` | cheap | Contradiction check (Haiku) |
249
+ | `vir dedupe` | cheap | Interactive duplicate detection |
250
+ | `vir sync-claude` | free | Inject top knowledge into CLAUDE.md |
251
+ | `vir sync-claude --dry-run` | free | Preview changes, no writes |
252
+ | `vir sync-claude --force` | free | Apply without confirmation |
253
+ | `vir embed` | free | Generate embeddings for semantic search |
254
+ | `vir embed --force` | free | Regenerate all embeddings |
255
+ | `vir schedule install` | free | Register the background daemon |
256
+ | `vir schedule uninstall` | free | Remove the background daemon |
257
+ | `vir status` | free | Knowledge heatmap + daemon status |
258
+ | `vir doctor` | cheap | Diagnose installation issues |
234
259
 
235
260
  ## MCP server (Claude Code integration)
236
261
 
@@ -252,23 +277,42 @@ To unregister:
252
277
  vir mcp uninstall
253
278
  ```
254
279
 
280
+ ## Semantic search (optional)
281
+
282
+ Vir uses TF-IDF by default. For semantic search via embeddings:
283
+
284
+ ```bash
285
+ brew install ollama
286
+ ollama pull nomic-embed-text
287
+ ollama serve
288
+ ```
289
+
290
+ Then in a new terminal:
291
+
292
+ ```bash
293
+ vir embed
294
+ vir query "how do I handle rate limiting in Next.js"
295
+ ```
296
+
297
+ Falls back to TF-IDF automatically if Ollama is not running.
298
+
255
299
  ## Config reference
256
300
 
257
301
  Located at `~/.vir/config.json`.
258
302
 
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 |
303
+ | Field | Default | Description |
304
+ | ------------------- | --------------------------- | ---------------------------------------------------------- |
305
+ | `vaultPath` | — | Absolute path to Obsidian vault |
306
+ | `outputDir` | `vir` | Subdir inside vault |
307
+ | `claudeProjectsDir` | `~/.claude/projects` | Claude Code sessions |
308
+ | `cadenceHours` | `3` | Daemon run frequency (hours) |
309
+ | `provider` | `anthropic` | `anthropic` or `kie` |
310
+ | `anthropicApiKey` | — | Required if `provider=anthropic` |
311
+ | `kieApiKey` | — | Required if `provider=kie` |
312
+ | `filterThreshold` | `0.4` | Heuristic pre-filter (0..1) |
313
+ | `filterToolCalls` | `moderate` | Tool-output filtering: `aggressive` \| `moderate` \| `off` |
314
+ | `models.classify` | `claude-haiku-4-5-20251001` | Classify model |
315
+ | `models.distill` | `claude-sonnet-4-6` | Distill model |
272
316
 
273
317
  ## Vault structure
274
318
 
@@ -292,20 +336,20 @@ vault/vir/
292
336
  ~/.vir/daemon.log — daemon run log
293
337
  ```
294
338
 
295
- ## How it compares
339
+ ## Project status
296
340
 
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 |
341
+ | | |
342
+ | -------------- | ----------------------------------------- |
343
+ | Tests | 50 passing |
344
+ | Platforms | macOS (launchd), Linux (systemd/cron) |
345
+ | Node | 20+ |
346
+ | First-run cost | $1–5 (Kie.ai recommended for 72% savings) |
347
+ | Ongoing cost | ~$0.05 per run |
305
348
 
306
349
  ## Roadmap
307
350
 
308
351
  - [x] Linux support (systemd timer + cron fallback) — experimental
352
+ - [ ] Active learning — `vir review` to approve, edit, or reject distillations, with verified notes prioritized in retrieval
309
353
  - [ ] Windows support
310
354
  - [ ] GUI installer for non-developers
311
355
  - [ ] Obsidian plugin for in-vault queries
@@ -331,10 +375,14 @@ npm test
331
375
 
332
376
  MIT
333
377
 
334
- ## Author
378
+ ## Author & credits
335
379
 
336
380
  Built by Djordje Marković / GrowthQ Lab DOO.
337
381
 
382
+ Vir (вир) is the Serbian word for _whirlpool_ — the place where a river pulls
383
+ everything in and concentrates it. Sessions flow in, Vir pulls out what matters,
384
+ and deposits it somewhere permanent.
385
+
338
386
  Inspired by Andrej Karpathy's LLM Wiki pattern and Uros Pesic's KB Brain concept.
339
387
 
340
388
  [GitHub](https://github.com/djolex999) ·
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djolex999/vir-cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Distills Claude Code sessions into a compounding knowledge vault",
5
5
  "author": "Djordje Marković <djordje@growthq.rs>",
6
6
  "license": "MIT",