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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@sjovanovic/recall.js

v1.0.3

Published

Semantic search as long term memory for LLMs

Readme

recall.js - Embedded RAG system

Recall.js is long term memory for AI apps!

It is a tool for building RAG (Retrieval-augmented generation) in a form of JavaScript library and command line utility focused on speed, ease of use and embeddability.

It is versatile and you don't have to use it exclusively for RAG, use it for generic Semantic Search, as expert memory for your AI app, as a recommendation system, there are so many possibilities...

Recall.js supports multilingual embeddings out of the box so you can add data in one language and then query it in another.

Under the hood, recall.js uses sentence vector embeddings and a vector database to index and query your data. It is a light wrapper around local language models such as MiniLM-L12-v2 and CozoDB vector database.

Install

npm install @sjovanovic/recall.js

Usage

Console:

recall --add 'The quick brown fox jumps over the lazy dog|Fox|{"foo":"bar"}'
recall --query "Un animal saute par-dessus un autre animal" --limit 1

Warning: when this library is used for the first time, it will download a local language model MiniLM-L12-v2 which may take long time depending on your Internet connectivity. Please be patient.

Below is the same example in JavaScript:


import * as RECALL from '@sjovanovic/recall.js'

const testRecall = async () => {
    await RECALL.addBatch([
        {
            input: "The quick brown fox jumps over the lazy dog",
            result: "Fox and dog",
            data: { foo: "bar" }
        }
    ])

    // Semantic search query in different language (French) "Animal jumps over another animal"
    let response = await RECALL.searchText("Un animal saute par-dessus un autre animal", 1)
    console.log(response)
}
testRecall()

/*

response:

{
  "headers": [
    "dist",
    "result",
    "id",
    "data"
  ],
  "rows": [
    [
      0.5840495824813843, // vector similarity
      "Fox and dog",
      "08840189191373282",
      {
        "foo": "bar"
      }
    ]
  ]
}

*/

Options

Easy way to view all the options is via command line:

recall --help

Usage:
recall --query "Foo Bar"

Options:
--query "SEARCH_STRING"                - search
--limit 2                              - limit number of results (used with --query)
--add 'input|result|{"foo":"bar"}'     - add data
--remove 'id'                          - remove data
--nuke                                 - destroy database
--mcp                                  - run as MCP server
--db "FILE_NAME"                       - database file (SQLite)
--import "file.csv | file.tsv"         - import from CSV or TSV w/ columns: 1. input 2. result 3. and remaining columns are additional data
--input-header "foo"                   - when used with --import designates specific header column as input
--result-header "bar"                  - when used with --import designates specific header column as result
--json "FILE_NAME"                     - import from file which has one json object per line: {input:"", result:"", data:{}}

Note: when adding data recall will generate unique id automatically. To set custom id add it as a string property named "id" in the data object (i.e. {"id":"customID"}).

JavaScript API Reference

RECALL.config

Configuration object.

export const config = {
    VECTOR_SIZE: 384, // number of dimensions
    MODEL_NAME: 'Xenova/paraphrase-multilingual-MiniLM-L12-v2', // model to use 
    SHOW_ERRORS: true, // Show errors
    DB_FILE: join(PATH, 'vector.db'), // Path to the datbase file (SQLite file used by CozoDB)
    PATH: PATH // directory of recall.js
}

RECALL.getDb()

Returns reference to the CozoDB instance.

RECALL.getEmbeddings(text) -> Promise(Array)

Given text calculates the embeddings vector

RECALL.add(input, result, data={}) -> Promise(Object)

Add data. input is the sentence to get embeddings from. result is the string to show in the results. data is arbitrary object intended to hold related pieces of information and references. If data object contains id property it will be used as unique id of the record.

RECALL.addBatch(batch) -> Promise(Object)

Add data in batches (faster than using add repeteadely). batch is an Array that looks like this:

let batch = [{input:"", result:"", data:{}}]

RECALL.remove(id) -> Promise(Object)

Remove data by id. id is a string.

RECALL.searchText(text, numResults = 5) -> Promise(Object)

Query the vector database. Accepts query text and number of results to return.

RECALL.nuke()

Deletes the database.

RECALL.importFromJSONStream(fileName) -> Promise(object)

Imports from readable stream or file which consists of JSON objects, one per line. e.g.

{input:"one", result:"one result", data:{"id":"123"}}
{input:"", result:"", data:{}}
...

This is the most efficient way to import data.

RECALL.importFromCSVorTSV(fileName, inputHeader=null, resultHeader=null) -> Promise()

Imports from CSV or TSV file. By default fist column is used as input, second as result and remaining columns are put in the data object. If inputHeader is specified, function will try to find the column by that name and use it as input. If resultHeader is specified, function will try to find the column by that name and use it as result.

RECALL.mcp() -> Promise()

(Experimental) Runs MCP server and makes the results available when mentioning Recall search in the prompt. Currently only supports STDIO.