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

@cartisien/engram

v0.2.0

Published

Persistent memory for AI assistants. SQLite-backed conversational memory with semantic search.

Readme

Engram

Persistent memory for AI assistants with temporal recall.

import { Engram } from '@cartisien/engram';

const memory = new Engram({ dbPath: './memory.db' });

// Store
await memory.remember('user_123', 'I ride a Triumph Bonneville', 'user');

// Recall with temporal queries
const yesterday = await memory.recallByTime('user_123', 'yesterday');
const lastWeek = await memory.recallByTime('user_123', 'last week');

The Problem

AI assistants are amnesiacs. Every conversation starts fresh. Context windows fill up. Important details get lost.

You wouldn't hire an employee who forgot every meeting. Why accept it from your AI?

The Solution

Engram gives your assistants persistent, queryable memory — backed by SQLite, designed for simplicity.

  • Zero config: Works out of the box
  • Fast: SQLite with proper indexes
  • Temporal: Natural language time queries ("yesterday", "last week", "3 days ago")
  • Portable: Single file database
  • Typed: Full TypeScript support

Installation

npm install @cartisien/engram

Quick Start

import { Engram } from '@cartisien/engram';

const memory = new Engram({
  dbPath: './bot-memory.db'  // or ':memory:' for ephemeral
});

// In your chat handler
async function handleChat(sessionId: string, message: string) {
  // 1. Store the user's message
  await memory.remember(sessionId, message, 'user');
  
  // 2. Retrieve relevant context
  const context = await memory.recall(sessionId, message, 5);
  
  // 3. Build prompt with memory
  const prompt = buildPrompt(context, message);
  
  // 4. Get AI response
  const response = await openai.chat.completions.create({ messages: prompt });
  
  // 5. Store the response
  await memory.remember(sessionId, response.choices[0].message.content, 'assistant');
  
  return response;
}

Temporal Recall

Engram understands natural language time expressions. Ask for memories from any point in time:

// Simple temporal queries
const yesterday = await memory.recallByTime('session_123', 'yesterday');
const lastWeek = await memory.recallByTime('session_123', 'last week');
const threeDaysAgo = await memory.recallByTime('session_123', '3 days ago');

// Combined with keyword search
const meetingsLastWeek = await memory.recallByTime(
  'session_123', 
  'last week', 
  'meeting'  // Only entries containing "meeting"
);

// Recent memories (last 7 days)
const recent = await memory.recallRecent('session_123', 7);

// Since a specific date
const sinceLaunch = await memory.recallSince('session_123', new Date('2024-01-01'));

// Daily summaries
const lastWeekByDay = await memory.dailySummary('session_123', 7);
// Returns: [{ date, entries: [...], count }, ...]

Supported Temporal Expressions

| Expression | Meaning | |------------|---------| | today | From midnight to now | | yesterday | Full previous day | | tomorrow | Next day (useful for scheduled items) | | 3 days ago | Specific day 3 days back | | a week ago | 7 days ago | | 2 weeks ago | 14 days ago | | last monday | Most recent Monday | | last week | Previous full week (Sun-Sat) | | last month | Previous full month | | this week | Current week (Sun-today) | | this month | Current month | | last 3 days | Last 72 hours | | last 7 days | Last week (rolling) | | january 15 | Specific date | | 3/15 | March 15 (current year) | | jan 15 to jan 20 | Date range | | recent, lately | Last 7 days |

API

new Engram(config?)

Create a memory instance.

const memory = new Engram({
  dbPath: './memory.db',        // Database file path
  maxContextLength: 4000        // Max characters per entry
});

remember(sessionId, content, role?, metadata?)

Store a memory entry.

await memory.remember('session_abc', 'User loves Thai food', 'user', {
  source: 'preference_extraction'
});

recall(sessionId, query?, limit?, options?)

Retrieve memories for a session. Supports temporal filtering via options.temporalQuery.

// Recent memories
const recent = await memory.recall('session_abc', undefined, 10);

// Keyword search
const relevant = await memory.recall('session_abc', 'food preferences', 5);

// Temporal + keyword
const yesterdayMeetings = await memory.recall(
  'session_abc', 
  'meeting', 
  10, 
  { temporalQuery: 'yesterday' }
);

// Filtered by role
const userOnly = await memory.recall('session_abc', undefined, 10, { role: 'user' });

recallByTime(sessionId, temporalQuery, keyword?, limit?, options?)

Recall memories by natural language time expression.

const { entries, range } = await memory.recallByTime(
  'session_abc',
  'last week',
  'project update'  // optional keyword filter
);

console.log(`Found ${entries.length} entries from ${range.description}`);
console.log(`Range: ${range.start.toDateString()} to ${range.end.toDateString()}`);

recallRecent(sessionId, days?, keyword?, limit?, options?)

Get memories from the last N days.

const { entries, days, since } = await memory.recallRecent('session_abc', 7);
console.log(`${entries.length} entries in the last ${days} days`);

recallSince(sessionId, since, keyword?, limit?, options?)

Get memories since a specific date.

const { entries, count } = await memory.recallSince(
  'session_abc', 
  new Date('2024-01-01')
);

recallBetween(sessionId, start, end, keyword?, limit?, options?)

Get memories between two dates.

const { entries, count } = await memory.recallBetween(
  'session_abc',
  new Date('2024-01-01'),
  new Date('2024-01-31')
);

dailySummary(sessionId, days?)

Get memories grouped by day.

const summary = await memory.dailySummary('session_abc', 7);
// [
//   { date: Date, entries: MemoryEntry[], count: 5 },
//   { date: Date, entries: MemoryEntry[], count: 3 },
//   ...
// ]

history(sessionId, limit?)

Get chronological conversation history.

const chat = await memory.history('session_abc', 20);

forget(sessionId, options?)

Delete memories.

// Delete all for session
await memory.forget('session_abc');

// Delete specific entry
await memory.forget('session_abc', { id: 'entry_id' });

// Delete before a date
await memory.forget('session_abc', { before: new Date('2024-01-01') });

// Delete in a date range
await memory.forget('session_abc', { 
  after: new Date('2024-01-01'),
  before: new Date('2024-02-01')
});

stats(sessionId)

Get memory statistics.

const stats = await memory.stats('session_abc');
// { total: 42, byRole: { user: 21, assistant: 21 }, oldest: Date, newest: Date }

temporalStats(sessionId, days?)

Get activity statistics grouped by day.

const activity = await memory.temporalStats('session_abc', 30);
// [
//   { date: '2024-01-15', count: 5, byRole: { user: 3, assistant: 2 } },
//   ...
// ]

The TemporalQuery Parser

You can use the temporal parser standalone:

import { TemporalQuery } from '@cartisien/engram';

const parser = new TemporalQuery();
const range = parser.parse('last week');

if (range) {
  console.log(range.description);  // "last week"
  console.log(range.start);        // Sun, Jan 07 2024 00:00:00
  console.log(range.end);          // Sat, Jan 13 2024 23:59:59
}

Philosophy

"The trace precedes presence." — Derrida

Memory isn't storage. It's the substrate of self.

Engram doesn't just persist data. It gives your assistants continuity — the ability to learn, reference, and grow across conversations. Time is not a sequence of moments to be archived, but a horizon of meaning that shifts with each recollection.

The Cartesian cogito assumed memory was given. We're making it so.

The Trilogy

Engram is part of the Cartisien Memory Suite:

| Package | Purpose | |---------|---------| | @cartisien/engram | This package — persistent memory with temporal recall | | @cartisien/extensa | Vector infrastructure (coming soon) | | @cartisien/cogito | Identity & state management (coming soon) |

Res cogitans meets res extensa.

License

MIT © Cartisien Interactive


Built with 🖤 by people who think forgetting is a bug.