keepsake
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., "@keepsakesearch my vault for sourdough starter notes"
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.
keepsake
Own your AI memory.
Import a chat export or your notes, search it locally, seal it into an encrypted, portable .keepsake vault, and let any AI agent recall from it over MCP.
by svx · MIT Licensed
Live site: keepsake · Source: github.com/srivtx/keepsake
Docs: Spec · Usage · Conformance · FAQ
Format: keepsake/v1
Why
The memory you give an AI is trapped in that vendor's cloud. It is not a file you can copy, it is not portable between assistants, and it disappears when the account does. Exporting usually means a pile of JSON with no integrity story and no way to hand it to a different agent.
keepsake makes your memory a file you own: an open format, encrypted at rest,
portable across tools, and readable by any agent that speaks MCP.
Related MCP server: Enigma MCP Server
What it is
An open format —
keepsake/v1, a small, fully specified, deterministic container for memory cells. Seespec/SPEC.md.A browser app — import, browse, search, and seal locally. No upload, no account, no network. The vault is built in the page and saved with the File System Access API or a download.
A Bun CLI — the same engine for scripts and CI: import, search, seal, open, verify.
An MCP server — expose a vault to any MCP-capable agent over stdio so it can recall from your memory without a vendor holding it.
All four are a reference implementation of the format, not the format itself. Anything that follows the spec can read and write the same vaults.
Install
keepsake is not published to npm. Install it from GitHub with the one-line
script (requires Bun):
# One-line install (installs the `keepsake` binary)
curl -fsSL https://raw.githubusercontent.com/srivtx/keepsake/main/install.sh | sh
# Or run once, without installing
bunx github:srivtx/keepsake#main --help
# Install globally
bun add -g github:srivtx/keepsake
keepsake --help
# Add to a project as a dev dependency
bun add -d github:srivtx/keepsakeUsage
CLI
# Import a chat export into a new sealed vault
keepsake import chatgpt-export.zip --source chatgpt-export --out memory.keepsake
# Import notes as free-form memories
keepsake import notes.md --source notes.md --out memory.keepsake
# Search a vault locally (exact, lexical)
keepsake search "sourdough" memory.keepsake
# Open a vault to plaintext cells, or seal a plaintext file back up
keepsake open memory.keepsake --out cells.json
keepsake seal cells.json --out memory.keepsake
# Verify the integrity of a vault (hashes and Merkle root)
keepsake verify memory.keepsake
# Merge two vaults into one
keepsake merge memory.keepsake archive.keepsake --out merged.keepsake
# Remove cells by id, tag, source, or query, then rewrite the vault
keepsake forget --vault memory.keepsake --query "staging database" --out pruned.keepsake
# Re-encrypt a vault under a new passphrase (new one in KEEPSAKE_NEW_PASSPHRASE)
keepsake rotate --vault memory.keepsake
# Compare two vaults
keepsake diff memory.keepsake archive.keepsake
# Print a token-budgeted Markdown context pack for a task
keepsake context "plan the migration" --vault memory.keepsake --budget 1500
# Decrypt a vault into a plaintext memory pack, or seal a pack back into a vault
keepsake pack --vault memory.keepsake --out memory.md
keepsake unpack memory.md --out restored.keepsake
# Run the published conformance vectors against this implementation
keepsake conformance
# Serve the vault over MCP on stdio
keepsake mcp --vault memory.keepsakeImport accepts ChatGPT exports, Claude conversations.json, JSONL transcripts,
JSON message arrays, and plain text or notes. The passphrase is never written to
disk or passed on the command line: the CLI reads it from KEEPSAKE_PASSPHRASE,
and commands that touch a second vault read KEEPSAKE_PASSPHRASE_B. There is no
recovery if it is lost.
Exit codes:
Code | Meaning |
| Success (or, for |
| A finding or negative result (a failed check, or no matches) |
| Invalid usage, or a vault or cell that does not parse |
| I/O error: a file could not be read, written, or found |
MCP
Any MCP-capable agent can recall from a vault over stdio:
{
"mcpServers": {
"keepsake": {
"command": "bunx",
"args": ["github:srivtx/keepsake#main", "mcp", "--vault", "/path/to/memory.keepsake"],
"env": { "KEEPSAKE_PASSPHRASE": "…" }
}
}
}The server exposes memory_recall, memory_context, memory_stats, and
memory_verify over your cells, plus memory_remember and memory_forget to
write. memory_context returns the same token-budgeted pack as the CLI, and
memory_forget removes a memory by id or query. The server asks for the
passphrase on startup. It makes no network calls: the vault is opened
in-process.
On-device semantic recall
The browser app can optionally run a real embedding model in the tab. After you click Load on-device model, it embeds every cell (384 dimensions, mean-pooled and normalized), and search gains three modes:
lexical — BM25 over the cell text. This is the default, and the only mode the CLI and the MCP server use.
semantic — cosine similarity over the on-device embeddings, so a query can match a cell that shares no words with it.
hybrid — a blend of the lexical and semantic scores.
The model is self-hosted. The site ships the Transformers.js v3 runtime, the
Xenova/all-MiniLM-L6-v2 model at dtype: q8, and the ONNX Runtime Web WASM
binaries from its own assets/, models/, and wasm/ directories, so loading
it adds roughly 45 MB of static assets served from the same origin. Everything
runs in the browser: no memory or query leaves the machine and no external
requests are made. The feature is optional, and the app works fine without
loading it. The CLI and the MCP server stay lexical (BM25); semantic recall is a
browser-app capability for now.
Move your memory between tools
A vault and a pack are two projections of the same cells. The vault is the
encrypted on-disk file (.keepsake): AES-256-GCM under PBKDF2-SHA256, with a
Merkle root committing to the plaintext. The memory pack is a plaintext
interchange file: a single Markdown document that carries the exact same cells
losslessly, so a human or an LLM can read it and any tool can move it. A pack is
not encrypted.
# Decrypt a vault into a plaintext memory pack
keepsake pack --vault memory.keepsake --out memory.md
# Verify a pack's hashes and Merkle root, then seal it into a new vault
keepsake unpack memory.md --out restored.keepsakeBoth commands read the passphrase from KEEPSAKE_PASSPHRASE. unpack checks the
pack's per-cell hashes and Merkle root before sealing and exits 1 if the pack
does not verify. Because a pack is plaintext, anyone who has the file can read
every cell; share it only where that is intended.
Verify a vault in CI
Commit a .keepsake vault and let CI prove it still opens and checks out. The
repository ships a composite action that installs Bun and runs keepsake verify
against the vault, failing the job if the passphrase is wrong or any cell hash or
the Merkle root does not match.
name: Verify memory
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: srivtx/keepsake@v0.5.0
with:
vault: memory.keepsake
passphrase: ${{ secrets.KEEPSAKE_PASSPHRASE }}Pass the passphrase as a repository secret, never a literal string. The action
defaults to version: main; pin it to a tag to match the release you run:
- uses: srivtx/keepsake@v0.5.0
with:
vault: memory.keepsake
passphrase: ${{ secrets.KEEPSAKE_PASSPHRASE }}
version: v0.5.0The format in brief
A memory is a Cell:
{
"id": "3f7c9d2e-1a4b-4c8d-9e0f-1a2b3c4d5e6f",
"text": "I want to move my chat history out of the cloud.",
"source": "chatgpt-export",
"role": "user",
"createdAt": "2026-01-05T09:12:00.000Z",
"tags": ["privacy", "memory"],
"hash": "32003353cb5403744610e2570bd435030b4aaa5d930e272c8723a382f7526516"
}The hash is the SHA-256 of the cell's canonical JSON: its six non-hash
fields with object keys sorted recursively. A vault is a JSON file:
{
"format": "keepsake/v1",
"createdAt": "2026-03-01T12:00:00.000Z",
"cells": 3,
"kdf": { "name": "PBKDF2-SHA256", "iterations": 250000, "salt": "…base64…" },
"cipher": { "name": "AES-GCM", "iv": "…base64…" },
"ciphertext": "…base64, includes the 16-byte GCM tag…",
"merkle": "4e540078fb922de39e689dcf86a9828e4e274986fd6fe5a03da2333724c96d2d"
}The plaintext is the canonical JSON of the cells array, encrypted with
AES-256-GCM under a key derived by PBKDF2-SHA256 (250,000 iterations, 16-byte
salt, 12-byte IV). The merkle root is a SHA-256 hash tree over the sorted cell
hashes; an empty vault's root is sha256(""). Transport is the file itself:
there is no server, no account, and no network call.
The full specification, the JSON Schema, and conformance vectors are in
spec/.
Security
Local only. No network code. Importing, searching, sealing, and opening all run on your machine.
Encrypted at rest. AES-256-GCM with the tag included; any change to the ciphertext fails to open.
Integrity you can check. Per-cell hashes and a Merkle root detect any change to the plaintext.
No key escrow. The passphrase is never stored and there is no recovery.
Honest limits.
keepsake/v1has no semantic embeddings and no sync.keepsake rotatere-encrypts a vault under a new passphrase, but there is no in-place re-wrap. The container leaks its format, creation time, cell count, KDF parameters, and approximate size. See the security notes in the spec.
Report vulnerabilities privately via GitHub Security Advisories.
Roadmap
Embeddings — optional local semantic recall layered over the same cells, without changing the vault format.
Sync — optional, opt-in multi-device sync with a documented merge and conflict model.
Key rotation in place — re-wrap a vault under a new passphrase without re-encrypting every cell; today
keepsake rotaterewrites the file.
For agents
Every surface is built to be read by a program: the spec is normative and deterministic, the schema is machine-checkable, and the MCP server exposes a vault directly.
Docs index: the site serves a machine-readable index at srivtx.github.io/keepsake/llms.txt.
Agent guide:
AGENTS.mdcovers build, test, layout, and the hard rules.MCP server: point an agent at a vault over stdio.
{ "mcpServers": { "keepsake": { "command": "bunx", "args": ["github:srivtx/keepsake#main", "mcp", "--vault", "/path/to/memory.keepsake"] } } }
License
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
- mcpOAuthai.butlerbrain
Persistent memory for AI assistants. Save once; recall from Claude, ChatGPT, or any MCP client.
Persistent memory for AI agents — log and recall conversation context over MCP.
Shared long-term memory vault for AI agents with 20 MCP tools.
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Related MCP Servers
AlicenseAqualityBmaintenanceExposes local memory vaults as 6 MCP tools over stdio, enabling clients like Windsurf, Zed, and Claude Desktop to read and write memory.6243 npm2MIT
Enigma MCP Serverofficial
AlicenseNot gradedqualityAmaintenanceOffers MCP tools for managing a local AI memory vault, including remembering, searching, context packing, deletion, and verification of receipts.38 npm1Apache 2.0- FlicenseAqualityCmaintenanceLocal explicit memory vault exposing MCP tools for storing, searching, and managing memories, providing a shared memory layer for agents like Codex and ChatGPT.7-
- AlicenseNot gradedqualityAmaintenanceProvides AI agents with a local, private Markdown-based memory vault and SQLite search. Enables agents to search, read, list, and traverse linked knowledge pages via MCP with zero external runtime dependencies.3MIT