Technical knowledge persistence for Claude Code. Extracts durable knowledge from conversations -- commands, errors, discoveries, procedures, warnings -- and injects relevant memories into future sessions.
- After each session (or before a context compaction), a hook extracts reusable knowledge from the transcript using Claude.
- Before each prompt, a hook searches stored memories with hybrid (semantic + keyword) retrieval and injects the relevant ones as context.
- Knowledge is embedded as 4096-dim vectors and stored in LanceDB (embedded, in-process -- no server).
- A maintenance system handles consolidation, conflict resolution, quality deprecation, relation discovery, global promotion, warning synthesis, and conservative stale validity checks.
- Each injection is rated for usefulness on the next session and the score feeds back into ranking.
- Node.js >= 20
- pnpm (package manager)
- Embedding API -- any OpenAI-compatible endpoint serving a 4096-dim model (e.g. LM Studio with
qwen3-embedding-8b, or a remote inference server) - Anthropic credentials -- one of:
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN, or signed-in Claude Code OAuth credentials
LanceDB itself is embedded -- nothing to install or run.
The wizard is the recommended way to install. It tests your embedding endpoint, detects Anthropic credentials, writes config, and installs hooks, slash commands, and the MCP server into your Claude Code config in one shot.
git clone <repo-url>
cd claude-memory
pnpm install
pnpm build # required -- the wizard installs hooks pointing at dist/
pnpm wizardWhat it asks (in order):
- Embedding server -- base URL (default
http://127.0.0.1:1234/v1), model name (defaulttext-embedding-qwen3-embedding-8b), whether the server needs an API key, whether to skip TLS verification (HTTPS only). Probes the endpoint and reports the actual embedding dimension. - Anthropic credentials -- auto-detects
ANTHROPIC_API_KEY/OPENCODE_API_KEY/ANTHROPIC_AUTH_TOKENand Claude Code OAuth tokens. If none are found, prompts for an API key and verifies it with a small Claude call. - Vector storage -- LanceDB directory (default
~/.claude-memory/lancedb) and table name (defaultcc_memories). - Extraction model -- pick from a short list (Sonnet 4.5 by default).
- Install -- writes
~/.claude-memory/config.jsonand updates~/.claude/settings.jsonwith:- Hooks:
UserPromptSubmit->pre-prompt.js,SessionEndandPreCompact->post-session.js, and matcher-qualifiedPostToolUse(memory_write) ->memory-write-hint.js - Slash commands:
/prior-knowledge(show injected memories),/remember(mark conversation for extraction),/skip-extraction(skip extraction for this session) - MCP server:
claude-memory(read-onlysearch_memoriestool)
- Hooks:
After the wizard finishes, start (or restart) Claude Code. Memories will accumulate automatically. Open the dashboard with pnpm dashboard to inspect them.
If anything in the wizard goes wrong (e.g. the embedding server is offline), it warns but continues -- you can edit ~/.claude-memory/config.json and re-run pnpm wizard later.
Skip the wizard if you'd rather wire things up yourself. Add to ~/.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [{
"hooks": [{ "type": "command", "command": "node \"/path/to/claude-memory/dist/hooks/pre-prompt.js\"", "timeout": 15 }]
}],
"SessionEnd": [{
"hooks": [{ "type": "command", "command": "node \"/path/to/claude-memory/dist/hooks/post-session.js\"", "timeout": 15 }]
}],
"PreCompact": [{
"hooks": [{ "type": "command", "command": "node \"/path/to/claude-memory/dist/hooks/post-session.js\"", "timeout": 15 }]
}],
"PostToolUse": [{
"matcher": "memory_write",
"hooks": [{ "type": "command", "command": "node \"/path/to/claude-memory/dist/hooks/memory-write-hint.js\"", "timeout": 5 }]
}]
},
"mcpServers": {
"claude-memory": {
"command": "node",
"args": ["/path/to/claude-memory/dist/mcp-server.js"]
}
}
}The MCP server is optional -- relevant memories are already auto-injected by the pre-prompt hook. The MCP search_memories tool is for explicit "look up that thing I stored" requests.
Configuration is loaded in this order (later overrides earlier):
- Defaults (with env vars as the lowest-priority fallbacks)
- Global config --
~/.claude-memory/config.json - Project config --
<project-root>/config.json - Settings overrides --
~/.claude-memory/settings.json(per-keyCC_MEMORIES_SETTING_*env vars also apply)
{
"lancedb": {
"directory": "~/.claude-memory/lancedb",
"table": "cc_memories"
},
"embeddings": {
"baseUrl": "http://127.0.0.1:1234/v1",
"model": "text-embedding-qwen3-embedding-8b",
"apiKey": "optional-bearer-token",
"insecure": false
},
"extraction": {
"model": "claude-sonnet-4-6"
}
}| Variable | Default | Description |
|---|---|---|
CC_MEMORIES_LANCEDB_DIR |
~/.claude-memory/lancedb |
LanceDB directory |
CC_MEMORIES_COLLECTION |
cc_memories |
LanceDB table name |
CC_EMBEDDINGS_URL |
http://127.0.0.1:1234/v1 |
Embedding API base URL |
CC_EMBEDDINGS_MODEL |
text-embedding-qwen3-embedding-8b |
Embedding model name |
CC_EMBEDDINGS_API_KEY |
-- | Bearer token for authenticated endpoints |
CC_EMBEDDINGS_INSECURE |
false |
Set true to skip TLS certificate verification |
CC_EXTRACTION_MODEL |
claude-sonnet-4-6 |
Claude model for extraction |
ANTHROPIC_API_KEY |
-- | Anthropic API key |
ANTHROPIC_AUTH_TOKEN |
-- | OAuth token (alternative to API key) |
ANTHROPIC_BASE_URL |
-- | Custom Anthropic endpoint (e.g. for proxies) |
CC_MEMORIES_SETTING_* |
-- | Override any setting (e.g. CC_MEMORIES_SETTING_MIN_SEMANTIC_SIMILARITY=0.4) |
CLAUDE_MEMORY_DEBUG |
-- | Set 1 for debug logging |
CLAUDE_MEMORY_LOG_LEVEL |
info |
debug / info / warn / error |
{
"embeddings": {
"baseUrl": "https://your-inference-server/v1",
"model": "your-model-id",
"apiKey": "your-api-key",
"insecure": true
}
}If the server uses a custom CA, either set "insecure": true or point NODE_EXTRA_CA_CERTS at the CA bundle before starting Claude Code.
Tuning knobs for retrieval, maintenance, and models. Editable through the dashboard's Settings page or directly. Highlights:
| Setting | Default | Description |
|---|---|---|
minSemanticSimilarity |
0.65 |
Minimum cosine similarity for vector results |
semanticAnchorThreshold |
0.65 |
At least one raw-prompt result must clear this before planned semantic matches are injected |
minScore |
0.45 |
Minimum hybrid score to include a result |
minExpandedScore |
0.45 |
Minimum score for memories added through relation expansion |
maxRecords |
8 |
Max memories injected per prompt |
maxTokens |
4000 |
Token budget for injected context |
mmrLambda |
0.7 |
MMR diversity parameter (1.0 = pure relevance) |
enableTopicSuppression |
true |
Suppress memories recently injected in the same session |
topicChangeThreshold |
0.3 |
Clear recently-injected suppression when prompt embedding similarity falls below this |
recentlyInjectedWindow |
20 |
Number of injected memory IDs retained per session; 0 disables suppression |
suppressionMode |
soft |
hard excludes recently injected memories; soft downweights them |
suppressionPenalty |
0.5 |
Score penalty for soft suppression |
enableRelationExpansion |
true |
Expand initial hits through stored memory relations before MMR |
maxRelationHops |
1 |
Max relation hops to follow (0-2) |
maxRelationExpansions |
5 |
Max related memories added per retrieval |
relationHopDecay |
0.6 |
Score decay applied per relation hop |
maxRelationsPerRecord |
50 |
Max relates_to edges retained per memory; supersedes edges are preserved |
enableHaikuRetrieval |
false |
Use Haiku to plan / expand retrieval queries |
enableMemoryWriteHints |
true |
Capture native memory_write calls as priority anchors for post-session extraction |
extractionDedupThreshold |
0.85 |
Similarity threshold for update-vs-insert during extraction |
extractionContextOverlapTurns |
3 |
Context overlap when incrementally extracting a resumed session |
consolidationThreshold |
0.80 |
Similarity threshold for merging records |
consolidationNoMergeBackoffDays |
90 |
Recheck delay for unchanged clusters rejected by the consolidation verifier |
autoMaintenanceIntervalHours |
24 |
Run maintenance automatically after extraction if it's been this long (0 disables) |
autoUpdateIntervalHours |
0 |
Hours between automatic git fetch attempts; 0 disables pulling |
autoRebuildEnabled |
true |
Rebuild dist/ when source or dependency inputs differ from the last successful build; pulling is refused when disabled |
extractionModel |
claude-sonnet-4-6 |
Model for knowledge extraction |
chatModel |
claude-opus-4-8 |
Model used by the dashboard chat |
reviewModel |
claude-opus-4-8 |
Model used by injection / extraction reviews |
Any setting can be overridden via CC_MEMORIES_SETTING_<SCREAMING_SNAKE_CASE>.
# Build & develop
pnpm build # TypeScript compile (root + dashboard)
pnpm dev # tsx watch mode
pnpm test # vitest (some tests skip if services are unavailable)
pnpm test:watch # vitest watch
pnpm test:ui # vitest UI
# Setup & ops
pnpm wizard # interactive setup (recommended)
pnpm maintenance # run the safe auto-maintenance pipeline
pnpm maintenance --dry-run # preview without writing
pnpm run self-update # reconcile registrations, optionally pull, and rebuild stale dist
pnpm run self-update --dry-run # inspect without fetching/building (crash recovery still runs)
pnpm run self-update --pull # fetch now, still honoring all git safety guards
pnpm run self-update --force # force only the dist rebuild
pnpm run self-update --rollback # restore dist.prev and hold rebuilds until source changes
pnpm run self-update --clear-hold # explicitly clear a rollback hold
pnpm run self-update --dashboard # also run the existing dashboard build script
# Dashboard
pnpm dashboard # API (3001) + Vite (5000)
pnpm dashboard:server # API only
pnpm dashboard:prod # production server
# Debug & audit
pnpm debug <cmd> # debug CLI (see below)
pnpm audit # full-corpus Gemini audit (interactive)
pnpm audit:auto # Gemini audit, no prompts
pnpm apply-audit # apply audit findingsThe detached post-session worker checks dist/ freshness on every run and rebuilds it
when enabled. Fetching is separately interval-gated and opt-in. A pull requires a clean
tree, no local commits ahead of the configured upstream, and a fast-forward; neither
--pull nor --force bypasses those guards. --pull only bypasses the fetch interval,
while --force requests a rebuild regardless of freshness or the auto-rebuild setting.
--rebuild-only disables pulling for that invocation and cannot be combined with
--pull. Rollback and clear-hold are exclusive operations. --force does not bypass
a rollback hold;
--clear-hold is the explicit override. An unchanged rollback hold blocks pulling
as well as rebuilding, so every successful pull always rebuilds. A pending build is
retried after the hold is cleared or source inputs change. Dashboard compilation is
never automatic.
Dependency installation happens in the live checkout before compilation. If
installation succeeds but the later build or directory swap fails, the previous
dist/ remains active against the newly installed dependency tree until the next
self-update retry succeeds. This is a known limitation of updating in place.
A web UI for browsing and operating the memory pool. Start with pnpm dashboard and open http://localhost:5000.
| Page | What it does |
|---|---|
| Overview | Pool statistics, record-type breakdown, retrieval scoring chart, install/health status |
| Memory Pool | Search, filter, and edit individual records |
| Extractions | List extraction runs and drill into per-record details |
| Sessions | Inspect injected memories per session and run an Opus-powered "was this injection useful?" review |
| Chat | Interactive chat with tool access -- search and edit the pool, inspect extraction runs |
| Maintenance | Preview maintenance phases, execute safe phases, and review the diffs |
| Simulator (Context Preview) | Replay retrieval for a custom prompt with full diagnostics |
| Settings | Edit retrieval, maintenance, and model settings (writes ~/.claude-memory/settings.json) |
pnpm debug <command> is a terminal companion to the dashboard for fast introspection and Opus-powered reviews.
Memory pool: stats, search <query>, similar <id>, consolidation, deprecation,
promotion, record <id>, export, embedding <text>, compare <id1> <id2>,
settings
Sessions: sessions, session <sessionId>
Extractions: extractions, extraction <runId>
Reviews: review-session <id>, review-extraction <id> (stream Opus thinking)
All commands accept --json for machine-readable output. Run pnpm debug help for the full flag list.
The MCP server (dist/mcp-server.js) exposes a single read-only tool, search_memories:
| Param | Description |
|---|---|
query |
Natural-language search query |
project |
Project path to scope to (defaults to cwd) |
type |
Filter to one of command/error/discovery/procedure/warning |
limit |
1--50 (default 10) |
It's wired into Claude Code automatically by the wizard. The tool is intentionally read-only -- writes happen via the extraction hook, not at LLM request.
pre-prompt.ts(UserPromptSubmit) -- hybrid retrieval + MMR diversity, optional Haiku query planning, semantic-anchor gate, injects context on stdout. Tracks injected IDs per session for downstream usefulness rating.memory-write-hint.ts(PostToolUse, matchermemory_write) -- synchronously captures a bounded, deduplicated per-session hint. Hints only direct the normal extraction pass; they never write records to LanceDB directly.post-session.ts(SessionEnd,PreCompact) -- thin launcher; spawns a detached worker so the hook returns instantly.post-session-worker.ts-- extracts knowledge from the transcript via Claude, deduplicates against existing records (update-vs-insert viaextractionDedupThreshold), rates the previously-injected memories' usefulness, triggers periodic maintenance, and finally checks registrations, source freshness, and the optional pull interval.
- LanceDB layer (
lancedb-*.ts) -- connection, CRUD, hybrid search, schema with inline migrations viaensureSchemaFields(). (milvus.tsremains as a compatibility barrel for the old import path.) - Embedding (
embed.ts) -- OpenAI-compatible client with optional bearer token and TLS bypass. - Extraction (
extract.ts) -- LLM-based transcript extraction; rates the previous turn's injected memories. - Retrieval (
retrieval.ts,context.ts,retrieval-query-generator.ts) -- multi-query hybrid search, MMR reranking, signal extraction from prompts, optional Haiku query planning. - Maintenance (
maintenance/) -- see below. - Auth (
anthropic.ts) -- multi-path: API key -> OAuth token -> Claude Code / Kira credential files, with auto-refresh. - File storage (
file-store.ts) --JsonStore/JsonLinesStoreunder~/.claude-memory/: sessions, extractions, token-usage events, stats snapshots. - Settings (
settings.ts,settings-schema.ts) -- custom validation (no Zod). Three sections: retrieval, maintenance, models. - Config (
config.ts) -- merge order: defaults (env vars lowest) -> global -> project -> settings overrides. - Installer (
installer.ts) -- the wizard's hook / command / MCP installer. Used bypnpm wizardand the dashboard. - Self-update (
self-update.ts) -- reconciles missing hooks and unmodified slash commands, safely fast-forwards an eligible checkout, and stages/switches compiled hook builds.
| Type | Description | Key fields |
|---|---|---|
command |
Shell command with outcome | command, exitCode, outcome, resolution |
error |
Error message + resolution | errorText, errorType, cause, resolution |
discovery |
Factual finding about code/architecture | what, where, evidence, confidence |
procedure |
Step-by-step instructions | name, steps, prerequisites, verification |
warning |
"Don't do X, do Y instead" | avoid, useInstead, reason, severity |
Every record carries a scope (project or global), sourceSessionId / sourceExcerpt for traceability, and usage counters (retrievalCount, usageCount) that feed into ranking.
Hybrid scoring combines:
- Semantic -- cosine similarity on 4096-dim embeddings.
- Keyword -- DataFusion
LIKEsubstring matching onexact_text. - MMR reranking -- maximal marginal relevance for diversity.
- Usage boost -- previously-helpful records score higher; recently-deprecated ones score lower.
- Semantic anchor gate -- planned semantic matches require a candidate that clears
semanticAnchorThresholdagainst the raw prompt; raw keyword matches may survive independently.
pnpm maintenance, dashboard "Run all", and hook-triggered auto-maintenance use the same safe operation list:
[
'consolidation',
'cross-type-consolidation',
'conflict-resolution',
'quality-deprecation',
'relation-discovery',
'warning-synthesis',
'global-promotion',
'stale-check'
]Weak usage-based deprecators are preview-only in the dashboard and are excluded from run-all/auto execution. They can still be invoked individually as dry-run candidate reviews.
| Phase | Purpose |
|---|---|
| Consolidation | Merge near-duplicates within the same record type |
| Cross-type consolidation | Merge near-duplicates across record types (e.g. command <-> procedure) |
| Conflict resolution | Resolve contradictory records via LLM judgement |
| Quality deprecation | Deprecate high-confidence extraction artifacts such as raw tool dumps |
| Relation discovery | Strengthen links between memories repeatedly injected together |
| Warning synthesis | Synthesise warning records from clusters of related errors |
| Global promotion | Promote project-scoped records that recur across projects to global scope |
| Stale check | Validate stale command/procedure records with conservative command checks |
| Stale-unused deprecation (preview-only) | Surface old zero-usage records for review |
| Low-usage deprecation (preview-only) | Surface high-retrieval zero-usage records for review |
| Low usage (preview-only) | Surface records below the configured usefulness ratio for review |
| Promotion suggestions (dry-run only) | Surface candidates for promotion to review |
- LanceDB -- vectors + record metadata. Default location:
~/.claude-memory/lancedb, tablecc_memories. ~/.claude-memory/--config.json,settings.json,self-update-state.json, sessions, extraction logs, token-usage events, stats snapshots, installer state, and transientmemory-write-hints/sessions/*.jsonlpriority anchors.~/.claude-memory/debug.logand~/.claude-memory/extraction-audit.log-- worker diagnostics; trimmed on worker startup when they exceed the built-in size cap.