[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80343":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":41,"readmeContent":42,"aiSummary":43,"trendingCount":15,"starSnapshotCount":15,"syncStatus":16,"lastSyncTime":44,"discoverSource":45},80343,"continuum","pouyahasanamreji\u002Fcontinuum","pouyahasanamreji","Shared memory + orchestration for your coding agents — one MCP server, persistent vector memory, agent registry","",null,"TypeScript",74,14,21,0,2,3,8,6,3.53,false,"main",true,[25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40],"agent-memory","agent-orchestration","ai-agents","astro","claude","claude-code","codex","mcp","model-context-protocol","multi-agent","nestjs","nodejs","rag","sqlite-vec","typescript","vector-database","2026-06-12 02:04:01","\u003Cdiv align=\"center\">\n\n\u003Cimg src=\"docs\u002Fassets\u002Fcontinuum.png\" alt=\"Continuum\" width=\"640\" \u002F>\n\n### **Shared memory + orchestration for your coding agents.**\n\nOne MCP server. Tell any client to read the plot — it becomes the orchestrator. \u003Cbr\u002F>\nDispatches fresh agents in isolated worktrees, shares lessons across every Claude Code \u002F Codex \u002F Cline chat on the project.\n\n[![Node](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fnode-%3E%3D22.12.0-brightgreen?style=for-the-badge)](package.json)\n[![pnpm](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpnpm-10.33-orange?style=for-the-badge)](package.json)\n[![NestJS](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FNestJS-11-red?style=for-the-badge&logo=nestjs)](https:\u002F\u002Fnestjs.com)\n[![Astro](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FAstro-6-purple?style=for-the-badge&logo=astro)](https:\u002F\u002Fastro.build)\n[![sqlite-vec](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fsqlite--vec-RAG-blue?style=for-the-badge&logo=sqlite)](https:\u002F\u002Fgithub.com\u002Fasg017\u002Fsqlite-vec)\n[![MCP](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FMCP-Streamable_HTTP-black?style=for-the-badge)](https:\u002F\u002Fmodelcontextprotocol.io)\n\n[Quick Start](#quick-start) • [Memory & Vectors](#memory--vectors) • [Workflow](#the-workflow) • [MCP Tools](#mcp-tools) • [Wire It In](#wire-it-into-your-ai-client) • [Configuration](#configuration)\n\n![Two Claude Code chats sharing memory through Continuum — left reads the plot and dispatches, right runs the work and updates status](docs\u002Fassets\u002Fhero-two-chats.png)\n\n\u003C\u002Fdiv>\n\n---\n\n> **Your agents forget. Continuum remembers.**\n>\n> Point any MCP client at Continuum and tell it to read the plot. The client becomes an orchestrator — it researches the codebase, verifies the plan, persists a dispatch record, and hands you a ready-to-paste prompt for a fresh agent in an isolated git worktree. Every other Claude Code \u002F Codex \u002F Cline chat on the project sees what's reserved, shares what's been learned, and never re-explains the codebase. One local server: vector knowledge base, orchestration protocol, agent registry — shared across every MCP-speaking app on your machine.\n\n```mermaid\nflowchart TD\n    CC[\"Claude Code\"]\n    CX[\"Codex\"]\n    CL[\"Cline\"]\n    YOU[\"YOU\"]\n\n    subgraph CONTINUUM[\"CONTINUUM ORCHESTRATOR\"]\n        direction LR\n        PLOT[\"PLOT.md\u003Cbr\u002F>protocol\"]\n        KNOW[\"KNOWLEDGE\u003Cbr\u002F>(vectorized)\"]\n        AGENTS[\"AGENTS\u003Cbr\u002F>registry\"]\n        PANEL[\"WEB PANEL\u003Cbr\u002F>(humans)\"]\n    end\n\n    DB[(\"SQLite + sqlite-vec\u003Cbr\u002F>one file, your disk\")]\n\n    CC -- MCP --> CONTINUUM\n    CX -- MCP --> CONTINUUM\n    CL -- MCP --> CONTINUUM\n    YOU -- HTTP --> CONTINUUM\n    CONTINUUM --> DB\n```\n\n> **No SaaS. No telemetry. No keys to manage.** Boots in seconds. Survives reboots. Scales with you.\n\n---\n\n## What you get\n\n|  | |\n|---|---|\n| 🧠 **Vectorized memory** | Every lesson your agents learn becomes a 768-dim embedding indexed in `sqlite-vec`. Recall is semantic, fuzzy, and instant — no exact-match games. |\n| 🔍 **RAG-native search** | `knowledge_search({q: \"how do we handle webhook retries?\"})` returns ranked metadata (slug + kind + agentSlug + timestamps); follow up with `knowledge_get({slug})` for the body. Metadata first keeps top-K context cheap; only fetch what's worth reading. |\n| 🗺️ **Canonical workflow** | Every project gets a PLOT.md seeded with a 4-phase dispatch protocol — Intake → Research → Verify → Handoff. Stop re-explaining your process. |\n| 🤖 **Multi-agent registry** | State machine + reserved-path tracking stops parallel agents from clobbering each other across git worktrees. |\n| 📚 **Two-tier knowledge** | `fundamental` lessons are binding rules loaded on every dispatch. `situational` lessons surface via semantic search when relevant. |\n| 🖥️ **Human web panel** | Astro + React UI to browse projects, agents, plot, and knowledge while AI clients drive everything via MCP. |\n| 🔌 **Client-agnostic** | Standard MCP \u002F Streamable HTTP. Works with Claude Code, Codex, Cline, Cursor, or anything that speaks the protocol. |\n| 🔒 **Local-first** | One SQLite file. WAL mode. No cloud. Optional embedder is your call (Ollama, TEI, anything OpenAI-shaped). |\n| 📦 **One container in prod** | Single image, one HTTP port, one mounted volume. Drop on any host, point your MCP clients at it. |\n\n---\n\n## Why Continuum exists\n\n| Without Continuum | With Continuum |\n|---|---|\n| Session ends → context gone. | Lessons persist as embedded vectors. Recall survives reboots, models, and clients. |\n| You re-explain conventions every session. | `knowledge_search` ranks lessons by relevance; `knowledge_get` pulls the body when needed. |\n| Two parallel agents edit the same file. | `reserved_paths` + status state machine surfaces collisions before dispatch. |\n| Each new task improvises orchestration. | PLOT.md protocol seeded into every project — Intake → Research → Verify → Handoff. |\n| \"What did Claude do last week?\" | `registry_list` paginates dispatch metadata (slug, status, branch, reserved paths). `agent_get({slug})` pulls the full record. |\n| Knowledge scattered across chat logs. | One SQLite database. One vector index. One source of truth. |\n\n---\n\n## Quick start\n\n### 🐳 The easy path — one Docker command\n\n```bash\ndocker compose -f docker-compose.dev.yml up\n```\n\nThat's it. The whole stack comes up with hot reload, a SQLite browser, and a single shared volume — no Node, no pnpm, no native-build dance on your host machine.\n\nWhat you get:\n\n| Service | URL | What it is |\n|---|---|---|\n| **api** | http:\u002F\u002Flocalhost:6685 | NestJS + MCP server. Swagger at `\u002Fdocs`. Hot-reloaded on file change. |\n| **web** | http:\u002F\u002Flocalhost:6680 | Astro + React panel. Hot-reloaded. |\n| **sqlite-web** | http:\u002F\u002Flocalhost:6667 | Browser UI for the live SQLite database — inspect projects, agents, knowledge, vectors. Loads `sqlite-vec` automatically. |\n| **embedder** (optional) | http:\u002F\u002Flocalhost:8080 | Hugging Face TEI running an HTTP embedder. Off by default. |\n\nThe API embeds in-process by default (`Snowflake\u002Fsnowflake-arctic-embed-m-v1.5` via Transformers.js, 768-dim, ONNX q8). No external service required for semantic search. Override via `EMBEDDER_URL` to point at any HTTP-based embedder (Ollama, TEI, OpenAI-compatible). Turn the bundled TEI container on with the `embedder` profile:\n\n```bash\nHF_TOKEN=hf_xxx docker compose -f docker-compose.dev.yml --profile embedder up\n```\n\nBind mounts keep the source tree on your host — edits are instant. Named volumes hold `node_modules` so installs survive restarts. Database lives at `.\u002F.local-data\u002Fdev-orchestrator.db` on your host, gitignored, safe to wipe.\n\nStop everything:\n\n```bash\ndocker compose -f docker-compose.dev.yml down            # keep data\ndocker compose -f docker-compose.dev.yml down -v         # nuke volumes too\n```\n\n### 🛠️ Or run on bare metal\n\n```bash\npnpm install\npnpm dev\n```\n\n| | |\n|---|---|\n| API + MCP | http:\u002F\u002Flocalhost:7776 (Swagger at `\u002Fdocs`) |\n| Web panel | http:\u002F\u002Flocalhost:7777 |\n\nDev SQLite at `.\u002F.local-data\u002Forchestrator.db`. Gitignored. Wipe to reset — next boot recreates and migrates forward.\n\nRequires Node `>=22.12.0` and pnpm `10.33+`. The compose path skips both.\n\n---\n\n## Memory & vectors\n\nThis is the headline. Continuum's knowledge layer is what makes your agents stop being amnesiac.\n\n### How a lesson becomes memory\n\n```\nagent finishes a dispatch\n        │\n        ▼\nknowledge_create({\n  project, agentSlug, slug,\n  content: \"When wiring rate-limit guards in Nest,\n            register them in app.module.ts AFTER\n            the auth guard, not before. Order matters.\",\n  kind: 'situational'\n})\n        │\n        ▼\ncontent → embedder (in-process by default, or Ollama \u002F TEI \u002F OpenAI-compatible)\n        │       Snowflake Arctic Embed v1.5 → 768-dim vector\n        ▼\nSQLite row + sqlite-vec index entry\n        │       freshness profile = (URL, model, dim)\n        ▼\nforever queryable by ANY future agent on this project\n```\n\n### How recall works\n\nPhase 1 of every dispatch (the orchestrator does this automatically):\n\n```\nknowledge_list({ project, kind: 'fundamental' })\n  └─ returns metadata for every binding lesson — slug + agentSlug + timestamps.\nknowledge_get({ project, slug })  \u002F\u002F for each fundamental slug\n  └─ full body — base branch, worktree convention, no-AI-attribution, etc.\n\nknowledge_search({ project, q: \"rate limit middleware nest interceptor order\" })\n  └─ vector similarity over your prose\n  └─ returns top-K ranked metadata (no content)\n  └─ does NOT need exact wording — natural language works\nknowledge_get({ project, slug })  \u002F\u002F for each relevant hit\n  └─ pulls the full lesson body\n```\n\nSearch and list return metadata only — slug + kind + agentSlug + timestamps. Call `knowledge_get` for the body of any lesson worth reading. Keeps top-K context cheap; the orchestrator triages first, fetches second.\n\nThe result: the agent that's about to plan your task already knows what your last five agents learned the hard way. No prompt engineering. No \"here's our convention\" copy-paste.\n\n### Two kinds of knowledge\n\n| Kind | Loaded when | Use for |\n|---|---|---|\n| `fundamental` | Every dispatch, unconditionally | Project-wide rules: base branch, worktree naming, commit conventions, append-only files |\n| `situational` | Only if semantically relevant to the task | Specific gotchas: \"auth guard ordering,\" \"regen artifact merge strategy,\" \"Stripe webhook idempotency keys\" |\n\n### The freshness profile\n\nVectors are pinned to a `(EMBEDDER_URL, EMBEDDER_MODEL, EMBEDDER_DIM)` triple. Change any one and Continuum marks stale vectors for rebuild on next boot. You stay in control of which embedder owns your memory — local Ollama, self-hosted TEI, or anything OpenAI-shaped.\n\n### Pluggable embedders\n\nThe embedder is required and runs in-process by default (`Snowflake\u002Fsnowflake-arctic-embed-m-v1.5`, 768-dim, ONNX q8). The model weights are bundled in the API image — no extra container, no extra config, semantic search works out of the box.\n\nOverride via `EMBEDDER_URL` to delegate embedding to an HTTP service:\n\n```bash\n# Option A — Ollama (simplest, fully local)\nollama pull \u003Cembedding-model>\n# EMBEDDER_URL=http:\u002F\u002F127.0.0.1:11434\u002Fapi\u002Fembed\n# EMBEDDER_MODEL=\u003Cembedding-model>   EMBEDDER_DIM=768\n\n# Option B — Hugging Face TEI (production-grade, batched)\nHF_TOKEN=hf_xxx docker compose -f docker-compose.dev.yml --profile embedder up embedder\n# EMBEDDER_URL=http:\u002F\u002F127.0.0.1:8080\u002Fv1\u002Fembeddings\n# EMBEDDER_MODEL=\u003Crepo-id>   EMBEDDER_DIM=768\n\n# Option C — anything OpenAI-compatible \u002Fv1\u002Fembeddings\n# Works out of the box. Match the dim.\n```\n\n### Built on `sqlite-vec`\n\nThe vector index lives in the same SQLite file as your projects, agents, and plot. One file. One backup. One restore. No separate vector DB to provision, no Pinecone bill, no Chroma daemon to babysit. WAL mode keeps reads concurrent with writes; foreign keys keep your registry consistent; `busy_timeout = 5000` keeps things calm under contention.\n\n---\n\n## Wire it into your AI client\n\n### Claude Code\n\n```jsonc\n\u002F\u002F ~\u002F.claude.json  →  mcpServers\n{\n  \"mcpServers\": {\n    \"continuum\": {\n      \"transport\": \"streamable-http\",\n      \"url\": \"http:\u002F\u002F127.0.0.1:7776\u002Fmcp\"\n    }\n  }\n}\n```\n\nRestart Claude Code. Tools appear under `mcp__continuum__*`.\n\n### Codex\n\n```toml\n# ~\u002F.codex\u002Fconfig.toml\n[mcp_servers.continuum]\ntransport = \"streamable-http\"\nurl = \"http:\u002F\u002F127.0.0.1:7776\u002Fmcp\"\n```\n\n### Anything else (Cline, Cursor, custom)\n\nPoint any MCP-compatible client at `http:\u002F\u002F127.0.0.1:7776\u002Fmcp`. Streamable HTTP, stateful sessions (UUID-keyed). Server name `continuum`.\n\n---\n\n## Your first project\n\nInside any wired client:\n\n```\nCreate a Continuum project for \u002Fabsolute\u002Fpath\u002Fto\u002Fmy\u002Frepo,\nthen read the PLOT.md and act as orchestrator\nfor the following task: \u003Cdescribe what you want done>.\n```\n\nWhat happens:\n\n1. Client calls `project_create({project: \"\u002Fabsolute\u002Fpath\u002F...\"})`\n2. Server seeds PLOT.md (the orchestration protocol) and an empty knowledge base\n3. Client calls `plot({project})`, reads the protocol, enters orchestrator mode\n4. Client follows the 4-phase workflow — researches, verifies, persists a dispatch record, hands you a ready-to-paste prompt for a fresh agent in a git worktree\n\nYou paste the prompt into a new Claude Code \u002F Codex session. That agent codes inside an isolated worktree against its reserved paths. Other parallel agents see the new agent's reservations via the coordination brief.\n\nWhen work merges, the orchestrator records what was learned via `knowledge_create` — and **every future dispatch on this project benefits from it forever**.\n\n---\n\n## The workflow\n\n### 1. Intake\n\n```\nregistry_list({project, status:'active'})     \u002F\u002F paginated metadata: slug + reservedPaths + timestamps\nagent_get({project, slug})                    \u002F\u002F bodies (request\u002Fplan\u002FimplPrompt\u002FcoordinationBrief) per active agent\nknowledge_list({project, kind:'fundamental'}) \u002F\u002F binding-rule metadata\nknowledge_get({project, slug})                \u002F\u002F body per fundamental slug — read every one\nknowledge_search({project, q: \"\u003Ctask intent>\"}) \u002F\u002F RAG → ranked metadata\nknowledge_get({project, slug})                \u002F\u002F body for each relevant hit\n```\n\n### 2. Research\n\nSpawn an `Explore` \u002F `Plan` subagent. It reads the codebase against the loaded knowledge. Produces a file-by-file plan: create \u002F modify \u002F delete. **Plan only — no code.**\n\n### 3. Verify\n\nSpawn a critique agent. It challenges every file touched, looks for orphans and broken call sites, cross-checks against active agents' reserved paths. Returns annotated deltas.\n\n### 4. Handoff\n\n```\nagent_create({\n  project, slug, branch, worktree,\n  reservedPaths,        \u002F\u002F paths this agent owns\n  request,              \u002F\u002F verbatim human task\n  plan,                 \u002F\u002F final agreed plan\n  implPrompt,           \u002F\u002F self-contained prompt for the dispatched agent\n  coordinationBrief,    \u002F\u002F short block for every other active agent\n})\n```\n\nAgent lands as `draft`. Promote with `agent_update({status:'active'})` when you dispatch. On merge, record the SHA and bank the lesson:\n\n```\nagent_update({ project, slug, status:'merged', mergedCommit, postMergeNotes })\nknowledge_create({ project, agentSlug, slug, content, kind:'situational' })\n```\n\nThe orchestrator never edits source, runs regen, merges branches, or pushes commits. It researches, verifies, coordinates, and persists. Code lives in fresh agents inside isolated worktrees.\n\n---\n\n## MCP tools\n\nEvery tool takes `project` (canonical absolute path) as its first argument.\n\n### Project\n\n| Tool | Purpose |\n|---|---|\n| `project_list` | Enumerate registered projects |\n| `project_get` | Fetch one project |\n| `project_create` | Register project, seed PLOT.md + knowledge |\n| `project_rename` | Rename a project |\n| `project_delete` | Cascade delete (project + agents + lessons) |\n\n### Plot — the orchestration protocol\n\n| Tool | Purpose |\n|---|---|\n| `plot` | Read PLOT.md |\n| `plot_update` | Apply a unified git-format diff (zero fuzz, exact context match) |\n\n`plot_update` validates `--- a\u002FPLOT.md` \u002F `+++ b\u002FPLOT.md` \u002F `@@` headers strictly. Context mismatch throws `hunk_mismatch` with the failing hunk header. Re-read with `plot`, regenerate the diff, retry. No silent overwrites.\n\n### Knowledge — the vector memory\n\n| Tool | Purpose |\n|---|---|\n| `knowledge_list` | Lesson metadata (slug, kind, agentSlug, timestamps). Optional `kind` filter. **No content.** |\n| `knowledge_search` | Semantic query → ranked metadata. `q` free-text intent, optional `kind`, optional `limit`. **No content.** |\n| `knowledge_get` | Read one lesson by slug — full body |\n| `knowledge_create` | Record a new lesson — `kind: 'fundamental' \\| 'situational'`. Embedded automatically. |\n| `knowledge_update` | Replace lesson content. Re-embeds on save. |\n| `knowledge_delete` | Retire a lesson |\n\n`knowledge_search` runs vector lookup over the `sqlite-vec` index. Pass natural prose — questions, task statements, descriptions all work. SQL wildcard syntax does not. Response is ranked metadata; call `knowledge_get({project, slug})` for the body of any hit worth reading. Same pattern for `knowledge_list` (use `kind: 'fundamental'` to enumerate the binding set, then get each).\n\n### Agents\n\n| Tool | Purpose |\n|---|---|\n| `registry_list` | Paginated agent metadata — `{data, page, limit, hasNextPage}`. Each `data` row: slug, status, branch, worktree, reservedPaths, timestamps, mergedCommit, abandonedReason. Optional `status` filter; default `limit` 10, max 50. **No artifact bodies.** |\n| `agent_get` | Full record by slug — includes request, plan, implPrompt, coordinationBrief, postMergeNotes |\n| `agent_create` | Persist a draft dispatch record |\n| `agent_update` | Transition status, edit fields |\n\nAllowed transitions: `draft → active → merged | abandoned`. `merged` requires a 7–40 char commit SHA. `abandoned` requires a reason. Only `active` agents reserve paths.\n\n`registry_list` returns the collision matrix metadata in one paginated envelope. To inspect a dispatch's plan or implPrompt, follow with `agent_get({project, slug})`. Page through with `page` until `hasNextPage` is false.\n\n---\n\n## Example session\n\n```\nhuman: orchestrate adding rate-limit middleware to \u002Fapi routes\n\nclaude: → registry_list({project, status:'active'})  \u002F\u002F 0 active\n        → knowledge_list({project, kind:'fundamental'})\n                                              \u002F\u002F metadata for binding rules\n        → knowledge_get({project, slug:'base-branch'})       \u002F\u002F → main\n        → knowledge_get({project, slug:'worktree-convention'}) \u002F\u002F → ..\u002F\u003Cslug>\u002F\n        → knowledge_search({project, q:'rate limit middleware nest interceptor'})\n                                              \u002F\u002F ✨ 2 ranked hits on guard ordering (metadata)\n        → knowledge_get({project, slug:'rate-limit-guard-ordering'}) \u002F\u002F bodies fetched\n        → spawn Plan subagent → plan returned\n        → spawn critique subagent → 1 issue: missed `app.module.ts` registration → fixed\n        → agent_create({\n            slug: 'rate-limit-middleware',\n            branch: 'feature\u002Frate-limit',\n            worktree: '\u002Fabs\u002Fpath\u002F..\u002Frate-limit-middleware',\n            reservedPaths: ['apps\u002Fapi\u002Fsrc\u002Fcommon\u002Frate-limit\u002F**', 'apps\u002Fapi\u002Fsrc\u002Fapp.module.ts'],\n            request: 'orchestrate adding rate-limit middleware to \u002Fapi routes',\n            plan: '...',\n            implPrompt: '...',\n            coordinationBrief: 'reserves common\u002Frate-limit\u002F**, edits app.module.ts (additive)'\n          })\n        → here's the impl prompt to paste into a fresh session: ...\n\n[ task ships ]\n\nclaude: → agent_update({slug:'rate-limit-middleware', status:'merged', mergedCommit:'a1b2c3d'})\n        → knowledge_create({\n            agentSlug: 'rate-limit-middleware',\n            slug: 'rate-limit-guard-ordering',\n            kind: 'situational',\n            content: 'Rate-limit guards must register AFTER auth guard in app.module.ts.\n                      Order in providers array decides execution order. Reverse → 401s\n                      bypass rate limiting.'\n          })\n        \u002F\u002F ✅ lesson embedded → vector indexed → permanent memory\n```\n\nNext time anyone — you, Claude, Codex — touches anything rate-limit-shaped on this project, that lesson surfaces automatically.\n\n---\n\n## Web panel\n\n![Agents registry — slug, status, branch, reserved-path count, timestamps](docs\u002Fassets\u002Fpanel-agents.png)\n\n![Knowledge browser — a fundamental lesson opened, metadata + content](docs\u002Fassets\u002Fpanel-knowledge.png)\n\nAstro 6 + React 19 islands. Tailwind v4. shadcn\u002Fui.\n\n| Page | What |\n|---|---|\n| `\u002F` | Landing |\n| `\u002Fprojects` | Projects list — TanStack Table, sortable, filterable |\n| `\u002Fagents` | Registry \u002F status board across projects |\n| `\u002Fknowledge` | Markdown viewer — GFM, syntax highlight, anchored sections, search |\n| `\u002Fplot` | Plot viewer + editor with diff preview |\n| `\u002Fsettings` | Embedder URL + model + dim, tokenizer key, REST gate, log level |\n\nSettings stored in `app_settings` (SQLite) override env vars. Headless deploys still work via env alone.\n\n---\n\n## Configuration\n\nBoth env vars and panel settings supported. Panel takes precedence.\n\n| Var | Default | Purpose |\n|---|---|---|\n| `PORT` | `7776` | HTTP port |\n| `CORS_ORIGIN` | _unset_ | `*` or comma-separated origins |\n| `ORCHESTRATOR_DB_PATH` | `\u002Fdata\u002Forchestrator.db` | SQLite path. Dev scripts override to `.\u002F.local-data\u002Forchestrator.db` |\n| `PANEL_REST_ENABLED` | `false` | Mount `\u002Fapi\u002Forchestrator\u002F*` REST surface (panel uses it) |\n| `NODE_ENV` | _unset_ | Production blocks destructive migrations |\n| `ORCHESTRATOR_ALLOW_DESTRUCTIVE_MIGRATE` | _unset_ | Set `1` to override in production |\n| `ANTHROPIC_API_KEY` | _unset_ | Token-count endpoints (server-side only) |\n| `ANTHROPIC_TOKENIZER_MODEL` | `claude-opus-4-7` | Model name for `count_tokens` |\n| `EMBEDDER_URL` | _unset_ | HTTP embedding endpoint (Ollama \u002F TEI \u002F OpenAI-compatible). Unset → in-process embedder |\n| `EMBEDDER_MODEL` | `Snowflake\u002Fsnowflake-arctic-embed-m-v1.5` | Model id (in-process default; passed through to HTTP embedder when configured) |\n| `EMBEDDER_DIM` | `768` | Expected embedding dimension |\n\n---\n\n## Stack\n\n| Layer | Tech |\n|---|---|\n| **Memory** | `sqlite-vec` vector index • Snowflake Arctic Embed v1.5 in-process via Transformers.js (default) • Ollama \u002F TEI \u002F OpenAI-compatible embedders via `EMBEDDER_URL` • freshness-pinned vectors |\n| API | NestJS 11 • `@rekog\u002Fmcp-nest` • `@modelcontextprotocol\u002Fsdk` 1.10 • Zod 4 • Swagger |\n| Persistence | `better-sqlite3` (WAL, FK, busy_timeout 5s) |\n| Diff engine | `diff` 9 (zero-fuzz unified-diff applier) |\n| Web | Astro 6 • React 19 • Tailwind 4 • shadcn\u002Fui • TanStack Table • rehype\u002Fremark • highlight.js |\n| Tooling | Turborepo 2 • pnpm 10.33 • TypeScript 5.9 • Prettier 3 • Jest |\n\n---\n\n## Scripts\n\n```bash\npnpm dev          # turbo run dev — api + web in watch\npnpm build        # turbo run build\npnpm lint         # turbo run lint\npnpm check-types  # turbo run check-types\npnpm format       # prettier across ts\u002Ftsx\u002Fjs\u002Fastro\u002Fmd\u002Fjson\n\npnpm -F @continuum\u002Fapi dev          # api only — nest start --watch\npnpm -F @continuum\u002Fapi mcp:dev      # api with local SQLite at .local-data\u002F\npnpm -F @continuum\u002Fapi test         # jest unit tests\npnpm -F @continuum\u002Fapi test:e2e     # jest e2e\n\npnpm -F @continuum\u002Fweb dev          # web only — astro dev\npnpm -F @continuum\u002Fweb build        # astro build → dist\u002F\n```\n\n---\n\n## Conventions\n\n- **`project` is always a canonical absolute path.** Pass the project root, never a worktree subdirectory. Worktree paths throw `project_not_found`.\n- **Plot mutations flow through unified diffs.** No full-text writes. Bad context → server rejects with the failing `@@` header.\n- **Knowledge updates are whole-content replace.** Pass the full new `content`. Re-embedded on save.\n- **Reserved paths are JSON arrays of globs.** Only `active` agents reserve.\n- **Migrations are forward-only on boot.** Production blocks destructive migrations unless explicitly opted in.\n\n---\n\n## Troubleshooting\n\n| Symptom | Likely cause |\n|---|---|\n| `project_not_found` | Passing a worktree path. Use the canonical project root registered with `project_create`. |\n| `hunk_mismatch` from `plot_update` | Stale diff. Re-read with `plot`, regenerate against current content, retry. |\n| `knowledge_search` \u002F `knowledge_list` returns empty \u002F weird results | Embedder unreachable, model mismatch, or dim mismatch (search only). Check `\u002Fsettings`. Backfill stale vectors. Remember: both return metadata — call `knowledge_get({project, slug})` for the body. |\n| Vectors not regenerating after embedder swap | Freshness profile (URL + model + dim) must change. Restart server to trigger backfill. |\n| `invalid_transition` from `agent_update` | Allowed: `draft → active → merged \\| abandoned`. Anything else throws. |\n| `missing_merged_commit` \u002F `invalid_merged_commit` | `merged` requires a 7–40 char SHA. |\n| Schema migration refuses in production | Set `ORCHESTRATOR_ALLOW_DESTRUCTIVE_MIGRATE=1` if you really mean it. |\n\n---\n\n## Roadmap\n\n- [ ] Cross-project knowledge sharing (`kind: 'global'`)\n- [ ] Embedding re-rank with a small reranker model\n- [ ] One-shot import of existing CLAUDE.md \u002F AGENTS.md \u002F Cursor rules → fundamentals\n- [ ] Read-only public knowledge mirror (publish a project's lessons as a static site)\n- [ ] Built-in observation hooks for SessionStart \u002F SessionEnd events\n\n---\n\n## Contributing\n\nContributions welcome. Fork, branch, test, PR. Match Prettier defaults (100-col, double quotes, semicolons, ES5 trailing commas). Keep MCP tool changes Zod-typed.\n\n---\n\n## Support\n\n| | |\n|---|---|\n| Issues | GitHub Issues |\n| Docs | this README + Swagger UI at `\u002Fdocs` + the seeded PLOT.md inside each project |\n| MCP spec | https:\u002F\u002Fmodelcontextprotocol.io |\n\n---\n\n\u003Cdiv align=\"center\">\n\n### Stop letting your agents forget.\n\n**`pnpm install && pnpm dev`** — and they never will again.\n\n\u003C\u002Fdiv>\n","Continuum 是一个用于编码代理的共享内存和编排工具，它提供了一个MCP服务器、持久化向量内存和代理注册表。项目的核心功能包括通过`sqlite-vec`实现的向量化记忆存储，支持语义模糊即时检索；以及RAG原生搜索能力，可以快速获取相关知识。该工具适用于需要多个AI代理（如Claude Code, Codex, Cline等）协同工作的开发场景中，能够确保所有代理之间的知识共享与同步，避免重复解释代码库。基于Node.js和NestJS构建，无需SaaS服务或额外密钥管理，启动迅速且易于扩展。","2026-06-11 04:00:25","CREATED_QUERY"]