Skip to content

Unified AI memory system - consolidating recall, episodic-memory, and memory-server

Notifications You must be signed in to change notification settings

beeard/unified-memory

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

38 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

unified-memory

A production-ready semantic memory system for AI agents.

Combines semantic search, keyword search, and structured metadata into a single, fast, local-first memory store. Built for Claude, OpenAI, and any LLM that needs long-term memory.

License: MIT TypeScript

✨ Features

  • πŸ” Hybrid Search β€” Semantic (embeddings) + keyword (FTS5) + metadata filters
  • ⚑ Fast β€” SQLite with WAL mode, prepared statements, FTS5 full-text search
  • 🎯 Smart Ranking β€” RRF fusion, confidence scoring, temporal decay, usefulness tracking
  • πŸ”Œ MCP Protocol β€” 8 tools for Model Context Protocol (Claude Code, mcporter)
  • πŸ–₯️ CLI β€” Zero-dependency CLI for terminal workflows
  • 🎨 Presets β€” Domain-specific configurations (coding, research, personal assistant)
  • ☁️ Edge Deployment β€” Cloudflare Workers + D1 + Workers AI
  • πŸ“¦ Local-First β€” Your data stays on your machine (or your Workers)

πŸš€ Quick Start

# Install
cd unified-memory
pnpm install && pnpm build

# CLI
npx @unified/cli store "JWT tokens should use httpOnly cookies" --project auth --tags security
npx @unified/cli search "authentication best practices" --mode hybrid --limit 5
npx @unified/cli stats

# MCP Server
export OPENAI_API_KEY=sk-...
node packages/mcp/dist/cli.js ~/.unified-memory/main.db

# Or via mcporter
mcporter config add unified-memory --stdio "node /path/to/mcp/dist/cli.js /path/to/memory.db"
mcporter call unified-memory.memory_search --args '{"query": "React hooks patterns"}'

πŸ“¦ Packages

Package Description
@unified/core Abstract types, interfaces, retrieval algorithms
@unified/sqlite SQLite storage backend with FTS5
@unified/mcp MCP server with 8 tools
@unified/cli Command-line interface
@unified/presets Domain-specific configurations
@unified/cloudflare Cloudflare Workers deployment

πŸ—οΈ Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Applications                          β”‚
β”‚  Claude Code β€’ mcporter β€’ Custom LLM apps β€’ CLI scripts     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    @unified/mcp (MCP Server)                β”‚
β”‚  8 tools: store, search, get, delete, update, feedback,    β”‚
β”‚           stats, cleanup                                    β”‚
β”‚  + OpenAI embedding adapter                                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  @unified/sqlite (Storage)                  β”‚
β”‚  SQLite + FTS5 + vector storage + migrations                β”‚
β”‚  WAL mode, prepared statements, hybrid search               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   @unified/core (Abstractions)              β”‚
β”‚  MemoryStore interface, EmbeddingAdapter, RRF fusion,      β”‚
β”‚  confidence scoring, temporal decay                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

🎯 Use Cases

For Claude Code (via MCP)

Store coding patterns, architecture decisions, and debugging solutions:

// Claude can store memories as you code
mcporter call unified-memory.memory_store --args '{
  "content": "React Query cache invalidation: use queryClient.invalidateQueries with exact:true to target specific queries",
  "metadata": {"project": "web-app", "tags": ["react-query", "caching"], "language": "typescript"}
}'

// Search when solving similar problems
mcporter call unified-memory.memory_search --args '{
  "query": "react query cache management",
  "mode": "hybrid",
  "project": "web-app"
}'

For Personal Assistant

Track preferences, decisions, and conversations:

# Store a preference
unified-memory store "I prefer meetings after 2pm on Tuesdays and Thursdays" \
  --source preferences --tags scheduling

# Recall it later
unified-memory search "when do I prefer meetings" --mode semantic

For Research

Build a semantic knowledge base:

# Import papers/notes
cat research-notes.jsonl | unified-memory import --project phd-thesis

# Search by concept (semantic)
unified-memory search "attention mechanisms in transformers" --mode semantic --limit 20

# Export for backup
unified-memory export > backup-$(date +%Y%m%d).jsonl

πŸ” Search Modes

Mode How It Works Best For
keyword FTS5 full-text search (BM25) Exact terms, code snippets, file paths
semantic OpenAI embeddings + cosine similarity Natural language, conceptual queries
hybrid Both, fused with RRF General use (default, best overall)
auto Query analysis β†’ picks best mode Let the system decide

Example:

# Keyword: exact code terms
unified-memory search "useEffect cleanup function" --mode keyword

# Semantic: natural language
unified-memory search "how to prevent memory leaks in React" --mode semantic

# Hybrid: best of both
unified-memory search "React hooks memory management" --mode hybrid

🎨 Presets

Domain-specific configurations that tune search weights, scoring, metadata, and cleanup policies.

import { resolvePreset, presetToSearchOptions } from '@unified/presets';

// Use a preset
const preset = resolvePreset('coding-assistant');
const searchOpts = presetToSearchOptions(preset);

// Override specific fields
const custom = resolvePreset('coding-assistant', {
  search: { defaultAlpha: 0.9 },  // More semantic
  scoring: { sessionBoost: 1.5 }  // Stronger session affinity
});

Built-in presets:

  • coding-assistant β€” Code patterns, RRF fusion, branch/session boost
  • personal-assistant β€” Natural language, recency bias, weekly cleanup
  • research β€” Deep semantic search, long retention, minimal cleanup
  • norwegian-construction β€” Norwegian language, TEK17/NS standards, domain synonyms

See packages/presets for details.

πŸ“– CLI Usage

# Store a memory
unified-memory store "Your memory content here" --project my-app --tags tag1,tag2

# Search (hybrid by default)
unified-memory search "your query" --limit 10 --min-score 0.3

# Get by ID
unified-memory get <uuid>

# Update
unified-memory update <uuid> "New content" --usefulness 0.9

# Feedback (adjust usefulness)
unified-memory feedback <uuid> up    # or: down, helpful, unhelpful, +, -

# List memories
unified-memory list --limit 25 --offset 0

# Statistics
unified-memory stats

# Cleanup (dry run by default)
unified-memory cleanup --min-usefulness 0.1 --older-than 90
unified-memory cleanup --min-usefulness 0.1 --older-than 90 --confirm

# Import/Export (JSON lines)
unified-memory export > backup.jsonl
cat backup.jsonl | unified-memory import --project restored

# Global options
unified-memory search "query" --db ~/memory.db --json --verbose

See packages/cli for full documentation.

πŸ”Œ MCP Tools

When running as an MCP server, unified-memory exposes 8 tools:

Tool Description
memory_store Store a new memory with metadata
memory_search Search with semantic/keyword/hybrid modes
memory_get Get a memory by ID (increments access count)
memory_delete Delete a memory
memory_update Update content or metadata
memory_feedback Mark helpful/unhelpful (adjusts usefulness)
memory_stats Get store statistics
memory_cleanup Remove old/low-value memories

Example MCP config (Claude Code):

{
  "mcpServers": {
    "unified-memory": {
      "command": "node",
      "args": ["/path/to/unified-memory/packages/mcp/dist/cli.js", "/path/to/memory.db"],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}

See packages/mcp for details.

🚒 Deployment

Local (recommended)

SQLite database on your filesystem. Fast, private, zero-cost.

export UNIFIED_MEMORY_DB=~/.unified-memory/main.db
export OPENAI_API_KEY=sk-...

# Run MCP server
node packages/mcp/dist/cli.js $UNIFIED_MEMORY_DB

Cloudflare Workers

Deploy to the edge with D1 (SQLite) + Workers AI (embeddings).

cd packages/cloudflare
wrangler d1 create unified-memory
wrangler d1 migrations apply unified-memory
wrangler deploy

See packages/cloudflare for details.

🧠 How It Works

Storage

  • SQLite database with WAL mode for concurrent access
  • FTS5 virtual table for full-text keyword search (BM25)
  • Vector embeddings stored as BLOB (Float32Array)
  • Metadata as JSON with generated columns for fast filtering

Search

  1. Keyword search β€” FTS5 matches, BM25 scoring
  2. Semantic search β€” OpenAI embeddings, cosine similarity
  3. Hybrid fusion β€” Reciprocal Rank Fusion (RRF) combines both
  4. Reranking β€” Confidence scoring (relevance + usefulness + access + recency + metadata)
  5. Filtering β€” Project, tags, date range, session

Usefulness Tracking

Memories start at 50% usefulness. When you mark helpful (+0.1) or unhelpful (-0.1), the score adjusts. High-usefulness memories rank higher in search and survive cleanup.

Cleanup

Automatically (or manually) remove:

  • Low usefulness (--min-usefulness 0.1)
  • Rarely accessed (--min-access 0)
  • Old entries (--older-than 90)

Dry run by default. Add --confirm to actually delete.

πŸ› οΈ Development

# Clone
git clone https://github.com/beeard/unified-memory.git
cd unified-memory

# Install
pnpm install

# Build all packages
pnpm build

# Run tests (when implemented)
pnpm test

# Clean
pnpm clean

Package Structure

unified-memory/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ core/          # Abstract types, interfaces, algorithms
β”‚   β”œβ”€β”€ sqlite/        # SQLite storage implementation
β”‚   β”œβ”€β”€ mcp/           # MCP server with 8 tools
β”‚   β”œβ”€β”€ cli/           # Command-line interface
β”‚   β”œβ”€β”€ presets/       # Domain-specific configurations
β”‚   └── cloudflare/    # Cloudflare Workers deployment
β”œβ”€β”€ scripts/           # Utility scripts
└── README.md          # This file

πŸ“š API Documentation

Core Interfaces

import type { MemoryStore, StoreParams, SearchOptions } from '@unified/core';

// Store a memory
const entry = await store.store({
  content: "Your memory content",
  metadata: { project: "my-app", tags: ["tag1"] },
  usefulness: 0.8,
  embedding: await embeddings.embed("Your memory content")
});

// Search
const response = await store.search("your query", {
  mode: "hybrid",
  limit: 10,
  minScore: 0.3,
  project: "my-app",
  tags: ["tag1"]
});

// Get by ID
const memory = await store.get("uuid");

// Update
const updated = await store.update({
  id: "uuid",
  content: "New content",
  metadata: { confidence: 0.95 }
});

// Delete
const deleted = await store.delete("uuid");

// Feedback
const feedback = await store.feedback({
  memoryId: "uuid",
  wasHelpful: true
});

// Stats
const stats = await store.stats();

// Cleanup
const result = await store.cleanup({
  minUsefulness: 0.1,
  olderThanDays: 90,
  dryRun: false
});

See individual package READMEs for detailed API docs.

πŸ”„ Migration from Legacy Systems

If you're migrating from wip-tool-recall, wip-episodic-memory, or memory-server:

From wip-tool-recall

# Export from recall (if you had export functionality)
# Then import to unified-memory:
cat recall-export.jsonl | unified-memory import --source recall

Key changes:

  • Usefulness is now 0-1 (was 0-10) β€” automatically normalized
  • RRF fusion is built-in (no need to configure)
  • Session/branch boost is now in presets

From wip-episodic-memory

Episodic patterns are supported via metadata:

await store.store({
  content: "Conversation turn content",
  metadata: {
    sessionId: "session-123",
    archivePath: "/path/to/archive.txt",
    lineStart: 42,
    lineEnd: 50,
    source: "episodic"
  }
});

From memory-server

Norwegian construction preset is included:

import { resolvePreset } from '@unified/presets';
const preset = resolvePreset('norwegian-construction');

Synonym expansion, stop words, and term boosting are built-in.

🀝 Contributing

Contributions welcome! Please:

  1. Fork the repo
  2. Create a feature branch (git checkout -b feature/amazing)
  3. Commit your changes (git commit -am 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing)
  5. Open a Pull Request

πŸ“„ License

MIT Β© beeard

πŸ™ Acknowledgments

This project consolidates patterns from:

  • wip-tool-recall β€” RRF fusion, confidence scoring, usefulness tracking
  • wip-episodic-memory β€” Session grouping, archive paths, conversation context
  • memory-server β€” Domain presets, Norwegian language support, tag hierarchies

πŸ“ž Support

About

Unified AI memory system - consolidating recall, episodic-memory, and memory-server

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors