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

@mnemehq/distiller-claude

v0.1.0

Published

Anthropic-backed memory distiller for @mnemehq/sdk. Bring your own Anthropic key; extract structured memories from raw text via Claude's tool-use API with prompt caching enabled by default.

Readme

@mnemehq/distiller-claude

Anthropic-backed memory distiller for @mnemehq/sdk. Pass raw text — a conversation transcript, a journal entry, a meeting note — and Claude extracts structured memories that mneme persists for you.

Status: v0.1.0 — first npm release. Pairs with @mnemehq/sdk ^0.1.2. ADR 0012 for the full design.

Why

The SDK on its own requires you to call remember() manually for every memory. Useful for explicit writes; brutal for converting a chat transcript into useful long-term memory. The distiller closes that gap:

import { Mneme } from '@mnemehq/sdk'
import { ClaudeDistiller } from '@mnemehq/distiller-claude'

const mneme = await Mneme.open({
  passphrase: 'correct horse battery staple',
  distiller: new ClaudeDistiller({ apiKey: process.env.ANTHROPIC_API_KEY }),
})

await mneme.distill(`
  Had a great espresso on Brick Lane. Reminded me I really prefer single-origin
  to blends. Also — Sarah from marketing is replying super fast on Slack DMs,
  much faster than email. Should make that the default channel.
`)

// → mneme.remember() called automatically for each extraction:
//   { kind: 'event',        body: 'Visited the espresso bar on Brick Lane' }
//   { kind: 'preference',   body: 'Prefers single-origin coffee over blends' }
//   { kind: 'relationship', body: 'Sarah works in marketing' }
//   { kind: 'preference',   body: 'Prefers Slack DMs over email for reaching Sarah in marketing' }

Install

bun add @mnemehq/sdk @mnemehq/distiller-claude

Requires Bun >= 1.3. The Anthropic SDK is pulled in transitively.

How it works

  • Bring your own key. The distiller calls Anthropic with the API key you provide. The mneme infra never sees your key, your prompts, or your responses. The thesis — your data, your keys — extends to the LLM call.
  • Tool-use, not JSON.parse. Claude returns a tool_use block validated against a Zod schema. No regex parsing, no malformed-JSON debugging.
  • Prompt caching enabled by default. The system prompt + few-shot examples (~2-3k tokens, stable across calls) are marked cache_control: ephemeral. Subsequent distillations within ~5 minutes pay ~10% of the input token cost. Distill 20 conversations for the price of 1.5.
  • Retries 429 / 5xx / transient errors with exponential backoff (250ms → 500ms → 1s → 2s, ±25% jitter), up to 4 attempts by default.
  • Cost estimation per call. Every distill() returns usage.costUsdEstimate so you can budget. Bound it hard with maxCostUsdPerCall.
  • Observability hook for logging every request, retry, response, and error.

Default model

claude-sonnet-4-6 — capable extraction quality at ~$0.001-0.005 per distillation (cache-warm). Override:

new ClaudeDistiller({ apiKey: '...', model: 'claude-opus-4-7' })
new ClaudeDistiller({ apiKey: '...', model: 'claude-haiku-4-5' })

We maintain a small price table covering the current Sonnet / Haiku / Opus tiers so costUsdEstimate stays meaningful. Unknown models report 0 (the adapter still works; you just lose the cost estimate).

Options

new ClaudeDistiller({
  apiKey: process.env.ANTHROPIC_API_KEY!,         // required
  model: 'claude-sonnet-4-6',                     // default
  maxOutputTokens: 2048,                          // covers ~10-15 memories
  requestTimeoutMs: 30_000,                       // 30s
  maxRetries: 4,                                  // 429 / 5xx backoff
  maxCostUsdPerCall: 0.10,                        // hard ceiling, default Infinity
  disablePromptCaching: false,                    // caching ON by default
  onEvent: (e) => console.log(e),                 // observability
})

For tests, swap the real client out:

new ClaudeDistiller({
  client: stubAnthropicClient,                    // any { messages: ... }
})

Errors

| Cause | Surfaced as | | --- | --- | | Empty text input | MnemeError('invalid_record', ...) | | Missing apiKey (and no stubbed client) | MnemeError('invalid_record', ...) | | Cost would exceed maxCostUsdPerCall | MnemeError('invalid_record', ...) with the projected cost | | 429 / 5xx / network errors after maxRetries exhausted | Underlying error rethrown | | Tool-use block missing from response | Error('Claude did not return a tool_use block ...') | | Tool input fails Zod validation | ZodError rethrown |

The adapter never silently returns partial results. Either the full extraction succeeds or it throws.

What it extracts

Six categories aligned to the mneme protocol's MemoryKind:

| Kind | What it means | | --- | --- | | fact | Durable, verifiable information about the speaker (location, identity, allergies, possessions) | | preference | Likes, dislikes, opinions held over time | | event | Specific things that happened, with rough time context | | relationship | Named people in the speaker's life | | context | Current ongoing situation, project, or theme | | skill | Abilities, expertise, or active learning |

The system prompt explicitly tells Claude to refuse third-party gossip, hypotheticals, fleeting moods, and questions. Confidence rubric: 0.95+ for explicit statements, ~0.75 for strong implications, ~0.55 for inference, below 0.5 skipped by the SDK default.

What's coming

  • @mnemehq/distiller-openai — same interface, OpenAI key (next minor release; the adapter copy-paste against openai's SDK is ~2 hours of work)
  • @mnemehq/distiller-local — on-device extraction via llama.cpp / transformers.js. Gated on resolving the Bun + onnxruntime cleanup issue (ADR 0004 §4)
  • Streaming distillation for long transcripts — adapter emits memories as they're extracted (v0.2)
  • Eval harness — curated corpus + queries with expected top matches, measuring extraction precision (ADR 0013, next PR after this one)

License

Apache-2.0.