Stop re-explaining your work to the next agent.
You hit a usage limit in Codex, reopen the folder in Claude Code, and spend twenty minutes rebuilding context you already paid for. crossmem reads the session stores those tools already keep on your disk and hands the next one a clean brief. Installing it installs the agent skill too — so your agent does this without being asked.
$ crossmem list . --limit 3
1. claude · 15 hours ago · export conversations as q&a
2. codex · 2 days ago · windows store paths
3. devin · 4 days ago · devin desktop uses one sessions.db
$ crossmem load --session <ref> --full
# guardrails: AGENTS.md, CLAUDE.md authoritative
# session: the transcript context only Two halves, one idea
Every agent tool writes its conversations to disk in its own shape — JSONL here, SQLite there. That history is yours, it is already local, and no tool will read another's. crossmem is the layer that does.
The skill — what your agent reaches for
crossmem-loader ships inside the CLI and installs itself alongside it. It teaches your agent when to recover context, how to show you the candidates and wait for you to pick, and how to turn a raw transcript into a brief.
The CLI — deterministic plumbing
crossmem finds a folder's sessions across every tool, ranks them newest-first, and prints the conversation as Markdown. It decides nothing about meaning. Never guesses, never summarizes, never phones home.
The split is deliberate: summarization policy belongs to the consuming agent, not to a CLI — different agents and tasks need different amounts of history. The CLI stays the honest source; the skill brings the judgment.
Install
Homebrew
brew install muthuishere/tap/crossmemnpm
npm install -g @muthuishere/crossmemgo install github.com/muthuishere/crossmemcli/cmd/crossmem@latest The skill comes with it — nothing else to run
However you install crossmem, crossmem-loader lands in ~/.claude/skills/ and ~/.agents/skills/. A CLI your agent doesn't know about is only half installed, so this is not a second step: npm does it in postinstall, every other channel does it on the first command after an install or upgrade, and a new version refreshes it automatically.
Global only, by design — crossmem is a cross-repo layer. It never fails a command: an unwritable home directory prints one line and carries on.
crossmem install --skills --agents # force it
crossmem uninstall --skills --agents # remove it, and stop it coming back
CROSSMEM_NO_SKILL_INSTALL=1 crossmem … # skip it for this run The hot path
Because the skill is already installed, you say “resume” and your agent runs this. By hand, it is three commands.
-
See what exists for this folder
crossmem list . --limit 5Each row is the agent, how long ago it ran, and — the part that distinguishes two sessions in one folder — the first and last thing you asked. The first question is the goal; the last is where work stopped. Tool output is skipped when picking them, because agents record their own shell results as user turns.
-
Load the one you picked
crossmem load --session <ref> --fullThe ref is the handle from
list— a transcript path, ordevin:<id>/opencode:<id>/copilot-cli:<id>. Loading is identical whether that session lived in a JSONL file or a database. -
Persist it so nobody pays twice
crossmem update .Writes a committable
.crossmem/—context.md,guardrails.md,sessions.json,sources.json. Idempotent: no generated-at timestamp, unchanged files untouched, so re-running makes no diff.
Four decisions worth knowing
Guardrails ≠ history
Repo instruction files (AGENTS.md, CLAUDE.md) are marked authoritative. Transcripts are context only — what happened, never what you must do. When they conflict, the guardrail wins, and the bundle says so.
It matches by real cwd
A session maps to a folder by the working directory recorded inside its transcript, not a name guess. Dashes in folder names, relocated configs, encoded project dirs: all handled.
Worktrees are the same repo
An agent works one worktree per task, but the context often lives in the main checkout. A folder also matches its repo's other worktrees — read from git's own files, so no git binary is needed.
Your live session is excluded
load . means the previous session, not a mirror of the conversation you're in. Detected automatically for Claude Code, Codex and the Devin CLI; CROSSMEM_CURRENT_SESSION covers the rest.
Read-safety is a contract
This tool reads other tools' private stores, so the boundary is written into the code and the docs both:
- Credential files, auth databases,
*.envandvault/directories are never read — Devin'scredentials.tomlsits next to the session DB and is deliberately skipped. - The same filter applies to dumps, so a
syncpushed to a remote cannot carry a secret. exportwrites a nameless corpus: no agent name, no model name, no tokens.- No telemetry. Every operation is a local read; debug logging is opt-in and never logs transcript contents.
Also a Go library
pkg/crossmem is the same engine the CLI runs, with no process-global state — so a Go orchestrator can link it instead of shelling out to whatever crossmem is on PATH.
c, err := crossmem.New(crossmem.Options{})
sessions, err := c.List(ctx, crossmem.ListOptions{CWD: root, Limit: 5})
tr, err := c.Transcript(ctx, sessions[0].Ref)
md, err := c.Load(ctx, sessions[0].Ref, crossmem.LoadFull)
rules, err := c.Guardrails(root) Semver from v0.2.0; the JSON field names of Session, Store, QARecord, Transcript and Event are frozen. Go reference.
Design records
- ADR 1 — cross-platform store resolution — every store lists all its OS candidates in one place, with no runtime.GOOS branching.
- ADR 2 — Devin is one sessions.db — the desktop app drives the CLI over an ACP connector, so there is no separate desktop store.
- ADR 3 — the public library API — what pkg/crossmem freezes, and why it keeps no process-global state.