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

@wiscale/velesdb-memory-node-darwin-x64

v0.14.1

Published

Local-first agent memory for Node.js (napi-rs): remember/recall/relate/forget/why with the why() knowledge-graph wedge, plus auto-extraction.

Readme

velesdb-node — @wiscale/velesdb-memory-node

Local-first agent memory for Node.js: remember, recall, and explain why — in-process, no server.

npm Node License

Portability: ✅ a plain npm dependency — no MCP client, no server, no daemon, no API key · ✅ prebuilt binaries for macOS, Linux (glibc) and Windows · ⚠️ no musl prebuild, so Alpine-based images need a local build.

This crate is never published to crates.io. It compiles to a napi-rs cdylib that ships to npm as @wiscale/velesdb-memory-node, wrapping the exact same hardened Rust as the velesdb-memory MCP server and the Python binding — no logic is reimplemented here.

Objective

An agent that runs in Node forgets everything between processes, and a vector store only hands back text that looks like the question. Neither can answer "why is this value 7?", because the answer is usually a fact that shares no words with the question — the customer constraint behind the constant, the incident behind the config.

This addon gives a Node agent durable memory that never leaves the machine. It remembers facts, recalls them semantically, connects them with typed links, and walks those links to return the evidence trail behind an answer. It also carries the deterministic context compiler, which shrinks a prompt under a hard token budget with no model call at all.

recall() finds the booking but misses the reason; why() reaches it through typed links, across a session restart

The store is on disk, so memory survives process restarts: a new session reopens it and why() still walks the graph to context that shares no words with the question.

What you actually gain

Two problems cost you real money and real quality every day, and this addon fixes both — in your own Node process, with no service to run.

Your agent forgets. Close the process and everything it learned is gone. The store is a directory on disk, so a new process reopens it and the facts are still there.

Every turn re-sends the whole conversation. That is what you are billed for, and a context padded with repeated logs is also one where the model attends less to what matters. compileContext shrinks that payload before you send it — deterministically, and without calling any model itself.

| What improves | Measured | How it was measured | |---|---|---| | Context sent to the model | 82.5 % smaller over a 12-turn coding session (80.8–87.4 % per turn as it grows) | committed corpus, real cl100k tokenizer — every turn compiled twice, byte-identical | | Compile cost | 0.7 ms stateless, 24.5 ms with source/event persistence on | same run | | Storing a memory | zero AI calls — nothing leaves the process | the write path never calls a model | | Prompt-cache prefix | byte-stable across all 12 turns (45 tokens reusable) | same run |

Those percentages come from our corpus. Every figure is pinned to its committed source by a contract the CI enforces: if one drifts from what the code produces, the build goes red.

How it works, in four steps

Everything below runs in-process. No server, no network, no API key.

1. It stores facts, not transcripts. remember takes one fact — "the API port is 6333 because 3000 collided with the web UI" — and writes it to a local directory. No model call.

2. It finds them by meaning. recall matches on sense, so "which port did we settle on" reaches that fact although the words differ.

3. It connects them — the part a search engine cannot do. Facts are linked to the topics they mention, and why walks those links: it returns the best match plus the facts that explain it, including ones sharing no words with your question. That is what the GIF above shows across a restart.

Those links have to exist. If you only ever call remember, the graph stays flat and why degrades to a search. rememberExtracted takes a paragraph, splits it into facts and wires the links for you.

4. It compresses what is too big. compileContext takes your accumulated context and a token budget, and returns a compiled view with one auditable decision per fragment — kept, abstracted, or dropped — plus a handle to fetch any original back. Nothing is destroyed; retrieveContextSource returns the exact bytes.

Use cases

  • A Node or TypeScript coding agent that must still know, three weeks and several processes later, why a timeout is 7 seconds — and can show the constraint it came from.
  • An Electron or CLI tool that needs memory without asking the user to install, run and secure a database service.
  • Regulated or air-gapped work where context cannot transit a third-party LLM API, and "show why it recalled that" has to be answerable.
  • A long agent session about to blow its context window: compile the prompt under a budget instead of summarizing and restarting.

Prerequisites

| Requirement | Minimum version | Note | |---|---|---| | Node.js | 18.17 | The package engines.node floor. CI builds and tests on Node 20. | | A supported platform | — | macOS (arm64/x64), Linux glibc (x64/arm64), Windows x64 — see Compatibility. | | Rust | 1.90 | Not needed to install. Only to build the addon yourself: building from source. | | Ollama | any | Optional. Only for embedder: "ollama" and rememberExtracted. The default embedder is offline and dependency-free. |

Installation

npm install @wiscale/velesdb-memory-node

That downloads a prebuilt binary; nothing is compiled on your machine, and no Rust toolchain is involved. Unsupported platform, or working on the binding itself? See building the Node addon from source.

First success in 60 seconds

Save this as first.mjs in a project with "type": "module", then run node first.mjs:

import { mkdtempSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { MemoryService } from '@wiscale/velesdb-memory-node'

// Offline "hash" embedder by default: no model, no network, no API key.
const store = MemoryService.open(mkdtempSync(join(tmpdir(), 'velesdb-')))

// An earlier session recorded a decision and the human reason behind it.
const reason = await store.remember(
  'field crews work from remote mining sites over satellite links',
)
await store.remember('the default HTTP request timeout is 7 seconds', [
  { target: reason, relation: 'because' },
])
await store.remember('the vector index uses HNSW with M=16')

const question = 'why is the request timeout 7 seconds?'

console.log('recall — vector similarity only:')
for (const hit of await store.recall(question, 2)) {
  console.log(`  ${hit.content}`)
}

console.log('why  — vector seed + graph of typed links:')
const { nodes, edges, truncated } = await store.why(question)
for (const node of nodes) console.log(`  hop ${node.hop}  ${node.content}`)
console.log(`  ${edges.length} typed edge(s) walked`)
if (truncated) console.log('  explanation truncated')

Expected output, exactly:

recall — vector similarity only:
  the default HTTP request timeout is 7 seconds
  the vector index uses HNSW with M=16
why  — vector seed + graph of typed links:
  hop 0  the default HTTP request timeout is 7 seconds
  hop 1  field crews work from remote mining sites over satellite links
  1 typed edge(s) walked

That is the whole product in eight lines of output. recall never surfaces the satellite-link constraint — it shares no words with the question, so vector similarity ranks an unrelated HNSW note above it. why() follows the because edge and reaches it at hop 1, so your agent warns you before you "round 7 down" and cut off the customer.

Failure looks unmistakable: Failed to load native binding means no prebuilt binary matched your platform (Troubleshooting), and a why section with only hop 0 means the typed link was not stored — check that reason was passed as { target, relation }.

Configuration

There are no environment variables. Everything is an argument to the factory:

| Argument | Default | Effect | |---|---|---| | path | — | Directory of the on-disk store. Created if missing; reopened on the next run. | | embedder | "hash" | "hash" is offline and deterministic; "ollama" gives real semantic recall. | | ollamaUrl | "http://localhost:11434" | Only with embedder: "ollama". | | ollamaModel | "all-minilm" | Only with embedder: "ollama". |

const store = MemoryService.open('./agent_mem', 'ollama')

A store is fixed to one embedder — the vector dimension is decided when the store is created — so use a separate directory when you switch.

Examples

examples/why_magic_constant.mjs is the runnable version of the demo above, scaled to 14 memories so the blindness of plain recall is unmistakable. From this directory, after a build:

node examples/why_magic_constant.mjs

The same wedge in the other bindings is listed in the velesdb-memory README.

API

21 methods on one class, in three families:

| Family | Methods | |---|---| | Durable memory | remember, recall, recallWhere, recallFused, recallFusedDated, relate, unrelate, forget, why, entity, feedback, rememberExtracted | | Context compiler | compileContext, compileTranscript, explainCompilation, contextSavings, retrieveContextSource, suggestBudget | | Session resumption | saveWorkingContext, loadWorkingContext, listWorkingContexts |

loadWorkingContext resolves the {found, working, other_sessions} envelope the MCP tool serves — breaking in 0.12.0, where it used to resolve the bare working context or null; read .working for that value, and .other_sessions to tell a genuine fresh start from a typo in session.

Three contracts hold across all of them: every method returns a Promise and runs off the event-loop thread; every id crosses as a decimal string (a JS number loses precision above 2^53); every rejection is an Error whose message starts with [INVALID_INPUT], [NOT_FOUND] or [INTERNAL].

Parameter types are generated into index.d.ts and shipped with the package — read them from your editor. Everything else (per-method semantics, the compiler surface, media fragments, working contexts, resource caps) is in the Node addon guide.

Bundled agent skills

Wiring the API gives your agent the methods; it does not tell it when to use them. Three skills ship inside the package for that — velesdb-memory (the recall → remember → relate → why → feedback loop), velesdb-context-optimizer (the compression workflow, including when not to compress) and velesdb-learning-loop (the discipline that makes those two compound: recall before designing, check recurrence before storing a fix, and never write to memory by reflex):

cp -r node_modules/@wiscale/velesdb-memory-node/skills/velesdb-memory ~/.claude/skills/
cp -r node_modules/@wiscale/velesdb-memory-node/skills/velesdb-context-optimizer ~/.claude/skills/
cp -r node_modules/@wiscale/velesdb-memory-node/skills/velesdb-learning-loop ~/.claude/skills/

That cp is a snapshot, not a live link: re-run it after every npm update. Details in the Node addon guide.

Need the full engine?

This addon is the memory wedge, by design and by license: memory semantics only. It exposes no raw VelesQL, no deep graph MATCH, no collection administration — a test pins the prototype allowlist and asserts query, upsert, createCollection and traverse are absent.

For the full engine from Node, run the REST server and talk to it with @wiscale/velesdb-sdk; the runnable two-step recipe is in the Node addon guide.

Known limits

  • Memory semantics only. No database-shaped API, ever — see above.
  • One process per store. The store takes a single-writer lock, so a second MemoryService.open on the same directory fails while the first is alive.
  • A store is fixed to one embedder. The dimension is set at creation.
  • No path fragment ingestion. The MCP server can read a file by reference under an allowlist; this binding has no such configuration surface. Read the file yourself and pass its content.
  • Bring-your-own-links by default. The graph comes from relate and links; automatic extraction needs rememberExtracted and a local model.
  • No musl prebuild, so Alpine images must build the addon themselves.
  • Not on crates.io. publish = false: the artifact is the npm package.

Compatibility

Prebuilt binaries, one per target declared in package.json napi.targets:

| Platform | Target triple | Status | |---|---|---| | macOS, Apple silicon | aarch64-apple-darwin | Prebuilt, load-smoke-tested in CI | | macOS, Intel | x86_64-apple-darwin | Prebuilt, cross-built (no native runner to smoke-test on) | | Linux x64, glibc | x86_64-unknown-linux-gnu | Prebuilt, load-smoke-tested in CI | | Linux arm64, glibc | aarch64-unknown-linux-gnu | Prebuilt, cross-built | | Windows x64 | x86_64-pc-windows-msvc | Prebuilt, load-smoke-tested in CI | | Linux musl (Alpine) | *-unknown-linux-musl | Not shippedbuild from source |

| Runtime | Status | |---|---| | Node.js 18.17+ | Supported (engines.node) | | Node.js 20 | The version CI builds and tests on | | Bun / Deno | Untested — Node-API support exists in both, but nothing here verifies it |

Troubleshooting

| Symptom | Cause | Fix | |---|---|---| | Failed to load native binding | No prebuilt binary matches this platform — most often Alpine/musl. There is no source fallback. | Build the addon from source, or use a glibc base image. | | [INTERNAL] storage error: [VELES-031] Database is already opened by another process: <path> | The single-writer lock is held — a second MemoryService on the same directory. | Keep one instance per store, or give the second one its own path. | | [NOT_FOUND] memory 999999999 does not exist on relate / feedback | The id was rounded by JS number arithmetic, or came from a different store. | Never convert an id with Number(); pass the decimal string through verbatim. | | [INVALID_INPUT] invalid id 'not-an-id' (expected a decimal u64 string) | A non-numeric value reached an id argument (often an object or undefined). | Pass the exact string remember resolved to. | | [INTERNAL] extraction error: ... ollama request failed: ... Connection refused | rememberExtracted needs a running Ollama, whatever embedder the store uses. | Start Ollama and pull the model, or use remember with explicit links. | | EPERM / EBUSY deleting a store directory on Windows | The velesdb.lock file is still held; the release finalizer is not deterministic. | Retry the delete, or drop the directory on the next run. |

License

VelesDB Core License 1.0 (source-available, based on ELv2). See LICENSE — a local copy, so npm bundles it into the published package and each per-platform sub-package.

Running this addon inside your own application, where your users only ever receive results, is the license's expressly-permitted embedded, local-first use. What it forbids is re-hosting VelesDB as a multi-tenant service where third parties drive the database — which this package makes impossible by construction: memory semantics only, and it is a library, not a service. Questions: [email protected].


velesdb-node v0.14.1 (npm @wiscale/[email protected]) · Last updated: 2026-08-19 · Applies to: velesdb-core 5.1.0 · Report a docs error