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

@parad0x_labs/context-capsule

v1.2.1

Published

Lossless agent session-history archive (zlib + SHA-256 Merkle root), a short prompt pointer, and on-demand keyword retrieval, for nulla-local and OpenClaw agents.

Readme

@parad0x_labs/context-capsule

Keep agent session history out of the prompt until it is needed. Stores the history losslessly, gives the model a short pointer, and retrieves matching messages on demand.

What it does

  • compressContext() stores the session as zlib-compressed JSONL (lossless) with a SHA-256 Merkle root over the messages.
  • injectCapsule() returns a short pointer string for the prompt: session id, zlib ratio, up to 5 topic words, Merkle prefix. It does not contain the session's facts.
  • searchCapsule() decompresses the archive and returns every message containing any query term. Your code decides when to call it and puts the result in the prompt.

All of it is deterministic and local. No exported function calls a model. How each stage works: docs/CONTEXT_CAPSULE_DATAFLOW.md.

Public benchmark

Model-free and reproducible; Node.js 22, no dependencies. Bundled 109-message development fixture, 40 questions written with it (35 answerable from it). Token counts are chars / 4 estimates.

| Measurement | Result | What it covers | |---|---|---| | Archive (zlib, lossless) | 31,818 -> 10,382 bytes (3.1x) | stored history | | Initial prompt payload | 7,919 -> 53 tokens | pointer string only; retrieval not counted | | Pointer alone, answer keywords present | 2 / 40 | no-retrieval control | | searchCapsule(question) keyword recovery | 34 / 40 (34 / 35 answerable), ~6,750 tokens retrieved per question | retrieval returns 93 of 109 messages on average | | searchCapsule(content words) keyword recovery | 33 / 40, ~2,600 tokens per question | 22 of 109 messages on average | | searchCapsule(content words, { limit: 8 }) | 32 / 40, ~1,130 tokens per question | at most 8 messages | | End-to-end model task success / total tokens | not measured yet | harness defined, see benchmark doc |

Keyword recovery means every required keyword occurs in the retrieved message text; it is not a model answering the question. Five questions are flagged unanswerable in the question file (a required keyword never occurs in the session); recovery is reported over all 40 and over the 35 answerable ones. Method, baselines (sliding window, top-k retrieval), result files and the planned model-task comparison: docs/CONTEXT_CAPSULE_BENCHMARK.md.

cd packages/context-capsule
npm run bench:public   # bench/results/latest.json, latest.md
npm run bench:scope    # bench/results/scope.json, scope.md (all arms)

Limits:

  • The fixture is one synthetic session; other content compresses and retrieves differently.
  • The pointer is a reference, not a summary. Without retrieval the model does not see earlier details.
  • Retrieval is term matching (any term, substring). A question in different words than the session may miss; a broad query returns most of the history.
  • Token counts are estimates, not a model tokenizer.

Install

npm install @parad0x_labs/context-capsule

The package ships TypeScript source (src/index.ts) and no compiled JavaScript. Import it from a TypeScript-aware runtime or bundler such as tsx, Bun, Vite or esbuild. Plain node refuses to strip types from files under node_modules (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING).

Usage

import { compressContext, injectCapsule, searchCapsule, estimateSavings } from '@parad0x_labs/context-capsule'

// Compress session history
const capsule = compressContext(messages, { sessionId: 'my-session' })

// Short pointer for the next LLM call (53 estimated tokens on the bundled fixture)
const injection = injectCapsule(capsule)

// When earlier detail is needed, retrieve it and add it to the prompt yourself
const relevant = searchCapsule(capsule, 'payment receipt')

// Pointer size vs full history (initial payload only; retrieval not included)
const savings = estimateSavings(messages, capsule)
console.log(savings.savedPercent)

API

compressContext(messages, opts?): ContextCapsule

Compresses an array of { role, content } messages using zlib deflate (level 9), lossless. Builds a SHA-256 Merkle root over per-message hashes, so a stored history can be checked against a recorded root.

injectCapsule(capsule): string

Returns a short pointer string (53 estimated tokens on the bundled fixture) with session ID, zlib ratio, up to 5 topic words, and a truncated Merkle root. It does not include facts or decisions.

searchCapsule(capsule, query, opts?): string

Decompresses the capsule and returns, in original order and untruncated, every message that contains any query term (case-insensitive substring). Without opts.limit results are not capped, so common words return most of the history; use specific terms. With { limit: n } it keeps the n messages containing the most distinct query terms (ties: earlier first), still in original order. The header line gives counts only and does not repeat the query.

estimateSavings(messages, capsule): SavingsEstimate

Compares chars / 4 of the full JSONL history with chars / 4 of the injectCapsule() string, plus a USD delta at a fixed $15 per 1M input tokens. It measures the initial pointer only; tokens from searchCapsule() results are not included.

ContextCapsule shape

interface ContextCapsule {
  sessionId: string          // set by caller or auto-generated
  capsuleId: string          // sha256(sessionId + createdAt + merkleRoot)[:32]
  originalTokenEstimate: number
  compressedBytes: number
  compressionRatio: string   // zlib ratio, e.g. "3.1x"
  topics: string[]           // up to 5 extracted key topics
  merkleRoot: string         // 64-char hex SHA-256 Merkle root
  createdAt: number          // Unix ms
  compressedBase64: string   // zlib-deflated JSONL, base64-encoded
}

Corrections and anchoring

taggedCompressContext() tags each message (instruction, correction, additive, query, ack) with keyword heuristics and builds activeInstructions, where a correction replaces the earlier instruction it overlaps most. injectEnrichedCapsule() prints only the counts; render capsule.activeInstructions into your prompt if the model should see the corrected instructions.

anchorCorrectionChain(chain, rpcUrl?) posts a Merkle root of the correction chain as an SPL Memo (correction_chain:<root>). There is no default cluster. It sends a transaction only when all three are present: SOLANA_KEYPAIR, an RPC endpoint (the rpcUrl argument or the CONTEXT_CAPSULE_ANCHOR_RPC environment variable), and an installed @solana/web3.js. Otherwise it sends nothing, logs the reason, and returns dry_run:<merkleRoot>; that string is not a transaction. verifiableCapsule(messages, { rpcUrl }) passes the endpoint through.

Requirements

Node.js >= 22.0.0. No external npm dependencies — only Node.js built-ins (node:crypto, node:zlib).

License

MIT