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

@memoryengine/client

v0.2.8

Published

Client library for memory engine

Readme

@memoryengine/client

TypeScript client for memory engine. Full type inference from shared Zod schemas — no manual type duplication.

Install

npm install @memoryengine/client

Quick Start

import { createClient } from "@memoryengine/client";

const me = createClient({
  server: "http://localhost:3000",
  apiKey: "me_...",
});

// Store a memory
const memory = await me.memory.create({
  content: "The project deadline is March 15th",
  meta: { source: "meeting-notes", priority: "high" },
  tree: "work.projects.launch",
});

// Search memories (hybrid BM25 + semantic)
const results = await me.memory.search({
  fulltext: "project deadline",
  semantic: "what are the upcoming deadlines?",
  limit: 10,
});

// Get current user
const whoami = await me.auth.whoami();

API

createClient(options?) returns a client with namespaced methods:

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | server | string | "http://localhost:3000" | Server URL | | apiKey | string | — | Bearer token for authentication | | timeout | number | 30000 | Request timeout (ms) | | retries | number | 3 | Max retries with exponential backoff |

memory

// Create a memory
await me.memory.create({
  content: "Remember this",
  meta: { source: "chat" },        // optional JSONB metadata
  tree: "work.projects.me",        // optional hierarchical path
  temporal: { start: "2025-03-15" }, // optional time range
});

// Get by ID
await me.memory.get({ id: "019..." });

// Update content, metadata, tree, or temporal
await me.memory.update({
  id: "019...",
  content: "Updated content",
  meta: { source: "chat", reviewed: true },
});

// Delete by ID
await me.memory.delete({ id: "019..." });

// Batch create (up to 1000)
await me.memory.batchCreate({
  memories: [
    { content: "First memory", tree: "notes" },
    { content: "Second memory", tree: "notes" },
  ],
});

// Search — fulltext (BM25), semantic (vector), or both (hybrid)
await me.memory.search({ fulltext: "deadline" });
await me.memory.search({ semantic: "upcoming deadlines" });
await me.memory.search({
  fulltext: "deadline",
  semantic: "upcoming deadlines",
  meta: { source: "meeting-notes" },  // filter by metadata
  tree: "work.*",                      // filter by tree path
  limit: 20,
});

// Move memories between tree paths
await me.memory.mv({
  source: "work.old_project",
  destination: "archive.old_project",
});

auth

// Login with email/username + password
const { key, principal } = await me.auth.login({
  identifier: "[email protected]",
  password: "secret",
});

// Get current principal
const whoami = await me.auth.whoami();

// Create an API key
const { key, id } = await me.auth.createApiKey({ name: "ci-bot" });

// List API keys
const keys = await me.auth.listApiKeys();

// Revoke an API key
await me.auth.revokeApiKey({ keyId: "key_id_here" });

principal

// Create a user
await me.principal.create({
  name: "alice",
  email: "[email protected]",
  password: "securepass",
  can_login: true,
});

// Create an agent (no login, no email)
await me.principal.create({ name: "indexer-bot" });

// Get principal by name
await me.principal.get({ name: "alice" });

// List all principals
await me.principal.list();

// Set password
await me.principal.setPassword({ name: "alice", password: "newpass123" });

// Delete principal
await me.principal.delete({ name: "alice" });

grant

Tree-based access control — grant read/create/update/delete on hierarchical paths.

// Grant access
await me.grant.create({
  principal_name: "alice",
  tree_path: "work.projects",
  actions: ["read", "create", "update"],
});

// Check access
await me.grant.check({ tree_path: "work.projects.me", action: "read" });

// List grants (optionally filter by principal)
await me.grant.list();
await me.grant.list({ principal_name: "alice" });

// Revoke access
await me.grant.revoke({
  principal_name: "alice",
  tree_path: "work.projects",
});

owner

Assign ownership of tree paths to principals.

// Set owner
await me.owner.set({
  tree_path: "work.projects.me",
  principal_name: "alice",
});

// Get owner of a path
await me.owner.get({ tree_path: "work.projects.me" });

// List all ownerships
await me.owner.list();
await me.owner.list({ principal_name: "alice" });

// Remove ownership
await me.owner.remove({ tree_path: "work.projects.me" });

role

Role-based membership for grouping principals.

// Add member to role
await me.role.addMember({
  role_name: "engineers",
  member_name: "alice",
});

// List role members
await me.role.listMembers({ role_name: "engineers" });

// List roles for a principal
await me.role.listForPrincipal({ principal_name: "alice" });
await me.role.listForPrincipal(); // current principal

// Remove member from role
await me.role.removeMember({
  role_name: "engineers",
  member_name: "alice",
});

Schemas

Import Zod schemas directly for validation or type extraction:

import { createMemorySchema, memorySchema } from "@memoryengine/client/schemas";
import type { RpcInput, RpcOutput } from "@memoryengine/client/schemas";

// Validate input
const parsed = createMemorySchema.parse(data);

// Extract types from any RPC method
type SearchParams = RpcInput<"memory.search">;
type SearchResult = RpcOutput<"memory.search">;

Low-Level API

// Typed RPC call
const result = await me.call("memory.search", { semantic: "test" });

// Batch multiple requests in one HTTP round-trip
const [a, b] = await me.batch([
  { method: "memory.get", params: { id: "..." } },
  { method: "auth.whoami" },
]);