clawvault 2.6.1 → 2.6.4

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 (125) hide show
  1. package/README.md +352 -20
  2. package/bin/clawvault.js +8 -2
  3. package/bin/command-runtime.js +9 -1
  4. package/bin/register-maintenance-commands.js +19 -0
  5. package/bin/register-query-commands.js +58 -6
  6. package/bin/register-workgraph-commands.js +451 -0
  7. package/dist/{chunk-VXEOHTSL.js → chunk-2JQ3O2YL.js} +1 -1
  8. package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
  9. package/dist/chunk-2ZDO52B4.js +52 -0
  10. package/dist/chunk-4BQTQMJP.js +93 -0
  11. package/dist/{chunk-MAKNAHAW.js → chunk-5PJ4STIC.js} +98 -8
  12. package/dist/{chunk-IEVLHNLU.js → chunk-627Q3QWK.js} +3 -3
  13. package/dist/{chunk-R6SXNSFD.js → chunk-6NYYDNNG.js} +3 -3
  14. package/dist/chunk-ECRZL5XR.js +50 -0
  15. package/dist/chunk-GNJL4YGR.js +79 -0
  16. package/dist/{chunk-OZ7RIXTO.js → chunk-IIOU45CK.js} +1 -1
  17. package/dist/chunk-L4HSSQ6T.js +152 -0
  18. package/dist/{chunk-XAVB4GB4.js → chunk-LIGHWOH6.js} +1 -1
  19. package/dist/{chunk-PBEE567J.js → chunk-LUBZXECN.js} +2 -2
  20. package/dist/{chunk-UEOUADMO.js → chunk-MFL6EEPF.js} +204 -35
  21. package/dist/chunk-MM6QGW3P.js +207 -0
  22. package/dist/{chunk-T76H47ZS.js → chunk-MNPUYCHQ.js} +1 -1
  23. package/dist/{chunk-TLGBDTYT.js → chunk-MPOSMDMU.js} +6 -6
  24. package/dist/{chunk-RVYA52PY.js → chunk-NJYJL5AA.js} +1 -1
  25. package/dist/{chunk-Q2J5YTUF.js → chunk-OQGYFZ4A.js} +669 -33
  26. package/dist/{chunk-ME37YNW3.js → chunk-P7SY3D4E.js} +3 -3
  27. package/dist/chunk-RHISK3SZ.js +189 -0
  28. package/dist/{chunk-3BTHWPMB.js → chunk-S5OJEGFG.js} +2 -2
  29. package/dist/{chunk-MGDEINGP.js → chunk-SS4B7P7V.js} +1 -1
  30. package/dist/chunk-U4O6C46S.js +154 -0
  31. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  32. package/dist/chunk-WIOLLGAD.js +190 -0
  33. package/dist/chunk-WMGIIABP.js +15 -0
  34. package/dist/{chunk-QVMXF7FY.js → chunk-X3SPPUFG.js} +50 -0
  35. package/dist/{chunk-THRJVD4L.js → chunk-Y6VJKXGL.js} +1 -1
  36. package/dist/{chunk-KL4NAOMO.js → chunk-YDWHS4LJ.js} +49 -9
  37. package/dist/{chunk-4VRIMU4O.js → chunk-YNIPYN4F.js} +4 -4
  38. package/dist/{chunk-HIHOUSXS.js → chunk-YXQCA6B7.js} +105 -1
  39. package/dist/cli/index.js +18 -16
  40. package/dist/commands/archive.js +3 -2
  41. package/dist/commands/backlog.js +1 -0
  42. package/dist/commands/blocked.js +1 -0
  43. package/dist/commands/canvas.js +1 -0
  44. package/dist/commands/checkpoint.js +1 -0
  45. package/dist/commands/compat.js +2 -1
  46. package/dist/commands/context.js +5 -3
  47. package/dist/commands/doctor.d.ts +10 -1
  48. package/dist/commands/doctor.js +11 -8
  49. package/dist/commands/embed.js +5 -3
  50. package/dist/commands/entities.js +2 -1
  51. package/dist/commands/graph.js +3 -2
  52. package/dist/commands/inject.d.ts +1 -1
  53. package/dist/commands/inject.js +4 -3
  54. package/dist/commands/kanban.js +1 -0
  55. package/dist/commands/link.js +2 -1
  56. package/dist/commands/migrate-observations.js +3 -2
  57. package/dist/commands/observe.js +8 -6
  58. package/dist/commands/project.js +1 -0
  59. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  60. package/dist/commands/rebuild-embeddings.js +91 -0
  61. package/dist/commands/rebuild.js +6 -4
  62. package/dist/commands/recover.js +1 -0
  63. package/dist/commands/reflect.js +5 -4
  64. package/dist/commands/repair-session.js +1 -0
  65. package/dist/commands/replay.js +7 -6
  66. package/dist/commands/session-recap.js +1 -0
  67. package/dist/commands/setup.js +3 -2
  68. package/dist/commands/shell-init.js +2 -0
  69. package/dist/commands/sleep.d.ts +1 -1
  70. package/dist/commands/sleep.js +8 -6
  71. package/dist/commands/status.d.ts +2 -0
  72. package/dist/commands/status.js +35 -24
  73. package/dist/commands/sync-bd.js +3 -2
  74. package/dist/commands/tailscale.js +3 -2
  75. package/dist/commands/task.js +1 -0
  76. package/dist/commands/template.js +1 -0
  77. package/dist/commands/wake.d.ts +1 -1
  78. package/dist/commands/wake.js +4 -2
  79. package/dist/index.d.ts +333 -10
  80. package/dist/index.js +320 -33
  81. package/dist/{inject-x65KXWPk.d.ts → inject-DYUrDqQO.d.ts} +2 -2
  82. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  83. package/dist/lib/auto-linker.js +1 -0
  84. package/dist/lib/canvas-layout.js +1 -0
  85. package/dist/lib/config.d.ts +27 -3
  86. package/dist/lib/config.js +4 -1
  87. package/dist/lib/entity-index.js +1 -0
  88. package/dist/lib/project-utils.js +1 -0
  89. package/dist/lib/session-repair.js +1 -0
  90. package/dist/lib/session-utils.js +1 -0
  91. package/dist/lib/tailscale.js +1 -0
  92. package/dist/lib/task-utils.js +1 -0
  93. package/dist/lib/template-engine.js +1 -0
  94. package/dist/lib/webdav.js +1 -0
  95. package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
  96. package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
  97. package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
  98. package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
  99. package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
  100. package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
  101. package/dist/registry-BR4326o0.d.ts +30 -0
  102. package/dist/store-CA-6sKCJ.d.ts +34 -0
  103. package/dist/thread-B9LhXNU0.d.ts +41 -0
  104. package/dist/transformers.node-A2ZRORSQ.js +46775 -0
  105. package/dist/{types-C74wgGL1.d.ts → types-BbWJoC1c.d.ts} +1 -1
  106. package/dist/workgraph/index.d.ts +5 -0
  107. package/dist/workgraph/index.js +23 -0
  108. package/dist/workgraph/ledger.d.ts +2 -0
  109. package/dist/workgraph/ledger.js +25 -0
  110. package/dist/workgraph/registry.d.ts +2 -0
  111. package/dist/workgraph/registry.js +19 -0
  112. package/dist/workgraph/store.d.ts +2 -0
  113. package/dist/workgraph/store.js +25 -0
  114. package/dist/workgraph/thread.d.ts +2 -0
  115. package/dist/workgraph/thread.js +25 -0
  116. package/dist/workgraph/types.d.ts +54 -0
  117. package/dist/workgraph/types.js +7 -0
  118. package/hooks/clawvault/HOOK.md +34 -4
  119. package/hooks/clawvault/handler.js +751 -8
  120. package/hooks/clawvault/handler.test.js +247 -0
  121. package/hooks/clawvault/openclaw.plugin.json +72 -0
  122. package/openclaw.plugin.json +84 -0
  123. package/package.json +8 -4
  124. package/dist/chunk-4QYGFWRM.js +0 -88
  125. package/dist/chunk-MXSSG3QU.js +0 -42
package/README.md CHANGED
@@ -1,17 +1,301 @@
1
+ <div align="center">
2
+
1
3
  # ClawVault 🐘
2
4
 
3
- Structured memory system for AI agents and operators: typed markdown memory, graph-aware context, task/project primitives, Obsidian views, and OpenClaw hook integration.
5
+ **Persistent Memory for AI Agents**
4
6
 
7
+ [![Tests](https://img.shields.io/badge/tests-466%20passing-brightgreen)](https://github.com/Versatly/clawvault)
5
8
  [![npm](https://img.shields.io/npm/v/clawvault)](https://www.npmjs.com/package/clawvault)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
10
+ [![PRs Merged](https://img.shields.io/badge/PRs%20merged-20%2B-purple)](https://github.com/Versatly/clawvault/pulls?q=is%3Amerged)
11
+ [![Contributors](https://img.shields.io/badge/contributors-6-orange)](https://github.com/Versatly/clawvault/graphs/contributors)
12
+
13
+ *An elephant never forgets. Neither should your AI.*
14
+
15
+ [Documentation](https://clawvault.dev) · [npm Package](https://www.npmjs.com/package/clawvault) · [Obsidian Plugin](https://clawvault.dev/obsidian) · [GitHub](https://github.com/Versatly/clawvault)
16
+
17
+ </div>
18
+
19
+ ---
20
+
21
+ ## What is ClawVault?
22
+
23
+ ClawVault is a **structured memory system** for AI agents that uses **markdown as the storage primitive**. It solves the fundamental problem of AI agents losing context between sessions — what we call "context death."
24
+
25
+ Unlike vector databases or cloud-based memory solutions, ClawVault is:
26
+
27
+ - **Local-first** — Your data stays on your machine. No cloud sync, no vendor lock-in.
28
+ - **Markdown-native** — Human-readable, git-friendly, works with Obsidian out of the box.
29
+ - **Graph-aware** — Wiki-links build a knowledge graph that enriches context retrieval.
30
+ - **Session-resilient** — Checkpoint/recover primitives survive crashes and context resets.
31
+ - **Fact-aware** — Write-time extraction builds structured facts with conflict resolution.
32
+
33
+ ```
34
+ ┌─────────────────────────────────────────────────────────────────────────────┐
35
+ │ ClawVault Architecture │
36
+ ├─────────────────────────────────────────────────────────────────────────────┤
37
+ │ │
38
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
39
+ │ │ Agent │───▶│ Session │───▶│ Observer │───▶│ Router │ │
40
+ │ │ (Claude, │ │ Watcher │ │Compressor│ │ │ │
41
+ │ │ GPT..) │ └──────────┘ └──────────┘ └────┬─────┘ │
42
+ │ └──────────┘ │ │
43
+ │ │ ▼ │
44
+ │ │ ┌─────────────────────────────────────────────────────┐ │
45
+ │ │ │ Markdown Vault │ │
46
+ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │
47
+ │ │ │ │decisions/│ │ lessons/ │ │ people/ │ │projects│ │ │
48
+ │ │ │ └──────────┘ └──────────┘ └──────────┘ └────────┘ │ │
49
+ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │
50
+ │ │ │ │ tasks/ │ │ backlog/ │ │handoffs/ │ │ inbox/ │ │ │
51
+ │ │ │ └──────────┘ └──────────┘ └──────────┘ └────────┘ │ │
52
+ │ │ └─────────────────────────────────────────────────────┘ │
53
+ │ │ │ │
54
+ │ │ ┌──────────────────────────┴──────────────────────────┐ │
55
+ │ │ │ .clawvault/ (Internal State) │ │
56
+ │ │ │ graph-index.json │ last-checkpoint.json │ config │ │
57
+ │ │ └─────────────────────────────────────────────────────┘ │
58
+ │ │ │ │
59
+ │ ▼ ▼ │
60
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
61
+ │ │ wake │◀──▶│ context │◀──▶│ Graph │◀──▶│ Search │ │
62
+ │ │ sleep │ │ profiles │ │ Traversal│ │(qmd/vec) │ │
63
+ │ │checkpoint│ └──────────┘ └──────────┘ └──────────┘ │
64
+ │ └──────────┘ │
65
+ │ │
66
+ │ Data Flow: Session → Observe → Score → Route → Store → Reflect → Promote │
67
+ │ │
68
+ └─────────────────────────────────────────────────────────────────────────────┘
69
+ ```
70
+
71
+ ---
72
+
73
+ ## The 8 Primitives
74
+
75
+ ClawVault is built around 8 core primitives that model how agents should interact with persistent memory:
76
+
77
+ | Primitive | Description | ClawVault Implementation |
78
+ |-----------|-------------|--------------------------|
79
+ | **Goals** | What the agent is trying to achieve | `tasks/`, `projects/`, `--working-on` flags |
80
+ | **Agents** | Identity and ownership tracking | `--owner` metadata, agent handoffs |
81
+ | **State Space** | Current context and environment | `checkpoint`, `recover`, session state |
82
+ | **Feedback** | Learning from outcomes | `lessons/`, `observations/`, reflection engine |
83
+ | **Capital** | Resources and constraints | Token budgets, context profiles, priority scoring |
84
+ | **Institution** | Rules and patterns | `decisions/`, `preferences/`, injection rules |
85
+ | **Synthesis** | Combining information | Graph traversal, context blending, semantic search |
86
+ | **Recursion** | Self-improvement loops | `reflect`, weekly promotion, archival |
87
+
88
+ These primitives map directly to CLI commands and vault structure, creating a coherent system for agent memory.
89
+
90
+ ---
91
+
92
+ ## Quick Start
93
+
94
+ ### Installation
95
+
96
+ ```bash
97
+ # Install ClawVault CLI
98
+ npm install -g clawvault
99
+
100
+ # Install qmd (required for search/context features)
101
+ npm install -g github:tobi/qmd
102
+ ```
103
+
104
+ ### Initialize Your Vault
105
+
106
+ ```bash
107
+ # Create a new vault
108
+ clawvault init ~/memory --name my-brain
109
+
110
+ # Optional: Set up Obsidian integration
111
+ clawvault setup --theme neural --canvas
112
+ ```
113
+
114
+ ### Basic Workflow
115
+
116
+ ```bash
117
+ # Start your session
118
+ clawvault wake
119
+
120
+ # Store memories as you work
121
+ clawvault remember decision "Use PostgreSQL" --content "Chosen for JSONB support"
122
+ clawvault capture "TODO: Review PR tomorrow"
123
+
124
+ # Checkpoint during heavy work
125
+ clawvault checkpoint --working-on "auth rollout" --focus "token refresh"
126
+
127
+ # End your session
128
+ clawvault sleep "finished auth rollout" --next "implement migration"
129
+ ```
130
+
131
+ ### Search and Context
132
+
133
+ ```bash
134
+ # Keyword search
135
+ clawvault search "postgresql"
136
+
137
+ # Semantic search
138
+ clawvault vsearch "what did we decide about storage"
139
+
140
+ # Get context for a task
141
+ clawvault context "database migration"
142
+ clawvault context --profile planning "Q1 roadmap"
143
+ ```
144
+
145
+ ---
146
+
147
+ ## v3.0 — Structured Memory
148
+
149
+ ClawVault v3 adds **write-time fact extraction** and **entity graphs** to the core memory pipeline:
150
+
151
+ - **Fact Store** — Extracts structured facts (preferences, attributes, relationships) at write time with conflict resolution and deduplication
152
+ - **Entity Graph** — Builds a relational graph enabling multi-hop queries ("Alice works at Google + Google is in CA → Alice is in CA")
153
+ - **Hybrid Search** — BM25 + semantic embeddings + Reciprocal Rank Fusion (RRF)
154
+
155
+ ### Project Stats
6
156
 
7
- > Local-first. Markdown-first. Built to survive long-running autonomous work.
157
+ - **466 tests** passing across **71 test files**
158
+ - **20+ PRs** merged from **6 external contributors**
159
+ - Published on npm as [`clawvault`](https://www.npmjs.com/package/clawvault)
160
+ - Active development since February 2026
161
+
162
+ ---
163
+
164
+ ## Features
165
+
166
+ ### Memory Graph
167
+
168
+ ClawVault builds a typed knowledge graph from wiki-links, tags, and frontmatter:
169
+
170
+ ```bash
171
+ # View graph summary
172
+ clawvault graph
173
+
174
+ # Refresh graph index
175
+ clawvault graph --refresh
176
+ ```
177
+
178
+ ### Context Profiles
179
+
180
+ Different tasks need different context. Use profiles to tune retrieval:
181
+
182
+ | Profile | Purpose |
183
+ |---------|---------|
184
+ | `default` | Balanced retrieval |
185
+ | `planning` | Broader strategic context |
186
+ | `incident` | Recent events, blockers, urgent items |
187
+ | `handoff` | Session transition context |
188
+ | `auto` | Hook-selected based on session intent |
189
+
190
+ ```bash
191
+ clawvault context --profile incident "production outage"
192
+ ```
193
+
194
+ ### Task Management
195
+
196
+ Full task lifecycle with Kanban support:
197
+
198
+ ```bash
199
+ # Create tasks
200
+ clawvault task add "Ship v2 onboarding" --owner agent --project core --priority high
201
+
202
+ # View blocked items
203
+ clawvault blocked
204
+
205
+ # Sync with Obsidian Kanban
206
+ clawvault kanban sync
207
+ ```
208
+
209
+ ### Dynamic Prompt Injection
210
+
211
+ Pull relevant decisions and preferences into agent context automatically:
212
+
213
+ ```bash
214
+ clawvault inject "How should we handle the deployment?"
215
+ clawvault inject --enable-llm "What's our pricing strategy?"
216
+ ```
217
+
218
+ ---
219
+
220
+ ## Obsidian Integration
221
+
222
+ ClawVault is designed to work seamlessly with Obsidian:
223
+
224
+ - **Graph themes** — Neural/minimal themes with colored nodes by category
225
+ - **Bases views** — Auto-generated task views (`all-tasks.base`, `blocked.base`, `by-project.base`)
226
+ - **Canvas dashboards** — `clawvault canvas` generates visual dashboards
227
+ - **Kanban round-trip** — Export/import between ClawVault and Obsidian Kanban
228
+
229
+ ```bash
230
+ # Generate canvas dashboard
231
+ clawvault canvas --template brain
232
+
233
+ # Set up Obsidian integration
234
+ clawvault setup --theme neural --canvas --bases
235
+ ```
236
+
237
+ ---
238
+
239
+ ## OpenClaw Integration
240
+
241
+ For hook-based lifecycle integration with OpenClaw:
242
+
243
+ ```bash
244
+ # Install and enable hook pack
245
+ openclaw hooks install clawvault
246
+ openclaw hooks enable clawvault
247
+
248
+ # Verify
249
+ openclaw hooks list --verbose
250
+ openclaw hooks check
251
+ clawvault compat
252
+ ```
253
+
254
+ The hook automatically:
255
+ - Detects context death and injects recovery alerts
256
+ - Auto-checkpoints before session resets
257
+ - Provides `--profile auto` for context queries
258
+
259
+ ### MEMORY.md vs Vault
260
+
261
+ If you use both a `MEMORY.md` workspace file and a ClawVault vault, understand their roles:
262
+
263
+ - **MEMORY.md** = Boot context (executive summary the agent sees instantly)
264
+ - **Vault** = Full knowledge store (searchable, structured, versioned)
265
+
266
+ MEMORY.md should contain high-level identity, key decisions, and current focus. The vault stores everything else. Update MEMORY.md periodically to reflect vault state, but it doesn't need to mirror it.
267
+
268
+ See [docs/openclaw-plugin-usage.md](docs/openclaw-plugin-usage.md) for detailed guidance on this pattern.
269
+
270
+ ---
8
271
 
9
272
  ## Requirements
10
273
 
11
274
  - Node.js 18+
12
- - `qmd` installed and available on `PATH`
275
+ - `qmd` installed and available on `PATH` (for search/context features)
276
+
277
+ ## LLM Providers
278
+
279
+ ClawVault supports multiple LLM providers for features like context generation, observation compression, and semantic search. Set the appropriate environment variable to enable a provider:
13
280
 
14
- ClawVault currently relies on `qmd` for core vault/query flows. Install it before first use.
281
+ | Provider | Environment Variable | Default Model | Notes |
282
+ |----------|---------------------|---------------|-------|
283
+ | **Anthropic** | `ANTHROPIC_API_KEY` | `claude-3-5-haiku-latest` | Claude models |
284
+ | **OpenAI** | `OPENAI_API_KEY` | `gpt-4o-mini` | GPT models |
285
+ | **Google Gemini** | `GEMINI_API_KEY` | `gemini-2.0-flash` | Gemini models |
286
+ | **xAI (Grok)** | `XAI_API_KEY` | `grok-2-latest` | Grok models via OpenAI-compatible API |
287
+ | **Ollama** | (local) | `llama3.2` | Local models, no API key needed |
288
+ | **OpenAI-compatible** | `OPENAI_API_KEY` | `gpt-4o-mini` | Any OpenAI-compatible endpoint |
289
+
290
+ Provider priority (when multiple keys are set): OpenClaw > Anthropic > OpenAI > Gemini > xAI
291
+
292
+ ```bash
293
+ # Example: Use xAI (Grok) as your LLM provider
294
+ export XAI_API_KEY="your-xai-api-key"
295
+
296
+ # Example: Use Anthropic
297
+ export ANTHROPIC_API_KEY="your-anthropic-api-key"
298
+ ```
15
299
 
16
300
  ## Install
17
301
 
@@ -68,35 +352,39 @@ Append these to your existing memory workflow. Do not replace your full prompt s
68
352
  - Use `clawvault context "<task>"` or `clawvault inject "<message>"` before complex decisions.
69
353
  ```
70
354
 
71
- ## Real CLI Surface (Current)
355
+ ---
356
+
357
+ ## CLI Reference
72
358
 
73
- Core:
359
+ ### Core Commands
74
360
 
75
361
  - `init`, `setup`, `store`, `capture`
76
362
  - `remember`, `list`, `get`, `stats`, `reindex`, `sync`
77
363
 
78
- Context + memory:
364
+ ### Context + Memory
79
365
 
80
366
  - `search`, `vsearch`, `context`, `inject`
81
367
  - `observe`, `reflect`, `session-recap`
82
368
  - `graph`, `entities`, `link`, `embed`
83
369
 
84
- Resilience:
370
+ ### Resilience
85
371
 
86
372
  - `wake`, `sleep`, `handoff`, `recap`
87
373
  - `checkpoint`, `recover`, `status`, `clean-exit`, `repair-session`
88
374
  - `compat`, `doctor`
89
375
 
90
- Execution primitives:
376
+ ### Execution Primitives
91
377
 
92
378
  - `task ...`, `backlog ...`, `blocked`, `project ...`, `kanban ...`
93
379
  - `canvas` (generates default `dashboard.canvas`)
94
380
 
95
- Networking:
381
+ ### Networking
96
382
 
97
383
  - `tailscale-status`, `tailscale-sync`, `tailscale-serve`, `tailscale-discover`
98
384
 
99
- ## Quick Usage
385
+ ---
386
+
387
+ ## Quick Usage Examples
100
388
 
101
389
  ```bash
102
390
  # Store and retrieve memory
@@ -119,15 +407,7 @@ clawvault kanban sync
119
407
  clawvault canvas
120
408
  ```
121
409
 
122
- ## Obsidian Integration
123
-
124
- - Setup can generate:
125
- - graph theme/snippet config (`--theme neural|minimal|none`)
126
- - Bases views (`all-tasks.base`, `blocked.base`, `by-project.base`, `by-owner.base`, `backlog.base`)
127
- - default canvas (`dashboard.canvas`) via `--canvas` or `clawvault canvas`
128
- - Kanban round-trip:
129
- - export: `clawvault kanban sync`
130
- - import lane changes back to task metadata: `clawvault kanban import`
410
+ ---
131
411
 
132
412
  ## Tailscale + WebDAV
133
413
 
@@ -139,6 +419,29 @@ clawvault tailscale-serve --vault ~/memory
139
419
  clawvault tailscale-discover
140
420
  ```
141
421
 
422
+ ---
423
+
424
+ ## Vault Structure
425
+
426
+ ```
427
+ vault/
428
+ ├── .clawvault/ # Internal state
429
+ │ ├── graph-index.json # Knowledge graph
430
+ │ ├── last-checkpoint.json
431
+ │ └── config.json
432
+ ├── decisions/ # Key choices with reasoning
433
+ ├── lessons/ # Insights and patterns
434
+ ├── people/ # One file per person
435
+ ├── projects/ # Active work tracking
436
+ ├── tasks/ # Task files with frontmatter
437
+ ├── backlog/ # Quick captures and ideas
438
+ ├── handoffs/ # Session continuity
439
+ ├── inbox/ # Quick captures
440
+ └── templates/ # Document templates
441
+ ```
442
+
443
+ ---
444
+
142
445
  ## Troubleshooting
143
446
 
144
447
  - Hook not found after enable:
@@ -154,6 +457,35 @@ clawvault tailscale-discover
154
457
  - Session transcript corruption:
155
458
  - run `clawvault repair-session --dry-run` then `clawvault repair-session`
156
459
 
460
+ ---
461
+
462
+ ## Links
463
+
464
+ | Resource | URL |
465
+ |----------|-----|
466
+ | **Documentation** | [clawvault.dev](https://clawvault.dev) |
467
+ | **npm Package** | [npmjs.com/package/clawvault](https://www.npmjs.com/package/clawvault) |
468
+ | **GitHub** | [github.com/Versatly/clawvault](https://github.com/Versatly/clawvault) |
469
+ | **Issues** | [github.com/Versatly/clawvault/issues](https://github.com/Versatly/clawvault/issues) |
470
+ | **Obsidian Plugin** | [clawvault.dev/obsidian](https://clawvault.dev/obsidian) |
471
+
472
+ ---
473
+
474
+ ## Contributing
475
+
476
+ We welcome contributions! ClawVault has had **20+ PRs merged** from **6 external contributors**.
477
+
478
+ 1. Fork the repository
479
+ 2. Create a feature branch
480
+ 3. Run tests: `npm test`
481
+ 4. Submit a PR
482
+
483
+ See our [contribution guidelines](https://github.com/Versatly/clawvault/blob/main/CONTRIBUTING.md) for details.
484
+
485
+ ---
486
+
487
+ **$CLAW**: [`5Fjr82MTB8mvxkzi9FYtvrUsPiDGE2M29w3dYcZpump`](https://pump.fun/coin/5Fjr82MTB8mvxkzi9FYtvrUsPiDGE2M29w3dYcZpump)
488
+
157
489
  ## License
158
490
 
159
491
  MIT
package/bin/clawvault.js CHANGED
@@ -23,13 +23,16 @@ import { registerProjectCommands } from './register-project-commands.js';
23
23
 
24
24
  import { registerTaskCommands } from './register-task-commands.js';
25
25
 
26
+ import { registerWorkgraphCommands } from './register-workgraph-commands.js';
26
27
  import { registerTailscaleCommands } from './register-tailscale-commands.js';
27
28
  import {
28
29
  getVault,
29
30
  resolveVaultPath,
30
31
  runQmd,
31
32
  printQmdMissing,
32
- QmdUnavailableError
33
+ printQmdConfigError,
34
+ QmdUnavailableError,
35
+ QmdConfigurationError
33
36
  } from './command-runtime.js';
34
37
  import {
35
38
  createVault
@@ -66,7 +69,9 @@ registerQueryCommands(program, {
66
69
  getVault,
67
70
  resolveVaultPath,
68
71
  QmdUnavailableError,
69
- printQmdMissing
72
+ QmdConfigurationError,
73
+ printQmdMissing,
74
+ printQmdConfigError
70
75
  });
71
76
 
72
77
  registerSessionLifecycleCommands(program, {
@@ -104,6 +109,7 @@ registerProjectCommands(program, {
104
109
  resolveVaultPath
105
110
  });
106
111
 
112
+ registerWorkgraphCommands(program, { chalk, resolveVaultPath });
107
113
  registerTailscaleCommands(program, { chalk });
108
114
  registerConfigCommands(program, { chalk, resolveVaultPath });
109
115
  registerRouteCommands(program, { chalk, resolveVaultPath });
@@ -4,6 +4,7 @@ import path from 'path';
4
4
  import {
5
5
  ClawVault,
6
6
  QmdUnavailableError,
7
+ QmdConfigurationError,
7
8
  QMD_INSTALL_COMMAND,
8
9
  resolveVaultPath as resolveConfiguredVaultPath
9
10
  } from '../dist/index.js';
@@ -90,4 +91,11 @@ export function printQmdMissing() {
90
91
  console.log(chalk.dim(`Install: ${QMD_INSTALL_COMMAND}`));
91
92
  }
92
93
 
93
- export { QmdUnavailableError };
94
+ export function printQmdConfigError(err) {
95
+ console.error(chalk.red(`Error: ${err.message}`));
96
+ if (err.hint) {
97
+ console.log(chalk.yellow(`Hint: ${err.hint}`));
98
+ }
99
+ }
100
+
101
+ export { QmdUnavailableError, QmdConfigurationError };
@@ -80,6 +80,25 @@ export function registerMaintenanceCommands(program, { chalk }) {
80
80
  }
81
81
  });
82
82
 
83
+ // === REBUILD-EMBEDDINGS ===
84
+ program
85
+ .command('rebuild-embeddings')
86
+ .description('Rebuild local embedding cache for hybrid search (uses all-MiniLM-L6-v2)')
87
+ .option('-v, --vault <path>', 'Vault path')
88
+ .option('--force', 'Force rebuild all embeddings (ignore cache)')
89
+ .action(async (options) => {
90
+ try {
91
+ const { rebuildEmbeddingsCommand } = await import('../dist/commands/rebuild-embeddings.js');
92
+ await rebuildEmbeddingsCommand({
93
+ vaultPath: options.vault,
94
+ force: options.force
95
+ });
96
+ } catch (err) {
97
+ console.error(chalk.red(`Error: ${err.message}`));
98
+ process.exit(1);
99
+ }
100
+ });
101
+
83
102
  // === COMPAT (OpenClaw compatibility) ===
84
103
  program
85
104
  .command('compat')
@@ -9,13 +9,15 @@ export function registerQueryCommands(
9
9
  getVault,
10
10
  resolveVaultPath,
11
11
  QmdUnavailableError,
12
- printQmdMissing
12
+ QmdConfigurationError,
13
+ printQmdMissing,
14
+ printQmdConfigError
13
15
  }
14
16
  ) {
15
17
  // === SEARCH ===
16
18
  program
17
19
  .command('search <query>')
18
- .description('Search the vault via qmd (BM25)')
20
+ .description('Search the vault via qmd (BM25), optionally with semantic hybrid search')
19
21
  .option('-n, --limit <n>', 'Max results (default: 10)', '10')
20
22
  .option('-c, --category <category>', 'Filter by category')
21
23
  .option('--tags <tags>', 'Filter by tags (comma-separated)')
@@ -23,20 +25,57 @@ export function registerQueryCommands(
23
25
  .option('--full', 'Include full content in results')
24
26
  .option('-v, --vault <path>', 'Vault path')
25
27
  .option('--json', 'Output as JSON')
28
+ .option('--semantic', 'Enable hybrid search (BM25 + semantic with RRF)')
29
+ .option('--rebuild-embeddings', 'Rebuild the embedding cache before searching')
26
30
  .action(async (query, options) => {
27
31
  try {
32
+ const vaultPath = resolveVaultPath(options.vault);
28
33
  const vault = await getVault(options.vault);
29
34
 
30
- const results = await vault.find(query, {
31
- limit: parseInt(options.limit, 10),
35
+ // Handle --rebuild-embeddings flag
36
+ if (options.rebuildEmbeddings) {
37
+ const { rebuildEmbeddingsForVault } = await import('../dist/commands/rebuild-embeddings.js');
38
+ console.log(chalk.cyan('Rebuilding embedding cache...'));
39
+ const stats = await rebuildEmbeddingsForVault(vaultPath, {
40
+ onProgress: (current, total) => {
41
+ process.stdout.write(`\r Embedding ${current}/${total} documents...`);
42
+ }
43
+ });
44
+ console.log(chalk.green(`\n Done. ${stats.total} embeddings (${stats.added} new, ${stats.skipped} cached)`));
45
+ console.log();
46
+ }
47
+
48
+ // Get BM25 results
49
+ const bm25Results = await vault.find(query, {
50
+ limit: options.semantic ? 50 : parseInt(options.limit, 10),
32
51
  category: options.category,
33
52
  tags: options.tags?.split(',').map((value) => value.trim()),
34
53
  fullContent: options.full,
35
54
  temporalBoost: options.recent
36
55
  });
37
56
 
57
+ let results = bm25Results;
58
+ let searchMode = 'BM25';
59
+
60
+ // Apply hybrid search if --semantic flag is set
61
+ if (options.semantic) {
62
+ const { EmbeddingCache, hybridSearch } = await import('../dist/lib/hybrid-search.js');
63
+ const cache = new EmbeddingCache(vaultPath);
64
+ cache.load();
65
+
66
+ if (cache.size === 0) {
67
+ console.log(chalk.yellow('Warning: No embeddings found. Run with --rebuild-embeddings to build the cache.'));
68
+ } else {
69
+ results = await hybridSearch(query, bm25Results, cache, {
70
+ topK: parseInt(options.limit, 10),
71
+ rrfK: 60
72
+ });
73
+ searchMode = 'Hybrid (BM25 + Semantic)';
74
+ }
75
+ }
76
+
38
77
  if (options.json) {
39
- console.log(JSON.stringify(results, null, 2));
78
+ console.log(JSON.stringify({ searchMode, results }, null, 2));
40
79
  return;
41
80
  }
42
81
 
@@ -45,7 +84,8 @@ export function registerQueryCommands(
45
84
  return;
46
85
  }
47
86
 
48
- console.log(chalk.cyan(`\n🔍 Found ${results.length} result(s) for "${query}":\n`));
87
+ const icon = options.semantic ? '🔍🧠' : '🔍';
88
+ console.log(chalk.cyan(`\n${icon} Found ${results.length} result(s) for "${query}" [${searchMode}]:\n`));
49
89
 
50
90
  for (const result of results) {
51
91
  const scoreBar = '█'.repeat(Math.round(result.score * 10)).padEnd(10, '░');
@@ -62,6 +102,10 @@ export function registerQueryCommands(
62
102
  printQmdMissing();
63
103
  process.exit(1);
64
104
  }
105
+ if (err instanceof QmdConfigurationError) {
106
+ printQmdConfigError(err);
107
+ process.exit(1);
108
+ }
65
109
  console.error(chalk.red(`Error: ${err.message}`));
66
110
  process.exit(1);
67
111
  }
@@ -117,6 +161,10 @@ export function registerQueryCommands(
117
161
  printQmdMissing();
118
162
  process.exit(1);
119
163
  }
164
+ if (err instanceof QmdConfigurationError) {
165
+ printQmdConfigError(err);
166
+ process.exit(1);
167
+ }
120
168
  console.error(chalk.red(`Error: ${err.message}`));
121
169
  process.exit(1);
122
170
  }
@@ -163,6 +211,10 @@ export function registerQueryCommands(
163
211
  printQmdMissing();
164
212
  process.exit(1);
165
213
  }
214
+ if (err instanceof QmdConfigurationError) {
215
+ printQmdConfigError(err);
216
+ process.exit(1);
217
+ }
166
218
  console.error(chalk.red(`Error: ${err.message}`));
167
219
  process.exit(1);
168
220
  }