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

true-mem

v1.3.2

Published

Persistent memory plugin for OpenCode with cognitive psychology-based memory management

Readme

True-Mem

A persistent memory plugin for OpenCode with cognitive psychology-based memory management.


Table of Contents


Overview

True-Mem is a memory plugin for OpenCode that enables AI coding agents to remember information across sessions and projects. It doesn't just store information - it manages memory like a human mind would.


The Problem

If you've ever had to repeat your preferences to your AI assistant every time you start a new session, you know the pain. "I prefer TypeScript over JavaScript", "Never use var", "Always run tests before committing" - things you've already said, but the AI forgot.


The Solution

True-Mem automatically extracts and stores memories from your conversations:

  • Preferences: "I prefer functional style over OOP"
  • Constraints: "Never use var keyword"
  • Decisions: "We decided to use SQLite instead of Postgres for this project"
  • Semantic info: "The API uses REST, not GraphQL"
  • Learning: "Learned that bun:sqlite is built-in"

Next time you open OpenCode, it remembers. No more repeating yourself.


The Psychology Behind It

What makes True-Mem different from a simple database? It's modeled after how human memory actually works:

Ebbinghaus Forgetting Curve - Episodic memories fade over time (7-day default), while preferences and decisions stay permanent. Just like your brain forgets what you had for lunch last Tuesday but remembers your favorite color.

7-Feature Scoring Model - Every memory is scored using Recency, Frequency, Importance, Utility, Novelty, Confidence, and Interference. This determines which memories surface when you need them.

Dual-Store Architecture (STM/LTM) - Short-term and long-term memory stores with automatic promotion. High-strength memories get promoted to LTM; weak ones stay in STM or decay.

Four-Layer Defense System - Prevents false positives with Question Detection (filters questions before classification), Negative Pattern filtering (including AI meta-talk detection), Multi-Keyword Scoring with sentence-level isolation, Confidence Thresholds, and Role Validation (only Human messages for user-level preferences).

Reconsolidation - When new information conflicts with existing memories, the system detects similarity and handles it intelligently (merge duplicates, keep both complements, or resolve conflicts).

Jaccard Similarity Search - Fast, lightweight semantic retrieval without heavy ML dependencies.


Key Features

| Feature | Description | |---------|-------------| | Dual-Scope Memory | Global (follows you across projects) + Project-specific | | Non-Blocking | Async extraction, no UI freezes or QUEUED states | | Multilingual | Full support for Italian, Spanish, French, German, and 11 more languages | | Smart Decay | Only episodic memories fade; preferences and decisions stay forever | | Zero Native Dependencies | Works on Bun and Node 22+ with built-in SQLite | | Multilingual | Full support for Italian, Spanish, French, German, and 11 more languages |


Noise Filtering

What truly sets True-Mem apart is its ability to distinguish signal from noise. Unlike simpler memory plugins that store everything matching a keyword, True-Mem understands context and intent:

What gets filtered OUT:

| Pattern Type | Example | Why filtered | |--------------|---------|--------------| | Questions | "Do you remember this?" | It's a question, not a statement | | 1st person recall | "I remember when we fixed that" | Recounting, not requesting storage | | Remind-me recall | "Remind me how we did this" | Asking AI to recall info, not store | | AI meta-talk | "Goal: The user is trying to..." | AI-generated, not user content | | List selections | "I prefer option 3" | Context-specific choice, not general preference |

What gets stored:

| Pattern Type | Example | Why stored | |--------------|---------|------------| | Imperatives | "Remember this: always run tests" | Explicit storage request | | Preferences | "I prefer TypeScript over JavaScript" | General, reusable preference | | Decisions | "We decided to use SQLite" | Project-level decision | | Constraints | "Never use var keyword" | Permanent rule |

All filtering patterns support 10 languages: English, Italian, Spanish, French, German, Portuguese, Dutch, Polish, Turkish, and Russian.


Installation

Add to your ~/.config/opencode/opencode.jsonc:

{
  "plugin": [
    "true-mem"
  ]
}

OpenCode will automatically download the plugin from npm.

A ~/.true-mem/ directory will be created to store the SQLite database and debug logs.

After restarting OpenCode, you'll see a toast notification confirming the plugin is loaded:

True-Mem vX.X.X
Memory active.

This confirms True-Mem is installed and working correctly.


Configuration

True-Mem creates a configuration file at ~/.true-mem/config.jsonc on first run. You can edit this file to customize behavior:

{
  // Injection mode: 0 = session start only, 1 = every prompt (default, real-time updates)
  "injectionMode": 1,
  
  // Sub-agent mode: 0 = disabled, 1 = enabled (default)
  "subagentMode": 1,
  
  // Embeddings: 0 = Jaccard similarity only, 1 = hybrid (Jaccard + embeddings)
  "embeddingsEnabled": 0,
  
  // Maximum memories to inject per prompt (10-50 recommended)
  "maxMemories": 20
}

Settings Explained

| Setting | Values | Description | |---------|--------|-------------| | injectionMode | 0 or 1 | 0 = inject at session start only (~76% token savings). 1 = inject on every prompt (default, real-time updates) | | subagentMode | 0 or 1 | 0 = disable memory injection for sub-agents. 1 = enable for sub-agents (default) | | embeddingsEnabled | 0 or 1 | 0 = use Jaccard similarity only (fast, default). 1 = use hybrid semantic embeddings (experimental) | | maxMemories | 10-50 | How many memories to include in each prompt (default: 20). Lower = fewer tokens, Higher = more context |

Injection Mode Trade-off:

  • Mode 1 (ALWAYS) - Default. Real-time memory updates. New memories appear immediately. Best for most users.
  • Mode 0 (SESSION_START): Memories are injected once at session start. New memories extracted during the session won't appear until you restart OpenCode. Best for long sessions (20+ prompts) where token cost matters.

Environment Variables

You can also configure via environment variables (override config file):

| Variable | Values | Description | |----------|--------|-------------| | TRUE_MEM_INJECTION_MODE | 0 or 1 | Override injectionMode setting | | TRUE_MEM_SUBAGENT_MODE | 0 or 1 | Override subagentMode setting | | TRUE_MEM_EMBEDDINGS | 0 or 1 | Override embeddingsEnabled setting | | TRUE_MEM_MAX_MEMORIES | 10-50 | Override maxMemories setting |

Example:

export TRUE_MEM_INJECTION_MODE=1
export TRUE_MEM_MAX_MEMORIES=25
opencode

Usage

Automatic Extraction

Just have conversations with OpenCode. True-Mem extracts relevant info in the background.

What gets stored:

  • User preferences: "I prefer TypeScript over JavaScript"
  • Constraints: "Never use var keyword"
  • Decisions: "We decided to use SQLite instead of Postgres"
  • Semantic info: "The API uses REST, not GraphQL"
  • Learning: "I learned that bun:sqlite is built-in"

List Injected Memories

To see which memories are currently injected in your prompt, use one of:

list-memories
list-memory
show-memory

All three commands are equivalent and display all memories grouped by scope (Global/Project) and store (LTM/STM). Useful for debugging or understanding what the AI remembers about you.

Delete a Memory

To delete a specific memory from True-Mem, ask your AI assistant mentioning "true-mem" to avoid confusion with other memory plugins:

"Delete the true-mem memory about using bun"
"Remove from true-mem the memory that says 'always run tests'"

The AI assistant can directly query and update the SQLite database at ~/.true-mem/memory.db.

Explicit Memory Storage

Use phrases like "Remember this:" or "Remember that ..." to force storage:

"Remember this: never commit without running tests first"
"Remember that I prefer to use TypeScript in my projects"

Scope Behavior:

By default, explicit intent memories are stored at project scope (only visible in the current project). To make them global (available in all projects), include a global scope keyword anywhere in your phrase:

| Language | Global Scope Keywords | |----------|---------------------| | English | "always", "everywhere", "for all projects", "in every project", "globally" | | Italian | "sempre", "ovunque", "per tutti i progetti", "in ogni progetto", "globalmente" | | Spanish | "siempre", "en todas partes", "para todos los proyectos" | | French | "toujours", "partout", "pour tous les projets" | | German | "immer", "überall", "für alle projekte" | | Portuguese | "sempre", "em todos os projetos" |

Examples:

| Memory | Scope | Phrase | |---------|---------|---------| | Project | project_scope = current_project | "Remember that we use REST for the API" | | Global | project_scope = null | "Remember to always run tests before committing" | | Global | project_scope = null | "Remember that I always use Typescript in every project" |


Advanced: Semantic Embeddings (Experimental)

True-Mem includes an experimental NLP embeddings feature that provides semantic similarity search beyond basic Jaccard matching.

What It Does

When enabled, True-Mem uses a lightweight transformer model (all-MiniLM-L6-v2) to generate 384-dimensional embeddings for each memory. This enables:

  • Semantic retrieval - Find memories by meaning, not just keyword matching
  • Better relevance - Understands that "I like TypeScript" relates to "JavaScript preferences"
  • Cross-lingual support - Works across the 15 supported languages

How It Works

Architecture:

Main Thread (Bun) → Node.js Worker Process → Transformers.js v4 → ONNX Runtime

The plugin spawns a separate Node.js process to run the transformer model in isolation, ensuring Bun stability. The model is automatically downloaded on first use and cached locally.

Trade-offs:

  • Storage: ~23MB for cached model (downloaded once to ~/.true-mem/models/)
  • Memory: ~200MB RAM when worker is active (during embedding generation)
  • Init time: 2-3 seconds on first use (model loading)
  • Hot-reload resilient: Debounce (1s) prevents spawn thrashing

Enabling Embeddings

Edit ~/.true-mem/config.jsonc and set:

{
  "embeddingsEnabled": 1
}

Or use environment variable:

export TRUE_MEM_EMBEDDINGS=1
opencode

To disable, set to 0 or remove the line from config.

Status

Experimental - The feature works well but is still being tested. The Jaccard-only mode (default) is production-stable. When embeddings are enabled, the system gracefully falls back to Jaccard if the worker fails (circuit breaker: 3 failures / 5 minutes).

Checking If Active

# Check config file
cat ~/.true-mem/config.jsonc | grep embeddingsEnabled

# Check logs for [embeddings=true] tag
tail -f ~/.true-mem/plugin-debug.log | grep "\[embeddings=true\]"

Architecture

true-mem/
├── src/
│   ├── index.ts                 # Entry point with fire-and-forget init
│   ├── state.ts                 # Plugin state management
│   ├── logger.ts                # File-based debug logging
│   ├── shutdown.ts              # Graceful shutdown handling
│   ├── config/
│   │   ├── config.ts            # JSONC config loading with comments
│   │   ├── state.ts             # Runtime state persistence
│   │   ├── migration.ts         # Config migration (v1.2 → v1.3)
│   │   └── injection-mode.ts    # Injection mode utilities
│   ├── storage/
│   │   ├── sqlite-adapter.ts    # bun:sqlite + node:sqlite runtime adapter
│   │   └── database.ts          # MemoryDatabase class with scope filtering
│   ├── memory/
│   │   ├── patterns.ts          # Multilingual patterns (15 languages)
│   │   ├── negative-patterns.ts # False positive prevention
│   │   ├── role-patterns.ts     # Role-aware extraction (Human vs Assistant)
│   │   ├── classifier.ts        # Four-layer defense + role validation
│   │   ├── embeddings.ts        # Jaccard similarity search
│   │   ├── embeddings-nlp.ts    # NLP embeddings worker management
│   │   ├── embedding-worker.ts  # Worker process for transformer model
│   │   └── reconsolidate.ts     # Conflict resolution
│   ├── extraction/
│   │   └── queue.ts             # Fire-and-forget extraction queue
│   ├── adapters/
│   │   └── opencode/
│   │       ├── index.ts         # Full extraction + injection hooks
│   │       ├── injection.ts     # Memory injection logic
│   │       └── injection-tracker.ts  # Session injection tracking
│   └── utils/
│       ├── version.ts           # Version utilities
│       ├── jsonc.ts             # JSONC parser with comments
│       └── toast.ts             # Toast notifications
└── dist/
    ├── index.js                 # Bundle (~155KB)
    └── memory/
        └── embedding-worker.js  # Worker bundle (~3KB)

Memory Classifications

| Type | Decay | Store | Scope | Example | |------|-------|-------|-------|---------| | constraint | Never | STM | Global | "Never use var" | | preference | Never | STM | Global | "Prefers functional style" | | learning | Never | LTM | Global | "Learned bun:sqlite API" | | procedural | Never | STM | Global | "Run tests before commit" | | decision | Never | LTM | Project | "Decided SQLite over Postgres" | | semantic | Never | STM | Project | "API uses REST, not GraphQL" | | episodic | Yes (7d) | STM | Project | "Yesterday we refactored auth" |


Technical Details

7-Feature Scoring Model

| Feature | Weight | Description | |---------|--------|-------------| | Recency | 0.20 | Time since creation (0 = recent, 1 = old) | | Frequency | 0.15 | Number of accesses (log scale) | | Importance | 0.25 | Combination of signals (diminishing returns) | | Utility | 0.20 | Usefulness for current task | | Novelty | 0.10 | Distance from existing memories | | Confidence | 0.10 | Consensus of extraction evidence | | Interference | -0.10 | Penalty for conflicts |

Strength Formula: Strength = Sum(weight_i * feature_i) clamped to [0, 1]

Four-Layer False Positive Prevention

| Layer | Purpose | |-------|---------| | 1. Question Detection | Filter questions before classification | | 2. Negative Patterns | AI meta-talk, list selections, 1st person recall, remind-me recall (10 languages) | | 3. Multi-Keyword + Sentence-Level | Require 2+ signals in the same sentence | | 4. Confidence Threshold | Store only if score >= 0.6 |

Decay Strategy

  • Episodic memories: Decay using Ebbinghaus formula (lambda = 0.05 STM, 0.01 LTM)
  • All other types: Permanent (no decay)

Contributing

Want to contribute or test your own changes? Here's how:

  1. Fork this repository

  2. Build the plugin

    cd true-mem
    bun install
    bun run build
  3. Use your local version in ~/.config/opencode/opencode.json:

    {
      "plugin": [
        "file:///path/to/your/fork/true-mem"
      ]
    }
  4. Restart OpenCode - it will load your local build instead of the npm version.

  5. Make your changes, rebuild with bun run build, and test.

  6. Submit a PR when ready!

Inspired by PsychMem - a pioneering plugin for persistent memory in OpenCode.


Debug

# View logs
tail -f ~/.true-mem/plugin-debug.log

# Query database
sqlite3 ~/.true-mem/memory.db "SELECT classification, summary, strength FROM memory_units WHERE status = 'active' ORDER BY strength DESC LIMIT 10;"

License: MIT Status: Actively maintained