 Command

Pranesh Nikhar's personal site. Vim-style keybinds for navigation; theme + font pickers below.

Theme
 Font Body Code
Reader
Keybinds
Navigation
j / ↓ Next item k / ↑ Previous item g First item in region G Last item in region zz Center focused item h / l Move left/right region ] / [ Next/previous heading } / { Next/previous block d / u Half-page down/up
Layout
<zh> / <zl> Toggle left/right sidebar <zr> Toggle reader view <zj> / <zk> Focus main/navbar <S-h/j/k/l> Focus left/main/navbar/right ⌃H / ⌃L Focus left/right sidebar ⌃J / ⌃K Focus main/navbar ⇧C / ⇧E Collapse / expand all sections
Dialogs
⌃P / : Command palette ⌃X Theme picker / Search ? Show keybinds Esc / ⌃C Close dialog
History
n Next document b Previous document ⌃O History back ⌃I History forward
 Search
about: Pranesh Nikhar about/more: πŸͺͺ More docs/test: Docs Test ideas: πŸ’‘ Ideas more: βž• More now: Now posts: πŸ“¬ Posts projects: πŸ“š Projects webtui: Style posts/agentic-eda: πŸ“Š AgenticEDA β€” Automated Exploratory Data Analysis with LangGraph posts/cap-theorem-outage-story: 🌐 CAP Theorem with a Real Outage Story posts/codepilot: ✈️ CodePilot β€” From Requirements to Deployable FastAPI Backend posts/common-auth-mistakes: πŸ” Common Auth Mistakes Developers Make posts/compiled-vs-jit-vs-interpreted: ⚑ Why Is X Language Fast or Slow? β€” Compiled vs JIT vs Interpreted posts/cs-degree-gaps: πŸŽ“ Things CS Degrees Don't Teach You posts/cve-2025-breach-analysis: πŸ›‘οΈ CVE-2025 Breach Analysis β€” Midnight Blizzard and the 16 Billion Credential Leak posts/fixloop: πŸ”„ FixLoop β€” AI Agent Loop for Self-Correcting Code posts/functional-vs-oop: ⚑ Functional vs OOP β€” Same Problem, Both Ways posts/getman: 🦾 Getman β€” Declarative API Tester for CLI & TUI posts/how-compilers-optimize: βš™οΈ How Compilers Actually Optimize Your Code posts/http3-quic: ⚑ HTTP/3 and QUIC β€” Why They Matter posts/leetcode-vs-engineering: 🧩 LeetCode vs Real Engineering Skills posts/llm-from-scratch: 🧠 LLM from Scratch β€” GPT-Style Transformer in PyTorch posts/lsm-trees-bloom-filters: 🌳 LSM Trees & Bloom Filters β€” Production Deep Dive posts/mcp-workflow-builder: πŸ”§ MCP Workflow Builder β€” Visual DAG for MCP Tools posts/persistent-memory: 🧠 Persistent Memory β€” Long-Term Memory for AI Agents via MCP posts/playcli: 🎬 PlayCLI β€” Terminal Video Player posts/postgres-mvcc: πŸ—„οΈ How PostgreSQL MVCC Works β€” Multi-Version Concurrency Control Deep Dive posts/raft-consensus: β›΅ Raft Consensus Algorithm Explained posts/rust-borrow-checker: πŸ¦€ Rust Borrow Checker β€” Catches Real Bugs posts/titan: πŸ€– Titan β€” Terminal AI Coding Agent posts/what-happens-url: 🌐 What Happens Between Typing a URL and Seeing the Page posts/what-happens-when-you-run-a-program: βš™οΈ What Actually Happens When You Run a Program posts/zero-knowledge-proofs: πŸ” Zero-Knowledge Proofs Explained Simply webtui/components/accordion: Accordion webtui/components/badge: Badge webtui/components/button: Button webtui/components/checkbox: Checkbox webtui/components/dialog: Dialog webtui/components/input: Input webtui/components/popover: Popover webtui/components/pre: Pre webtui/components/progress: Progress webtui/components/radio: Radio webtui/components/range: Range webtui/components/separator: Separator webtui/components/spinner: Spinner webtui/components/switch: Switch webtui/components/table: Table webtui/components/textarea: Textarea webtui/components/tooltip: Popover webtui/components/typography: Typography webtui/components/view: View webtui/contributing/contributing: Contributing webtui/contributing/contributing: ## Local Development webtui/contributing/contributing: ## Issues webtui/contributing/contributing: ## Pull Requests webtui/contributing/style-guide: Style Guide webtui/contributing/style-guide: ## CSS Units webtui/contributing/style-guide: ## Selectors webtui/contributing/style-guide: ## Documentation webtui/installation/astro: Astro webtui/installation/astro: ## Scoping webtui/installation/astro: ### Frontmatter Imports webtui/installation/astro: ### β€Ήstyleβ€Ί tag webtui/installation/astro: ### Full Library Import webtui/installation/nextjs: Next.js webtui/installation/vite: Vite webtui/plugins/plugin-dev: Developing Plugins webtui/plugins/plugin-dev: ### Style Layers webtui/plugins/plugin-nf: Nerd Font Plugin webtui/plugins/theme-catppuccin: Catppuccin Theme webtui/plugins/theme-custom: Custom Theme webtui/plugins/theme-everforest: Everforest Theme webtui/plugins/theme-gruvbox: Gruvbox Theme webtui/plugins/theme-nord: Nord Theme webtui/plugins/theme-vitesse: Vitesse Theme webtui/start/ascii-boxes: ASCII Boxes webtui/start/changelog: Changelog webtui/start/installation: Installation webtui/start/installation: ## Installation webtui/start/installation: ## Using CSS webtui/start/installation: ## Using ESM webtui/start/installation: ## Using a CDN webtui/start/installation: ## Full Library Import webtui/start/installation: ### CSS webtui/start/installation: ### ESM webtui/start/installation: ### CDN webtui/start/intro: Introduction webtui/start/intro: ## Features webtui/start/plugins: Plugins webtui/start/plugins: ## Official Plugins webtui/start/plugins: ### Themes webtui/start/plugins: ## Community Plugins webtui/start/theming: Theming webtui/start/theming: ## CSS Variables webtui/start/theming: ### Font Styles webtui/start/theming: ### Colors webtui/start/theming: ### Light & Dark webtui/start/theming: ## Theme Plugins webtui/start/theming: ### Using Multiple Theme Accents webtui/start/tuis-vs-guis: TUIs vs GUIs webtui/start/tuis-vs-guis: ## Monospace Fonts webtui/start/tuis-vs-guis: ## Character Cells
 Theme Current: Light j/k or ↑/↓ + Enter

🧠 Persistent Memory β€” Long-Term Memory for AI Agents via MCP

MCP server that gives AI agents long-term memory with semantic search (vector embeddings) and keyword search (BM25). Zero infrastructure β€” just Python and SQLite.

🎯 What It Does

Persistent Memory is an MCP (Model Context Protocol) server that gives AI agents long-term memory. Agents can store facts, recall them by meaning (semantic search via vector embeddings), search by keyword (BM25 via SQLite FTS5), and filter by metadata tags β€” all with zero infrastructure requirements.

Agent: "Remember that the user prefers concise responses"
Server: βœ“ Stored with 3 tags

Agent: "What do you know about the user's preferences?"
Server: [semantic match] "User prefers concise responses"
         [keyword match] "User likes Python over JavaScript"

🧱 Tech Stack

ComponentTechnology
Frameworkfastmcp (MCP server framework)
Embeddingssentence-transformers (all-MiniLM-L6-v2, 384-dim)
StorageSQLite with FTS5 (full-text search)
SimilarityNumPy cosine similarity

Zero external infrastructure β€” no PostgreSQL, no Pinecone, no Redis, no GPU needed. The entire system runs in-process with a single SQLite database file.


πŸ—οΈ Architecture

server.py          β†’ FastMCP entry, registers 7 @mcp.tool() functions
memory_store.py    β†’ Business logic: orchestrates store/recall/search/forget
embeddings.py      β†’ sentence-transformers singleton, cosine_similarity()
storage.py         β†’ SQLite CRUD with FTS5 auto-sync via triggers

πŸ› οΈ MCP Tools

ToolDescription
storeSave a fact with optional tags and source
recallSemantic search: query β†’ embed β†’ cosine sim β†’ top-K
searchKeyword search: BM25 via SQLite FTS5
forgetDelete a specific memory by ID
listList all memories, optionally filtered by tags
statsReturn count of memories
clearDelete all memories

πŸ’Ύ Storage Design

The storage.py module uses a clever SQLite schema:

CREATE TABLE memories (
    id TEXT PRIMARY KEY,
    content TEXT NOT NULL,
    embedding BLOB,           -- pickle of numpy array
    tags TEXT,                -- JSON array
    source TEXT,
    created_at TEXT,
    updated_at TEXT
);

CREATE VIRTUAL TABLE memories_fts USING fts5(
    content, tags,
    content=memories, content_rowid=rowid,
    tokenize='porter unicode61'
);

-- Triggers auto-sync the FTS index on INSERT/UPDATE/DELETE

Key design choices:

  • Embeddings stored as pickled numpy arrays in a BLOB column (no vector extension needed)
  • FTS5 with porter unicode61 tokenizer for English stemming + Unicode support
  • Triggers keep the full-text index in sync automatically
  • WAL mode for concurrent reads
  • Cosine similarity computed in Python β€” loads all vectors, compares, returns top-K

FeatureSemantic (recall)Keyword (search)
How it worksEmbed query β†’ cosine similarity with all stored embeddingsBM25 via SQLite FTS5
Good forFinding by meaning/contextFinding by exact terms
Trade-offO(n) scan over all embeddingsO(log n) via FTS index
Modelall-MiniLM-L6-v2 (384-dim)Porter stemmer (English)

Both search methods return results ranked by relevance, with the top-K results returned to the agent.


πŸ€– Integration with Any MCP Client

Any MCP-compatible client can connect:

  • Claude Desktop: Add to mcpServers in config
  • Cursor: Register as an MCP server in settings
  • Any MCP host: Connect via stdio transport

πŸš€ Quick Start

pip install persistent-memory

# Start the MCP server (stdio transport)
python -m persistent_memory server

# Or configure in your MCP client:
{
  "mcpServers": {
    "persistent-memory": {
      "command": "python",
      "args": ["-m", "persistent_memory", "server"]
    }
  }
}

πŸ“Š Resource Usage

ResourceEstimate
RAM~500MB (sentence-transformers model loaded once)
Disk~80MB (model download on first use)
CPUMinimal (inference is ~10ms on modern CPUs)
Modelall-MiniLM-L6-v2 (80MB, 384-dim embeddings)

πŸ’‘ Why It’s Interesting

The biggest limitation of current AI agents is statelessness β€” every conversation starts from scratch. Persistent Memory solves this with an elegant zero-infrastructure design. It uses SQLite FTS5 for keyword search (not a separate search engine), in-process sentence embeddings for semantic search (no external API), and the MCP protocol for universal compatibility. The entire system fits in a single Python package with no external services, no GPU, and no API keys. Drop it into any MCP client and your agent suddenly has a persistent brain.

 praneshnikhar.site / posts / persistent-memory Β· Top 1:1