memory
A local, private memory service that lets any AI coding agent search and store shared context across all your tools.
Search shared memory (
memory_search) — semantic search across session logs from all agents, project docs, decisions and notes; scope to a specific project or search everything; returns snippets with source and relevance score (default 8 results).Write memories (
memory_write) — persist durable facts, decisions, discoveries, insights or errors, optionally tagged and assigned to a project, so any future session in any tool can recall them.Inspect the store (
memory_stats) — list collections and chunk counts to see what has been indexed.Cross-tool recall — one memory shared by Claude Code, Codex-style CLIs, OpenCode, ZCode and any MCP-capable agent.
Ingest sources — index AI-tool session histories via connectors plus any registered project/docs folder (auto-watched).
Local-first & private — embeddings (Ollama, e.g. bge-m3) and search run entirely on your machine; no cloud, no accounts.
Fast at scale — sqlite-vec KNN with 1-bit coarse recall and hot/warm/cold tiering (2M+ chunks searched in ~0.36–1.20 s).
Operations included — health/monitor endpoints, feedback-based re-ranking, backups/restore, snapshot archiving, tier maintenance.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@memorysearch memory for our auth architecture decisions from last week"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
English | 中文
https://github.com/user-attachments/assets/a8d5d77c-98bc-42f7-9c58-7b48295875fe
The problem
Every AI coding tool starts from zero.
You spend a week with Claude Code designing an architecture, switch to Codex next week, and it knows nothing about what you decided or why. You paste context again. You re-explain the project. Three tools later, the same conversation has happened five times, and none of it is searchable.
cross-agent-memory fixes this. It runs a small local memory service that:
Ingests your session history from any AI tool (Claude Code / Codex-style CLIs / OpenCode / ZCode / …) and any project folder you point it at.
Indexes everything with local embeddings into a single searchable store.
Serves it back to every agent through an HTTP API or directly as MCP tools — so any MCP-capable agent can recall what every other agent (and you) already figured out.
No cloud. No accounts. Nothing ever leaves your machine.
Related MCP server: Project Context MCP
Features
🔒 Local-first, private by design — embeddings and search run on your machine (Ollama + SQLite + sqlite-vec). Airplane mode is a supported mode.
🧠 Cross-tool by design — connectors for Claude Code, OpenCode and ZCode session stores, plus a generic file watcher for any project/docs folder. Agents share one memory regardless of which tool produced it.
🔌 One-line MCP integration —
memory_search,memory_writeandmemory_statsare exposed over the Model Context Protocol. Claude Code, Codex CLI, Cursor and anything else MCP-capable can use them today.⚡ Fast at real scale — built for large corpora: sqlite-vec vec0 KNN with a 1-bit coarse recall prefilter and hot/warm/cold tiering. The reference deployment searches 2,000,000+ chunks in 0.36–1.20 s (see measured numbers).
🛠 Ops included — health/monitor endpoints, rolling-window degradation detection, backups & restore, snapshot archiving, tier maintenance scripts.
📈 Battle-tested — extracted from a continuously running multi-agent system where four different AI tools share one memory daily, with millions of chunks and daily incremental indexing.
Architecture
Claude Code Codex-style CLI OpenCode / ZCode any project
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────────────────────────────────────────────────────────┐
│ Connectors / Indexers │
│ incremental watermarks · content-hash dedup · active-session │
│ skip · unified chunker · local embeddings (Ollama, e.g. bge-m3) │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ SQLite memory store (single file) │
│ chunks (source of truth) ├─ vec0 KNN index (sqlite-vec) │
│ FTS-ready metadata ├─ 1-bit recall codes (Hamming) │
│ └─ hot / warm / cold tier tables │
└────────────────────────────────────────────────────────────────────┘
│
┌─────────────────┴───────────────────┐
▼ ▼
HTTP API (port 5370) MCP server (stdio)
/api/search /api/memories memory_search
/api/stats /api/health ... memory_write / memory_stats
▲ ▲
└─────────────────┬───────────────────┘
│
every agent you use, in any language/toolDesign notes and the full retrieval pipeline are documented in docs/ARCHITECTURE.md.
🤖 Let your AI agent install it (one paste)
The fastest path: open this repository in your AI coding assistant and paste the block below. It installs everything locally — venv, dependencies, a fresh isolated database — verifies a real write/search round trip, and reports back with exact commands and results. Nothing is sent anywhere; the agent works on your machine only.
Install this repository locally. Read AGENTS.md and INSTALL-FOR-AI.md first.
Use ./install.sh --dry-run, then ./install.sh. Keep all runtime data isolated
from existing databases and bind only 127.0.0.1. Verify initialization twice,
Ollama bge-m3, health, and a real write/search round trip using examples/run.py.
Add the client instructions from examples/client-instructions.md. Report exact
commands, results and blockers; do not claim success from health alone.
Do not import personal projects, restore backups or change system services.Prefer doing it yourself? The manual path is right below. The same protocol is documented for agents in INSTALL-FOR-AI.md and AGENTS.md.
Quickstart
0. Prerequisites
macOS or Linux (Windows is not supported yet — connectors use POSIX file locks)
Python 3.10+
Ollama running locally (for embeddings)
ollama pull bge-m3 # ~1.2 GB, good multilingual embedding model1. Install
git clone https://github.com/indamices/cross-agent-memory.git
cd cross-agent-memory
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt2. Start the service
python3 server.py
# Server listening on 127.0.0.1:53703. Give it something to remember
Register any project folder (docs, decisions, notes):
curl -s -X POST http://127.0.0.1:5370/api/register \
-H 'Content-Type: application/json' \
-d '{"root": "/path/to/your/project"}'The folder needs a
.memory-service.yamlor sensible defaults are used — see examples/. Files are indexed immediately; later changes are batched by a debounce window (default 1 hour,MEMSVC_WATCH_DEBOUNCE). For instant pickup:POST /api/reindex {"project": "..."}or start withMEMSVC_WATCH_DEBOUNCE=0.
Or ingest AI-tool session history with a connector:
python3 connectors/index_claude_code.py # ~/.claude/projects/**/*.jsonl
python3 connectors/index_opencode.py # ~/.local/share/opencode/opencode.db
python3 connectors/index_zcode.py # ~/.zcode/v2/tasks-index.sqlite4. Search from anywhere
curl -s -X POST http://127.0.0.1:5370/api/search \
-H 'Content-Type: application/json' \
-d '{"query": "why did we choose the tiered storage design", "n_results": 5}'Or write a memory directly (decisions, insights — great for agent hooks):
curl -s -X POST http://127.0.0.1:5370/api/memories \
-H 'Content-Type: application/json' \
-d '{"items": [{"type": "decision", "content": "We picked sqlite-vec over a server-based vector DB for local-first operation."}]}'Connect your agents (MCP)
mcp_server.py is a zero-dependency MCP (stdio) server that exposes the
memory API as tools. Point your agent at it:
Claude Code
claude mcp add memory -- python3 /ABS/PATH/cross-agent-memory/mcp_server.pyor in .mcp.json:
{
"mcpServers": {
"memory": {
"command": "python3",
"args": ["/ABS/PATH/cross-agent-memory/mcp_server.py"],
"env": { "MEMORY_SERVICE_URL": "http://127.0.0.1:5370" }
}
}
}Codex CLI (~/.codex/config.toml)
[mcp_servers.memory]
command = "python3"
args = ["/ABS/PATH/cross-agent-memory/mcp_server.py"]
env = { MEMORY_SERVICE_URL = "http://127.0.0.1:5370" }Cursor / other MCP agents — same server command and args in that tool's MCP
settings. If you started the service with MEMSVC_TOKEN set, also set
MEMORY_SERVICE_TOKEN for the MCP server.
Once connected, your agent gets:
Tool | What it does |
| Semantic search across all indexed sessions/projects of every tool |
| Store a decision / insight / discovery for future sessions |
| List collections and sizes |
How retrieval works
Each /api/search request runs a staged pipeline:
Query embedding — computed locally (Ollama), cached by text hash.
Coarse recall — a 1-bit-per-dimension code per chunk is prefiltered by Hamming distance (skipped automatically for small collections).
Exact KNN — sqlite-vec
vec0cosine KNN over the shortlist (falls back to a numpy brute-force path when sqlite-vec is unavailable).Re-ranking — time decay (30-day half-life) + MMR diversity + a small
helpfulfeedback factor.Result — text + source + distance + score per hit.
Under the hood it also handles the boring-but-critical parts: content-hash deduplication, per-connector increment watermarks, skipping sessions that are still being written, batch-write pacing, WAL tuning, and stale-index self-healing.
Measured numbers
From the reference deployment (a Mac mini M4 Pro running this service 24/7 for a multi-agent setup):
Metric | Value |
Indexed chunks | 2,013,030 across 16 collections |
Tools sharing one memory | 4 (Claude Code, OpenCode, ZCode, OpenClaw) |
Sampled | 0.36 s – 1.20 s (5 production queries, warm cache) |
Embedding model |
|
Storage | single SQLite file + derived vec0 index (rebuildable at any time) |
These are real numbers from a heavy, messy, constantly-growing corpus — not a toy benchmark. Your numbers will vary with corpus size and hardware; on a fresh database everything is sub-100 ms.
API overview
Endpoint | Method | Description |
| GET | Liveness (no DB access) |
| GET | Health incl. embedding status, disk, degraded reasons |
| GET | Collections and chunk counts |
| GET | Configured projects |
| GET | Latency/cache/disk metrics |
| POST | Semantic search ( |
| POST | Directly capture memory items |
| POST | Mark a chunk |
| POST | Register a project directory for indexing |
| POST | Force re-index (single project or all) |
| POST | Backup / restore the database |
| POST | Compress old snapshot files |
Full reference with request/response examples: docs/API.md.
Configuration
Everything works with defaults; tune via environment variables when needed:
Variable | Default | Purpose |
|
| HTTP port |
|
| SQLite database path |
|
|
|
|
| 1-bit coarse recall prefilter ( |
|
| HTTP worker cap (503 fast-fail beyond) |
|
| Dump stacks when a search stalls |
| (unset) |
|
| (unset) | Bearer secret; setting it also enables auth |
| (unset) |
|
|
| Database backup directory |
|
| Slow-query threshold for health |
| (disabled) | JSONL of zero/low-quality results (write-back candidates) |
| (disabled) | JSONL sampling of top hits per query |
|
| Claude Code connector source |
|
| OpenCode connector source |
|
| ZCode connector source |
|
| Used by the MCP server |
| (unset) | Bearer token if auth is enabled |
Operations
Health:
GET /api/healthreportsstatus, disk usage, embedding availability and degraded reasons (e.g. slow queries, disk pressure) — designed to be scraped by a cron/monitor without false alarms.Backups:
scripts/backup_silent.py(cron-friendly) orPOST /api/backup. Restore withPOST /api/restore.Tiering (optional):
scripts/migrate_to_vec0.pybuilds the vec0 index;scripts/tier_rebuild.pybuilds hot/warm/cold tier tables to keep the hot set small on very large corpora.Snapshot archiving:
scripts/archive_silent.py.Health cron with alerts:
scripts/health_check.py(optional Feishu webhook support is built in — configure.alert.env).
Design choices (and non-goals)
SQLite, not a vector server. One file, zero services, trivially backed up, works offline. The vec index is derived and rebuildable.
Local embeddings, not an API. Privacy and zero marginal cost; swap the model in
config.pyif you prefer something else.Files are the source of truth. Everything indexed can be re-ingested from its source; deleting the database loses nothing that lives on disk.
Not a cloud sync product. This is a local service for one machine (multiple agents, one memory). Multi-user/server mode is on the roadmap.
Not a vector database benchmark entry. It prioritizes a small dependency surface and operability over raw ANN throughput.
Roadmap
Web console (browse / search / curate memories)
More connectors: Codex CLI session store, Cursor, Aider, generic JSONL
First-class memory types (facts / lessons / code-change context) with extraction pipelines
Multi-machine sync for people who work across hardware
Python package / Docker image for one-command installs
Issues and PRs are welcome — especially new connectors. See CONTRIBUTING.md.
Acknowledgements
Built on the shoulders of excellent tools: SQLite, sqlite-vec, Ollama, numpy, watchdog.
License
MIT © 2026 indamices
Available Tools
3 toolsmemory_searchA
Search the shared memory across ALL agent tools (session logs of this and other AI coding tools, project docs, decisions, notes). Use it whenever you need past context: previous decisions, how a problem was solved before, architecture rationale, user preferences. Returns the most relevant text snippets with their source and relevance score.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Natural-language search query. | |
| project | No | Optional collection/project to search within. Omit to search everything. | |
| n_results | No | Number of results to return (default 8). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It does disclose a meaningful trait, that the search spans ALL agent tools' session logs rather than only the current project, and it sketches the return shape (snippets with source and relevance score). It says nothing about permission boundaries, latency, result freshness, or whether empty results are possible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the scope and immediately followed by usage triggers and the return shape. No filler and no repetition of the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 3-parameter read tool with no output schema, the description covers purpose, cross-tool scope, invocation triggers, and a one-line return summary. The main gap is behavioral depth that annotations would normally supply, such as ranking, freshness, or failure behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so query, project, and n_results are already documented with defaults and the 'omit to search everything' behavior. The description adds no syntax, format, or query-construction guidance beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Search) and resource (shared memory) plus the scope of what is indexed: session logs of this and other AI coding tools, project docs, decisions, notes. That is far more informative than the tool name alone. It does not explicitly contrast itself with memory_write or memory_stats, though the read-vs-write distinction is easy to infer.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use it whenever you need past context" is followed by concrete triggers: previous decisions, prior problem-solving, architecture rationale, user preferences. This gives an agent clear conditions for invocation, but offers no exclusions or alternatives (e.g. when to prefer memory_stats for counting, or what to do if the query returns nothing).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_statsA
Get memory-service statistics: which collections exist and how many chunks each holds. Useful to see what has been indexed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does convey that this is a non-mutating inventory read returning aggregate counts, but says nothing about permissions, cost/rate limits, or whether empty collections are included.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences with the payload described first and the rationale second — front-loaded and near waste-free. The second sentence is mildly redundant but justifies the tool's existence, so it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description is the only source of return-shape information, and it names the two key fields (collections, chunk counts). That is sufficient for a zero-parameter tool, with only minor gaps such as output format or ordering.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4; there is no parameter semantics for the description to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (get) and resource (memory-service statistics) and specifies the returned content: collection names and chunk counts per collection. That distinguishes it from memory_search and memory_write, though neither sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Useful to see what has been indexed' implies a discovery/inventory use case, so an agent can infer when to reach for it over search or write. It does not state exclusions (e.g., use memory_search to inspect content) or prerequisites, so guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
memory_writeA
Store an item into shared memory so future sessions (in this tool or any other connected AI tool) can find it. Use it for durable facts: decisions made, discoveries, important insights, user preferences.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Optional tags for later filtering. | |
| type | No | Item kind: decision | discovery | insight | error. | insight |
| content | Yes | The text to remember (self-contained, specific). | |
| project | No | Optional project/collection name. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it does disclose genuine behavior: the write persists across sessions and is visible to any connected AI tool, which materially raises the stakes of a bad write. It is silent on duplicate handling, overwrite/replace semantics, whether the write can be revoked, and what confirmation comes back — significant gaps for an irreversible-looking mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler, with the core action front-loaded and the usage criterion following immediately. Every clause earns its place by adding either scope or selection guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a four-parameter, one-required write tool with fully documented schema and no output schema, the description covers purpose, target content, and cross-session effect well enough to call it correctly. The only real remaining gap is write semantics — duplicate handling and what is returned on success — which a mutation tool without annotations ideally would state.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented, including the type enum values and the required content. The description's example categories loosely mirror the type enum and hint at what content should look like (durable, specific facts), but add nothing about tag syntax, project scoping, or defaults beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (store) and resource (item into shared memory) plus the downstream purpose (retrievable in future sessions and by other connected AI tools). Against siblings memory_search and memory_stats, this is unmistakably the write counterpart, so an agent can select it without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
"Use it for durable facts" gives an explicit positive selection criterion, reinforced by the enumerated categories (decisions, discoveries, insights, user preferences). It never states what should NOT be stored (transient chatter, secrets) or points to memory_search as the retrieval partner, so exclusions and named alternatives are absent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v0.1.0- First observed
memory_search - First observed
memory_stats - First observed
memory_write
TDQS
Scored across 3 tools
Each tool maps to a distinct memory operation: inspection (stats), retrieval (search), and storage (write). There is no plausible way to confuse them, and the descriptions reinforce the boundary between reading and writing.
All three names follow the identical memory_<verb> pattern (memory_stats, memory_search, memory_write), with short, predictable verbs. Naming is fully consistent and self-documenting.
Three tools is a tight, well-scoped surface for a memory service where each tool clearly earns its place. It sits at the thin edge of the ideal range, though the narrow scope justifies it.
Read (search), write, and introspection (stats) are covered, but there is no way to delete, correct, or update a stored memory, and stats gives only counts rather than per-collection detail. Agents that wrote a wrong or stale fact have no lifecycle operation to fix it, which is a notable gap for a shared memory store.
Maintenance
Related MCP Connectors
Shared memory for coding agents. Stop re-explaining your codebase every session.
Persistent memory for AI agents. Search, store, and recall across sessions.
Universal persistent memory and knowledge retrieval layer for AI agents and LLMs.
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceProvides AI agents with persistent, local, and shareable project memory by storing decisions and code context in a searchable SQLite index, supporting keyword and semantic search via MCP.3MIT
- AlicenseBqualityCmaintenanceEnables coding agents to incrementally index project text and code, persist decisions and constraints with clear sources, and assemble focused project context across sessions via MCP.3416 npm8MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI coding agents to query a unified local index of all their sessions through native tools, supporting session summaries, full-text search, listing, message timelines, and handoff context packages for another agent.2MIT
- AlicenseNot gradedqualityBmaintenanceEnables coding agents to search local repositories through hybrid keyword and embedding retrieval, read matched chunks, and list indexed repos via MCP, without API keys or cloud services.MIT