Semantic + keyword recall over your Claude Code session history, backed by a single
SQLite file (sqlite-vec for vectors, FTS5 for BM25, fused with Reciprocal Rank Fusion).
It indexes the JSONL transcripts under ~/.claude/projects and lets you recall past
work by meaning and by exact term — from the terminal, from a /recall command,
or autonomously via an MCP server Claude can call mid-session.
pip install -e . # or: uvx ccvec-mcp
ccvec index --all # build the index (first run downloads the embed model)
ccvec stats # per-project breakdown: projects, files, sessions, chunksRun ccvec with no arguments to see the full command menu.
ccvec search "why were tokens expiring right after login"
ccvec search "ERR_TOKEN_EXPIRED" --mode keyword # literal-term recall
ccvec search "auth middleware" -p api --role assistant --since 2026-03-01
ccvec context 10472 # expand a hit in situ
ccvec index --path ~/Work/api # index one project by folder
ccvec projects exclude some-noisy-project
ccvec tui # interactive browser + live searchccvec tui opens a terminal UI (Textual): projects in a sidebar, sessions on the
right, and a search bar that shows the top 5 hits as you type. Highlight a result to
preview its surrounding turns; press Enter to drop out with the claude --resume
command for that session. / focuses search, Esc clears it, q quits.
claude mcp add -s user ccvec -- ccvec mcpExposes search, get_context, index, status, list_sessions, manage_projects.
The plugin/ directory bundles /recall slash commands, a recall skill that teaches
Claude when to reach for memory, and a SessionEnd hook that incrementally re-indexes
finished sessions.
/plugin uninstall ccvec@ccvec-local
/plugin marketplace remove ccvec-local
/plugin marketplace add <PATH>
/plugin install ccvec@ccvec-local
~/.claude/projects/*/*.jsonl
│ parse (skip tool blobs / metadata)
│ chunk per message turn
│ embed (384-dim, fastembed/ONNX)
▼
SQLite: chunks ─ vec_chunks (sqlite-vec) ─ fts_chunks (FTS5)
│ query = vector KNN + BM25 → RRF fusion
▼
MCP · CLI · /recall · skill · SessionEnd hook
Everything lives under ~/.ccvec/ (ccvec.db + config.json). Source transcripts are
never modified. Indexing is incremental: unchanged files are skipped, appended files
resume from the last line, branch-forked duplicates are deduped by content hash.
| Env | Default | Meaning |
|---|---|---|
CCVEC_DIR |
~/.ccvec |
Data dir |
CCVEC_DB |
~/.ccvec/ccvec.db |
DB path |
CLAUDE_PROJECTS_DIR |
~/.claude/projects |
Source transcripts |
CCVEC_MODEL |
sentence-transformers/all-MiniLM-L6-v2 |
Embedding model (384-dim) |
CCVEC_RRF_K |
60 |
RRF constant |
Note: the spec named
multilingual-e5-small, which isn't infastembed. The default issentence-transformers/all-MiniLM-L6-v2(384-dim) — chosen for indexing speed (~2.5× faster thanbge-small, half the transformer layers). For higher retrieval quality at lower throughput, setCCVEC_MODEL=BAAI/bge-small-en-v1.5. Any 384-dim fastembed model works; changing models requiresccvec index --rebuild(enforced — ccvec refuses to mix embedding spaces).
Embedding throughput dominates indexing. Two things make it fast: chunks are
length-sorted before batching (so a short message isn't padded to a long one's
token length — the single biggest win), and onnxruntime already parallelizes
inference across cores. On a 16-core box this indexes ~5 sessions/s (~64 chunks/s).