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

@hasna/mementos

v0.17.10

Published

Universal memory system for AI agents - CLI + MCP server + library API

Readme

@hasna/mementos

Persistent memory for AI agents, available as a CLI, MCP server, REST service, and TypeScript library. Hosted clients use the authenticated Mementos HTTP API; local SQLite is available only through an explicit local-mode opt-in.

npm License

Install

Mementos requires Bun 1.0 or newer at runtime.

npm install -g @hasna/mementos
# or
bun add -g @hasna/mementos

The package installs three binaries:

| Binary | Purpose | | --- | --- | | mementos | Memory, agent, project, graph, session, and maintenance CLI | | mementos-mcp | MCP server; Streamable HTTP by default, stdio on request | | mementos-serve | REST API server |

Quick start

Local mode must be selected explicitly. The first command after the opt-in creates and migrates ~/.hasna/mementos/mementos.db.

export HASNA_MEMENTOS_LOCAL=1
mementos save project-stack "Bun, TypeScript, SQLite" \
  --scope shared --category fact
mementos recall project-stack
mementos search "TypeScript"
mementos list --scope shared

Register an agent and project when memories need explicit ownership:

mementos projects --add --name my-project --path "$PWD"
mementos register-agent marcus --role coding-agent
mementos inject --project "$PWD" --agent marcus --format compact

Memory scopes are global, shared, private, and working. working is transient session scratch space and defaults to a one-hour lifetime. Categories are preference, fact, knowledge, history, procedural, and resource.

For CLI context and inject, an explicit --project must resolve to a registered project and restricts every included scope to that exact project. SDK getContext({ project_id }) uses the same exact-project rule. Unknown explicit projects fail before memories are selected or touched; omitting the project keeps the existing scope selection.

The library and MCP injection strategies retain unassigned agent-private context alongside the selected project's private memories. They exclude private memories assigned to another project. Their existing global/shared policies remain: library strategies include global memories across projects and project-scoped shared memories; direct MCP injection also scopes global memories to the project, while its full smart pipeline uses the library policy.

Injection project references may be a stable project ID, registered name, or registered path. Library, MCP, and HTTP/SDK injection resolve that reference once and use the stable project ID for every downstream profile, search, filter, hook, and touch path.

The list API and SDK expose include_unassigned_project: true with project_id for this union. The filter applies before pagination and also governs total; without a project it has no effect. Omitting it keeps an exact project match.

CLI

Optional decision assistance

Decision assistance is off by default. No provider account or key is needed for ordinary Mementos commands. Configure and enable the features you want from the CLI; there is no web setup. This adds no service-side configuration and does not change ordinary search, context injection, or consolidation.

mementos decisions status --json
mementos decisions configure --provider openrouter --model typesafe/jev-1.13
mementos decisions enable --retrieval --relationships
# Supply OPENROUTER_API_KEY through your secret manager's process environment.
mementos --project my-project decisions search "release approval policy" --limit 10 --json
mementos decisions evaluate --input pair.json --json
mementos decisions disable

For prompt hooks, mementos prompt-context --enabled --input - accepts JSON containing prompt, project and optional explicit scope filters. It returns a bounded, read-only context receipt. Without --enabled it performs no retrieval; provider decisions still require their separate opt-in. The Hooks app registers the native event with hooks install mementos-context --target codex (also claude or codewith). See the prompt hook setup for environment enablement, project scope, provider disclosure and native trust.

configure always leaves assistance disabled. enable permits only the selected features and explicitly permits sending their text to the configured provider. The key is read from OPENROUTER_API_KEY; it is never saved in decision settings. status reports key presence without verifying or calling the provider. Settings are versioned client preferences in the Mementos data root's decisions.json; updates reject concurrent changes. status, configuration, and evaluate do not open a memory store or require a hosted Mementos account.

decisions search retrieves a bounded candidate set using the existing project, agent, session, scope, category, and tag filters, then optionally reranks it. Every candidate is retained; ties preserve the original order. On a missing key, timeout, invalid answer, oversized input, or provider failure, the original ordering is returned with an explicit assessment reason. This command has no pagination cursor: its receipt names ranking_scope: "returned_candidates" and reports has_more. Use ordinary search for pagination. JSON includes compact snippets and source IDs/versions, with a 128 KiB output ceiling.

evaluate accepts a JSON file or stdin (--input -). A relationship input is:

{
  "task": "relationship",
  "candidates": [
    { "id": "a", "text": "Production deployment requires approval." },
    { "id": "b", "text": "Production deployment does not require approval." }
  ]
}

For relevance, use "task": "relevance", a non-empty "query", and a "candidates" array of the same {id,text} shape. Relationship suggestions are equivalent, complementary, contradictory, unrelated, or uncertain. Evaluation is read-only: suggestions never authorize writes or replace source authority, human review, or version checks. An unavailable evaluation exits 2; a disabled evaluation exits 0 with an explicit disabled receipt.

The built-in adapter calls OpenRouter's Decisions API with a pinned model ID, no automatic retries, and provider fallback disabled. Defaults bound each assessment to 20 candidates, 16,000 serialized input characters, and five seconds; configure these with --max-candidates, --max-input-chars, and --timeout-ms. Input files are limited to 256 KiB and provider responses to 64 KiB. Only query and candidate text go to OpenRouter; arbitrary metadata and candidate IDs are excluded. Known secret patterns and credential-bearing URLs are redacted before transmission. Redaction is heuristic: enable this only for content you are permitted to send to your chosen provider.

Jev returns judgments, not generated memories or embeddings. Its confidence is distribution concentration, not a probability of correctness. Pinning the model and criteria makes requests reproducible but does not promise deterministic provider answers. Keep structural validation and authorization deterministic.

Other providers, including local implementations, can implement the public DecisionProvider interface; no OpenRouter dependency is required by callers:

import { assessDecisions, rankDecisionCandidates } from "@hasna/mementos/sdk";
import type { DecisionProvider } from "@hasna/mementos/sdk";

// `provider` is your adapter implementing DecisionProvider.
async function rank(provider: DecisionProvider, query: string,
  candidates: Array<{ id: string; text: string }>) {
  const assessment = await assessDecisions({ task: "relevance", query, candidates }, {
    enabled: true, retrieval: true, provider: provider.id, model: provider.model,
  }, { provider });
  return { assessment, candidates: rankDecisionCandidates(candidates, assessment) };
}

Knowledge consumers can reuse this contract to assess already authorized retrieval candidates or flag potentially conflicting passages. Source citations, review state, and guarded publication remain the consumer's responsibility.

mementos --help
mementos <command> --help

Human-readable list and search commands are compact and paginated by default. Use --limit with --cursor or --offset, --verbose for wider snippets, and mementos show <id> for a full record.

JSON collection output is intentionally envelope-based in this minor release. projects --json, agents --json, list --json, and search --json no longer return bare arrays: each returns a compact collection plus truthful _meta continuation fields. --agent-json remains an alias for the list receipt. --full changes row detail inside the envelope; --all exhausts the query inside the envelope (up to 100,000 rows / 64 MiB). Neither flag restores a bare array for these four commands. The sole legacy bare-array escape is export --all, because export is an explicitly bulk-oriented command.

Agent JSON uses offset pagination. Stable ID tie-breakers prevent overlap for equal timestamps and importance while the result set is unchanged; writes between page requests can shift offsets, so restart traversal when a stable snapshot is required.

mementos list --json                         # compact 20-row receipt, <=32 KiB
mementos list --json --cursor 20
mementos list --json --full --limit 5        # explicit full detail, still bounded
mementos list --json --all                   # exhaustive receipt, still an envelope
mementos projects --json                     # compact continuation receipt
mementos agents --json                       # compact continuation receipt
mementos search "deploy" --json              # compact byte-capped search receipt
mementos export                              # truthful paginated export receipt
mementos export --all                        # explicit exhaustive legacy array
mementos storage mode --json

The complete command tree and option conventions are in the CLI reference.

MCP

mementos-mcp defaults to a shared, stateless Streamable HTTP server bound to 127.0.0.1:8867:

mementos-mcp
# explicit equivalent
mementos-mcp --http --port 8867

Endpoints are GET /health and POST /mcp. Set MCP_HTTP_PORT to change the port. For an MCP host that launches a child process over stdio, opt in explicitly:

mementos-mcp --stdio
# or: MCP_STDIO=1 mementos-mcp

Cursor, Codex, Claude, and other command-based MCP host entries should use command = "mementos-mcp" with args = ["--stdio"].

The default core MCP profile exposes a bounded 23-tool agent surface. Select additional comma-separated profiles with --mcp-profile, HASNA_MEMENTOS_MCP_PROFILE, or the compatibility alias MEMENTOS_MCP_PROFILE: search, graph, automation, admin, storage, hooks, and full. The explicit full profile preserves all 124 tools and the legacy unpaged mementos://memories, mementos://agents, and mementos://projects resources; reduced profiles omit those resources and use bounded list/get tools instead.

MCP tools/list remains the authoritative schema source. search_tools returns a bounded names-only page for active-profile tools, and describe_tools requires one to ten explicit names. memory_context defaults to ten ranked ~240-character previews under a 32 KiB ceiling; use detail="full" explicitly. memory_inject defaults to lightweight hints and preserves complete injection behind mode="full". memory_export is paginated and receipt-bearing. See the MCP reference for profile membership and compatibility details.

REST API

mementos-serve --port 19428

The server binds to 127.0.0.1 unless MEMENTOS_HOST is set. /v1 is the canonical API prefix and /api is a backward-compatible alias. Operational probes and the generated contract are available without authentication:

GET /health
GET /ready
GET /version
GET /openapi.json

API routes use bearer/API-key authentication when configured. See the REST API reference.

Storage

Client storage selection

The hosted Mementos API is the ordinary client default. The CLI, MCP server, and SDK resolve the hosted credential and authority chain described below; if no hosted credential resolves, client data commands fail closed rather than opening or creating SQLite automatically.

SQLite is available only through an explicit local opt-in:

# Use the standard local data root (~/.hasna/mementos/mementos.db).
export HASNA_MEMENTOS_LOCAL=1

# Or select one exact SQLite file explicitly.
export HASNA_MEMENTOS_DB_PATH=/absolute/path/to/mementos.db

MEMENTOS_LOCAL=1 and MEMENTOS_DB_PATH are compatibility aliases. Legacy ~/.mementos data is considered for migration only after local mode has been selected explicitly; it is never an automatic client fallback.

Server backend and HTTP clients

There are no deployment modes. The only runtime switch is the server data backend: sqlite | postgresql, selected by HASNA_MEMENTOS_DATABASE_URL presence. Raw PostgreSQL credentials are server-only — configure mementos-serve with HASNA_MEMENTOS_DATABASE_URL; configure CLI and MCP clients with the HTTPS API endpoint and API key instead:

# mementos-serve environment
HASNA_MEMENTOS_DATABASE_URL=postgres://...

# client environment; do not distribute the database URL to clients
HASNA_MEMENTOS_API_URL=https://mementos.example.com
HASNA_MEMENTOS_API_KEY=...

Hosted clients — one credential chain

The CLI, the MCP server and the ./sdk client resolve their credential and service authority through the ONE resolver in @hasna/contracts (@hasna/contracts/client), fresh on every call so a key rotation heals a long-lived shell or MCP server without a restart:

| Tier | Source | | --- | --- | | 1 | explicit arguments (--api-key / --profile, or baseUrl / apiKey in the SDK) | | 2 | deliberate env pointer: HASNA_MEMENTOS_API_KEY_OVERRIDE, HASNA_PROFILE, HASNA_MEMENTOS_API_KEY_REF (a secrets-vault item key, never a value) | | 3 | macOS Keychain: generic password hasna.credentials.mementos.api-key, account HASNA_STATION → hostname -s → USER | | 4 | disk: ~/.hasna/mementos/config/credentials, owner-only 0400/0600 (HASNA_HOME / HASNA_CONFIG_HOME move the root) | | 5 | environment: HASNA_MEMENTOS_API_KEY |

The authority follows HASNA_MEMENTOS_API_URL, the Keychain api-url item, the credentials file, and finally the fleet gateway https://api.hasna.com/mementos — a credential ALONE is a complete configuration. The legacy unprefixed MEMENTOS_API_URL / MEMENTOS_API_KEY spellings survive only as the resolver's silent alias fallback for one release. Writing a key to the disk tier:

mkdir -p ~/.hasna/mementos/config
printf 'HASNA_MEMENTOS_API_KEY=%s\n' "$KEY" > ~/.hasna/mementos/config/credentials
chmod 600 ~/.hasna/mementos/config/credentials

FAIL LOUD (owner ruling 2026-09-04): a hosted run with no credential anywhere exits non-zero naming every tier it consulted; there is no SQLite fallback and no local-fallback event. The on-box SQLite store is reachable ONLY through the deliberate opt-ins HASNA_MEMENTOS_DB_PATH / MEMENTOS_DB_PATH (an explicit file) or HASNA_MEMENTOS_LOCAL=1 (alias MEMENTOS_LOCAL=1, honoured only when nothing configures an authority) — and every local run prints one line saying it is local on stderr. Retired locations (~/.hasna/fleet-env/, ~/.hasna/cloud/, ~/.config/hasna/, $XDG_CONFIG_HOME) and retired *_MODE / *_STORAGE_MODE variables are inputs nowhere.

mementos storage mode reports the chosen transport without opening a database or making a network request; mementos status prints the resolved API: line (hasna/apps#1588).

The old storage push, pull, and sync commands remain for compatibility; they are not the cutover architecture. See Configuration and storage and the cloud cutover runbook.

TypeScript APIs

The main package exports the synchronous database/domain API from @hasna/mementos and an authenticated fetch client from @hasna/mementos/sdk — one package carries every surface (CLI, MCP server, REST server, SDK); there is no separate -sdk or -mcp package. See Library and SDK APIs.

Shared event webhooks

The CLI includes the events and webhooks command groups supplied by @hasna/events, allowing memory events to trigger command or HTTP automation. Inspect their installed-version help before configuring a webhook:

mementos events --help
mementos webhooks --help

Event command handlers receive the envelope on stdin and in HASNA_EVENT_JSON. Include working_dir, project_path, or repo_path when a downstream agent must run in a particular repository.

Development

bun install
bun run typecheck
bun test
bun run build

Development entry points are bun run dev:cli, bun run dev:mcp, and bun run dev:serve.

Documentation

License

Apache-2.0 — see LICENSE.

Claude Code Stop hook

Preview the installed CLI's managed hook configuration:

mementos session setup-hook --claude

Apply that exact preview with --apply --expect-settings-sha256 <digest> (or absent for a new settings file). A recognized legacy hook also requires --expect-hook-sha256 <digest>. The installer preserves unrelated settings, retains the original settings as a private backup, and refuses custom or changed hook files. A symlinked .claude directory is preserved and requires the preview's --expect-directory-sha256 <digest>; retargeting the alias invalidates the preview even when its settings have identical bytes. mementos init uses the same installer and does not start a local server when a hosted API is configured.

When Skills manages Claude's native discovery, installation validates the existing review and updates the Stop hook and its discovery witnesses together. Existing plugin, permission, native skill, or hook drift refuses installation; it is never silently adopted. Installations without a Skills policy retain the standalone behavior. Skills is loaded only while applying the installation. The installer uses the published Skills 0.9.14 SDK and supports explicitly reviewed v2 settings and marketplace witnesses. Their allowed model-effort and marketplace timestamp changes remain valid; the installer does not enable v2 reviews or adopt unrelated changes on its own.

Installation names the owning CLI entrypoint on the installing station — the entrypoint at ~/.local/bin/mementos first, then ~/.bun/bin/mementos — in the portable shell form "$HOME/.local/bin/mementos" session stop-hook --claude, so the Stop hook does not depend on Claude's PATH and a settings copy or restore keeps working across homes. Neither a versioned package cache path nor a particular station's home is frozen into Claude's configuration; the entrypoint symlink owns the runtime and version. When neither entrypoint exists, the published portable command mementos session stop-hook --claude stays the installed form and requires the installed CLI on Claude's PATH. It reads the native transcript_path and final assistant text, excludes tool payloads, redacts known secret patterns, and submits through the normal hosted credential resolver. It never ingests the hook envelope as a conversation, falls back to a local store, or automatically retries an ambiguous submission. Failures report a fixed, private-data-free phase and reason, such as [phase=request; reason=timeout], and an actual HTTP error status when available. Input, transcript, configuration, request, and response failures are distinct; exception messages, transcript paths, credentials, and server bodies stay out of the diagnostic. An interrupted request can have reached the server, so its failure is not proof that no job was created. The hook exits 1 on failure, which reports it without blocking Claude's Stop; see the Claude hook exit-code contract. The hook reads at most 8 MiB of conversation text and 64 KiB of input context. A transcript within the 128 MiB scan bound is read in full; past it the hook reads a bounded 64 MiB tail of the most recent records, starting on the first complete record, and the 8 MiB conversation bound keeps the most recent text of that window instead of refusing the ingest. When MEMENTOS_AGENT is configured, the hook preserves that agent attribution. The installer also recognizes the historical CLI-ingest migration shim by its exact digest; modified copies remain protected as custom hooks.