@tobilu/qmd 0.9.0 → 1.0.5
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/CHANGELOG.md +290 -22
- package/README.md +15 -6
- package/dist/collections.d.ts +115 -0
- package/dist/collections.js +282 -0
- package/dist/db.d.ts +33 -0
- package/dist/db.js +34 -0
- package/dist/formatter.d.ts +119 -0
- package/dist/formatter.js +350 -0
- package/dist/llm.d.ts +375 -0
- package/dist/llm.js +1036 -0
- package/dist/mcp.d.ts +21 -0
- package/dist/mcp.js +545 -0
- package/dist/qmd.d.ts +1 -0
- package/dist/qmd.js +2224 -0
- package/dist/store.d.ts +696 -0
- package/dist/store.js +2374 -0
- package/package.json +21 -16
- package/qmd +15 -24
- package/src/collections.ts +0 -390
- package/src/formatter.ts +0 -429
- package/src/llm.ts +0 -1208
- package/src/mcp.ts +0 -654
- package/src/qmd.ts +0 -2535
- package/src/store.ts +0 -3072
package/CHANGELOG.md
CHANGED
|
@@ -1,34 +1,302 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [1.0.5] - 2026-02-16
|
|
6
|
+
|
|
7
|
+
The npm package now ships compiled JavaScript instead of raw TypeScript,
|
|
8
|
+
removing the `tsx` runtime dependency. A new `/release` skill automates the
|
|
9
|
+
full release workflow with changelog validation and git hook enforcement.
|
|
10
|
+
|
|
11
|
+
### Changes
|
|
12
|
+
|
|
13
|
+
- Build: compile TypeScript to `dist/` via `tsc` so the npm package no longer
|
|
14
|
+
requires `tsx` at runtime. The `qmd` shell wrapper now runs `dist/qmd.js`
|
|
15
|
+
directly.
|
|
16
|
+
- Release tooling: new `/release` skill that manages the full release
|
|
17
|
+
lifecycle — validates changelog, installs git hooks, previews release notes,
|
|
18
|
+
and cuts the release. Auto-populates `[Unreleased]` from git history when
|
|
19
|
+
empty.
|
|
20
|
+
- Release tooling: `scripts/extract-changelog.sh` extracts cumulative notes
|
|
21
|
+
for the full minor series (e.g. 1.0.0 through 1.0.5) for GitHub releases.
|
|
22
|
+
Includes `[Unreleased]` content in previews.
|
|
23
|
+
- Release tooling: `scripts/release.sh` renames `[Unreleased]` to a versioned
|
|
24
|
+
heading and inserts a fresh empty `[Unreleased]` section automatically.
|
|
25
|
+
- Release tooling: pre-push git hook blocks `v*` tag pushes unless
|
|
26
|
+
`package.json` version matches the tag, a changelog entry exists, and CI
|
|
27
|
+
passed on GitHub.
|
|
28
|
+
- Publish workflow: GitHub Actions now builds TypeScript, creates a GitHub
|
|
29
|
+
release with cumulative notes extracted from the changelog, and publishes
|
|
30
|
+
to npm with provenance.
|
|
31
|
+
|
|
32
|
+
## [1.0.0] - 2026-02-15
|
|
33
|
+
|
|
34
|
+
QMD now runs on both Node.js and Bun, with up to 2.7x faster reranking
|
|
35
|
+
through parallel GPU contexts. GPU auto-detection replaces the unreliable
|
|
36
|
+
`gpu: "auto"` with explicit CUDA/Metal/Vulkan probing.
|
|
37
|
+
|
|
38
|
+
### Changes
|
|
39
|
+
|
|
40
|
+
- Runtime: support Node.js (>=22) alongside Bun via a cross-runtime SQLite
|
|
41
|
+
abstraction layer (`src/db.ts`). `bun:sqlite` on Bun, `better-sqlite3` on
|
|
42
|
+
Node. The `qmd` wrapper auto-detects a suitable Node.js install via PATH,
|
|
43
|
+
then falls back to mise, asdf, nvm, and Homebrew locations.
|
|
44
|
+
- Performance: parallel embedding & reranking via multiple LlamaContext
|
|
45
|
+
instances — up to 2.7x faster on multi-core machines.
|
|
46
|
+
- Performance: flash attention for ~20% less VRAM per reranking context,
|
|
47
|
+
enabling more parallel contexts on GPU.
|
|
48
|
+
- Performance: right-sized reranker context (40960 → 2048 tokens, 17x less
|
|
49
|
+
memory) since chunks are capped at ~900 tokens.
|
|
50
|
+
- Performance: adaptive parallelism — context count computed from available
|
|
51
|
+
VRAM (GPU) or CPU math cores rather than hardcoded.
|
|
52
|
+
- GPU: probe for CUDA, Metal, Vulkan explicitly at startup instead of
|
|
53
|
+
relying on node-llama-cpp's `gpu: "auto"`. `qmd status` shows device info.
|
|
54
|
+
- Tests: reorganized into flat `test/` directory with vitest for Node.js and
|
|
55
|
+
bun test for Bun. New `eval-bm25` and `store.helpers.unit` suites.
|
|
56
|
+
|
|
57
|
+
### Fixes
|
|
58
|
+
|
|
59
|
+
- Prevent VRAM waste from duplicate context creation during concurrent
|
|
60
|
+
`embedBatch` calls — initialization lock now covers the full path.
|
|
61
|
+
- Collection-aware FTS filtering so scoped keyword search actually restricts
|
|
62
|
+
results to the requested collection.
|
|
4
63
|
|
|
5
64
|
## [0.9.0] - 2026-02-15
|
|
6
65
|
|
|
7
|
-
|
|
66
|
+
First published release on npm as `@tobilu/qmd`. MCP HTTP transport with
|
|
67
|
+
daemon mode cuts warm query latency from ~16s to ~10s by keeping models
|
|
68
|
+
loaded between requests.
|
|
69
|
+
|
|
70
|
+
### Changes
|
|
71
|
+
|
|
72
|
+
- MCP: HTTP transport with daemon lifecycle — `qmd mcp --http --daemon`
|
|
73
|
+
starts a background server, `qmd mcp stop` shuts it down. Models stay warm
|
|
74
|
+
in VRAM between queries. #149 (thanks @igrigorik)
|
|
75
|
+
- Search: type-routed query expansion preserves lex/vec/hyde type info and
|
|
76
|
+
routes to the appropriate backend. Eliminates ~4 wasted backend calls per
|
|
77
|
+
query (10.0 → 6.0 calls, 1278ms → 549ms). #149 (thanks @igrigorik)
|
|
78
|
+
- Search: unified pipeline — extracted `hybridQuery()` and
|
|
79
|
+
`vectorSearchQuery()` to `store.ts` so CLI and MCP share identical logic.
|
|
80
|
+
Fixes a class of bugs where results differed between the two. #149 (thanks
|
|
81
|
+
@igrigorik)
|
|
82
|
+
- MCP: dynamic instructions generated at startup from actual index state —
|
|
83
|
+
LLMs see collection names, doc counts, and content descriptions. #149
|
|
84
|
+
(thanks @igrigorik)
|
|
85
|
+
- MCP: tool renames (vsearch → vector_search, query → deep_search) with
|
|
86
|
+
rewritten descriptions for better tool selection. #149 (thanks @igrigorik)
|
|
87
|
+
- Integration: Claude Code plugin with inline status checks and MCP
|
|
88
|
+
integration. #99 (thanks @galligan)
|
|
89
|
+
|
|
90
|
+
### Fixes
|
|
91
|
+
|
|
92
|
+
- BM25 score normalization — formula was inverted (`1/(1+|x|)` instead of
|
|
93
|
+
`|x|/(1+|x|)`), so strong matches scored *lowest*. Broke `--min-score`
|
|
94
|
+
filtering and made the "strong signal" short-circuit dead code. #76 (thanks
|
|
95
|
+
@dgilperez)
|
|
96
|
+
- Normalize Unicode paths to NFC for macOS compatibility. #82 (thanks
|
|
97
|
+
@c-stoeckl)
|
|
98
|
+
- Handle dense content (code) that tokenizes beyond expected chunk size.
|
|
99
|
+
- Proper cleanup of Metal GPU resources on process exit.
|
|
100
|
+
- SQLite-vec readiness verification after extension load.
|
|
101
|
+
- Reactivate deactivated documents on re-index instead of creating duplicates.
|
|
102
|
+
- Bun UTF-8 path corruption workaround for non-ASCII filenames.
|
|
103
|
+
- Disable following symlinks in glob.scan to avoid infinite loops.
|
|
104
|
+
|
|
105
|
+
## [0.8.0] - 2026-01-28
|
|
106
|
+
|
|
107
|
+
Fine-tuned query expansion model trained with GRPO replaces the stock Qwen3
|
|
108
|
+
0.6B. The training pipeline scores expansions on named entity preservation,
|
|
109
|
+
format compliance, and diversity — producing noticeably better lexical
|
|
110
|
+
variations and HyDE documents.
|
|
111
|
+
|
|
112
|
+
### Changes
|
|
113
|
+
|
|
114
|
+
- LLM: deploy GRPO-trained (Group Relative Policy Optimization) query
|
|
115
|
+
expansion model, hosted on HuggingFace and auto-downloaded on first use.
|
|
116
|
+
Better preservation of proper nouns and technical terms in expansions.
|
|
117
|
+
- LLM: `/only:lex` mode for single-type expansions — useful when you know
|
|
118
|
+
which search backend will help.
|
|
119
|
+
- LLM: HyDE output moved to first position so vector search can start
|
|
120
|
+
embedding while other expansions generate.
|
|
121
|
+
- LLM: session lifecycle management via `withLLMSession()` pattern — ensures
|
|
122
|
+
cleanup even on failure, similar to database transactions.
|
|
123
|
+
- Integration: org-mode title extraction support. #50 (thanks @sh54)
|
|
124
|
+
- Integration: SQLite extension loading in Nix devshell. #48 (thanks @sh54)
|
|
125
|
+
- Integration: AI agent discovery via skills.sh. #64 (thanks @Algiras)
|
|
126
|
+
|
|
127
|
+
### Fixes
|
|
128
|
+
|
|
129
|
+
- Use sequential embedding on CPU-only systems — parallel contexts caused a
|
|
130
|
+
race condition where contexts competed for CPU cores, making things slower.
|
|
131
|
+
#54 (thanks @freeman-jiang)
|
|
132
|
+
- Fix `collectionName` column in vector search SQL (was still using old
|
|
133
|
+
`collectionId` from before YAML migration). #61 (thanks @jdvmi00)
|
|
134
|
+
- Fix Qwen3 sampling params to prevent repetition loops — stock
|
|
135
|
+
temperature/top-p caused occasional infinite repeat patterns.
|
|
136
|
+
- Add `--index` option to CLI argument parser (was documented but not wired
|
|
137
|
+
up). #84 (thanks @Tritlo)
|
|
138
|
+
- Fix DisposedError during slow batch embedding. #41 (thanks @wuhup)
|
|
139
|
+
|
|
140
|
+
## [0.7.0] - 2026-01-09
|
|
8
141
|
|
|
9
|
-
|
|
142
|
+
First community contributions. The project gained external contributors,
|
|
143
|
+
surfacing bugs that only appear in diverse environments — Homebrew sqlite-vec
|
|
144
|
+
paths, case-sensitive model filenames, and sqlite-vec JOIN incompatibilities.
|
|
10
145
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- **Document IDs** — 6-char content hash for stable references across re-indexes
|
|
20
|
-
- **Multi-get** — retrieve multiple documents by glob pattern, comma list, or docids
|
|
21
|
-
- **Multiple output formats** — JSON, CSV, Markdown, XML, files list
|
|
22
|
-
- **Claude Code plugin** — inline status checks and MCP integration
|
|
146
|
+
### Changes
|
|
147
|
+
|
|
148
|
+
- Indexing: native `realpathSync()` replaces `readlink -f` subprocess spawn
|
|
149
|
+
per file. On a 5000-file collection this eliminates 5000 shell spawns,
|
|
150
|
+
~15% faster. #8 (thanks @burke)
|
|
151
|
+
- Indexing: single-pass tokenization — chunking algorithm tokenized each
|
|
152
|
+
document twice (count then split); now tokenizes once and reuses. #9
|
|
153
|
+
(thanks @burke)
|
|
23
154
|
|
|
24
155
|
### Fixes
|
|
25
156
|
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
157
|
+
- Fix `vsearch` and `query` hanging — sqlite-vec's virtual table doesn't
|
|
158
|
+
support the JOIN pattern used; rewrote to subquery. #23 (thanks @mbrendan)
|
|
159
|
+
- Fix MCP server exiting immediately after startup — process had no active
|
|
160
|
+
handles keeping the event loop alive. #29 (thanks @mostlydev)
|
|
161
|
+
- Fix collection filter SQL to properly restrict vector search results.
|
|
162
|
+
- Support non-ASCII filenames in collection filter.
|
|
163
|
+
- Skip empty files during indexing instead of crashing on zero-length content.
|
|
164
|
+
- Fix case sensitivity in Qwen3 model filename resolution. #15 (thanks
|
|
165
|
+
@gavrix)
|
|
166
|
+
- Fix sqlite-vec loading on macOS with Homebrew (`BREW_PREFIX` detection).
|
|
167
|
+
#42 (thanks @komsit37)
|
|
168
|
+
- Fix Nix flake to use correct `src/qmd.ts` path. #7 (thanks @burke)
|
|
169
|
+
- Fix docid lookup with quotes support in get command. #36 (thanks
|
|
170
|
+
@JoshuaLelon)
|
|
171
|
+
- Fix query expansion model size in documentation. #38 (thanks @odysseus0)
|
|
172
|
+
|
|
173
|
+
## [0.6.0] - 2025-12-28
|
|
174
|
+
|
|
175
|
+
Replaced Ollama HTTP API with node-llama-cpp for all LLM operations. Ollama
|
|
176
|
+
adds convenience but also a running server dependency. node-llama-cpp loads
|
|
177
|
+
GGUF models directly in-process — zero external dependencies. Models
|
|
178
|
+
auto-download from HuggingFace on first use.
|
|
179
|
+
|
|
180
|
+
### Changes
|
|
181
|
+
|
|
182
|
+
- LLM: structured query expansion via JSON schema grammar constraints.
|
|
183
|
+
Model produces typed expansions — **lexical** (BM25 keywords), **vector**
|
|
184
|
+
(semantic rephrasings), **HyDE** (hypothetical document excerpts) — so each
|
|
185
|
+
routes to the right backend instead of sending everything everywhere.
|
|
186
|
+
- LLM: lazy model loading with 2-minute inactivity auto-unload. Keeps memory
|
|
187
|
+
low when idle while avoiding ~3s model load on every query.
|
|
188
|
+
- Search: conditional query expansion — when BM25 returns strong results, the
|
|
189
|
+
expensive LLM expansion is skipped entirely.
|
|
190
|
+
- Search: multi-chunk reranking — documents with multiple relevant chunks
|
|
191
|
+
scored by aggregating across all chunks rather than best single chunk.
|
|
192
|
+
- Search: cosine distance for vector search (was L2).
|
|
193
|
+
- Search: embeddinggemma nomic-style prompt formatting.
|
|
194
|
+
- Testing: evaluation harness with synthetic test documents and Hit@K metrics
|
|
195
|
+
for BM25, vector, and hybrid RRF.
|
|
196
|
+
|
|
197
|
+
## [0.5.0] - 2025-12-13
|
|
198
|
+
|
|
199
|
+
Collections and contexts moved from SQLite tables to YAML at
|
|
200
|
+
`~/.config/qmd/index.yml`. SQLite was overkill for config — you can't share
|
|
201
|
+
it, and it's opaque. YAML is human-readable and version-controllable. The
|
|
202
|
+
migration was extensive (35+ commits) because every part of the system that
|
|
203
|
+
touched collections or contexts had to be updated.
|
|
204
|
+
|
|
205
|
+
### Changes
|
|
206
|
+
|
|
207
|
+
- Config: YAML-based collections and contexts replace SQLite tables.
|
|
208
|
+
`collections` and `path_contexts` tables dropped from schema. Collections
|
|
209
|
+
support an optional `update:` command (e.g., `git pull`) before re-index.
|
|
210
|
+
- CLI: `qmd collection add/list/remove/rename` commands with `--name` and
|
|
211
|
+
`--mask` glob pattern support.
|
|
212
|
+
- CLI: `qmd ls` virtual file tree — list collections, files in a collection,
|
|
213
|
+
or files under a path prefix.
|
|
214
|
+
- CLI: `qmd context add/list/check/rm` with hierarchical context inheritance.
|
|
215
|
+
A query to `qmd://notes/2024/jan/` inherits context from `notes/`,
|
|
216
|
+
`notes/2024/`, and `notes/2024/jan/`.
|
|
217
|
+
- CLI: `qmd context add / "text"` for global context across all collections.
|
|
218
|
+
- CLI: `qmd context check` audit command to find paths without context.
|
|
219
|
+
- Paths: `qmd://` virtual URI scheme for portable document references.
|
|
220
|
+
`qmd://notes/ideas.md` works regardless of where the collection lives on
|
|
221
|
+
disk. Works in `get`, `multi-get`, `ls`, and context commands.
|
|
222
|
+
- CLI: document IDs (docid) — first 6 chars of content hash for stable
|
|
223
|
+
references. Shown as `#abc123` in search results, usable with `get` and
|
|
224
|
+
`multi-get`.
|
|
225
|
+
- CLI: `--line-numbers` flag for get command output.
|
|
226
|
+
|
|
227
|
+
## [0.4.0] - 2025-12-10
|
|
228
|
+
|
|
229
|
+
MCP server for AI agent integration. Without it, agents had to shell out to
|
|
230
|
+
`qmd search` and parse CLI output. The monolithic `qmd.ts` (1840 lines) was
|
|
231
|
+
split into focused modules with the project's first test suite (215 tests).
|
|
232
|
+
|
|
233
|
+
### Changes
|
|
234
|
+
|
|
235
|
+
- MCP: stdio server with tools for search, vector search, hybrid query,
|
|
236
|
+
document retrieval, and status. Runs over stdio transport for Claude
|
|
237
|
+
Desktop and MCP clients.
|
|
238
|
+
- MCP: spec-compliant with June 2025 MCP specification — removed non-spec
|
|
239
|
+
`mimeType`, added `isError: true` to errors, `structuredContent` for
|
|
240
|
+
machine-readable results, proper URI encoding.
|
|
241
|
+
- MCP: simplified tool naming (`qmd_search` → `search`) since MCP already
|
|
242
|
+
namespaces by server.
|
|
243
|
+
- Architecture: extract `store.ts` (1221 LOC), `llm.ts` (539 LOC),
|
|
244
|
+
`formatter.ts` (359 LOC), `mcp.ts` (503 LOC) from monolithic `qmd.ts`.
|
|
245
|
+
- Testing: 215 tests (store: 96, llm: 60, mcp: 59) with mocked Ollama for
|
|
246
|
+
fast, deterministic runs. Before this: zero tests.
|
|
247
|
+
|
|
248
|
+
## [0.3.0] - 2025-12-08
|
|
249
|
+
|
|
250
|
+
Document chunking for vector search. A 5000-word document about many topics
|
|
251
|
+
gets a single embedding that averages everything together, matching poorly for
|
|
252
|
+
specific queries. Chunking produces one embedding per ~900-token section with
|
|
253
|
+
focused semantic signal.
|
|
254
|
+
|
|
255
|
+
### Changes
|
|
256
|
+
|
|
257
|
+
- Search: markdown-aware chunking — prefers heading boundaries, then paragraph
|
|
258
|
+
breaks, then sentence boundaries. 15% overlap between chunks ensures
|
|
259
|
+
cross-boundary queries still match.
|
|
260
|
+
- Search: multi-chunk scoring bonus (+0.02 per additional chunk, capped at
|
|
261
|
+
+0.1 for 5+ chunks). Documents relevant in multiple sections rank higher.
|
|
262
|
+
- CLI: display paths show collection-relative paths and extracted titles
|
|
263
|
+
(from H1 headings or YAML frontmatter) instead of raw filesystem paths.
|
|
264
|
+
- CLI: `--all` flag returns all matches (use with `--min-score` to filter).
|
|
265
|
+
- CLI: byte-based progress bar with ETA for `embed` command.
|
|
266
|
+
- CLI: human-readable time formatting ("15m 4s" instead of "904.2s").
|
|
267
|
+
- CLI: documents >64KB truncated with warning during embedding.
|
|
268
|
+
|
|
269
|
+
## [0.2.0] - 2025-12-08
|
|
270
|
+
|
|
271
|
+
### Changes
|
|
272
|
+
|
|
273
|
+
- CLI: `--json`, `--csv`, `--files`, `--md`, `--xml` output format flags.
|
|
274
|
+
`--json` for programmatic access, `--files` for piping, `--md`/`--xml` for
|
|
275
|
+
LLM consumption, `--csv` for spreadsheets.
|
|
276
|
+
- CLI: `qmd status` shows index health — document count, size, embedding
|
|
277
|
+
coverage, time since last update.
|
|
278
|
+
- Search: weighted RRF — original query gets 2x weight relative to expanded
|
|
279
|
+
queries since the user's actual words are a more reliable signal.
|
|
280
|
+
|
|
281
|
+
## [0.1.0] - 2025-12-07
|
|
282
|
+
|
|
283
|
+
Initial implementation. Built in a single day for searching personal markdown
|
|
284
|
+
notes, journals, and meeting transcripts.
|
|
285
|
+
|
|
286
|
+
### Changes
|
|
287
|
+
|
|
288
|
+
- Search: SQLite FTS5 with BM25 ranking. Chose SQLite over Elasticsearch
|
|
289
|
+
because QMD is a personal tool — single binary, no server dependencies.
|
|
290
|
+
- Search: sqlite-vec for vector similarity. Same rationale: in-process, no
|
|
291
|
+
external vector database.
|
|
292
|
+
- Search: Reciprocal Rank Fusion to combine BM25 and vector results. RRF is
|
|
293
|
+
parameter-free and handles missing signals gracefully.
|
|
294
|
+
- LLM: Ollama for embeddings, reranking, and query expansion. Later replaced
|
|
295
|
+
with node-llama-cpp in 0.6.0.
|
|
296
|
+
- CLI: `qmd add`, `qmd embed`, `qmd search`, `qmd vsearch`, `qmd query`,
|
|
297
|
+
`qmd get`. ~1800 lines of TypeScript in a single `qmd.ts` file.
|
|
32
298
|
|
|
33
|
-
[
|
|
299
|
+
[Unreleased]: https://github.com/tobi/qmd/compare/v1.0.0...HEAD
|
|
300
|
+
[1.0.0]: https://github.com/tobi/qmd/releases/tag/v1.0.0
|
|
301
|
+
[0.9.0]: https://github.com/tobi/qmd/compare/v0.8.0...v0.9.0
|
|
34
302
|
|
package/README.md
CHANGED
|
@@ -6,18 +6,26 @@ QMD combines BM25 full-text search, vector semantic search, and LLM re-ranking
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
You can read more about QMD's progress in the [CHANGELOG](CHANGELOG.md).
|
|
10
|
+
|
|
9
11
|
## Quick Start
|
|
10
12
|
|
|
11
13
|
```sh
|
|
12
|
-
# Install globally
|
|
14
|
+
# Install globally (Node or Bun)
|
|
15
|
+
npm install -g @tobilu/qmd
|
|
16
|
+
# or
|
|
13
17
|
bun install -g @tobilu/qmd
|
|
14
18
|
|
|
19
|
+
# Or run directly
|
|
20
|
+
npx @tobilu/qmd ...
|
|
21
|
+
bunx @tobilu/qmd ...
|
|
22
|
+
|
|
15
23
|
# Create collections for your notes, docs, and meeting transcripts
|
|
16
24
|
qmd collection add ~/notes --name notes
|
|
17
25
|
qmd collection add ~/Documents/meetings --name meetings
|
|
18
26
|
qmd collection add ~/work/docs --name docs
|
|
19
27
|
|
|
20
|
-
# Add context to help with search results
|
|
28
|
+
# Add context to help with search results, each piece of context will be returned when matching sub documents are returned. This works as a tree. This is the key feature of QMD as it allows LLMs to make much better contextual choices when selecting documents. Don't sleep on it!
|
|
21
29
|
qmd context add qmd://notes "Personal notes and ideas"
|
|
22
30
|
qmd context add qmd://meetings "Meeting transcripts and notes"
|
|
23
31
|
qmd context add qmd://docs "Work documentation"
|
|
@@ -231,6 +239,7 @@ The `query` command uses **Reciprocal Rank Fusion (RRF)** with position-aware bl
|
|
|
231
239
|
|
|
232
240
|
### System Requirements
|
|
233
241
|
|
|
242
|
+
- **Node.js** >= 22
|
|
234
243
|
- **Bun** >= 1.0.0
|
|
235
244
|
- **macOS**: Homebrew SQLite (for extension support)
|
|
236
245
|
```sh
|
|
@@ -252,18 +261,18 @@ Models are downloaded from HuggingFace and cached in `~/.cache/qmd/models/`.
|
|
|
252
261
|
## Installation
|
|
253
262
|
|
|
254
263
|
```sh
|
|
264
|
+
npm install -g @tobilu/qmd
|
|
265
|
+
# or
|
|
255
266
|
bun install -g @tobilu/qmd
|
|
256
267
|
```
|
|
257
268
|
|
|
258
|
-
Make sure `~/.bun/bin` is in your PATH.
|
|
259
|
-
|
|
260
269
|
### Development
|
|
261
270
|
|
|
262
271
|
```sh
|
|
263
272
|
git clone https://github.com/tobi/qmd
|
|
264
273
|
cd qmd
|
|
265
|
-
|
|
266
|
-
|
|
274
|
+
npm install
|
|
275
|
+
npm link
|
|
267
276
|
```
|
|
268
277
|
|
|
269
278
|
## Usage
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collections configuration management
|
|
3
|
+
*
|
|
4
|
+
* This module manages the YAML-based collection configuration at ~/.config/qmd/index.yml.
|
|
5
|
+
* Collections define which directories to index and their associated contexts.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Context definitions for a collection
|
|
9
|
+
* Key is path prefix (e.g., "/", "/2024", "/Board of Directors")
|
|
10
|
+
* Value is the context description
|
|
11
|
+
*/
|
|
12
|
+
export type ContextMap = Record<string, string>;
|
|
13
|
+
/**
|
|
14
|
+
* A single collection configuration
|
|
15
|
+
*/
|
|
16
|
+
export interface Collection {
|
|
17
|
+
path: string;
|
|
18
|
+
pattern: string;
|
|
19
|
+
context?: ContextMap;
|
|
20
|
+
update?: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The complete configuration file structure
|
|
24
|
+
*/
|
|
25
|
+
export interface CollectionConfig {
|
|
26
|
+
global_context?: string;
|
|
27
|
+
collections: Record<string, Collection>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Collection with its name (for return values)
|
|
31
|
+
*/
|
|
32
|
+
export interface NamedCollection extends Collection {
|
|
33
|
+
name: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Set the current index name for config file lookup
|
|
37
|
+
* Config file will be ~/.config/qmd/{indexName}.yml
|
|
38
|
+
*/
|
|
39
|
+
export declare function setConfigIndexName(name: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Load configuration from ~/.config/qmd/index.yml
|
|
42
|
+
* Returns empty config if file doesn't exist
|
|
43
|
+
*/
|
|
44
|
+
export declare function loadConfig(): CollectionConfig;
|
|
45
|
+
/**
|
|
46
|
+
* Save configuration to ~/.config/qmd/index.yml
|
|
47
|
+
*/
|
|
48
|
+
export declare function saveConfig(config: CollectionConfig): void;
|
|
49
|
+
/**
|
|
50
|
+
* Get a specific collection by name
|
|
51
|
+
* Returns null if not found
|
|
52
|
+
*/
|
|
53
|
+
export declare function getCollection(name: string): NamedCollection | null;
|
|
54
|
+
/**
|
|
55
|
+
* List all collections
|
|
56
|
+
*/
|
|
57
|
+
export declare function listCollections(): NamedCollection[];
|
|
58
|
+
/**
|
|
59
|
+
* Add or update a collection
|
|
60
|
+
*/
|
|
61
|
+
export declare function addCollection(name: string, path: string, pattern?: string): void;
|
|
62
|
+
/**
|
|
63
|
+
* Remove a collection
|
|
64
|
+
*/
|
|
65
|
+
export declare function removeCollection(name: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Rename a collection
|
|
68
|
+
*/
|
|
69
|
+
export declare function renameCollection(oldName: string, newName: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get global context
|
|
72
|
+
*/
|
|
73
|
+
export declare function getGlobalContext(): string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Set global context
|
|
76
|
+
*/
|
|
77
|
+
export declare function setGlobalContext(context: string | undefined): void;
|
|
78
|
+
/**
|
|
79
|
+
* Get all contexts for a collection
|
|
80
|
+
*/
|
|
81
|
+
export declare function getContexts(collectionName: string): ContextMap | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Add or update a context for a specific path in a collection
|
|
84
|
+
*/
|
|
85
|
+
export declare function addContext(collectionName: string, pathPrefix: string, contextText: string): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Remove a context from a collection
|
|
88
|
+
*/
|
|
89
|
+
export declare function removeContext(collectionName: string, pathPrefix: string): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* List all contexts across all collections
|
|
92
|
+
*/
|
|
93
|
+
export declare function listAllContexts(): Array<{
|
|
94
|
+
collection: string;
|
|
95
|
+
path: string;
|
|
96
|
+
context: string;
|
|
97
|
+
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Find best matching context for a given collection and path
|
|
100
|
+
* Returns the most specific matching context (longest path prefix match)
|
|
101
|
+
*/
|
|
102
|
+
export declare function findContextForPath(collectionName: string, filePath: string): string | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Get the config file path (useful for error messages)
|
|
105
|
+
*/
|
|
106
|
+
export declare function getConfigPath(): string;
|
|
107
|
+
/**
|
|
108
|
+
* Check if config file exists
|
|
109
|
+
*/
|
|
110
|
+
export declare function configExists(): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Validate a collection name
|
|
113
|
+
* Collection names must be valid and not contain special characters
|
|
114
|
+
*/
|
|
115
|
+
export declare function isValidCollectionName(name: string): boolean;
|