Skip to content

v0.3.0 — Smart, linked, and 100k-ready

Choose a tag to compare

@shubhsaxena2020 shubhsaxena2020 released this 13 Jun 17:36
· 7 commits to main since this release

Cortex earns the name. Six of v0.3's eight roadmap items shipped (the kill criteria asked for at most five — we beat it), plus two items the criteria didn't anticipate: an MCP server turning the second brain into native Claude tool calls, and a graph performance overhaul that takes the canvas from 2.9 FPS at 100k+ nodes (v0.2) to 133 FPS settled.

Privacy-first desktop app: captures AI conversations from Claude, ChatGPT, and Gemini into a local knowledge graph. Nothing leaves your machine.

Headline features

  • Bidirectional [[wiki]] links + backlinks panel. Obsidian-style syntax ([[Title]] and [[Title|alias]]) persists as graph edges with a dedicated emerald color and a "wiki" signal type. Clickable in detail-panel previews and the editor's markdown preview; unresolved targets render muted as dangling links. New memories automatically resolve inbound links — if someone wrote [[Cortex Architecture]] before that memory existed, the link binds itself the moment the memory appears. Backlinks ("Linked mentions") section on every memory shows who points here.
  • Auto-tagging from content. Deterministic heuristic tagger weights title words 3× and prefers existing vocabulary tags (scaled by usage) over fresh keywords. No Ollama dependency — works fully offline. Lock semantics: first capture of an untagged conversation gets suggested tags; re-captures and user edits are never clobbered. Per-memory "suggest" button in the detail panel.
  • Embedding backfill UI. Visible progress bar in both the Settings AI panel and the status bar; pause at batch boundaries, resume restarts the scan. Skip reasons (Ollama down, model not pulled, vector search disabled) become actionable hints instead of silent no-ops.
  • Cortex MCP server. Six tools over stdio JSON-RPC 2.0 — cortex_search (FTS5 keyword + sqlite-vec semantic with auto-fallback), cortex_get_memory, cortex_list_memories, cortex_create_memory, cortex_related, cortex_stats. Zero new dependencies (hand-rolled dispatch beats @modelcontextprotocol/sdk's postinstall native-rebuild churn). Runs under Electron-as-Node because better-sqlite3 is compiled for Electron's ABI. Registered for Claude Code (project .mcp.json) and Claude Desktop (claude_desktop_config.json). Tested with 31 unit tests + a full end-to-end smoke harness against the live DB.
  • Graph performance overhaul: 125k+ nodes, no jank. Measured on a 60k-memory + 60k-file + 150k-edge fixture:
    • Far view (auto-fit, full graph in view): 7.5 ms/frame steady state — 133 FPS. (v0.2 measurement on the same hardware: 347 ms/frame, 2.9 FPS — 44× improvement.)
    • Cold open to first paint: 13–15 s at 125k nodes (the layout streams from tick 0 — early frames show physics organizing instead of a blank canvas).
    • Medium-zoom pan/zoom with ~40k edges on screen: 78 ms/frame (~13 FPS) settled — still degraded by per-edge stroke cost, but interactive instead of frozen.
    • Memory content no longer ships to the renderer. memories:getAll returns the LIGHT projection (id + title + tags + 200-char snippet); full bodies hydrate per selection. Editor mounts gate behind hydration so autosave can't write empty content over real data.
    • Mention edges computed in the main process behind a fingerprint cache. Renderer never tokenizes memory content.
    • Worker simulation scales by node count. ≥20k nodes drops forceCollide (its per-tick quadtree dominates the profile and the spacing it buys is sub-pixel at 100k zoom levels), raises Barnes-Hut theta to 1.2, cools faster, batches fewer ticks per post. Zero-copy typed-array init protocol — three ArrayBuffers instead of object arrays (structured-cloning 100k objects costs seconds).
    • Far-LOD scene cache. Clusters + bundled edge segments (deduped per pair, hard-capped at 6,000 segments) computed over the whole graph once per zoom band; reused across every pan/zoom frame in the band. Per-frame far cost becomes O(clusters), not O(nodes + links).
    • Density-override LOD. Visible-count override forces the cluster path whenever the frame would otherwise be unpayable, regardless of zoom band.
    • Flat-fill fast path above 1,500 visible nodes (no gradient, no shadowBlur per node — the rich style costs ~40 µs/node).
    • Adaptive quadtree leaf capacity (32 ≥ 20k points; 8 below). 4× fewer tree-node objects on big graphs with no measurable query-time hit.
    • Quadtree-local edge hover above 20k links — tests only edges incident to nodes near the cursor instead of the full O(links) scan.
    • Throttled position application. Worker batches are stashed (only the newest matters) and applied at 400 ms cadence — earlier code applied every batch, an O(nodes) copy + bounds pass that starved the main thread while the sim streamed per-tick.
    • Sidebar render cap at 300 rows. Mounting one DOM row per memory put 7+ MB of nodes in the React tree at 60k and froze first paint.

Shipped vs slipped (v0.3 kill criteria: ship ≥5 of 8)

Item Status
Bidirectional [[wiki]] links + backlinks panel ✅ Shipped
Auto-tagging from content ✅ Shipped
Embedding backfill UI ✅ Shipped
Saved searches / smart folders ✅ Shipped (search history + named saved searches + date-range filters)
Graph force simulation in a web worker ✅ Shipped in v0.2; further tuned here
Conversation summarization � Slipped to v0.4 — needs a second Ollama model (llama3.2:3b). Not worth blocking on.
Multi-model Ollama picker � Slipped to v0.4 — settings plumbing with no consumer until summarization exists.
db.test.disabled.ts → vitest-electron � Slipped to v0.4 — infra-only; live-process scripts + 399 unit tests cover the DB layer.

6/8 shipped — kill criteria exceeded.

Verified this release

  • 399/399 unit + integration tests green. npm run build clean across all three processes + worker chunk.
  • MCP server end-to-end smoke harness: 12/12 checks (handshake → tools/list → stats → search keyword → search semantic → get → related → create → round-trip → error paths).
  • Graph at 125,177 nodes / 175,087 edges: cold open to interactive in 13–15s; far-zoom steady state 133 FPS (7.5 ms/frame); pan/zoom never frozen.
  • Live verification via Chrome DevTools Protocol harness (scripts/cdp-fps2.mjs) — actual draw timings from the real renderer, not synthetic micro-benchmarks.

Migrations

  • Schema v6 unchanged from v0.2 (introduced idx_memories_source + ANALYZE). No migrations in this release.
  • Wiki backfill runs once at startup, LIKE-prefiltered so vaults with no wiki syntax pay one scan and zero writes.

Known limitations carried into v0.3.0

  • Medium-zoom pan/zoom still degraded at 5–10k visible nodes (~13 FPS). Far and close zoom are smooth; the middle band has 40k edges in view simultaneously and per-edge stroke cost dominates. v0.4 candidate: edge strength threshold rising with visible count, or OffscreenCanvas + WebGL.
  • Edge hover stops tooltipping at scale for edges whose endpoints are both far from the cursor (20k-link quadtree-local fallback). Acceptable trade-off.
  • Installer unsigned — SmartScreen will warn. Code-signing is v0.4 (~$300/yr in certs).
  • Windows-only installer — macOS DMG + Linux AppImage are v0.4.
  • Embedding 10k still takes ~5 min — Ollama CPU inference, not the script.

Stack

Electron 31 · React 18 · TypeScript 5 · Tailwind 3 · better-sqlite3 12 · sqlite-vec 0.1 · Fastify 5 · D3 7 (force sim in a Web Worker, scale-adaptive) · Zustand 4 · Vitest 4. 399/399 tests passing.