# MemWeave **Repository Path**: Duke_Bit/mem-weave ## Basic Information - **Project Name**: MemWeave - **Description**: Let AI coding agents truly “remember” your project. - **Primary Language**: Unknown - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-06-09 - **Last Updated**: 2026-07-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # MemWeave > A local-first, memorable, reasoning-capable memory and context infrastructure for AI agents. > > **中文版本:** [README.md](./README.md) --- ## What is it MemWeave is a local service that lets AI Agents **remember context without blowing up their context window**. LLM context windows are limited. Stuffing full memory records into the system prompt wastes tokens—the agent may only need a line or two. MemWeave's answer is **Progressive Disclosure**: > **Inject only summaries; pull full detail on demand.** ``` system prompt → memory id + title + summary ← low token cost Agent calls → memory_expand(id) → full body ← tokens spent only when needed ``` Around this core design, MemWeave provides a complete memory infrastructure: - **Structured memory**: facts, decisions, preferences, events, lessons… organized by `type` / `tier` in local SQLite. - **Four-layer retrieval**: keyword (BM25) + vector semantics + graph relations + causal chains, fused on demand. - **Consolidation ("Sleep")**: periodically promotes short-term → long-term, evicts cold items, discovers causal links. - **Auto-injection** (OpenCode plugin): relevant summaries appended to the system prompt on every turn / file read, zero call overhead. - **MCP tools** (v0.4+): 10 `memory_*` tools embedded in the server process and exposed via Streamable HTTP at the `/mcp` endpoint; closes the progressive-disclosure loop. - **MCP tool set** (v0.4+): 10 `memory_*` tools embedded in the server process, exposed via Streamable HTTP at the `/mcp` endpoint; closes the progressive-disclosure loop. - **Web UI** (Calm Memory Atlas): browse, search, debug, and operate the whole memory system in a browser. - **REST API**: a complete HTTP interface for scripts and third-party tools. All data lives in local SQLite. **No mandatory external dependencies** — runs end-to-end without any optional components installed. --- ## Progressive Disclosure — Core Design MemWeave stores **full memory body** (`content`) but **injects only summaries** (`title` + `summary`) by default. The idea: given a limited context window, give the agent the most relevant "clues" first, and let it pull full details on demand. ### Three consumption granularities | Level | Contains | When | Token cost | |---|---|---|---| | **Compact (default)** | `id` / `type` / `tier` / `title` / `summary` | Injection, search (`mode: "compact"`) | Low | | **Full record** | Above + `content` / `concepts` / `importance` … | `GET /api/v1/memories/:id` / `MCP memory_expand` | Medium | | **Plus neighbors** | Above + edges, sessions, causal chains | `MCP memory_expand` (with edges) | High | ### Injected XML ```xml User prefers strict TypeScript Always use noImplicitAny, exactOptionalPropertyTypes. ... ``` The LLM sees the summary and calls `memory_expand({ memoryId: "m_abc" })` to fetch the full `content`. ### Closing the loop The plugin only injects summaries into the system prompt (step 1). The MCP tools (`memory_expand` etc.) are provided by the `/mcp` endpoint embedded in `@mem-weave/server` (see previous section). OpenCode connects to it via the `mcp: { memweave: { type: 'remote', url: 'http://127.0.0.1:3131/mcp' } }` block; other clients the same. > **Design point**: Progressive disclosure is not "phased verbosity" — it's **always-summary, full-on-demand**. Every injection phase renders the same granularity; only the memory set and count differ. --- ## 5-minute quickstart ### Option A — global install (recommended; needed for OpenCode / IDE integration) ```bash npm install -g @mem-weave/server npm install -g @mem-weave/opencode-plugin memweave init # generate memweave.config.jsonc + data dir memweave start # background server (default since v0.5.7) ``` Open [`http://127.0.0.1:3131/ui/`](http://127.0.0.1:3131/ui/) to see the **Calm Memory Atlas** Web UI. #### `start` is background by default `memweave start` **detaches to its own process and exits immediately**; closing the terminal will not stop the server. Logs are appended to `/memweave.log` (default `~/.memweave/data/memweave.log`); the PID file lives in the system temp dir. ```bash memweave start # background (default) memweave status # /api/v1/health memweave stop # use the PID file # run inline for debugging (Ctrl-C to stop) memweave start -f # or --foreground ``` > The legacy `Start-Process -WindowStyle Hidden memweave start` workaround is no longer needed since v0.5.7 — `start` is already a background command. OpenCode client — edit `~/.config/opencode/opencode.json`: ```jsonc { "plugin": ["@mem-weave/opencode-plugin"], "mcp": { "memweave": { "type": "remote", "url": "http://127.0.0.1:3131/mcp", "enabled": true } } } ``` > **The `mcp` block is required.** OpenCode does not call a plugin > `config` hook (see the [plugins docs](https://opencode.ai/docs/plugins/)). > The `type` field **must** be `"remote"` — OpenCode's Effect schema only > accepts `"remote"`; `"http"` / `"sse"` are silently dropped. > > The plugin **also** ships a `.mcp.json` at its package root as a > backup path via [`oh-my-openagent`](https://github.com/code-yeongyu/oh-my-openagent), > but oh-my-openagent depends on `~/.claude/plugins/installed_plugins.json` > (Claude Code's plugin DB) — most users don't have Claude Code, so > `.mcp.json` is **not** a reliable path. Hand-editing `mcp.memweave` > is the main path. ### Option B — npx try-out (no install) ```bash npx @mem-weave/server init # generate memweave.config.jsonc + data dir npx @mem-weave/server start # foreground server ``` **Try-out only.** OpenCode / IDE integration needs the server to be globally installed (Option A), otherwise the `http://127.0.0.1:3131/mcp` endpoint disappears the moment the npx process exits. ### Option C — from source (development) ```bash git clone memweave cd memweave npm install npm run dev # builds web + starts server on :3131 ``` ### Health check ```bash curl http://127.0.0.1:3131/api/v1/health # → {"ok":true,"service":"memweave-server"} ``` --- ## Architecture at a glance ``` ┌────────────────────────────────────────────────────────────┐ │ Clients │ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌────────────┐ │ │ │ Web UI │ │ CLI │ │ MCP/IDE │ │ OpenCode │ │ │ │ │ │ │ │ │ │ Plugin │ │ │ └────┬────┘ └─────┬────┘ └─────┬────┘ └─────┬──────┘ │ └────────┼─────────────┼─────────────┼─────────────┼──────────┘ │ HTTP │ stdio │ stdio │ HTTP │ │ │ │ (POST /injection/preview) └──────────────┴─────┬──────┴─────────────┘ ▼ ┌────────────────────────────┐ │ memweave-server │ │ (Fastify + TypeScript) │ └────────────┬───────────────┘ ▼ ┌──────────────────────────────────────┐ │ Retrieval Engine (4-layer fusion) │ │ ┌────────┐ ┌────────┐ ┌──────┐ ┌──┐ │ │ │ BM25 │ │ Vector │ │Graph │ │Caus│ │ │ └────────┘ └────────┘ └──────┘ └──┘ │ └────────────────┬─────────────────────┘ ▼ ┌─────────────────────┐ │ SQLite (node:sqlite)│ │ + pure-JS vectors │ └─────────────────────┘ ▲ │ ┌─────────────────────┐ │ Consolidation Worker│ │ (periodic "sleep") │ └─────────────────────┘ ``` See [`docs/`](./docs/) for full design docs. --- ## Core concepts | Concept | Description | |---|---| | **Tenant** | Multi-tenant isolation unit (default `tenant_default`), each with its own API key. | | **Memory** | A structured record with `type` (fact / decision / preference / event / project_context / lesson / code_pattern / bug / workflow), `tier` (short / medium / long), `summary`, `details`, `scopes`, etc. | | **Session** | An Agent session, linked to a chain of observations. | | **Observation** | A single user/tool/assistant interaction. | | **Edge** | A relation between memories (causal / temporal / entity). | | **Consolidation Run** | A snapshot of a single "sleep" cycle: promotions, evictions, discovered causal links. | --- ## CLI cheatsheet The `memweave` global command is installed by `@mem-weave/server`. ```bash memweave ``` | Command | Description | |---|---| | `init` | Generate default config and data dir | | `start` | Start the service in the background (default) and exit. `start -f` to run inline. | | `stop` | Stop the background service | | `status` | Show service status | | `migrate` | Run database migrations | | `doctor` | Self-check (DB / config / port) | | `backup` | Back up the SQLite database | | `version` | Print version | | `help` | Show help | > The standalone `mcp` subcommand and `@mem-weave/mcp` package were retired in v0.4. The 10 MCP tools are now embedded in `@mem-weave/server` and served at the `/mcp` endpoint (Streamable HTTP). No separate install or `mcp` invocation is needed. --- ## REST API overview All routes are prefixed `/api/v1/`. See `packages/server/src/rest/routes/` for the full set. | Endpoint | Method | Purpose | |---|---|---| | `/health` | GET | Health check | | `/memories` | GET / POST | Search + write memories | | `/memories/:id` | GET / PATCH / DELETE | Memory detail / edit / delete | | `/memories/:id/edges` | GET | Relation graph of a memory | | `/injection/preview` | POST | Generate an injection bundle (XML) | | `/stats` | GET | Dashboard stats (KPIs, distributions) | | `/sessions` | GET | Session list | | `/sessions/:id/observations` | GET | Session observation log | | `/consolidation/runs` | GET | "Sleep" history | | `/consolidation/runs/:id` | GET | Run detail | | `/consolidation/runs/latest` | GET | Most recent run | | `/consolidation/run` | POST | Trigger a manual run | | `/devices` | GET / POST / DELETE | Device registration & management | | `/settings` | GET | View server config (secrets masked) | --- ## MCP tools As of v0.4 the 10 `memory_*` MCP tools are **embedded in the `@mem-weave/server` process** and exposed over **Streamable HTTP** at the `/mcp` endpoint. The standalone `@mem-weave/mcp` package has been retired. Any MCP client that supports Streamable HTTP (the 2025-03-26 spec) can connect directly: ```json { "mcpServers": { "memweave": { "url": "http://127.0.0.1:3131/mcp" } } } ``` OpenCode configuration (`mcp` section of `~/.config/opencode/opencode.json`): ```json { "mcp": { "memweave": { "type": "remote", "url": "http://127.0.0.1:3131/mcp", "enabled": true } } } ``` **The 10 registered tools:** | Tool | Description | |---|---| | `memory_save` | Persist an insight, decision, or fact as a long-term memory; supports type, title, concepts, files, scopes, importance | | `memory_recall` | Keyword search over past observations and memories | | `memory_smart_search` | Smart search: keyword + vector + graph + causal, four-layer fusion | | `memory_expand` | Expand a single memory: pull related edges, sessions, causal chains | | `memory_graph_query` | Run a graph query around an anchor (BFS / causal / entity) | | `memory_file_history` | Query all memories and observations related to a file path | | `memory_sessions` | List recent sessions with observation count and time range | | `memory_patterns` | Discover recurring patterns (frequent n-grams, concept clusters) | | `memory_consolidate` | Manually trigger a "sleep" consolidation run | | `memory_forget` | Soft-delete a memory (sets `deleted_at`) | All tools call the server's REST API through `MemweaveClient`. Override the server address via `MEMWEAVE_URL` (default `http://127.0.0.1:3131`). --- ## OpenCode plugin (auto-injection + auto-write + write-side closure) `@mem-weave/opencode-plugin` ships an OpenCode plugin called `MemweaveInjectPlugin` that closes the **read and write loop** with the MemWeave server: 1. **Read side** — automatically injects relevant memory summaries into the system prompt (LLM doesn't have to call any tool to see context). 2. **Write side (v0.4+)** — listens to OpenCode's `message.updated` event and pushes every completed user + assistant message to the server as a Session + Observation. The consolidation worker promotes high-signal observations into long-term memories on the next tick. 3. **MCP endpoint** — the 10 `memory_*` tools come from `@mem-weave/server`'s built-in `/mcp` (Streamable HTTP). They are reached via the `mcp.memweave` block in `~/.config/opencode/opencode.json` that **you must hand-add once** (see below). The `type` field **must** be `"remote"` — OpenCode's Effect schema only accepts `"remote"`. **Enable it:** ```bash npm install -g @mem-weave/opencode-plugin ``` Then in `~/.config/opencode/opencode.json`: ```jsonc { "plugin": ["@mem-weave/opencode-plugin"], "mcp": { "memweave": { "type": "remote", "url": "http://127.0.0.1:3131/mcp", "enabled": true } } } ``` > **The `mcp` block is required** with `type: "remote"`. Other `type` values > (`"http"`, `"sse"`, etc.) are silently dropped by OpenCode's schema validator. > > The plugin also ships a `.mcp.json` at its package root as a backup path > via [`oh-my-openagent`](https://github.com/code-yeongyu/oh-my-openagent) — > but oh-my-openagent's Claude Code plugin loader depends on > `~/.claude/plugins/installed_plugins.json` (Claude Code's plugin DB) which > most users don't have. So `.mcp.json` is **not** reliable; hand-editing > `mcp.memweave` is the main path. **What it does (hooks actually called by OpenCode):** 1. `event` (v0.4+) — on `message.updated`, reverse-queries the OpenCode SDK for the message's `Part[]` text, then `POST /api/v1/sessions` + `POST /api/v1/observations` on the server (both idempotent on `(sessionId, messageId)`). 2. `experimental.chat.system.transform` — asks the server for a `session_start` / `prompt_delta` context pack (based on session ID, user identity, tenant) and appends it to the system prompt. 3. `tool.execute.before` — on file-reading tool calls (`Read` / `Edit` / `Write` / `Glob` / `Grep`), extracts file paths and requests a `file_pack` of file-related memories. **Write-side data flow:** ``` OpenCode user message complete ↓ Plugin event hook fires → OpenCode SDK reverse query → text + messageId ↓ Plugin POST /api/v1/sessions → server upserts session POST /api/v1/observations → server upserts observation (tool_output = text, tool_input = JSON{messageId}) ↓ Server consolidation worker (every 6h) → promotes high-signal observations to memory ↓ Next system.transform injection → LLM sees summary → calls memory_expand for detail ``` **Injection format** — the server returns `contextXml` like: ```xml User prefers strict TypeScript Always use noImplicitAny, exactOptionalPropertyTypes. ... ``` Sort order: `tier` (long > medium > short) → `strength × importance`. The server-side `injection/` module handles querying, trimming, and token-budget enforcement. **Configuration:** | Env var | Default | Meaning | |---|---|---| | `MEMWEAVE_URL` | `http://127.0.0.1:3131` | Server URL | | `MEMWEAVE_PLUGIN_TIMEOUT` | `10000` (ms, hardcoded) | Per-injection request timeout | > The plugin **silently swallows server-unavailable errors** (try/catch) so a MemWeave outage never breaks the agent. ## Write-side dedup (server-side, zero token cost) The read side is closed — but what about the write side? `memory_save` will **not** create duplicates of memories the LLM just saw in the injected XML, because dedup runs server-side automatically. **The LLM never knows, and there is zero token cost.** **Mechanism**: `MemoryRepo.create` runs a dedup gate before any INSERT: 1. BM25 query on the FTS5 index using the new input's `concepts` field (same tenant, exclude soft-deleted) — sub-millisecond, zero embedding cost 2. Take top-5 candidates, compute **Jaccard similarity** on the concepts set (|A ∩ B| / |A ∪ B|) for each 3. If the best Jaccard is **≥ 0.8** AND `type` matches → it's a duplicate. **Reinforce the existing memory** instead of inserting a new row. **Reinforcement has two behaviors** based on whether the new content is richer: | Scenario | Action | |---|---| | New content is similar (length delta < 25%) | Just `recordAccess`: bump `access_count` / `reinforcement_score` / `strength` / `last_reinforced_at` | | New content is meaningfully richer (length > 1.25× or higher importance) | **Merge**: upgrade content, union concepts, union files, take `max` of importance | **Design points**: - **Zero LLM tokens** — pure server-side BM25 + set similarity - **Zero added latency** — FTS5 is sub-millisecond on SQLite - **Type must match** — a `fact` is never a duplicate of a `decision` - **Callers don't need to change** — `create()` still returns `MemoryRecord`. Use `createDetailed()` if you want the dedup signal: it returns `CreateResult { memory, deduped, reinforcedId }` - **REST routes unchanged** — `POST /api/v1/memories` still calls `create()`; behavior is fully transparent to API consumers > **No "LLM-side dedup"**: that approach (asking the LLM to first `memory_smart_search` before every `memory_save`) burns ~1000 defensive tokens per save even when there's no duplicate. This scheme only spends server CPU **when a duplicate actually exists**, and the LLM never has to think about it. ### Write-side companion: input limits + rate limiting + background merge + structured logging - **Hard limits in `CreateMemoryInputSchema`** (`packages/server/src/core/types.ts`): `content` ≤ 100,000 chars, `concepts` ≤ 50, `files` ≤ 50. A buggy or malicious LLM cannot insert 10MB of body or 10k concept tags. - **Write rate limit** (`packages/server/src/server/rate-limiter.ts`): one token bucket per API key, 30 writes/minute burst, 2/sec sustained. `POST /api/v1/memories` returns `429 Too Many Requests` + `Retry-After` header when over quota. - **Background merge stage** (`packages/server/src/workers/consolidator.ts`): in addition to evict + promote, the consolidation pipeline now has a **Jaccard merge stage** that reuses the same formula and threshold as the live write-side dedup. Scans all same-tenant same-type memory pairs and absorbs near-duplicates. Two-layer defense: live dedup + background merge. - **Process-wide consolidation mutex**: the `consolidationInFlight` boolean inside `runConsolidation` guarantees only one run per tenant. Background scheduler and manual `POST /api/v1/consolidate` never collide. - **pino structured logging** (`packages/server/src/server/logger.ts`): replaces 14 `console.*` error sites across the codebase. `LOG_LEVEL` env var tunes verbosity (default: `info`). JSON output is log-shipper-friendly (Loki, ELK, etc). - **Dedup reinforce writes an audit log row** (`packages/server/src/db/repositories/memory-repo.ts`): when `reinforceExisting` fires, it inserts a `source: 'dedup_reinforce'` row in `access_logs` so "this memory was reinforced" is auditable alongside regular retrievals. --- ## Local embeddings (optional) MemWeave's vector layer is **fully optional**. Three embedding providers, pick one: | Provider | Config key | External dep | When to use | |---|---|---|---| | **`noop`** (default) | `embedding.provider: "noop"` | none | Zero-config startup / no vector layer | | **`local-xenova`** | `embedding.provider: "local-xenova"` | `@xenova/transformers` (opt-in install) | Real semantic vectors, no API bill | | **`openai-compatible`** | `embedding.provider: "openai-compatible"` | any OpenAI-compatible `/v1/embeddings` endpoint | You already have OpenAI / Voyage / a self-hosted endpoint | **Enabling `local-xenova`:** ```bash npm install @xenova/transformers ``` `memweave.config.jsonc`: ```jsonc { "embedding": { "provider": "local-xenova", "model": "Xenova/nomic-embed-text-v1", "dimensions": 768 } } ``` **Key behaviors:** - The first `embed()` call dynamically loads the model and pulls weights from the Hugging Face Hub (~30MB), then caches them under `node_modules/@xenova/transformers/.cache/`. - Subsequent calls **reuse** the loaded pipeline (concurrent callers share the same load). - **Automatic degradation**: if `@xenova/transformers` is not installed, the model fails to load, or inference times out (default 60s), the provider falls back to a SHA-256 hash-based vector and emits a one-time `console.warn`, so the system never breaks. - Pass `fallbackOnError: false` to disable the fallback (let errors bubble up for debugging). - If the model's output dimension doesn't match the configured `dimensions`, the vector is **truncated or zero-padded** to match (consistent with the graceful-degrade style of `vector-search.ts`). See [`packages/server/src/providers/embedding/local-xenova.ts`](./packages/server/src/providers/embedding/local-xenova.ts) and [`packages/server/src/types/xenova.d.ts`](./packages/server/src/types/xenova.d.ts) for details. --- ## Web UI tour Visit `/ui/`. Five top-level pages + memory detail + graph: | Route | Name | Purpose | |---|---|---| | `/ui/` | **Atlas** | Dashboard: KPI cards, tier/type distributions, active projects, last consolidation | | `/ui/memories` | **Memories** | Three-pane: filter rail + list + detail (search, type filter, strength sort) | | `/ui/injection` | **Injection** | Form to preview the injection bundle (clipped to token budget) | | `/ui/sleep` | **Sleep** | Consolidation run history + git-diff view of promotions/evictions | | `/ui/settings` | **Settings** | Server config viewer, device list, API key reveal toggle | | `/ui/memories/:id` | **Memory Detail** | Memory detail (body / relation graph / access log) | | `/ui/graph/:id` | **Graph** | Relation graph (radial layout) | Light / dark theme toggle in the top-right. --- ## Development ### Directory layout Starting with v0.2, the repo is a monorepo. Each `packages//` is an independent npm package: ``` packages/ ├── server/ # @mem-weave/server — Fastify + SQLite + CLI │ └── src/ │ ├── cli.ts, cli-entry.ts │ ├── commands/ # 9 memweave subcommands │ ├── core/ # config, Zod enums, decay model │ ├── db/ # SQLite schema + 9 repositories │ ├── injection/ # injection bundler │ ├── prompts/ # prompt templates │ ├── providers/ # Embedding (noop/openai/xenova) / LLM (noop/openai) │ ├── rest/ # HTTP API (8 route files) │ ├── retrieval/ # 4-layer retrieval engine + RRF │ ├── server/ # HTTP bootstrap + scheduler │ ├── workers/ # Consolidation background tasks │ ├── types/ # ambient .d.ts │ └── mcp/ # embedded MCP server (Streamable HTTP, /mcp endpoint) │ ├── index.ts, service.ts, registry.ts │ └── tools/ # 10 memory_* tools └── opencode-plugin/ # @mem-weave/opencode-plugin — OpenCode plugin └── src/ ├── index.ts, client.ts web/ # React 18 + Vite frontend (separate subproject, not in packages/) ├── src/ │ ├── pages/ # 7 pages │ ├── components/ # AppShell + common components │ ├── api/ # typed fetch wrapper │ ├── lib/ # formatters / utils │ └── theme/ # CSS variables (design tokens) ├── tests/ # vitest + happy-dom └── vite.config.ts tests/ # cross-monorepo vitest integration + unit tests docs/ # design docs scripts/publish.mjs # one-shot build + publish all 3 npm packages ``` ### Common scripts **In the monorepo (development):** | Command | Description | |---|---| | `npm test` | Run all Vitest tests (server integration + units) | | `npm run typecheck` | TypeScript type check (entire monorepo) | | `npm run build` | Build frontend + both server packages (tsc) | | `npm run dev` | Build frontend + start server (foreground) | | `npm run web:dev` | Frontend Vite dev server (HMR, port 5173) | | `npm run web:build` | Build frontend into `dist/web/` | **Per-package (used by the publish script):** ```bash cd packages/server && npm run build # server only (includes embedded MCP) cd packages/opencode-plugin && npm run build # opencode-plugin only ``` **Publish to npm** (requires `$NPM_TOKEN` in your env or `~/.npmrc`): ```bash node scripts/publish.mjs --dry-run # inspect tarball contents node scripts/publish.mjs --publish # actually publish (server -> opencode-plugin order) ``` > Frontend unit tests live in `web/`: `cd web && npm test`. ### Quality gate After making changes, verify: ```bash npm test # all pass npm run typecheck # 0 errors npm run build # succeeds ``` --- ## FAQ **Q: Where is the data stored?** A: A SQLite file. See `storage.path` in `memweave.config.jsonc`; defaults to `/memweave.db`. **Q: Can it run without an external LLM / Embedding service?** A: Yes. Three fallback paths, in order of cost: 1. **Fully local + hash vectors** — `embedding.provider: "noop"` (default). No external service. When `embedding.dimensions: 0` the server skips the vector layer entirely; retrieval falls back to BM25 + graph + causal. 2. **Fully local + real embeddings** — `embedding.provider: "local-xenova"` + `npm install @xenova/transformers`. On the first call, the model weights (~30MB) are pulled from the Hugging Face Hub and cached under `node_modules/@xenova/transformers/.cache/`. If the package is missing or model loading fails, the provider **automatically degrades** to hash-based vectors and emits a one-time `console.warn`. 3. **External API** — `embedding.provider: "openai-compatible"`, against any OpenAI-compatible `/v1/embeddings` endpoint. **Q: Port already in use?** A: Change `server.port` in `memweave.config.jsonc`. **Q: How do I wipe all data?** A: Stop the service → remove the directory pointed to by `dataDir` → re-run `init`. **Q: Web UI returns 503?** A: The server can't find `dist/web/`. Run `npm run web:build`. --- ## Roadmap - [x] **Local ONNX embeddings** — implemented `LocalXenovaEmbeddingProvider` (built on `@xenova/transformers`, dynamic import + automatic noop fallback) - [ ] Multi-provider embedding adapters (OpenAI / Voyage / more local models) - [ ] Federation / sync protocol (device-to-device E2E-encrypted sync) - [ ] Automatic knowledge-graph extraction - [ ] "Right to be forgotten" (GDPR compliance) --- ## License No open-source license declared yet. Contact the author before use. --- ## Acknowledgements - [Fastify](https://fastify.io/) — high-performance HTTP server - [node:sqlite](https://nodejs.org/api/sqlite.html) — Node built-in SQLite (C-backed, no compile) - [@xenova/transformers](https://github.com/xenova/transformers.js) — local ONNX embeddings (prebuilt binaries) - [Ollama](https://ollama.com/) — local LLM runtime - [Model Context Protocol](https://modelcontextprotocol.io/) — agent tool-calling standard - [Vite](https://vitejs.dev/) + [React](https://react.dev/) — frontend