npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

persisted-memory

v1.1.1

Published

Persistent memory system for Claude Code via MCP — dual-write to Markdown + LanceDB with hybrid semantic search

Readme

Persisted Memory for Claude Code

A persistent memory system that survives Claude Code's context compaction. Memories are stored as Markdown files (source of truth) and indexed in LanceDB (vector search). Uses Ollama for local embeddings and AI-powered summarization with graceful degradation to keyword-only search.

How It Works

Claude Code Session (any project)
  │
  ├─ Hooks capture context automatically
  │   SessionStart  → injects SUMMARY.md
  │   PreCompact    → saves context before compaction
  │   PostToolUse   → logs file changes
  │   Stop          → marks turn completion
  │   SessionEnd    → auto-persist to LanceDB + AI summary
  │
  └─ MCP Server provides 10 tools
      memory_store, memory_search, memory_recall,
      memory_list, memory_status, memory_forget,
      memory_consolidate, memory_graph, memory_viewer

Memories are stored per-project at <project>/.claude/memory/. The MCP server and hooks are installed once globally and work with any project in any language.

Features

  • Dual-write architecture -- Markdown (human-readable, git-friendly) + LanceDB (fast vector search)
  • Hybrid search -- 70% semantic + 30% keyword, with automatic fallback
  • Knowledge graph -- automatic entity/relationship extraction across memories
  • Progressive disclosure -- token-efficient recall with summary/detailed/ids_only modes
  • Privacy tags -- wrap sensitive content in <private>...</private> to exclude from outputs
  • AI-powered summaries -- Ollama-generated session summaries (falls back to rule-based)
  • Web viewer -- browser-based UI for exploring and searching memories
  • Auto-persist -- hook-captured activity is automatically stored into LanceDB (no manual memory_store needed)
  • Configurable embeddings -- swap model and vector dimension via environment variables
  • Zero external APIs -- everything runs locally with Ollama

Prerequisites

  • Node.js 20+ (LTS)
  • Ollama with nomic-embed-text model (optional -- falls back to keyword search)
# Install Ollama (if not already installed)
brew install ollama

# Pull the embedding model
ollama pull nomic-embed-text

# Optional: pull the summarization model
ollama pull llama3.2

Installation

Step 1: Install the package

npm install -g persisted-memory

Step 2: Register the MCP server with Claude Code

claude mcp add --scope user memory -- persisted-memory

Step 3: Register hooks

Create or edit ~/.claude/settings.json to add the lifecycle hooks. Run the setup script that comes with the package:

# Find where the package is installed
INSTALL_DIR=$(npm root -g)/persisted-memory

# Run the setup script
bash "$INSTALL_DIR/scripts/install.sh"

The install script will:

  1. Register the MCP server at user-level (claude mcp add)
  2. Register hooks in ~/.claude/settings.json (SessionStart, PreCompact, PostToolUse, Stop, SessionEnd)
  3. Add memory instructions to ~/.claude/CLAUDE.md

Step 4: Restart Claude Code

The MCP server and hooks activate on restart.

Alternative: Install from source

git clone <repo-url> ~/Works/persisted_memory
cd ~/Works/persisted_memory
npm install && npm run build
bash scripts/install.sh

Setup for an Existing Project

No per-project setup is needed. Once installed globally, persisted-memory works automatically in every project you open with Claude Code.

On first use in a project, it creates the memory directory at:

<your-project>/.claude/memory/

The only recommended step is to add the LanceDB index to your .gitignore:

echo ".claude/memory/.lance/" >> .gitignore

The .md and .json files in .claude/memory/ are human-readable and optionally committable -- they provide shareable context for team members.

Verification

After restarting Claude Code:

# Check MCP server is connected
/mcp

# Check system status (inside any Claude Code session)
Ask: "Check memory status"
→ Claude calls memory_status → shows total entries, Ollama status, memory dir

Usage

Automatic (via hooks)

Hooks fire automatically during every Claude Code session:

  • Session start: Previous session's SUMMARY.md is injected into context
  • File changes: Edit/Write operations are logged to daily Markdown
  • Context compaction: Transcript is saved before compaction occurs
  • Session end: Daily log entries are auto-persisted to LanceDB, then AI-powered summary is generated (or rule-based fallback)

Manual (via MCP tools)

Ask Claude to use these tools naturally:

| What you say | Tool called | |---|---| | "Remember that we use Yarn, not npm" | memory_store | | "What did we decide about authentication?" | memory_search | | "Recall everything about the database schema" | memory_recall | | "Show me all stored memories" | memory_list | | "Check memory system status" | memory_status | | "Forget memory abc-123" | memory_forget | | "Clean up duplicate memories" | memory_consolidate | | "What concepts are related to Docker?" | memory_graph | | "Open the memory viewer" | memory_viewer |

Privacy Tags

Wrap sensitive content in <private> tags to keep it out of summaries, public views, and the web viewer:

memory_store: "API key is <private>sk-abc123</private>, use it for auth"

The private content is stored in LanceDB for search but stripped from all outputs. Tags are case-insensitive.

Progressive Disclosure

The memory_recall tool supports three detail levels to optimize token usage:

| Level | Description | |---|---| | summary (default) | Truncated text (200 chars), most token-efficient | | detailed | Full text of each memory | | ids_only | Just IDs, types, and scores -- minimal tokens |

Knowledge Graph

Every stored memory automatically extracts entities (files, technologies, concepts) and creates relationships between them. Explore the graph:

"What entities are related to TypeScript?"  → memory_graph entity: "typescript"
"Show me all known entities"                → memory_graph list_entities: true
"How big is the knowledge graph?"           → memory_graph (default)

Web Viewer

Launch a browser-based memory explorer:

"Open the memory viewer" → memory_viewer

Or from the command line:

npm run viewer
# Opens at http://localhost:3777

Features: dark theme, search with debounce, type/importance filter chips, expandable cards, pagination.

Memory Types

When storing memories, specify a type:

| Type | Use for | |---|---| | decision | Architecture/design decisions | | architecture | System design notes | | code_change | File modifications | | error_fix | Problem + solution pairs | | pattern | Reusable code patterns | | context | General session context | | preference | User/project preferences |

Importance Levels

| Level | Use for | |---|---| | critical | Must never be forgotten | | high | Important decisions and patterns | | medium | Useful context (default) | | low | Minor notes |

Auto-Persist

Hook-captured activity (file modifications, pre-compact saves, session context) is automatically stored into LanceDB at session end -- no manual memory_store calls needed.

How it works:

  1. Hooks write activity to daily log files (daily/YYYY-MM-DD.md) throughout the session
  2. On session end, the auto-persist system parses the daily log and classifies each section
  3. Already-stored memories (memory_store entries) are skipped to avoid duplicates
  4. File modifications are aggregated into a single code_change entry
  5. New entries are embedded and stored in LanceDB + knowledge graph
  6. A character offset is tracked to avoid re-processing on subsequent runs

All auto-persisted entries are tagged with "auto-persisted" for traceability.

| Daily Log Pattern | Classification | Action | |---|---|---| | **[type]** (importance) | memory_store | Skip (already in LanceDB) | | - HH:MM Modified: path | file_modification | Aggregate into one code_change entry | | _Turn completed at_ | turn_marker | Skip (noise) | | ## Session ended at | session_marker | Skip (noise) | | ## Pre-compact save | pre_compact | Store as context / medium | | Other (>50 chars) | content | Store as context / low |

Configuration

Embedding model and vector dimensions are configurable via environment variables:

| Variable | Default | Description | |---|---|---| | MEMORY_EMBED_MODEL | nomic-embed-text | Ollama embedding model name | | MEMORY_VECTOR_DIM | 768 | Vector dimension (must match model output) | | OLLAMA_URL | http://localhost:11434 | Ollama server URL (localhost only) |

Storage math (768 dims): ~3KB per vector. 1,000 memories = ~3MB, 10,000 = ~30MB.

Example with a smaller model:

export MEMORY_EMBED_MODEL=all-minilm
export MEMORY_VECTOR_DIM=384

Important: MEMORY_VECTOR_DIM must match the actual output dimension of your chosen model. A mismatch will cause vectors to fall back to zero-vectors, disabling semantic search.

Per-Project Data

Each project gets its own memory directory:

<your-project>/.claude/memory/
├── .lance/                    # LanceDB vector index (add to .gitignore)
├── .auto-persist-offset       # Tracks last-persisted position per daily log
├── SUMMARY.md                 # Auto-generated context summary
├── knowledge-graph.json       # Entity/relationship graph
├── daily/                     # Daily session logs
│   └── 2026-02-18.md
├── sessions/                  # Archived session summaries
│   └── 2026-02-18-10-30.md
└── decisions.md               # Append-only decisions log

Search

Search uses a hybrid approach:

  • 70% semantic (vector cosine similarity via Ollama embeddings)
  • 30% keyword (LanceDB full-text search)

If Ollama is unavailable, search falls back to 100% keyword automatically.

Disaster Recovery

Markdown files are the source of truth. If LanceDB data corrupts:

  1. Delete .claude/memory/.lance/
  2. The index will be rebuilt from Markdown on next use

Uninstallation

# If installed from source
bash ~/Works/persisted_memory/scripts/uninstall.sh

# If installed globally via npm
INSTALL_DIR=$(npm root -g)/persisted-memory
bash "$INSTALL_DIR/scripts/uninstall.sh"
npm uninstall -g persisted-memory

This removes the MCP server and hooks. Per-project memory data at <project>/.claude/memory/ is preserved -- delete manually if no longer needed.

Project Structure

persisted-memory/
├── src/
│   ├── index.ts                # Entry point (stdio MCP transport)
│   ├── server.ts               # MCP server with 10 tool definitions
│   ├── storage/
│   │   ├── types.ts            # MemoryEntry, MemoryType, Importance
│   │   ├── lance-store.ts      # LanceDB CRUD + vector/FTS search
│   │   ├── markdown-store.ts   # Markdown file read/write/append
│   │   └── knowledge-graph.ts  # Entity/relationship extraction + graph
│   ├── embeddings/
│   │   └── ollama.ts           # Ollama nomic-embed-text client
│   ├── search/
│   │   └── hybrid.ts           # Merge vector + keyword results
│   ├── utils/
│   │   ├── chunking.ts         # Split text into embeddable chunks
│   │   ├── project.ts          # Resolve CLAUDE_PROJECT_DIR
│   │   ├── privacy.ts          # Private tag stripping
│   │   ├── summarize.ts        # AI-powered summary generation
│   │   ├── daily-log-parser.ts # Parse daily log into classified sections
│   │   └── auto-persist.ts     # Auto-persist orchestrator
│   ├── cli/
│   │   ├── viewer.ts           # Web viewer CLI entry point
│   │   ├── generate-summary.ts # Summary generation CLI
│   │   └── auto-persist.ts     # Auto-persist CLI entry point
│   └── viewer/
│       ├── server.ts           # HTTP server for web viewer
│       └── index.html          # Self-contained web UI
├── hooks/                      # Shell scripts for Claude Code hooks
├── scripts/
│   ├── install.sh              # Build + register MCP + hooks
│   └── uninstall.sh            # Clean removal
├── package.json
└── tsconfig.json

Dependencies

Only 4 runtime packages:

| Package | Purpose | |---|---| | @modelcontextprotocol/sdk | MCP server protocol | | @lancedb/lancedb | Embedded vector database | | apache-arrow | Columnar data format (LanceDB dep) | | zod | Schema validation for tool parameters |

No Python. No Docker. No background daemons. No external APIs.

License

MIT