# mem — documentation (agent edition)

mem is portable agent memory: atomic facts stored once, retrieved as ranked plain-prose
context in any session, any tool. This file is the condensed, machine-friendly version of
/docs.html. Human page: /docs.html. Index: /llms.txt.

## Model

- **Memory (chunk)**: one atomic fact = one self-contained sentence, stored verbatim with
  embedding, confidence (0–1), staleness (0–1), kind, tags, version history.
- **Vault**: isolation boundary (per project/team/purpose). Nothing crosses vaults.
- **Kind**: `episodic` (what happened; freshness half-life ~7d) | `semantic` (what is;
  default; ~30d) | `procedural` (how we do things; ~120d).
- **Tags**: first-class labels; server suggests tags for new facts from nearest tagged
  neighbours (`suggested_tags` in observe responses).
- **Remote**: named tag-rule view over a vault, e.g. `{any:[backend], none:[personal]}`.
- **Staged queue**: facts awaiting commit. Local file per machine + shared server-side
  queue. Staging does NOT embed; commit does.
- **Review inbox**: a new fact ≥0.85 cosine to an existing one is stored flagged
  (`needs_review`), EXCLUDED from retrieval until a human resolves or deletes it, and the
  older fact's staleness is bumped +0.2.
- **Tokens**: bearer credential, hash-stored, shown once. `user` scope = full account.
  `vault` scope = agent credential confined to exactly one vault everywhere.

## Write path (how an agent should save)

Distil BEFORE calling: one self-contained, present-tense sentence per fact. mem stores
verbatim — it never rewrites. Set `kind`; add `tags` (untagged facts are invisible to
remotes); set `confidence` if you know it (else a heuristic applies).

Dispositions returned per fact: `created` | `duplicate` (≥0.97 similar — skipped) |
`flagged` (0.85–0.97 — stored but held for review).

## Read path (how an agent should retrieve)

`GET /v1/context?vault=<slug>&task=<text>` or MCP `mem_context`. Pipeline:
hybrid search (embeddings + keyword/BM25, fused) → composite score
(relevance × confidence × kind-aware freshness × (1−staleness) × usage boost × kind-hint
boost) → MMR diversity (paraphrases dropped) → optional 1-hop graph expansion
(`expand=true`) → token budget (`budget=N`; response header `X-Mem-Tokens-Estimate`) →
subject-prefix compression. Output: plain prose, one fact per line. Typical spend:
150–300 tokens.

## MCP tools (endpoint: POST /mcp, Authorization: Bearer <vault-scoped token>)

- `mem_context {task, limit?, budget?, kind_hint?}` → plain-prose context block.
- `mem_observe {observation, kind?, tags?, confidence?}` → saves one atomic fact.
- `mem_status {}` → counts and health.

## CLI

login --url --token | init (installs Claude Code SessionStart+Stop hooks) |
link <vault> [--create] | observe "<fact>" [--kind --tag --confidence] | status |
stage | commit | push | pull [--remote --budget --if-stale] |
context --task "…" [--kind-hint --expand --budget --remote] | search <query> |
export [--format json|markdown --remote --output] | import --file [--tag] |
remote create/ls/preview | org create/ls/member/vault

Server admin (`mem-api`): serve | migrate up|down | token create/list/revoke |
password set | doctor | preflight | keygen | sign.

## HTTP API (Bearer auth except health/login/metrics/docs)

POST /v1/login {email,password} → {token}          GET /v1/me
POST /v1/password {password}                        GET|POST /v1/tokens, DELETE /v1/tokens/{id}
GET|POST /v1/vaults, GET /v1/vaults/{slug}
POST /v1/observe {vault, content|observations:[{content,kind,tags,confidence}]}
GET /v1/context?vault&task&limit&budget&kind_hint&expand&remote   (text/plain)
GET /v1/search?vault&q&limit&kind_hint&remote                     (JSON, scored)
GET /v1/vaults/{slug}/snapshot?remote&limit&budget                (ETag/If-None-Match)
POST|GET /v1/staged, POST /v1/staged/commit, DELETE /v1/staged/{id}
GET|POST /v1/vaults/{slug}/chunks, GET|PATCH|DELETE /v1/chunks/{id}
GET /v1/chunks/{id}/history, POST /v1/chunks/{id}/rollback, POST /v1/chunks/{id}/resolve
GET /v1/vaults/{slug}/tags|remotes|review|stats|log|graph
POST /v1/vaults/{slug}/remotes, GET .../remotes/{r}/preview, POST .../links/rebuild
POST|GET /v1/orgs, GET|POST /v1/orgs/{slug}/members, POST /v1/orgs/{slug}/vaults
/v1/admin/version|releases|releases/{v}/install|rollback   (self-update; gated)
GET /v1/health (no auth)   GET /metrics (Prometheus, no auth)

Notes: PATCH /v1/chunks/{id} requires the current `version` (optimistic locking → 409 on
conflict). Batch observe embeds the whole batch in one provider call. Rate limit: 429 +
Retry-After when exceeded.

## Security

Tokens hash-stored, shown once, revocable (≤30s cache). Passwords only mint session
tokens; recovery = log in with any account token, or `mem-api password set` on the host.
Vault tokens: one vault only, everywhere; cannot mint tokens, manage orgs, or update the
server. Releases are Ed25519-signed; unsigned artifacts can never install. No outbound
calls except the configured embedding provider.
