Releases: NBibikov/cogvault
Release list
0.11.3 — 2026-10-06 — agents check memory first, and get the whole card
- Fix: a summary hit hid the card. Since 0.11.0 a card's
name — descriptionis
indexed as its own chunk, and when that chunk ranked best, recall returned only that
line. Recording the demo exposed it: the agent found the right card and still answered
without the fix, because the fix was in the body. A summary hit now returns the whole
card when it is short (≤2000 chars, frontmatter dropped), else the summary plus the
card's best body chunk. Ranking is unchanged, so the benchmark numbers stand. - MCP
instructions. The server now sends instructions withinitialize, which
Claude Code puts in the system prompt: recall before investigating a bug, a how-to
(run / test / deploy / configure), where something lives, or a past decision; record
decisions and fixes after. Tool descriptions alone were not enough — clients may defer
MCP tool schemas, and in testing the model answered "how do I run the API tests?" by
grepping an empty repo while the answer sat in memory. With the change, on four
questions whose answers live in memory, the agent called recall in 9 of 11 runs. cogvault_recalldescription and the plugin'smemoryskill now name the concrete
triggers (bugs, errors, restart loops, "how do we…", "where is…", "what did we decide…").- The full re-embed warning names the backend when that is what changed, instead of the
confusing "MiniLM/384 → MiniLM/384". - Plugin: the
doctorskill is gone — it ran the CLI through the shell, outside the MCP
server. The health check stays a CLI command (uvx cogvault doctor).
0.11.2 — 2026-10-05 — Claude Code plugin
- Claude Code plugin. The repo is a plugin marketplace:
/plugin marketplace add NBibikov/cogvault,/plugin install cogvault@cogvault.
It runs the MCP server throughuvx(tenant~/.cogvault/memory, override with
COGVAULT_TENANT) and ships amemoryskill (when to recall, what to record),
/cogvault:rememberand/cogvault:doctor. - Fix:
cogvault_recordwith a~tenant path. MCP clients start the server
without a shell, so--tenant ~/memoryarrived unexpanded: recall worked, but
record wrote to the literal path and failed. The server now writes to the
vault's resolved directory. - README: 30-second start (plugin, one-line MCP, JSON for Desktop/Cursor, pointing
at Claude Code's auto-memory) and an illustrative session figure.
0.11.1 — 2026-10-05 — on PyPI and the MCP Registry
- Published to PyPI (
pip install cogvault,uvx cogvault mcp --tenant DIR) and
listed in the official MCP Registry asio.github.NBibikov/cogvault(server.json). - Releases are built, tested and published by
.github/workflows/publish.ymlon a
v*tag: PyPI via trusted publishing (no stored token), the registry via GitHub OIDC. - README images and links are absolute, so the PyPI project page renders them.
- No code changes.
0.11.0 — token-window chunks, real-query eval, repair
First release since 0.6.0. Covers 0.7.0 → 0.11.0; full detail in CHANGELOG.md.
Highlights
The vector channel was blind to most of memory (0.10). paraphrase-multilingual-MiniLM truncates input at 128 tokens, while chunks were packed to 1500 characters. On real multilingual tenants 91–94% of chunks exceeded the window, so only ~35% of stored text ever reached the vector channel. Chunks are now fitted to the model's token window (lines → sentences → words), and an index stamp triggers one automatic rebuild.
multilingual-e5-small support. Same 384 dimensions, a 512-token window, automatic query:/passage: prefixes for the e5 family.
Judged on real queries, not just synthetic ones (0.11). New cogvault eval scores recall against a per-tenant set of real queries (<tenant>/.cogvault-golden.jsonl). On 65 judged real queries the large synthetic gain measured for 0.10 did not reproduce — all configurations landed within noise — so the release says so plainly. What did help: indexing each card's name — description as its own chunk (hit@5 0.877 → 0.923).
Keeping tenants healthy.
cogvault doctor— untyped cards, legacy filenames, nested frontmatter, duplicate slugs, links to nothing. No longer flags links inside code, external paths, or deliberately unindexed targets.cogvault repair— fixes the mechanical half (dry run by default,--applyto write), rewrites references to renamed cards, and preserves mtime so temporal decay is not reset.[[links]]resolve by frontmattername:, filename, either separator style, and with or without the card-type prefix.
Operations.
- Older processes never rebuild an index written by a newer cogvault (long-lived MCP servers used to revert upgrades).
- The MCP server warms its index in the background, so a rebuild never blocks
initialize. - Per-tenant
.cogvault.toml(model and options travel with the data); embedding-backend drift detection; pinned model cache. - One result per card; temporal decay from the file's live age;
coldlatency flag in the query log. - Write path hardened: no crash on unclosed frontmatter, no path escape via
name:, exclusive create for cards.
Upgrading
Indexes rebuild automatically on first cogvault index (embeddings are cached, so a same-model rebuild is cheap). Restart long-running cogvault mcp servers after upgrading.
Install
uv tool install git+https://github.com/NBibikov/cogvault@v0.11.0or install the attached wheel. Not published on PyPI.
0.6.0 — folder-tree / Obsidian indexing
0.6.0 — index folder trees (Obsidian vaults & knowledge bases)
A tenant can now be a nested vault, not just a flat directory of .md files. All new options are opt-in; flat agent-memory tenants are unaffected.
What's new
--recursive— walk subdirectories. Files are keyed by their path relative to the tenant, so two notes namedTasks.mdin different folders never collide.--strip-frontmatter— drop a leading YAML--- … ---block before chunking, so frontmatter keys don't pollute the embedding.--ignore GLOB(repeatable) — skip paths relative to the tenant root (e.g..obsidian/*,Templates/*). The recursive walk also prunes dotfile directories.
Available on index, search, and mcp, and as Config(recursive=…, strip_frontmatter=…, ignore_globs=…) in the library.
cogvault index --tenant ~/vault --recursive --strip-frontmatter \
--ignore ".obsidian/*" --ignore "Templates/*"Validated at scale
A real ~3,500-note Obsidian vault → 9,544 chunks, first (cold) index ≈ 216 s, then warm recall in 9–10 ms with on-point top hits across diverse queries. Indexing stays incremental — later passes only re-embed changed files.
26/26 tests pass (5 new).
0.5.0 — atomic guard+rebuild & resilient search
0.5.0 — atomic guard+rebuild & resilient search (fleet concurrency fix)
Hardens the index lifecycle against the failure mode where recall could return SQLite "database disk image is malformed" after a model switch or an interrupted reindex.
Root cause
A model/dim-mismatch wipe was committed in _connect()'s own transaction, then the separate re-embed reindex ran later. If the process was killed between those two commits, the index was left with an empty chunks table and inconsistent vec0 shadow tables — which the next search() tripped over. PRAGMA integrity_check still reported ok (the core B-trees were sound); the corruption was internal to the sqlite-vec virtual table.
Fixes
- Atomic guard + rebuild. The mismatch-wipe now happens inside
reindex()'sBEGIN IMMEDIATEtransaction, so wipe and rebuild are one atomic unit. A kill mid-rebuild rolls back to the previous model's index instead of corrupting it. (Uses per-statementexecute()rather thanexecutescript(), which would force an implicit COMMIT and break the atomic transaction.) - Resilient search.
search()now catchessqlite3.DatabaseError, returns an empty result, and fires a single background full reindex to self-heal — it never propagates the error to the caller and never reindexes inline (heavy embedding work under concurrent agent load would be a DoS)._searchwraps its connection intry/finallyso a corrupt index can't leak connections.
Tests
Two new regression tests — corrupt-index resilience and atomic-rebuild rollback. 21/21 pass.