Skip to main content
Glama
README.md
# memento

> Persistent memory for AI coding agents. Local-first. Zero cloud. Plug-and-play with Claude Code via MCP.

[![CI](https://github.com/UmoLab/memento/actions/workflows/ci.yml/badge.svg)](https://github.com/UmoLab/memento/actions)
[![Tests](https://img.shields.io/badge/tests-179%20passing-brightgreen)](https://github.com/UmoLab/memento/actions)
[![Coverage](https://img.shields.io/badge/coverage-92%25-brightgreen)](https://github.com/UmoLab/memento/actions)
[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://pypi.org/project/memento-memory/)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](https://github.com/UmoLab/memento/blob/main/LICENSE)
[![MCP](https://img.shields.io/badge/MCP-compatible-purple)](https://modelcontextprotocol.io/)

**Stop losing context between sessions.** `memento` gives your AI agent a long-term brain that runs entirely on your laptop. Stored facts (preferences, decisions, conventions) survive across sessions and are recalled by semantic similarity — so the next time you ask Claude to "use my dark theme," it remembers without you re-explaining.

Built for [Claude Code](https://claude.ai/code) but works with any [MCP](https://modelcontextprotocol.io/)-compatible client.

---

## Why

Every Claude Code session starts cold. You re-explain your preferences, your project's conventions, your architecture decisions. After 50 sessions, you've typed the same context thousands of times.

`memento` solves this with persistent memory:

- **Stored automatically** by your agent via MCP tools (`memento_store`, `memento_recall`, etc.)
- **Recalled by semantic similarity** (vector search, no exact-key matching)
- **Survives sessions, restarts, machines** (single SQLite file)
- **100% local** — no API calls, no telemetry, no cloud lock-in
- **Battle-tested** — 179 tests, 92% coverage (with branch tracking), real concurrency tests

---

## 30-second quickstart

### 1. Install

```bash
pip install memento
```

(First run downloads a ~80MB embedding model — one-time, then cached.)

### 2. Initialize the database

```bash
memento init
```

Creates `~/.local/share/memento/memory.db`.

### 3. Wire into Claude Code

Add to `~/.claude/mcp_servers.json` (or `.mcp.json` in your project):

```json
{
  "mcpServers": {
    "memory": {
      "command": "memento",
      "args": ["start"],
      "env": {"MEMENTO_PATH": "~/.local/share/memento/memory.db"}
    }
  }
}
```

### 4. Use it

Open Claude Code. It now has access to:

- `store` — save a fact (preference, decision, convention)
- `recall` — semantic search across stored facts
- `update` / `forget` — mutate stored facts
- `recent` / `browse` — inspect what's stored

Tell Claude: *"Remember that I prefer dark mode in all my projects."* Next session, it'll know.

---

## First day with memento

A 5-minute walkthrough to prove the round-trip works:

```bash
$ memento init
Initialized memento at ~/.local/share/memento/memory.db

$ memento list
No memories yet. Run `memento init` then store something.

# Stash something via Python (or via Claude Code)
$ python -c "from memento import Memory; \
  m = Memory(); \
  m.store('I prefer dark mode in editors', 'fact', 0.8, subject_key='user.theme')"

$ memento list
  01KVF2CKW772  fact    imp=0.80  [user.theme] I prefer dark mode in editors

$ memento search "what theme does the user like"
  1. 01KVF2CKW772  fact    imp=0.80  [user.theme] I prefer dark mode in editors

$ memento show 01KVF2CKW772
Memory 01KVF2CKW772QQG4ZRPSDEH99E
  kind:         fact
  subject_key:  user.theme
  importance:   0.80
  source:       manual
  ...

  content:
    I prefer dark mode in editors
```

If you see this — Claude Code will too. The next session, just open Claude and ask *"what theme does the user like?"* — it'll know.

---

## What's stored

Three kinds of memories:

| Kind | Use for | Example |
|------|---------|---------|
| `fact` | User preferences, project facts, conventions | "User prefers dark mode" |
| `event` | Things that happened, dated context | "Migrated from Postgres to SQLite on 2026-01-15" |
| `lesson` | Procedural rules the agent should follow | "When using sqlite-vec, always include `AND k = ?`" |

Each memory can have a `subject_key` (e.g. `user.theme`, `project.db_choice`) for deterministic lookup, plus metadata and importance (0.0–1.0).

---

## Architecture

```
┌──────────────────────────────────────────────────┐
│  Claude Code (or any MCP client)                 │
│         │                                        │
│         │ MCP protocol (JSON-RPC over stdio)     │
│         ▼                                        │
│  ┌──────────────────────────────────────────┐    │
│  │  memento mcp_server                      │    │
│  │  (10 tools: memento_store, memento_recall, …) │    │
│  └──────────────┬───────────────────────────┘    │
│                 │                                │
│                 ▼                                │
│  ┌──────────────────────────────────────────┐    │
│  │  memento core (Python)                   │    │
│  │  ┌──────────┐ ┌──────────┐ ┌─────────┐    │    │
│  │  │  Store   │ │ Recall   │ │ Embedder│    │    │
│  │  │ (SQLite) │ │(vec+fts) │ │  (sbert)│    │    │
│  │  └──────────┘ └──────────┘ └─────────┘    │    │
│  └──────────────┬───────────────────────────┘    │
│                 │                                │
│                 ▼                                │
│       SQLite + FTS5 + vec0  (~/.local/share/…)   │
└──────────────────────────────────────────────────┘
```

Everything in one SQLite file. SQLite gives ACID transactions, WAL for concurrent reads, and single-file backup. No Docker, no Postgres, no Redis.

---

## When to use `memento`

You want persistent memory that just works, runs on your laptop, doesn't phone home, and integrates with Claude Code in under a minute.

## When NOT to use it

You need multi-tenant cloud storage, embeddings for non-text modalities, or 100k+ memories per user (vector search in SQLite caps out around there).

---

## ⚠️ Auto-execute awareness

Claude Code (and other MCP clients) may auto-execute `memento_*` tools without explicit confirmation if the user enables auto-mode. Every `memento_store` call writes a row to your local SQLite file. Two practical consequences:

1. **Use `subject_key` for deterministic facts.** Free-form `memento_store` calls without a `subject_key` will dedupe via vector similarity — convenient, but you'll get a fresh row each time the wording shifts.
2. **Audit before clearing.** `memento_forget` is a soft archive (recoverable). `memento_forget --hard` and `memento_forget-prefix` are destructive — they `DELETE` rows from the on-disk SQLite file. There is no undo.

If your agent runs in a context where another process might invoke these tools, wrap your MCP server call in an explicit user prompt.

---

## Backing up and restoring

Everything is in one SQLite file. To back up:

```bash
cp ~/.local/share/memento/memory.db backup.db
# Or export to portable JSONL:
memento export ~/.local/share/memento/memory.db > backup.jsonl
```

To restore:

```bash
# From a SQLite file:
cp backup.db ~/.local/share/memento/memory.db
# From a JSONL file:
memento init ~/.local/share/memento/memory.db --force
memento import_data ~/.local/share/memento/memory.db backup.jsonl
```

## Upgrading the embedding model

If you switch `MEMENTO_EMBEDDING_MODEL` or upgrade `sentence-transformers`, old memories
have embeddings in the old dimension. Run:

```bash
memento reembed
```

This re-encodes every memory using the current model. Without it, sqlite-vec
queries on mixed-dim embeddings will crash.

---

## Usage

### CLI

```bash
memento init                              # create empty DB
memento verify                            # health check (8 checks)
memento stats                             # show counts, model, schema version
memento list                              # show recent memories (formatted)
memento show <id>                         # show one memory by id
memento search "query"                    # semantic search via CLI
memento start                             # run MCP server on stdio
memento export <path> > backup.jsonl      # export all memories to JSONL
memento import_data <path> <file.jsonl>   # import from JSONL backup
memento import <path> <pm-db-path>        # import from PMB-format DB
memento reembed                           # re-encode stale embeddings
memento about                             # show user.* facts + recent events
memento forget <id>                       # soft-archive one memory
memento forget <id> --hard                # physical delete (irreversible)
memento forget-prefix <prefix>            # archive all memories by subject_key prefix
```

### Python API

```python
from memento import Memory

mem = Memory(path="~/.local/share/memento/memory.db")

# Store a fact (with subject_key for deterministic dedup)
mem.store(
    content="User prefers dark mode",
    kind="fact",
    importance=0.8,
    subject_key="user.theme",
)

# Semantic recall (results are MemoryRecord, sorted by relevance)
results = mem.recall("what theme does the user prefer?")
for r in results:
    print(f"[{r.kind}]  {r.content}")

# Update
mem.update(id=results[0].id, content="User prefers dark mode in editors, light in terminals")

# Forget
mem.forget(id=results[0].id)

# Browse by prefix
for item in mem.browse(subject_key_prefix="user."):
    print(item.content)
```

### MCP tools

When running as an MCP server, these tools are exposed:

| Tool | Purpose |
|------|---------|
| `memento_store` | Store a fact/event/lesson |
| `memento_recall` | Semantic search across all memories |
| `memento_update` | Update content/importance/metadata |
| `memento_forget` | Soft-delete (archive); `hard=True` purges from disk |
| `memento_forget_prefix` | Soft-archive all memories by subject_key prefix |
| `memento_recent` | Browse recent memories |
| `memento_browse` | List by subject_key prefix |
| `memento_stats` | Counts, schema version, model info |
| `memento_store_many` | Atomic batch insert |
| `memento_recall_many` | Batch semantic search |

All tool names are prefixed with `memento_` to avoid collisions with other MCP servers exposing generic names like `store` or `recall`.

For migration from PMB-format DBs, use the Python API:
`from memento.importers.pmb import import_pmb`.

---

## Storage format

Single SQLite file with three tables:

- `memories` — content + metadata (subject_key, kind, importance, source, timestamps)
- `memory_fts` — FTS5 virtual table for keyword fallback
- `memory_vec` — sqlite-vec virtual table for semantic search

Schema migrations: `schema_version` table tracks applied migrations; `memento init` upgrades existing DBs in place.

---

## Testing

```bash
git clone https://github.com/UmoLab/memento
cd memento
pip install -e ".[dev]"
pytest                     # 179 tests, ~10 min on CPU
pytest --cov=memento       # with coverage
ruff check src tests       # lint
```

---

## Documentation

- [Installation guide](docs/installation.md)
- [Claude Code integration](docs/claude-code-integration.md)
- [Python & MCP API reference](docs/api.md)
- [CHANGELOG](CHANGELOG.md)
- [CONTRIBUTING](CONTRIBUTING.md)

---

## License

Apache 2.0. See [LICENSE](LICENSE).

---

## Credits

- [sqlite-vec](https://github.com/asg017/sqlite-vec) — vector search in SQLite
- [sentence-transformers](https://www.sbert.net/) — local embeddings
- [fastmcp](https://github.com/jlowin/fastmcp) — MCP server framework
- [python-ulid](https://github.com/aztechverder/python-ulid) — sortable IDs

Maintenance

ActivityMaintained
ResponsivenessSyncing