memory_list
List every saved memory with its type and one-line description. Start here to see what is known.
type
io.github.fainirPublished by GitHub account fainirv0.3.0Updated Nov 1, 2026
Read and write Claude Code auto memory from Codex, Cursor or any MCP client. Zero dependencies.
Shares Claude Code's per-project Markdown memory with other MCP agents, letting an assistant list, read, link-follow, write and delete those memories.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
[CI] [License: MIT] [npm] [fainir/recall MCP server] [Mentioned in Awesome MCP Servers]
Your Claude Code memory, in every agent. recall reads and writes the memory Claude Code keeps for each project, so Codex, Cursor or an agent you build yourself can use the same memories, over MCP or from code. Zero dependencies, no vectors, no database: the memories stay plain Markdown files.
Claude Code now remembers things on its own: your corrections, how you like to work, project decisions, where things live. It saves them as Markdown files with [[wiki-links]] under ~/.claude/projects/<project>/memory/. That is a good format, but only Claude Code reads it. Switch to another agent and it starts from zero.
recall makes that memory portable. It finds the same directory Claude Code uses (same rules, down to its folder-naming hash), reads every file Claude Code writes, and writes files Claude Code reads back.
Point any MCP client at recall and the project's repository. --read-only lets the other agent read what Claude Code remembers without changing it; leave it off to let both write.
Codex
Cursor (.cursor/mcp.json in the project, or ~/.cursor/mcp.json)
Cline: in the MCP Servers panel choose Configure, and add the same recall entry as for Cursor to cline_mcp_settings.json. Or ask Cline to "set up the MCP server from https://github.com/fainir/recall": in a test on 2026-11-01 it read this README, added the entry, started the server and listed its tools.
Gemini CLI: gemini extensions install https://github.com/fainir/recall (it serves the memory of the folder you start Gemini in).
Any other MCP client: run npx -y @fainir/recall with the same arguments as a stdio server. Needs Node.js 18+.
The agent then has these tools. Here is a real run against a repository with three memories Claude Code wrote:
memory_recall followed the [[reference_ci]] link on its own. In testing, a Codex agent given only this server answered a question by calling memory_list and then memory_get.
recall-mcp options: --claude-code [repo] (the default, using the current directory), --dir <dir> for any other memory directory (add --format claude-code to write Claude Code's file format there), --read-only, and --allow-secrets. RECALL_DIR, RECALL_READ_ONLY=1 and RECALL_ALLOW_SECRETS=1 work as environment variables.
Output (before the write):
write() produces the file Claude Code itself writes:
and adds a line to MEMORY.md, the index Claude Code loads at the start of every session, leaving the existing lines alone:
Rewriting an existing memory keeps the fields recall does not own, such as Claude Code's originSessionId.
claudeCodeMemoryDir(repo) returns the directory, using Claude Code's rules:
a-z, A-Z and 0-9 turned into -. Paths longer than 200 characters are cut and given the same hash suffix Claude Code adds.CLAUDE_CONFIG_DIR replaces ~/.claude. CLAUDE_CODE_PROJECT_DIR_NAME (next to CLAUDE_CONFIG_DIR) names the folder. An autoMemoryDirectory setting in the project's .claude/settings.local.json or your ~/.claude/settings.json wins over both.This was checked against a real ~/.claude/projects folder: the rule reproduced 40 of 41 project folder names, including all three long, hashed ones (the other one belonged to a session that was moved after it started). recall listed and parsed all 194 memory files in it.
The package exports the Recall class and claudeCodeMemoryDir(). Every method is async.
A Memory is { name, type, description, updated_at, frontmatter, body, links }. type and updated_at come from the flat fields or from Claude Code's metadata: block, whichever the file has. links lists the memory names the body links to, deduplicated and in order.
write, get and delete throw on an unsafe name; write also throws on an invalid type or decay_class, a non-string body or description, or a reserved extra key. recall never throws on unknown names; it lists them in missing.
One file per memory, <name>.md, with frontmatter and a Markdown body. recall reads both shapes, whichever format you pick for writing.
Claude Code's format (format: 'claude-code'; older Claude Code files have a flat type: instead of metadata:, and recall reads those too):
recall's own format (format: 'recall', the default, which earlier versions wrote):
a-z, 0-9, - and _, starting with a letter or digit, up to 128 characters. That keeps file names safe on every OS.[[name]], [[name|label]] and [[name#heading]] all point at name. They are case-insensitive, - and _ match each other, and links inside code are ignored.key: value lines, quoted strings, # comments, and one level of nesting (Claude Code's metadata: block).MEMORY.md, README.md, My Notes.md, folders) are not memories and are skipped.recall() picks the slicerequires. No embeddings, no fuzzy search.[[wiki-links]] from those, breadth-first, up to link_depth hops.budget_tokens (estimated as characters / 4), memories are dropped until it fits: the deepest links first, so the required memories go last; at the same depth, ephemeral first, then fast, slow, permanent. Their names come back in dropped, and the rest keep their walk order.For an agent that knows what it needs, explicit keys beat similarity search: asking for "voice" should return the voice memory, not four memories that mention the word.
decay_class says how often a memory should be re-confirmed. dueForReview() returns the ones whose last update (Claude Code's modified, or recall's updated_at) is older than their window. Nothing is deleted automatically.
--read-only and point it only at projects you are happy to share.[redacted]: passwords in connection URLs, bearer tokens, private key blocks, and Anthropic, OpenAI, GitHub, Slack, AWS, Google and Stripe keys, plus JWTs, and says how many it hid. The files on disk are not changed. --allow-secrets turns this off. It is a safety net for known formats, not a guarantee: keep secrets out of memories.MEMORY.md at the start of a session, so a memory another agent writes shows up in Claude Code's next session, not the current one. Claude Code loads only the first 200 lines (or 25 KB) of that index.No dependencies, so there is nothing to install:
/goal for every turn: sends Claude Code back when it stops earlySource: README.md at commit af62c9e
List every saved memory with its type and one-line description. Start here to see what is known.
typeRead one memory in full. Names match file names; "-" and "_" are interchangeable.
namerequiredRead the named memories plus the memories they link to with [[wiki-links]], trimmed to a token budget. Unknown names are reported as missing instead of failing.
requiresrequiredlink_depthbudget_tokensList memories old enough that they should be re-confirmed with the person before being relied on.
as_ofSave a memory, or replace the one with the same name. One fact per memory. Save only what a future session could not work out from the code or git history. Never save secrets. Link related memories in the body with [[name]]. user: who the person is and how they like to work. feedback: corrections and confirmed approaches. project: ongoing work, decisions and deadlines not in the code. reference: where to find things outside the project.
bodyrequirednamerequiredtyperequireddecay_classdescriptionrequiredDelete a memory that turned out to be wrong or obsolete. Exact name only.
namerequired90% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
codex mcp add recall -- npx -y @fainir/recall --claude-code /path/to/your/repo --read-only{ "mcpServers": { "recall": { "type": "stdio", "command": "npx", "args": ["-y", "@fainir/recall", "--claude-code", "/path/to/your/repo", "--read-only"] } }}> memory_list3 memories in /Users/you/.claude/projects/-Users-you-code-acme-api/memory:- feedback_testing (feedback) - run the integration suite before saying a change works- reference_ci (reference) - where CI runs and how to rerun a flaky job- user_role (user) - backend lead, prefers short answers with the command to run
> memory_recall {"requires": ["feedback_testing"]}## feedback_testing (feedback) - run the integration suite before saying a change worksRun `npm run test:int` (needs the local Postgres from docker compose), not just `npm test`.**Why:** the unit tests mock the database; two "done" changes broke prod queries.**How to apply:** any change under src/db/ or src/queries/. CI details in [[reference_ci]].
## reference_ci (reference) - where CI runs and how to rerun a flaky jobCI is GitHub Actions, workflow `ci.yml`. Rerun a flaky job with `gh run rerun --failed`.
tokens_used: 180npm install @fainir/recallimport { Recall } from '@fainir/recall';
const memory = Recall.forClaudeCode('/Users/you/code/acme-api');console.log(memory.dir);
for (const m of await memory.list()) console.log(m.name, '|', m.type, '|', m.description);
const slice = await memory.recall({ requires: ['feedback-testing'] });console.log(slice.memories.map(m => m.name), slice.tokens_used);
// Save something Claude Code will see in its next session.await memory.write({ name: 'project_freeze', type: 'project', description: 'merge freeze until the 3rd for the mobile release', body: 'No merges to main until Nov 3. **Why:** mobile release cut.',});/Users/you/.claude/projects/-Users-you-code-acme-api/memoryfeedback_testing | feedback | run the integration suite before saying a change worksreference_ci | reference | where CI runs and how to rerun a flaky jobuser_role | user | backend lead, prefers short answers with the command to run[ 'feedback_testing', 'reference_ci' ] 180---name: project_freezedescription: merge freeze until the 3rd for the mobile releasemetadata: node_type: memory type: project modified: 2026-10-27T17:51:14.486Z---
No merges to main until Nov 3. **Why:** mobile release cut.- [Testing](feedback_testing.md) - run the integration suite before saying a change works- [CI](reference_ci.md) - where CI runs and how to rerun a flaky job- [Role](user_role.md) - backend lead, prefers short answers- [project_freeze](project_freeze.md) - merge freeze until the 3rd for the mobile release---name: feedback_testingdescription: run the integration suite before saying a change worksmetadata: node_type: memory type: feedback modified: 2026-10-20T09:12:44.120Z---
Run `npm run test:int` first. CI details in [[reference_ci]].---name: top-customerstype: projectdescription: paying customers above $10K ACVdecay_class: slowupdated_at: 2026-05-25---- Northwind - $48K ACV (see [[northwind-account]])git clone https://github.com/fainir/recall.gitcd recallnpm test # node:test, no networknode examples/basic.js # the library on a plain recall directory