Operations

Last verified against the code: 2026-11-13 (0.9.0)

Remem runs on one machine, as the person. There is nothing to deploy and no secret anywhere.

Files on disk

Path What Written by
~/.remem/memory.db The store (SQLite): episodes, sessions, lessons, predictions ingest, recall (touches), sleep, serve (remember)
~/.remem/lessons.jsonl The wire format: one lesson per line sleep
~/.remem/morning.md Last night's report sleep
~/.claude/projects/<project>/*.jsonl The raw stream: Claude Code's transcripts (read only) Claude Code
~/.claude/projects/<project>/memory/om-<id>.md One rendered lesson sleep (render)
~/.claude/projects/<project>/memory/MEMORY.md The index Claude Code loads; Remem owns one marked section sleep (render), Claude Code
~/.claude/projects/<project>/memory/written.json, vetoed.json What render wrote; what the owner vetoed sleep (render)

Back up ~/.remem to keep the memory; the raw stream is Claude Code's own and can be re-read at any time (remem ingest after deleting memory.db rebuilds everything except notes, touches and vetoes).

Configuration

Variable Default What it does
REMEM_HOME ~/.remem Where the store, lessons.jsonl and morning.md live
CLAUDE_PROJECTS_DIR ~/.claude/projects Where transcripts are read and memory folders written
REMEM_LLM 1 0 (or false, off) disables the local model
REMEM_LLM_URL the first of localhost:1234/v1 (LM Studio) and localhost:11434/v1 (Ollama) that answers, probed once per process with a one-second timeout The OpenAI-compatible endpoint
REMEM_LLM_KEY unset A bearer token sent by remem experiment to a hosted model (the frontier replication, goal A4); never stored by Remem
REMEM_LLM_MODEL first listed The model id; otherwise the first in GET /models
REMEM_LLM_TIMEOUT 120 Seconds per completion
REMEM_UPSTREAM the local model server that answers (as REMEM_LLM_URL) Where remem proxy forwards OpenAI-compatible requests, e.g. https://api.openai.com/v1
REMEM_ANTHROPIC_UPSTREAM https://api.anthropic.com Where the proxy forwards /v1/messages
REMEM_PROXY_TIMEOUT 600 Seconds per proxied request
REMEM_PROXY_MEMORY moment Where the proxy puts the memory: moment (only a lesson the message meets, plus the end-of-turn reminder; paper §7.3), first (the whole memory as its own system message before the app's, one cached prefix for every app) or last (after the app's system prompt)
REMEM_PROXY_LOG unset Any value: the proxy logs each request to stderr
REMEM_SHARE_DIR unset, then ~/.remem/share-target A folder or a commons URL every sleep syncs with; the target last synced by hand is remembered in share-target
REMEM_COMMONS_TOKEN ~/.remem/commons-token The bearer token the commons wants until launch
CODEX_HOME ~/.codex Where Codex CLI keeps sessions/, read by ingest
GEMINI_HOME ~/.gemini Where Gemini CLI keeps tmp/ (saved chats, checkpoints), read by ingest
REMEM_HOLDOUT 0.5 Share of sessions whose reminders are logged but not shown (the experiment)
REMEM_EMBED auto: the first Ollama model with "embed" in its name, else hashed hash keeps hashed words; or an Ollama model name
REMEM_EMBED_URL http://localhost:11434 The Ollama server for embeddings
REMEM_EMBED_TIMEOUT 60 Seconds per embedding batch

The local model

Any OpenAI-compatible chat server. LM Studio is the default because it listens on port 1234 with no setup. The model is asked to write a session gist (300 tokens) per ingested session and a lesson (80 tokens) per new lesson, with temperature 0.2. Reachability is checked once per process with a two-second timeout; a server that is down costs two seconds and nothing else.

This machine (AMD Ryzen AI MAX+ 395, Radeon 8060S, 128 GB unified memory) runs mid-size local models comfortably. Ollama 0.40.8 is installed under ~/.local/ollama (no sudo) and runs as a user service (~/.config/systemd/user/ollama.service, systemctl --user status ollama, started at boot through loginctl enable-linger), with hf.co/unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF:Q4_K_M pulled for sleep (Ollama's own qwen3:30b-a3b-instruct-2507-q4_K_M tag is the same model): a mixture-of-experts instruct model (no thinking) that is fast on this hardware and only needs to summarize and to write one careful sentence. ~/.local/ollama/bin/ollama ps shows whether a run used the GPU.

For embeddings (0.2.0), qwen3-embedding:0.6b is pulled (640 MB; curl localhost:11434/api/pull -d '{"model":"qwen3-embedding:0.6b"}' if the ollama binary is not on the PATH). Ingest embeds one batch per transcript; a sleep that switches spaces embeds every memory again, about a second for the owner's store.

The commons

/commons/ on the same Worker (src/commons.js), stored in the KV namespace COMMONS (ff0b3287315c467aa4b5b12ac8d17722, bound in wrangler.jsonc). The secret COMMONS_TOKEN gates reads and writes until launch; the owner's copy is ~/.remem/commons-token (mode 600; never in a repository). Rotate it with npx wrangler secret put COMMONS_TOKEN --name remem and copy the new value to every machine. This machine syncs there every sleep (~/.remem/share-target); its origin is remem share whoami. Inspect with curl -H "authorization: Bearer $(cat ~/.remem/commons-token)" https://remem.acific.com/commons/index.

Releasing

A release is done only when uv run python scripts/release-check.py passes every line (AGENTS.md rule 17). The order: bump VERSION and pyproject.toml, CHANGELOG and MIGRATIONS entries, docs (every "last verified" header, Appendix A, README, home page, ROADMAP's where we left off), tests and npm test, uv tool install --reinstall -q ., uv run python scripts/live-snapshot.py, npm run deploy, commit and push, the handbook log and the memory notes, then the release check.

The installer

npm run build builds a wheel from the checkout (uv build), puts it and install.sh (its SHA-256 written in) in dist/install/; the Worker serves /install/ only with the commons token. remem share invite prints the line. /version.json (public) says what is deployed.

The site: remem.acific.com

A Cloudflare Worker named remem serving dist/ as static assets through the ASSETS binding (wrangler.jsonc: assets.directory is dist, run_worker_first so the gate sees every request, the custom domain remem.acific.com on the acific.com zone, workers_dev on). npm run deploy builds and deploys; it needs npx wrangler login once on the machine. The pre-launch gate is on when the GATE_PASSWORD secret is set (npx wrangler secret put GATE_PASSWORD; the shared password from the handbook) and off otherwise, so local npm run dev is open. It is off: the secret was deleted on 2026-11-09 and the whole site is public; put the secret back to close it again. Every response carries the security headers of SECURITY.md, set in src/worker.js; /.well-known/security.txt is served without the password. /live/ shows the store as of the last uv run python scripts/live-snapshot.py (it copies the store to a temporary home, adds one repeated error and one correction, runs the real sleep there with the local model, and writes site/live/snapshot.json; run it before a deploy when the page should show today). Assets are cached four hours at the edge: bump V in scripts/build-site.mjs when a file under site/assets/ changes. The okay loader files come from okaydesign (npm run sync there); remem is listed in its consumers.json.

This machine, as left on 2026-10-24

0.2.0 is installed (uv tool install --reinstall . from the checkout; the remem on the PATH is that install, not the checkout, so reinstall after every change or the cron runs old code). Embeddings come from qwen3-embedding:0.6b. The store after the 0.2.0 sleep: 23 memories, 3 lessons (two themes and one single correction), 3 open predictions; the store from before is at ~/.remem/memory.db.before-0.2.0.

As left on 2026-10-22

The owner's Linux box (amd-halo): the hook, the MCP server and the 4 am cron are wired in; Ollama runs as a user service with the instruct model above; wrangler is logged in as the owner (npx wrangler whoami), so npm run deploy works; the GATE_PASSWORD secret is deleted (the site is public since 2026-11-09); Dependabot alerts and security updates are on for the repository. The store holds the first full run (11 memories, no lessons yet); ~/.remem/morning.md is what sleep last wrote.

The nightly job

0 4 * * * remem sleep >/dev/null 2>&1

Sleep runs in well under a second without a model on hundreds of episodes; with a model it takes as long as the model needs per new lesson. It is safe to run twice. The report is in morning.md either way.

The hook

remem ingest --quiet on Claude Code's SessionEnd (remem hook prints the JSON). Ingest with a model takes one completion per session; without one it is instant. A session that is still open is re-read on its next end because its mtime changed.

remem prime on UserPromptSubmit (0.2.0) reads the hook's JSON on stdin and prints the lessons the prompt bears on, which Claude Code adds to the prompt's context. It embeds one text (tens of milliseconds with Ollama warm; the embedding timeout is three seconds here) and scores every lesson. Shown lessons are remembered per session in ~/.remem/primed/<session>.json; every prime is appended to ~/.remem/primed.jsonl. Any failure prints nothing and exits 0. Since 0.2.1 the same command answers Stop (prints {"decision": "block", "reason": …} when the reply ends in a hand-back and a correction lesson bears on it; nothing when stop_hook_active) and PreToolUse (prints {"hookSpecificOutput": {"hookEventName": "PreToolUse", "additionalContext": …}}). REMEM_HOLDOUT (default 0.5) is the share of sessions whose primes are logged with "shown": false and not shown. Wired on the owner's machine since 2026-10-24 by remem setup (backup: ~/.claude/settings.json.before-remem).

Monitoring

remem status is the dashboard: counts, the model found, what to run next. The morning report's first line has the trend; comparing predictions confirmed with failed over weeks is the system's own fitness signal (paper §7.3).

Troubleshooting

Problem Where to look
Ingest reads nothing remem paths; ls $CLAUDE_PROJECTS_DIR/*/*.jsonl
A lesson keeps coming back after deleting it It was not written by render (no remem- prefix) or vetoed.json was removed
The site does not resolve from this machine right after the domain was attached The local resolver (and the router's) cached the miss from before the record existed; Cloudflare's own resolvers answer. Wait for the negative TTL, flush with resolvectl flush-caches, or test with curl --resolve remem.acific.com:443:<edge ip>
memory.db is locked Two commands at once (cron sleep during a hook ingest); SQLite waits five seconds by default, then fails; rerun
A rendered file has the wrong project Episodes carry the cwd of their session; sessions started from ~ render into ~'s project
The model times out Raise REMEM_LLM_TIMEOUT or load a smaller model; or --no-llm