Shared memory for AI agents, as a graph in your own Postgres. Writes never call an LLM.
Shared memory for AI coding agents. What Claude Code learns, Codex and Cursor can recall — in one graph, on your own machine, with every write auditable.
Apache 2.0. The server makes no LLM call on the write path, so storing a memory adds no inference cost of its own.
Run it yourself — nothing leaves your machine:
pipx install echo-mem
echo-memory quickstart
That starts the database, applies the schema, and prints the claude mcp add command
that registers it with your tools, filled in with the port it actually used. Docker is the only prerequisite; the Postgres image is published, so
nothing is compiled.
Or use the hosted service and run no database at all:
pipx install echo-mem
echo-memory connect <key> # a key from https://api.echo-mem.com
Either way, restart your client afterwards. An MCP server holds the code and config it started with.
Then, once per machine, so the agent knows when to record and recall rather than only that the tools exist:
echo-memory install --global
Every AI agent starts from zero unless something remembers what happened last time, and remembers it well enough and fast enough to still be useful after months or years of accumulated history. Most memory tools solve short-term recall with plain vector search over stored facts. That degrades as history grows: more candidates, more noise, slower retrieval. Echo Memory is built around the read/write algorithm and the data structure that keeps working at long horizons, not just at day one:
docs/designs/echo-memory-design.md
for the actual mechanism.caused_by, led_to,
blocked_by, contradicts, set by the agent's own read of the conversation, not
inferred statistically. Honest about what's tractable today and what isn't.echo-memory why <fact_id>). Memory that consolidates and edits
itself is only trustworthy if you can see why.echo-memory benchmark: write 15ms median, query 8ms, digest 1ms, $0.00 inference
cost per episode. The tradeoff is explicit and worth stating: the agent must arrive
with entities and facts already extracted, which is more work for the caller and the
reason the MCP tool contract spells the shape out. The
comparison that makes this matter is Zep/Graphiti, the closest architectural match
(bi-temporal edges, fact invalidation, episode provenance): its own published
description of ingestion is that "every episode triggers multiple LLM calls for
extraction, entity resolution, and invalidation" and that "write cost scales with
volume". Here it doesn't.Early and staged. See docs/designs/ for the full architecture and the
v1a → v1b build plan. The validated wedge driving v1a is specifically cross-tool coding
agent memory (the founder's own daily pain, real and tested). The broader vision above
is the target this architecture is built toward, not yet something v1a itself proves. v1a
proves basic recall works before v1b adds causal typing and multi-hop graph retrieval, and
before v1.1 adds the org-wide tenancy the broader vision depends on.
quickstart is the short way. If you would rather see every step, or you are working on
Echo Memory itself, docs/DEVELOPMENT.md has the long version:
clone, docker compose up -d, pip install -e ".[dev]", alembic upgrade head, and the
claude mcp add line with its environment.
Wiring a second tool? Give it its own ECHO_MEMORY_AGENT_ID. Cursor should say
cursor, Claude Desktop claude-desktop. Memory is shared either way, but a fact records
which tool learned it, and two tools claiming the same id makes cross-tool recall
impossible to see afterwards. echo-memory adopt wires every MCP client on the machine at
once, each with its own id, and shows the diff before writing anything.
Scoped to one project instead — a single Claude project, a Cursor workspace, a repo whose
memory should not mingle with the rest? echo-memory install [path] writes a
project-scoped MCP config plus a skill (or, for Cursor, an always-applied rule), committed
alongside the code.
See docs/INTEGRATIONS.md for using Echo Memory from an agent
that does not speak MCP — a chatbot, a DevOps agent, or any custom tool-calling loop.
Memory is a graph, not a list of notes. Entities are nodes; a fact is an edge between two of them. That is the whole data model, and everything below follows from it.

Three projects here. checkout-api, mobile-app and data-pipeline were
recorded in separate sessions and never told about each other, yet the picture
already separates them — because separation is a property of the edges, not a
label anyone applied.
Clusters come from structure. Densely connected facts are grouped by label
propagation over the edges, and each cluster is named after its most-connected
node. That is why data-pipeline sits apart on the left: nothing it knows
touches payments. It is also why checkout-api and mobile-app share a cluster
despite being different codebases — they genuinely do share an idea, and the
graph found it rather than being told.
Components are the stronger claim. Two nodes in different components have no path between them at all, which is the strongest statement this graph can make that two memories are unrelated.
Projects are a facet, not the structure. Every fact records the project it was written from, and you can colour by it, but project says where a fact was written, not what it belongs with.

idempotency keys is the concept that joined those two codebases. The panel
shows it referenced from checkout-api twice and mobile-app once, the three
facts it appears in, and how the node itself resolved — each mention matched an
existing node by exact name rather than creating a duplicate.
Nobody wrote "these projects are related." Two sessions independently recorded a fact about idempotency keys, entity resolution matched them to one node, and the relationship exists as a consequence.

This is what a knowledge graph gives you that a code map cannot. Selecting the edge answers, for that single fact:
| what | the sentence, its relation_type, and how confidently it was stated |
| when | when it became valid, and when it was superseded if it has been |
| who | which agent wrote it, in which session |
| where | which project it came from |
| why | the audit trail — created, superseded from what to what, and the entity-resolution rationale for the nodes at either end |
A superseded fact is never deleted. It stops being drawn, because the graph no
longer asserts that relationship, but it stays reachable from its node and keeps
its full history. echo-memory why <fact_id> prints the same trail in a terminal.
echo-memory dashboard --serve --open
The images above come from a synthetic dataset (scripts/demo-seed.py) rather
than a real store, for the obvious reason: a real memory graph is full of
hostnames, account numbers and client names.
pgvector and Apache AGE extensionsnetworkx added in v1b for multi-hop associative retrievalwrite_episode, query_memory, record_recall_save, get_audit_logecho-memory health
A score, what is strong, what needs attention, and what to do about each,
including what recall has cost: how often memory was read, how often a read
returned anything, roughly how many tokens were injected, and how many saves
those reads produced. Writes were counted from the start; reads were not counted
at all, so nothing could answer whether recall earns what it costs. It
exists to be run when you have no question - a store can look healthy by every
number this CLI reports while most of its facts came from a bulk import, the
last real write was a week ago, and only one of several wired agents has ever
written anything. --json for machine-readable output.
Nothing in it is gated. The paid tiers sell hosting and the things that only exist when several people share a graph; diagnostics about your own data are not a thing to withhold from the person whose data it is.
See CONTRIBUTING.md. Issues and PRs welcome; please read the design
docs first so proposals fit the staged build plan. A first pull request is asked to sign
the Contributor License Agreement — once, in the PR thread.
Apache License 2.0. See LICENSE.
mcp-name: io.github.ayushcodes10/echo-mem
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
uvx echo-memMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-ayushcodes10-echo-mem": {
"command": "uvx",
"args": [
"echo-mem"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceecho-mempypiEcho Memory works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.