Memory that follows you.
mem stores what your AI agents learn — decisions, preferences, architecture, gotchas — as atomic facts, and injects the relevant ones into every new session, in any tool, for a few hundred tokens.
01What mem is
Every agent session starts from zero: the context you built up yesterday dies when the window closes. mem is the persistence layer underneath — a server (this one) that your tools write observations into and read ranked, task-relevant context out of.
- Write path — you or an agent
observeone-sentence facts. The server embeds them, detects duplicates and contradictions, and stores them. - Read path — a session asks for context for a task; mem returns the best handful of facts as plain prose, ready to inject. Never JSON, never metadata, ~15 tokens per fact.
- Everywhere — the same memory serves Claude Code (via hooks), Claude Desktop and any MCP client (via
/mcp), the CLI, and this web app.
mem runs no reasoning LLM. Distilling messy experience into atomic facts is the agent's job at write time; mem's job is embedding, ranking, storage, and honesty about what it knows.
02Core concepts
| Concept | What it means |
|---|---|
| Memory (chunk) | One atomic fact — a single self-contained sentence, stored verbatim with an embedding, confidence, staleness, and provenance. The unit of everything. |
| Vault | The isolation boundary. A scoped collection of memories owned by you or an org — a project, a team, a purpose. Nothing crosses vaults unless you arrange it. |
| Kind | Every memory is episodic (what happened — fades in days), semantic (what is — the default), or procedural (how we do things — holds for months). Kinds set freshness decay and can bias retrieval. |
| Tags | First-class labels ([backend], [infra]) that make memories filterable. The server suggests tags for new facts from their nearest tagged neighbours. |
| Remote | A named, tag-based view over a vault — "everything tagged #backend, nothing tagged #personal". Projects consume remotes, so one vault serves many scoped contexts. |
| Staged queue | Facts waiting for commit. Local per machine (offline buffer) and server-side (shared across your devices). Nothing is embedded until commit. |
| Review inbox | New facts too similar to an existing one (possible contradictions) are stored but flagged, excluded from retrieval, and held here for a human verdict. |
| Token | The credential. Full-account tokens are for your machines; vault-scoped tokens are for agents and can touch exactly one vault. |
03Getting started
In this app
- Create a vault (sidebar), add a memory in the Memories view, watch Review and Health as it grows.
- Account → mint tokens for other machines and agents, set a password, manage server updates.
On a machine (CLI)
# once per machine mem login --url https://mem.chrisgarlick.com --token mem_… # once per project folder — creates .mem/ and installs Claude Code hooks mem init mem link my-project --create # daily flow mem observe "We deploy via signed release tarballs." --kind procedural --tag deploy mem commit # run staged facts through the pipeline mem pull # refresh the context cache for session injection mem context --task "refactor the deploy script"
mem init wires two Claude Code hooks: SessionStart injects the cached
context block at the top of every session, and Stop nudges the agent — once per
session — to save durable lessons before finishing.
In Claude Desktop / any MCP client
Mint a vault-scoped token (Account → New token → pick the vault), then add
https://mem.chrisgarlick.com/mcp with the token as a Bearer header.
The agent gets mem_context, mem_observe, and mem_status.
04CLI reference
| Command | Does |
|---|---|
mem login --url --token | Authenticate this machine (stored in ~/.mem/credentials, 0600). |
mem init | Create .mem/ in the project + install the Claude Code hooks. |
mem link <vault> [--create] | Point this project at a vault (committed to git; holds no secrets). |
mem observe "<fact>" | Stage one atomic fact locally. --kind, --tag, --confidence. |
mem status | Local buffer + server queue counts. |
mem stage | Upload the local buffer to the server queue without committing. |
mem commit / mem push | Sync up, then commit the whole server queue — including facts staged from other devices. |
mem pull | Refresh the session-injection cache. --remote, --budget, --if-stale (ETag check). |
mem context --task "…" | Live retrieval. --kind-hint, --expand (graph neighbours), --budget, --remote. |
mem search <query> | Human-facing search: scored results with ids — the "why did the agent get told that?" tool. |
mem export | Whole vault (or --remote view) as JSON or markdown. Zero lock-in; also the team-onboarding hand-off. |
mem import --file | Bring facts in from a JSON export or a plain text list; duplicates are absorbed. |
mem remote create/ls/preview | Manage tag-rule views, with live token-count previews. |
mem org … | Orgs, members, roles, org vaults. |
05How retrieval works
When a session asks for context, every stored fact competes:
- Hybrid search — semantic similarity (embeddings) and keyword match (proper nouns like "BullMQ" that embeddings blur) run in parallel and are fused.
- Composite ranking — relevance × confidence × freshness (per-kind half-life) × (1 − staleness), nudged by how often a fact has actually been used and by the query's kind hint.
- Diversity — ten facts returned are ten different facts: near-paraphrases are dropped, not repeated.
- Token budget — ask for
budget=300and the block fits it; the estimated spend is reported on every response. - Compression — facts sharing a subject merge on render:
Kritano: uses BullMQ / targets UK SMEs.
Contradictions handle themselves: when a new fact lands very close to an old one, the old fact's staleness rises and it sinks in ranking — the vault heals toward current truth, and the flagged newcomer waits in Review for a human verdict.
06MCP tools
| Tool | Parameters | Does |
|---|---|---|
mem_context | task, limit, budget, kind_hint | Ranked plain-prose context for the task. Call at the start of work. |
mem_observe | observation, kind, tags, confidence | Save one atomic fact, verbatim. Distil before calling: one self-contained present-tense sentence. |
mem_status | — | Vault counts and health. |
MCP tokens are vault-scoped: the tools operate on the token's vault automatically and can reach nothing else.
07HTTP API
Bearer-token auth on everything except /v1/health, /v1/login,
/metrics, and these docs. Plain-prose endpoints return
X-Mem-Tokens-Estimate.
| Endpoint | Does |
|---|---|
POST /v1/login | Email + password → a fresh session token. |
GET /v1/me · POST /v1/password | Who am I; set/replace password. |
GET/POST /v1/tokens · DELETE /v1/tokens/{id} | List, mint, revoke tokens. |
GET/POST /v1/vaults · GET /v1/vaults/{slug} | Vaults. |
POST /v1/observe | Ingest one fact or a batch (observations: […], one embedding call). |
GET /v1/context | ?vault&task&limit&budget&kind_hint&expand&remote → plain-prose block. |
GET /v1/search | ?vault&q → scored JSON results. |
GET /v1/vaults/{slug}/snapshot | The session-cache block; supports ETag / If-None-Match. |
POST/GET /v1/staged · POST /v1/staged/commit · DELETE /v1/staged/{id} | Server-side staging queue. |
GET/POST…/chunks · PATCH/DELETE /v1/chunks/{id} | Memories; updates use optimistic version locking. |
GET /v1/chunks/{id}/history · POST …/rollback | Full version history; nothing is permanently lost. |
POST /v1/chunks/{id}/resolve | Approve a review-flagged memory back into retrieval. |
GET …/tags · …/remotes · …/remotes/{r}/preview | Tags and remotes. |
GET …/review · …/stats · …/log · …/graph · POST …/links/rebuild | Review inbox, health, agent log, relationship graph. |
POST/GET /v1/orgs … | Orgs, members (owner/admin/member/viewer), org vaults. |
/v1/admin/* | Self-update: version, releases, upload, install, rollback (gated, see below). |
08Security model
- Tokens are the credential. The server stores only SHA-256 hashes — a token is shown once, at mint. Revocation is immediate (≤30s of cache).
- Passwords are a door, not a key. Signing in with email + password just mints a session token. Forgot it? Log in with any account token and set a new one.
- Agent tokens are confined. A vault-scoped token sees exactly one vault everywhere — API, app, MCP — and cannot mint tokens, manage orgs, or touch updates.
- Rate limiting per caller; invalid tokens burn their own bucket.
- No phoning home. The only outbound call is to the embedding provider you configured, with your key. Fonts, UI, docs — all served from the binary.
- Releases are signed. Self-update refuses any artifact not Ed25519-signed by the operator's own key, which never leaves their machine.
09Self-hosting & updates
mem is one static binary (UI, docs, and migrations embedded) plus Postgres with pgvector. Full feature parity self-hosted, forever — no licence keys, no tiers.
- Deploy —
make releasebuilds a signed tarball;deploy/install.shsets up the systemd service.mem-api doctorverifies the whole install in one command. - Update from this app — Account → Server updates: upload the tarball, click Install. The server verifies the signature, preflights the new binary against the real database, swaps, restarts (~4s), and can roll back with one click.
- Operate —
/metricsfor Prometheus;journalctl -u mem-apifor logs; nightlypg_dumpfor backups.
For agents: a condensed, plain-markdown version of everything on this page lives at /docs.md, and a one-paragraph index at /llms.txt. Fetch those instead of parsing this HTML.