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
[episodic] 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 episodic
- Apostrophe: a GNOME markdown editor you wrote a PiSource article about knowledge
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 external
- Wiki.js (AGPL-3.0, Node.js): wiki with markdown editor
- Docmost (AGPL-3.0, Docker): Confluence alternative
CMS with markdown support: project
- Sveltia CMS and DecapCMS: both work with Forgejo/Gitea backends
That's the lot, pulled from your conversations, your articles, a repo you trained it on, and your Forgejo preference, 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: preferences, decisions, 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.

[external]
External references

Links and posts you've shared: GitHub threads, blog posts, anything worth hanging onto.

[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.

01 · graveyard

The Graveyard

Every dead end gets logged: what you tried, why it failed, and how much time you burned on it. Your agent checks the graveyard before it suggests a library or pattern, so you don't go down the same rabbit hole twice.

02 · scoring

Experience scoring

Something that took four attempts and a weird platform workaround to crack? That's gold. The harder it was, the more prominently it surfaces next time.

03 · integrity

Contradiction detection

If a new memory disagrees with something you've already stored, OmniMem catches it. There's a quick check on every write, and if you want a proper look, Claude can dig deeper on demand.

04 · dedup

Semantic deduplication

New memories get compared against what's there. Too similar? You get a heads-up instead of a duplicate. Run find_duplicates to clean up in bulk.

05 · namespaces

Four namespaces

Episodic for decisions and bugs. Project for stack and state. Knowledge for RSS articles and extracted facts. Preferences for how you like to work. All searched together, with compiled skills alongside.

06 · briefing

One-call briefing

One briefing() and your agent gets project context, experience stats, stale memories, new articles, and contradictions. No three-step warm-up.

07 · dashboard

Web UI dashboard

Browse, search, and manage your memories from an htmx web interface. RSS feeds, project contexts, backups and memory details, all without touching the command line.

08 · telemetry

Telemetry & metrics

Every recall tracks which memories get used. Recall counts and last-accessed per memory, plus a Prometheus /metrics endpoint for Grafana.

09 · maintenance

Auto-maintenance

Every few briefings, OmniMem quietly scans for duplicates and runs a heuristic contradiction check in the background. Stale duplicates get archived and conflicts get flagged, no babysitting required.

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 matches or beats OmniMem on that row. 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 · deprioritise
record_experience · briefing · health
Web UI
Starlette · htmx · Jinja2
Dashboard · Search · Browse
Projects · Duplicates · Backups
↓           ↓
Valkey + search
idx:episodic
idx:project
idx:knowledge
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

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 →