Skip to content

Releases: NBibikov/cogvault

0.11.3 — 2026-10-06 — agents check memory first, and get the whole card

Choose a tag to compare

@github-actions github-actions released this 05 Oct 22:23
  • Fix: a summary hit hid the card. Since 0.11.0 a card's name — description is
    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 with initialize, 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_recall description and the plugin's memory skill 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 doctor skill 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

Choose a tag to compare

@github-actions github-actions released this 05 Oct 17:42
  • Claude Code plugin. The repo is a plugin marketplace:
    /plugin marketplace add NBibikov/cogvault, /plugin install cogvault@cogvault.
    It runs the MCP server through uvx (tenant ~/.cogvault/memory, override with
    COGVAULT_TENANT) and ships a memory skill (when to recall, what to record),
    /cogvault:remember and /cogvault:doctor.
  • Fix: cogvault_record with a ~ tenant path. MCP clients start the server
    without a shell, so --tenant ~/memory arrived 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

Choose a tag to compare

@github-actions github-actions released this 05 Oct 17:19
  • Published to PyPI (pip install cogvault, uvx cogvault mcp --tenant DIR) and
    listed in the official MCP Registry as io.github.NBibikov/cogvault (server.json).
  • Releases are built, tested and published by .github/workflows/publish.yml on 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

Choose a tag to compare

@NBibikov NBibikov released this 05 Oct 11:46

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, --apply to write), rewrites references to renamed cards, and preserves mtime so temporal decay is not reset.
  • [[links]] resolve by frontmatter name:, 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; cold latency 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.0

or install the attached wheel. Not published on PyPI.

0.6.0 — folder-tree / Obsidian indexing

Choose a tag to compare

@NBibikov NBibikov released this 28 Jun 05:19

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 named Tasks.md in 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

Choose a tag to compare

@NBibikov NBibikov released this 28 Jun 04:46

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()'s BEGIN IMMEDIATE transaction, 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-statement execute() rather than executescript(), which would force an implicit COMMIT and break the atomic transaction.)
  • Resilient search. search() now catches sqlite3.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). _search wraps its connection in try/finally so a corrupt index can't leak connections.

Tests

Two new regression tests — corrupt-index resilience and atomic-rebuild rollback. 21/21 pass.