Roadmap¶
What's shipped, what's next, what we've deliberately scoped out. Revised on each release.
Last updated: 2026-04-22 (v1.5.0 + plugin v1.5.0 shipped.)
Versioning policy¶
Plugin and server ship aligned at major.minor — when server goes X.Y.0, plugin goes X.Y.0 the same day (even if the plugin has no code changes, as a "version alignment" release with a CHANGELOG note). Patch versions may drift. The capabilities[] array in discovery.json remains the actual compatibility handshake; version numbers are a signal to users that "plugin 1.4.x works with server 1.4.x". The plugin jumps 0.2.1 → 1.4.0 in v1.4.0 to establish the alignment baseline.
Shipped¶
| Release | Scope | Paired plugin |
|---|---|---|
| v1.0.0 | Core: semantic search + knowledge graph + vault editing over stdio MCP | — |
| v1.1.x | Live file watcher (chokidar) replaces scheduled reindex; offline-catchup on boot | — |
| v1.2.0 | active_note via companion plugin (first plugin-dependent tool) |
0.1.0 |
| v1.2.1 | Defensive hardening — per-tool timeout, SQLite WAL busy_timeout = 5000, embedder request serialisation |
0.1.0 |
| v1.2.2 | Theme-cache correctness, patch_heading scope: 'body', valueJson for stringifying harnesses |
0.1.0 |
| v1.3.0 | dataview_query + capability gating via plugin discovery |
0.2.0 |
| v1.3.1 | Discriminated Dataview 424 responses (not-installed / not-enabled / api-not-ready) + doc-currency fixes | 0.2.1 |
| v1.4.0 | Retrieval-quality foundation (chunks + hybrid RRF + configurable embedder) + Bases via Path B + P0/P1 correctness fixes | 1.4.0 |
| v1.5.0 | Ollama embedder + task-type prefix factory, next_actions envelope + hints for search/read_note/find_connections, L1 move_note inbound link rewriting, H2/H4 disambiguation + includeStubs, I graph-analytics credibility guards (PageRank min-incoming, Louvain modularity warning, betweenness normalisation), slim npm tarball (drop docs from files) |
1.5.0 |
Next up¶
v1.5.0 — agent UX + Ollama + polish (shipped)¶
Pairs with plugin v1.4.0 (version alignment jump from 0.2.1). Three pillars:
A — correctness fixes from field-test feedback (P0/P1):
- delete_note invalidates the theme cache (regenerates cluster summary from the live member list on write); detect_themes also lazy-filters + regenerates on read as belt-and-braces.
- reindex({}) default resolution: 1.0 so the bare call does what the description promises.
- patch_heading returns removedLen / linesConsumed so callers can detect greedy trailing-heading consumption; body-scope no longer produces a double blank line.
- Doc-note that create_note / move_note auto-inject title: frontmatter.
B — retrieval foundation:
- Chunk-level embedding. New chunks + chunks_vec tables. Heading-aware recursive chunker that preserves code + LaTeX blocks. SHA-256 content-hash dedup means unchanged chunks don't re-embed. Search returns one row per note by default (best chunk's score wins) with opt-in unique: 'chunks' for chunk-level inspection.
- Hybrid RRF search as default. mode: 'hybrid' | 'semantic' | 'fulltext' — default hybrid runs both semantic and full-text, fuses via Reciprocal Rank Fusion. Clients call search({query}) with no mode param; semantic + fulltext remain explicit escape hatches.
- FTS5 polish. Porter stemming via tokenize='porter unicode61'; BM25 column-weighted bm25(nodes_fts, 5.0, 1.0) (5× title vs body).
- Configurable + pluggable embedder. New Embedder interface. TransformersEmbedder default (reads EMBEDDING_MODEL env). index_metadata table stores model + dim; switching model auto-reindexes on next boot. Recommendation table in README for MiniLM / bge-small / bge-base / multilingual.
C — Obsidian Bases integration:
- Plugin /base route + resolveBases() discriminated union (not_enabled / unsupported_obsidian_version). Appends "base" to capabilities.
- Server-side base_query MCP tool — new tool surface (tool count 15 → 16).
- Path B implementation (own YAML parser + expression evaluator) — Obsidian's public API still has no read-access surface as of 1.12.7 (forum request open since 2026-01-31, unacknowledged). Public BasesQueryResult types are stable since 1.10, so a future Path A swap-in is drop-in.
- v1.4.0 supported subset: tree ops (and/or/not nested), comparisons, leaf boolean, file props (file.name/path/folder/ext/size/mtime/ctime/tags), file.hasTag/file.inFolder, frontmatter dot-access.
- Rejected with clear "unsupported construct" errors: arithmetic, method calls, function calls, regex literals, formulas:, summaries:, this. These are staged:
- v1.4.1 — arithmetic + date arithmetic + method calls.
- v1.4.2 — formulas.
- v1.4.3 — summaries.
Effort: ~12–18 h focused. Risk: medium — Path B evaluator has semantic-drift risk vs. Obsidian's evaluator (mitigated by fixture-driven tests against real .base files in a tiny vault).
v1.5.0 — agent UX + Ollama + deferred polish¶
Pairs with plugin v1.5.0 (version-alignment release; no plugin code changes). No new MCP tools — tool count stays at 16.
- Ollama embedding provider via the v1.4
Embedderinterface.EMBEDDING_PROVIDER=ollama+EMBEDDING_MODEL=nomic-embed-text(etc.). Task-type prefixes for asymmetric models (nomic / qwen / mxbai) are applied automatically — the single detail most third-party integrations get wrong and it costs ~10-20% retrieval quality. next_actionsstate hints in tool responses (opt-in per tool). Shared{data, context: {state, next_actions}}envelope atsrc/tools/register.ts. Five tools get hints day-one:search(top hit →read_note),read_note(unresolved links →create_note),find_connections(many connections →detect_themes),detect_themes(per cluster →rank_notes),delete_note(orphan check). Additive — clients ignoring the field keep working unchanged.- Deferred UX (L1/L3/L4/L5) from prior feedback:
- L1:
move_noterewrites inbound[[wiki-links]]across the vault after rename. Response reportslinksRewritten: {files, occurrences}. - L3:
patch_headingon multi-match raises a clear error listing each occurrence + line number;headingIndex?: numberto disambiguate explicitly. - L4:
read_notereturnstruncated: truewhenmaxContentLengthcuts the body. - L5:
includeStubs?: boolean(default true) ondetect_themes+rank_notes(matcheslist_notes). - Graph analytics credibility guards.
rank_notes(pagerank)excludes nodes with< 2incoming links by default (tunable).detect_themesaddswarningto the response when Louvain modularity is< 0.3.rank_notes(bridging)normalizes betweenness byn*(n-1)/2so values compare across vault sizes.
Explicitly deferred from v1.5.0 (earn their own milestones — see v1.6.0):
- L2 — dryRun?: boolean on write tools. Needs its own design pass on diff format + preview/apply split.
- L6 — bulk edit_note tuple array with atomic rollback. Heavy + high-value.
Effort: ~8–12 h focused. Risk: low — additive UX + a single new provider behind an existing interface.
Future milestones¶
v1.6.0 — agentic-writes safety bundle (~2 weeks)¶
Pairs with plugin v1.6.0 (version alignment, no plugin code changes expected).
dryRun: trueon write tools (edit_note,move_note,delete_note,link_notes). Returns the proposed diff without committing. Unified-diff string per file; preview-ID handed back for a separateapply_edit_preview(previewId)commit. L2 from feedback.- Bulk
edit_note— tuple array, atomic rollback via SQLite savepoint + filesystem journal. L6 from feedback. - Fuzzy matching on window edits.
fuzzy_threshold: 0.9param; Levenshtein match when exact fails. Typo-tolerant edit targets. - Content buffer for failed edits. Session-keyed;
edit_note(from_buffer: true)retrieves and retries. Prevents "Claude wrote 500 tokens, edit failed, has to rewrite everything."
v1.7.0 — block-ref editing + FTS5 frontmatter + topic-aware PageRank (~1-2 weeks)¶
Pairs with plugin v1.7.0.
edit_note(mode: 'patch_block', block_id: '^abc123'). Parse^[a-zA-Z0-9-]+$at line end into a newblock_refs(id, node_id, start_line, end_line)table; boundary is text from ID back to previous blank line or previous block ID. Meaningful Obsidian-power-user gap (lstpsche ships it, we don't). Adds one tool — count becomes 17.- FTS5 frontmatter fielding. Tokenize frontmatter alongside title + body as a fielded index, moderate 2× boost. Complements v1.4.0's stemming + column-weighted BM25.
find_influential_notes_about(topic). The tool only obsidian-brain can ship because only it co-locates both signals: semantic neighborhood → induced subgraph → PageRank on the subgraph. Replaces the noisy full-vault PageRank for topic-aware "what are the hubs here". One new tool — count becomes 18.
v1.8.0 — graph analytics credibility writeup (~1 week)¶
Pairs with plugin v1.8.0 (alignment, no plugin code changes).
- Evaluation on a real vault. Publish top-10 PageRank results on the author's actual vault, manual hit-rate assessment, write up the methodology. Per the competitive-analysis critique: an honest 60% hit rate is more credible than silence.
- Blog post + README "how well does this work" section.
- No feature code — the work is the eval + writeup.
v2.0 — daemon mode + ecosystem reach¶
Revisit when user demand (resource cost, install friction) actually surfaces. None of the below is committed or dated.
- Multi-client daemon mode. One long-running daemon + per-client stdio-proxy shims. Shared embedder + watcher + SQLite. Saves ~200 MB RAM per extra MCP client. Needs: daemon lifecycle (auto-start, health, restart), Unix socket transport (Windows: named pipe), graceful upgrade, per-client auth. Worth it only when running 3+ simultaneous MCP clients is common.
- Community plugin registry submission. PR
obsidian-brain-plugintoobsidianmd/obsidian-releasesfor one-click install from Obsidian's in-app Community Plugins browser (no BRAT required). Wait until the plugin's endpoint surface has stabilised (post-v1.5.0 at earliest); registry review is 1–2 weeks and re-submitting after every API change is friction. - Dynamic Templater-style tool registration. If the companion plugin is installed + Templater is enabled, scan the user's templates and register each as a typed MCP tool (parsing
tp.user.askString("X")prompts into Zod schemas). Lets "Claude, make me a meeting note" becomemeeting_notes({title, attendees, date})with validation. High ceiling, niche audience. - Optional git integration for write auditing. If the vault is a git repo, each agent-initiated edit becomes a commit with attribution (
agent: claude, tool: edit_note, note: X). Auditable + recoverable. Opt-in config flag so non-git users are unaffected.
Explicitly NOT planned¶
Stances worth naming so expectations stay calibrated:
- Cloud embeddings (OpenAI, Voyage, Cohere). Deliberate local-only stance — zero egress, works offline, nothing leaves the machine. The v1.4.0
Embedderinterface is forkable if anyone wants a cloud variant, but it won't be a first-party config knob. - DQL execution without Obsidian running. Reimplementing Dataview's query engine + metadata cache outside Obsidian is months of work for no meaningful gain over the companion-plugin approach.
- Full Bases feature parity — rendered card / calendar / map views. MCP returns data; rendering is the client's job.
- DataviewJS / JS-block execution. Arbitrary JS eval against the vault is a security hole; skip permanently.
- Plugin writes from the server (move Obsidian's cursor, open a file in the UI, inject text into the editor). The companion plugin is read-only by design. If we ever want this, it's a separately-scoped feature with its own threat model and opt-in.
- Rewrite in Rust. Node + sqlite-vec + transformers.js covers the performance envelope. A Rust rewrite would cost months for no user-visible win.
- Collapse to 5 hub-tools (aaronsb-style). Good pattern for single-surface operations; wrong for a tool set with distinct graph-analytics + writes + search semantics. We take the
next_actionshint pattern (v1.5.0), not the tool-count philosophy.
How this list updates¶
- Every release bumps the "shipped" table.
- Anything in "next up" that ships moves up; anything learned during execution (scope revisions, newly-discovered risk) edits the entry in place.
- "Future milestones" items only move up into "next up" when they become the most-leveraged work. Order is defensible but not sequential — v1.7 could preempt v1.6 if block-ref editing becomes the load-bearing gap.
- Field-test feedback and user issues add entries; nothing gets added speculatively.
- Items in "NOT planned" require a documented reason to move out of that bucket.
For bug fixes and maintenance releases that don't change the roadmap shape, only the "shipped" table gets a row.