Memory for your own tools
The optional TypeScript SDK uses scoped MCP calls to save, search and hand off memory. Conditional writes detect concurrent edits. Build it from the repository; it is not published on npm.
Product
Handoffs and search are the daily use. These are the other things a memory that lives in one server can do for you, from passing work between projects to keeping a client’s memory apart from another’s.
Two repositories that talk over an API, each with its own agent and its own memory. The frontend agent knows the protocol. Instead of reading the whole API repository, it writes a complete request and drops it in that project’s inbox.
Project A
send
Inbox, claimed once
Project B
pop
API spec
Untrusted input
No shared context
In the frontend repository
> Ask the agent in default/api to add a /v1/export endpoint that streams NDJSON, keep the existing auth middleware, and send it through ai-memory.
The agent calls memory_message_send with a self-contained body. The request has to stand on its own, because the reader cannot see this project.
Later, in the API repository
📬 ai-memory: 1 cross-project message waiting in this project’s inbox.
> Check my ai-memory inbox.
The agent calls memory_message_pop, gets the request with who sent it, and works from it. A second pop returns nothing.
# Send from the current project
ai-memory message send --to-workspace default --to-project api \
--subject "export endpoint" "Add a /v1/export endpoint that streams NDJSON…"
# In the other project: list without consuming, or claim the oldest
ai-memory message list
ai-memory message pop
# Change your mind before it is claimed
ai-memory message cancel --id <message-id>
A message targets a workspace and project, optionally one registered harness. Only that harness can claim directed mail. The browser can queue and edit a pending message with access to both projects.
The session start notice carries only a count. Message text reaches an agent through a deliberate pop, fenced and marked as untrusted, with the sender shown outside the fence. A project can opt in to the same count-only notice on prompts.
The recipient project must exist, so a typo is rejected instead of landing in an inbox nobody reads. Each inbox holds at most 256 pending messages.
The sender can cancel a message until it is claimed. Secrets are scrubbed on send, the body is size-capped, and on a shared server every message records who sent it.
Memory is filed by workspace and project. A checkout with a git remote is filed by that remote, so the same repository cloned twice shares one memory, and a folder without a remote uses its name. A small file changes the rest.
client-a
client-b
personal
Workspaces
.ai-memory.toml
Mono-repo
Rules
Expires Friday
Feedback
Drop .ai-memory.toml in ~/work/client-a/ and repositories below it use that workspace. This controls where memory is filed and searched by default. It is not an access-control rule: deliberate cross-project searches and shared profiles need separate consideration.
A marker that names a project pins every subdirectory to it, so packages share one memory. Leave the project out and each package keeps its own.
Linked worktrees resolve to the main repository, so a branch checked out elsewhere keeps the same memory.
Actor-aware routing separates callers. Concurrent sessions by one person still need explicit workspace/project arguments or a client that forwards the hook session ID; static MCP configs cannot always distinguish them.
Register each server with ai-memory server add and name it in the marker with server = "team-b". Hooks from that tree go there and nowhere else, and a name that does not resolve sends nothing.
identity = "acme/platform" files a checkout under that key wherever it lives, even with no remote.
# Every repository under this directory files under the client-a workspace
workspace = "client-a"
Tell the agent to remember something permanently and it becomes a page in the wiki. Rules are filed apart from facts, and the session brief can put them in front of the agent before the first prompt.
“Remember: before touching the payment code, read the PCI notes.” The agent writes a durable page. Ask for it as a global rule and it applies to all your projects.
With inject_on_session_start = true in the project marker, the brief starts with pinned pages, rules and slots. Pages that do not fit are listed for memory_read_page. Set inject_on_subagent_start = true separately to give Claude Code subagents the same bounded brief.
When a rule looks durable enough, memory_lint suggests copying it into CLAUDE.md or AGENTS.md. ai-memory never edits those files itself.
The server does not read or write your repository files. Agents and local setup commands can. Keep ADRs in the repository; [capture] ignore_paths reduces tool capture of them, but does not filter prompts or guarantee exclusion.
# Prepend pinned pages, rules and slots to every session
[briefing]
inject_on_session_start = true
A page with expires_at leaves normal search after that date. You can include expired pages in a query until the retention sweep deletes them, even if pinned.
memory_feedback records helpful, not helpful, stale or wrong. Feedback affects retention of eligible session pages; stale and wrong also flag pages for lint. It never changes search ranking or directly deletes a page.
A session captured in the wrong project, after a cd into a scratch directory, can be reattached with ai-memory move-session. Its observations and page move with it.
After a compaction, Claude Code, Codex and Factory Droid receive a short anchor with the session's first and latest prompts instead of the usual startup packet. Every agent also carries a rule to re-read its own prompts and trust them over the summary. reload context still fetches a bounded recap by hand.
The built-in dashboard shows projects, capture health, agent activity and response usage. Its Knowledge tab has page outlines, backlinks, version evidence and search; bundled guides live under /web/docs.
Every page links to its versions, with a diff between any two, and every session opens a timeline of its observations in capture order. Root sees a health page with the hook counters and the fix for anything failing.
Each project is an Open Knowledge Format bundle. ai-memory export-okf packages it for any tool that reads OKF, and the files are plain markdown for everything else.
ai-memory install-mcp also installs a short routing snippet and managed Agent Skills, so the agent knows which tool answers “have we discussed this?” and which sends mail.
ai-memory run starts the agent through the memory server. On a harness switch, it can also pass a private temporary file of visible history from the previous agent on this machine. The path and contents stay local; the file is deleted when the child exits. Without a usable local transcript, the portable ledger and handoff remain.
ai-memory run
Sandbox offer
Self-upgrade
Closes on exit
Web sign-in
ai-memory upgrade downloads the matching release, checks the checksum, swaps the binary and refreshes the hooks. Docker, Homebrew, AUR and RPM installs keep their own path.
ai-memory run --yolo says what it is about to disarm and, on Linux and macOS with ai-jail usable, offers to re-run the session inside the sandbox with a checklist of what the jail may see. --jail goes straight in with sensible defaults.
--env KEY=VALUE and --env-file reach the spawned agent and ai-memory’s own session lookup, so a per-account CLAUDE_CONFIG_DIR needs no wrapper script.
Agents with no session-end hook (Command Code, Kiro CLI, Antigravity CLI) get their summary and handoff when the launcher exits. finalize-session --reopen covers a conversation that went on afterwards.
The built-in wiki has login and change-password pages for password users, and a root-only page to approve or reject pending auto-improvement proposals across projects.
[search.fts] stopwords lists the function words of your language, so full-text ranking on a Portuguese wiki is not skewed by de and que.
Yes, through explicit cross-project queries when the caller has access. Normal queries use the current project. Messaging delivers a self-contained request to another project’s inbox; it does not give the recipient access to the sender’s files.
No. A popped message is fenced as untrusted cross-project input and carries a notice saying so. The agent evaluates it as a task request with you, and the sender is shown outside the fence so you can judge trust first.
The first pop claims the message and the second gets nothing. A message is claimed exactly once, the same rule handoffs follow.
No. Without a marker file, everything files under a workspace called default, with the git remote as the project, or the directory name when there is none. Add .ai-memory.toml only when you want client separation, a mono-repo as one project, work and personal memory kept apart, or a second server.
The optional TypeScript SDK uses scoped MCP calls to save, search and hand off memory. Conditional writes detect concurrent edits. Build it from the repository; it is not published on npm.
The optional ai-memory-wikisync companion syncs selected shared page families with repository Markdown. It reports conflicting edits, uses conditional writes and keeps deletion opt-in. It does not replicate servers or private session history.
The optional ai-memory-importer reads one local file you name: Markdown, a text-layer PDF, DOCX, PPTX, XLSX, CSV, VTT or SRT. It writes one attributed page, runs as a dry run by default, records the source digest and never replaces a page it does not own. No OCR, no images, no audio. It also imports a claude-mem database from a read-only snapshot, with explicit project mapping and a dry run first.
Free and open source under the MIT license. The default memory features need no model API key; your coding agent may require its own account.