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

@sayyamkhan/engram-ai

v0.2.0

Published

Persistent memory layer for Claude AI. Drop-in context and history management for any Claude-powered application.

Readme

Engram

Persistent memory for Claude. Because every conversation shouldn't start from zero.

npm version License: MIT Node.js Version

Engram is a drop-in TypeScript library that gives Claude persistent memory. Drop it into any Claude-powered application and your users will never lose context again — preferences, history, facts, and decisions all persist seamlessly across sessions.


The Problem

Every Claude conversation starts completely blank. All context, user preferences, learned behavior, and history is permanently lost between sessions. Developers building Claude-powered apps have no standard, drop-in solution for persistent memory.

Without Engram:

Session 1: "Hi, I'm Alice. I'm building a FastAPI app on AWS."
Session 2: "Hey, can you help me with my project?"
Claude: "Of course! What are you working on?" ← starts from zero, again

With Engram:

Session 1: "Hi, I'm Alice. I'm building a FastAPI app on AWS."
Session 2: "Hey, can you help me with my project?"
Claude: "Hi Alice! Happy to continue helping with your FastAPI app on AWS." ← remembers everything

Features

  • Store — Persist every conversation turn to SQLite (or PostgreSQL) with userId, sessionId, role, timestamp, and token count
  • Extract — Use Claude to extract structured user facts (name, preferences, goals, skills) after every turn
  • Compress — Automatically summarise old turns when history exceeds your token threshold
  • Inject — Prepend the right context (facts + summary + recent turns) before every Claude API call
  • Search — Keyword search across all stored memories with relevance ranking
  • MCP Server — Full Model Context Protocol server for Claude Desktop and MCP clients
  • Zero config — Works out of the box with SQLite, no database setup required
  • TypeScript-first — Strict types, full type exports, no any

Installation

npm install engram

Peer dependencies (already included):

# These are bundled as dependencies — no extra installs needed
# @anthropic-ai/sdk, better-sqlite3, @modelcontextprotocol/sdk, zod

Quick Start

import Anthropic from '@anthropic-ai/sdk';
import { Engram } from 'engram';

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

const engram = new Engram({
  apiKey: process.env.ANTHROPIC_API_KEY!,
  userId: 'user_123',
});

// Store turns after each exchange
await engram.store({ role: 'user',      content: "I'm Alice. I love Python." });
await engram.store({ role: 'assistant', content: 'Nice to meet you, Alice!' });
await engram.extract(); // extract facts: name=Alice, language=Python

// In a new session — inject memory into your Claude call
const { messages, systemContext } = await engram.inject("What language do I prefer?");

const reply = await anthropic.messages.create({
  model: 'claude-sonnet-4-6',
  max_tokens: 1024,
  system: systemContext,   // injected facts + summary
  messages,                // history + new message
});

That's it. Claude now remembers Alice is a Python developer across every future session.


How It Works

┌──────────────────────────────────────────────────────────────────┐
│                          Engram Pipeline                          │
│                                                                   │
│  User message                                                     │
│       │                                                           │
│       ▼                                                           │
│  ┌─────────┐   ┌─────────┐   ┌──────────┐   ┌────────────────┐  │
│  │  STORE  │──▶│ EXTRACT │──▶│ COMPRESS │──▶│    INJECT      │  │
│  │         │   │         │   │          │   │                │  │
│  │ Save to │   │ Claude  │   │ Claude   │   │ Facts +        │  │
│  │ SQLite  │   │ extracts│   │summarises│   │ Summary +      │  │
│  │ with    │   │ name,   │   │ old turns│   │ Recent turns   │  │
│  │ token   │   │ prefs,  │   │ when over│   │ → messages[]   │  │
│  │ count   │   │ goals   │   │ threshold│   │                │  │
│  └─────────┘   └─────────┘   └──────────┘   └────────────────┘  │
│                                                      │            │
│                                                      ▼            │
│                                              Claude API call      │
└──────────────────────────────────────────────────────────────────┘
  1. Store — Every turn is saved with timestamp and token count
  2. Extract — Claude identifies user facts and stores them in a facts table
  3. Compress — When token count exceeds the threshold, old turns are summarised
  4. Inject — Before every new call, relevant facts + summary + recent turns are assembled

Full API Reference

new Engram(config)

const engram = new Engram({
  apiKey: string,                    // Anthropic API key (required)
  userId: string,                    // User identifier (required)
  storage?: 'sqlite' | 'postgres',   // Storage backend (default: 'sqlite')
  dbPath?: string,                   // SQLite file path (default: './engram.db')
  postgresUrl?: string,              // PostgreSQL connection string
  maxTokensBeforeCompress?: number,  // Compression threshold (default: 4000)
  maxInjectTokens?: number,          // Injection budget (default: 2000)
  extractFacts?: boolean,            // Auto-extract facts (default: true)
  model?: string,                    // Claude model (default: 'claude-sonnet-4-6')
  sessionId?: string,                // Session ID (auto-generated if omitted)
});

engram.store(message)

Store a conversation turn. Call after every user message and assistant response.

const id = await engram.store({ role: 'user', content: 'Hello!' });
// role: 'user' | 'assistant' | 'system'
// Returns: number (stored turn ID)

engram.inject(userMessage)

Build a memory-injected messages array for the next Claude API call.

const { messages, systemContext } = await engram.inject("What's my name?");

await anthropic.messages.create({
  model: 'claude-sonnet-4-6',
  max_tokens: 1024,
  system: systemContext,  // Pass as the system prompt
  messages,               // Pass as the messages array
});

engram.extract()

Use Claude to extract and persist structured user facts from recent turns.

await engram.extract();
// Stores facts like: { name: 'Alice', preferred_language: 'Python', ... }

engram.compress()

Compress old turns into a summary using Claude. Returns true if compression occurred.

const compressed = await engram.compress();
// Automatically respects maxTokensBeforeCompress threshold

engram.search(query, topN?)

Search stored memories by keyword. Returns turns ordered by relevance.

const results = await engram.search('Python programming', 5);
// Returns: MessageTurn[]

engram.getFacts()

Retrieve all extracted facts for this user.

const facts = await engram.getFacts();
// Returns: MemoryFact[] — [{ key: 'name', value: 'Alice', confidence: 1.0, ... }]

engram.clear()

Delete all stored memory for this user. Irreversible.

await engram.clear();

engram.stats()

Get aggregate memory statistics.

const stats = await engram.stats();
// Returns: {
//   userId, totalTurns, activeTurns, compressedTurns,
//   totalFacts, totalSummaries, estimatedTokens
// }

engram.close()

Close the storage connection. Call when your app shuts down.

await engram.close();

MCP Server

Engram ships with a full MCP server so you can give Claude Desktop persistent memory with zero code.

Add to claude_desktop_config.json

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "engram": {
      "command": "npx",
      "args": ["engram-mcp"],
      "env": {
        "ANTHROPIC_API_KEY": "your-api-key-here",
        "ENGRAM_DB_PATH": "/Users/you/engram.db"
      }
    }
  }
}

Restart Claude Desktop — Engram's tools will be available immediately.

Available MCP Tools

| Tool | Description | |---------------------|------------------------------------------------------| | engram_store | Store a conversation message turn | | engram_inject | Get memory-injected messages for the next API call | | engram_search | Search memories by keyword | | engram_get_facts | Get all extracted facts for a user | | engram_compress | Trigger compression of old turns | | engram_extract | Extract facts from recent conversation | | engram_clear | Clear all memory for a user | | engram_stats | Get memory statistics |

See examples/mcp-usage.md for full tool schemas and examples.


Storage Options

SQLite (default — zero config)

const engram = new Engram({
  apiKey: '...',
  userId: 'user_123',
  storage: 'sqlite',
  dbPath: './engram.db',  // relative to cwd, auto-created
});

SQLite is the default. The database file is created automatically on first use. Uses WAL mode for concurrent read performance.

PostgreSQL

const engram = new Engram({
  apiKey: '...',
  userId: 'user_123',
  storage: 'postgres',
  postgresUrl: 'postgresql://user:pass@localhost:5432/engram',
});

Or use environment variables (PGHOST, PGPORT, PGDATABASE, PGUSER, PGPASSWORD) and omit postgresUrl.

Tables are created automatically on first use.

Custom Storage Adapter

Implement StorageAdapter to add your own backend (Redis, DynamoDB, Firestore, etc.):

import { StorageAdapter, Engram } from 'engram';

class MyCustomStorage implements StorageAdapter {
  async initialize() { /* ... */ }
  async storeTurn(turn) { /* ... */ }
  // ... implement all methods
}

Environment Variables

| Variable | Default | Description | |-----------------------|---------------------|------------------------------------------| | ANTHROPIC_API_KEY | (required) | Your Anthropic API key | | ENGRAM_DB_PATH | ./engram.db | SQLite database path | | ENGRAM_MAX_TOKENS | 4000 | Token threshold before compression | | ENGRAM_MODEL | claude-sonnet-4-6 | Claude model for compress/extract ops |


Roadmap

  • [ ] Vector embeddings — Semantic similarity retrieval via pgvector / sqlite-vss
  • [ ] Redis adapter — In-memory storage for high-throughput applications
  • [ ] Multi-user session management — Group sessions, shared context, org-level memory
  • [ ] Web dashboard — Visual memory explorer and fact editor
  • [ ] Cloudflare Workers support — Edge-compatible storage via D1 / KV
  • [ ] Auto-store hook — Middleware that automatically stores turns after each Claude call
  • [ ] Memory versioning — Track how user facts evolve over time
  • [ ] Export / import — Portable memory snapshots in JSON

Contributing

Contributions are welcome!

  1. Fork the repository
  2. Create a feature branch: git checkout -b feat/my-feature
  3. Make your changes (TypeScript strict mode, no any)
  4. Run tests: npm test
  5. Submit a pull request

Please open an issue first for significant changes to discuss the approach.

Development Setup

git clone https://github.com/your-username/engram
cd engram
npm install
npm run build
npm test

License

MIT — see LICENSE for details.


Built for the Anthropic Claude for Open Source Program — Ecosystem Impact Track.