memory-lean

Long-term memory for AI coding agents that doesn't burn the context window. A drop-in replacement for the reference memory server with about 40x smaller answers. One file, zero dependencies.

Documentation

memory-lean icon

memory-lean

Long-term memory for AI coding agents that doesn't burn the context window.

npm version npm downloads tests zero dependencies node 18 or newer MIT license

Quick start · What the agent sees · Why it stays lean · Tools · Agent protocol · Settings · Contributing


memory-lean is an MCP server that gives Claude Code, Claude Desktop, Cursor and any other MCP client a knowledge graph that persists between sessions. It is a drop-in replacement for the reference memory server (@modelcontextprotocol/server-memory): same memory.jsonl file, same nine tool names, plus two extras. What changes is how much the tools send back.

Call, on a real graph of 237 entitiesReference servermemory-lean
read_graph~77,800 tokens~2,000 tokens40× smaller
search_nodes (average of 5 common words)~31,000 tokens~770 tokens40× smaller

One file. No dependencies. Nothing to build.

Quick start

Claude Code: install the plugin. It adds the server, a skill with the agent instructions, and a short reminder at the start of each session.

/plugin marketplace add zamansheikh/memory-lean
/plugin install memory-lean@memory-lean

Any other agent: add the server to the agent's MCP config, then give the agent the instructions.

{
  "mcpServers": {
    "memory": { "command": "npx", "args": ["-y", "memory-lean"] }
  }
}
npx -y memory-lean --protocol >> AGENTS.md   # into the rules file your agent reads

The config file and its exact shape differ per agent.

Copy-paste setup for each agent is in docs/SETUP.md:

AgentServer configInstructions
Claude Codepluginincluded in the plugin
Xiaomi MiMo Codemimocode.jsoncskill or AGENTS.md
opencodeopencode.jsonAGENTS.md
OpenAI Codex CLIcodex mcp addAGENTS.md
Cursor.cursor/mcp.jsonAGENTS.md or a rule
VS Code (Copilot).vscode/mcp.jsoncopilot-instructions.md
Gemini CLIsettings.jsonGEMINI.md
Windsurfmcp_config.jsona rule
Clinecline_mcp_settings.json.clinerules/
Zedsettings.jsonAGENTS.md or .rules
JetBrains IDEsAI Assistant settingsa rule or guidelines
Claude Desktopclaude_desktop_config.jsonproject instructions

The graph is created on the first write at ~/.claude/memory-graph/memory.jsonl, whichever agent writes to it, so several agents can share one memory. Set MEMORY_FILE_PATH to keep it somewhere else.

Run from a clone instead of npm
git clone https://github.com/zamansheikh/memory-lean.git
claude mcp add --scope user memory -- node /absolute/path/to/memory-lean/server/memory-lean.mjs

No npm install is needed.

What the agent sees

The reference server answers a search with every matching entity in full, as pretty-printed JSON. memory-lean answers with a ranked list of names and the lines that matched:

> search_nodes { "query": "deploy" }

57 match "deploy", top 10 shown (narrow the query or raise limit). open_nodes for full entities.
- shop-backend [service] 12 obs, 6 rel
    › 2026-03-02: deployed 2.4.0 to production
    › deploy with scripts/release.sh, never by hand
- PENDING shop-backend 2.4.0 [pending] 2 obs, 3 rel
    › …mobile apps still call the old endpoint until the deploy of 2.4.0 reaches them

The agent then opens only what it needs:

> open_nodes { "names": ["shop-backend"] }

## shop-backend [service]
- NestJS API behind api.example.com
- 2026-03-02: deployed 2.4.0 to production

## relations
shop-app -talks_to-> shop-backend
PENDING shop-backend 2.4.0 -blocks-> shop-app

That is the whole pattern: search, then open.

Why it stays lean

A knowledge graph is only useful if the agent can afford to look at it, and a graph that every session appends to grows without limit. memory-lean limits both what it returns and what it stores.

LimitWhat it means
Small answerssearch_nodes returns at most 10 names with snippets, read_graph returns an index of names, and only open_nodes returns full entities.
Short factsAn observation longer than 300 characters is rejected, with a message telling the agent to split it or put the detail in the repo.
A cap per entityAn entity keeps 15 observations. Past that, the oldest dated ones move to archive/<entity>.md next to the graph. Nothing is deleted: the agent can list and restore them, and undated observations (the identity facts) always stay.
Multi-word search that worksEvery word must match somewhere in the entity, so adding a word narrows the result. The reference server looks for the query as one exact phrase.

And it is careful with the file:

SafeguardWhat it means
Safe to shareWriters take a lock file, so several agent sessions can use one graph without overwriting each other. Every write replaces the file atomically.
Daily backupsA copy goes to backups/ once a day; the last 7 are kept.
Damaged lines are keptA line that cannot be read is moved to memory.jsonl.unreadable on the next write and reported, never silently dropped.
Plain filesThe graph is JSON lines, archives are Markdown, backups are copies. You can read, grep and edit all of it by hand.

Measure it on your own graph

From a clone of this repo:

node tools/bench.mjs                  # read_graph + your five most common words
node tools/bench.mjs deploy "api v2"  # your own queries

It is read-only and prints sizes, never content. Tokens are estimated as characters ÷ 4. A narrow search that matches one or two entities saves much less, because there was little to trim.

Tools

ToolWhat it returns
search_nodesRanked list of entity names with counts and up to two matching snippets each. Every word must match the name, type, an observation, or the type of a relation touching the entity.
open_nodesThe full entities you name, as compact text, with every relation touching them. Unknown names come back with "did you mean" suggestions.
read_graphAn index: entity names grouped by type, with observation counts. Never the observations.
create_entitiesCreates entities; existing names are skipped.
create_relationsCreates relations between existing entities; duplicates are skipped.
add_observationsAdds facts to an entity, enforcing the length limit and the per-entity cap.
rename_entityRenames an entity, keeping its observations, relations and archive. Not in the reference server.
archived_observationsLists what was archived for an entity, optionally filtered, and can restore chosen observations. Not in the reference server.
delete_observationsRemoves observations by exact text.
delete_relationsRemoves specific relations.
delete_entitiesRemoves entities and every relation touching them.

The three read tools are marked read-only, so clients that support it can run them without asking.

Teach your agent to use it

A memory server only helps if the agent reads it before working and writes to it when something changes. docs/AGENT-PROTOCOL.md is a ready-made set of instructions: what to look up at the start of a task, what to record, how to name things, and what never to store. The Claude Code plugin includes it. For every other agent, one command installs it:

npx -y memory-lean --protocol >> AGENTS.md     # into a rules file: always on
npx -y memory-lean --skill .agents/skills      # as an Agent Skill: loaded when relevant

Adjust the entity types and names in it to your own work.

Coming from the reference memory server

Point MEMORY_FILE_PATH at your existing memory.jsonl and swap the command. The file format is identical, so you can switch back at any time. Existing observations longer than 300 characters are kept as they are; only new writes are checked.

To see what in an existing graph is over budget, and optionally fix it:

npx -y memory-lean --lint      # report only
npx -y memory-lean --compact   # back up, then move overflow to archive/

Settings

All optional, set as environment variables on the server:

VariableDefaultMeaning
MEMORY_FILE_PATH~/.claude/memory-graph/memory.jsonlWhere the graph lives
MEMORY_OBS_MAX_CHARS300Longest observation accepted
MEMORY_OBS_MAX15Observations per entity before the oldest dated ones are archived
MEMORY_SEARCH_LIMIT10Default number of search results
MEMORY_BACKUPS_KEPT7Daily backups kept

Good to know

  • Your graph is private. It holds whatever your agent learned about your projects. Keep it out of git, and never store passwords, keys or tokens in it: record where a secret lives, not its value.
  • Search is plain text matching, not embeddings. Good entity names matter more than clever queries.

Roadmap

  • A Claude Code plugin that installs the server and the agent protocol together
  • Ready-made setup for MiMo Code, Codex, Cursor and other agents
  • Setup guides for Cline, Zed and JetBrains IDEs
  • Windows in the CI matrix
  • rename_entity, keeping relations intact
  • A way to list and restore archived observations
  • Listings in the MCP registry and the Claude Code plugin directory
  • Search across archived observations of every entity

Contributing

Ideas, bug reports and pull requests are welcome. The whole server is one file with no dependencies, and npm test runs in about a second, so a first change is quick to make. CONTRIBUTING.md has the layout, the ground rules and a list of good first contributions.

If you try memory-lean on your own graph, the output of tools/bench.mjs makes a useful issue post. And if it saves you tokens, a ⭐ helps other people find it.

Support

memory-lean is free and MIT licensed. If it is useful to you, you can support the work:

Buy Me a Coffee Ko-fi

Author

Created and maintained by Zaman Sheikh at Silifton.

GitHub X LinkedIn Website

Built on the file format and tool names of the Model Context Protocol reference memory server.

License

MIT © 2026 Zaman Sheikh. Free to use, change and share, including commercially; keep the copyright notice.