// Built at Moss · YC F25 · Search
Mycelium
Your browser, with memory.
A spore for every page you finish.
Browser history works when you remember a title or a URL. Mycelium is for when you only remember the idea. It quietly turns the long articles you read into private semantic memory, then lets you search them by meaning from a command palette, and shows how they connect.
Mycelium is an unpacked Chrome extension (Chrome 121+), not on the Web Store yet, so there's nothing to visit. The palette, ingestion and graph below are recreations that run on this page.
Live demo, running on this page· typing, click to take over
Recently ingested
- Building agents that remember across sessionsdev.to · 620 words
- Local-first software: you own your datamartinfowler.com · 1,811 words
- Vector search explained with picturesmedium.com · 2,208 words
- Offscreen documents in Chrome extensionsgithub.blog · 1,569 words
- Knowledge graphs from your readingmedium.com · 2,484 words
00 Overview
After about 1.8 seconds on a page, and again when a single-page app changes URL, a content script runs Mozilla Readability. Only HTTP(S) pages with at least 500 readable words become memories, and a guard skips webmail, banking, checkout, payment and medical-record URLs. A stable URL hash means a revisit updates one memory instead of making a duplicate.
Moss runs embedding and vector search in WebAssembly inside the extension. Captured pages sync to your Moss project so the durable index can be built; once that index is loaded, warm queries run locally with no network round trip. OpenRouter is optional and off by default.
- Built at
- Moss · YC F25
- Platform
- Chrome extension (MV3)
- Retrieval
- Moss Web SDK, WASM
- Model
- moss-minilm
- Graph
- d3-force + Canvas 2D
- TypeScript
- Chrome Extension API (MV3)
- Moss SDK (WASM)
- d3-force
- Canvas 2D
- OpenRouter (optional)
01 Browse → ingest
Every article becomes memory.
Each tab below runs the real gates: Readability, the 500-word floor, the sensitive-site guard and URL-hash dedupe. Pages that pass are written to chrome.storage.local immediately, then upserted to Moss.
- dev.to/building-agents-that-rememberBuilding agents that remember1,840 wordsIngested · new memory
- medium.com/local-first-softwareLocal-first software2,310 wordsIngested · new memory
- news.example.com/quick-updateQuick product update212 wordsSkipped · under 500 readable words
- bank.example.com/accounts/checkingChecking accountnot readSkipped · sensitive-site guard (banking)
- arxiv.org/abs/self-improving-agentsSelf-improving AI agents3,120 wordsRevisit · same URL hash, 1 memory updated
02 Search
Search by idea, not title.
⌘/Ctrl+K on any page (or ⌘/Ctrl+Shift+K, or the toolbar icon) opens the palette in an isolated Shadow DOM. Input is debounced 150 ms; up to eight ranked results come back with query-aware snippets, favicons, scores, the retrieval source and measured latency. The footer is honest about where answers came from: LOCAL WASM when Moss answered from the loaded index, LOCAL CACHE when a lexical fallback answered while Moss was warming up. Moss gets 1.2 s before it times out; the fallback can render after about 250 ms and is replaced when Moss hits arrive.
- Keystroke150 ms debounce
- LOCAL CACHElexical fallback renders after about 250 ms
- LOCAL WASMMoss hits replace the fallback when they arrive; it gets 1.2 s before timing out
The palette at the top of the page runs this race in your browser, over a 40-page demo index with a tiny hashed embedding, not Moss's model. The first query after a cold start shows it: LOCAL CACHE answers while the index warms, then LOCAL WASM results replace it.
03 Connect
Memory becomes connected.
⌘/Ctrl+Shift+G opens graph.html: up to 300 pages, clustered by domain with stable colours, sized by revisits and search matches. Edges come from normalised shared-term overlap, kept above 0.08 and capped at five per node, and cached by data revision. Pan, zoom, drag, hover focus, graph search and a node inspector.
All 40 pages, as a list
- dev.to
- arxiv.org
- medium.com
- github.blog
- simonwillison.net
- lilianweng.github.io
- web.dev
- martinfowler.com
04 Under the soil
Four parts, one message.
- 01Content script
React + Shadow DOM. Readability after ~1.8 s, 500-word and sensitive-site gates, immediate chrome.storage.local write, the palette UI.
- 02Service worker
MV3 background: search orchestration and lexical fallback, settings, graph and summary caches, the OpenRouter queue, commands, offscreen lifecycle.
- 03Offscreen document
Owns @moss-dev/moss-web: createIndex, addDocs({ upsert: true }) in batches of 50, loadIndex, then in-browser query embedding and top-8 vector retrieval.
- 04graph.html
React + d3-force + Canvas 2D with an affinity-edge cache.
Why an offscreen document: MV3 service workers are short-lived and can't host the Moss WASM stack, so a long-lived offscreen page owns the client and the loaded index. The background build is a single static file because dynamic imports are rejected there; Vite builds three targets (extension pages, the worker, an IIFE content script).
05 What stays local
Honest about what leaves.
- Page text + metadatachrome.storage.localSTAYS LOCALAlways. Written the moment a page passes the gates.
- Page textYour Moss projectSYNCSSynced, so the durable index can be built and loaded.
- Search queriesMoss WASM, inside the extensionSTAYS LOCALLocal. No per-query network round trip once the index is loaded.
- Title + up to 12,000 charsOpenRouterNOT SENTOff by default. Nothing is sent.
06 Also
Optional AI summaries
Off by default. When on, OpenRouter (openrouter/free by default) writes one sentence under 20 words from the title and up to 12,000 characters, capped at 60 tokens, cached per URL and queued so it never blocks ingestion. Without it, Mycelium falls back to the title or snippet silently.
Built for revisits
Each memory tracks first and last visit, revisit count and how often it matched a search, which also drives node size in the graph.
Local by default
Text and metadata live in your Chrome profile with unlimitedStorage. Six storage keys hold pages, settings, summaries, the data revision, last sync and the graph cache.
Stack TypeScript, React, Chrome Extension MV3 (service worker, offscreen document, content scripts, commands), Moss Web SDK (WASM, moss-minilm), Mozilla Readability, d3-force, Canvas 2D, Vite, pnpm, OpenRouter (optional).
07 From the promo video
Frames from the 27-second promo video in the repo, rendered programmatically with Python and Pillow. They're stylised, not screen recordings, and the latency figures in them are illustrative.



