io.github.bolnet/memwright
Embedded memory for AI agents with SQLite FTS5, pgvector, and Neo4j graph search.
Ask AI about io.github.bolnet/memwright
Powered by Claude Β· Grounded in docs
I know everything about io.github.bolnet/memwright. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
Embedded memory for AI agents. Open and inspectable. Works with Claude Code.
Why Memwright?
AI agents forget everything between conversations. The typical fix is a managed vector database or cloud memory service. Memwright takes a different approach:
- Open & inspectable β Your memories live in a SQLite file. Run
sqlite3 memory.dband see exactly what the agent knows. No black boxes. - 3-layer retrieval β Tag matching, Neo4j entity graph, and pgvector semantic search fused with Reciprocal Rank Fusion.
- Token efficient β 300-500 tokens per recall vs 15,000+ for full history replay.
- Fully local β Everything runs on your machine via Docker. No cloud dependency.
Works as a Claude Code MCP server, a Cursor MCP server, or a Python library.
Install
pip install memwright[all]
Tip: On macOS with Homebrew Python, use
pipx install "memwright[all]"to install as a standalone CLI tool.
Requirements: Docker Desktop and an embedding API key (OPENROUTER_API_KEY or OPENAI_API_KEY).
Quick Start β Claude Code
Paste this prompt into Claude Code and it handles the rest:
Set up memwright as this project's persistent memory.
1. Install: pip install "memwright[all]" (if pip fails on macOS, use: pipx install "memwright[all]")
2. Make sure Docker Desktop is running
3. Initialize: agent-memory init ~/.agent-memory/PROJECT_NAME
4. Add your embedding API key to ~/.agent-memory/PROJECT_NAME/.env (OPENROUTER_API_KEY or OPENAI_API_KEY)
5. Create .mcp.json in the project root:
{
"mcpServers": {
"memory": {
"command": "agent-memory",
"args": ["serve", "~/.agent-memory/PROJECT_NAME"],
"env": {
"OPENROUTER_API_KEY": "your-key-here",
"PG_CONNECTION_STRING": "postgresql://memwright:memwright@localhost:5432/memwright",
"NEO4J_URI": "bolt://localhost:7687",
"NEO4J_PASSWORD": "memwright"
}
}
}
}
6. Add to CLAUDE.md: Use memory_recall at conversation start, memory_add to store context.
7. Verify: agent-memory doctor ~/.agent-memory/PROJECT_NAME
Manual Setup
# 1. Install
pip install "memwright[all]"
# 2. Initialize (starts Docker containers for pgvector + Neo4j)
agent-memory init ~/.agent-memory/my-project
# 3. Add your embedding API key
echo 'OPENROUTER_API_KEY=sk-or-...' >> ~/.agent-memory/my-project/.env
Add to your project's .mcp.json:
{
"mcpServers": {
"memory": {
"command": "agent-memory",
"args": ["serve", "~/.agent-memory/my-project"],
"env": {
"OPENROUTER_API_KEY": "sk-or-...",
"PG_CONNECTION_STRING": "postgresql://memwright:memwright@localhost:5432/memwright",
"NEO4J_URI": "bolt://localhost:7687",
"NEO4J_PASSWORD": "memwright"
}
}
}
}
Note: The
envblock is required because the MCP server process doesn't auto-load the.envfile.
Restart Claude Code. You now have 7 memory tools: memory_add, memory_get, memory_recall, memory_search, memory_forget, memory_timeline, memory_stats.
Add to your CLAUDE.md:
## Memory
Use `memory_recall` at the start of each conversation with the user's first message.
Use `memory_add` to store preferences, decisions, and project context.
Quick Start β Cursor
# 1. Install and initialize
pip install "memwright[all]"
agent-memory init ~/.agent-memory/my-project
Add to .cursor/mcp.json:
{
"mcpServers": {
"memory": {
"command": "agent-memory",
"args": ["serve", "~/.agent-memory/my-project"],
"env": {
"OPENROUTER_API_KEY": "sk-or-...",
"PG_CONNECTION_STRING": "postgresql://memwright:memwright@localhost:5432/memwright",
"NEO4J_URI": "bolt://localhost:7687",
"NEO4J_PASSWORD": "memwright"
}
}
}
}
Quick Start β Python Library
from agent_memory import AgentMemory
mem = AgentMemory("./my-agent")
# Store facts
mem.add("User prefers Python over Java",
tags=["preference", "coding"], category="preference")
mem.add("User works at SoFi as Staff SWE",
tags=["career"], category="career", entity="SoFi")
# Recall relevant memories
results = mem.recall("what language does the user prefer?")
for r in results:
print(f"[{r.match_source}:{r.score:.2f}] {r.content}")
# Get formatted context string for prompt injection
context = mem.recall_as_context("user background", budget=500)
# Contradiction handling β old facts get auto-superseded
mem.add("User works at Google as Principal Eng",
tags=["career"], category="career", entity="SoFi")
# ^ The SoFi memory is now superseded automatically
Benchmarks
LOCOMO (Long Conversation Memory)
| System | Score |
|---|---|
| MemMachine | 84.9% |
| Zep | ~75% |
| Letta | 74.0% |
| Mem0 (Graph) | 66.9% |
| Memwright | 62.5% |
| OpenAI Memory | 52.9% |
LOCOMO scores are disputed across vendors. Numbers above are self-reported.
MemoryAgentBench (ICLR 2026)
| Category | Score |
|---|---|
| Accurate Retrieval | 55% |
| Conflict Resolution | 62% |
| Overall | 58.5% |
How Memwright uses LLMs: Embeddings, entity extraction, memory extraction, and contradiction detection all use LLM calls. Retrieval combines tag matching, graph traversal, and vector search with RRF fusion β no LLM re-ranking or judge.
How Retrieval Works
Multi-layer cascade with Reciprocal Rank Fusion:
graph TD
Q[Query] --> T["Tag Match"]
Q --> G["Graph Β· Neo4j"]
Q --> V["Vector Β· pgvector"]
T --> R[RRF Fusion]
G --> R
V --> R
R --> O[Ranked Results]
style Q fill:#C15F3C,stroke:#C15F3C,color:#fff
style R fill:#C15F3C,stroke:#C15F3C,color:#fff
style O fill:#161b22,stroke:#C15F3C,color:#F4F3EE
style T fill:#161b22,stroke:#30363d,color:#F4F3EE
style G fill:#161b22,stroke:#30363d,color:#F4F3EE
style V fill:#161b22,stroke:#30363d,color:#F4F3EE
Entity relationships are traversed to find related memories (e.g., querying "Python" also finds memories about "FastAPI" if they're connected). Graph relationship triples are injected as synthetic context for multi-hop reasoning.
CLI
agent-memory init ./store # Initialize store + Docker + .env
agent-memory add ./store "text" ... # Add a memory
agent-memory recall ./store "query" # Multi-layer recall
agent-memory search ./store "text" # Search memories
agent-memory list ./store # List memories
agent-memory timeline ./store # Entity timeline
agent-memory stats ./store # Store statistics
agent-memory doctor ./store # Health check
agent-memory serve ./store # Start MCP server
agent-memory export ./store -o bak.json
agent-memory import ./store bak.json
Architecture
AgentMemory
βββ SQLite β Core storage, always on
βββ pgvector β Semantic vector search (PostgreSQL)
βββ Neo4j β Entity graph, multi-hop traversal
βββ Retrieval β Multi-layer cascade with RRF fusion
βββ Temporal β Contradiction detection, supersession
βββ Extraction β Rule-based + optional LLM
βββ MCP Server β Claude Code / Cursor integration
βββ CLI + Doctor β Health check for all components
Configuration
AgentMemory stores config.json in the memory store directory:
{
"default_token_budget": 2000,
"min_results": 3,
"pg_connection_string": "postgresql://memwright:memwright@localhost:5432/memwright",
"neo4j_uri": "bolt://localhost:7687",
"neo4j_password": "memwright"
}
Environment variables override config: PG_CONNECTION_STRING, NEO4J_PASSWORD, OPENROUTER_API_KEY / OPENAI_API_KEY.
License
Apache 2.0
mcp-name: io.github.bolnet/memwright
