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

@mormubis/memory

v0.4.2

Published

Memory infrastructure library — store, version, search, and decay knowledge over time

Downloads

243

Readme

@mormubis/memory

Memory infrastructure library. Store, version, search, and decay knowledge over time.

Install

pnpm add @mormubis/memory

For default local embeddings (optional):

pnpm add @huggingface/transformers

Usage

import { createMemory } from '@mormubis/memory';

const memory = createMemory({
  path: './memory.db',
  typeStrength: {
    fact: 0.6,
    decision: 0.7,
    observation: 0.3,
  },
});

// Store
const result = await memory.remember(
  'fact',
  'FIDE requires Buchholz as primary tiebreaker',
);
// { id: '...', version: 1, parentId: null }

// Similar content auto-versions
const v2 = await memory.remember(
  'fact',
  'FIDE requires Buchholz as the primary tiebreaker in Swiss',
);
// { id: '...', version: 2, parentId: result.id }

// Search (BM25 + vector + link expansion)
const results = await memory.search('tiebreaker rules');

// Link
memory.link(result.id, v2.id, 'related_to');

// List, filter, get
const all = memory.list({ type: 'fact', limit: 10 });
const specific = memory.get(result.id);
const chain = memory.history(v2.id);
const linked = memory.related(result.id);

// Delete
memory.forget(result.id);
memory.unlink(result.id, v2.id, 'related_to');

How It Works

Single SQLite file. One table for all memories regardless of type or maturity.

Versioning — When you insert content similar to an existing memory (cosine similarity above threshold), the library creates a new version and auto-boosts its strength: max(provided, previous_effective + reinforcementBoost). Repeated mentions accumulate strength naturally.

Decay — Lazy Ebbinghaus-inspired. Strength decays over time: effective = strength * decayRate^days. Computed on read, not stored until reinforcement or eviction. Memories below evictionThreshold are excluded from search.

Search — Hybrid BM25 (FTS5) + vector similarity, fused with reciprocal rank fusion. Results expanded 1 hop via weighted links. Pure relevance scoring — strength controls eviction, not ranking.

Links — Typed directional edges (source, target, relation, weight). Weights decay lazily and are reinforced on traversal.

Types — Opaque strings. The library stores and filters by type but never interprets it. Configure default strength per type via typeStrength.

Configuration

createMemory({
  path: './memory.db',              // SQLite file path
  embed: async (text) => number[],  // Custom embedding function
  typeStrength: { ... },            // Default strength per type
  defaultStrength: 0.2,             // Fallback when type not in map
  similarityThreshold: 0.85,        // Cosine threshold for auto-versioning
  decayRate: 0.99,                  // Daily decay multiplier (~1% per day)
  reinforcementBoost: 0.1,          // Strength boost on access/versioning
  evictionThreshold: 0.05,          // Strength below which memories are excluded
  searchWeights: { bm25: 0.4, vector: 0.6 },
  rrfK: 60,                         // RRF constant
  linkExpansionHops: 1,             // Link expansion depth in search
  clock: () => new Date(),          // Injectable clock for testing
});

API

| Method | Description | | ----------------------------------------- | ----------------------------------------------- | | remember(type, content, strength?) | Insert or auto-version a memory | | search(query, options?) | Hybrid BM25 + vector search with link expansion | | get(id) | Fetch by ID (reinforces strength if current) | | list(options?) | List current memories with decay filtering | | history(id) | Version chain (newest to oldest) | | link(source, target, relation, weight?) | Create or reinforce a link | | unlink(source, target, relation?) | Hard delete a link | | related(id, options?) | Get linked memories | | forget(id) | Hard delete a memory, its vector, and links |

Design

Follows the unitary model of memory — one store, not separate short-term and long-term stores. The difference between a transient observation and durable knowledge is strength, not location.

Wrapper-agnostic. No opinions on framework, LLM provider, transport layer, or consolidation strategy. The wrapper imports the library and uses it however it wants.