sessionmem
sessionmem is a local-first MCP memory server for persisting project context across AI sessions, with tools to store, retrieve, inspect, summarize, and manage memories.
Search compact memory indexes and browse timelines by memory ID or UTC date range, including superseded history.
Retrieve memories ranked by relevance, recency, and importance, with fallback fetch/startup-injection tools for hosts lacking MCP resources or prompts.
Store single or batched memories such as decisions, facts, warnings, preferences, and summaries, with tags, importance, expiry, and redaction controls.
List all memories or fetch a specific memory by exact ID.
Permanently delete memories and reset access-pattern counters.
Ingest raw session events, summarize sessions into durable memories, and run the session-end summarization and retention-prune pipeline.
View aggregate project statistics for stored memories and ingested session events.
Keep data locally in SQLite with secret redaction and retention enabled by default; optional team sharing and cloud summarization are available per the README.
sessionmem
Project memory between sessions, stored on your machine.
New session. Claude starts fresh.
WITHOUT sessionmem:
You explain the stack. The JWT bug from last week.
The Stripe migration that's halfway done. The billing code to stay away from.
Same questions. Different day.
WITH sessionmem:
[warning] JWT blacklist must be checked before issuing new tokens. Fixed PR #47.
[decision] Stripe migration ~50% done. Do NOT use /lib/billing-v1.
[fact] Stack: TypeScript, Next.js, Postgres.
Claude: "Looks like you're mid-Stripe migration. Where do you want to pick up?"sessionmem is an MCP server that stores decisions, warnings, and project context across sessions. Claude Code hooks capture supported tool events and load relevant memories automatically. Other hosts use its MCP tools and installed instructions; session automation depends on the host. It works with Claude Code, Cursor, Cline, Codex, Windsurf, and other MCP hosts.
Default retrieval uses SQLite FTS5 BM25 and entity overlap. An optional local MiniLM model adds semantic candidates. Weights are installed separately; queries make no network calls and fall back to BM25 when local inference is unavailable. See measured comparisons for quality gains, missed questions, and latency costs.
By default, everything stays on your machine. You don't need an account or a cloud service. Data only leaves your computer if you enable sharing or cloud summarization.
Quickstart
You need a terminal (Command Prompt, Terminal, or PowerShell) and Node.js, version 20.19+ on the Node 20 line, or 22.13+. Node 22 LTS is recommended. No programming experience is required.
1. Install sessionmem
npm install -g sessionmem2. Register it with your AI tool
Run this in your project folder after configuring your AI tool (Claude Code, Cursor, etc.):
sessionmem install
# Optional: select one host explicitly, including in automation:
sessionmem install --adapter claude-code
# Other names: cursor, cline, codex, windsurf, antigravity, qcoder, genericinstall detects installed hosts from local executables, including from a plain
terminal, and configures every host found. Automatic discovery currently supports
Claude Code on PATH or in its standard native install locations. Use
--adapter <name> for the other adapters or to override discovery. The existing
SESSIONMEM_ADAPTER environment override also works; the flag takes precedence.
If no supported host is found, the command says so and exits nonzero before
creating files. Discovery and configuration work fully offline.
This initializes the database and configures the selected adapters:
Registers
sessionmemwith your AI tool's MCP host so the host can start it automatically.Creates
~/.sessionmem/config.jsonwith secret redaction enabled and a 90-day retention window, if the file doesn't already exist.Adds instructions to the selected host's guidance file, such as
~/.claude/CLAUDE.mdfor Claude Code or~/.codex/AGENTS.mdfor Codex. You can re-run the command without duplicating those instructions.Installs Claude Code's SessionStart, SessionEnd, and PostToolUse hooks and prints what was configured per host. If a host fails, the remaining hosts are still attempted and the command exits nonzero.
Enables and starts one per-user login service for
sessionmem watch. Re-running install updates that registration in place and restarts capture. Capture continues after closing the terminal and starts again at login.
Login capture uses a LaunchAgent in ~/Library/LaunchAgents on macOS, a
systemd --user service on Linux, and a Scheduled Task with a user logon trigger
on Windows. Linux requires systemd and an available user service manager; macOS
requires a GUI login session. If registration or startup fails, install exits
nonzero, preserves completed setup, and prints a repair hint. After fixing the
OS service error, run sessionmem autostart enable.
The watcher captures existing and updated Claude Code, Codex CLI, and Cursor history offline, without API keys. It starts immediately after install; no manual scan or watch process is required. Hosts outside these three can use MCP memory tools, but do not have a transcript reader.
3. Restart your AI tool
Restart your editor or agent so it loads the MCP registration. Your host starts
sessionmem run automatically; running it directly starts a stdio server that
waits for MCP messages, so it can appear to hang in a terminal. For an unknown
host (generic), install writes a project-local .mcp.json; if your host uses
another format or location, copy its server entry into that host’s MCP config.
After restarting:
In Claude Code, the installed PostToolUse, SessionEnd, and SessionStart hooks capture supported tool events, summarize them, and load prior memories automatically.
Codex and Cursor use the auto-started watcher for transcript capture. Install does not wire lifecycle capture hooks for these hosts. Their MCP tools and installed instructions provide recall and explicit memory operations.
Other MCP hosts use sessionmem's tools and installed instructions; automatic transcript capture requires a supported transcript reader.
Check the installation offline:
sessionmem doctor
# For an explicitly selected host:
sessionmem doctor --adapter claude-codeRelated MCP server: codemem
Table of Contents
What problem does this solve?
Most AI coding assistants rely on the current conversation for context. Start a new session and you may need to explain the project's setup, libraries, fixed bugs, and design decisions again.
sessionmem keeps short notes between sessions:
While you work, it captures session events.
At session end, it summarizes decisions, warnings, and useful facts into stored memories.
At the next session start, it loads the most relevant memories within a small token budget.
Claude Code runs these steps through the installed hooks. Other hosts need their agent to call the MCP memory and lifecycle tools; the installed guidance explains how to do that.
How is sessionmem different?
Compared with projects such as claude-mem and other cloud or Claude-only memory tools, sessionmem focuses on local storage and support for multiple MCP hosts:
sessionmem | Typical cloud/Claude-only memory tools | |
Where is data stored? | A single SQLite file on your computer ( | Often a hosted service, a cloud vector database, or a separate server process you have to run |
Account / sign-up required? | No | Sometimes |
Which AI tools does it work with? | Claude Code, Cursor, Codex, Cline, Windsurf, Antigravity, QCoder, and any other MCP-compatible host | Usually just one specific tool (commonly Claude Code only) |
Secret redaction | Built in, on by default. Common credential shapes (API keys, tokens, | Often not handled, or left to the user |
Token budget control | Injected memories are trimmed to a small, fixed token budget (see benchmarks below) | Varies, often unbounded |
Entity boost (optional) | Case-insensitive names and explicit aliases add a bounded score boost alongside relevance, recency and importance. Local only, defaults off. | Varies |
Scopes | Optional local context labels on sessions, memories and entity associations. Capture detects a directory or project label; queries can filter or boost a selected scope. All scopes by default. | Varies |
Old/stale memory cleanup | Built-in retention policy automatically prunes old memories (configurable, on by default) | Often no automatic cleanup ("memory rot") |
Team sharing | Optional, via a shared folder you already control (network drive, synced directory). No server needed. | Usually requires a shared hosted backend |
Offline-capable | Yes. Works with no network connection by default. | Usually requires network access to the memory service |
The SQLite file is easy to inspect, back up, or delete, and you can use it across AI tools from different vendors.
Benchmark results
npm run benchmark evaluates conversational retrieval on the committed LoCoMo
corpus: 10 conversations, 272 sessions, 5,882 turns, and 1,527 scored questions.
It captures dialogue through the public storeMemory API and asks the original
questions through retrieveMemories, fully offline with no API keys.
The evaluation reports hit rate, precision, recall, complete-evidence retrieval, and latency. Production retrieval uses offline BM25 ranking with English stemming; conversational questions test recall beyond exact copies of memory text. See benchmark results and the methodology, dataset license, and metric definitions.
npm run build
npm run benchmark
npm run benchmark -- --output benchmarks/results/locomo.jsonHow it works (in plain English)
┌──────────────────────────────────────────────┐
│ Your AI tool │
│ (Claude Code, Cursor, Codex, Cline, ...) │
└───────────────────────┬──────────────────────┘
│
┌───────────▼───────────┐ ┌──────────────┐
│ sessionmem adapter │ │ sessionmem │
│ (translates for your │ │ CLI │
│ specific AI tool) │ │ (you type │
└───────────┬───────────┘ │ commands) │
│ └──────┬───────┘
▼ │
┌──────────────────────────────────────────────┐
│ sessionmem core engine │
│ watches sessions · writes summaries · │
│ finds relevant memories · trims to fit │
└───────────────────────┬──────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ One SQLite file on your computer │
│ ~/.sessionmem/memories.db │
└──────────────────────────────────────────────┘Adapters connect each AI tool to sessionmem. Supporting another tool doesn't require changing the memory engine.
The core engine stores memories, ranks their relevance, and selects what fits in the next session's context budget. Every adapter uses the same engine.
The database is a local file. You can back it up, move it, inspect it, or delete it.
See docs/architecture.md for the technical overview.
CLI command reference
Command | What it does |
| Detect installed hosts, configure integrations, write default config, and enable login capture; the flag selects one host. |
| Check the store, schema, auto-start, binary paths, capture freshness, transcript discovery, hooks, MCP wiring, and canary recall offline; print PASS/FAIL and repair hints. |
| Start login capture, stop and unregister it, or inspect its registration and binary paths. |
| Stop and unregister login capture, then remove sessionmem from the selected host. |
| Start the MCP server. |
| Open the local read-only web viewer (default port 3777). |
| Start the local single-user REST API (default port 3778). |
| Check the local version and database reachability. |
| Search current memories by text query (limit 1–100, default 10). Include superseded facts with |
| List up to 200 recent memories for the current project; warns when truncated. |
| List extracted entities, typed relations, and their source memory IDs. Defaults to the current project. |
| List supersession chains with old/new values, source memory IDs, reasons, and timestamps. |
| Show memory details (content capped at 2000 characters; use export for full content). |
| Delete a memory by ID. |
| Export all current-project memories to JSON (default |
| Import up to 1000 valid records from UTF-8 JSON into the current project. Existing IDs are preserved, including with |
| Import existing Claude Code, Codex CLI, and Cursor transcripts into local session memories. Reports files found, sessions imported, memories created, skips, and errors. |
| Capture new or updated Claude Code, Codex CLI, and Cursor transcripts. Polls every 5 seconds by default; |
| Show memory statistics for the current project. |
| Show token savings from compression and injection, with percentage. |
| Scan stored memories for secrets; |
| Prune old memories (dry-run by default). |
| Read and write policy config. |
| Manage shared-path team memory mode. |
| Push local memories and pull teammate memories via the shared path. |
| List projects or preview up to 50 recent memories from one project. |
| Preview duplicate memories; |
| Refresh memories with stale embedding versions. |
| Print prior context as Claude Code SessionStart hook JSON. |
| Read a Claude Code PostToolUse JSON payload from stdin and capture supported tool events. |
| Summarize ingested events and apply retention pruning; reads the hook session ID from stdin. |
Use sessionmem --help or sessionmem <command> --help for options, and
sessionmem --version for the installed version. Destructive commands require
--force, --apply, or --purge as shown above. team disable preserves
teammate memories unless --remove-team-memories is passed.
The default database is ~/.sessionmem/memories.db. Set SESSIONMEM_DB_PATH
to use another file; its parent directories are created automatically and the
default directory is not created by database commands. Server logs are written
to logs/mcp.log beside the selected database (disabled for :memory:). Config remains at
~/.sessionmem/config.json. uninstall --purge deletes the selected database.
Quote paths containing spaces (for example "C:\Users\Ada Lovelace\memory.db"
on Windows). In JSON config files, use forward slashes or escaped backslashes
for Windows paths. Imports accept CRLF and a UTF-8 BOM; convert other encodings to UTF-8.
SESSIONMEM_PROJECT_ID pins the project bucket (useful when moving a repository);
otherwise it is derived from the repository root or working directory.
SESSIONMEM_ADAPTER selects the install/doctor/uninstall host unless --adapter is set.
SESSIONMEM_DEBUG=1 enables ingest-hook diagnostics on stderr.
Local REST API and JavaScript client
sessionmem serve --api
curl 'http://127.0.0.1:3778/v1/search?query=database&limit=5'This is a local single-user API, not a hosted service. It binds to 127.0.0.1
and uses the current repository's project, including SESSIONMEM_PROJECT_ID
overrides. It supports compact search, timelines, full details, saves and deletes
through the same service methods as MCP. Other projects cannot be selected by a
request. Set SESSIONMEM_API_TOKEN or --token to require bearer authentication
on every route. Cross-origin browser requests and unexpected Host headers are
rejected. Non-loopback binds require --allow-remote and print a warning.
import { SessionmemClient } from "sessionmem/client";
const client = new SessionmemClient("http://127.0.0.1:3778");
const index = await client.searchMemoryIndex({ query: "database", limit: 5 });
if (index.memories.length) console.log(await client.getMemory(index.memories[0].id));The fetch client includes TypeScript declarations and adds no runtime dependencies. See API documentation for authentication, limits, all client methods and curl examples.
Inspect memories in your browser
sessionmem ui
sessionmem ui --port 8080
sessionmem ui --port 0 # Pick an available portThe command prints its URL and opens your default browser. It binds only to
127.0.0.1, needs no authentication, and serves all assets locally using Node's
built-in HTTP server. No external services, CDNs, or additional runtime dependencies
are used. If browser launch is unavailable, open the printed URL manually. Press
Ctrl-C to stop the server and close its database connection.
The viewer starts on the current project, with a selector for other projects in
the same store. Browse saved memories, search through the existing recall path,
inspect extracted entities and relations with their source memories, and follow
supersession chains with old/new values, source IDs, assertion times, detection
times, and partial/full status. Search returns up to 50 results and defaults to
current facts; select Include superseded facts in search to recall history.
Browsing lists all saved records, including superseded and expired ones, in pages
of 50. Source IDs open full memory details. Entity visibility and history links
use the same rules as sessionmem entities and sessionmem history.
The database is opened read-only. Browsing and on-demand search do not increment
access counts, migrate the schema, or change memories. Only HTTP GET and HEAD are
accepted; no write, delete, or edit routes are exposed. Responses are not cached,
and cross-origin browser requests and unexpected Host headers are rejected. Run
sessionmem ping first to initialize a missing store or upgrade an older schema.
The usual SESSIONMEM_DB_PATH and SESSIONMEM_PROJECT_ID overrides
apply. Anyone with access to this computer can read the local viewer while it is
running; stop it when finished inspecting private memories.
Import existing sessions and watch for new ones
When a fact changes, sessionmem can link its replacement locally. For example, “I use VS Code” followed by “I switched to Neovim” supersedes the earlier editor choice. Recall excludes fully superseded memories by default. retrieveMemories accepts the optional includeHistory: true; sessionmem search --include-history searches earlier facts too. sessionmem history shows what replaced what. The old memory stays available through show, list, and export.
Detection uses deterministic entity/relation rules, shared purpose words, a small tool-category vocabulary, and explicit negation or replacement phrases. It needs no API or model. Unfamiliar wording can be missed, and ambiguous changes can be misclassified. A memory with independent claims remains searchable while any claim is current; history labels these partial supersessions. See supersession details.
Install starts capture for existing history and new sessions automatically. For a manual import or a foreground diagnostic run:
sessionmem scan
sessionmem watch --once
sessionmem watch --interval 10
sessionmem scan --host cursorBoth commands sweep all detected transcript histories by default:
Claude Code:
~/.claude/projects/**/*.jsonl.Codex CLI:
~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl.Cursor:
User/globalStorage/state.vscdbunder~/Library/Application Support/Cursoron macOS,~/.config/Cursoron Linux, or%APPDATA%/Cursoron Windows.
Missing history directories are allowed. Use --transcripts-dir "/path/to/history"
to select another transcript tree; each JSONL file's host is detected from its records.
For Cursor, the override accepts its User directory or a state.vscdb path.
Use --host cursor, --host codex, or --host claude-code to select one host,
including when using an override. A Cursor User directory or .vscdb file is
also detected without --host. Files that do not match a supported format, or
the selected host, produce an explicit unsupported format error.
Both commands work offline without API keys and always use the local summarizer,
even if cloud summarization is enabled elsewhere. sessionmem doctor checks
transcript discovery for all three hosts, parses JSONL samples, and validates
Cursor's composer indexes and message rows when history is present.
Transcript user/assistant text, supported Claude tool uses (Bash, Edit, Write,
MultiEdit), and Codex function calls pass through the existing event-ingestion,
redaction, and session-summary pipeline. Codex tool events retain the native tool
name and call_id. Encrypted agent_message payloads and obvious injected machine
blocks, including plugin catalogues and environment context, are excluded. Each
session gets one summary memory, including short sessions with only one event.
Updated sessions refresh that summary. Project buckets come from
each Claude transcript's cwd, Codex session_meta.payload.cwd, or Cursor's
workspace path, using the repository root when available; the directory where you run scan/watch does not
select the project. SESSIONMEM_PROJECT_ID can explicitly pin all imports to one
bucket. Transcripts without capturable events are skipped. Claude transcripts
without a working directory are also skipped; Codex session metadata must contain
an ID and working directory. Nested subagent files get separate session summaries.
Summary memories record sourceAdapter as claude-code, codex, or cursor
according to the transcript host. Cursor session IDs come from composerId.
Cursor stores messages in cursorDiskKV bubble rows in its global SQLite
database. The importer supports workspace composer.composerData indexes
(Cursor 2.6 and earlier) and the central composer.composerHeaders index
(Cursor 3.0 and later). It captures up to 4,000 characters of user/assistant text
per bubble and excludes tool-only bubbles and internal tool/code fields. Missing
tables, index keys, or required conversation data produce an explicit
unsupported format for cursor error.
Cursor databases are never written. Each sweep copies the database and its WAL to a private temporary directory, checking for concurrent changes during the copy. SQLite opens the copy read-only, using immutable mode when URI support is available and there is no WAL to replay. Cursor's live database is never opened by SQLite. Busy copies are reported and retried. Each sweep reads a fresh snapshot; per-composer checkpoints skip unchanged messages, and streamed bubble updates refresh the existing event without duplicating it.
Codex resumes create new rollout files. Files with the same session ID are grouped,
and replayed events are deduplicated across files, sweeps, and restarts. A Codex
sub-agent keeps its own session_meta.payload.id, even when parent_thread_id
points to a parent session.
Re-running either command does not duplicate memories or transcript events.
File and composer checkpoints live in the selected memory database, and unchanged
files or composers are skipped across restarts. For Cursor, files found counts
global databases, and skipped counts unchanged or empty composers.
Stable event IDs also make interrupted imports safe to
retry. Partial or malformed JSONL lines are reported and retried on later sweeps;
valid events in the same file can still be captured. A single sweep exits with
status 1 if it encounters errors. The daemon keeps running and retries errors.
watch prints its first sweep and subsequent imports or errors. A manual run
stays in the foreground until SIGINT or SIGTERM. Login capture uses the same
watcher with an absolute Node executable and absolute sessionmem entry point;
it does not need a shell, a TTY, or your interactive PATH.
Control login capture explicitly:
sessionmem autostart status
sessionmem autostart disable
sessionmem autostart enableenable updates one registration and starts capture immediately. disable stops
the registered watcher and removes its login registration, preserving memories.
The next sessionmem install enables it again. This control affects the login
watcher; Claude Code hooks and explicit MCP memory tools remain active.
Registrations:
OS | Registration |
macOS |
|
Linux |
|
Windows | Scheduled Task |
Capture output and failures are appended with timestamps to logs/watch.log
beside the selected database (default ~/.sessionmem/logs/watch.log). The
watcher also writes memories.db.watch-checkpoint.json beside the default store
after each completed sweep. Doctor checks this checkpoint's age, capture errors,
and transcript checkpoint count; unchanged history and an empty history are
healthy when the watcher continues completing sweeps. A checkpoint older than
two minutes fails the default 5-second watcher check. For a custom polling
interval, the limit is the greater of two minutes and three intervals.
SESSIONMEM_DB_PATH selected at install or enable is saved as an absolute
watcher argument. Run enable with that variable again to switch stores. The
policy config remains ~/.sessionmem/config.json. After moving sessionmem or
changing Node versions, run sessionmem autostart enable to update the absolute
paths. For failures before the watcher can open its log, inspect launchctl print gui/<uid>/io.sessionmem.watch, journalctl --user -u sessionmem-watch.service, or Windows Task Scheduler's task history.
Uninstall
sessionmem uninstall --adapter claude-code
# Also delete the selected memory database:
sessionmem uninstall --adapter claude-code --purgeUninstall stops capture and removes the login registration before removing MCP
configuration, Claude hooks, and agent guidance for the selected host. It keeps
the database, config and logs by default. Use the same SESSIONMEM_DB_PATH as
install when selecting a custom database to purge. If stopping or unregistering
the watcher fails, uninstall reports the OS error and leaves the database intact.
For multiple installed hosts, repeat uninstall with each adapter to remove its
MCP configuration and guidance.
Privacy, secrets, and your data
Storage, retrieval, and summarization run locally by default. There is no account, telemetry, or hosted memory service. Settings live in ~/.sessionmem/config.json.
Secrets are scrubbed automatically
Before saving memory content, sessionmem replaces common secret patterns with REDACTED:
Email addresses
API keys (
sk-..., AWSAKIA..., GitHubghp_.../gho_..., etc.)Bearer tokens and JWTs
Private key blocks (
-----BEGIN ... PRIVATE KEY-----)Connection-string style secrets (
password=...,secret=...)Prose declarations (
password is ..., quoted values or credential-shaped words)
Redaction is best-effort pattern matching, not exhaustive secret detection. Do not paste real credentials into agent chats; use your secret manager.
Redaction is on by default. To scan and clean up older memories:
sessionmem redact-scan # see what would be redacted
sessionmem redact-scan --apply # actually redact in placeFull details: docs/privacy-and-retention.md.
Memory rot: keeping memory accurate over time
Old decisions and duplicate facts can accumulate in a memory store, causing the assistant to use outdated information. This is sometimes called "memory rot."
sessionmem handles it through retention, ranking, and sync rules:
Retention pruning: memories older than a configurable window (90 days by default) are eligible for deletion. A lightweight check runs at session end. You can also run it manually:
sessionmem retention prune # dry run - shows what *would* be deleted sessionmem retention prune --force # actually deletesImportance-weighted ranking: retrieval ranks memories by offline BM25 lexical relevance, entity overlap, recency, and importance. Older, less important notes rank lower even before they are pruned.
Token-budgeted injection: only the highest-ranked memories are loaded, trimmed to a small token budget (see benchmarks). The context stays within that budget as the store grows.
Conflict resolution in team mode: merging teammate memories uses last-write-wins by id to avoid stale duplicates and keeps the higher importance score so a warning isn't downgraded.
The conversational benchmark measures retrieval quality separately from retention and startup token budgets.
Export your memories before pruning if you want to keep a copy:
sessionmem exportTeam mode (optional)
To share decisions and warnings across your team's AI assistants, point sessionmem at a folder everyone can read and write, such as a network drive or synced directory:
sessionmem team enable <shared-path>
sessionmem syncTeam mode is off by default. Nothing is shared until you enable it.
Memories are shared as files in that folder; no server is needed.
Teammate memories appear with an
author:prefix identifying their source.Redaction runs on every pulled memory using your redaction policy.
Full details, including the trust model: docs/team-mode.md.
Cloud summarization (optional, off by default)
By default, session summaries are created locally, with no API calls.
To use Claude's API for higher-quality summaries, set allowCloudSummarization=true and provide an ANTHROPIC_API_KEY. If cloud summarization fails after retries, sessionmem uses local summarization. Failures are recorded for diagnosis; see the configuration guide below.
Details: docs/cloud-summarization.md.
Automatic memory by host
After installation, the login-started watcher captures supported local transcripts. Recall on hosts without native hooks follows installed agent instructions, so it depends on the agent executing the memory tools.
Host | Capture | Recall |
Claude Code | Tool/end hooks and transcript watcher | SessionStart and UserPromptSubmit hooks inject context |
Codex | Rollout watcher | Global AGENTS.md and MCP instructions require startup and new-topic searches |
Cursor | Composer SQLite watcher | Project always-apply rule and MCP instructions require searches |
Windsurf, Cline | Instructed agent saves; no transcript importer | Installed rules and MCP instructions |
Antigravity, QCoder | Instructed saves; native adapter paths remain unverified | Instruction-driven, subject to host loading |
Generic MCP | Instructed saves if the host reads AGENTS.md or MCP instructions | Instruction-driven, subject to host support |
Install detects available Claude Code, Codex, Cursor and Windsurf CLI executables.
Other hosts use --adapter at setup. Missing guidance now fails installation.
Doctor checks capture and recall separately, identifies instruction-driven modes,
and provides repair hints. See automatic memory for
exact scope, supported formats, tool permissions and the CI install-to-recall test.
Memory retrieval tools
Use searchMemoryIndex for a compact list of matches, memoryTimeline to inspect
nearby records, and getMemory for selected full details. Compact tools default
to 10 results and cap one-line summaries at 160 characters. See
retrieval tools and optional ranking for inputs,
visibility rules and measured token costs.
Temporal retrieval defaults off because it did not improve the pinned-clock
LoCoMo run. Entity coverage is enabled for BM25 and disabled when MiniLM is
active. This raises default hit rate from 63.92% to 64.44%, precision from 14.05%
to 14.32%, and recall from 57.45% to 58.27%; optional hybrid quality is preserved.
The entityLinkBoost setting overrides this automatic choice. Source-informed
adaptive and additive alternatives remain opt-in. See
all before/after results and losses.
An independent bounded entity boost is available with
sessionmem config set entityBoost true. Exact names and explicit aliases can
add at most 0.06 to the final ranking score, while recency and importance still
apply. Queries without known entities keep their scores. It defaults off:
LoCoMo hit rate @5 rose from 64.44% to 64.51%, but precision and recall fell.
See the measured tradeoffs. Compact search, timeline
and details by ID keep the same interfaces and response limits.
Capture also records an optional context label called a scope. It uses the real
working directory name, falling back to the project ID for headless capture.
Override it with scope on capture requests, --scope <name> on scan/watch,
SESSIONMEM_SCOPE, or sessionmem config set scope <name> for new sessions.
Run sessionmem scopes --json to inspect local labels and counts.
sessionmem search "deployment" --scope release filters a context;
adding --scope-mode boost favors that context while retaining other results.
Queries without a scope keep their existing response bytes and ranking.
Existing databases upgrade automatically without labelling historical records.
See scope behavior and migration safety.
Supported tools
sessionmem works with any MCP-compatible host, including:
Claude Code
Cursor
Codex
Cline
Windsurf
Antigravity
QCoder
Other tools that implement the Model Context Protocol can connect too.
Further documentation
Automatic memory: capture and recall per host, diagnostics and CI evidence.
Retrieval tools: compact search, timeline, full details and optional ranking.
Architecture: how the core engine, adapters, CLI, and SQLite storage fit together.
Benchmark: conversational retrieval results and reproduction steps.
Privacy and retention: secret redaction, retention pruning, and config.
Team mode: shared-path team memory.
Cloud summarization: the opt-in cloud summarization path.
Migration: the SQLite migration system and version-upgrade policy.
Troubleshooting: install failures, adapter issues, and
better-sqlite3native-build problems.
Troubleshooting
For install failures, adapter issues, missing session data, or better-sqlite3 native-build problems, see docs/troubleshooting.md.
Start with offline diagnostics:
sessionmem doctor
sessionmem doctor --adapter claude-code # explicit host overridedoctor reports a separate PASS or FAIL for the memory store, schema, transcript
discovery for Claude Code, Codex and Cursor, login auto-start registration,
registered binary paths, watcher capture checkpoint freshness, hook definitions
shipped with the current version, configured MCP command, and a canary
write/recall. It exits nonzero if any check fails and prints fix hints,
including exact commands for safe repairs. It does not create a missing store or
apply migrations. Its temporary canary is isolated from your projects and rolled
back even on failure. The MCP check starts the installed local command and verifies
its version, tools, and a stats response; it does not require a running agent.
Use sessionmem ping to initialize a missing store or apply pending schema
migrations, or sessionmem install --adapter claude-code to refresh Claude Code's
MCP registration and hooks. Use sessionmem autostart enable to refresh the
login service and absolute binary paths; inspect logs/watch.log beside the
database when capture fails. Run repairs with the same SESSIONMEM_DB_PATH as
doctor when using a custom store.
If stats shows sessions: 0 after real work, see “0 sessions” / no session data recorded. Memories are keyed to the repository root, so every directory inside one repo shares a bucket; outside a repo the working directory itself is the key.
To check database access and memory counts:
sessionmem ping # can the local database be opened?
sessionmem stats # is data being stored?FAQ
How do I give Cursor, Cline, or Windsurf memory between sessions?
Install sessionmem (npm i -g sessionmem), then run sessionmem install in your project. Use --adapter cursor, --adapter cline, or --adapter windsurf when auto-detection cannot identify your host.
How do I give Claude Code persistent memory?
Use the same install steps above. sessionmem also ships as a Claude Code plugin (the .claude-plugin directory in the repo) for Claude Code's native plugin system.
Is there a local MCP memory server that works offline with no API key?
Yes. sessionmem stores memories in a single SQLite file at ~/.sessionmem/memories.db and works offline by default. Sharing and cloud summarization are optional and off by default.
How is sessionmem different from claude-mem? sessionmem works with Claude Code, Cursor, Cline, Codex, Windsurf, Antigravity, QCoder, and other MCP hosts. It redacts secrets (API keys, tokens, JWTs) by default, prunes old memories automatically, and includes reproducible benchmarks.
Does sessionmem send my code to the cloud? No. Nothing leaves your machine by default. The optional cloud summarization path is opt-in and off by default.
How do I see how many tokens sessionmem saved me?
Run sessionmem savings to see a breakdown of storage compression (raw session tokens vs memory tokens) and injection efficiency. Add --json for machine-readable output.
Security
See the security policy for supported versions, private vulnerability reporting through GitHub security advisories, and response expectations.
Contributing
Issues and pull requests are welcome. The codebase is TypeScript, tested with Vitest, and linted with ESLint:
npm ci
npm run build
npm run typecheck
npm test
npm run lintMCP config for local development: Clone the repository, build it, copy
.mcp.json.example to .mcp.json, and replace the example path with the absolute
path to your checkout’s dist/cli/index.js. This runs your local build.
sessionmem install registers the sessionmem executable on PATH instead. The .mcp.json file is gitignored because it contains machine-specific paths.
License
Available Tools
15 toolsbatchStoreMemoryA
Persist multiple memory units in a single atomic SQLite transaction. Significantly faster than calling storeMemory repeatedly for session-end writes of 10-20 memories.
WHEN TO CALL: At session end or whenever you have multiple memories to store at once. Reduces overhead from per-insert fsync by wrapping all writes in one transaction.
WHEN NOT TO CALL: For a single memory — use storeMemory instead. For imports from external files — use importMemories.
Each item in the memories array follows the same schema as storeMemory (memoryId, sessionId, sourceAdapter, kind, content, importance). Invalid items are reported individually; valid items are still stored atomically.
NOTE: the per-item memory echoed back in the response has its content truncated to 2000 characters (a batch can return many rows). The full body is still persisted — fetch it with getMemory if you need the complete text. (Single-record storeMemory echoes the full content.)
Inputs: memories (required).
fetch_memoriesA
Fallback memory retrieval for hosts that do not support MCP resources. Call this instead of accessing the sessionmem:// resource URI directly when the host lacks resource support. Semantically equivalent to retrieveMemories — returns stored memories ranked by relevance to the query. Read-only; no side effects.
WHEN TO CALL: At session start and mid-session when you need to retrieve context and the host does not support MCP resources. Do not call if the host supports MCP resources — use the sessionmem:// resource URI or retrieveMemories tool instead.
Parameter query: natural-language description of what context you need to recall (e.g. 'API design decisions', 'database schema choices').
Inputs: query (required).
forgetMemoryADestructive
Permanently delete a single memory by ID. The record is removed from the local SQLite store immediately and CANNOT be recovered. Destructive and irreversible.
WHEN TO CALL: Only when a memory is known to be incorrect, dangerously outdated, or a duplicate that would mislead future sessions.
WHEN NOT TO CALL: If there is any doubt. A memory that is merely old or low-relevance does not need deletion — retrieval ranking deprioritizes it automatically.
Inputs: memoryId (required).
getMemoryARead-onlyIdempotent
Fetch a single memory record by its exact ID. Returns the full record: content, kind, importance, timestamps, and session metadata. Read-only; no side effects.
WHEN TO CALL: After searchMemoryIndex or memoryTimeline, fetch selected IDs for full details. IDs from retrieveMemories or listMemories also work.
For topic searches, start with searchMemoryIndex. getMemory requires an exact ID.
Inputs: memoryId (required).
handleSessionEndAIdempotent
Run the full session-end pipeline: auto-summarize the session's ingested events into a durable memory (when enough events exist) and apply a light retention prune of stale memories. Idempotent on the summary memory (upsert by sessionId).
WHEN TO CALL: Once, at the very end of a session, after ingesting session events via ingestSessionEvents. Lets sessionmem generate and store the session summary for you.
WHEN NOT TO CALL: Mid-session, or when you have already written your own summary (use summarizeSessionToMemory instead). On Claude Code this also runs automatically via the installed SessionEnd hook, so calling it explicitly is usually unnecessary there.
Provide sessionId and sourceAdapter. memoryId (optional) pins the summary's id; omit to derive ${sessionId}-summary. config (optional) tunes autoSummarize / minimumEventThreshold / cloud summarization; omit for sensible local-only defaults.
RESPONSE status is one of: 'stored', 'skipped_threshold' (too few events), 'skipped_disabled', 'failed'. warningCodes may carry cloud/local fallback signals.
Inputs: sessionId (required), sourceAdapter (required), scope, config, +2 more.
ingestSessionEventsAIdempotent
Push raw session events (tool calls, decisions, file edits, user turns) to sessionmem so they can be summarized at session end and counted toward token-savings analytics. Writes immediately, in a single transaction. Re-ingesting the same (sessionId, eventIndex) is a no-op, so retries are safe.
WHEN TO CALL: Periodically during a session (e.g. at task boundaries) to record what happened, OR in one batch shortly before the session ends. This is what powers automatic session-end summarization and sessionmem savings.
WHEN NOT TO CALL: For durable, individually-important facts/decisions — use storeMemory for those. Session events are transient raw material for summarization, not first-class memories.
Each event needs: id (unique), eventIndex (monotonic 0-based order within the session), eventType (e.g. 'tool_use', 'user_message'), payloadJson (a JSON string of the event body).
LIMITS: at most 500 events per call. For more than 500 events, call this tool multiple times in chunks — re-ingestion of already-stored events is safe (idempotent via the (project, session, eventIndex) UNIQUE index), so overlapping chunks never double-count.
Inputs: events (required), sessionId (required), scope, replaceExisting, +1 more.
listMemoriesARead-onlyIdempotent
Return every memory stored for the current project, unfiltered and without ranking. Read-only; no side effects.
WHEN TO CALL: When you need a complete inventory of stored memories — to audit what has been saved, detect duplicates, or build a full summary of all known context.
WHEN NOT TO CALL: For normal context loading at session start — use retrieveMemories instead, which ranks by relevance. listMemories returns the entire store unfiltered and can be very large.
Inputs: limit.
memoryTimelineARead-onlyIdempotent
Browse compact memories in capture order around memoryId, or within an inclusive UTC fromDate/toDate range. Provide an ID or both dates. Includes superseded history by default. Default limit 10, maximum 50. Use getMemory for full details. Does not update access counters.
Inputs: limit, scope, toDate, fromDate, +2 more.
resetAccessCountsAIdempotent
Reset access-pattern counters for all memories in the current project. Sets access_count to 0 and clears last_accessed timestamps without deleting any memories. Useful after large refactors when old access patterns no longer reflect current relevance.
WHEN TO CALL: After major codebase restructuring, project pivots, or when access-boosted rankings no longer reflect current relevance.
WHEN NOT TO CALL: During normal operation — access patterns self-correct as usage shifts.
Inputs: no named parameters.
retrieveMemoriesA
Semantically search stored memories and return the top matches ranked by a weighted combination of relevance, recency, and importance. Read-only; no side effects.
WHEN TO CALL: (1) At the start of every session — pass the current task or file as the query to pre-load relevant context. (2) Mid-session whenever a new topic, file, or decision area arises that may have prior context. Do NOT call on every user turn.
WHEN NOT TO CALL: If you already retrieved memories for this topic this session. Use getMemory if you have a specific memoryId. Use listMemories only to audit the full store, not for context loading.
Returns up to limit results (default 20). mode='auto' is the standard startup path; mode='on-demand' signals an explicit mid-session lookup. depth='deep' runs a broader semantic sweep at higher latency — use when the topic is unfamiliar. Phrase query as what you need to recall, not what you are about to do.
NOTE: this tool updates access-pattern counters on the memories it returns (used to boost frequently-recalled memories in future ranking), so it is NOT side-effect-free despite being a lookup.
Inputs: query (required), mode, tags, depth, +2 more.
searchMemoryIndexARead-onlyIdempotent
Search a compact memory index. Returns IDs, one-line previews, kinds, capture dates and scores. Start here for topic lookups, use memoryTimeline for nearby context, then getMemory for selected full bodies. Default limit 10, maximum 50. Does not update access counters. hasMore refers to the bounded candidate pool.
Inputs: query (required), tags, limit, scope, +2 more.
startup_inject_memoriesA
Fallback startup-injection for hosts that do not support MCP prompts. Call this once at the very start of a session instead of relying on the automatic sessionmem startup prompt when the host lacks prompt support. Injects the top relevant memories for the current project into the working context. No parameters required.
WHEN TO CALL: Once per session start, before any user task work begins, when the host does not surface MCP prompts automatically. Do not call if the host already surfaces the sessionmem startup prompt — calling both duplicates injected context.
Note: access counts are incremented on retrieval.
Inputs: no named parameters.
statsARead-onlyIdempotent
Return aggregate statistics for the current project: total stored memory count and total ingested session event count. Read-only; no side effects.
WHEN TO CALL: For diagnostic or monitoring purposes — to confirm memories were stored after a session, check store health, or report usage numbers.
WHEN NOT TO CALL: As part of normal context loading. stats returns counts only, not content; use retrieveMemories to load actual context.
Inputs: no named parameters.
storeMemoryA
Persist a single memory unit to the local SQLite store. Accepts decisions, facts, architectural choices, warnings, and session summaries. NOT idempotent — each call creates a new record even with identical content. Writes to disk immediately.
WHEN TO CALL: After any significant decision, discovery, or conclusion that should be available in a future session. Good candidates: technology choices, non-obvious constraints, bug root-causes, architectural decisions, key facts about the codebase.
WHEN NOT TO CALL: For trivial observations, transient state, or content that duplicates what was just retrieved. Do not store entire files or full conversation transcripts.
kind categories: 'decision', 'fact', 'summary', 'warning', 'preference'. Write content to be self-contained — it must be useful without any surrounding conversation context. importance 1-10 (10 = most critical); directly affects retrieval ranking in future sessions.
RESPONSE may include warningCodes: 'session_write_limit_warning' (this session has stored many memories — stop storing trivia and prefer batchStoreMemory) and 'redaction_partial_failure' (a redaction rule errored; the write still succeeded). Treat them as advisory signals, not errors.
Inputs: kind (required), content (required), memoryId (required), sessionId (required), +5 more.
summarizeSessionToMemoryAIdempotent
Store an agent-authored session summary as a durable 'summary' memory in one call. Upserts on memoryId, so calling it again with the same memoryId replaces the prior summary rather than duplicating it.
WHEN TO CALL: At session end when you have already written a concise summary of what was accomplished and want to persist it directly (the simpler alternative to handleSessionEnd's automatic summarization).
WHEN NOT TO CALL: When you want sessionmem to generate the summary from ingested session events — use handleSessionEnd for that. For non-summary facts/decisions use storeMemory.
Provide: memoryId (stable id for this session's summary), sessionId, sourceAdapter, summary (the text), importance (1-10; 7 is typical for summaries).
Inputs: summary (required), memoryId (required), sessionId (required), importance (required), +3 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 15 tools
Four tools retrieve memories (retrieveMemories, fetch_memories, searchMemoryIndex, startup_inject_memories) and three browse the store (listMemories, memoryTimeline, searchMemoryIndex), creating real selection risk. Descriptions do explain the distinctions (host-capability fallback vs. ranked search vs. index scan), but an agent must read carefully to avoid duplication, and startup_inject_memories overlaps heavily with retrieveMemories at session start.
Most tools use camelCase verb_noun (storeMemory, getMemory, forgetMemory, batchStoreMemory), but two use snake_case (fetch_memories, startup_inject_memories). Also, for a memory domain, the noun is sometimes 'Memory' and sometimes omitted (stats, handleSessionEnd), which weakens the pattern.
15 tools sits at the upper bound for a memory server, and several earn their place only in niche host configurations (fetch_memories, startup_inject_memories, resetAccessCounts). The core lifecycle could be covered with roughly 10 tools; the extra fallback/administrative surface makes the set feel heavy.
Coverage is broad: create, batch create, semantic retrieve, index search, timeline browse, get, list, delete, session events, summaries, and stats. The notable gap is updating/editing an existing memory's content or importance — only summaries upsert, so corrections require forget + store.
Maintenance
Related MCP Connectors
Shared memory MCP server for Claude Code, Codex, Gemini CLI and Cursor. Cited, editable.
Hosted MCP memory: save sessions/decisions once, search from Claude, Cursor, ChatGPT. EU-hosted FTS.
Persistent memory for AI assistants. Save once; recall from Claude, ChatGPT, or any MCP client.
Give your AI agent persistent, governed memory for every project. At task start it recalls the approved decisions, conventions, risks and architecture (semantic search, ranked by importance); at close it proposes what was learned as typed memories that you review and approve — governance, not a notes dump. Agents propose, humans govern: edits go back to pending and deletion is human-only by design. Connect Claude Code, Cursor, Claude Desktop or any MCP client in two minutes with just your API key — hosted (nothing to install) or locally via `uvx solucortex-mcp`. Built by SoluAI and dogfooded daily: SoluCortex is developed using its own living memory.
Related MCP Servers
- AlicenseAqualityBmaintenancePersistent memory MCP server for Claude Code, Cursor, and GitHub Copilot. Semantic search, Git sync, project-based, Persistent memory MCP server for Claude Code, Cursor, and GitHub Copilot. Semantic search, Git sync, project-based organization, and team collaboration via Model Context Protocol.15342 npm2MIT
- AlicenseBqualityBmaintenancePersistent memory MCP server that captures coding session context and automatically injects relevant memories into prompts using hybrid search for OpenCode and Claude Code.1482MIT
- AlicenseBqualityCmaintenanceCross-tool AI memory MCP server for Claude Code, Cursor, Antigravity, Windsurf, and every MCP-compatible AI. 400 tokens not 4,000.35MIT
- AlicenseAqualityCmaintenanceLocal-first MCP server that gives any AI coding agent per-project memory, workflow intelligence, and always-on, lossless token & context optimization.3765 npm6MIT