A hybrid search memory system for coding agents (70% vector similarity + 30% BM25 keyword).
Based on the memory system from OpenClaw (originally Clawdbot).
- Hybrid search combining vector similarity and keyword matching
- Local embeddings included (no API key needed)
- Optional OpenAI embeddings for faster queries
bun:sqlitestorage (no native extensions needed)- Support for
MEMORY.md+memory/*.mdfiles - Embedding cache for efficiency
- Works with Claude Code, Cursor, Codex, and 30+ other agents
bunx skills add rjyo/memory-searchThis installs the /memory skill to your coding agent (Claude Code, Cursor, Codex, etc.).
Save information:
/memory remember that I prefer TypeScript over JavaScript
Search memories:
/memory what did we decide about authentication?
Or just ask naturally - the skill triggers on phrases like "remember this" or "what did we decide about X".
Want Claude to search memory automatically? Add to your CLAUDE.md:
## Memory
When questions relate to past decisions or preferences, use /memory to search first.Or use a hook in .claude/hooks.json:
{
"hooks": {
"SessionStart": [{
"command": "bunx memory-search \"project context preferences decisions\"",
"timeout": 30000
}]
}
}import { MemoryIndex } from "memory-search";
// Create index (uses local embeddings by default)
const memory = await MemoryIndex.create({
workspaceDir: "./my-project",
});
// Index files
await memory.sync();
// Search
const results = await memory.search("authentication");
// Returns: [{ path, startLine, endLine, score, snippet }]
// Read a file
const file = await memory.readFile({ path: "MEMORY.md" });
// Get status
const status = memory.status();
// Clean up
await memory.close();your-project/
├── MEMORY.md # Long-term: preferences, patterns, decisions
└── memory/
├── 2024-01-15.md # Daily notes
├── 2024-01-16.md
└── architecture.md # Topic-specific memory
- User preferences
- Project decisions
- Coding patterns
- Architecture choices
- Daily session notes
- Work in progress
- Ideas to explore
- Meeting notes
Local embeddings work out of the box.
First Run: The first query downloads a ~300MB embedding model. Run
bunx memory-search --warmupafter installing to pre-download it.
For faster embeddings, you can optionally use OpenAI:
export OPENAI_API_KEY=sk-...interface MemoryConfig {
workspaceDir: string; // Required: directory with MEMORY.md
// Database
dbPath?: string; // Default: {workspaceDir}/.memory.sqlite
// Embeddings
embeddingProvider?: 'local' | 'openai'; // Default: local
openaiApiKey?: string; // Required for 'openai' provider
openaiModel?: string; // Default: text-embedding-3-small
localModelPath?: string; // Default: hf:ggml-org/embeddinggemma-300M-GGUF/...
modelCacheDir?: string; // Default: ~/.cache/memory-search
// Chunking
chunkTokens?: number; // Default: 400
chunkOverlap?: number; // Default: 80
// Search
maxResults?: number; // Default: 6
minScore?: number; // Default: 0.35
vectorWeight?: number; // Default: 0.7
textWeight?: number; // Default: 0.3
}# Install dependencies
bun install
# Run tests
bun test
# Type check
bun run typecheck
# Build
bun run build- Indexing: Scans
MEMORY.mdandmemory/*.md, chunks into ~400 token pieces - Embedding: Converts chunks to vectors via local model (or OpenAI)
- Storage: SQLite database with FTS5 for keyword search
- Search: Hybrid (70% vector similarity + 30% BM25 keyword)
- Caching: Embeddings cached to avoid re-computation
MIT