Open source · Self-hosted · Free forever

Stop living the same session twice

A self-hosted MCP server that gives your AI agent persistent memory across sessions, projects, and machines. Everything runs on your own hardware and, yes, it's free.

claude · recall
$ claude
claude> recall("markdown editor preferences")
→ merged from 4 namespaces, re-ranked
[preference] you prefer Typora for long-form
[knowledge] Obsidian 1.6 adds live preview
[project] repo ships docs as .mdx
[graveyard] abandoned: remark pipeline (effort 4/5)
claude>
Install OmniMem
curl -fsSL https://code.squarecows.com/ric/omnimem/raw/branch/main/install.sh | bash

Paste that into your terminal, or if you'd rather do it by hand, follow the manual setup below.

Model-agnostic

Works with the tools you already use

If it speaks MCP, it works. One memory layer for every agent you run, on hardware you own. Each tile links to its setup guide.

Read the setup guides
The problem

Every session starts from zero

Your AI agent doesn't know your project. It doesn't remember what failed last week. It has no idea you spent three hours last Tuesday figuring out why onnxruntime crashes on Alpine, only to find something that actually works.

So you explain everything again. It suggests the same broken library again. Same alarm, same song. It's Groundhog Day: you're Bill Murray, and your agent is Punxsutawney.

// without omnimem
claude> use onnxruntime for the embeddings
... 45 minutes of debugging later ...
SIGILL: illegal instruction (Alpine musl libc)
You fixed this exact problem last Tuesday.
Claude doesn't know that.
// with omnimem
claude> use onnxruntime for the embeddings
⚠ WARNING: previously abandoned approach
onnxruntime: SIGILL crash on Alpine musl libc (effort 4/5)
→ switched to sentence-transformers instead
See it in action

One recall() pulls context from everywhere

Personal preferences, ingested articles, past conversations, project context. It all gets ranked together and merged into one properly useful answer.

claude · recall
› what tools do we know about that are useful for writing markdown in?
● omnimem · recall (MCP) (query: "markdown editors and writing tools", top_k: 10)
└ {"result":[{"namespace":"knowledge","content":"Announcing Autosave & More…","score":0.334,"state":"active"}, …
… +70 lines (ctrl+o to expand)
● From memory, here's what we know about markdown writing tools:
You actively use:
- Vim: your go-to editor for everything, including markdown preference
- Apostrophe: a GNOME markdown editor you wrote a PiSource article about episodic
From the self-hosted / FOSS knowledge base:
- Ghost (MIT, Node.js): markdown blogging platform you wrote about
- WriteFreely (AGPL-3.0, Go): federated markdown blogging
- BookStack (MIT, PHP): wiki with markdown support knowledge
- Wiki.js (AGPL-3.0, Node.js): wiki with markdown editor
- Docmost (AGPL-3.0, Docker): Confluence alternative
CMS with markdown support:
- Sveltia CMS and DecapCMS: both work with Forgejo/Gitea backendsproject
That's the lot, pulled from your preferences, your articles, a repo you trained it on, and your project's own stack, all ranked together.
› nope that's great, you reminded me of exactly what I use
● Glad it worked well. OmniMem connected your preferences and past writing into one useful answer.
A real recall() about markdown editors. Every tagged line traces back to a different memory source (they're the four on the right).
[episodic]
Episodic memory

Picked up from your conversations: decisions, bugs, what you tried, and the things you mention in passing.

[knowledge]
Knowledge base

RSS articles, auto-summarised and embedded. They surface when relevant to what you're asking.

[preference]
Preferences

How you like to work, stated once and applied from then on: the editor you reach for, the licence you prefer, the way you want things written.

[project]
Project context

Extra context it knows matters to you, like your preferred tools and platforms.

What makes it different

Not just a key-value store with an MCP wrapper

OmniMem models how memory actually works. Things fade over time, they sometimes contradict each other, and the hard-won stuff earns its place.

The graveyard

Every dead end, kept on purpose

What you tried, why it failed, and how much time it burned. Your agent checks the graveyard before it reaches for a library or a pattern, so the same rabbit hole only costs you once.

A warning comes back with the way out attached: what was abandoned, and what worked instead.

warn_if_abandoned("global limiter")
✗ abandoned · effort 4 · 6 tries
→ use one limiter per shard instead
recall()
A recall query returning ranked memories in the terminal
One call. Ranked by similarity, lifecycle, age and what it cost you to learn.
48
MCP tools

Remember, recall, audit, compile. One server, every client that speaks MCP.

1.8×
Battle-hardened

Four attempts and a weird workaround? That is gold. The harder it was, the higher it surfaces.

Four namespaces

Searched together, never muddled

Decisions and bugs, stack and state, articles and extracted facts, and how you like to work. Compiled skills sit alongside them.

episodicprojectknowledgepreference
One-call briefing

No three-step warm-up

One briefing() hands over project context, experience stats, stale memories, new articles and contradictions.

score = similarity × surface × recency × experience
Integrity

Contradiction detection

If a new memory disagrees with one you already have, OmniMem catches it on write, and Claude can dig deeper on demand.

Deduplication

Semantic, not string

Too close to something stored? You get a heads-up, not a duplicate. find_duplicates cleans up in bulk.

Dashboard

A web UI for all of it

Browse, search and manage memories, feeds, project contexts and backups without touching the command line.

Telemetry

Know what earns its keep

Recall counts and last-accessed per memory, plus a Prometheus /metrics endpoint for Grafana.

Auto-maintenance

Tidies itself

Every few briefings it scans for duplicates and checks for conflicts in the background. No babysitting.

Lifecycle

Memory is not binary

Most systems either remember or delete. OmniMem has a proper lifecycle. When you say "forget about X" you usually mean stop bringing it up, not wipe it from existence.

ACTIVE
1.0× weight
→
DEPRIORITISED
0.2× weight
→
ARCHIVED
0.0× weight
→
DELETED
gone

Deprioritised memories aren't gone for good. Attach reinstate hints, and if a future query matches, the memory comes back with a note explaining why it was pushed down. You can mute entire topics across all sessions.

// final ranking
score = similarity × surface_score × recency × experience_weight

Four factors decide what comes back. Semantic similarity on its own isn't enough, so lifecycle state, age, and how hard something was to figure out all play a part.

Effort
Meaning
Weight
1
Worked first time
1.0×
2
Minor friction
1.1×
3
Multiple iterations
1.25×
4
Significant struggle
1.5×
5
Battle-hardened
1.8×
Skills

Skills that build (and evolve) themselves

Memories tell an agent what happened. A skill tells it how you work. OmniMem compiles skills from the work you actually did: the breakthroughs, the gotchas that keep coming back, and the graveyard of dead ends. As new experience lands, the skill evolves with it.

A PATTERN EARNS A RULE

One-off episodes don't compile. A lesson has to recur before it becomes policy, unless you bless it to jump the queue.

NOTHING WRITES SILENTLY

Every compile proposes a diff you can review. Rewrites of existing rules get flagged loudly, and nothing commits until you say so.

DERIVED, NEVER HAND-EDITED

Memories are the source of truth and the skill is just build output. Want different guidance? Update the memories and recompile.

SUGGESTED, NEVER AUTO-LOADED

The briefing recommends relevant skills for the session. You and the agent decide what loads.

compile_skill("python") distils a domain's accumulated experience into a loadable SKILL.md: do this, watch out for that, and never try X again because it cost you an afternoon. Load it at the start of some Python work and the agent works your way from the very first prompt.

// the flywheel
work → record_experience() → compile_skill() → SKILL.md → work

Every skill tells the agent to keep recording lessons and dead ends whilst it works. A richer pool compiles a better skill next time, and the knowledge watch flags fresh articles that contradict a compiled rule, so your skills stay current.

Full design: the skill compiler

claude · compile_skill
claude> compile_skill("python")
→ 87 memories · 14 reinforced lessons · 3 dead ends
+ do pin deps with uv lock before builds
+ avoid gather() without return_exceptions
+ ref valkey-search HNSW tuning guide
~ watch new article may contradict rule #7
→ proposed diff, nothing written until you accept
claude> compile_skill("python", mode="write")
✓ SKILL.md committed · every rule cites its memories
How it compares

Most memory servers just store and retrieve

Claude Code's built-in memory (CLAUDE.md, plus the newer auto-memory that writes markdown notes for itself) is still flat, machine-local files with keyword recall. No semantic search, no lifecycle, no contradiction handling. OmniMem goes quite a bit further. mem0 is the other name you'll hear. It's a good product aimed at a different job, a memory layer for products serving many users with a managed cloud behind it, and the table includes the things it does that OmniMem doesn't.

Capability
Claude built-in
mem0
<OmniMem>
Semantic vector search
No
Yes, plus keyword
Yes
Memory lifecycle states
No
Partial, expiry only
Yes, 4 states
Abandoned approach warnings
No
No
Yes, graveyard
Experience scoring
No
No
Yes, effort 1-5
Compiled skills
Partial, hand-written
No
Yes, from experience
Contradiction detection
No
Yes, resolved on write
Yes, 2-tier
Semantic deduplication
No
Yes, on write
Yes, write + batch
Topic suppression
No
No
Yes
RSS knowledge ingestion
No
No
Yes, auto-summarised
Reinstate hints
No
No
Yes
Self-hosted / no SaaS
Partial, local files
Yes, OSS or cloud
Yes, Docker
Multi-machine sync
No
Yes, cloud or REST
Yes, via proxy
Web dashboard
No
Yes, cloud or OpenMemory
Yes, htmx
Telemetry / Prometheus
No
Partial, cloud events
Yes, /metrics
Auto-maintenance
No
Yes, cloud only
Yes, on briefing
LLM fact extraction on write
No
Yes, required
Yes, optional Haiku
Keyword and entity retrieval
Partial, keyword only
Yes, BM25 and graph
No
Multimodal memories
No
Yes, image, audio, video
No
Multi-user and multi-tenant
No
Yes, users and orgs
Partial, projects only
Per-memory version history
No
Yes
No
Per-memory expiry
No
Yes
Partial, articles only
Webhooks
No
Yes, cloud only
No
SDKs and REST API
No
Yes, Python, JS, REST
No, MCP only
Managed cloud option
No
Yes
No, by design
Runs offline, no API key
Yes
Yes, with Ollama
Yes, local ONNX

A green box with a tick matches or beats OmniMem on that row, and ~ marks a partial one. A black box in the OmniMem column is a straight no where another system has it.

Architecture

Four containers. Nothing leaves your machine.

Local embeddings, self-hosted, all in Docker. The MCP server and the web UI both talk straight to Valkey and share the same memory package, so there's no duplicated logic to drift apart.

AI agent
any machine · SSE/MCP
Browser
HTTP :8080
↓           ↓
MCP Server
Python fastmcp
remember · recall · briefing
record_experience · compile_skill
health
Web UI
Starlette · htmx · Jinja2
Dashboard · Search · Skills
Projects · Duplicates · Backups
↓           ↓
Valkey + search
idx:episodic
idx:project
idx:knowledge
idx:preference
idx:skill
RSS Worker
feedparser
APScheduler
Claude Haiku
// recall pipeline
→ query
→ abandoned fast-path (keyword scan)
→ embed query
→ vector search, top 20 / namespace
→ filter archived + deleted
→ filter suppressed topics
→ apply surface_score
→ apply recency decay (90d)
→ apply experience_weight
→ check reinstate eligibility
→ surface contradiction warnings
→ merge, re-rank, return top_k
→ log event + increment counters
Get started

Up and running in two minutes

You'll need Docker and Docker Compose, plus git to clone the repo. Nothing else: no Python, no Valkey, no models to fetch by hand. It all runs in containers on your own machine.

01

Clone and configure

Pick a strong Valkey password (please don't use "password"). If you want RSS summaries and smarter contradiction detection, add your Anthropic API key too.

bash
# clone the repo
git clone https://code.squarecows.com/ric/omnimem.git
cd omnimem
cp .env.example .env
# edit .env: set VALKEY_PASSWORD and ANTHROPIC_API_KEY
02

Start the containers

Spins up four containers: Valkey with vector search, the MCP server, the RSS worker, and the web UI dashboard.

bash
docker compose up -d
# Web UI at http://localhost:8080
03

Connect Claude Code

Point Claude Code at OmniMem in your MCP config, then drop the included CLAUDE.md into your project.

~/.claude.json or .mcp.json
{
  "mcpServers": {
    "omnimem": {
      "type": "sse",
      "url": "http://localhost:8765/sse"
    }
  }
}
Pro tip

OmniMem's instructions are injected automatically when the MCP server connects. To customise how Claude uses OmniMem across all projects, add your own overrides to ~/.claude/CLAUDE.md.

View on Squarecows →