Turn any corpus into a thinking brain — then read its mind for the non-obvious connections.
Cortex embeds your notes, docs, or an AI-agent trace into a live 3D neural map: each concept becomes a neuron, each embedding similarity becomes a synapse. A spreading-activation engine animates the graph in real time — attending, spreading activation, and making dream-jumps — while a scored, ranked set of evidence-backed Insight Cards rolls up into an exportable Insight Digest. It runs 100% in your browser — no backend, no upload, no CDN.
▶ Live demo — runs entirely in your browser; nothing is uploaded.
What the demo is showing you. The pre-loaded 237-concept brain was built by the offline
build_brain.pypipeline (768-dimnomic-embed-text, card text written by a local llama3.2), not by the in-browser path this README describes. Click + your data and everything below becomes literally true: 384-dimall-MiniLM-L6-v2embeddings computed in your tab, and card text composed from the measurements rather than generated.
Most knowledge graphs are decorative — a pretty picture you look at once. Cortex is built around the output: the graph is context, the digest of non-obvious connections is the product. Pairs are scored, ranked most-surprising-first, and each comes with a "why" backed by the numbers behind it and an angle to pursue.
Worth being precise, because it's the whole claim. A bridge is scored as
surprise = relatedness × (1 − neighbourhood overlap) × same-note discount
Both live terms are measured in the full embedding space: relatedness is
cosine similarity, and neighbourhood overlap is the Jaccard overlap of the two
concepts' nearest-neighbour sets. The interesting case isn't two things that are
far apart — those are just unrelated. It's a pair that is genuinely related
while sitting in two neighbourhoods that never touch: two clusters meeting at a
single point. Every card in the exported digest carries the cosine similarity and the
measured neighbour overlap behind it, so you can check the claim rather than take
it. (On screen the card shows the prose; the numbers ride along on export.)
The overlap term used to be dead — it was computed over each concept's 12 nearest neighbours while the candidate pairs were drawn from ranks 12–60, so the two windows never met and the overlap was 0 for 54 of 59 insights, which made the score cosine with a scalar on it. It is now measured over a neighbourhood that reaches the candidate band, and it carries the ranking: re-scoring the demo corpus drops the Spearman correlation between the final score and plain cosine from 0.85 to 0.44, with only 2 of the top-10 insights surviving as a plain cosine top-10.
frontend/public/brain-safe.json was built before this fix and
still carries the old scores — run python3 analyze_brain.py against it and it
reports the 0.85, and flags that its stored scores predate the current formula.
Regenerating it is tracked separately; until then the shipped deck is the old
ranking. Both runs are recorded in
docs/bridge-score-baseline.md.
There used to be a third factor, a ×1.15 cross-domain bonus. It compared the parent folder name — not an embedding measurement, and uniformly "note" for pasted text — and once the overlap term worked it changed only ~6 of 59 selected pairs and never the top 10, because cross-cluster pairs already are the low-overlap pairs. It was deleted rather than shipped as an inert multiplier. Whether a pair crosses an embedding-derived cluster boundary is still computed (from the vectors, not a folder name) and shown on each card as context, so the grouping is a real measurement now — it just isn't multiplied into the score. The folder name, where a corpus has one, stays a display label.
Two honest notes on that:
-
The card text is composed from measurements, not generated, in the in-browser path — the one that runs on your own data. Genuinely written explanations require a model, which the offline
build_brain.pypipeline uses (via local Ollama) and the browser deliberately does not — that's the price of never phoning home. The pre-baked demo brain came from that offline pipeline, so the cards you see before dropping in your own data are llama3.2 prose, not composed measurements. Drop in a corpus and you get the composed kind. -
A "concept" is a passage, not a whole document. Files are split on their own structure — headings first, then paragraph breaks — so a note covering three ideas becomes three neurons instead of one blurred point sitting between all three. A blank line is treated as the author saying "new idea", so passages are never repacked across one to hit a size target; only true fragments are glued to their neighbour, and a wall of text is cut on sentence boundaries. Each passage keeps a pointer back to its source document, and a single file is capped at 40 neurons so one long document can't drown out the rest of the graph.
This matters for the scoring above: two passages of the same note are now the commonest high-similarity pair in the graph and the least interesting one — the author already wrote those ideas side by side, so nothing was discovered. They're discounted to 0.35× rather than allowed to crowd out genuine cross-source bridges.
(Earlier versions made one neuron per file, truncated to 600 characters — which discarded most of a long note and made the graph document × document.)
cd frontend
npm ci # exact, reproducible install (pinned lockfile)
npm run dev # then open the printed localhost URLThe default view is a 237-concept demo brain (AI / neuroscience / cognition) — hit ⚡ all in the Insight Digest panel to surface every connection at once.
Serve it over http (the
npm run devURL, or the builtdist/). Opening the files directly withfile://breaks ES-module loading.
Click + your data, then drop a folder, pick files, paste text, or hand it an
AI-agent trace (.md, .txt, .json, .jsonl). Cortex embeds it locally
and builds the brain in-browser.
- Provably local. The embedding model (
all-MiniLM-L6-v2) and the ONNX-runtime WebAssembly are vendored into the app — open your browser's Network tab while it embeds and you'll see requests to only your own origin, never a CDN. - Secret-safe. API keys, tokens, and private keys are auto-redacted on ingest, before anything becomes a neuron or a shareable card.
- Fault-tolerant. If a file won't parse, Cortex tells you exactly why instead of silently producing an empty brain.
Each bridge emits an Insight Card: concept A × concept B · why it's non-obvious · an angle to explore, carrying its surprise score, the cosine similarity and neighbour
overlap behind that score, and the source snippets. Cards come out ranked, highest
score first. Copy or download the whole digest as Markdown, or export any card as a
watermarked share image.
(The engine's animated dream-jumps are a live traversal of this same graph — they're what makes the visualisation move, not what decides which connections are worth showing. The ranking above does that.)
| Layer | What it is |
|---|---|
| Neurons | your concepts, embedded with all-MiniLM-L6-v2 (384-dim), laid out in 3D via PCA — this is the in-browser path, which is what runs on your data. The pre-baked demo brain was built by the offline pipeline instead (768-dim); see the demo note above |
| Synapses | k-nearest-neighbour cosine similarity between concept embeddings |
| Bridges | related-but-non-adjacent pairs, scored by relatedness × (1 − neighbour overlap) × same-note discount and sorted |
| Curiosity engine | live spreading-activation with an attend → spread → dream-jump policy; the firing is emergent, not scripted. It animates the graph — the ranking above, not the walk, selects which connections surface |
| Insight Digest | the ranked, evidence-backed export — the product |
- Local embeddings —
@xenova/transformers(all-MiniLM-L6-v2, quantized), running in WASM - Rendering —
three.jswith UnrealBloom postprocessing - Build — Vite + TypeScript; unit-tested with Vitest
- Zero external runtime dependencies — the model and wasm are committed under
frontend/public/; see PROVENANCE for exact files, sources, and licenses. Nothing is fetched from a third party at runtime — the only requests are same-origin (brains.json,brain-*.json, and the vendored model and wasm), which is the claim that actually matters and the one you can watch in the Network tab.
Two extra, fully local tools ship alongside the web app:
A zero-dependency Python pipeline that turns your Claude Code .jsonl history into
one named archetype ("The Pouncer," "The Director," "The Surgeon"…) and a set of
ranked, shareable "how you actually work with your AI agent" cards — computed
entirely on your machine. It emits aggregate stats only: file paths are one-way
hashed, model names are collapsed to a coarse family, no prompt text is ever stored,
and a privacy tripwire hard-fails the run if anything path- or secret-shaped would be
written. See agent-insights/README.md.
Now also standalone: cmonaco0317/agent-insights — same tool, its own repo, for people who want the Claude Code report without the graph app. The copy here stays as part of Cortex.
Archetypes are decided by rates, not totals — corrections per 100 prompts, not corrections — so the label describes how you work rather than how much. (Absolute counts appear only as minimum-sample gates; three prompts isn't a personality.) The statistical mining underneath — Wilson score intervals on tool-success rates, an order-2 Markov next-move model, high-lift move mining — is the rigorous part; the archetype is the readable surface over it.
A local CLI that embeds a folder of markdown/text with a local model (Ollama
nomic-embed-text) and writes a brain JSON the web app can load — for when you'd
rather build the graph offline than in the browser. It also writes generated
explanations (via local llama3.2), which the browser path can't do.
blind_test.py + corpus_safe.json are a self-contained blind A/B harness that puts
a scored bridge and a plain nearest-neighbour side by side, shuffled and unlabelled,
and asks you to pick. It scores with an exact two-sided binomial test against
chance, and it will tell you the run was inconclusive — which, at n=20 with one
rater, is the honest answer most of the time. It deliberately has no "pass bar":
an earlier version passed the engine at ≥30% wins, which is at or below chance once
"neither" is an option, so it could print PASS while the baseline was actually
preferred twice as often. Read any result narrowly: one rater on one corpus is not
evidence of a general effect, and the harness says so in its own output.
build_brain.py and blind_test.py need pip install numpy, and so do the tests
that cover them — the cross-language conformance golden, the clustering, and the
blind-test power maths. The agent-insights/ half is genuinely standard-library
only, and its own repo's CI installs nothing but pytest to keep it that way.
python3 -m pytest # from the repo root — 123 tests (106 without numpy,
# which SKIPS the 17 that need it; CI installs numpy
# and fails if they skip)npm audit currently reports 0 advisories — and that number is not the argument.
For a while it was 11, including three criticals, and none of those reached a page
visitor either. The alarming one (protobufjs, via the ONNX runtime) is tree-shaken
out of the build entirely, because the model is parsed by the vendored WebAssembly
rather than in JavaScript. SECURITY.md shows the greps that prove it —
CI runs all four against the built dist/ on every push, and asserts the advisory
count, so neither claim can go stale unnoticed — and explains what the advisories
did put at risk (the build machine) and why npm audit fix --force was the wrong
tool.
Cortex's own code is MIT. Vendored components keep their own licenses: the embedding model is Apache-2.0 and ONNX Runtime Web is MIT — details in PROVENANCE.
made with Cortex — a local curiosity engine. Nothing leaves your machine.


