mori
Mori (森) is a shared memory layer for AI coding agents — one that compounds. Sessions feed a dream pipeline that distils activity into durable knowledge, so every instance starts informed rather than cold. One Mori, many agents — every session benefits from what every other session learned.
Works with any OpenAI-compatible provider. No homelab, no Anthropic account, no LLM Gateway required — though those all work too.
Why use mori?
You're right to be sceptical of "memory systems" — most are a vector DB with a
retrieval prompt bolted on, and you already have a CLAUDE.md (or .cursorrules)
that works. Keep it. Mori doesn't replace that file; it's the layer above it.
CLAUDE.mdis your unconditional floor — static facts you hand-edit, always present, that never change: commands, conventions, hard rules.Mori is the compounding layer — the decisions, patterns, and institutional knowledge that accumulate as you work. A dream pipeline distils each session into curated, tiered, freshness-checked memories, so the next session — on any machine, any agent — starts from what was actually learned, not a cold prompt.
The rule: if it never changes, it belongs in CLAUDE.md; if it compounds, it
belongs in mori. Complementary, not competing — the static floor and the layer
that grows above it. (the full distinction →)
And it's yours: self-hosted (your server, your data), open-source (AGPL-3.0), and provider-agnostic. No data leaves your infrastructure.
Related MCP server: GrantAi
Multi-Instance Coherence
If you run AI coding agents across multiple machines, profiles, or in a team — one focused on the API layer, another on the frontend, a third on infrastructure — you already know the problem: each instance is brilliant in isolation, but none of them know what the others decided.
Instance B doesn't know that Instance A just changed the auth contract. Instance C doesn't know that Instance B's deployment assumptions shifted. They find out the hard way, mid-task, when something breaks.
Mori solves this. Every coding agent instance sends its session events to the shared Mori
server. The dream pipeline distils those events from all instances into a
unified memory store. At the start of any session, /brief surfaces what the
other instances have been doing. From turn one, each instance knows what the
others know.
Quickstart
1. Deploy your server
Every Mori instance is yours — deployed into your own account, never shared. Pick a path:
Cloud — deploy into your own account:
Platform | Persistence | ~Cost | |
✅ free Postgres | ~$5/mo + $0 Postgres | ||
Render (persistent disk in config) | ✅ SQLite on disk | ~$7/mo | |
✅ free Postgres | Pay-per-use | ||
GitHub Codespaces — evaluate Mori with no local setup | ⚠️ ephemeral | free tier |
Fly.io (CLI): free persistent volume + SQLite, ~$3–5/mo — see one-click-deploy.md.
Persistence note: SQLite needs a persistent disk or volume; stateless platforms (Railway, Cloud Run, Render free tier) lose data on restart without Postgres. The deploy script and guide walk through connecting a free Neon or Supabase database — the recommended $0 durable path. Codespaces are ephemeral by design — use them to evaluate Mori, then deploy to a persistent host when you're ready.
Full guide: docs/getting-started/one-click-deploy.md
Or run locally with Docker Compose:
git clone https://github.com/fjwood69/mori.git
cd mori
cp deploy/homelab/.env.example deploy/homelab/.env
# Edit .env: set MORI_API_KEY to your provider key (Novita, DeepInfra, OpenAI, …)
# and MORI_BASE_URL to the provider's OpenAI-compatible endpoint.
docker compose -f deploy/homelab/docker-compose.yml up -d2. Verify
curl http://localhost:8968/health
# {"status":"ok","service":"mori-advisor"}3. Connect your agent
Claude Code — install as a plugin (recommended). Inside Claude Code, run:
/plugin marketplace add fjwood69/mori
/plugin install mori@moriYou'll be prompted for your Mori server URL and API key on enable (the key is stored
in your OS keychain, not in settings.json). Then /reload-plugins or restart.
The same plugin package (plugins/mori/) also targets Codex, Cursor, and
Google Antigravity — MCP connection and skills work across all four; client-specific
hooks land per platform. See the platform guides.
Or use the legacy installer scripts (bespoke; superseded by the plugin):
./scripts/legacy/install-mori-claude.sh # Claude Code
./scripts/install-mori-cursor.sh # Cursor
powershell -File scripts/legacy/install-mori-claude.ps1 # WindowsPlatform guides
Platform | Install | Full guide |
Claude Code | Plugin: | |
Codex | Plugin package | |
Cursor | Plugin package | |
Google Antigravity IDE | Plugin package | |
Cline |
|
Capabilities
Capability | What it does | Slash command |
Dream pipeline | Auto-distils session events into structured memories |
|
Session grounding | Loads shared context at session start — not per-query RAG; lightweight delta re-grounding after context compaction |
|
Memory search | Ranked full-text search and browse across the shared store (SQLite FTS5 / Postgres |
|
Web dashboard | Built-in memory browser served at the mori root URL — search, browse, unfurl | — |
Universal ingestion | Feed PDFs, images, git, transcripts into the memory store |
|
Strategic review | LLM guidance with focus areas and auto-injected standards |
|
Requirements tracking | Lightweight project checklist surfaced via |
|
Governance | Capability-scoped API keys (read/write/dreamer roles), versioning, trusted dreamers, rollback, attribution | — |
Curation queue | Ingestion's canonical/standard proposals await trusted-dreamer sign-off in a review UI ( | — |
One-click deploy | Stand up your own server on Render / Railway / Fly / Cloud Run (or free managed Postgres + any stateless host) | — |
NATS messaging | Real-time cross-device awareness |
|
Inter-agent messaging | Send tasks, questions, and decisions across the device network |
|
Skill deployment | Push slash commands to all devices in one step |
|
Full reference: docs/reference/slash-commands.md
Pairs well with
Mori is your team's earned memory — not a docs cache. It remembers what your agents decided and learned across sessions and devices. It complements tools that supply live external knowledge:
Context7 — up-to-date, version-specific library and framework documentation injected into the prompt. Where Mori remembers "we chose X, and why", Context7 supplies "here is X's current API." Different layer, complementary purpose.
Your platform's own docs — for fast-moving tool and harness behaviour (hook schemas, config formats), consult the current official docs rather than training-data recall. See the Read the current manual, not your memory practice in agent-working-practices.
How it works
Dream pipeline
Session events are captured via agent lifecycle hooks (Claude Code, Cursor, Antigravity) and distilled into structured memories by a configurable LLM.
Hook fires → POST /api/events/raw → events table (SQLite/Postgres)
↓
PreCompact → POST /api/precompact → dream_run() reads since watermark
↓
LLM distills events → structured memories
↓
memories written to store (with attribution)
↓
watermark advancedThe PreCompact hook triggers an immediate synchronous dream before context
compression — so nothing is lost at the moment it matters most.
Its counterpart works after compression: a SessionStart hook fires when the
session resumes post-compaction (source: "compact") and runs /brief --post-compact
— a lightweight delta that surfaces only what changed in the shared store since
your last brief (new, superseded, and evicted memories), skipping the full base
reload and the freshness scan. PreCompact preserves what this session learned;
SessionStart re-grounds it on what every other instance changed while it was busy.
What it captures: PostToolUse, PostToolUseFailure, PreCompact,
UserPromptSubmit, Stop — tool calls, prompts, errors, stop reasons,
session ID, hostname, working directory, transcript path, and (on Stop)
the assistant's own reasoning — the plans, analysis, and decisions behind
each turn.
Memory store
Memories live in the store — SQLite (memories.db) for solo/sync deployments,
Postgres for team/async — with three tiers:
Backend requirement — SQLite is the base mode, Postgres is mandatory for anything meaningful. SQLite is the zero-config default for a single user on one machine. For a team, multiple machines/agents, or any concurrent-writer workload, Postgres is mandatory — SQLite's file-level locking serialises writes and cannot sustain it. Some capabilities are Postgres-only by design (e.g. the autonomous-agent intake / governance pipeline): they require concurrent writers and the async store, and are simply unavailable on a SQLite backend. We do not engineer every capability for both backends — choose Postgres for production/team use.
Tier | Scope | Lifecycle |
Ephemeral | Session summaries | Auto-expire unless explicitly saved |
Working | Patterns, decisions, project context | Flagged after 30 days without retrieval |
Canonical | Explicitly promoted by a trusted dreamer | Indefinite, freshness-checked via |
Versioning, diff, rollback, attribution, and governance built in. See docs/reference/configuration.md.
Universal ingestion
New team members start cold. /ingest bootstraps the memory store from
existing source material — applying the same distillation pipeline that
powers the dream phase.
# Preview (zero cost, no LLM):
/ingest --source ~/my-project --preview
# Dry-run to validate extraction quality:
/ingest --source ~/my-project --dry-run --focus decisions
# Commit:
/ingest --source ~/my-project --focus all --tier workingSupported: PDF, images/whiteboards (Kimi K2.6 vision), CC transcripts
(.jsonl), git history (--since 30d), text and code.
Works with remote servers: /ingest reads files on the client device and
sends content over the wire — no shared filesystem needed. Works whether
mori-advisor is running locally or on GCE.
Cost guard: --max-cost (default $5.00) aborts before spending. Preview
is always free. SHA256 dedup prevents re-ingesting the same content.
Strategic consultation (/consult)
Ask a question mid-session and get strategic guidance grounded in your actual project context — not generic advice. When a focus area is specified, relevant team standards are automatically pulled from the memory store and injected alongside your question. The advisor checks against your own baseline, not a textbook.
# Architecture review with file context:
/consult "should we move auth to a separate service?" --focus architecture
# Security review against your team's own baseline:
/consult "review this handler" --focus security --file src/auth.py
# Chain tool output directly into the advisor:
/consult "review this" --focus security --file src/auth.py --file snyk-report.jsonFocus areas: general, architecture, security, performance, style
Depth levels: quick (fast scan), balanced (default), deep (thorough)
Standards-aware: set MORI_STANDARDS_DIR to a directory of .md files
and Mori imports them as protected memories. /consult --focus security
automatically injects your security baseline — your agents check against your
rules, not generic ones.
Inter-agent messaging (/msg)
Delegate tasks, ask questions, and share decisions across your Claude Code
instances — without a shared session. Messages are typed, reply-threaded, and
picked up at the next /brief. The mori-msg daemon receives messages
server-side: decision messages are written directly to the memory store
without any human session on the receiving end.
# From UX3405, delegate a task to the NUC:
/msg send workstation task "Refactor auth middleware — extract rate limiting into its own module"
# NUC picks it up at next /brief and acks:
/msg ack a3f9c2b1 "on it"
# Back on UX3405, check the reply:
/msg inbox
# NUC marks it done when finished:
/msg done a3f9c2b1Message types: task, decision, question, reply, ack, done, broadcast
Requires the mori-msg daemon running alongside mori-advisor (included in
the default pod stack). See docs/reference/msg.md for full reference.
Web dashboard
Not everyone who needs the shared memory runs a Claude Code session. Mori serves a built-in memory browser at its own root URL — just open the server in a browser:
http://<your-mori-host>:8968/Enter any valid API key (the same MORI_API_KEYS your clients use) and you can search,
browse, and click any card to unfurl its full body and provenance (origin clients, tier,
retrieval count, freshness). The page is served same-origin, so it talks to the very
mori instance it loaded from — no base URL to configure, no separate server to run. It's a
single dependency-free file (vanilla JS, no build step, no CDN), backed by a small read
REST API:
Route | Returns |
| Ranked full-text (or recency) list — lean shape, no body |
| One memory in full — body + provenance (lazy-loaded on unfurl) |
| Session event log, newest first |
The dashboard and its routes are read-only and API-key gated (X-Api-Key); write
actions (delete, trusted-dreamer review) are deferred until the read surface is validated.
The page is also available standalone (dashboard/index.html) if you'd rather host it
elsewhere and point it at a mori instance — set MORI_CORS_ORIGINS for that cross-origin
case (it's unnecessary for the built-in same-origin serving).
Architecture
Configuration
Configuration reference → docs/reference/configuration.md Recommended models → docs/reference/models.md For teams → docs/for-teams.md Team configuration reference → docs/reference/team-configuration.md
Key environment variables:
Variable | Default | Description |
|
|
|
| — | Provider key (required in |
| — | OpenAI-compatible base URL |
|
| Advisor + consult model |
| falls back to | Dream + ingest distillation model |
|
| Contradiction scan + freshness checks |
| — | Named client API keys: |
| — | Comma-separated trusted hostnames |
|
| Dream cron interval (minutes) |
| — | Path to team standards |
|
| Spawn headless Claude for incoming tasks |
| — | Comma-separated hostnames allowed to trigger headless CC |
Authentication: Set MORI_API_KEYS to give each client a named key. Without it the server starts in open mode (fine for private Tailscale networks; always set keys for shared or internet-accessible deployments). Generate secrets with python3 -c "import secrets; print(secrets.token_hex(32))". Full details: docs/reference/configuration.md → Authentication.
Building
git clone https://github.com/fjwood69/mori.git
cd mori
podman build -t localhost/mori-advisor:latest .
# Or: docker build -t mori-advisor:latest .License
AGPL-3.0 — see LICENSE. Commercial licences available — see COMMERCIAL.md.
This server cannot be installed
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/fjwood69/mori'
If you have feedback or need assistance with the MCP directory API, please join our Discord server