Repository navigation
v0.3.0 — Smart, linked, and 100k-ready
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 becausebetter-sqlite3is 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:getAllreturns 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-Hutthetato 1.2, cools faster, batches fewer ticks per post. Zero-copy typed-array init protocol — threeArrayBuffers 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
shadowBlurper 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 buildclean 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.